docs(devices): add randomized-MAC retention/prune to discovery spec

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
root
2026-06-08 20:48:21 +10:00
parent d513ca8fa4
commit b9b94c9777

View File

@@ -50,6 +50,7 @@ the Void's existing services "discovered → promote" pattern).
| Identity | **MAC primary key**; IP a mutable column | Survives DHCP IP changes. |
| Review flow | Mirror services `discovered → promote` | New MAC → `status='new'`; owner names/edits → `status='known'`. |
| Source of truth | **DB** (`lan_devices`); `devices.json` becomes the one-time migration seed, then removed | Single source of truth. |
| Randomized-MAC bloat | **Auto-prune unreviewed + absent rows** (randomized >24h, others >14d); keep `known`/`ignored` forever | Rotated randomized MACs never accumulate; the table stays bounded. |
## Architecture
@@ -97,10 +98,14 @@ Table `lan_devices`:
- `listKnown()` (`status='known'`, grouped by `grp`), `listDiscovered()`
(`status='new'`), `get(mac)`, `update(mac, {name, grp, status, note, flagged})`,
`remove(mac)`. (`ignored` devices show in neither.)
- `prune()` — delete unreviewed + absent rows past their TTL: `status='new' AND
present=false AND ((randomized AND last_seen < now()-'24h') OR (NOT randomized
AND last_seen < now()-'14d'))`. Never touches `known`/`ignored`.
### Cron (`lib/cron/index.js`)
Add hourly (`7 * * * *`): `runScan()``upsertScan``markAbsent`. Wrapped in
try/catch — a scan failure logs and never crashes the cron.
Add hourly (`7 * * * *`): `runScan()` → `upsertScan` → `markAbsent` → `prune()`.
Wrapped in try/catch — a scan failure logs and never crashes the cron, and
`prune()` only runs after a *successful* scan (so a failed scan can't reap rows).
### API `lib/api/routes/devices.js` (mount `/api/devices`, owner-gated)
- `GET /` — known devices grouped for the band.
@@ -117,6 +122,10 @@ try/catch — a scan failure logs and never crashes the cron.
- **Discovered review** — a section/panel listing `/api/devices/discovered`, each
with an **Add / Edit** form (name + group select + notes) that `PATCH`es to
promote; plus inline edit for known devices and an Ignore/Delete action.
- **Randomized devices** get a small "randomized MAC" badge (with a tooltip:
naming pins it only until the MAC rotates; disable SSID randomization for
stable tracking). A `known` device that's been `present=false` for ≥30d shows
an "absent Nd" marker for easy manual cleanup (never auto-deleted).
- Remove `public/devices.json` (superseded by the DB).
## Infra setup (one-time, on CT 311)
@@ -149,8 +158,9 @@ error and the feature degrades to "no new discoveries" (existing data still show
## Out of scope (YAGNI)
- Service/port fingerprinting, SNMP/LLDP topology (that's Scanopy's job).
- Multi-subnet/VLAN scanning (single `/24`).
- Auto-pruning stale `new` devices (revisit only if the queue gets noisy).
- Push notifications on new-device discovery.
- Stable identity for randomized-MAC devices across rotations (not solvable from
L2 alone; the user-side fix is disabling MAC randomization for the SSID).
## References
- Scanopy — github.com/scanopy/scanopy ; scanopy.net (self-hosted discovery/topology, AGPL-3.0).