Commit Graph

2990 Commits

Author SHA1 Message Date
e8a6058488 fix(toolbox): off-bypass via named set @rlevel_off dans la chaîne fanout (return same-chain — table séparée ne bloquait pas le DNAT)
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 15:42:30 +02:00
78ccae7b58 feat(toolbox): sbxmitm-policyctl (atomic peer-rlevel.json + nft off-bypass regen + audit)
Root-scoped ctl for the per-peer wg-toolbox MITM R-level policy (task 4 of
the rlevel-per-peer plan): set-floor/force/set-chosen/set-default/list.
Shadow-write + atomic rename of peer-rlevel.json (the rename itself is the
hot-reload signal the Go workers poll for), server-side clamp of set-chosen
to the peer's floor, regeneration of the nft off-bypass drop-in from peers
whose effective mode is off (one priority below the toolbox DNAT fanout),
and an append-only JSON audit line per mutation. Invalid mode or unknown
pubkey aborts before any write.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 15:23:03 +02:00
a441fdb50c feat(toolbox-ng): per-peer clamp wired into Decide (decideForPeer, both accept paths)
Both sbxmitm accept paths (CONNECT/handleConnect and transparent/
handleTransparent) now go through a single decideForPeer(clientIP, host, sni)
helper: it calls the existing px.pol.Decide, then clamps the verdict to the
calling peer's R-level via px.rlevel.ModeForIP + clampVerdict when a
PeerPolicy is wired in. Factoring both call-sites onto the same helper means
they can never drift on how the clamp is applied.

