1a25243505fc5c52213348ce3cd9969827f843aa
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1a25243505 |
feat(orchestrator): durable launch-broker secret via TrustDomain (#468)
prd-number-check / require-numbered-prds (pull_request) Failing after 12s
tracker-policy-pr / check-pr (pull_request) Successful in 13s
test / integration-docker (pull_request) Successful in 20s
lint / lint (push) Failing after 56s
test / unit (pull_request) Failing after 4m4s
test / coverage (pull_request) Has been skipped
Chunk 2 of the host-control-server stack: close the PRD's **durable secret** gap and replace chunk 1's BOT_BOTTLE_BROKER_SECRET stopgap. - trust_domain.py: two new domains. LAUNCH_BROKER holds the durable HS256 key both the orchestrator (signer) and the host control server (verifier) share for the broker's launch JWT — a host-canonical key file minted 0600 on first use, so a restarted orchestrator re-verifies against the same key (re-adoption). HOST_CONTROLLER is the separate domain for the controller's own lifecycle endpoints, keyed by a key the orchestrator never holds (its lifecycle role is `host`, deliberately outside the control-plane ROLES). LaunchBrokerProvisioning is the fail-closed seam, mirroring ControlPlaneProvisioning. - orchestrator_auth.py: ROLE_HOST, outside ROLES so the orchestrator's control-plane key can neither mint nor accept it. - paths.py: key-file + env-var constants for both domains. - host_server.py / __main__.py: broker_secret() now resolves the durable LAUNCH_BROKER key — env-injected for a containerized launcher, else the host key file for a host-side dev-harness process — so `--broker http` and the host controller "just work" on one host without exporting a secret, and stay fail-closed when the root is unwritable. Tested: domain boundary (host role unmintable by the control plane, cross-domain tokens don't verify), distinct keys/env vars per domain, provisioning fail-closed, and broker_secret env/file resolution + durability. Full unit suite green; pyright clean; pylint 9.90. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
e53104d5c1 |
refactor(orchestrator): fail closed unconditionally, drop topology opt-out
tracker-policy-pr / check-pr (pull_request) Successful in 7s
test / integration-docker (pull_request) Successful in 15s
test / unit (pull_request) Successful in 39s
test / integration-firecracker (pull_request) Successful in 3m55s
test / coverage (pull_request) Successful in 22s
test / publish-infra (pull_request) Has been skipped
prd-number / assign-numbers (push) Failing after 21s
test / integration-docker (push) Successful in 22s
lint / lint (push) Successful in 56s
Update Quality Badges / update-badges (push) Successful in 53s
test / unit (push) Successful in 1m52s
test / integration-firecracker (push) Successful in 5m2s
test / coverage (push) Successful in 16s
test / publish-infra (push) Successful in 1m56s
Remove the empty-key opt-out codex flagged: ControlPlaneProvisioning no longer lets the orchestrator start without a signing key when a backend declares an "isolated" topology. Host separation is not the safety condition — the gateway (and any other caller) must reach the control-plane listener for /resolve, so an open orchestrator would still grant them full `cli`. The signing key is now mandatory for every backend. Drops the now-purposeless Topology/COLOCATED machinery (no backend declared a non-default topology) and the contractual test_orchestrator_key_allows_empty_when_isolated. Updates the PRD's invariant 4 and lifecycle docstring accordingly. Docs/behaviour only otherwise. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
45f3cefbc5 |
refactor(orchestrator): uniform control-plane auth provisioning per trust domain
Hoist control-plane auth provisioning out of the per-backend launchers into one shared contract, parameterized per trust domain (#476). Every blocking finding in PR #471 was the same integration-bug class: each launcher re-derived, by hand, how to generate the signing key, scope it to the orchestrator, mint the gateway JWT, and keep the host key canonical. Introduces `trust_domain.py`: * `TrustDomain` — one credential boundary (host-canonical key file + role set + env vars). `mint`/`verify` are scoped to the domain's roles, so a future host-controller domain (#468) uses its own key/verifier/roles rather than a `host` role on the control plane's frozenset (which the orchestrator key could then forge). * `ControlPlaneProvisioning` — the single seam answering the four invariants: host-canonical key, split key-vs-token credential, CLI token valid across co-running backends, and fail-closed (no open mode) for any co-located topology. * `Topology` — the backend declares what it is; the default is co-located + fail-closed, so a backend need not redeclare it. The `Orchestrator` ABC gets `control_plane_key()` (fail-closed) and routes `mint_gateway_token()` through the contract; docker/macOS/firecracker orchestrators, the server (verify), and the host CLI client (mint cli) all go through the domain instead of reading the host key directly. `orchestrator_auth` gains an optional `roles=` arg (default unchanged) so a domain scopes its own role set; `paths.host_signing_key(filename)` generalizes host_orchestrator_token. Adds unit coverage for the domain boundary + provisioning invariants and a PRD capturing the durable rationale. No change to the auth primitive's HMAC, the plane split, or the server's documented open-mode fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Closes #476 |