The repo says what every Sentry should be. Deploys ship the code, the command queue ships the settings, the heartbeat reports the truth, and this console compares the two — and fixes the difference.
1. Declare
fleet/ in the repo says what a device should be
2. Push
the declaration is stored in the cloud
3. Compare
diffed against the device's own heartbeat
4. Apply
one finding → one queued command → one honest ack
5. Verify
the next heartbeat shows the drift gone
The loop runs on the Desired State panel of every device page.
| Sentry | The product name for a door unit — the box on the wall with the camera. Lives on the enclosure and the site. |
| door | The same thing's technical name. In the database (devices.kind), heartbeats, and config it is always `door`. |
| pit-door / grounds-door | The two live Sentries, named for the door they guard. These fleet aliases are what every fleet command takes. |
| cloud_id | The UUID the backend knows a device by. The device's file in fleet/devices/ records both names so they can never drift apart. |
| Hawkeye | The sibling product — the mat camera. Not a door. |
| sim-door | A disposable fake Sentry that exists only while the test rig runs. See below. |
The code that runs on a Sentry — core/, v2/, agent/, integrations/. Face recognition, the door relay, the heartbeat agent. This is software.
The description of what a Sentry should be — fleet/. Not software: a statement of fact in three stacked layers, later layers winning.
A device file may hold only physical facts — a GPIO pin, a camera rotation, a door id. Anything else needs a written why: and is reported as a standing exception forever. Sameness is free; divergence costs a line and stays visible. And fleet/ never ships to a Pi — it is the blueprint on the desk, not a part of the building.
There is no git on a Pi. Deploying is one script, run from a repo checkout:
Sync the shared root
fleet/, docs/, databases, retired modules) can never reach production hardware, even by accident.Remove what was retired
Overlay v2/
The core rule (contract C21): SSH is for looking, never for changing. Both doors were once configured by hand over SSH; they silently diverged, and one ran a hidden 3am job for days because no check can see a hand-edited machine.
Three commands cover everything a machine's state is made of: set_config (change or delete config keys), set_service_state (enable / disable / mask a service), set_cron (replace the crontab whole — a merge would preserve exactly the stowaway line this system exists to kill).
Every 60 seconds each Sentry phones home a heartbeat carrying a runtime block: service states, its crontab, its sudo grants, its config with secrets redacted to <set>. The cloud always knows what each box actually is — no one has to log in to find out.
Two views of the same comparison: python3 fleet/check_drift.py in the repo (exit non-zero on any difference; --via cloud needs no SSH at all), and the Desired State panel on every device page here — one row per difference, worst first, an Apply button when a command can fix it, and an honest reason when one cannot (no sudo grant yet, a credential that must be set locally, a unit file only a deploy can remove).
Nothing with authority over a real door runs before it has passed python3 fleet/sim/acceptance.py. The rig stands up a complete fake Roll Call world on a laptop: a throwaway database, the real backend, and the real agent code — with fake systemctl / sudo / crontab swapped in so it manages pretend services, never the machine it runs on. It registers as a device called sim-door, deliberately breaks itself, and proves seven things — ending with: every break detected, every fix applied and acknowledged, and a sabotaged fix reporting error, never ok.
A second tier boots a real ARM Linux VM under QEMU for full systemd realism, on demand.
SSH never configures
Logging in is for diagnosis. Every change travels the command queue, where it is recorded, acknowledged, and visible here.
Acks are honest
An agent that fails RAISES, so the console shows an error — never “Executed” for work that did not happen.
Unreachable is never clean
A device that could not be read fails the drift check. Silence is not health.
Secrets are named, never valued
Declarations say a credential must exist, never what it is. Heartbeats redact values before they leave the Pi.
Source of truth: docs/modules/device-desired-state/MODULE.md· contract C21 · this page is a reader's digest — when they disagree, the module doc wins.