Proxy gains an rlevel *PeerPolicy field, loaded in main() from
SECUBOX_PEER_RLEVEL / SECUBOX_WG_PEERS (env-overridable, falling back to
peer-rlevel.json and machash.go's wgPeersPath). A nil rlevel is a total
no-op — every Proxy built without it (existing suite, CONNECT PoC) keeps
today's exact px.pol.Decide behavior.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 15:13:09 +02:00
fd4bcb5c45 feat(toolbox-ng): PeerPolicy loader (peer-rlevel.json + ip→pubkey join, hot-reload, fail-safe passive)
Joins peer-rlevel.json (pubkey -> {chosen,forced,floor}) with wg-peers.json
(pubkey -> ip) into an ip -> RLevel map. ModeForIP resolves an unknown IP to
the file's declared defaults, and any unreadable/corrupt input degrades to
Passive for every peer (fail-closed). Hot-reloads both files on mtime change,
mirroring the reload.Watcher pattern already used by policy.go.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 15:05:47 +02:00
f43c408b5e feat(toolbox-ng): rlevel effective() + clampVerdict() (off/passive/active/reel)
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 15:00:25 +02:00
f38d388d1c docs(toolbox): plan d'implémentation R-level par peer (8 tâches, grounded sbxmitm)
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 14:58:56 +02:00
328e102307 docs(toolbox): design R-level MITM par peer wg-toolbox (4 modes, self-service borné + override admin)
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 14:52:25 +02:00
750a7b7c69 docs(plan): PAC .onion -> Tor (secubox-tor) — 4 tâches TDD + recette manuelle
Some checks are pending
License Headers / check (push) Waiting to run
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 08:42:08 +02:00
4e1d3b5d6d docs(spec): PAC auto-routing .onion → Tor (secubox-tor)
PAC qui dévie les .onion vers le SOCKS Tor local (SOCKS5 = remote DNS, Tor
résout le .onion), tout le reste en DIRECT (le transparent wg-toolbox inspecte
déjà). SOCKS confiné sur 192.168.1.200:9050 (SocksPolicy accept LAN+wg reject *,
jamais open-relay). Servi par nginx en application/x-ns-proxy-autoconfig,
LAN-only. Prérequis signalé : tor est inactive/failed sur le board, le plan doit
le réparer avant de livrer une pièce morte.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 08:38:12 +02:00
github-actions[bot]
eaa3fdb1fa ci: Update metrics [skip ci] 2026-07-24 06:07:58 +00:00
35967f698e docs(todo): frigate (bloqué podman-in-LXC) + hexo (non-LXC) — intégration webui différée
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 08:04:04 +02:00
e79343c67c feat(picobrew): page admin = cockpit supervision + accès (au lieu de l'iframe pleine page)
L'UI réelle de picobrew_pico vit sur son sous-domaine LAN-confiné
(picobrew.gk2, avec zoom), donc une iframe pleine page dans la page admin était
redondante. La page admin devient un cockpit de supervision :
- contrôle : démarrer / arrêter / redémarrer / rafraîchir ;
- cartes statut : état, version figée, session, mémoire du conteneur ;
- bloc « accès distant » : lien Ouvrir vers l'interface complète, adresse LAN
  directe, note mode zoom, redirection DNS de l'appareil ;
- journal picobrew_pico (tail du conteneur).

ctl : status --json expose mem_mb (best-effort cgroup, toujours un entier pour
ne pas casser le JSON) ; nouveau verbe restart (stop+start ; la garde de session
ne concerne que update). API : routes /restart et /logs (dégradation propre
conteneur à l'arrêt). Sudoers inchangé (tout picobrewctl déjà accordé).

Vérifié live : status mem_mb=88, /logs rend le vrai journal, panel sans iframe.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 07:46:58 +02:00
947df7e058 feat(sbxmitm): proxifier l'upgrade WebSocket dans les flux MITM'd (fix wss via wg-toolbox)
Le pipeline MITM sert un flux déchiffré avec un handler manuel (up.Do → resp →
write) : un http.Client ne peut PAS porter un « 101 Switching Protocols », donc
tout wss:// sur un hôte MITM'd traversant wg-toolbox échouait (Socket.IO de
picobrew_pico, zigbee2mqtt, toute app temps-réel). Seuls les hôtes splicés
passaient (leur io.Copy brut portait nativement le WebSocket).

Fix (comme httputil.ReverseProxy) : détecter l'upgrade (Connection: upgrade +
Upgrade: websocket), dialer upstream en forçant http/1.1 (un 101 ne peut pas
rider h2), transmettre le handshake verbatim, relayer le 101, puis piper les
octets bruts bidirectionnellement jusqu'à fermeture. Fait AVANT anonymize/DPI/
inject (un upgrade est un canal de contrôle, pas une requête inspectable ; les
en-têtes Sec-WebSocket-* doivent atteindre upstream intacts). La copie
client→upstream lit le bufio.Reader du pipeline (frames déjà bufferisées),
sinon elles seraient perdues.

dialUChrome gagne un paramètre ALPN (dialUChromeALPN) — un seul call-site — pour
que la voie WS force http/1.1 sans toucher la voie normale (h2 préféré).

Tests : détection (liste de Connection, casse, faux positifs) + relais 101 +
pipe bidirectionnel echo sur un upstream TLS réel. build + vet + suite complète
-race verts, zéro régression.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 07:46:58 +02:00
github-actions[bot]
d8c1697233 ci: Update metrics [skip ci] 2026-07-24 05:43:17 +00:00
e287389138 feat(picobrew): panel embarque l'UI complète picobrew_pico (iframe) + bandeau de contrôle
Some checks are pending
License Headers / check (push) Waiting to run
Webui admin la plus complète possible sans dev : bandeau de contrôle SecuBox
(état + start/stop/rafraîchir + plein écran) au-dessus d'un iframe de l'UI
complète de picobrew_pico, servie via son sous-domaine LAN-confiné
picobrew.gk2.secubox.in (même domaine parent → cert wildcard valide, pas de
mixed-content). L'iframe n'est chargée que conteneur en marche.

Réf. montage vhost (live gk2, patron lyrion) : sous-domaine LAN-only
(snippet exposure allow-privé/deny-all) → nginx:9080 → LXC:80, TLS terminée
par HAProxy, route dans /etc/secubox/waf/haproxy-routes.json, upgrade WebSocket
(Upgrade/Connection comme spiderfoot). CAVEAT: un wss:// via wg-toolbox échoue
tant que sbxmitm ne pipe pas l'upgrade WebSocket dans un flux MITM'd (général,
pas spécifique picobrew).

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 07:02:36 +02:00
1208374a9a feat(picobrew): installer active l'appareil (provision oneshot --no-block) + guideline
« apt install secubox-picobrew » provisionne désormais le conteneur tout seul :
nouveau service oneshot secubox-picobrew-provision.service qui lance
`picobrewctl install` (debootstrap + clone picobrew_pico + venv + nginx/TLS),
démarré --no-block par le postinst (dpkg rend la main en ~40s, pas 5-8 min) et
gardé par ConditionPathExists=!pinned-sha (provisionne une fois, no-op ensuite).

Prouvé live sur gk2 : reset LXC → dpkg -i 2.0.1 → auto-provision en arrière-plan
→ LXC RUNNING 10.100.0.150, panel 200, /api/v1/picobrew/status JSON, appareil
:80 et TLS :443 à 200. Le webui est bien le frontend de picobrewctl via l'API.

Documente le motif comme guideline recommandée (.claude/MODULE-COMPLIANCE.md,
section « Install activates — LXC / external-service modules ») : install =
activation complète, provisionnement lourd en oneshot --no-block gardé par
marqueur, contrat ctl install (idempotent, pin-not-float, marqueur au succès
seul), et le piège de routage gk2 (webui.conf exact-match ne charge pas
secubox.d → module à socket dédié = location explicite modèle waf). Réf :
secubox-picobrew.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-24 06:45:51 +02:00
github-actions[bot]
f3697a9508 ci: Update metrics [skip ci] 2026-07-23 21:42:33 +00:00
9b45487da7 feat(picobrew): panel hybrid-dark avec navbar + toasts + lien appliance
Réécrit le panneau selon le look management par défaut du dépôt
(hybrid-dark, Courier Prime, sidebar via /shared/sidebar.js), au lieu du
squelette minimal C3BOX. Ajoute des toasts d'action (échec start/stop plus
silencieux), vérifie response.ok, et un lien vers l'interface réelle de
l'appareil (https://<ip>/) affiché quand le conteneur tourne.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 21:41:31 +02:00
1dfcb66fa5 fix(picobrew): postinst — unbound-control reload charge le drop-in, pas SIGHUP
Découvert à l'installation live sur gk2 : `systemctl reload unbound` (SIGHUP)
ne recharge PAS les local-zone d'unbound — le drop-in picobrew.com n'était donc
jamais appliqué avant un restart. Préférer `unbound-control reload` quand il est
configuré, sinon try-restart, sinon reload en dernier recours (best-effort).

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 21:20:45 +02:00
CyberMind
7dd2f6217b
Merge pull request #899 from CyberMind-FR/feat/picobrew-phase1-lxc
feat(picobrew): phase 1 — LXC qui redonne vie à l'appareil PicoBrew
2026-07-23 21:13:52 +02:00
29989e16d5 fix(picobrew): final branch-review fixes (C2-C5, I1-I8, mineurs)
C2: fix IP collision — picobrew's 10.100.0.140 is already used by
secubox-frigate on br-lxc (verified /data/lxc/frigate/config); reassign to
10.100.0.150 everywhere (ctl, unbound drop-in, tests, specs/plans docs).

