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:
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user