feat(orchestrator): slice 2 — launch lifecycle + signed launch-broker #356

Open
didericis-claude wants to merge 1 commits from orchestrator-slice2 into prd-orchestrator
Collaborator

Slice 2 of PRD 0070, stacked on #352 (branched off prd-orchestrator). Still a backend-neutral dev-harness — no real launch yet.

  • broker.py — the launch-broker contract. LaunchRequest is structured (static ids/flags only: bottle id, pool slot, content-addressed image_ref; never a path/argv) and signed as a compact HS256 JWT so the broker verifies provenance before acting — a compromised co-located component can't forge a launch without the shared secret. verify_request is fail-closed. Stdlib only. Ships a StubBroker for the harness.
  • service.py — the Orchestrator: owns the registry, brokers the lifecycle. launch_bottle mints + signs + brokers, rolling the registry entry back if the launch fails (no orphans); teardown_bottle brokers teardown then deregisters.
  • control_plane.pyPOST /bottles launches, DELETE tears down (both via the Orchestrator + broker); dispatch/server take an Orchestrator.

Tests: sign/verify round-trip, tamper / wrong-secret / malformed / off-schema rejection, StubBroker fail-closed; Orchestrator launch→registry→attribute, teardown, rollback-on-failure. Full suite green (only the pre-existing /bin/sleep errors); harness does launch → attribute → teardown over HTTP.

Merge #352 first (this targets that branch). Slice 3 = the real Docker broker.

🤖 Generated with Claude Code

Slice 2 of PRD 0070, **stacked on #352** (branched off `prd-orchestrator`). Still a backend-neutral dev-harness — no real launch yet. - **`broker.py`** — the launch-broker contract. `LaunchRequest` is **structured** (static ids/flags only: bottle id, pool slot, content-addressed `image_ref`; never a path/argv) and signed as a compact **HS256 JWT** so the broker verifies **provenance** before acting — a compromised co-located component can't forge a launch without the shared secret. `verify_request` is fail-closed. Stdlib only. Ships a `StubBroker` for the harness. - **`service.py`** — the `Orchestrator`: owns the registry, brokers the lifecycle. `launch_bottle` mints + signs + brokers, **rolling the registry entry back if the launch fails** (no orphans); `teardown_bottle` brokers teardown then deregisters. - **`control_plane.py`** — `POST /bottles` launches, `DELETE` tears down (both via the Orchestrator + broker); `dispatch`/server take an `Orchestrator`. **Tests:** sign/verify round-trip, tamper / wrong-secret / malformed / off-schema rejection, StubBroker fail-closed; Orchestrator launch→registry→attribute, teardown, rollback-on-failure. Full suite green (only the pre-existing `/bin/sleep` errors); harness does launch → attribute → teardown over HTTP. Merge #352 first (this targets that branch). Slice 3 = the real Docker broker. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
didericis-claude added 1 commit 2026-07-13 14:42:52 -04:00
feat(orchestrator): slice 2 — launch lifecycle + signed launch-broker (#352)
lint / lint (push) Successful in 2m2s
test / unit (pull_request) Successful in 57s
test / integration (pull_request) Successful in 18s
test / coverage (pull_request) Successful in 1m6s
9226d45041
Second slice of PRD 0070, still a backend-neutral dev-harness:

  * orchestrator/broker.py — the launch-broker contract. A LaunchRequest is
    structured (static ids/flags only — bottle id, pool slot, a
    content-addressed image_ref; never a path/argv) and signed as a compact
    HS256 JWT so the broker verifies PROVENANCE before acting: a compromised
    co-located component can't forge a launch without the shared secret.
    verify_request is fail-closed (bad sig / malformed / off-schema -> raise).
    Stdlib only (no runtime deps). Ships a StubBroker that records verified
    requests for the harness/tests.
  * orchestrator/service.py — the Orchestrator: owns the registry and brokers
    the lifecycle. launch_bottle mints the bottle + sends a signed launch,
    rolling the registry entry back if the launch fails (no orphans);
    teardown_bottle brokers teardown then deregisters; attribute delegates.
  * control_plane.py — POST /bottles now launches, DELETE tears down (both go
    through the Orchestrator + broker). dispatch/server take an Orchestrator.
  * __main__.py wires an ephemeral secret + StubBroker for the harness.

Tests: broker sign/verify round-trip, tamper/wrong-secret/malformed/off-schema
rejection, StubBroker fail-closed; Orchestrator launch->registry->attribute,
teardown, rollback-on-broker-failure; control-plane updated for launch/teardown.
Full suite green (only the pre-existing /bin/sleep errors); harness does
launch -> attribute -> teardown over HTTP.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
didericis approved these changes 2026-07-13 14:56:56 -04:00
Some checks are pending
lint / lint (push) Successful in 2m2s
test / unit (pull_request) Successful in 57s
test / integration (pull_request) Successful in 18s
test / coverage (pull_request) Successful in 1m6s
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin orchestrator-slice2:orchestrator-slice2
git checkout orchestrator-slice2
Sign in to join this conversation.