C3: postinst no longer aborts under set -e when the unit is masked
(unmask before enable, tolerate failure like the start line already does).

C4: drop ReadWritePaths=/sys/bus/w1 from the unit — the path doesn't exist
on the board and phase 1 ships no sensor controller (preserved untouched in
lib/stillwatch/); no other sensor paths were present to remove.

C5: run the API as User=secubox/Group=secubox instead of root, matching the
sudoers grant (secubox -> picobrewctl) and the repo's single-privileged-
surface rule; drop the now-pointless ExecStartPost socket chown/chmod;
NoNewPrivileges=no kept and documented (required for sudo to work). No
shared parent (/run/secubox, /etc/secubox, /var/log/secubox) is touched.

I1: prerm no longer removes the nginx conffile on upgrade (only
remove/purge), so an upgrade keeps the API/panel route alive.

I2: /status, /start, /stop become plain `def` handlers — they call the
synchronous, blocking `_ctl` (subprocess.run, 20s timeout) and must not run
on the async event loop.

I3: add python3-fastapi | python3-pip to Depends (api/main.py imports
fastapi directly).

I4: drop ConditionArchitecture=arm64 and the stale 1-Wire/I2C sensor
comment — phase 1 is a sensor-less LXC appliance, nothing arch-specific.

I5/I6: rewrite debian/control's Description and README.md to describe what
phase 1 actually ships (LXC-hosted picobrew_pico server + DNS rewrite +
panel), moving fermentation/sensor tracking to "later phase, not shipped".

