Skip to content

Add operator-marked trusted scanners (#64) - #77

Merged
mattmacrocket merged 4 commits into
mainfrom
feature/trusted-scanners
Oct 18, 2026
Merged

mattmacrocket merged 4 commits into
mainfrom
feature/trusted-scanners

Conversation

@mattmacrocket

Copy link
Copy Markdown
Collaborator

Closes #64.

What

A per-device trusted scanner flag, set from the device detail view. Decoy trips from a trusted scanner are kept as forensic evidence and still count toward the decoy's connection total, but they neither create nor feed Decoy Trip alerts. Credential trips stay Critical regardless of the flag. The flag is independent of trust status.

Sensor

  • Schema v13: devices.trusted_scanner INTEGER NOT NULL DEFAULT 0, idempotent _apply_v13 for existing databases.
  • GET /devices, GET /devices/{id} return trusted_scanner; PUT /devices/{id} accepts it. Device WebSocket payloads carry it.
  • DecoyAlertHandler._is_trusted_scanner reads the flag at event time (not cached), so toggling in the app takes effect on the next connection in either direction. The branch sits after the discovery-probe check and before the credential branch, so credential use never reaches it.

App

  • DeviceSummary / DeviceDetail decode trusted_scanner as Bool? so a pre-v13 sensor still decodes; isTrustedScanner is the read surface.
  • DeviceUpdateRequest.trustedScanner (trusted_scanner), nil leaves the sensor value unchanged.
  • Device detail: Mark as Trusted Scanner / Unmark Trusted Scanner action plus a header badge. All four DeviceSummary reconstructions (presence flips in WSEventProcessor and AppState, save edits, trust changes) carry the flag so none of them clears it.

Deception integrity

Control surface only. Nothing under decoys/ or scouts/ changes; the decoy's response to a trusted device is byte-identical to its response to anyone else, so a compromised trusted device cannot detect that it is trusted.

Tests

Red first, then green:

  • TestMigrationV13 (default false on fresh DB; applies to a v12 DB and is idempotent)
  • TestTrustedScanner in test_routes_devices.py (list/detail expose it, PUT sets and clears it)
  • TestTrustedScanner in test_decoy_alert_handler.py (trip is evidence without an alert and counters still increment; credential use is still Critical; marking a source trusted stops feeding its open alert; untrusted device still alerts)
  • Device manager payload carries the flag
  • Swift: DeviceSummary decodes with and without the key; updateDevice encodes only trusted_scanner when that is all that changed

test_schema_v12_adds_campaign_table pinned SCHEMA_VERSION == 12; it now asserts the v12 row exists and the version is at least 12.

Full runs: sensor pytest 2539 passed, 6 skipped; ruff check clean; swift test 160 passed across both targets.

Docs

docs/USER_GUIDE.md: new action under Device Detail View, and the Decoy Trip row notes trusted-scanner activity is retained without an alert.

Operator tests and legitimate LAN scanners trip decoys and produce High
alerts identical to an intrusion, which trains people to stop reading
alerts. This adds a per-device trusted_scanner flag the operator sets in
the device detail view. Decoy trips from a trusted scanner are still
recorded in the forensic log and still count toward the decoy's
connection total, but they neither create nor feed Decoy Trip alerts.
Credential trips stay Critical regardless of the flag.

Sensor:
- Schema v13 adds devices.trusted_scanner (INTEGER NOT NULL DEFAULT 0),
  with an idempotent migration for existing databases.
- /devices and /devices/{id} return trusted_scanner; PUT /devices/{id}
  accepts it. Device WebSocket payloads carry it too.
- DecoyAlertHandler reads the flag at event time, so flipping it in the
  app takes effect on the next connection in either direction.

App:
- DeviceSummary/DeviceDetail decode trusted_scanner as an optional so a
  pre-v13 sensor still decodes; isTrustedScanner is the read surface.
- Device detail gains a Mark/Unmark Trusted Scanner action and a header
  badge. Every DeviceSummary reconstruction carries the flag so a
  presence flip or trust change does not clear it.

Deception integrity: control surface only. The decoy's response to a
trusted device is unchanged, so a compromised trusted device cannot
detect that it is trusted.

The v12 campaign test pinned SCHEMA_VERSION == 12; it now asserts the
v12 row exists and the version is at least 12.
@mattmacrocket
mattmacrocket force-pushed the feature/trusted-scanners branch from 57b81b6 to 8fb5f2d Compare October 18, 2026 04:26
chrissyrocket
chrissyrocket previously approved these changes Oct 18, 2026
@mattmacrocket
mattmacrocket merged commit e83cb43 into main Oct 18, 2026
6 checks passed
@mattmacrocket
mattmacrocket deleted the feature/trusted-scanners branch October 20, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Operator-marked trusted scanners file decoy trips as evidence instead of High alerts

2 participants