feat(ops): device-audit script + canonical devices.yaml registry (#15) #16
No reviewers
Labels
No labels
agent:felinus
agent:human
agent:maximus
priority:p0
priority:p1
priority:p2
priority:p3
status:blocked
status:needs-review
status:wip
type:chore
type:docs
type:feat
type:fix
type:perf
type:refactor
type:test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jmz/matrix-bridge!16
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/15-device-audit"
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?
Summary
Closes #15. Adds
devices.yaml(canonical bridge fleet) +scripts/audit-devices.py(diff against Synapse's per-user device list) + scheduled Forgejo workflow + tests + runbook update.Closes a recurrence vector of #5: tonight's diagnostic dance for the
mba-726dadit"ghost device" only proved the device was legitimate after manually finding its curve25519 in our local crypto store — pure luck. With this in place, the same investigation reduces to looking at a diff.What's new
devices.yaml— canonical bridge-fleet registry, 4 Maximus/Felinus bridges pre-populated. Schema documented inline in the file.scripts/audit-devices.py— stdlib-only (PyYAML is the sole third-party dep) script that diffs registry vs. Synapse and reports three classes of mismatch:last_seen>idle_warn_days(default 30)scripts/test_audit_devices.py— 16 stdlibunittesttests, no test-framework dep. Covers cross-signing-key filter, pure-logicaudit()for each mismatch class + mixed state, YAML parsing + validation, and report-formatting sanity..forgejo/workflows/audit-devices.yml— weekly cron (Monday 06:00 UTC) + manualworkflow_dispatch. Requires repo secretSYNAPSE_ADMIN_TOKEN.docs/bridge-client-setup.md— new step 8 in the rotation procedure ("updatedevices.yamlin the same commit") + new "Auditing the device fleet" section.Design choices
audit()function is pure (no I/O);query_synapse_devices()is the only external interaction, called frommain(). Tests exercise the pure parts; the HTTP path is left to manual CLI verification because mockingurllibfor one endpoint is more ceremony than the call warrants./devicesresponses depending on the homeserver. The filter looks for ids with/AND matching^[A-Za-z0-9+/]{43}$(the observed shape on@jmzand@kittytonight). Real bridge ids (mba-…,nas-…,rpi5-…, plus pre-host-prefix 10-char ids likeG9MCQri1N2) pass through.never-seen≠idle: a device withlast_seen_ts is None(registered but never connected) doesn't trigger the idle alert — it's a distinct state. If the device fails to materialize fully, the NEXT audit catches it via the missing-from-Synapse path.Known blockers (not fixed by this PR)
nas:/root/handoff-headscale-acl-fix.mdto fix the ACL. Once the runner is back, this workflow picks up on the next Monday 06:00 UTC.SYNAPSE_ADMIN_TOKENrepo secret needs to be set in Settings → Secrets before the workflow can succeed. Token source:msc3861.admin_tokenin/opt/docker/matrix/files/homeserver.yamlon the NAS.Test plan
python3 -m unittest scripts.test_audit_devices -v→ 16/16ast.parse)🤖 Generated with Claude Code
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.