| .mcp | ||
| config | ||
| deploy | ||
| docs | ||
| examples/runtime-pilot | ||
| public | ||
| scripts | ||
| src | ||
| test | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| AGENT_STATUS.md | ||
| AGENTS.md | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
Kordin Lab
Control plane personnel pour publier des expériences, déployer des runtimes et exploiter progressivement des services durables.
- URL :
https://lab.kordin.fr - code :
/srv/apps/lab - données :
/srv/lab - workspace MCP :
lab
Fonctionnalités
- portail privé HTTPS derrière Traefik et Basic Auth ;
- publication atomique d'expériences statiques sous
/<slug>/; - runtimes container bornés, sans port hôte ni volume utilisateur arbitraire ;
- worker hôte restreint, sans socket Docker dans le serveur HTTP ;
- liveness/readiness séparées, health checks, métriques structurées, snapshots de logs et journal runtime rotatif verrouillé ;
- interface privée
/adminavec actions sécurisées ; - déploiements container versionnés, référence d’image immuable et promotion après health check ;
- snapshots Docker mutualisés, maintenance non chevauchante et concurrence bornée ;
- nettoyage prudent des images avec dry-run et protection de l’historique ;
- rollback manuel, ciblé ou automatique ;
- réconciliation de la configuration runtime désirée ;
- pilote Node de référence validant API, préfixe, assets, logs et arrêt propre ;
- rétention configurable des versions, aperçu de nettoyage, suppression bornée et diagnostics d’orphelins ;
- publication statique prévisualisable, bornée et sans suivi de symlinks ;
- exclusions
.labignore, contexte Docker filtré et rétention des backups statiques ; - contrôle-plane révisé avec CAS, verrous interprocessus et journal d’opérations ;
- file administrative FIFO avec quarantaine et déduplication ;
- transitions static/container/remove explicites et récupérables ;
- modèle canonique
Projectrétrocompatible avec profilsexperiment,serviceetworker; - fiches opérationnelles Project avec états, preuves, releases et inconnues explicites ;
- intégration de services externes en lecture seule, avec PixDrop comme premier service durable ;
- observation Docker/HTTP/TLS/stockage/SQLite/Android sans mutation ;
- contrats de données stricts avec criticité, propriétaire, dépendances et reconstructibilité ;
- observations filesystem et SQLite expurgées, fraîches et purement en lecture seule ;
- exigences déclaratives de sauvegarde, restauration et compatibilité de rollback ;
- politiques de sauvegarde versionnées avec fréquence, rétention, destination logique et vérification ;
- runner Restic hôte borné pour médias et SQLite cohérent, avec vérification, rétention et artefacts restaurables ;
- attestations Ed25519 obligatoires pour qualifier une preuve comme
protected; - exercices de restauration isolés avec sandbox, budgets, contrôles filesystem/SQLite et nettoyage ;
- scénario combiné PixDrop implémenté avec cohérence catalogue/médias, candidate isolée et rapport expurgé ; preuve réelle hôte encore requise avant clôture du Lot 5C ;
- contrats de migration par release et gates avant Docker pour déploiement, rollback manuel, réconciliation et rollback automatique ;
- snapshots immuables de compatibilité dans chaque version et refus prudent des versions historiques sans politique ;
- cockpit affichant schéma observé, matrice de releases et raisons exactes des rollbacks bloqués ;
- PixDrop volontairement
blockedtant que ses vraies releases compatibles avec le schéma 5 ne sont pas déclarées ; - assistant opérationnel en lecture seule fondé uniquement sur les preuves Project expurgées ;
- synthèse déterministe toujours disponible et Ollama optionnel avec JSON Schema, timeout, citations et fallback ;
- faits et résumé conservés déterministes même lorsque le modèle enrichit les hypothèses et recommandations ;
- aucun outil LLM, aucune mutation, aucun accès Docker, shell, SSH, secret, volume de production ou file administrative ;
- cockpit mobile avec questions par projet, citations consultables et mode de réponse explicite ;
- shell
/adminmobile-first à vues exclusives : overview, projets, assistant et activité ; - listes compactes, recherche/filtres, actions repliées et fiches projet en accordéons plein écran sur téléphone ;
- événements et diagnostics séparés au lieu d’une page monolithique interminable ;
- états
protected,attention,unknown,ready,blocked,passedetfailedsans faux succès ; - moteur de capacités Project strictement default-deny ;
- politiques prospectives, par profil et surcharges complètes par projet ;
- approbations courtes, exactes et consommables une seule fois ;
- revalidation des mutations dans l’API, le worker, la CLI et le wrapper hôte ;
- commande
diagnoseproduisant un bundle partageable sans secrets, logs bruts ni chemins internes ; - projection v3 sans mutation et migration v4 prévisualisable, sauvegardée et idempotente ;
- configuration typée unique avec version et empreinte de politique ;
- reverse proxy filtré, limites 400/413/504 et abandon upstream ;
- service statique HEAD/Range/ETag/MIME/cache ;
- en-têtes de sécurité et container Lab read-only sans capabilities.
Approbations des mutations
Inspecter la matrice effective :
node dist/src/cli.js project capabilities <slug>
Créer un jeton à usage unique :
node dist/src/cli.js project approve <slug> <action>
Puis transmettre son UUID uniquement au processus de mutation via LAB_PROJECT_APPROVAL_ID. Les wrappers hôte créent et injectent automatiquement ce jeton. Les dry-runs restent disponibles sans approbation lorsqu’ils ne modifient rien.
PixDrop autorise view, diagnose, observe et status. Les seules mutations de données ouvertes dans le checkpoint sont backup et restore-exercise, toutes deux avec approbation à usage unique liée à la politique ou à l’exercice exact. restore-production, restore et delete-data restent refusées.
Contrats de données
Lister les contrats expurgés et observer les preuves en lecture seule :
node dist/src/cli.js data list
node dist/src/cli.js data observe pix-drop
PixDrop déclare deux ressources critiques : la bibliothèque média et le catalogue SQLite. Leur présence, lisibilité, sentinel, intégrité et schéma sont observés sans exposer les chemins hôte.
Les exigences backup: required et restore: required ne signifient pas encore qu’une sauvegarde ou restauration a été prouvée. Les capacités backup, restore et delete-data restent deny jusqu’aux lots suivants.
Politiques de sauvegarde
Lister les politiques validées et évaluer les preuves externes disponibles :
node dist/src/cli.js backup list
node dist/src/cli.js backup evaluate pix-drop
PixDrop déclare une politique quotidienne pour les médias et une politique toutes les douze heures pour le catalogue. Les deux exigent une destination secondaire, une rétention multi-échelle et une vérification.
Le checkpoint contient désormais un runner hôte déterministe. Une preuve n’est qualifiée protected que si le runner a exécuté la politique, vérifié la sauvegarde, appliqué la rétention et produit une attestation Ed25519 valide. La présence du code ne prouve pas encore que le repository secondaire de production est configuré ou qu’une sauvegarde réelle a réussi : tant que cette exécution n’est pas faite, l’état réel reste unknown ou blocked.
Commandes ajoutées :
node dist/src/cli.js backup run pix-drop media-daily manual
node dist/src/cli.js backup run pix-drop catalogue-daily manual
node dist/src/cli.js restore list
node dist/src/cli.js restore evaluate pix-drop
node dist/src/cli.js restore exercise pix-drop <exercise-id>
Les exécutions manuelles exigent une approbation ciblée. Les timers systemd utilisent une identité planifiée dédiée. Le scénario combiné est déclaré sous l’identifiant pixdrop-media-catalogue et se lance par la même commande restore exercise ; son exécution réelle doit encore réussir avant clôture du Lot 5C.
Gates de migration et rollback
Inspecter les contrats et simuler les décisions sans mutation :
node dist/src/cli.js migration list
node dist/src/cli.js migration inspect [slug]
node dist/src/cli.js migration gate-deploy <slug> <image>
node dist/src/cli.js migration gate-rollback <slug> [version]
Un projet sans ressource persistante sensible conserve le comportement historique. Pour un projet à données, Lab exige un contrat de release exact, une observation de schéma fraîche, une compatibilité de lecture/écriture, les prérequis de sauvegarde et la coexistence nécessaire avant le moindre appel Docker.
Chaque version autorisée mémorise une politique immuable. Une version historique sans cette politique ne devient jamais rétroactivement « compatible ». Les changements réels de schéma restent bloqués jusqu’à livraison d’un exécuteur de migration dédié et de preuves avant/après.
Le contrat PixDrop est volontairement vide : aucune release réelle n’a été inventée. Le panel affiche donc blocked tant que la matrice schéma 5 n’est pas renseignée à partir des vraies images et de leur compatibilité. Voir docs/LOT5D_MIGRATION_ROLLBACK_GATES.md.
Assistant opérationnel local
Le mode déterministe fonctionne sans modèle :
node dist/src/cli.js ai status
node dist/src/cli.js ai ask --project pix-drop --deterministic "Pourquoi PixDrop est-il bloqué ?"
Ollama peut être activé explicitement par configuration hôte. Il reçoit seulement un paquet borné de preuves déjà expurgées et doit retourner un JSON conforme à un schéma fermé, avec citations exactes. Les faits et le résumé publiés restent déterministes ; le modèle peut uniquement enrichir les hypothèses et recommandations citées.
Le cockpit /admin expose la même fonction. Aucune question ou réponse n’est persistée, aucune commande n’est générée, et la route ne crée ni action ni approbation. L’indisponibilité ou la réponse invalide du modèle provoque un fallback déterministe. Voir docs/LAB_AI_01_READONLY_ASSISTANT.md.
Manifeste statique
slug: ants-demo
title: Ants Demo
description: Simulation publiée dans le Lab
visibility: private
source: dist
pnpm run build
node dist/src/cli.js publish ./lab.yml --dry-run
LAB_PROJECT_APPROVAL_ID=<uuid-publish> node dist/src/cli.js publish ./lab.yml
La prévisualisation indique les fichiers inclus, les exclusions et les budgets appliqués. Sont exclus par défaut : lab.yml, .labignore, .git, .mcp, .mcp-tx, node_modules, .env, .env.*, coverage, .cache et *.log.
Un fichier .labignore placé à la racine de source peut ajouter des motifs simples avec *, ** et ?. Les négations ! sont refusées explicitement pour éviter une sémantique ambiguë. Les limites par défaut sont de 10 000 fichiers et 256 Mio ; elles peuvent être remplacées pour la CLI par LAB_STATIC_MAX_FILES et LAB_STATIC_MAX_BYTES.
visibility: unlisted masque l’expérience du portail et de l’API de découverte tout en conservant l’accès direct après Basic Auth. visibility: public est refusé tant que le domaine entier reste protégé par la Basic Auth globale.
Manifeste container
slug: node-demo
title: Node Demo
type: container
visibility: private
profile: experiment
runtime.image: node:24-alpine
runtime.port: 3000
runtime.healthcheck: /health
LAB_PROJECT_APPROVAL_ID=<uuid-publish> node dist/src/cli.js register ./lab.yml
LAB_PROJECT_APPROVAL_ID=<uuid-deploy> node dist/src/cli.js runtime deploy node-demo
node dist/src/cli.js runtime versions node-demo
LAB_PROJECT_APPROVAL_ID=<uuid-rollback> node dist/src/cli.js runtime rollback node-demo
Chaque version est démarrée hors trafic, validée par son health check, puis promue via l'alias réseau stable lab-active-<slug>. La version précédente reste disponible pour rollback. Le rollback automatique applique un seuil configurable, une période de grâce, un cooldown et une quarantaine anti-ping-pong.
Modèle Project
Les expériences existantes sont projetées en projets sans mutation du registre. La migration v4 est explicite :
node dist/src/cli.js project list
node dist/src/cli.js project migrate --dry-run
node dist/src/cli.js project migrate --apply
node dist/src/cli.js project profile node-demo service --dry-run
LAB_PROJECT_APPROVAL_ID=<uuid-change-profile> \
node dist/src/cli.js project profile node-demo service
Les profils disponibles sont experiment, service et worker. Un worker n’expose aucune route HTTP, mais reste administrable. Un profil autre que experiment exige la migration v4 afin que l’intention soit persistée sans ambiguïté.
Runtime Pilot Node
Le pilote réel est disponible sous :
https://lab.kordin.fr/runtime-pilot/
Il fournit :
/runtime-pilot/health;/runtime-pilot/api/info;- une interface et des assets CSS/JS compatibles avec le préfixe ;
- des logs JSON structurés ;
- un arrêt gracieux sur
SIGTERMetSIGINT.
La release désirée est stockée dans examples/runtime-pilot/release-version.txt. La v2 est la release finale active.
LAB_PROJECT_APPROVAL_ID=<uuid-prepare> \
node dist/src/cli.js runtime prepare runtime-pilot
LAB_PROJECT_APPROVAL_ID=<uuid-start> \
node dist/src/cli.js runtime start runtime-pilot
node dist/src/cli.js runtime status runtime-pilot
runtime status runtime-pilot vérifie l'image active, l'API directe, l'API via le reverse proxy Lab et les assets proxifiés.
Commandes principales
node dist/src/cli.js list
node dist/src/cli.js info <slug>
node dist/src/cli.js project list
node dist/src/cli.js project info <slug>
node dist/src/cli.js project capabilities <slug>
node dist/src/cli.js project approve <slug> <action>
node dist/src/cli.js project migrate --dry-run
node dist/src/cli.js project migrate --apply
node dist/src/cli.js project profile <slug> <experiment|service|worker> --dry-run
node dist/src/cli.js project profile <slug> <experiment|service|worker>
node dist/src/cli.js diagnose
node dist/src/cli.js diagnose <slug>
node dist/src/cli.js external list
node dist/src/cli.js external observe [slug]
node dist/src/cli.js data list
node dist/src/cli.js data observe [slug]
node dist/src/cli.js backup list
node dist/src/cli.js backup evaluate [slug]
node dist/src/cli.js backup run <slug> <policy-id> <manual|scheduled>
node dist/src/cli.js restore list
node dist/src/cli.js restore evaluate [slug]
node dist/src/cli.js restore exercise <slug> <exercise-or-scenario-id>
node dist/src/cli.js migration list
node dist/src/cli.js migration inspect [slug]
node dist/src/cli.js migration gate-deploy <slug> <image>
node dist/src/cli.js migration gate-rollback <slug> [version]
node dist/src/cli.js ai status
node dist/src/cli.js ai ask [--project <slug>] [--deterministic] <question>
node dist/src/cli.js runtime pilot-build runtime-pilot <version>
node dist/src/cli.js runtime deploy <slug>
node dist/src/cli.js runtime rollback <slug> [version]
node dist/src/cli.js runtime versions <slug>
node dist/src/cli.js runtime prune <slug> --dry-run
node dist/src/cli.js runtime prune <slug>
node dist/src/cli.js runtime prune-all --dry-run
node dist/src/cli.js runtime image-prune --dry-run
node dist/src/cli.js runtime image-prune --apply
node dist/src/cli.js static prune <slug> --dry-run
node dist/src/cli.js static prune <slug>
node dist/src/cli.js transition <slug> <static|container> <lab.yml> --dry-run
node dist/src/cli.js transition <slug> removed --dry-run
node dist/src/cli.js config
node dist/src/cli.js migrate
node dist/src/cli.js runtime start <slug>
node dist/src/cli.js runtime stop <slug>
node dist/src/cli.js runtime status <slug>
node dist/src/cli.js runtime logs <slug>
node dist/src/cli.js doctor
Le serveur HTTP reverse-proxy les runtimes versionnés par le réseau Docker, mais n'appelle jamais Docker directement.
Documentation :
docs/ARCHITECTURE.mddocs/OPERATIONS.mddocs/ROADMAP.mddocs/design/KORDIN_LAB_TARGET_ROADMAP_CONTROL_PLANE_AI.mddocs/LOT2G4_RESILIENCE_OBSERVABILITY_RECOVERY.mddocs/LOT2G5_SCALABILITY_MAINTAINABILITY.mddocs/LOT3A_PROJECT_MODEL.mddocs/LOT3B_PROJECT_OPERATIONS.mddocs/LOT3C_PIXDROP_READONLY.mddocs/LOT3D_PROJECT_CAPABILITIES.mddocs/LOT5A_DATA_CONTRACTS.mddocs/LOT5B_BACKUP_POLICIES.mddocs/LOT5C_RESTORE_EXERCISES.mddocs/LOT5D_MIGRATION_ROLLBACK_GATES.mddocs/LAB_AI_01_READONLY_ASSISTANT.mddocs/COCKPIT_MOBILE_UX.mddocs/HANDOFF_LAB_AI_01_WIP_2026-07-27.mddocs/HANDOFF_LOT5D_WIP_2026-07-27.mddocs/HANDOFF_LOT5C_COMBINED_WIP_2026-07-27.mddocs/HANDOFF_LOT5C_WIP_2026-07-26.md— historiquedocs/PROMPT_REPRISE_LOT5C_5D_2026-07-26.md— prompt initialdocs/LOT2D_VERSIONED_DEPLOYMENTS.mddocs/LOT2E_NODE_RUNTIME_PILOT.mddocs/LOT2F_RUNTIME_LIFECYCLE.mddocs/audits/AUDIT_LAB_POST_LOT2F_2026-07-09.mddocs/design/PLAN_DIRECTEUR_CORRECTIF_POST_AUDIT_2026-07-09.mddocs/design/VALIDATION_MATRIX_POST_AUDIT_2026-07-09.mddocs/PROMPT_REPRISE_CORRECTIFS_POST_AUDIT_2026-07-09.md