1711 Commits

Author SHA1 Message Date
James Smith a5a91fff69 chore: bump version to 2.29.0
Cover TSCM sweep metadata/cleared-devices/ignore-list/report category
filter features and the ADS-B Postgres password fix. Updates the
in-app dashboard changelog (config.py), CHANGELOG.md, and the GitHub
Pages TSCM feature description.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
v2.29.0
2026-07-05 15:01:12 +01:00
James Smith 9c3eb62499 fix: correct ADS-B Postgres password env var mismatch and docs
setup.sh wrote/read the local Postgres wizard password under
INTERCEPT_ADSB_DB_PASS, but config.py and docker-compose.yml expect
INTERCEPT_ADSB_DB_PASSWORD — any custom password set via the wizard
was silently ignored. Also make docker-compose actually honor
INTERCEPT_ADSB_DB_PASSWORD instead of hardcoding "intercept" for both
the app and Postgres containers, and correct a misleading .env.example
comment about admin password auto-generation.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-05 14:57:36 +01:00
James Smith 96172ca593 style: apply ruff-format to entire codebase
First-time run of ruff-format via pre-commit hook normalises quote
style, trailing commas, and whitespace across 188 Python files.
No logic changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 14:48:11 +01:00
James Smith 82e64104fe fix: resolve ruff import ordering and unused import errors
Fixes 4 linting errors that were failing CI:
- Remove unused `shutil` import from bin/import_artemis.py
- Sort/format import blocks in routes/signalid.py and
  tests/test_signalid_match_route.py

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 14:44:56 +01:00
James Smith 065b4778a9 feat: TSCM sweep metadata, cleared devices, and examiner ignore list
Four new features requested by TSCM users:

- Site/Location and Examiner name fields appear at the top of the
  sweep config; both are embedded in HTML and PDF/annex reports.
- Mark Cleared button on every live device item dims the entry with a
  CLEARED badge and excludes it from generated reports. Cleared state
  resets at the start of each new sweep. The report executive summary
  shows a count of cleared devices.
- Ignore List stores the examiner's own devices persistently in
  localStorage. Ignored devices are filtered from the live display and
  all report exports. An Ignore button appears on every device item;
  the sidebar Examiner Ignore List section shows current entries with
  per-item removal and a clear-all button.
- Site/examiner params forwarded to PDF and annex server routes so
  the text report header includes them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 14:37:08 +01:00
James Smith 5d87656909 chore: exclude design docs and purge sensitive history
Remove docs/plans/, docs/specs/, and docs/design/ from tracking and
add them to .gitignore. History also purged of instance/intercept.db
(user auth DB accidentally committed in January).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 14:25:04 +01:00
James Smith 8b2879c71f feat: add category filter to TSCM report exports
Users can now choose which risk categories to include in generated
reports — High Interest, Needs Review, and Informational — via three
checkboxes that appear after a sweep completes. Applies to the HTML
report, PDF, JSON annex, and CSV annex. Defaults to High Interest +
Needs Review (Informational excluded) to keep reports concise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 13:34:09 +01:00
James Smith 1c9bd34a28 chore: release v2.28.0
Bump version to 2.28.0, update changelog, and add Signal ID to the
GitHub Pages feature listing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:48:54 +01:00
James Smith b192dd704c feat: expand signal database to 594 signals from Artemis-DB
Imports 574 signals from AresValley/Artemis-DB (v73) into data/signals.json,
growing the bundled offline database from 20 to 594 signals. Adds
bin/import_artemis.py to refresh the database when Artemis-DB releases updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:45:58 +01:00
James Smith 1483682172 fix: load SignalIdModal on dashboard pages; clear status on zero matches
- Added signal-id-modal.js script to base_dashboard.html (nav button was silent on dashboard pages)
- Added else branch to clear "Searching…" status when zero matches returned

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 09:08:34 +01:00
James Smith c6977eedde feat: wire SignalIdModal to waterfall and global nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:56:26 +01:00
James Smith ea7e3941d4 feat: add SignalIdModal IIFE component with scored results
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:49:55 +01:00
James Smith a336da80fb fix: return 503 (not 502) when signal DB match fails 2026-07-03 08:32:49 +01:00
James Smith 29c3f9bdaf feat: add POST /signalid/match route with scoring and caching 2026-07-03 08:29:21 +01:00
James Smith e2d8504beb fix: remove unused pytest import in test_signalid_match
Removed unused `import pytest` from line 5. The file uses no pytest
fixtures, marks, or raises, making this import dead code and causing
an F401 lint violation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:21:50 +01:00
James Smith 9f4895a80b feat: add signal_db loader and match_signals scoring function
Implements lazy-cached load_signals() and pure match_signals() with
frequency/bandwidth/modulation/region scoring for the signal ID feature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:10:47 +01:00
James Smith d1f768e23f feat: add signal database seed and schema validation test
Create data/signals.json with 20 seed signals (FM broadcast, airband,
ISM bands, maritime VHF, AIS, ACARS, ADS-B, POCSAG, cellular, WiFi/BT,
amateur radio, DAB, PMR446, FRS/GMRS, NOAA weather radio). Point
frequencies adjusted to ±500 Hz windows; fixed-value bandwidth_ranges
widened to strict min < max windows required by schema.