I7: panel now links to the real PicoBrew interface (https://<lxc-ip>/),
shown only while the container is running.

I8: document in the plan's manual verification recipe that LAN -> br-lxc
forwarding (default-DROP nftables) must be checked before the first real
device test, since that test is also the first test of that network path.

Mineurs: panel act()/load() gain try/catch and response.ok checks with
visible error feedback (previously implemented alongside C1, already
committed: argv fix + guard test, _wait_running polling loop replacing the
fixed `sleep 3` in cmd_install, cmd_status validating the pinned SHA before
emitting it, and a comment documenting PICOBREW_SESSION_FILE as test-only).
2026-07-23 19:23:50 +02:00
a345c8ad0d fix(picobrew): correct argv shift breaking update + guard test
`cmd_update` called `lxc_attach '<script>' _ "$sha"` on top of `lxc_attach`'s
own internal `sh -c "$cmd" _ "$@"` framing, shifting the SHA one position to
the right. The remote script's `$1` landed on the literal `_` placeholder
instead of the SHA, so `git fetch --depth 1 origin "$1"` always failed and
`update` could never work.

Adds a discriminating test that fakes lxc-attach/lxc-info/id in PATH to
capture the real argv delivered to the remote `sh -c` invocation and assert
the SHA lands on $1. Verified to fail when the superfluous `_` is
reintroduced (see final-fixes-report.md for the captured failure).
2026-07-23 19:20:06 +02:00
25d6e69e9f feat(picobrew): packaging phase 1 — sudoers, ctl, drop-in DNS, postinst durci 2026-07-23 19:03:04 +02:00
c1e03fa052 fix(picobrew): nginx enable --now no-op on active preset unit blocks TLS + :80 bind (ref #8)
debootstrap ships nginx with an auto-enabled systemd preset, so on a fresh
LXC nginx is already active (default vhost, listen 80) before cmd_install
writes the TLS config. `systemctl enable --now` is a no-op on an already
active unit: the new 443 config never loads, and nginx keeps holding :80,
which then makes picobrew.service (Flask) fail to bind. Replace with
`systemctl enable nginx && systemctl restart nginx`, which covers both the
stopped and already-active cases. nginx -t still gates activation and the
existing failure handling is unchanged.
2026-07-23 18:58:56 +02:00
bde53fb05d feat(picobrew): terminaison TLS dans le LXC pour la série Z 2026-07-23 18:51:09 +02:00
84ba6afeac feat(picobrew): panel — état du LXC, version figée, actions 2026-07-23 18:47:00 +02:00
00b2291023 feat(picobrew): drop-in DNS Unbound redirigeant picobrew.com vers le LXC 2026-07-23 18:42:34 +02:00
5cfcdfde53 feat(picobrew): update explicite, refusé pendant une session de brassage 2026-07-23 18:38:13 +02:00
28d526c9de feat(picobrew): install — LXC Debian, picobrew_pico en venv, SHA figé 2026-07-23 18:31:01 +02:00
0668268608 feat(picobrew): génération testable de la config LXC 2026-07-23 18:27:06 +02:00
282a2dc637 docs(picobrew): consigner le hash du commit correctif dans le rapport tâche 2 2026-07-23 18:22:50 +02:00
b2163fb3ca fix(picobrew): tests _ctl→OS pour argv sudo, dégradation OS et garde JSON (ref revue tâche 2)
Les 3 tests existants patchaient api.main._ctl en entier : le corps de
_ctl (argv sudo exact, try/except OSError/SubprocessError, garde
JSONDecodeError) n'était jamais exécuté. Ajoute 5 tests qui patchent
subprocess.run à la place, chacun vérifié discriminant en cassant puis
restaurant temporairement api/main.py (sudo/-n retiré, try/except
retiré, garde JSON retirée) — preuves dans .superpowers/sdd/task-2-report.md.
api/main.py inchangé.
2026-07-23 18:22:25 +02:00
391612bb7d feat(picobrew): API de gestion déléguant au ctl; contrôleur capteurs préservé pour la phase 2 2026-07-23 18:14:03 +02:00
6f327afea1 feat(picobrew): picobrewctl — squelette, validateurs et status 2026-07-23 18:07:36 +02:00
a70ca89fa0 fix(plan): tâche 8 — nginx ne doit pas écouter sur :80 (boucle sur lui-même)
Revue pré-vol : la config nginx faisait écouter nginx sur :80 tout en
proxifiant vers 127.0.0.1:80, où Flask écoute déjà. nginx se serait parlé à
lui-même. nginx ne prend que le 443 ; les appareils non-Z joignent Flask
directement en :80.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 18:06:14 +02:00
89025c9313 docs(plan): secubox-picobrew phase 1 — LXC + picobrew_pico + DNS + TLS + panel
Some checks are pending
License Headers / check (push) Waiting to run
Plan d'implémentation de la phase 1 de la spec : 9 tâches TDD, 46 étapes.

Le provisionnement réel (debootstrap, root, réseau) n'étant pas testable en
unitaire, les parties décidables sont isolées derrière des entrypoints cachés
testables : __guard (validateur de SHA), __emit-config (config LXC) et
__emit-nginx (terminaison TLS). Le reste est couvert par une recette de
vérification manuelle explicite plutôt que par de faux tests.

Auto-revue : écart trouvé et corrigé — la spec place le TLS série Z en phase 1
alors que le plan le renvoyait hors périmètre ; or la série Z n'accepte que
HTTPS, un appareil Z aurait donc été inutilisable. Tâche 8 ajoutée.

Le contrôleur de capteurs (992 lignes) est déplacé intact dans lib/stillwatch/
plutôt que supprimé : la phase 2 le reprendra sans archéologie git.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 18:03:47 +02:00
58166f02d0 docs(spec): secubox-picobrew — suite brassage/fermentation/distillation en LXC
Réaligne le paquet Debian (squelette hôte : 992 lignes de contrôleur de
fermentation à capteurs, aucun LXC) sur l'intention du portage OpenWrt, SANS
jeter l'existant : le contrôleur déménage dans le LXC et devient sbx-stillwatch,
étendu à la distillation.

Décisions : LXC Debian natif (pas Alpine, pas Docker) ; upstream picobrew_pico
(Pico S/C/Pro + Z + Zymatic) plutôt que le fork CyberMind limité au Zymatic ;
clone GitHub latest puis SHA figé, update explicite refusé pendant une session
(un changement upstream en plein brassage est inacceptable) ; drop-in DNS
picobrew.com actif par défaut, le cloud constructeur étant éteint depuis 2020 ;
héberger l'éprouvé (CraftBeerPi 4) et n'écrire que le manquant.

Limite de conception posée : stillwatch surveille et guide la distillation mais
n'actionne pas d'alambic — les coupes têtes/coeur/queues sont matérialisées et
tracées, la décision reste humaine. cuts.py est une fonction pure, testable sans
matériel.

Livraison en 3 phases utilisables seules, avec porte de réévaluation YAGNI sur
CraftBeerPi en phase 3. LXC alloué en 10.100.0.140 (motif appliances 1x0).

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 16:55:11 +02:00
e45c9690c9 docs(todo): pixels de suivi email (spec validé, plan différé) + anomalie rspamd non câblé
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 13:23:22 +02:00
fc8e0f9dc2 docs(spec): détection des pixels de suivi (web + email) — design validé
Neutralisation des pixels traceurs dans les emails entrants, en deux couches :
réécriture à la réception (data: URI 1x1 inline, zéro requête émise) avec
archivage du brut DKIM-intact, plus le filet MITM existant à l'ouverture.

Décisions actées : heuristique conservatrice (invisible OU domaine/chemin
connu), aucune réconciliation des compteurs entre couches, intégrité du
courrier non négociable (toute exception => remise de l'original intact).

Deux trous comblés en auto-revue : emplacement/déploiement du code (LXC mail,
pas l'hôte) et synchronisation hôte->LXC de learned-trackers.txt, sans laquelle
le partage de la liste entre couches était illusoire.

Signale au passage une anomalie hors périmètre : rspamd tourne mais n'est
câblé dans aucun milter Postfix (smtpd_milters vide) => ne filtre rien.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 13:14:11 +02:00
188cb278b3 fix(toolbox): NEVER-SPLICE guard — ad networks must never become passthrough
Correctif de fond du #ads affamé : rien n'empêchait autolearn de promouvoir les
régies pub en splice. Or splice = passthrough, et le feed de candidats (#662) ne
se déclenche que sur le chemin allow/mitm ("never the block 204 / splice
paths") — une régie splicée est donc structurellement inobservable, et la boucle
d'apprentissage s'étiole en silence.

Le piège est que les endpoints pub correspondent PARFAITEMENT à l'heuristique de
splice (hits >= SPLICE_MIN_HITS ET html_hits == 0 : ils ne servent jamais de
HTML et sont très sollicités). C'est ainsi que adform/rubicon/google-analytics
et consorts ont atterri dans splice-learned.txt et gelé l'apprentissage 9 jours.

_splice_feed() filtre désormais via _never_splice(), calqué sur le NEVER_LEARN
de #685 : graine des principaux réseaux pub/analytics, vérification sur l'hôte
ET son registrable, extensible par SECUBOX_NEVER_SPLICE sans changement de code.

2 tests (échouent sans la garde) ; 19 tests autolearn/ads passent.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 13:04:46 +02:00
44ae2cad85 fix(toolbox): #ads — show the ad-candidate backlog instead of a false "rien détecté"
L'onglet #ads affichait "aucun tracker/pub détecté dans la fenêtre" alors que
67 hôtes réels (permutive, amplitude, byteintlapi, digiteka…) attendaient leur
promotion en base. Cause : ad_candidates est un BACKLOG (upsert host+site,
promu à AD_MIN_SITES sites distincts), pas une série temporelle — le fenêtrer
à `hours` masque tout dès que l'alimentation se tarit, rendant une boucle
d'apprentissage à l'arrêt invisible au lieu d'évidente.

ad_stats() bascule sur le cumul quand la fenêtre est vide et le signale via
candidates_cumulative ; le panneau l'étiquette explicitement ("cumul — rien de
neuf dans la fenêtre") pour ne pas faire passer un backlog ancien pour de la
détection récente.

Deux tests couvrent le repli et la non-régression du cas fenêtré (le premier
échoue en KeyError sans le correctif).

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 11:17:25 +02:00
github-actions[bot]
9491129467 ci: Update metrics [skip ci] 2026-07-23 07:39:24 +00:00
003bab710f docs: update tracking files (meshtastic v2.15.0, rpi400 image fixes, wiki Support)
HISTORY: entrées datées pour secubox-meshtastic (#897/PR #898/v2.15.0), les
correctifs de l'image rpi400 (deps auth, --kiosk CI, postinst mediaflow
#DEBHELPER#, prompts conffile) et la page wiki Support.

WIP: les deux chantiers passent en  avec leurs follow-ups ; le blocage réseau
du rpi400 est documenté avec les deux pistes de reprise.

TODO: nouvelle section « Afficheurs & appliances » pour les trois sujets mis en
pause (réseau rpi400, reflash round eye, console double écran Pepper's ghost),
avec pour chacun le point de reprise exact.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 09:07:29 +02:00
a08b7e4b12 merge: rpi400 auth runtime deps + --kiosk CI + mediaflow #DEBHELPER# postinst fix
Corrige la cause racine du login cassé sur l'image rpi400 (deps argon2/pyotp/
qrcode jamais tirées à cause de dpkg -i --force-depends), câble --kiosk dans
la CI, et corrige deux bugs latents révélés par l'apt-get strict du kiosk :
le token #DEBHELPER# dans un commentaire du postinst mediaflow (cassait
chaque install) et les prompts conffile non auto-répondus.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-23 09:05:07 +02:00
93e7b0d4c1 docs(wiki): trim Support donation channels to Revolut/Liberapay/GitHub Sponsors
Some checks are pending
License Headers / check (push) Waiting to run
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-22 19:04:17 +02:00
40f0e32baf docs(wiki): add Revolut card-payment link to Support page top
Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-22 19:00:05 +02:00
github-actions[bot]
80a1a031ea ci: Update metrics [skip ci] 2026-07-22 11:58:14 +00:00
cf1c220134 fix(mediaflow,rpi400): postinst #DEBHELPER# comment bug + kiosk conffile prompts
Two failures surfaced by the strict apt-get pass that --kiosk runs in the
rpi chroot (the lenient `dpkg -i --force-depends || true` had been swallowing
the first one on every build):

1. secubox-mediaflow postinst had `#DEBHELPER#` inside a comment. dh_installsystemd
   substitutes that token textually wherever it appears, so it expanded the
   systemd block mid-comment and orphaned "; kick one refresh" onto its own
   line → `syntax error near ';'` → configure fails on EVERY install. Reword
   the comment (real token stays alone on line 22). Bump to ~bookworm3.

2. The kiosk apt-get relied on DEBIAN_FRONTEND=noninteractive, which governs
   debconf, not dpkg's conffile prompt — a pre-existing /etc/secubox/mesh.toml
   triggered an interactive prompt that EOFs on the closed chroot stdin and
   aborted the build. Pass --force-confdef/--force-confold (as the main
   dpkg --configure pass already does) to auto-keep existing conffiles.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-22 13:11:45 +02:00
feda7182ed fix(rpi400): ship auth runtime deps + wire --kiosk through CI
secubox-auth/users crash at import on the rpi400 image because it is built
with `dpkg -i --force-depends` + debootstrap --include, so their declared
Depends (python3-argon2, python3-pyotp, python3-qrcode) are never pulled —
unlike normal apt installs on mochabin. The engine does `from argon2 import
...` / `import pyotp` / `import qrcode`, so the daemon dies at startup →
nginx 502 → no login. Add pyotp+qrcode (pure-Python) to INCLUDE_PKGS and
argon2 via the QEMU-proven pip step (mirroring the cryptography exclusion).

Also expose the kiosk GUI through CI: a `kiosk` workflow_dispatch boolean
→ build-image.sh --kiosk → forwarded to build-rpi-usb.sh, so a rebuilt
rpi400 image can ship the chromium fullscreen dashboard.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-22 11:53:42 +02:00
db0ebe1675 fix(meshtastic): ExecStartPre clears stale socket so the daemon survives restart (ref #897)
Some checks are pending
License Headers / check (push) Waiting to run
uvicorn/uvloop refuses to rebind an existing UDS ('Address already in use') →
crash-loop on restart. ExecStartPre=+/bin/rm -f the socket (root, clears any
owner in the sticky /run/secubox) before ExecStart.

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-22 10:46:56 +02:00