2026-06 · Workshop
Home Assistant on the LAN, a bridge that only dials out, authorization enforced inside Postgres, and a public page that cannot leak whether anyone is home. Phases 0 through 4 merged in one day. The security model is a button, not a paragraph.
9
merges on the surface
17
checks run against the live database
413 to 639 ms
command round trip, 3 s budget
I wanted to control my house from anywhere and I wanted a public page that shows the house is real and running. Those two goals normally fight: expose the automation server and it is a scannable target; put authorization in application code and one bug in a route handler is control of physical devices; publish live telemetry and anyone can learn when the house is empty; queue a command while the link is down and it fires hours later on a garage door.
Consumer hardware and a home network I refuse to expose: no port forward, no VPN endpoint, no tunnel listener. A public page had to be truthful without becoming a schedule of when nobody is home. Leak sensors had to open an incident with no human awake to notice.
Three planes with one-way trust. A small worker on the LAN (under 300 lines, two dependencies) opens an outbound socket to Home Assistant and an outbound connection to a hosted Postgres broker, and accepts nothing. The web app never talks to devices; it inserts a command row through one SECURITY DEFINER function that re-checks membership, role, device flags, capability allowlist, and a rate limit inside the database. Commands expire at sixty seconds instead of firing late. New devices land locked down. Public telemetry flows through two views that coarsen state to a scalar, delay it per device, and exclude presence, locks, garage, alarm, cameras, and media unconditionally.
Rejected
Port-forward or tunnel into Home Assistant
Every one of those is an inbound listener on the house. Nothing connects in, so a compromised web tier still has nothing to reach.
Authorization in the route handlers
One bug in a handler becomes control of physical devices. The insert path is the check, so the app cannot skip it.
A live public badge
Live telemetry is an occupancy feed. State is coarsened, delayed, and stamped with its own age, and the page renders observed fourteen minutes ago instead of live.
Schema, bridge, admin heartbeat, state mirror with staging promotion, live controls with expiry, scenes through the same command pipeline, an incidents engine with leak-to-critical-incident in about a second and a scheduled bridge-offline check, and the public observability page, all merged on 2026-06-12. A runnable systemd unit for the bridge followed in September.
The first heartbeat could report the bridge healthier than it was. The same-day fix (#1042) made the heartbeat truthful and added the in-app verification panel, which is the part I should have built first: a trust boundary you cannot re-prove on demand is a claim, not a control. The bridge also ran without a proper service unit for three months before #2346.
feat(manor): phase 0 foundation, schema plus bridge skeleton plus admin heartbeat
#1033 · 2026-06-12 · feature
feat(manor): phase 1 state mirror, staging promotion, live board; retire sitter page
#1040 · 2026-06-12 · feature
feat(manor): in-app gate verification panel + truthful-heartbeat and resync-provenance fixes
#1042 · 2026-06-12 · bugfix
feat(manor): phase 2 command loop, live controls, expiry honesty, verifier ladder
#1051 · 2026-06-12 · feature
feat(manor): phase 3a scenes through the command pipeline, atomic and role-gated
#1055 · 2026-06-12 · infra
feat(manor): phase 3b incidents engine + phase 4 public observability page
#1059 · 2026-06-12 · feature
MANOR bridge: runnable systemd unit + install.sh
#2346 · 2026-09-10 · feature
Checked at build against the published corpus.
www.jakelawrence.xyz/research/case-study-library/manor-control-plane
Cite: Lawrence, J. (2026). A public window and a private control plane over a live house, with no inbound ports. jakelawrence.xyz case study library.
I design and ship AI tools, full-stack apps, and data pipelines — end to end, to production. Tell me the problem in a sentence; I'll give you an honest read on fit within a day.
Work with me →