← Ledger


title: Phase 7c-b close — external hatch consumer polls rocky projection date: 2026-06-29 status: Accepted phase: 7c-b (external hatch.devarno.cloud/agents consumer) predecessor: docs/decisions/2026-06-29-phase-7c-a-close.md spec: docs/specs/2026-06-29-agent-registration-v1.md plan: docs/plans/2026-06-29-phase-7c-b.md external_repo: devarno-cloud/hatch external_pr: 13 external_merge: 08896dc0f877827c5e6d21ee50f945b1dc78704c

Phase 7c-b close

Shipped

Locked decisions

1. No re-fold on the consumer

Hatch trusts the fold that rocky-hq/console already computes. Adding a second fold client-side would duplicate spec surface and diverge on edge cases (out-of-order arrival, dedupe keys). The rocky projection is authoritative; hatch is a view of a view.

Alternatives rejected:

2. x-rocky-user-role: observer stub for cross-service auth

Rocky's GET is gated on the same three-role model (observer+) it uses for browser callers. Hatch is a trusted operator-tier peer under the same erid.tech umbrella, so a static role header is the minimal-surface bridge until airlock ships a signed cross-service token. That upgrade lands with 7c-c.

Alternatives rejected:

3. Parallel independent loads for airlock + rocky

Promise.all([loadAgents(), fetchRockyAgents()]). Either can fail; the other renders. Independent warning cards. The existing user-agent path is unchanged.

4. 5s timeout, best-effort read

Consumer-side timeouts belong on the poller, not on rocky. 5s is tight enough that a wedged endpoint never blocks an SSR render. Rocky's audit is an in-process JSON read; if 5s is short in practice we bump — but making the timeout longer at this altitude just hides slowness.

5. Rocky projection renders below, not replacing, airlock agents

Two distinct populations: airlock's AdminAgent (user-issued API-key agents — the airlock's own "who has an approved API key" list) versus rocky's registry projection (operator-facing agent.* producer view from council/sniffer/stratt/ralph/relay/driver). Same page because both answer "what agents exist"; separated because they answer it at different altitudes. When the two populations converge (e.g. when airlock 7c-c gates agent.approve on both), this split can revisit.

6. No workspace filter UI

Rocky supports ?workspace=<slug> on GET; hatch renders all workspaces flat in this slice. Hatch does not have a workspace switcher — it lists everything the operator owns. A filter UI can land when hatch grows tenant partitioning, not before.

Deferred

Acceptance verified

Phase 7 status after this slice

Slice State Notes
7a closed contract published, contracts v0.3.0
7b closed all 6 producers + RALPH natural-terminal observer
7c-a closed rocky-side audit + GET projection endpoint
7c-b closed (this) external hatch consumer wired
7c-c not-started Polar RATE enforcement + Airlock agent.approve (external repos)

Rocky-hq producer side + external hatch consumer side both complete. Remaining Phase 7 work is entirely in polar/airlock territory.

Sources