# WIP — Work In Progress *Mis à jour : 2026-07-21* --- ## ✅ 2026-07-21 : Scale-to-zero services publics (#896) + UX de réveil 2-phases (branche feat/scale-to-zero-public-services → master) Services on-demand : **sommeil si inactif, réveil à l'accès**, politique lifecycle par module, splash "terminal virtuel". Intègre aussi #893 (robustesse actionneur profils). - **Fait** : lifecycle/wake_class (manifeste + setter panel webui→ctl), actionneur état-observé, **mémoire durable des routes portail** (réveil restaure la route WAF — round-trip prouvé live sur yacy), waker (phase 1) + sleeper (idle), déclencheur sbxwaf-side, **splash phase-2 nginx** (`error_page` sur backend qui boote) généralisé à tous les vhosts on-demand via `nginx-sync` (5 câblés live). Fix infra : worker@ WAF crash-loop re-chownait `/run/secubox` → désactivés. - **Merge + release** : branche mergée sur master, issues #896/#893 fermées, bump + artefacts CI, sync debs → gk2, image rpi400. ### ⬜ Next / follow-ups - **WAF-drift reconcile** : perms cookie-audit (workers crashent) + retirer `RuntimeDirectory=secubox` du unit WAF ; **décision cutover** (fan-out worker@ hardened vs formaliser l'unité intérimaire). Board workers désactivés. - **Ré-activer secubox-sleeper** sur un service on-demand opt-in + observer un cycle idle→sleep→wake réel. - Backport du câblage phase-2 par-vhost dans l'outillage vhost ; #895 (DNS via vortex). --- ## ✅ 2026-07-19 : Profils Phase 2 — `Requires=secubox-core` → `Wants=` (branche feat/profiles-phase2-core-wants) Retrait de la cascade dure sur `secubox-core.service` (Type=oneshot mkdir+chown, RemainAfterExit) : un `Requires=` sur ~108 units les cascade-stoppait tous si core redémarre/échoue (ex. upgrade du paquet secubox-core) = thundering-herd. `After=` garde l'ordre, `Wants=` garde la dépendance souple **sans** la cascade. Prérequis de l'apply de masse natif (Phase 3). - **Source** : 91 units (`packages/*/{debian,systemd}/*.service`) + 2 scaffolds (`new-module.sh`/`new-package.sh`) convertis → les futurs modules naissent en `Wants=`. Chaque ligne `Requires=` était core-only ⇒ sed 1-ligne sûr. - **Live (Option A, sans herd)** : 162 units installés sed en place + `systemctl daemon-reload` — **aucun restart**. Board saine (admin/billets 200). Cascade retirée immédiatement. - **Release** : bump minor sur les 87 paquets affectés → CI build + publish apt.secubox.in. ### ⬜ Next - **Phase 3 native mass-apply** désormais débloqué (le cascade-stop ne peut plus entraîner d'autres units). - **Réconciliation boot** (`secubox-profile-apply.service`, décidée enforce/auto-apply). - **Surfaces API/panel/Companion profiles** + sudoers scopé (guideline webui→ctl). --- ## ✅ 2026-07-17 : Sessions auditables + Companion auth/system/metrics + billets hashtags emoji (branche feat/sessions-companion-emoji) Sessions traçables, les 2 modules Companion stubs deviennent réels, billets gagne les vues rapides par hashtag emoji. Live-vérifié gk2. Détail dans HISTORY.md. - **Sessions (root-cause)** 🔑 — `/login/mfa` + `/totp/confirm` codaient en dur `"ip": ""` (et pas d'UA) ; seul le chemin mot-de-passe les captait. **admin est forcé TOTP ⇒ tout login admin réel passait par MFA** → lignes de session non auditables, onglet Sessions de la webui users (déjà complet) affichait du vide. Fix `_client_meta(request)` (X-Forwarded-For d'abord : nginx/HAProxy sont devant, `request.client.host` = le proxy). Prouvé en pilotant le vrai handler `/login/mfa` en-process (fichier sessions temporaire) : `ip=192.168.1.77` + UA complet. - **Companion auth + system** ⚙️ — 2 stubs de 34 lignes qui devinaient les routes (`/api/v1/auth/users` → **404** ; les identités sont sous `/api/v1/users`). Reconstruits sur les routes lues dans le source. auth = identités + **sessions (qui/IP/device/âge/courante)** ; system = status/metrics/resources/health_score/network/security, chaque section dégradant indépendamment. - **Metrics emoji** 📊 — `core/metrics.js` : seuils **par type** (disk le plus strict, cpu tolérant) ⇒ disk 94.5% = 🔴 / cpu 10% = 🟢 ; langage simple ("Memory 75% — 5.5 GB of 7.7 GB used"). - **Billets hashtags emoji** 🏷️ — migration 0004 (`tag`+`billet_tag` indexés) ; tags **extraits du corps** (`#secu`) ⇒ zéro effort auteur + rétroactif : le backfill a taggé **37/46** billets. Slugs sans accents (#Réseau==#reseau), emoji stocké (pas de restyle silencieux), ancres d'URL non taggées, tag inconnu = badge neutre. Vues rapides `?tag=` sur `/` + `/feed.json` (EXISTS, pas JOIN → pagination keyset non dupliquée ; le pager garde le tag). - **Résumés du feed** 📄 — billets longs = extrait court + "Lire la suite" ; courts = entiers (16/20 résumés en live). - **`GET /admin/api/billets`** — liste d'authoring : le feed public ne peut pas la servir (son `id` est une URL permalien → **cause des 404 Edit/Delete**, et il masque les drafts). - **Companion re-login 401** 🔓 — les tokens box vivent 24h mais le Companion scelle le sien au pairing et le réutilise → le lendemain tout 401 sans issue ("Failed: unauthorized" billets + podcaster). `api.js` déclenche la ré-auth et **rejoue la requête une fois**, single-flight (1 prompt), donc un write en cours (un billet tapé) n'est pas perdu. SW v10. ### ⬜ Next / follow-ups - **Rebuild `.deb` billets** (migration 0004 + `services/tags.py` + postinst .pth). - **Refresh token** : éviter la re-login toutes les 24h sur le Companion. - ✅ **APK rebuild fait** : republié le 17/07 (SW v11, peertube, upload, re-login 401). Recette : `JAVA_HOME`=JBR Android Studio (le JDK système n'a pas `jlink`), `cap copy` (pas `sync`), gradle **8.9-bin**. Signer debug **inchangé** (`5e6163f9…`) → install par-dessus sans désinstaller. Ancien APK conservé en `.apk.prev`. `android/` est désormais versionné → build reproductible ailleurs. --- ## ✅ 2026-07-17 : Billets — API admin JWT + authoring/upload Companion (branche fix/companion-billets-feed) Companion devient un vrai client d'écriture pour le micro-blog billets. Live-vérifié gk2. Détail dans HISTORY.md. - **API admin JWT** 📝 — nouveau `api/routes/jwt_admin.py` : surface JSON JWT-authed (`require_jwt` : Bearer OU cookie `secubox_session`), parallèle à l'admin HTML session, **réutilise le même repo/media**. `POST/PUT/DELETE /admin/api/billets`, `POST /admin/api/billets/{id}/media` (multipart, EXIF-strip), `GET /admin/api/comments` + approve/delete. No-op si `secubox_core` absent. - **Fix venv (packagé)** — le venv isolé billets ne pouvait pas importer le `secubox_core` géré par `.deb` ; postinst pose un `zz-secubox-system.pth` trié-dernier (append dist-packages, wheels venv prioritaires — fastapi/pydantic non shadowés). Backport du hotfix board. - **Module Companion billets** — EP → `/feed.json` + `/admin/api/*` ; éditeur gagne un champ image uploadé après création du billet ; SW v6→v7. - **Vérifié live gk2** — JWT minté en user `secubox` (résolution `_secret()` identique au service) : create → feed (30 items), upload PNG valide → `{url, thumb}` (PNG corrompu correctement 415), delete — tous 200. ### ⬜ Next / follow-ups - **Merger** `fix/companion-billets-feed` ; rebuild `.deb` billets pour livrer le postinst .pth aux installs neuves. --- ## ✅ 2026-07-17 : WAF (webui + autoban→firewall + analyse) + Nextcloud rework (PR #866, #867 mergées) Deux dashboards refaits cyan, un gros trou de contrôle WAF colmaté, module Nextcloud réparé. Live-vérifié gk2. Détail dans HISTORY.md. - **WAF webui** 🛡️ — dashboard sbxwaf restylé cyan hybrid-skin (cartes emoji, pulse live, refresh réactif) ; endpoints préservés ; rend la donnée live (198k threats). - **WAF autoban→firewall** 🔥 (PR #866) — le bridge CrowdSec était **silencieusement OFF** (unit passe `--crowdsec-url` mais pas `--crowdsec-jwt-file` → branche 'disabled' → `Report()` jamais appelé). 198k threats, ~0 ban réel (un IP a tapé 36 881×). Ajout `CscliReporter` (`cscli decisions add` = vrai drop nft bouncer, le chemin du ban manuel qui marche) + dedup 5-min par IP (anti-storm `signal: killed`). Rebuild arm64 + deploy. Prouvé : 5 hits honeypot → 1 seule décision. - **WAF analyse efficacité** 📊 — détection forte / contrôle faible (2 bans seulement) ; ~26% du pattern-matching (voip/xmpp = 39/149) inutile en HTTP ; top /24 = 26% du volume. Fixes classés. - **Nextcloud** ☁️ (PR #867) — `/nextcloud/` montrait Stopped/vide : probe status cassé (lxc-info/occ **sans sudo** + lxc_path `/srv/lxc` vs `/data/lxc` ; seul `sudo nextcloudctl` est permis ; **`NoNewPrivileges=yes` bloquait sudo** — gotcha wireguard). Fix : port-probe privilege-free + ops via `sudo nextcloudctl` (occ passthrough) + **cache daemon-thread 60s** (le startup uvicorn ne firait pas) + web_url public. Webui restylé cyan. Vérifié : running v32.0.10, 2 users, 5.8G. ### ⬜ Next / follow-ups - **WAF efficacité #2–4** : bans subnet/ASN (le /24 = 26%), skip voip/xmpp en HTTP (26% de regex), ne plus logguer les IP déjà bannies. - **Backport Nextcloud** : drop-in `NoNewPrivileges=false` + `[nextcloud] domain="nc.gk2.secubox.in"` dans le paquet (secubox.conf/unit). - **#862–#864** toujours ouverts (provisioning mail, ACME wiring, vendorer ident_switch). --- ## ✅ 2026-07-16 : Mail overhaul + fix auth systémique + DPI exfil/regen (PR #865 mergée, #862–#864) Session multi-fix, **live-vérifiée sur gk2**, portable mergé (PR #865). Détail dans HISTORY.md. - **Auth (systémique, fleet-wide)** 🔑 — `require_jwt` : un Bearer périmé (vieux `sbx_token` localStorage) shadowait le cookie session valide → **boucle login sur tous les panels**. Fix : Bearer **puis** cookie. Prouvé (Bearer périmé + cookie valide → 200). - **Mail** 📧 — reset gk2-only ; **mailbox réparée** (ownership idmap → host `105000`) ; **submission 587/465** (SASL dovecot + vrai cert) ; **status TCP-probe** (fini les "Stopped" faux) ; domaine → `gk2.secubox.in` ; **webui reskin cyan** ; **`/user/password`** réparé (écrivait un fichier non lu) ; Roundcube **`password`** (self-service) + **`ident_switch`** (Gmail externe, vendored). - **DPI** 🔍 — `/exfil` sert le cumulatif (**7 devices**, "no devices" corrigé) ; moteur = `secubox-dpi-flowcap` (plus netifyd) ; **webui régénéré cyan**. - **openclaw** 🕷️ — CT lookup fallback certSpotter. - **ACME HTTP-01** 🔒 — câblé live (nginx `:8880` + route HAProxy) ; émission LE marchait pour aucun vhost WAF-routé. ### ⬜ Next / follow-ups - **WAF webui rework** 🛡️ — en cours (sbxwaf, cyan hybrid-skin, live 198k threats) ; + **analyse efficacité triggers/control** demandée. - **#862** provisioning mail (submission SASL, chown idmap 105000, users.sh maildir brace/path, helper self-service password) — backport paquet. - **#863** ACME wiring (nginx `:8880` + route HAProxy + certs webroot) — backport paquet. - **#864** vendorer `ident_switch` + schéma SQLite dans `secubox-mail`. - Rappel : mot de passe mailbox gk2 = `Gk24@SECUBOX;001`. --- ## ✅ 2026-07-12 : metalogue — suite OSINT Maltego-style en modules LXC (#845) Deux modules OSINT construits (subagent-driven + revue adversariale), déployés **et installés** sur gk2, mergés (#846–#850). Détail complet dans HISTORY.md. Voir [[Metalogue]] wiki. - **secubox-maigret** 🔎 — collecteur d'identité (pseudo → comptes sur 3000+ sites). LXC 10.100.0.42, CLI wrappé par une API host (job async, cap 3 lookups, 429), passif-only, JWT + audit. **Installé + fonctionnel** (lookup `torvalds` = vrais comptes). - **secubox-spiderfoot** 🌀 — moteur d'automatisation (200+ modules passifs + graphe corrélation = hub Maltego intérimaire). LXC 10.100.0.43. **Installé, UI live à https://spiderfoot.gk2.secubox.in/** (proxy à la racine, LAN-gated ; le subpath `/spiderfoot-ui/` heurtait le SPA portail → vhost dédié zigbee/lyrion pattern + route sbxwaf + ACL HAProxy). - **Rapport PDF stylisé** (maigret) — raw → dossier formel SecuBox (masthead, bloc métadonnées CONFIDENTIAL, §1 Résumé, §2 Findings en table cohérente zébrée/colorée par catégorie). `GET /lookup/{id}/report.pdf` (JWT, off-loop) + bouton 📄 PDF. fpdf2. - **2 root-causes corrigés (install)** : (1) `ip_forward` dérivé à 0 → aucune sortie internet des LXC (tous, openclaw inclus) ; restauré `sysctl --system`. (2) deps arm64 sans wheels → **piwheels** (17min-fail → 2min-ok). Backportés dans les `ctl`. ### ⬜ Next / follow-ups - **P3 OpenCTI** (hub graphe Maltego) — différé sur nœud amd64/dédié (stack ES trop lourde pour gk2, ~1.5 Go libre). - **ip_forward reset runtime** : qqch remet `ip_forward=0` après boot malgré le drop-in zz — investiguer (récurrent, casse la sortie des conteneurs). - **Ré-activation sur image neuve** : l'expo publique SpiderFoot (route sbxwaf + ACL HAProxy + nft :9043 + snippet exposure) a été câblée **live** ; le paquet livre les vhosts mais un re-enable opérateur est requis au flash. - **Self-registration aggregator.toml** : maigret/spiderfoot ajoutés à la main dans `modules=[]` (comme openclaw) ; le paquet ne s'auto-enregistre pas. --- ## ✅ 2026-07-10 : WireGuard — refonte WebUI + fix avalanche perf + purge peers (secubox-wireguard 1.0.3) `/wireguard/` était inopérant + bruyant. Corrigé end-to-end (board + source), **commits sur master** (poussés). Détail dans HISTORY.md. - **Privilège** : API (secubox) lit l'état WG via `sudo -n wgctl` (root requis pour `wg show dump`) ; sudoers scellé + `visudo`, unit `NoNewPrivileges=false` (bloquait sudo). - **Avalanche perf (load 56 → board starved)** : `wgctl status`/`peers` faisaient ~8 subprocess **par peer** → 30s+ sur le tunnel wg-toolbox (542 peers) ; `asyncio.wait_for` ne tuait pas l'enfant → zombies. Fix : passes uniques `wg show dump`/awk (542 peers 30s→0.07s), kill-on-timeout, cache single-flight. - **Sécurité (revue)** : le passage sudo activait une fuite de clé privée tronquée dans `_parse_wg_show` (parse all-dump par nombre de champs, ne lit jamais la privkey) ; handlers WebUI en `data-*`+délégation (plus d'interpolation onclick). - **WebUI** : dashboard cartes-interfaces (rôles 🧰🕸️🛡️, status live, drawers peers lazy, up/down + add-peer/QR), skin certs + navbar partagée. Grands tunnels = peers **connectés seulement** par défaut (toggle "Show all"). - **Purge wg-toolbox** : 543 peers dont **540 jamais connectés** (R3 enrôle 1 peer/navigateur dans `/var/lib/secubox/toolbox/wg-peers.json`, re-appliqué au boot par `secubox-toolbox-wg-restore`). Store sauvegardé, purgé runtime+store aux 3 clients vivants. ### ⬜ Next / follow-ups - **Reskin `/users/` en hybrid-skin (certs/wireguard) + doc "WebUI Panel Guidelines"** — demandé, en cours (users utilise crt-light light-green, à convertir dark-cyan). - GC `secubox-toolbox` : timer purgeant les peers wg-toolbox sans handshake > N jours (sinon ré-accumulation). - Merger PR nextcloud #429 (attend restauration gh auth). --- ## ✅ 2026-07-06 → 07-07 : Sentinel — moteur de menaces, activation, 3 surfaces + C2 auto-learn (#821 #823–#828) Toutes mergées + déployées + validées live gk2 (sauf #828 en attente de merge, déjà déployé). Détail complet dans HISTORY.md. - **#821/#822 Frigate NVR foundation** ✅ MERGED (podman-in-LXC amd64/OpenVINO). - **#823/#824 moteur Sentinel** ✅ MERGED (dark) — gate IOC inline + daemon async `sbx-sentinel` (bbolt, YARA build-tag), packs spyware commercial (Pegasus/Predator/Intellexa), report-only. - **#825 activation + 3 surfaces** ✅ MERGED — onglet WebUI **🛡️ Sentinelle** (flotte) + onglet **Compromission** rapport kbin + section **PDF**. Live gk2, e2e prouvé. Fix clobber `RuntimeDirectory=secubox` sur `/run/secubox` (drop-in). - **#826/#827 C2 auto-learn** ✅ MERGED — apprentissage beaconing haute-précision (gate allowlist + multi-signal rare/non-browser-JA4/DGA + candidate→confirm ≥3 fenêtres/≥30min), `/c2/*` + vue **C2 appris** + bouton **Ignorer**. Report-only. - **#828 fix faux-positif C2** ⏳ **OPEN (PR #828)** — dashboard admin appris sur rareté seule → exige désormais un signal FORT (`dga`/`non_browser_ja`), `rare` = support seul. Déployé board (toolbox-ng 0.1.31), validé live (vrai C2 appris, dashboard+mail supprimés). ### ⬜ Next / follow-ups - Merger **PR #828** (aligne master 0.1.31 = board, ferme la dérive). - Peupler `browser-ja4.txt` (seed vide → `dga` seul signal fort out-of-box ; besoin de vraies empreintes JA4 navigateur capturées). - Optionnel : activer `secubox-sentinel-feeds.timer` (détection C2 réelle via overlay MVT/CitizenLab/abuse.ch — opt-in opérateur). - Audit-log append-only pour les mutations `/c2/allow` (convention CSPN). --- ## ✅ 2026-07-03 → 07-04 : ToolBox — rapport vie privée fidèle + media types + fiche de personnage (#785 #790 #792) Trois features (brainstorm → spec → plan → SDD subagent-driven, revue two-stage + whole-branch adversariale), **toutes mergées sur master**, déployées + validées live gk2. - **#785 — PDF kbin fidèle à la page web + media types + WebUI DPI** ✅ MERGED (PR #787). Onglets DPI-Exfil (me) + Overall en **donut-grids** matplotlib (fini les puces) ; bloc **🎬 media types** (MIME réels capté sbxmitm + catégorie DPI `media`), me+overall, PDF+web ; `secubox_core.media_catch` (tail-read borné, fail-empty) ; 2 cards WebUI DPI + endpoint `/media_types`. - **Incident déploiement** ✅ résolu : rendu PDF matplotlib **sync sur l'event-loop** du worker unique + tempête auto-retry de la page 504 WAF → 504 board-wide. Durci (live+source) : threadpool + asyncio.Lock (pyplot pas thread-safe) + **cache PDF par device** (double-check → 1 rendu par tempête) + **MPLCONFIGDIR** persistant. - **#790 — fiche de personnage riche + parité routes** ✅ MERGED (PR #794). Fiche PDF fidèle à la carte `.nr` : ⚡ pips `●●●○○○`+notes, 🎒 inventaire ✓/✗, 🐉 bestiaire, ⚔️ Quêtes/menaces. `_enrich_report_data` factorisé → `/report/{token}` + `/admin/.../report` = même PDF riche que `/report/me` (avant : PDF nu). Full-fpdf. - **#792 (replié dans #790) — Quêtes réelles** ✅ CLOSED. `_dpi_stats` expose `alerts_raw` (kind/service/dst/detail) → les menaces montrent destination + détail (`🗡️ NEW CLOUD — AWS S3`) au lieu d'un « — » orphelin, côté HTML + PDF. Wiki : nouvelle page **[[ToolBox]]** (cas d'usage cabine numérique + features rapport). 202 tests toolbox verts. Backups board `/root/backup-785-*` + `/root/backup-790-062856`. --- ## ✅ 2026-07-04 : Zigbee WebSocket (#796 · PR #805) + PeerTube admin ops (#798 · PR #800/#804) - **#796 — sbxwaf laissait tomber les upgrades WebSocket** ✅ FIXÉ + live, **PR #805 ouverte**. `wss://zigbee.gk2.secubox.in/api` cassait (close 1006 + boucle de reconnexion) alors que `http://10.100.0.111:8080` LXC-direct marchait. 3 couches : `main.go` forçait `Connection: close` écrasant `Connection: Upgrade` ; `statusRecorder` + `cachingResponseWriter` n'implémentaient pas `http.Hijacker`. Fix : `isWebSocketUpgrade()` + `Hijack()` forwardé sur les 2 wrappers + log d'erreur upstream (qui a épinglé la couche Hijacker). `websocket_test.go` neuf. Live gk2 : `wss://zigbee → 101 Switching Protocols`, dashboard stable. `go test ./cmd/sbxwaf/` vert, merge propre avec master. - **#798 — PeerTube WebUI admin ops** (reset-password + version check + upgrade) ✅ MERGÉ (PR #800), spool→root (#407) : API non-privilégiée dépose un intent, `peertube-ops.path` root le draine via `peertubectl` (pas de sudo, NoNewPrivileges intact). **Bug de boucle corrigé, PR #804 ouverte** : `.path` surveille `OPS_DIR` en `DirectoryNotEmpty=` mais `process-ops` écrivait les résultats DANS `OPS_DIR` → jamais vide → `.path` re-déclenche `.service` en boucle → `start-limit-hit` tue le mécanisme après la 1re op. Fix : résultats dans `/run/secubox/peertube/results/` dédié ; `ops/` se vide après drain. Vérifié live gk2 (2 pings consécutifs drainent, `NRestarts=0`, résultat `root:secubox 0640` lisible secubox). Delta `main.py` posé en préservant les 4 endpoints async board. > ℹ️ Session parallèle : `secubox-toolbox-autolearn` (miroir splice-learned → bypass webui > MITM) + rename « WAF Filters → Filtres MITM » commités hors session sur master (`872be8c7`). ### ⬜ Next Up ToolBox (déféré, non bloquant) - **#786 — double-caching de l'agrégation media-catch** : `/media_types` + `_media_stats` agrègent le JSONL par requête (borné mémoire par tail-read, mais pas de cache 60 s comme la règle CLAUDE.md). Option préférée : sbxmitm émet un `media-stats.json` pré-roulé. Dormant hors R3/R4. - **Cosmétique HTML Quêtes** : double-espace quand une menace a un détail mais pas de destination. --- ## ✅ 2026-07-02 : P2P évolutions — DHT + Federation + Master-link LIVE sur le mesh 3 nœuds (#774 · PR #775) Reprise et refonte propre du chantier P2P (le code Mistral non-intégrant a été supprimé), puis construction **subagent-driven TDD** (17 tâches, 132 tests, revue par tâche + revue finale opus). Branche `feature/p2p-dht-federation`, **PR #775 ouverte**. - **Kademlia DHT custom** — asyncio/UDP `:51823`, records de joignabilité signés Ed25519 `{did,id_pubkey,wg_pubkey,endpoint,ts,sig}`, lookup itératif α-parallèle, persistance routing, store `put_health`/`get_health`. - **Federation health-checks** — probe aiohttp GET `/health` + fallback TCP, debounce up/down, publication via DHT. - **Master-link hiérarchique** — UDP `:51824`, élection déterministe `(priorité, node_id)`, failover par *term* monotone avec tie-break (pas de fenêtre zéro-master), heartbeats signés Ed25519. - **OPAD** — feature-flag OFF par défaut ; config `/etc/secubox/p2p.toml` `[dht]/[federation]/[masterlink]`. **Live-activé sur les 3 nœuds** : gk2 `10.10.0.1` (MASTER, term 1, prio 10) · c3box `10.10.0.2` + amd64 `10.10.0.3` (satellites). Chaque DHT découvre les 2 autres (peers=2), pas de split-brain. Déployés aussi : **onglet Mesh viz** du dashboard p2p, **fix du rebond de login** (3 box), **nginx gk2** re-routé `/api/v1/p2p/` → `p2p.sock` (l'endpoint reflète le vrai daemon), **nft reboot-persist** `wg-mesh udp {51823,51824}` (c3box+amd64). > Poster de synthèse + roadmap détaillée : `docs/P2P-EVOLUTIONS-POSTER-PROMPT.md`. ### ⬜ Next Up (roadmap P2P, non bloquant) - **Pont bans mesh → moteur sbxwaf** — les bans fédérés (threatmesh #768) s'appliquent au nft (`inet secubox_meshban`) seulement ; les faire alimenter sbxwaf via `cscli decisions add --ip X -R "secubox-mesh" -d 4h` (anti-boucle : filtre *reason* `secubox-mesh` dans `secubox-threatmesh-bridge`). - **macroctl sur satellites** — `secubox-p2p` standalone tourne `NoNewPrivileges=yes` ⇒ `sudo macroctl activate` refusé ; OK sur gk2 (aggregator NNP=no). Fixer le chemin privilégié satellite sans casser le durcissement. - **Fenêtre transitoire du socket p2p** — 502/504 webui satellite pendant un restart de `secubox-p2p` (recréation `p2p.sock`) ; lisser (socket-wait / `RuntimeDirectoryPreserve`). --- ## ✅ 2026-06-30 → 07-01 : Substrat de confiance Gondwana — fédération + registry + macros (#766 #769 #771) Trois features complètes (brainstorm → spec → plan → SDD subagent-driven avec revue adversariale), **toutes mergées sur master**, déployées gk2 + c3box, prouvées live : - **#766 — annuaire fédération sans-confiance (0.2.0→0.3.x)** ✅ CLOSED/master. `ingest_offer` impose `did_from_pubkey(pubkey)==provider` avant la vérif sig (auto-certifiant, aucune confiance préalable) ; offres portent `sig`+`signer_did`+ `provider_pubkey` ; verbe `genesis()` + CLI `annuairectl` (init/whoami/status/offer/ services/pull) ; écouteur mesh (postinst, IP-mesh only, `ip_nonlocal_bind`, validate-or- revert). Live : un 2e nœud (fondateur distinct) `annuairectl pull` → ingest sans-confiance. - **#769/#770 — p2p Service Registry = vue live du catalogue annuaire (secubox-p2p 1.8.0)** ✅ MERGED. `/services` fusionne catalogue annuaire + abonnements + overlay d'activation + services p2p-locaux ; « Auto register all » (active locaux + s'abonne aux distants selon auto/pending) ; s'abonne EN TANT QUE nœud (clé 0600). Live gk2+c3box. - **#771/#773 — sous-système macro + tor-exit (secubox-macro 0.1.0 NEW, p2p 1.9.0, annuaire 0.3.3)** ✅ MERGED (+#772 auto-fermé). Un service propose une **macro d'accès** vettée, confinée AppArmor : `macroctl` dispatcher root (allowlist kind, tamper-guard plugin, euid env-pin, audit append-only) + `macros.d/tor-exit` (nft SOCKS-over-mesh grant/revoke) + sudoers (env_reset) + auto-détection table firewall (`secubox_filter`|`filter` via `/etc/secubox/macro.conf`). Endpoint grant p2p (auth Subscription auto-signée, self-cert, auto-mode). **Démo live end-to-end** : gk2 propose son exit Tor → fédère → c3box s'abonne+ active → pull grant sur le mesh → gk2 nft-autorise l'IP mesh de c3box → **c3box route via l'exit Tor de gk2** (`IsTor:true`). La boucle de revue SDD a attrapé ~10 Criticals avant merge. ### ⬜ Next Up (déféré, non bloquant) - **Liaison NIZK/PSI GK·HAM** — les verbes annuaire utilisent encore les stubs documentés (`ZKP-HAM-v1`) ; brancher `zkp-hamiltonian` cffi. - **Nouveaux kinds macro** — `wg-relay`, `dns-resolver`, `http-mirror` (chacun = un plugin `macros.d/` vetté + profil AppArmor, même framework). - **Macros en mode `pending`** — nécessite la fédération cross-nœud des Subscription/APPROVE. - **Mesh gk2→c3box (sens inverse)** — pull satellite→master OK ; master→satellite bloqué (nft c3box) ; + installer Tor sur c3box pour un provider tor-exit natif. --- ## ✅ 2026-06-27 : c3box → SecuBox Debian — première install réussie · netboot prouvé (#748 #737) ### ✅ Fait (session 2026-06-27) - **Netboot gk2→c3box prouvé** — factory U-Boot 2020.10 → TFTP → rescue shell installeur (kernel 6.12.85 #5secubox). Détour cabling résolu (impasse LAB, pas logiciel). - **Première install SecuBox Debian sur un MOCHAbin physique (c3box)** — image CI artefact `secubox-mochabin-bookworm` (run 27426515472, 8 Gio), SHA256 + signature vérifiés, `gunzip|dd` en RAM → eMMC. c3box boot Debian v1.9.0 avec stack complète. - **boot.scr workaround déployé** — extlinux.conf charge le kernel à `0x02080000` (réservé factory U-Boot → reset). Construit `/boot/boot.scr` (kernel@`0x0a000000`) ; auto-boot Debian sans intervention vérifié après reboot. - **#748 bloquant documenté** — ciseau U-Boot : mochabin board UNIQUEMENT dans fork Tow-Boot 2022.07 (pas de `wget`) ↔ `wget` UNIQUEMENT dans stock ≥2023.07 (pas de board mochabin). Branche `feature/748-enhanced-tow-boot-http-netboot-serial-fl` parkée (spec+CI+Kconfig en place, dépend du backport wget OU port board mainline). ### ⬜ Rig netboot temporaire gk2 à démonter (quand c3box autonome) - `lan1=192.168.77.1/24` avec dnsmasq DHCP + `nft iif lan1 accept` + nginx `:8099` encore actifs. - À retirer une fois c3box en prod (voir TODO T5 — teardown rig). ### ⬜ Bootloader propre à faire (#748 ou alternative) - boot.scr = workaround ; fix durable = enhanced Tow-Boot (#748, bloqué ciseau) OU corriger les adresses de boot dans l'image (extlinux.conf → `0x0a000000`). Voir TODO T5. --- ## 🗂️ 2026-06-22 : triage issues (30 ouvertes → revue obsolètes) - **Fermées (user-validé 2026-06-22)** : #722 (nDPId — décidé contre, reverté) · #475 ToolBoX Phase 1 (live 2.7.x) · #502/#507/#508 Social mapping (carto + /social/me + report PDF live) · #495 Phase 5 mitm-LXC (superseded par #662 Go sbxmitm host) · #531 APK one-tap (superseded par #685/#686 non-root) · #486 geoip/ASN+flags+catégories dans rapports (livré master : geo.py + dpi_class.py + report wiring ; complémentaire de #718 ASN collector ; worktree stale nettoyé) · #515 CDN detection (live `social_host_meta.cdn_vendor`) · #516 anti-bot detection (live via #564/#565) · #519 enforcement plane (livré + **réparé** : blacklist-sync avortait NXDOMAIN + timeout unit → fix `|| true` + TimeoutStartSec 600, vérifié live, default-off ; inclut #522). Toolbox source bumpé 2.7.18 (fix live-patché sur gk2) · #468 /etc/secubox traversal (source+live = 0755, secrets/CA enfants restent 0750). - **Actives (worktrees en cours)** : #655 webext banner · #615 security-posture · #494 secubox-core ExecStart · #498 Phase 7 WAF enforcement · #485 SOC scoring. ### 🔎 Reco T0 — recon live gk2 2026-06-24 (avant fix) - ✅ **#494** : **FIX SYSTÉMIQUE poussé** (`fix/494-…`). Pas que core : 7 units re-chownaient le parent partagé `/run/secubox` (core+hub services, eye-remote/eye-square/metablogizer/ metrics/p2p postinsts ; eye-square chownait aussi /var/log/secubox = pire). Tous nettoyés (mkdir fallback only ; logs modules en sous-dossier propre ; orphan /etc/tmpfiles.d nettoyé). **Vérifié live** : /run/secubox 1777 **root:root** stable après restart core ET hub ; webui 200. Bumps core 1.1.7/hub 1.4.4/eye-remote 1.0.1/eye-square 1.0.4/metablog 1.2.2/metrics 1.0.4/p2p 1.7.1. - ✅ **#471** (mesh /run/secubox) : déjà résolu (changelog mesh "drop install -d /run/secubox") → verify-close. - ⬜ **#421** : sockets cachés en mount-ns privé (RuntimeDirectory) — mécanisme distinct, non traité. - 🆕 Suivi (classe #511) : mesh/toolbox/admin font `install -d -o /var/log/secubox` (propriétaire du parent partagé = user module) → autres daemons ne peuvent créer leurs logs. Séparé de #494, à traiter (sous-dossiers propres comme fait pour eye-square/p2p). - **#447** : pas une fuite — `password_hash=null` → lockout kiosk + user CI parasite ; **CI-image-gated** (rpi400, pas gk2). - **#91** : `haproxy.cfg` active valide ; backup `*.broken-by-haproxyctl-*` prouve le bug passé ; drift-guard #627 rattrape. Root cause = generate `haproxyctl` (api/main.py l.846/896). - ✅ **#53** : **FIX poussé** (`fix/53-…`) — gate `ConditionPathExists=/var/ossec/etc/ossec.conf` + `RestartSec=5` ; module conservé (SIEM opt-in). Vérifié gk2 (/var/ossec absent). Bump 1.0.1. - ✅ **#65** : déjà résolu en prod (webui.conf déployé inclut `secubox-routes.d/*.conf`, 163 snippets). Template `common/nginx/webui.conf` (stale) synchronisé sur `feature/65-…`. Reco fermer. Convention : `secubox-routes.d/`=actif, `secubox.d/`=legacy. - ✅ **#121** : **FIX poussé** (`fix/121-…`) — helper `fix_perms` chown -R secubox:secubox le site dir après chaque ingest .git (metablog-ingest-site.sh). Script dev, pas de deploy. - ⬜ Restent : **#91** (deploy WAF risqué) · **#65** (refactor include, risque 502) · **#447** (CI kiosk) · **#494/#471/#421** (worktree fix/494). Build+deploy toolbox 2.7.18 (#519) en attente. - **Backlog/future** : #685/#686 APK non-root (plan verrouillé) · #592 webmail-hub · #514/#515/#516/#519/#522/#525 Phase 12-14 (#515 CDN / #516 anti-bot partiellement couverts par antibot_sites/opgrade_sites du social graph) · #500 Utiq · #497/#480/ #478 VILLAGE3B Eye/poster · #472/#430/#429 Nextcloud · #471/#468/#421 perms (à vérifier si déjà corrigées) · #467/#462/#460/#255/#254 hardware/kernel · #455 egress · #454/#453/#452/#449 mesh/BLE · #448/#447/#446/#434 kiosk · #422 vm cascade · #393/#379/#347 packaging · #513 WebUI sub-tabs. - ⚠️ Fermeture finale = **user only** (sauf issues créées en session) ; les recommandations ci-dessus sont commentées sur chaque issue. --- ## ✅ 2026-06-22 : DPI exfil + Netrunner report + sbxmitm fixes (tous mergés, live gk2) Session livrée intégralement sur master + déployée. Détail dans HISTORY 2026-06-22. ### ✅ Fait (mergé + live) - **DPI exfil pipeline (#687)** — `secubox-dpi 1.1.2` : flowcap (ndpiReader) → Go collector (catégories cloud/media/game/adult/ai/messaging/filehost/social + scénarios exfil) → `/api/v1/dpi/exfil` ; dashboard "Cloud Exfiltration Watch" + cartes repointées ; beaconing tuné (#692) ; cumulatif 7j `cumulative.json` (#705) ; packagé arm64. - **Report kbin = fiche Netrunner (#707)** — HTML (onglets Pistage/DPI/Overall + persona néon) **et** PDF (`_persona_block` + "En un coup d'œil" + grille donuts + carto + tables emoji). Charts en **PNG matplotlib** (#714, rendu universel iOS/Chrome) ; grille = une image 2×2 (#716, fin des 24 pages). Classe via UA live + niveau R3 auto (wg peer). - **sbxmitm** — cert forgé 24h→365d (#689, fin des "certificat expiré") ; fin de la troncature >8MiB (#697, Gmail OK) ; splice own-domain **rejeté** (#688, on intercepte tout). ### ⬜ Next Up (différé) - **#685/#686 APK on-device — NON-ROOT ONLY (plan verrouillé)** : VpnService in-app (wireguard-go), CA en DER + network-security-config WebView, retrait du chemin root. Gros build Android (CI + test device) → session dédiée. Détail : commentaire #685 + TODO. - **DPI Phase 3** — ✅ enrichissement ASN (#719, 1.1.3) · ✅ historique + timeline (#721, 1.1.4) · ❌ démon nDPId **écarté** (#722/#723 revertés) : risque perf (démon permanent vs fenêtres ndpiReader bornées) sur board saturée → **on garde ndpiReader**. **Phase 3 close.** - **#685 APK on-device** — install auto CA + handoff WG + détection tunnel (en attente décision rooted vs non-root du user). - **Cosmétique PDF** — glyphes drapeaux régionaux dégradent en lettres (police embarquée) ; chiffres légèrement espacés dans certaines cellules. Non bloquant. --- ## 🔄 2026-06-19 : kbin Tor egress (#683) — ToolBoX 2.7.1, implémenté DARK Switch + tunnel Tor quick-switch livrés sur `feature/683`, **défaut OFF / fail-closed**. Détail dans la section "Implémenté DARK" ci-dessous + HISTORY 2026-06-19. --- ## 🔄 2026-06-19 : kbin milestone — ToolBoX 2.7.0 + chapitre Tor (plan) Checkpoint de fin de session. Pas de changement de comportement runtime — docs + positionnement + version + plan de la lame suivante. - ✅ **ToolBoX 2.7.0** (middle release) — clôt la ligne 2.6.x (ad-intelligence / Anti-Track v2 / anti-bot uTLS #662), ouvre le chapitre kbin « premier outil du couteau suisse cyber ». kbin = perf transparente + full encrypted + poison/smog + bandeau anti-adware + safe browsing. - ✅ **Docs kbin** — wiki [`Kbin-Toolbox.md`](../docs/wiki/Kbin-Toolbox.md), [`FAQ-KBIN-TOR.md`](../docs/FAQ-KBIN-TOR.md), blurb README. - ✅ **Plan #683** — spec [`2026-06-19-kbin-tor-anonymized-surfing-design.md`](../docs/superpowers/specs/2026-06-19-kbin-tor-anonymized-surfing-design.md) : endpoint Tor quick-switch (egress sortant, fail-closed, opt-in, no DNS leak, inspection préservée). Dépend du cœur Go #662. ### ✅ Implémenté DARK — chapitre Tor (#683, ToolBoX 2.7.1, branche feature/683) - ✅ **Transport tranché** : *torify l'egress MITM* (owner-match nft sur l'uid `secubox-toolbox`/mitm-wg → Tor TransPort 9040 / DNSPort 5353). Inspection préservée. Décision USER (vs dialer SOCKS5 #662 = bloqué, vs torify client = casse l'inspection). - ✅ **Switch** : flags `tor_mode`/`tor_preset` (filters.json) ; API kbin-gated `GET/POST /admin/tor/{state,on,off,newnym,check-leaks}` ; onglet 🧅 WebUI (badge, toggle, NEWNYM, sonde fuite). `tor_ctl.py` réutilise le control-port de secubox-tor. - ✅ **Tunnel** : `conf/nft-toolbox-tor.nft` (fail-closed kill-switch + drop v6) + `conf/torrc-toolbox-egress.conf` + reconciler root path-triggered (`secubox-toolbox-tor.path` surveille filters.json → portail reste NoNewPrivileges=true). nft chargé AVANT tor (pas de fenêtre clearnet). - ✅ 166 tests verts ; license headers OK ; changelog 2.7.1. #### ⬜ Avant flip ON (USER) - Soak DARK puis `tor_mode=true` via l'onglet (admin.gk2). - Test de fuite **hors-board** : l'IP réelle de la box ne doit jamais apparaître. - Forcer `tls_splice` (#649) OFF quand armé (sinon flux asset fuient l'IP réelle). - **Per-client (WG-hash)** : nécessite le dialer SOCKS5 du cœur Go #662 (l'owner-match est global). Suivi sous #662. --- ## 🔄 2026-06-17/18 : Anti-Track v2 + perf/ops sprint (gk2 live) Tout mergé sur master + déployé sur gk2. Détail dans HISTORY 2026-06-18. - ✅ **Anti-Track v2 (#633, PR #637)** — bloque/empoisonne/anonymise, moteur `privacy.py` + addon `privacy_guard.py`, learning (`learn.py`), IP-drop + unbound DNS-refuse (`ip_dns.py`/`escalate.py`), bypass-seed + #filtres badges, #social top-5. **Tourne DARK** (`privacy_enforce` unset). Wiki `Anti-Track.md`. - ✅ **Banner saga (#636/#639, PR #638/#640)** — mitm sert loader/bundle pour toute origine (PeerTube fixé), CSP fallback, top-bar, 1 bannière/visite. - ✅ **#634/#635** — reset-all clients + emojis device/flag/hosting. - ✅ **#642 (PR #643)** — social-graph ignore les edges IP-littéraux ; KPI "Trackers vus" = table. - ✅ **#644 (PR #645)** — hub dashboard/health-batch servis depuis cache TTL (health-batch 3.3 s → 8 ms) ; clients/rich enrichit 12 max. **hub 1.4.6**. - ✅ **#646 (PR #647)** — adaptive Accept-Encoding strip : plus de pages CSP-strict tirées décompressées via le worker R3 GIL-bound. **toolbox 2.6.53**. - ✅ **crowdsec** réparé (403 transitoire CDN → `dpkg --configure` RC=0, audit clean). - ✅ **#623 (PR #648, merged 9950e9ec)** — clobber systémique RÉSOLU au source. La vraie cause : boilerplate scaffold `install -d -m 750 /var/lib/secubox` + `/run/secubox` (parents NUS) dans ~56 postinsts — écrit `-m 750` (3 chiffres), d'où le ratage des sweeps précédents. Empiriquement prouvé que le form `install -d -m 750 /parent/leaf` NE clobbe PAS le parent (seuls les targets parents-nus). Fix : tous → 1777 (/run) / 0755 ; 6 lignes multi-arg splittées (4 mettaient /var/lib en world-writable 1777) ; 3 `chmod 750 /var/log` ; scaffold `new-package.sh` + `PATTERNS.md` ; core 1.1.8 tmpfiles.d déclare les 5 parents 0755. **PAS de mass-deploy** (60 paquets = mass-restart = risque thundering-herd) ; live couvert par `dirs-guard.timer` ; arrive au prochain build CI / reflash. - ✅ **#649 Lever A — selective SNI-splice (PR #650, toolbox 2.6.54 LIVE dark)**. New `tls_splice` addon (first in mitm-wg chain) splices pure-asset flows at the TLS ClientHello — curated media seed (googlevideo/ytimg/fbcdn/twimg/scdn…) ∪ autolearn-promoted never-HTML hosts — so GIL-bound R3 workers skip forge/decrypt/parse/16-addons on no-L7-value flows. Ships `tls_splice=observe` (DARK: classify+log, still MITM). Deployed gk2, addon loads clean, 0 runtime errors. Answer to "do we need full mitm?": YES for outbound HTTPS (per-host cert forging is intrinsic) — but only decrypt what we modify. Lever B (Go/Rust core) = strategic follow-up. WAF = later. ### ⬜ Next Up - **#649 SOAK → FLIP** — review `would-splice` logs + `/run/secubox/splice.json` on real traffic for a soak window, confirm no first-party/HTML host is classified, then flip `tls_splice=on` in `/etc/secubox/toolbox/filters.json` (hot-reload). Before flip: the fortknox-via-WebUI refresh gap is already fixed. - **Lever B (#649 follow-up)** — Go/Rust forging-proxy core if A isn't enough. - **Anti-Track v2 ARMING** (décision USER, gated) — soak observe-only puis flip `privacy_enforce=true` ; régénérer `data/cdn-allowlist.txt` depuis les plages publiques avant `privacy_ip_drop` ; `unbound-checkconf` avant `privacy_dns_feed`. - **Tunnel R3 perf** — l'encoding fix aide ; reste la contention CPU board-wide (load ~5/4 cœurs, workers mono-thread). Lever suivant = réduire les co-tenants (gitea/R2-mitm/crowdsec/metrics) ou isoler le mitm, pas du tuning d'addon. - **#615** — Security Posture dans la navbar du Hub (petit enhancement). - **#592 webmail-hub** — BLOQUÉ : besoin client OAuth Google + vhost ; Phase 1 IMAP (Gandi/OVH) peut démarrer sans OAuth. --- ## 🔄 2026-06-14 : ToolBoX privacy/perf sprint — 2.6.36 live (see HISTORY) Tout mergé + déployé sur gk2 (kbin sain, `secubox-toolbox 2.6.36`). Détail complet dans HISTORY 2026-06-14. Résumé : - ✅ Protective spoof (#560), modular filters + ad-ghoster (#566, collapse #584), media cache opt-in (#577), autolearn (#589/#591), DPI media donut (#570), donut + domain-nugget cartographie (#553/#587, IP cachées #575, favicons #555), guirlande banner + pin (#572/#578), webext popup panel (#574), /ca/fingerprint R3 (#562), postinst restart fix (#581), detect_antibot deployment-vs-challenge (#564). - ✅ Clients : APK v0.3.0 (zero-tap launch+boot), webext v0.1.4. - ✅ Fixes live : Nextcloud iPhone photos (files_antivirus off + PHP limits), kbin 503 (#581). ### ⬜ Next Up - **#592 secubox-webmail-hub** (Gmail OAuth2 + Gandi + OVH, inbox unifié) — design filé, **BLOQUÉ** : besoin d'un client OAuth Google (client_id/ secret/redirect) + nom de vhost + (read-only Phase 1 ?). Phase 1 IMAP (Gandi/OVH) peut démarrer sans OAuth sur "start phase 1". - Côté user : re-trust R3 CA `D5:E4:3A` sur l'iPhone (bannière HTTPS) ; tester l'upload photo Nextcloud ; activer `media_cache` si voulu (`/admin/filters/ui`) et surveiller `/admin/cache`. --- ## 🔄 2026-06-13 : Browser extension — emancipate cartographie live (#532) Extension navigateur (`clients/webext-toolbox/`, MV3 Firefox `.xpi` + Chromium) sœur de l'app Android. Sort la *cartographie sociale* R3 dans le navigateur : badge live des traceurs + popup. - **Extension** : `manifest.json` (MV3, background `service_worker` + `scripts` pour FF115+/Chromium), `api.js` (client `/wg/r3-check`, `/social/me` → token, `/social/graph/{token}`, `/social/wipe`), `background.js` (badge = total_trackers, re-pair silencieux si token expiré, couleur escalade gold→anti-bot→opérateur), popup (4 tuiles stats + **mini Round-Eye graph SVG sans dépendance** + top-traceurs taggés CDN/anti-bot/opérateur + actions cartographie/PDF/RGPD-wipe), options (hôte/fenêtre/token manuel). Pas de CORS backend nécessaire (host_permissions). Validé : JSON+JS+SVG OK, `.xpi` build 11.8 KB. - **Serve depuis la toolbox** (`2.6.14`) : `GET /wg/toolbox.xpi` (local sinon 302 → release), bouton `🧩 Extension navigateur` sur les 2 panneaux onboard, helper `secubox-toolbox-fetch-xpi`, postinst dir. - **CI** : `build-webext.yml` — `web-ext lint` (0 erreur, 2 warnings bénins) + build, artifact, release asset sur tag `webext-v*`. - **Release** (PR #540 + #541, mergées) : tag `webext-v0.1.1` poussé → CI a publié `secubox-toolbox-webext.xpi` (téléchargeable, vérifié 200). `make_latest:false` + URL **tag-pinned** dans `/wg/toolbox.xpi` + `secubox-toolbox-fetch-xpi` pour ne pas voler le pointeur "Latest" à la release APK Android (dont l'endpoint résout via `/releases/latest/...`). → bumper le tag dans la constante + le helper à chaque `webext-v*`. - **Reste à faire** : signature AMO (`.xpi` non signé = sideload/dev) ; endpoint SSE `/social/live/{token}` optionnel ; icône PNG Chromium ; contrôle Poke/Emancipate par-site quand #525 (déception) arrive ; déployer `secubox-toolbox 2.6.14` sur la board pour activer le bouton. --- ## 🔄 2026-06-13 : Android ToolBox app — serve + root-mode silent onboarding (#531/#536/#538) App compagnon Android **one-tap R3** pour la cabine VILLAGE3B (`clients/android-toolbox/`, `in.secubox.toolbox`, Kotlin + Compose). - **#531 — scaffold + CI** : projet Gradle/Compose (5-step stepper Discover→InstallCa→ImportProfile→Verify→Done), client `HttpURLConnection`, workflow `build-android-apk.yml` (debug APK artifact, release asset sur tag `android-v*`). CI **GREEN**. - **#536 — serve depuis la toolbox** : endpoint `GET /wg/toolbox.apk` (sert le build local `/var/lib/secubox/toolbox/android/`, sinon 302 → release GitHub) + bouton *📱 Installer l'app ToolBoX (1-tap)* dans les panneaux onboard kbin + helper `secubox-toolbox-fetch-apk`. Vérifié : 200 `application/vnd.android.package-archive`, 14.8 MB. - **#538 — root-mode silent onboarding** (PR #539, branche poussée) : bouton *⚡ Installation automatique (root)* sur devices rootés → install CA dans le magasin **système** (bind-mount cacerts + APEX conscrypt, SELinux ctx, `subject_hash_old` en Kotlin pur) + tunnel WireGuard **natif noyau** (`ip link add … type wireguard` + `wg set`) + vérif R3 auto. Fallback handoff app WireGuard si noyau sans WG. Toutes les actions root gated derrière le tap explicite. Nouveaux fichiers `RootShell.kt`, `RootOnboard.kt`, step `RootAuto` (log streamé). - **Reste à faire** : release signing (keystore secret CI) pour une empreinte publiée stable — actuellement debug-signé (sideload). --- ## 🔄 2026-06-12 : Admin WireGuard tunnel + SSH hardening (ref #529) Accès admin out-of-band + fermeture de la surface SSH publique. - **wg-admin** (#529) : interface dédiée UDP **51821**, server `10.98.0.1/24`, distincte de wg-toolbox (51820). Peer `gandalf-admin` @ `10.98.0.2`. nft drop-in `secubox-admin-wg.nft` (udp/51821), `wg-quick@wg-admin` enabled. Client importé dans NetworkManager du poste dev, tunnel UP, `ssh root@10.98.0.1` confirmé (key auth). - **Découverte sécurité** : la box subissait un brute-force SSH public actif (centaines de tentatives 87.251.64.x / 51.68.34.x + IPs déjà blacklistées). Le routeur `192.168.1.254` port-forward :22 → box sur `eth1`/`lan0`, et l'input chain a un blanket `iif eth1 accept` (le DNAT préserve l'IP source publique réelle). - **Hardening appliqué + vérifié** : - sshd : `PasswordAuthentication no` + `PermitRootLogin prohibit-password` (drop-in `99-secubox-hardening.conf`, key-only). - nft SSH-guard : `tcp dport 22 ip saddr != { 192.168.1.0/24, 10.0.0.0/8 } drop` inséré AVANT `iif eth1 accept` (live sans flush + persisté dans `/etc/nftables.conf`). - Résultat : `ssh root@10.98.0.1` (tunnel) OK key-only ; public `admin.gk2.secubox.in:22` **timeout (bloqué)**. Tables blacklist/wg intactes. - **Script reproductible** `scripts/setup-admin-tunnel.sh` (`provision | add | harden`), idempotent, branche `feature/529` poussée (pas de PR). - **Reste à faire (côté user)** : retirer le port-forward :22 du routeur (le tunnel remplace l'accès) ; IPv6 SSH non couvert par le guard v4 (à ajouter si exposition IPv6). --- ## 🔄 2026-06-11 : Phase 12.C + Phase 13 COMPLETE (protection enforcement plane) — v2.13.16→19 (ref #518-#528) ### ✅ Phase 12.C — operator-grade / state-adjacent (#518, v2.13.16) detect_operator_grade : telco header-enrichment (MSISDN/x-acr), consortium (Utiq/TrustPid), data-broker / state-adjacent (LiveRamp/BlueKai/Acxiom/ Neustar/Tapad/Experian/Palantir-class). Top-severity void-purple lens + PDF section. `secubox-toolbox 2.6.7`. ### ✅ Phase 13 — protection enforcement plane (#519) COMPLETE Le plan de bannissement (Vortex DNS + WAF + CrowdSec) enforce maintenant sur le browsing des appareils, à tous les niveaux egress. | Track | Issue | Livré | Tag | |---|---|---|---| | 13.A spine | #521 | nft set `inet secubox_blacklist` + forward-drop chain ; sync CrowdSec+threat-intel | v2.13.17 (2.6.8) | | 13.B DNS-guard | #522 | résout domaines blocklistés → IPs (anti-DoH bypass) + détection DoH/DoT count-only | v2.13.17 (2.6.9) | | 13.C attribution | #524 | per-device (WG/lease hash) blocked-attempts + quarantine set + endpoints | v2.13.18 (2.6.10) | | 13.D feedback | #527 | escalation evaluator (detections→nft/cscli/quarantine), audit-log, **default OFF** | v2.13.19 (2.6.11) | **Doctrine** : DEFAULT DROP préservé (policy accept n'ajoute que des drops) ; pas de WAF bypass ; anonyme (mac_hash sel rotatif) ; tout réversible (TTL + unban) ; escalade opt-in par source. **Bug latent corrigé (#521)** : `override_dh_strip` ne tourne jamais pour un paquet `Architecture: all` → tous les drop-ins nft/unbound/nginx/perf avaient cessé de shipper (cause racine de la live-config-drift). Déplacé vers `execute_after_dh_auto_install`. Mémoire ajoutée. ### 💡 Idée future capturée (#525) Phase 14 « plan de déception » : au lieu de bloquer les IPs trackers, générer des pseudo-réponses proxy (indistinguable du drop, pollue le profil) ; idem neutraliser les scripts CDN préchargés. Pour plus tard. ### 🧹 État du dépôt Toutes les branches Phase 11/12/13 mergées + supprimées sur origin. master @ `v2.13.19` (`secubox-toolbox 2.6.11`). Worktrees Phase 11-13 nettoyés. (Worktrees plus anciens #429/#485/#486/#490/#494/#495/#498 + license = travail parallèle, non touchés.) ### ⬜ Next up - **Phase 13 opt-in tuning** : activer les sources d'escalade (env `SECUBOX_ESCALATE_*`) selon politique opérateur quand voulu. - **threatfox feed = 0 IOCs** : investiguer pourquoi l'ingestion domain est vide (impacte 13.B resolved_domains). - **Phase 14 déception** (#525) quand prêt. --- ## 🔄 2026-06-10 (soir) : Phase 11 COMPLETE + Phase 12.A/B + toolbox tabs — merged v2.13.15 (ref #502-#516) Tout le stack Phase 11 + Phase 12.A/B mergé en une PR consolidée (#517), `secubox-toolbox 2.5.2 → 2.6.6`, tag **v2.13.15**. ### ✅ Done — mergé master | Issue | Livré | Version | |---|---|---| | #505 11.A backend | correlation engine + SQLite + /social API | 2.6.0 | | #507 11.B frontend | d3 graph + i18n FR/EN + favicon proxy + wipe + /social/me | 2.6.1 | | #513 toolbox tabs | 5-tab WebUI, kbin /admin/ inline UI supprimé | 2.6.2 | | #508 11.C evidence | consent-probe + PDF bilingue FR/EN | 2.6.3 | | #515 12.A CDN | detect_cdn + Round-Eye central-hotspot graph | 2.6.4 | | #516 12.B anti-bot | detect_antibot + ring levels visibles + Carto/Reset | 2.6.5/2.6.6 | ### ✅ Phase 11 — social mapping per device (#502) Live : `https://kbin.gk2.secubox.in/social/me` (🕸️ Ma carto). Graphe Round-Eye : l'appareil = œil central pulsant, sites sur anneau interne (forceRadial 0.9), trackers anneau externe. Montre le relais ad-tech `35.214.136.108` reliant 360yield + seedtag + smartadserver + smilewanted. PDF d'évidence bilingue (consentement RGPD art. 6.1.a+7, transferts hors-UE art. 44). Effacement RGPD art. 17. Anonyme (mac_hash sel rotatif 24h, aucune valeur cookie brute). ### ✅ Phase 12 — anti-human-detection platform (#514) - **12.A CDN** : detect_cdn (Cloudflare/Fastly/Akamai/CloudFront/Google/ Vercel/Netlify/Bunny/KeyCDN/Sucuri/Imperva). Nodes teintés par vendor, table social_host_meta, agrégat by_cdn. - **12.B anti-bot** : detect_antibot (reCAPTCHA/hCaptcha/Turnstile/ Datadome/PerimeterX-HUMAN/Arkose/Kasada/Akamai-BotManager). Lens cinnabar sévère + ring d'alerte + bannière "challenged your humanity". Table social_antibot per-client, agrégat by_antibot. **Bypass NON livré** — gated derrière doctrine (séquencement #514). - **Ring levels visibles** : forceRadial dominant + guides d'anneau + cache-bust ?v=264b (le user ne voyait pas la réorg ; corrigé). - **Outils opérateur Clients tab** : 🕸️ Carto (ouvre le graphe client via token, redirige vers kbin absolu), ↺ Reset/RAZ (efface social + events + score). ### ⚠️ Round Eye gadget — diagnostic, fix physique requis OTG USB CDC-Ethernet **TX queue wedged** (NETDEV WATCHDOG timeout sur 3-1.1.2). Le gadget énumère (descripteurs lisibles) mais le data path TX est mort — control transfers OK, bulk KO. Recovery gk2 épuisée (link bounce, unbind/rebind → probe error -110). **Power-cycle du Pi Zero ou re-seat câble OTG nécessaire** ; self-heal au prochain boot propre via la règle systemd .link. ### ⬜ Next up - **Phase 12.C** (#514) : opérateur-grade / state-adjacent (étend #500 Utiq). Détection identité carrier-grade + analytics state-adjacent. - **Phase 12.B bypass + 12.D noise** : derniers, chacun gated par sa doctrine + design review (interférence active 3rd-party = R3 opt-in). - **Round Eye** : reprendre côté gk2 dès que le Pi re-énumère propre. --- ## 🔄 2026-06-10 : Phase 11 social mapping (A+B) + system triage round (ref #502-#509) Grosse journée : Phase 11 social mapping shippé jusqu'au frontend live, puis une cascade de fixes système découverts par l'utilisateur en production sur gk2. ### ✅ Done — Phase 11 social mapping (#502 parent) | Issue | Phase | État | |---|---|---| | #505 / PR #506 | **11.A backend** : correlation engine + SQLite + API | ✅ mergeable, déployé live `secubox-toolbox 2.6.0` | | #507 | **11.B frontend** : d3 graph + i18n FR/EN + favicon proxy + wipe modal | ✅ déployé live `2.6.1`, branche poussée | | #508 | **11.C evidence + PDF** | 🔄 WIP checkpoint `55626e51` (schema + GeoIP fold + evidence helper) | **Design** : 2 rounds de design lock sur #502 (Gemini + GPT mockups), edge-thickness + animated-pulse + tracker bottom-sheet + 3s wipe countdown verrouillés. **Live URL** : `https://kbin.gk2.secubox.in/social/me` (splash → 🕸️ Ma carto). Le graphe montre les trackers cross-site réels (relais ad-tech `35.214.136.108` reliant 360yield + seedtag + smartadserver + smilewanted). **Fixes live-deploy critiques découverts** : - `social_graph.py` : `from . import local_store` ne résolvait jamais (mitmproxy charge les addons en top-level) → inliné le WG peer hash. - **PYTHONPATH manquant dans le launcher mitm-wg** : TOUS les addons (`inject_banner` dpi/geo/store, `social_graph`) avaient leurs `from secubox_toolbox import …` silencieusement dégradés. Fix global. - i18n déplacé de `data-*` attr vers `