mirror of
https://github.com/CyberMind-FR/secubox-deb.git
synced 2026-07-29 09:14:33 +00:00
* docs(plan): #340 secubox-sentinelle-gsm v0.2 standalone webui + local alerts (ref #340) * feat(sentinelle-gsm): alert_sink — SQLite history + SSE broadcast hub (ref #340) Introduces lib/sentinelle_gsm/alert_sink.py: a SQLite-backed alert history with an in-memory asyncio pub/sub hub that fans new alerts out to live Server-Sent Events subscribers. The Alert dataclass carries only privacy-safe fields — `subscriber_hash` is HMAC-truncated (Anonymizer), never plaintext. AlertSink.write() enforces this with a load-bearing privacy guard: any string field matching `\b\d{15}\b` (plaintext IMSI shape) triggers ValueError and the row is refused. SQLite is opened with check_same_thread=False so the FastAPI app can read/write from multiple coroutines safely. Adds api/tests/test_alert_sink.py with 5 tests covering write/list roundtrip, the plaintext-IMSI privacy guard, HMAC acceptance, live subscriber fan-out, and SSE chunk format. 5 passed locally. * feat(sentinelle-gsm): trusted phones registry — HMAC-hashed IMSI + label (ref #340) Privacy contract: - Plaintext IMSI is accepted by add() ONCE, immediately HMAC-hashed via the existing sentinelle_gsm.observer.Anonymizer.anonymize() helper. - The plaintext never persisted, never logged, never returned by any method. After add() returns, plaintext_imsi is out of scope. - The on-disk store contains only {id, imsi_hash, label, added_at}. Storage format: JSON via the stdlib `json` module instead of TOML. `python3-tomli-w` (the only writer for the new tomllib reader) is not in Debian bookworm — it first ships in trixie. python3-toml (legacy) writes TOML but is deprecated. JSON is stdlib, atomically renderable, and human-grep-able, which is what a trusted-phones registry needs. Anonymizer integration: uses .anonymize() (HMAC-SHA256, 16 hex chars truncated). The plan referenced .hash_subscriber_id() — that method does not exist on Anonymizer in observer.py; .anonymize() is the canonical hashing entry point. Tests: 6/6 passing - test_add_hashes_and_does_not_store_plaintext (privacy invariant enforced: plaintext IMSI never appears on disk) - test_lookup_by_hash_finds_added_phone - test_lookup_by_hash_returns_none_for_unknown - test_delete_removes_entry - test_invalid_imsi_rejected - test_persistence_across_instances * feat(sentinelle-gsm): API — /alerts (history + SSE + test) + /trusted CRUD (ref #340) Adds 6 endpoints under the existing /api/v1/sensor/gsm/ prefix (nginx-added; mounted at root of the FastAPI app): GET /alerts — paginated SQLite-backed history (query: ?limit=100&since=<epoch>) GET /alerts/stream — SSE live feed; Cache-Control: no-cache, X-Accel-Buffering: no, Connection: keep-alive so nginx and HTTP caches don't buffer it POST /alerts/test — operator manual trigger; ValueError from the AlertSink privacy guard (plaintext-IMSI shape) surfaces as HTTP 500 GET /trusted — list trusted phones (HMAC + label, no plaintext) POST /trusted — body {imsi, label}; ValueError → 400 DELETE /trusted/{id} — unknown id → 404 Wiring: * AlertSink + TrustedRegistry are module-level singletons initialised on FastAPI startup so tests can override via monkeypatch. * `require_jwt` is a no-op dependency stub — real JWT enforcement is done by nginx + Authelia in front of the Unix socket. The stub exists so test code (and future host-direct callers) can swap auth via `app.dependency_overrides[require_jwt]`. * Anonymizer is loaded via a new `_get_anonymizer()` helper that reads /etc/secubox/secrets/sentinelle-gsm-hmac when present and falls back to an ephemeral key otherwise. * trusted.json path is /etc/secubox/sentinelle-gsm/trusted.json (the Task-2 deviation from the plan's TOML; bookworm lacks python3-tomli-w). * version bumped 0.1.0 → 0.2.0 in the FastAPI metadata only; the debian/changelog bump lands in Task 6. Tests (7 new in api/tests/): * test_alerts_api.py — POST /alerts/test happy path, GET history roundtrip, plaintext-IMSI guard → 500, SSE route registration (via app.routes + /openapi.json, not by opening the stream — the async generator awaits forever on q.get(), incompatible with sync TestClient iteration; SSE chunk format is covered by test_alert_sink.py::test_stream_emits_sse_format). * test_trusted_api.py — add/list/delete roundtrip with hash-not- plaintext invariant, invalid IMSI → 400, unknown id → 404. Run: pytest api/tests/test_alerts_api.py api/tests/test_trusted_api.py Result: 7 passed. * feat(sentinelle-gsm): standalone webui — live alerts + browser Notification API (ref #340) Adds the Task 4 standalone WebUI for sentinelle-gsm at packages/secubox-sentinelle-gsm/www/sentinelle/: - index.html — canonical SecuBox scaffold (body flex, aside.sidebar 220px fixed with section anchors, main reserves the global menu bar with padding-top: calc(48px + 1.5rem)). Four panels: status strip, alerts table (aria-live=polite), trusted phones table, actions. - sentinelle.css — MIND palette (--mind-violet: #3D35A0) per Charte SecuBox, Space Grotesk titles + JetBrains Mono data/code, modal with z-index 1500 (above the global-menu-bar z-index 998), toast banner, score chip colour grading (low/med/high), responsive breakpoints. - sentinelle.js — vanilla single-IIFE module, no framework, no CDN. EventSource consumer of /api/v1/sensor/gsm/alerts/stream (auto-reconnect surface), CRUD wrappers for /alerts /alerts/test /trusted /trusted/{id}, Browser Notification API (requested from a user-gesture handler), beep synthesised on-the-fly via Web Audio API (no asset), localStorage mute toggle, modal-based add flow, ESC/backdrop close, accessible aria-live region for the alerts list. All API calls hit root-relative /api/v1/sensor/gsm/* — Task 5 will mount the nginx route. Local smoke test booted uvicorn against the API and verified the HTML/CSS/JS serve and all four CRUD/test routes respond as the UI expects. * feat(sentinelle-gsm): nginx route /sentinelle/ + MIND menu entry + .install (ref #340) * nginx/sentinelle-webui.conf: alias for /sentinelle/ (static webui) + SSE-tuned override for /api/v1/sensor/gsm/alerts/stream. Uses `^~` literal-prefix match so it wins precedence over the shorter /api/v1/sensor/gsm/ prefix in sentinelle-gsm.conf and against any future regex locations in the same server scope. Re-sets proxy_read_timeout / proxy_send_timeout to 24h after the common secubox-proxy include (which forces 30s) so long-lived SSE connections survive. * menu.d/45-sentinelle.json: MIND-category entry (icon: satellite, order: 45). Category emitted as lowercase `mind` to match the canonical schema used by every other package menu.d entry. * debian/secubox-sentinelle-gsm.install: ship the new files. The package uses a hand-rolled override_dh_auto_install in debian/rules, so the install file is documentation; debian/rules is extended with explicit cp steps for nginx/sentinelle-webui.conf and www/sentinelle/. menu.d already had a wildcard copy. * chore(sentinelle-gsm): bump 0.2.0 + extend privacy invariant tests (closes #340) - Append 3 new privacy invariant tests: * Alert dataclass has no plaintext IMSI/IMEI/TMSI/MSISDN/ICCID fields * TrustedPhone dataclass only stores imsi_hash (never plaintext) * AlertSink.write() raises ValueError on any 15-digit token in a textual field — non-regression guard for the OPAD-doctrine privacy invariant. - Bump debian/changelog to 0.2.0-1~bookworm1 with the full Task 1-6 feature summary: alert_sink, trusted registry, REST routes, WebUI, nginx + Hub menu integration. Notes the JSON-over-TOML deviation (python3-tomli-w not in bookworm). - 29/29 tests pass: 5 alert_sink + 4 alerts_api + 3 trusted_api + 6 trusted_registry + 11 privacy_invariant (8 prior + 3 new). --------- Co-authored-by: CyberMind-FR <gandalf@Gk2.net> |
||
|---|---|---|
| .. | ||
| secubox-ad-guard | ||
| secubox-admin | ||
| secubox-ai-gateway | ||
| secubox-ai-insights | ||
| secubox-auth | ||
| secubox-authelia | ||
| secubox-avatar | ||
| secubox-backup | ||
| secubox-c3box | ||
| secubox-cdn | ||
| secubox-certs | ||
| secubox-cloner | ||
| secubox-config-advisor | ||
| secubox-console | ||
| secubox-cookies | ||
| secubox-core | ||
| secubox-crowdsec | ||
| secubox-cve-triage | ||
| secubox-cyberfeed | ||
| secubox-daemon/debian | ||
| secubox-defaults | ||
| secubox-device-intel | ||
| secubox-dns | ||
| secubox-dns-guard | ||
| secubox-dns-provider | ||
| secubox-domoticz | ||
| secubox-dpi | ||
| secubox-droplet | ||
| secubox-exposure | ||
| secubox-eye-remote | ||
| secubox-eye-square | ||
| secubox-full/debian | ||
| secubox-gitea | ||
| secubox-glances | ||
| secubox-gotosocial | ||
| secubox-grafana | ||
| secubox-haproxy | ||
| secubox-hardening | ||
| secubox-health-doctor | ||
| secubox-hexo | ||
| secubox-homeassistant | ||
| secubox-hub | ||
| secubox-identity | ||
| secubox-interceptor | ||
| secubox-iot-guard | ||
| secubox-ipblock | ||
| secubox-jabber | ||
| secubox-jellyfin | ||
| secubox-jitsi | ||
| secubox-ksm | ||
| secubox-led-heartbeat | ||
| secubox-lite/debian | ||
| secubox-localai | ||
| secubox-localrecall | ||
| secubox-lyrion | ||
| secubox-mac-guard | ||
| secubox-magicmirror | ||
| secubox-mail | ||
| secubox-mail-lxc | ||
| secubox-master-link | ||
| secubox-matrix | ||
| secubox-mcp-server | ||
| secubox-mediaflow | ||
| secubox-mesh | ||
| secubox-meshname | ||
| secubox-metablogizer | ||
| secubox-metabolizer | ||
| secubox-metacatalog | ||
| secubox-metoblizer | ||
| secubox-metrics | ||
| secubox-mirror | ||
| secubox-mitmproxy | ||
| secubox-mmpm | ||
| secubox-modem | ||
| secubox-mqtt | ||
| secubox-nac | ||
| secubox-ndpid | ||
| secubox-netdata | ||
| secubox-netdiag | ||
| secubox-netifyd | ||
| secubox-netmodes | ||
| secubox-nettweak | ||
| secubox-network-anomaly | ||
| secubox-newsbin | ||
| secubox-nextcloud | ||
| secubox-ollama | ||
| secubox-openclaw | ||
| secubox-ossec | ||
| secubox-p2p | ||
| secubox-peertube | ||
| secubox-photoprism | ||
| secubox-picobrew | ||
| secubox-portal | ||
| secubox-publish | ||
| secubox-qos | ||
| secubox-rbs-sensor | ||
| secubox-redroid | ||
| secubox-repo | ||
| secubox-reporter | ||
| secubox-rezapp | ||
| secubox-roadmap | ||
| secubox-routes | ||
| secubox-rtty | ||
| secubox-rustdesk | ||
| secubox-saas-relay | ||
| secubox-sentinelle-gsm | ||
| secubox-simplex | ||
| secubox-smart-strip | ||
| secubox-smtp-relay | ||
| secubox-soc | ||
| secubox-soc-agent | ||
| secubox-soc-gateway | ||
| secubox-soc-web | ||
| secubox-streamforge | ||
| secubox-streamlit | ||
| secubox-system | ||
| secubox-system-hub | ||
| secubox-threat-analyst | ||
| secubox-threats | ||
| secubox-tor | ||
| secubox-torrent | ||
| secubox-traffic | ||
| secubox-turn | ||
| secubox-ui-manager | ||
| secubox-users | ||
| secubox-vault | ||
| secubox-vhost | ||
| secubox-vm | ||
| secubox-voip | ||
| secubox-vortex-dns | ||
| secubox-vortex-firewall | ||
| secubox-waf | ||
| secubox-watchdog | ||
| secubox-wazuh | ||
| secubox-webmail | ||
| secubox-webmail-lxc | ||
| secubox-webradio | ||
| secubox-wireguard | ||
| secubox-yacy | ||
| secubox-zigbee | ||
| secubox-zkp | ||
| zkp-hamiltonian | ||