You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Track the cross-repo rollout for the Gateway operator control surface across fro-bot/agent, fro-bot/dashboard, marcusrbrown/infra, and this control-plane repo.
The GitHub Project matrix is the structured source of truth. This issue body is the human-readable rollup; comments are the audit log.
Shipped / closed:
fro-bot/agent#907 is closed. The gateway producer spine is complete on main at operator contract v1.5.0.
fro-bot/agent#1033 is merged and released as v0.78.0. Agent releases have since advanced to v0.85.0. The deployed gateway is pinned to v0.83.0 and runs operator contract v1.6.0 live (dashboard.fro.bot/operator/health returns {"ok":true,"contractVersion":"1.6.0"}). The v1.5.0 → v1.6.0 cutover is complete: main, the latest release (v0.85.0), and the deployed gateway (v0.83.0) all carry contract v1.6.0.
fro-bot/agent#1111 is merged. Operator-initiated run cancellation is code-complete on main: POST /operator/runs/:runId/cancel cancels a queued or executing run, auto-rejects any pending tool approval through the single settlement gate, posts a cancellation notice to the run's origin Discord thread, and reconciles a per-repo lock stranded by a crash mid-cancel on startup recovery. This closes the one functional gap in the operator surface (previously launch/list/stream/approve but no stop). It bumped the operator contract to v1.6.0 (additive route + response type, MINOR), and is now released in v0.83.0 (2026-07-04) and deployed — the running gateway carries the cancellation route and contract v1.6.0.
fro-bot/agent#1109 is merged. Fixes a latent bug where run-state thread_id was written empty at admission and never persisted, which broke discord approval-scope resolution (scopeIdFor) and startup recovery thread-notes. Repaired at the root by persisting the live thread_id at run adoption; web/GitHub surfaces (scoped on run_id) were unaffected.
fro-bot/agent operator push notifications shipped across six PRs (#1152, #1157, #1160, #1162, #1163, #1165) and released in v0.85.0 (2026-07-11). The gateway is now the authoritative owner of operator push subscriptions, VAPID dispatch, and the notification lifecycle (pending approvals, failed runs, logout deactivation), with a durable subscription store, a connect-time SSRF guard on the relay path, and coarse lifecycle audit events. Push is disabled-by-default (active only when VAPID config is present) and adds only /operator/push/* REST routes — it deliberately does not bump OPERATOR_CONTRACT_VERSION, since additive REST is invisible to the dashboard's SSE ready-frame drift gate, so v0.85.0 carries contract v1.6.0 unchanged. Not yet deployed (the deployed pin is v0.83.0); production enablement additionally requires VAPID secret provisioning.
fro-bot/dashboard#108 is closed (COMPLETED). It scoped the browser half of operator push (consent UI, PushManager handoff, service-worker notification rendering/click handling); the gateway server half is the v0.85.0 push feature above. Any remaining browser-side push consumption is dashboard-repo work.
fro-bot/agent#929 shipped the web operator surface foundation.
fro-bot/agent#931 shipped the operator listener topology.
Unit 3 work landed across fro-bot/agent#932, #934, #936, #939, and #944.
Unit 7 was cut and superseded by GET /operator/repos; raw binding records must not reach the browser.
marcusrbrown/infra#579, #580, and #581 are closed.
fro-bot/dashboard#24, #25, #26, #39, #47, #53, #59, and #81 are closed.
fro-bot/dashboard#48 is closed as superseded. The dashboard already consumes canonical approval settle frames (settled:true) and must not invent deadline-specific copy unless a future gateway contract exposes a deadline reason or timestamp.
fro-bot/dashboard#122 is merged. The PWA is now operator-first: / renders the operator shell, the user-facing monitoring UI is suspended from the active frontend, and /api/monitoring survives behind operator auth as a server-side snapshot endpoint.
Tracker automation:
fro-bot/.github#3514 installed the scheduled Gateway Rollout Tracker workflow.
fro-bot/.github#3517 made tracker comments deterministic and idempotent with a Project/issue-state preflight.
The latest settled tracker snapshot is c112ff2769bfd1abf3d7311fba5686f098a2bed5b7821a7d45c0d4c7c6be58a6.
Still open / not yet complete:
fro-bot/.github#3512 — this tracker issue. Keep it open until live dashboard/operator verification (browser-session flows) and the push deploy/enablement tail are complete. The gateway-side deployed-version and contract-match gates are now satisfied.
Gateway live capability verification — the deployed gateway (v0.83.0) now runs contract v1.6.0 and carries run cancellation (#1111) and the thread_id persistence fix (#1109), both released in v0.83.0 and live. What remains is end-to-end verification of the live operator capability flows (launch, run listing, run stream, repo listing, approvals, run cancellation) and OAuth/session/CSRF/logout behavior against the deployed gateway — this is browser-session operator verification (dashboard-repo work), not gateway-side.
Operator push deploy + enablement (v0.85.0) — the push feature is released in v0.85.0 but not yet deployed (the deployed pin is v0.83.0). Production enablement additionally requires VAPID secret provisioning (marcusrbrown/infra) and the dashboard browser half (consent UI, PushManager, service worker). Push is disabled-by-default, so deploying v0.85.0 without VAPID config is inert on the push surface.
Dashboard consumption of the v1.6.0 contract — the dashboard already pins OPERATOR_CONTRACT_VERSION at v1.6.0 (the cutover landed with the deployed gateway; the exact-match drift gate is satisfied on both sides). The remaining dashboard-side UI work — the Cancel button consuming POST /operator/runs/:runId/cancel and per-kind failureKind failure copy — is tracked at fro-bot/dashboard#179.
Phase-1 monitoring tail — the user-facing monitoring UI is intentionally suspended by fro-bot/dashboard#122, not relocated or fallback. The remaining verification is to ratify that suspension as a deliberate decision and to verify R8 against the surviving /api/monitoring server-side endpoint and the monitoring-v1 cache-purge path, per docs/plans/2026-06-15-001-feat-monitoring-dashboard-phase-1-plan.md.
Cross-repo dependency matrix
Workstream
Item
State
Notes
Agent
fro-bot/agent#907
Done
Producer spine closed at contract v1.5.0.
Agent
fro-bot/agent#1033
Released
v0.78.0 published; releases since advanced to v0.85.0; deployed gateway pinned at v0.83.0, running contract v1.6.0 live.
Agent
fro-bot/agent#1111
Deployed
Operator run cancellation; bumped operator contract v1.5.0 → v1.6.0; released in v0.83.0 and live.
Agent
fro-bot/agent#1109
Deployed
Persists run-state thread_id at adoption; repairs discord approval-scope resolution + recovery thread-notes; released in v0.83.0.
Gateway-owned push subscriptions, VAPID dispatch, connect-time SSRF guard, lifecycle audit; released in v0.85.0 (contract unchanged at v1.6.0). Not yet deployed; needs VAPID secrets + dashboard browser half for enablement.
Dashboard
Cancel UI (fro-bot/dashboard#179)
Open
Cancel button consuming POST /operator/runs/:runId/cancel + per-kind failureKind copy. The v1.6.0 pin cutover is already complete (dashboard and deployed gateway both at v1.6.0).
Dashboard
Push browser half (fro-bot/dashboard#108)
Done
Closed COMPLETED; scoped consent UI / PushManager / service-worker rendering. Gateway server half shipped in v0.85.0.
Dashboard
fro-bot/dashboard#48
Done
Closed as superseded by canonical settled:true approval settle-frame behavior.
Coordination issue stays open until deploy/live verification and security/R8 checks are done.
Remaining rollout tasks
Confirm the deployed gateway is running a release that includes the current operator contract.Done (re-verified 2026-07-11 at v0.83.0 / contract v1.6.0). The contractVersion health-body field (shipped since #1096) now makes this a one-line probe:
marcusrbrown/infra pins the gateway to fro-bot/agentv0.83.0 (apps/gateway/upstream.json, pin bump 7b9bffd7b, 2026-07-04); version.ts at tag v0.83.0 declares OPERATOR_CONTRACT_VERSION = '1.6.0' and the tag carries the #1111 cancellation route and #1109thread_id fix.
The deploy asserts the running droplet image digest equals the CI-built digest and fails closed on mismatch.
Not yet advanced to v0.85.0 (operator push); that deploy is gated on VAPID secret provisioning and is inert on the push surface without it.
Complete live operator verification before marking the rollout complete:
gateway-origin operator routes deny as expected when reached from the wrong boundary.
launch, run listing, run stream, repo listing, approval, and run cancellation flows work against the deployed gateway.
OAuth/session/CSRF/logout behavior is verified end-to-end.
redaction/denylist behavior is checked against production-shaped data.
Phase-1 plan's operational/security tail:
ratify the monitoring-UI suspension from fro-bot/dashboard#122 as a deliberate decision, not a missing or fallback surface.
R8 verification against the surviving /api/monitoring endpoint and the monitoring-v1 cache-purge path: zero private repo names or node_id leaks in SSR, API, logs, or cache; fail closed on metadata failure.Verified in code (2026-06-28). All four leak surfaces pass with pinned tests: SSR renders no repo identity pre-auth; /api/monitoring is auth-gated with a strict DTO whitelist (internal identity fields never emitted) and Cache-Control: no-store; every aggregator logger call routes through safeRepoLogIdentity/safeRepoErrorContext; /api/* is service-worker NetworkOnly (never cached) and monitoring-v1 is purged on logout; metadata failure fails closed (no fresh query, no partial identity). One low-severity nit filed: /api/status lacks no-store (fro-bot/dashboard#125). The residual node_id-format gap is tracked at fro-bot/.github#3525. Production-shaped runtime confirmation against a live snapshot with both public and denylisted repos is still owed.
infra security posture: App key is file-mounted, container hardening is in place, secrets are absent from logs.Verified in code (2026-06-28). App private key is file-mounted (container receives a path via *_FILE, never key material in env; O_NOFOLLOW read); secrets are delivered via SSH stdin (never argv) with redaction on failure; the deploy asserts the running image digest fails closed on mismatch. Two gaps filed: gateway container hardening (fro-bot/agent#1053, closed 2026-06-28 — cap_drop: ALL + no-new-privileges shipped on main; read-only rootfs + non-root user deferred pending a tmpfs-mount audit), and there is no dedicated GitHub App key revocation runbook (marcusrbrown/infra#711).
post-merge security review for the dashboard and infra surfaces.
Keep the Project matrix current; use this issue for audit comments only when state actually changes.
Risks to keep visible
Same-origin cookie boundary: do not rely on cross-site browser cookies between dashboard and Gateway origins.
Auth/session duplication: dashboard's existing session is not Gateway operator auth.
SSE proxy buffering: reverse proxy must support long-lived streams without buffering.
Approval settlement: the UI must dismiss settled prompts without inventing settlement reasons the gateway does not send.
Binding enumeration: dashboard repo selection must not expose raw binding records or private-repo identity.
Announce ingress separation: existing /v1/announce HMAC route must remain distinct from browser operator control.
Operator contract drift (exact-match, fail-closed): the dashboard's drift gate breaks every operator run stream at the ready frame on any OPERATOR_CONTRACT_VERSION skew. The v1.5.0 → v1.6.0 cutover is complete and matched on both sides, so this is currently satisfied. It stays a live risk for any FUTURE contract bump — a gateway release/deploy carrying a new contract version and the dashboard's pin bump must land in the same deploy window. v0.85.0 (push) is deliberately contract-neutral (v1.6.0 unchanged), so deploying it carries no drift risk.
Suspended-surface drift: with the monitoring UI gone, the surviving /api/monitoring endpoint and its cache-purge path must stay watched so a removed thing does not become an unwatched thing.
Acceptance criteria
The Project matrix is current and reflects all shipped/closed rollout items.
fro-bot/dashboard#48 is closed as superseded by canonical settle-frame behavior.
The deployed gateway's operator contract version is verified and matched by the dashboard pin before live rollout claims are made. Satisfied: the deployed gateway (v0.83.0) runs contract v1.6.0 live and the dashboard pin is at v1.6.0 — the exact-match drift gate holds on both sides.
Production operator flows are verified live, including auth, CSRF, repo/run surfaces, SSE, approvals, and privacy boundaries.
R8/privacy verification, infra security posture, revocation runbook, and post-merge security review are complete.
This issue links the cross-repo issues and records state transitions without performing implementation directly from the tracker.
Summary
Track the cross-repo rollout for the Gateway operator control surface across
fro-bot/agent,fro-bot/dashboard,marcusrbrown/infra, and this control-plane repo.Project matrix: Gateway operator control-surface rollout
Current state
The GitHub Project matrix is the structured source of truth. This issue body is the human-readable rollup; comments are the audit log.
Shipped / closed:
fro-bot/agent#907is closed. The gateway producer spine is complete onmainat operator contractv1.5.0.fro-bot/agent#1033is merged and released asv0.78.0. Agent releases have since advanced tov0.85.0. The deployed gateway is pinned tov0.83.0and runs operator contractv1.6.0live (dashboard.fro.bot/operator/healthreturns{"ok":true,"contractVersion":"1.6.0"}). Thev1.5.0→v1.6.0cutover is complete:main, the latest release (v0.85.0), and the deployed gateway (v0.83.0) all carry contractv1.6.0.fro-bot/agent#1111is merged. Operator-initiated run cancellation is code-complete onmain:POST /operator/runs/:runId/cancelcancels a queued or executing run, auto-rejects any pending tool approval through the single settlement gate, posts a cancellation notice to the run's origin Discord thread, and reconciles a per-repo lock stranded by a crash mid-cancel on startup recovery. This closes the one functional gap in the operator surface (previously launch/list/stream/approve but no stop). It bumped the operator contract tov1.6.0(additive route + response type, MINOR), and is now released inv0.83.0(2026-07-04) and deployed — the running gateway carries the cancellation route and contractv1.6.0.fro-bot/agent#1109is merged. Fixes a latent bug where run-statethread_idwas written empty at admission and never persisted, which broke discord approval-scope resolution (scopeIdFor) and startup recovery thread-notes. Repaired at the root by persisting the livethread_idat run adoption; web/GitHub surfaces (scoped onrun_id) were unaffected.fro-bot/agentoperator push notifications shipped across six PRs (#1152,#1157,#1160,#1162,#1163,#1165) and released inv0.85.0(2026-07-11). The gateway is now the authoritative owner of operator push subscriptions, VAPID dispatch, and the notification lifecycle (pending approvals, failed runs, logout deactivation), with a durable subscription store, a connect-time SSRF guard on the relay path, and coarse lifecycle audit events. Push is disabled-by-default (active only when VAPID config is present) and adds only/operator/push/*REST routes — it deliberately does not bumpOPERATOR_CONTRACT_VERSION, since additive REST is invisible to the dashboard's SSE ready-frame drift gate, sov0.85.0carries contractv1.6.0unchanged. Not yet deployed (the deployed pin isv0.83.0); production enablement additionally requires VAPID secret provisioning.fro-bot/dashboard#108is closed (COMPLETED). It scoped the browser half of operator push (consent UI,PushManagerhandoff, service-worker notification rendering/click handling); the gateway server half is thev0.85.0push feature above. Any remaining browser-side push consumption is dashboard-repo work.fro-bot/agent#929shipped the web operator surface foundation.fro-bot/agent#931shipped the operator listener topology.fro-bot/agent#932,#934,#936,#939, and#944.GET /operator/repos; raw binding records must not reach the browser.marcusrbrown/infra#579,#580, and#581are closed.fro-bot/dashboard#24,#25,#26,#39,#47,#53,#59, and#81are closed.fro-bot/dashboard#48is closed as superseded. The dashboard already consumes canonical approval settle frames (settled:true) and must not invent deadline-specific copy unless a future gateway contract exposes a deadline reason or timestamp.fro-bot/dashboard#122is merged. The PWA is now operator-first:/renders the operator shell, the user-facing monitoring UI is suspended from the active frontend, and/api/monitoringsurvives behind operator auth as a server-side snapshot endpoint.Tracker automation:
fro-bot/.github#3514installed the scheduled Gateway Rollout Tracker workflow.fro-bot/.github#3517made tracker comments deterministic and idempotent with a Project/issue-state preflight.c112ff2769bfd1abf3d7311fba5686f098a2bed5b7821a7d45c0d4c7c6be58a6.Still open / not yet complete:
fro-bot/.github#3512— this tracker issue. Keep it open until live dashboard/operator verification (browser-session flows) and the push deploy/enablement tail are complete. The gateway-side deployed-version and contract-match gates are now satisfied.v0.83.0) now runs contractv1.6.0and carries run cancellation (#1111) and thethread_idpersistence fix (#1109), both released inv0.83.0and live. What remains is end-to-end verification of the live operator capability flows (launch, run listing, run stream, repo listing, approvals, run cancellation) and OAuth/session/CSRF/logout behavior against the deployed gateway — this is browser-session operator verification (dashboard-repo work), not gateway-side.v0.85.0) — the push feature is released inv0.85.0but not yet deployed (the deployed pin isv0.83.0). Production enablement additionally requires VAPID secret provisioning (marcusrbrown/infra) and the dashboard browser half (consent UI,PushManager, service worker). Push is disabled-by-default, so deployingv0.85.0without VAPID config is inert on the push surface.v1.6.0contract — the dashboard already pinsOPERATOR_CONTRACT_VERSIONatv1.6.0(the cutover landed with the deployed gateway; the exact-match drift gate is satisfied on both sides). The remaining dashboard-side UI work — the Cancel button consumingPOST /operator/runs/:runId/canceland per-kindfailureKindfailure copy — is tracked atfro-bot/dashboard#179.fro-bot/dashboard#122, not relocated or fallback. The remaining verification is to ratify that suspension as a deliberate decision and to verify R8 against the surviving/api/monitoringserver-side endpoint and themonitoring-v1cache-purge path, perdocs/plans/2026-06-15-001-feat-monitoring-dashboard-phase-1-plan.md.Cross-repo dependency matrix
fro-bot/agent#907v1.5.0.fro-bot/agent#1033v0.78.0published; releases since advanced tov0.85.0; deployed gateway pinned atv0.83.0, running contractv1.6.0live.fro-bot/agent#1111v1.5.0→v1.6.0; released inv0.83.0and live.fro-bot/agent#1109thread_idat adoption; repairs discord approval-scope resolution + recovery thread-notes; released inv0.83.0.#1152/#1157/#1160/#1162/#1163/#1165)v0.85.0(contract unchanged atv1.6.0). Not yet deployed; needs VAPID secrets + dashboard browser half for enablement.fro-bot/dashboard#179)POST /operator/runs/:runId/cancel+ per-kindfailureKindcopy. Thev1.6.0pin cutover is already complete (dashboard and deployed gateway both atv1.6.0).fro-bot/dashboard#108)PushManager/ service-worker rendering. Gateway server half shipped inv0.85.0.fro-bot/dashboard#48settled:trueapproval settle-frame behavior.fro-bot/dashboard#122/api/monitoringendpoint survives behind operator auth.marcusrbrown/infra#579marcusrbrown/infra#580marcusrbrown/infra#581fro-bot/.github#3512Remaining rollout tasks
Confirm the deployed gateway is running a release that includes the current operator contract.Done (re-verified 2026-07-11 atv0.83.0/ contractv1.6.0). ThecontractVersionhealth-body field (shipped since#1096) now makes this a one-line probe:dashboard.fro.bot/operator/healthreturns{"ok":true,"contractVersion":"1.6.0"}— the running gateway reports contractv1.6.0directly.marcusrbrown/infrapins the gateway tofro-bot/agentv0.83.0(apps/gateway/upstream.json, pin bump7b9bffd7b, 2026-07-04);version.tsat tagv0.83.0declaresOPERATOR_CONTRACT_VERSION = '1.6.0'and the tag carries the#1111cancellation route and#1109thread_idfix.v0.85.0(operator push); that deploy is gated on VAPID secret provisioning and is inert on the push surface without it.dashboard.fro.bot/operator/healthreturns healthy./and/operatorremain auth-gated.fro-bot/dashboard#122as a deliberate decision, not a missing or fallback surface.R8 verification against the survivingVerified in code (2026-06-28). All four leak surfaces pass with pinned tests: SSR renders no repo identity pre-auth;/api/monitoringendpoint and themonitoring-v1cache-purge path: zero private repo names ornode_idleaks in SSR, API, logs, or cache; fail closed on metadata failure./api/monitoringis auth-gated with a strict DTO whitelist (internal identity fields never emitted) andCache-Control: no-store; every aggregator logger call routes throughsafeRepoLogIdentity/safeRepoErrorContext;/api/*is service-worker NetworkOnly (never cached) andmonitoring-v1is purged on logout; metadata failure fails closed (no fresh query, no partial identity). One low-severity nit filed:/api/statuslacksno-store(fro-bot/dashboard#125). The residual node_id-format gap is tracked atfro-bot/.github#3525. Production-shaped runtime confirmation against a live snapshot with both public and denylisted repos is still owed.infra security posture: App key is file-mounted, container hardening is in place, secrets are absent from logs.Verified in code (2026-06-28). App private key is file-mounted (container receives a path via*_FILE, never key material in env;O_NOFOLLOWread); secrets are delivered via SSH stdin (never argv) with redaction on failure; the deploy asserts the running image digest fails closed on mismatch. Two gaps filed: gateway container hardening (fro-bot/agent#1053, closed 2026-06-28 —cap_drop: ALL+no-new-privilegesshipped onmain; read-only rootfs + non-root user deferred pending a tmpfs-mount audit), and there is no dedicated GitHub App key revocation runbook (marcusrbrown/infra#711).Risks to keep visible
/v1/announceHMAC route must remain distinct from browser operator control.readyframe on anyOPERATOR_CONTRACT_VERSIONskew. Thev1.5.0→v1.6.0cutover is complete and matched on both sides, so this is currently satisfied. It stays a live risk for any FUTURE contract bump — a gateway release/deploy carrying a new contract version and the dashboard's pin bump must land in the same deploy window.v0.85.0(push) is deliberately contract-neutral (v1.6.0unchanged), so deploying it carries no drift risk./api/monitoringendpoint and its cache-purge path must stay watched so a removed thing does not become an unwatched thing.Acceptance criteria
fro-bot/dashboard#48is closed as superseded by canonical settle-frame behavior.v0.83.0) runs contractv1.6.0live and the dashboard pin is atv1.6.0— the exact-match drift gate holds on both sides.