feat(supervise+orchestrator): slice 12 — multi-tenant git-gate hook + supervise server #368

Closed
didericis-claude wants to merge 1 commits from orchestrator-supervise-writers into orchestrator-supervise-multitenant
Collaborator

Slice 12: finishes the supervise data-plane writers for the shared gateway. Slice 11 did the egress token-allow path; the other two proposal writers still keyed off a single SUPERVISE_BOTTLE_SLUG env. Now each proposal is attributed to the calling bottle, consistent with slices 10/11.

git-gate gitleaks-allow hook

The pre-receive hook runs as a child of the git http-backend the backend already spawns (slice 10), so instead of touching the fragile embedded heredoc, the backend just stamps SUPERVISE_BOTTLE_SLUG=<bottle_id> into that CGI env in consolidated mode. The hook inherits it and queues under the right bottle. The bottle id is the namespaced root's final component (<base>/<bottle_id>) — the same per-bottle key egress uses. Single-tenant leaves the container-stamped slug untouched.

supervise_server (agent proposal submission)

_attributed_config resolves the proposal slug per request by source IP when BOT_BOTTLE_ORCHESTRATOR_URL is set — fail-closed: an unattributed or unreachable source raises rather than queue under the wrong (or empty) slug. serve/main build + attach the resolver and make the env slug optional in consolidated mode. Single-tenant unchanged.

Tests

  • A real git push proving SUPERVISE_BOTTLE_SLUG reaches the pre-receive hook's env as the resolved bottle id.
  • The supervise attribution matrix: single-tenant slug kept; source-IP bottle bound; unattributed + resolver-error both fail closed.

Remaining supervise gap (noted)

WebSocket DLP still reads self.config only (inert in consolidated mode) — a separate follow-up.

Verification

pyright 0 errors, pylint 9.83/10, unit suite green (1705 tests; the 13 test_sidecar_init /bin/sleep errors are pre-existing NixOS-local noise).

Stacked on #367.

🤖 Generated with Claude Code

Slice 12: finishes the **supervise data-plane writers** for the shared gateway. Slice 11 did the egress token-allow path; the other two proposal writers still keyed off a single `SUPERVISE_BOTTLE_SLUG` env. Now each proposal is attributed to the calling bottle, consistent with slices 10/11. ### git-gate gitleaks-allow hook The pre-receive hook runs as a **child of the `git http-backend`** the backend already spawns (slice 10), so instead of touching the fragile embedded heredoc, the backend just **stamps `SUPERVISE_BOTTLE_SLUG=<bottle_id>` into that CGI env** in consolidated mode. The hook inherits it and queues under the right bottle. The bottle id is the namespaced root's final component (`<base>/<bottle_id>`) — the same per-bottle key egress uses. Single-tenant leaves the container-stamped slug untouched. ### supervise_server (agent proposal submission) `_attributed_config` resolves the proposal slug **per request by source IP** when `BOT_BOTTLE_ORCHESTRATOR_URL` is set — **fail-closed**: an unattributed or unreachable source raises rather than queue under the wrong (or empty) slug. `serve`/`main` build + attach the resolver and make the env slug optional in consolidated mode. Single-tenant unchanged. ### Tests - A **real git push** proving `SUPERVISE_BOTTLE_SLUG` reaches the pre-receive hook's env as the resolved bottle id. - The supervise attribution matrix: single-tenant slug kept; source-IP bottle bound; unattributed + resolver-error both fail closed. ### Remaining supervise gap (noted) WebSocket DLP still reads `self.config` only (inert in consolidated mode) — a separate follow-up. ### Verification pyright **0 errors**, pylint **9.83/10**, unit suite green (1705 tests; the 13 `test_sidecar_init` `/bin/sleep` errors are pre-existing NixOS-local noise). Stacked on #367. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
didericis-claude added 1 commit 2026-07-13 20:04:44 -04:00
feat(supervise+orchestrator): slice 12 — multi-tenant git-gate hook + supervise server
lint / lint (push) Successful in 2m2s
test / unit (pull_request) Successful in 1m0s
test / integration (pull_request) Successful in 22s
test / coverage (pull_request) Successful in 1m11s
80d75de08a
Finishes the supervise data-plane writers for the shared gateway. Both
still keyed off a single SUPERVISE_BOTTLE_SLUG env; now each proposal is
attributed to the calling bottle, keeping slices 10/11's per-bottle model.

- git_http_backend: in consolidated mode stamp SUPERVISE_BOTTLE_SLUG=
  <bottle_id> into the CGI env. The gitleaks-allow pre-receive hook runs as
  a child of the `git http-backend` we spawn, so it inherits the stamp and
  queues under the right bottle — no change to the (fragile) embedded hook.
  The bottle id is the namespaced root's final component (slice 10), the
  same key egress uses. Single-tenant leaves the container-stamped slug.
- supervise_server: resolve the proposal slug per request by source IP when
  BOT_BOTTLE_ORCHESTRATOR_URL is set (`_attributed_config`), fail-closed —
  an unattributed / unreachable source raises rather than queue under the
  wrong or empty slug. `serve`/`main` build + attach the resolver and make
  the env slug optional in consolidated mode. Single-tenant unchanged.

Tests: a real git push proving the slug reaches the hook's env; the
supervise attribution matrix (single-tenant slug kept, source-IP bottle
bound, unattributed + resolver-error fail closed).

Remaining supervise gap (noted): websocket DLP still self.config-only.

pyright 0 errors; pylint 9.83/10; unit suite green (1705 tests; the 13
test_sidecar_init /bin/sleep errors are pre-existing NixOS-local noise).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
Author
Collaborator

Collapsed into the single stack PR #380 (per-host orchestrator, PRD 0070). Closing this slice PR; review + merge happens on #380.

Collapsed into the single stack PR #380 (per-host orchestrator, PRD 0070). Closing this slice PR; review + merge happens on #380.
didericis-claude closed this pull request 2026-07-14 00:57:30 -04:00
Some checks are pending
lint / lint (push) Successful in 2m2s
test / unit (pull_request) Successful in 1m0s
test / integration (pull_request) Successful in 22s
test / coverage (pull_request) Successful in 1m11s

Pull request closed

Sign in to join this conversation.