#!/bin/zsh # ============================================ # KA Guardian — courrier inter-nœuds (100 % zsh) # macOS 26 « Local Network Privacy » refuse le trafic LAN dès que python # (homebrew) est dans la chaîne de processus — même ses enfants ssh/curl. # Ce service launchd (binaire responsable: zsh) expédie donc les requêtes: # spool/outbox/.job → ssh curl http://127.0.0.1: # spool/done/.resp ← corps de réponse + dernière ligne = code HTTP # Format .job: ligne 1 = " ", reste = payload JSON. # ============================================ export PATH=/usr/bin:/bin:/usr/sbin:/sbin # launchd démarre sans PATH SPOOL=$HOME/ka-guardian-spool KEY=$HOME/.ssh/ka_guardian_ed25519 mkdir -p $SPOOL/outbox $SPOOL/done $SPOOL/tmp source $HOME/.ka-guardian.env 2>/dev/null || true while true; do for f in $SPOOL/outbox/*.job(N); do id=${f:t:r} hdr=$(head -1 $f) parts=(${(z)hdr}) # NB: ne JAMAIS nommer une variable `path` en zsh — c'est le tableau # spécial lié à PATH (l'assigner détruit le PATH du process). ip=$parts[1]; port=$parts[2]; jpath=$parts[3]; tmo=${parts[4]:-30} # 3 tentatives: un destinataire qui redémarre ne doit pas perdre le message. rc=1 for attempt in 1 2 3; do tail -n +2 $f | /usr/bin/ssh -i $KEY \ -o StrictHostKeyChecking=accept-new -o BatchMode=yes -o ConnectTimeout=8 \ -o ControlMaster=auto -o ControlPath=/tmp/kg-cm-%h -o ControlPersist=120 \ simon-pierreboucher@$ip \ "/usr/bin/curl -s -m $tmo --retry 2 --retry-connrefused -X POST http://127.0.0.1:$port$jpath -H 'Content-Type: application/json' -H 'X-KA-Token: $KA_GUARDIAN_TOKEN' -d @- -w '\n%{http_code}'" \ > $SPOOL/tmp/$id.resp 2>>$SPOOL/courier.log rc=$? [[ $rc -eq 0 ]] && break sleep 3 done [[ $rc -ne 0 ]] && print "\ncourier_ssh_rc_$rc" >> $SPOOL/tmp/$id.resp mv $SPOOL/tmp/$id.resp $SPOOL/done/$id.resp rm -f $f done # ménage: réponses jamais réclamées depuis > 1 h for old in $SPOOL/done/*.resp(N.mh+1); do rm -f $old; done sleep 1 done