deploy-gap: #828 lease-broker enforcement hooks shipped without a running broker daemon — bricks fleet agents (GATE_UNAVAILABLE / Stop-block) #869
Reference in New Issue
Block a user
Delete Branch "%!s()"
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?
Severity: P0 — bricked every Claude/Pi agent on the fleet host (
web1) after the 2026-07-22 04:22 framework upgrade. Currently held up only by two host-local fail-open bypasses (details below). cc @jason.woltje (owner of #828 / #860).Summary
The #828 lease-broker enforcement hooks were deployed (wired into
~/.claude/settings.json) without the broker runtime that makes them functional. Themutator-gate.py(PreToolUse) andreceipt-observer-client.py(Stop) hooks correctly fail closed when the broker identity env / socket is absent — but onweb1nothing starts the broker daemon and nothing injects the lease env, so every tool call is deniedGATE_UNAVAILABLEand every turn-end is blocked. This is a deploy-ordering gap, not a code bug in the gate.What happened
The 04:22 upgrade shipped the complete lease-broker toolkit under
~/.config/mosaic/tools/lease-broker/—daemon.py,launch-runtime.py,mutator-gate.py,receipt-observer-client.py,recover-context.py,lease_generation.py,revoke-lease.py, … — and wired the enforcement hooks into the runtime settings. But the activation half of #828 (a supervisor that runsdaemon.py, plus launch always chaining throughlaunch-runtime.pyto injectMOSAIC_LEASE_*) is not present on the host.Evidence (host
web1, userhermes)~/.claude/settings.json:PreToolUsematcher.*→python3 …/lease-broker/mutator-gate.py --runtime claude --recovery-command …/recover-context.pyStop→python3 …/lease-broker/receipt-observer-client.py --runtime claude --latest-entrypgrep -af daemon.py→ none;/run/user/<uid>/mosaic-lease/→ does not exist.*lease*/*broker*unit under~/.config/systemd/user/.claudeprocess carries noMOSAIC_LEASE_SESSION_ID/MOSAIC_LEASE_BROKER_SOCKET/MOSAIC_RUNTIME_GENERATION. The fleet runner launches viamosaic yolo claude; the installed CLI is 0.0.48 (dist/cli.jsbundled). In current framework sourceexecLeaseGatedRuntime()chainsclaudethroughlaunch-runtime.pyand setsMOSAIC_LEASE_BROKER_SOCKET, butlaunch-runtime.pyregister_anchor()requires a listening broker — which is not deployed. Whether 0.0.48 gates or execs claude directly, the outcome on this host is identical: enforcement hooks fire with no broker behind them.mos-claude.serviceagent reported everyBash/Read/Edit/WritedeniedGATE_UNAVAILABLE; the Stop hook re-blocked deterministically (the "hook blocked N times" backstop symptom).Why fail-open is NOT the fix
The gate's fail-closed-on-absent-identity behavior is intentional and test-locked — weakening it would (correctly) break these tests:
test_gate_entrypoint_denies_when_identity_environment_is_absenttest_environment_generation_and_request_failures_denySo the fix is infrastructure activation, not relaxing the gate.
Root cause
Enforcement was rolled out one step ahead of the infrastructure it depends on: the hooks assume a running broker +
launch-runtime.py-injected lease env that #828's activation work was supposed to guarantee on every host, but that activation never landed on the fleet host.Proposed fix direction (owner's call)
daemon.py(systemd--userunit, or fold broker startup into the launch path) so the broker socket exists before any gated runtime starts.mosaic yolo claudeon the deployed CLI) always goes throughlaunch-runtime.pysoMOSAIC_LEASE_*is injected — or make the hook a no-op when the host has explicitly not activated the broker (a deliberate, documented opt-out, not a silent fail-open).Current mitigation (temporary — to be reverted once the above lands)
To restore the fleet, two host-local fail-opens are in place on
web1(originals preserved at*.pre-bypass-bak):mutator-gate.py: returns 0 (allow) whenMOSAIC_LEASE_BROKER_SOCKETis unset.receipt-observer-client.py: replaced with a drain-stdin / exit-0 stub.These are acknowledged as incorrect long-term (they defeat #828 enforcement) and must be reverted the moment the broker is properly activated. Do not run a
mosaicframework upgrade onweb1until this is resolved — an upgrade reverts these bypasses and re-bricks the fleet.References