Skip to content

2026-08-20: The Bridge Was Fine

Pencil sketch of a brass fire gong frozen mid-strike above a workbench where a home router still shows one teal status lamp and three game consoles lie on their sides with cracked tiles — amber halo on the gong, teal on the lamp.

The Signal ping at 22:35 was [Sanctum INFO] Screen-time enforcement restored: Firewalla bridge is reachable again; kids' curfew enforcement is back to normal. There had been no matching DOWN on Signal. Quiet hours had swallowed the critical. The close-the-loop patch from The Restore That Never Rang had done its job: recovery was forced onto the channel the operator actually watches. The words on that channel were wrong.

Albert’s holiday curfew is 23:00. Winddown phase 0 (social) fires at 22:30. Force Flow posted POST /host/{mac}/rules across the kids’ devices in a few seconds. The first eight landed. Then the box returned HTTP 500 on the Xbox’s two NICs and the TCL Google TV.

Three 5xx. Circuit open. Backoff 300 seconds. Title: enforcement DOWN. Body: The Firewalla bridge is unreachable or rejecting auth.

The bridge process answered every call. The token was readable. Nothing was shadowing :1984. GET /health was fine. This is the same load-500 class the August 5 field note already named — a burst of policy:create under winddown, not a dead box.

It is also nightly. Same 22:30 500, same 22:35 restore, on the 13th, 15th, 16th, 17th, 18th, and 19th. The gong rang because three host writes failed, then rang again because the breaker closed. The router lamp never went out.

Force Flow delivers title: message verbatim. The producer invented the outage.

Lie one — the copy. _bridge_note_failure had one canned body for every classified failure: missing token, HTTP 401, connect timeout, and HTTP 500. “Unreachable or rejecting auth” is a mash of two different faults, and it is false for a 500. The restore mashed them again: “reachable again” is only true if the DOWN was a transport failure.

Lie two — the circuit. Per-host POST /host/{mac}/rules 500 incremented the global enforcement breaker. After the third xbox tile cracked, Force Flow stopped writing every device for five minutes and told the parent the bridge was gone. Eight social blocks had already landed. The last three hosts would have been retried on the next tick if the breaker had stayed closed.

The Restore That Never Rang taught the close-the-loop rule: if you page CRITICAL, Signal must hear the recovery. This night proved the inverse. A recovery that is forced onto Signal still has to describe the thing that actually happened, or the operator spends the next morning asking what broke.

In screen_time.py, every bridge failure now carries a kind. The parent page is rendered from that kind. “Unreachable” is reserved for transport. Missing token is a config fault, not an outage. Global 5xx (GET /hosts, /policies, /info) still opens the breaker — we cannot see the world — and the page names HTTP 503 on GET /hosts. Per-host 5xx logs and returns None; it does not open the breaker and does not page.

KindTitleSays
connect / timeoutenforcement DOWNunreachable (TimeoutError on the path)
401 after refreshenforcement DOWNrejecting auth (HTTP 401 on the path)
no tokenenforcement DISABLEDconfig fault, not an outage
global 5xxwrites failingHTTP 5xx on the path — never unreachable
per-host 5xx(no page)log only

Restore says “reachable again” only when the DOWN named unreachability. Auth restore says auth is working again. 5xx restore says writes resumed.

The suite that owns the breaker (test_bridge_resilience.py) pins each kind, including “per-host 500 does not page” and “copy helpers never say unreachable for a non-transport cause.” Full hermetic suite green at ship.

sanctum-screen-time on the Mini is the live engine (symlink into Force Flow). Landing on main is not enough. Force Flow PID 889 started 2026-08-19 16:27 and holds the old module in memory until the process that owns :4077 is actually replaced. launchctl kickstart without -k is a no-op when /health is green — the launch wrapper exits 0 on purpose, to avoid EADDRINUSE storms.

The reload is sudo /bin/launchctl kickstart -k system/haus.sanctum.force-flow. That exact command is what sudoers-sanctum-kickstart grants NOPASSWD. On 2026-08-19 the repo file was renamed to haus.sanctum.*; live sudoers still matched com.sanctum.force-flow, so kickstart returned 113 (service not found) and PID 889 did not move.

Bert reinstalled the file at 09:57 (visudo -cf parsed OK, install 440 root:wheel, size 1210 matches the repo). Then -k replaced the listener. New PID 53632 started 2026-08-20 09:57:31 — after the tree mtime 07:21:48. /screen/liveness enforcement_ready=true, last tick 8s after start. Thirteen enrolled screens still blocked (holiday wake 10:00). Albert already off curfew (wake 09:00), personal unpaused. Bridge sentinel HEALTHY.

GateEvidence
Everything E2E Testedtest_bridge_resilience.py including per-host 5xx, no-token config-fault copy, global-5xx warn, auth restore without “reachable again”; full hermetic suite 890 passed, 4 skipped
in Sanctum-docsThis field note + sidebar entry
Mergedsanctum-screen-time 259d779 on origin/main
And DeployedForce Flow PID 53632 started 2026-08-20 09:57:31 (file mtime 07:21:48). /screen/liveness enforcement_ready=true. 13/13 enrolled screens still blocked. Sentinel HEALTHY. Sudoers reinstalled haus.sanctum.* 09:57

The August 5 note closed the loop so a real outage’s recovery could be heard. This one stops the haus from hearing an outage that did not happen. The gong can still ring. It has to mean something.