Preserve the local graph-first investigation stack through macro V1. Include reviewed source, tests, contracts, documentation and synthetic assets. Retain the standalone financial V21 test foundation without runtime migration. Runtime remains V20; operational JobStore remains V3. Local experimental checkpoint, not a stable release.
5.2 KiB
Toolkit local et runner borné — lot J4
État :
CURRENTlocal, synthétique, non publié\ Runtime persistant : V20 inchangé\ Contrats de sortie :labfy.local_tool_result.v1,labfy.exiftool.metadata.derivative.v1
Parcours livré
Le registre statique expose deux capacités réellement consommées :
labfy.capability.eml_headers.v1 (NATIVE) et
labfy.capability.exif_metadata.v1 (SUBPROCESS). Le lanceur unique exécute
les deux sur des preuves SPECIMEN, publie en V20, ferme le writer, relit SQLite
en lecture seule et exporte le snapshot v3 :
make -j8 local-toolkit-demo
cd prototypes/web-graph
python3 run_local_toolkit_demo.py --port 8765
L'image reçoit ses métadonnées fictives avant import. L'adapter de production
n'accepte qu'un fichier contrôlé et les options fixes -config "" -j -G1 -n --.
Python ne fabrique ni résultat, ni disponibilité, ni métadonnée de secours.
Registre et disponibilité
Chaque descripteur porte identités/version de capacité, adapter et outil,
intention française, types acceptés/produits, nature, classe PASSIVE, contact
NONE, profil de limites et version du contrat. Les états sont available,
missing, incompatible, unverified et detection_error avec raison.
La sonde ExifTool passe elle-même par le runner (3 s, 16 Kio par flux) et désactive la configuration utilisateur. Le lookup n'analyse aucun fichier. La projection reçoit un registre déjà sondé et ne lance jamais de processus. Le snapshot distingue applicabilité et déclenchement : le prototype HTTP reste read-only et affiche « Exécution par le lanceur local » sur un bouton désactivé.
Runner POSIX borné
local_tool_runner_run() exige un exécutable absolu résolu, un argv séparé et
un répertoire privé. L'enfant crée une session/groupe propre, ferme stdin,
reçoit seulement PATH=/usr/bin:/bin, LANG/LC_ALL=C.UTF-8 et
HOME=/nonexistent, puis applique RLIMIT_CPU, RLIMIT_AS, RLIMIT_FSIZE et
RLIMIT_NOFILE. Aucun shell, profil utilisateur, config personnelle ou fd
inutile ne survit à execve.
Le profil normal est 30 s, grâce 250 ms, CPU 30 s, espace d'adressage 256 Mio,
fichier 4 Mio, 64 fd, stdout 1 Mio et stderr 256 Kio. Le délai monotone couvre
processus et vidange des pipes. Timeout, annulation ou plafond envoient
SIGTERM, puis SIGKILL au seul groupe créé. Le processus directement possédé
est récupéré. Un descendant conservant le pipe est donc borné. Un programme
qui s'échappe volontairement de la session n'est pas confiné par ce mécanisme :
J4 ne prétend pas fournir une sandbox ni une limite mémoire agrégée par cgroup.
Les états distinguent sortie normale, non-zéro, signal, timeout, annulation,
plafond, absence et erreur I/O. stdout/stderr restent des GBytes; chaque flux
porte taille observée, taille conservée, complétude et SHA-256 du préfixe
réellement conservé. Un JSON incomplet n'est jamais parsé.
Le résultat appartient à l'appelant jusqu'à
local_tool_runner_result_free(). Après une erreur d'argument ou système,
aucun résultat partiel ne s'échappe, même avec GError ** == NULL.
Adapter et persistance ExifTool
JSON-GLib parse strictement une racine tableau contenant exactement un objet,
avec au plus 2 048 tags et profondeur 16. Valeurs texte, nombres, booléens,
null et tableaux sont préservés ; les tags inconnus restent inspectables.
Une métadonnée n'atteste ni authenticité ni identité.
Le service recharge l'EvidenceRecord, refuse chemins absolus, .. et liens
symboliques, vérifie taille/SHA-256, analyse une copie privée puis revérifie
l'original. L'artefact privé conserve provenance, paramètres expurgés, version,
stdout base64, hash/tailles/complétude et métadonnées typées. Le snapshot
n'expose aucun chemin absolu ni stderr complet ; il projette source → extraction
→ dérivé et un aperçu borné de champs sûrs avec la référence stable du dérivé.
Le request_id est la clé idempotente : un replay compatible ne relance pas
ExifTool. Une divergence est un conflit ; extraction sans dérivé cohérent est
RECOVERY_REQUIRED. Staging et transaction sont compensés en supprimant
seulement le fichier créé par la tentative. Aucun DDL, osint_execution fictif
ou nouvelle migration n'est introduit.
Ajouter un adapter
- Ajouter un descripteur stable au registre et un profil mesuré.
- Implémenter l'adapter sans GTK/SQLite et sans arguments libres du Web.
- Versionner et borner le format brut/normalisé ; conserver les octets.
- Réutiliser le service de preuve contrôlée et les DAO V20, sans détournement.
- Projeter seulement des données persistées, sans exécution dans le lecteur.
- Ajouter fakes déterministes, outil réel optionnel et tests d'échec/replay.
Limites et suite
Les anciens parcours documentaires n'utilisent pas tous ce runner et ne sont pas déclarés protégés par J4. La provenance J3 reste à généraliser. J5 devra ajouter jobs persistants, leases/reprise, Resource Governor, budgets partagés, policy par tentative et arrêt global. J4 ne livre ni serveur de production, secrets, autonomie réseau, contrôle d'un outil hostile ou reprise après crash.
J4_LOCAL_TOOLKIT_RUNNER = COMPLETE_LOCAL