Add tests/test_signals_json.py with 9 schema validation tests covering
id uniqueness, required string fields, frequency range validity,
bandwidth range, modulation casing, categories, region codes, and
sigidwiki URLs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 11:48:57 +01:00
James Smith a75ad9f3e4 docs: refactor documentation to remove duplication and improve clarity
- README: remove CW/Morse notes, condense multi-arch Docker detail, fix screenshot path, tighten credentials note
- FEATURES.md: replace 550-line bullet dump with a concise mode→link table
- USAGE.md: replace 140-line Webhooks section with pointer to new WEBHOOKS.md; remove duplicate Configuration and CLI Options sections
- docs/WEBHOOKS.md: new file with full webhook setup, payload format, and Discord relay guide
- HARDWARE.md: remove duplicate Quick Install / Python Environment / Running INTERCEPT sections; add Icecast setup section
- TROUBLESHOOTING.md: replace Icecast install/config block with pointer to HARDWARE.md; replace duplicate udev rules with pointer to HARDWARE.md
- SECURITY.md: update auth section to reflect admin/admin login (was "no authentication mechanism")
- UI_GUIDE.md: add contributor/developer notice at the top

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 14:43:34 +01:00
James Smith 2f2d0dac9b fix: meshcore serial connection and battery calculation issues
- Fix _pollUntilConnected overwriting real error with generic timeout
  message — stop polling once backend reaches error state
- Fix battery % calculation: was battery_mv/42 (71% at empty); now
  (battery_mv-3000)/12 for a proper 0-100% LiPo curve
- Improve auto-detect: scan available ports rather than blindly using
  /dev/ttyUSB0; update label to show fallback so users know what to expect
- Add port refresh button (↻) — previously required switching modes
  and back if device was plugged in after panel opened
