PRD: Host control server - list_live broker op + reconcile via broker (chunk 3/5) #507
Open
didericis-claude
wants to merge 1 commits from
host-control-server-3-list-live into host-control-server-2-secret
pull from: host-control-server-3-list-live
merge into: didericis:host-control-server-2-secret
didericis:main
didericis:fix/quality-cleanup-consolidated
didericis:feat/macos-install-test-harness
didericis:prd-0081-reconcile-1-ca
didericis:fix/shared-storage-permissions
didericis:fix/authoritative-cleanup-identities
didericis:fix/bounded-heavy-operations
didericis:fix/cleanup-execution-integrity
didericis:fix/gateway-output-pump-shutdown
didericis:fix/gateway-request-boundaries
didericis:fix/authoritative-cleanup-revalidation
didericis:refactor/egress-policy-pipeline
didericis:refactor/orchestrator-fastapi
didericis:refactor/supervisor-mcp-dispatch
didericis:chore/misc-quality-cleanup
didericis:prd-forge-subroles
didericis:prd-gateway-reprovision-on-bringup
didericis:host-control-server-2-secret
didericis:host-control-server-1-transport
didericis:prd-new-host-control-server
didericis:fix/gitgate-persist-512
didericis:fix/firecracker-gateway-ca-persist-510
didericis:didericis/disable-agit-refs
didericis:didericis/prd-audit-event-schema
didericis:fix/pr-495-audit-contract
didericis:prd-egress-control-plane
didericis:prd-macos-container-ci-runner
didericis:refactor/control-plane-auth-provisioning-476
didericis:fix/db-off-data-plane-469
didericis:feat/encrypted-egress-secrets
didericis:spike/rootless-docker-macos
didericis:fix/ci-coverage-artifact-paths
didericis:claude-forward-host-credentials-rebased
didericis:fix-gateway-gitleaks-arch
didericis:fix/websocket-response-dlp-multitenant
didericis:orchestrator-agent-compose
didericis:orchestrator-gateway-ca
didericis:orchestrator-consolidated-launch
didericis:orchestrator-gateway-provision
didericis:orchestrator-gateway-network
didericis:orchestrator-client
didericis:orchestrator-gateway-net
didericis:orchestrator-gitgate-provision
didericis:orchestrator-registration
didericis:orchestrator-lifecycle
didericis:orchestrator-supervise-writers
didericis:orchestrator-supervise-multitenant
didericis:orchestrator-gitgate-multitenant
didericis:orchestrator-rename-gateway
didericis:orchestrator-slice8
didericis:orchestrator-slice7
didericis:orchestrator-slice6
didericis:prd-orchestrator
didericis:orchestrator-slice5
didericis:orchestrator-slice4
didericis:orchestrator-slice3
didericis:orchestrator-slice2
didericis:firecracker-backend
didericis:forge-native-integration
didericis:prd-smolmachines-linux
didericis:manifest-break-import-cycle
didericis:dlp-supervise-quality-fixes
didericis:table-drive-dlp-tests
didericis:fix-integration-test-failures
didericis:fix/macos-container-relative-dockerfile
didericis:prd-0054-install-script
didericis:commit-bottle-state
didericis:pr-211
didericis:move-codex-auth-to-contrib
didericis:feat/pipelock-skip-scan-extensions
didericis:prd-0049-named-labelled-agents
didericis:harden-git-gate-shell-rendering
No Reviewers
Labels
Clear labels
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Status/Needs Triage
Breaking change that won't be backward compatible
Something is not working
Documentation changes
Improve existing functionality
New functionality
This is security issue
Issue or pull request related to testing
Priority
Critical
1
The priority is critical
Priority
High
2
The priority is high
Priority
Low
4
The priority is low
Priority
Medium
3
The priority is medium
Status
Abandoned
3
Somebody has started to work on this but abandoned work
Status
Blocked
1
Something is blocking this issue or pull request
Status
Need More Info
2
Feedback is required to reproduce issue or to continue work
Awaiting initial classification
No Label
Milestone
No items
No Milestone
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: didericis/bot-bottle#507
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "host-control-server-3-list-live"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Chunk 3 of the host-control-server stack — grows the broker op vocabulary (PRD gap 3), starting with
list_live, and invertsreconcileonto it.Base:
host-control-server-2-secret(#497) — stacked, review/merge after it.What's here
broker.pysplits the closed vocabulary into mutation ops (launch/teardown— a bottle id + static launch flags) and query ops (list_live— carries nothing but itsopname).verify_requestnow enforces a strict schema — resolving PRD open question 1 ("reject unknown claim keys?") to yes:bottle_id/source_ip/image_ref/slot) is refused — the "no arguments" rule, enforced, not just documented.list_liveverb.LaunchBroker.list_live/SubmitBroker.list_livereturn the backend's live source IPs.DockerBrokerenumerates its labelled containers;StubBrokerderives the set from its recorded launches (or an explicit test override). A backend enumeration failure is converted to the singleBrokerUnavailableError"live set unknown" signal.POST /broker/liveon the host controller verifies a signedlist_livetoken and returns{"source_ips": [...]};BrokerClient.list_liveis its drop-in client. The verbs don't cross — a launch token routed to/broker/live(or vice-versa) is a fail-closed 401.OrchestratorCore.reconcile()drops thelive_source_ipsparameter and pulls the live set from the broker itself — the tell PRD 0070 called out (the orchestrator can't see the backend from inside its container) goes away. The/reconcileHTTP route andOrchestratorClient.reconcilebecome a bare trigger.Safety property
Reconcile is fail-safe: if the broker can't return an authoritative live set (unreachable, timed out, enumeration failed), the sweep is skipped, never run against an empty/partial set. Reaping a healthy bottle's row (which bricks its egress at a recycled address) is far worse than leaving an orphan one cycle longer. Covered by
test_reconcile_skipped_when_broker_cannot_enumerate.Scope note (the "pull chunk 5 forward" call)
Per the steer to make launch coherent through the broker on macOS, the next stacked PR pulls chunk 5's launch-behind-broker forward: it moves the Apple-container
container runbehind the host controller so--broker httpis coherent for all macOS ops, and wires macOS's existing enumeration (consolidated_launch.live_source_ips) in as the host controller'slist_live. That piece is macOS-specific and can't be exercised in the Linux CI sandbox, so it's isolated here to keep this chunk fully green and reviewable. Until it lands, macOS's orchestrator broker is still the stub, whose live set is its recorded launches — so the interim sweep only under-reaps (leaves an orphan a cycle longer), never reaps a healthy bottle.Tests + pyright clean; pylint 10.0 on
broker.py.Closes part of #468.
🤖 Generated with Claude Code
9729407430to7005b22bcfChunk 3 of the host-control-server stack: grow the broker op vocabulary (PRD gap 3), starting with `list_live`, and invert `reconcile` onto it. - broker: split the closed op vocabulary into mutation (`launch`/`teardown`, carry a bottle id + static flags) and query (`list_live`, carries nothing but its op name) kinds. `verify_request` now enforces a **strict schema** (open question 1, resolved yes): unknown claim keys are rejected, a mutation must name its bottle, and a query that smuggles any id/flag is refused. - broker verb: `LaunchBroker.list_live` / `SubmitBroker.list_live` return the backend's live source IPs; a backend enumeration failure is converted to the single `BrokerUnavailableError` "live set unknown" signal. `DockerBroker` enumerates its labelled containers; `StubBroker` derives from launches (or a test override). - host controller: `POST /broker/live` verifies a signed `list_live` token and returns `{source_ips}`; `BrokerClient.list_live` is its drop-in client. - reconcile: `OrchestratorCore.reconcile()` drops the `live_source_ips` parameter and pulls the live set from the broker itself — the tell that the orchestrator couldn't see the backend goes away. **Fail-safe**: if the broker can't return an authoritative set the sweep is skipped, never run against an empty/partial set (which would reap healthy rows). The `/reconcile` HTTP contract + `OrchestratorClient.reconcile` become a bare trigger. The macOS launcher's Apple-container enumeration stays for now; it becomes the host controller's `list_live` when launch itself moves behind the broker (the pulled-forward chunk 5, next in the stack). Tests + pyright clean; pylint 10.0 on broker. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>7005b22bcfto76037f36a6feat(orchestrator): list_live broker op + reconcile via broker (chunk 3/5)to feat(orchestrator): list_live broker op + reconcile via broker (chunk 3/3)feat(orchestrator): list_live broker op + reconcile via broker (chunk 3/3)to PRD: Host control server - list_live broker op + reconcile via broker (chunk 3/5)View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.