Skip to content

Phoenix Companion machine-API preparation

Summary

Companion deployment reaches Phoenix's browser SSO instead of its JSON API, even when the application supplies a Phoenix bearer key. A narrow machine route is prepared for the existing origin; UI SSO and all unrelated services are unchanged. This is source preparation only: no merge, host update, deployment, credential change, production API probe, or trace cleanup was performed.

Prepared change

The Phoenix service contract documents the exact methods/paths, native authentication boundary, global annotation-config permission limit, and rollout/rollback gates. The ADR-002 machine-token distinction still requires Authentik for the browser UI.

flowchart TD
    Request[Phoenix HTTPS request] --> Match{Exact deployment route and bearer header?}
    Match -->|No| SSO[Existing Authentik route]
    Match -->|Yes| Native[Phoenix native key validation]
    Native -->|Invalid or unauthorized| Deny[Reject request]
    Native -->|Authorized| API[Required deployment API]
    API --> Verify[Companion setup and readback]

A new self-hosted CI check exercises the checked-in rule through real Traefik with synthetic Phoenix/Authentik endpoints on an isolated Docker network. No real Phoenix database or model provider participates. Synthetic 401/403 behavior proves routing/response propagation, not the deployed Phoenix authorization model.

Validation

The focused suite passed 20 tests with zero skips, including real Traefik routing under umask 027. The initial Docker run caught preserved YAML newlines that Traefik rejects; equal scalar indentation corrected the rule, and a static regression now catches that formatting error. Cancellation/partial-setup cleanup uses synthetic Docker state tests; the actual routing cases use isolated Docker. CI also has an always-run cleanup restricted to this invocation's two ownership labels. Hard runner loss still requires a functioning daemon/runner for cleanup.

Remaining gates

  • Review PR and CI. Existing unrelated work in the shared checkout is preserved; implementation uses a clean isolated clone because a sync-created remote ref prevented fetching in the shared checkout.
  • Separately approve activation after confirming live Phoenix native auth denies missing/invalid keys on protected endpoints and accepts the existing approved key. OpenAPI availability alone is not authentication evidence.
  • Account for automatic main/host reconciliation and Traefik's watched dynamic directory: a host file update can activate the route without a restart.
  • After approved rollout, verify browser SSO, protected API denial/acceptance, and rerun Companion's same deployment command. API schema and write permissions remain unverified until its reconciliation/readback succeeds.

No new project, dataset, experiment, LLM judge, gateway capture policy, or historical trace migration is part of this change.