- Add baud rate selector to serial config strip (default 115200,
  options up to 921600) and wire it through to the connect request

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 14:22:10 +01:00
James Smith 7e50df25c9 fix: restore lightbox fixed positioning on GitHub Pages site
The body > *:not(#bg-canvas) rule carried ID-level specificity (1,0,1)
which overrode .lightbox's position:fixed and z-index:1000, leaving the
overlay stuck in document flow and invisible. Excluding #lightbox from
that rule lets the lightbox CSS take effect correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 14:06:22 +01:00
James Smith 7b81362b11 fix: restore lightbox popout for screenshot images
Reverts the <a target="_blank"> wrappers added previously — those were
opening images in a new tab and interfering with the existing lightbox.
Images now click-to-expand via the overlay lightbox as intended.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 13:58:51 +01:00
James Smith 5c5dd998ef fix: make screenshot images clickable on GitHub Pages site
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 13:56:20 +01:00
James Smith 5c49643a0a fix: skip vcgencmd throttle probe when binary is absent
The system metrics collector daemon thread ran vcgencmd via subprocess
every 3s even on non-Pi hosts, where it always failed — and leaked
Popen calls into any later test mocking subprocess (intermittent
test_weather_sat_decoder failure in full-suite runs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:43:34 +01:00
James Smith 751639b8d8 fix: tracker signature scoring — gate boost/length signals, name-only detects LOW
confidence_boost and the manufacturer-data-length signal applied without
any identifying indicator match, giving every device a phantom AirTag
baseline (a 22+ byte payload from any vendor scored 0.30 and was flagged
as an AirTag). Both now require a matched indicator, mirroring the
score>0 gating already used in _check_generic_tracker_indicators.

Name-pattern weight raised 0.15 -> 0.30 so a device advertising a known
tracker name yields a LOW-confidence detection, consistent with the
TSCM BLE scanner's name-only detection and the engine docstring.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 18:43:20 +01:00
James Smith 799278e58d test: repair stale assertions in bluetooth group and deauth detector
Bluetooth aggregator/api/heuristics tests updated to current behavior;
deauth detector integration test rewritten to exercise the tracker and
alert path directly instead of patching __globals__ (read-only on
Python 3.14).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 15:44:59 +01:00
James Smith 60480ccf37 test: repair stale assertions in validation/waterfall/meshtastic/routes
Auth fixture, /listening->/receiver waterfall rename, numeric validator
returns, and float timestamp — all matching current code behaviour.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 14:56:02 +01:00
James Smith 73e05ed31b fix: guard capabilities import in agent for stripped-host degradation
Matches the agent's established try/except import convention; the
agent now starts and reports empty capabilities when utils.capabilities
(or its dependency chain) is unavailable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 11:39:39 +01:00
James Smith ed496b006c fix: align pyproject meshcore pin with requirements.txt (>=2.3.0)
Caught by test_dependency_files_integrity, which had been buried in the
never-reached tail of the test suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 09:30:19 +01:00
James Smith 618f82a1c1 docs: record UI direction — dashboards for map-heavy modes
Phase 5 decision gate of the architecture refactor plan: dedicated
dashboard pages are the pattern for map-centric modes; APRS and
Meshtastic migrations to follow under separate plans.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:46:37 +01:00
James Smith ccb79408db refactor: single dependency probe in capability detection; real test coverage
detect_mode_availability accepts a pre-computed dep_status so the agent
probes once; interface and fallback paths now have content-level tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:37:30 +01:00
James Smith ac7171fed7 refactor: extract shared capability detection from agent
utils/capabilities.py now owns interface detection and mode
availability; the agent delegates via detect_interfaces() and
detect_mode_availability(). The agent keeps config gating and
tool_details population to preserve its result shape exactly.

The moved fallback path uses utils.dependencies.check_tool instead of
the agent's old shutil.which fallback; check_tool also searches
Homebrew paths, a strict superset (strictly better detection).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:31:54 +01:00
James Smith ec59ef0e42 test: mode registry consistency checks; fail fast if registry missing
Also documents the registry-driven mode integration in CLAUDE.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:11:04 +01:00
James Smith 71f44c0f40 refactor: registry-driven mode init dispatch in switchMode
A failing mode init now logs instead of aborting the remainder of
switchMode (deliberate hardening; previously an exception skipped
title/visuals updates).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 08:03:40 +01:00
James Smith 1348d16705 refactor: derive sidebar toggles and destroy map from registry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:46:40 +01:00
James Smith fc494a763e refactor: derive modeCatalog and modesWithVisuals from registry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:29:37 +01:00
James Smith 844a1698af feat: introduce frontend mode registry (no behaviour change)
window.INTERCEPT_MODES mirrors the existing modeCatalog, sidebar
toggles, visuals list, destroy map, and switchMode init branches.
Derivations follow in subsequent commits; a temporary console guard
verifies registry/catalog parity at runtime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:16:40 +01:00
James Smith 5fdf2a4fc6 fix: reject non-canonical subpaths in agent proxy allowlist
requests/urllib3 collapse dot segments before sending, so traversal
like wifi/v2/../../x escaped the prefix allowlist. Only canonical
paths are now forwarded; regression tests included.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:49:19 +01:00
James Smith 1c94fcdce9 refactor: route agent wifi clients through generic proxy
Removes the one-off proxy_wifi_clients route and the dead getApiBase()
helper; the allowlisted passthrough now covers agent wifi traffic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:43:16 +01:00
James Smith 36e3d7a36e feat: allowlisted generic agent proxy route
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:41:01 +01:00
James Smith 8b13ec85ac refactor: agent satellite predictor reads TLEs from unified store
Removes the agent's own CelesTrak download (the source of the stray
gp.php artifact) — the store is now the single TLE source for app and
agent alike.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:31:00 +01:00
James Smith 995a039ff5 test: isolate the TLE store suite-wide
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:29:03 +01:00
James Smith 715c24735d fix: point doppler and ground-station scheduler at unified TLE store
Both silently fell back to static bundled TLEs after the removal of
routes.satellite._tle_cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:25:29 +01:00
James Smith c8f2bc5a88 refactor: weather sat prediction reads TLEs from unified store
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:23:20 +01:00
James Smith 1a60c52fca refactor: hoist TLE reads and batch write-backs in satellite request paths
_resolve_satellite_request now operates on a caller-provided dict and
accumulates write-backs, flushed once per request behind a guard —
avoids per-satellite full-dict copies and store-cache thrash, and a
transient DB error can no longer fail a read request.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:20:01 +01:00
James Smith 3074318600 refactor: satellite routes read/write TLEs via unified store
data/satellites.py is no longer rewritten at runtime; it remains as
the read-only seed for the store.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:12:23 +01:00
James Smith 1cde06ffc7 fix: harden TLE store for cross-process use
- busy_timeout so concurrent app+agent writers wait instead of raising
- seed from _connect() so update-before-first-read can't drop the seed
- regression tests: seed ordering, concurrent writer, default DB path

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 17:07:30 +01:00
James Smith 67a543cd28 feat: add unified SQLite-backed TLE store
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:58:09 +01:00
James Smith d85ea1acb2 test: use shared fake_process fixture in agent mode tests
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:50:20 +01:00
James Smith 0f498de69d test: address review feedback on fake_process fixture
- document str defaults / bytes for binary-mode callers
- wire __exit__ to False so exceptions are not suppressed
- exercise exited-process path through subprocess.run

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:48:13 +01:00
James Smith 9d684578af test: add shared fake_process fixture for complete Popen mocking
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 16:44:04 +01:00