Skip to main content
Welcome. This site supports keyboard navigation and screen readers. Press ? at any time for keyboard shortcuts. Press [ to focus the sidebar, ] to focus the content. High-contrast themes are available via the toolbar.
serard@dev00:~/cv

Versioning, packaging, distribution — NuGet applique au droit

Tout ce qui suit existe deja dans l'ecosysteme NuGet/dotnet. On ne reinvente rien. On applique. L'innovation n'est pas dans l'infrastructure — elle est dans le contenu qui transite par cette infrastructure. Quand un package Law.France2026.Etalab.Dsl est publie sur un registre NuGet, il obeit aux memes regles qu'un package Newtonsoft.Json ou Serilog : SemVer, signature, lockfile, restauration deterministe, sources multiples. La difference est que ce package contient du droit type, pas du code utilitaire. Et cette difference change tout pour le destinataire.

SemVer juridique

Le versioning semantique est une convention tripartite : MAJOR.MINOR.PATCH. Chaque niveau a un sens technique precis dans l'ecosysteme .NET — et ce sens se transpose au droit sans forcer.

Niveau Sens juridique Exemple concret
MAJOR Refonte structurelle, breaking change pour les cas citoyens Nouvelle Constitution, refonte du Code du travail, changement de regime fiscal
MINOR Ajout de nouvelles regles sans casser les existantes Loi qui cree un nouveau droit, ajout d'articles, nouvelle aide sociale
PATCH Correction sans changement de comportement Decret rectificatif, correction materielle, clarification jurisprudentielle
+build Source de la version 1.2.3+legifrance-2026-04-10, 1.2.3+cassation-civ-1-26-01-2026
-pre Loi en discussion 1.3.0-projet-loi-eau-senat, 2.0.0-rc1-refonte-travail

Le MAJOR bump est detecte automatiquement : si au moins un cas citoyen existant compile differemment apres la mise a jour, c'est un MAJOR. Le bridge fournit la commande de diff :

dotnet law-bridge diff Law.France2026.Etalab.1.0.0.dll Law.France2026.Etalab.1.1.0.dll

Cette commande compare les deux assemblies, detecte les changements de types, d'attributs, de diagnostics, et renvoie le bump SemVer requis. Si l'auteur du package a declare un MINOR mais que le diff detecte un breaking change, le build echoue. La meme logique que NerdBank.GitVersioning, transposee au droit.

NuGet packaging — le .csproj d'un cadre juridique

Un cadre juridique publie est un projet .NET standard. Son .csproj contient les memes metadonnees que n'importe quel package NuGet :

// Fichier : Common.France2026.Etalab.Dsl.csproj (extrait des PropertyGroup)
// TargetFramework = netstandard2.0
// PackageId = Common.France2026.Etalab.Dsl
// Version = 1.1.0
// Authors = Etalab — DINUM
// Description = Common.Dsl instance for France 2026 — 142 biens, 36 000 communes, 487 procedures.
// PackageLicenseExpression = Etalab-2.0
// RepositoryUrl = https://git.etalab.gouv.fr/lex/common-france
// RepositoryCommit = a3f9c2e8...
// PackageReleaseNotes = https://lex.france.fr/changelog/Common.France2026.Etalab/1.1.0

La propriete RepositoryCommit est la cle de voute : la version publiee est cryptographiquement liee au commit git source. Quiconque doute du contenu d'un .nupkg peut cloner le depot, checkout le commit, rebuilder, et verifier que le hash correspond. C'est exactement ce que font les distributions Linux reproductibles (Guix, Nix) — transposes au droit.

La signature NuGet X.509 complete le dispositif. Les paquets officiels sont signes par une autorite certifiee ; le client dotnet verifie cette signature a chaque restore. Un paquet non signe ou dont la signature ne correspond pas a l'autorite declaree est rejete. L'infrastructure X.509 est mature, deployee partout dans le monde, et ne necessite aucun developpement specifique.

Le workflow citoyen : dotnet update et ce qui se passe en trente secondes

Mathilde, parent isole, a installe son cadre citoyen il y a six mois. Elle met a jour :

cd MyCases.MathildeMartin
dotnet add package Law.France2026.Etalab.Dsl
dotnet build

Le compilateur repond :

MyCases/MyCase.cs(23,17): warn CIT003: Question "BenefitsIfJobLoss"
  -> ATTENTION : la version 1.1.0 a modifie le calcul du RSA majore
  -> Votre montant change : 1058 EUR/mois -> 1124 EUR/mois (+66 EUR)
  -> Article modifie : L262-9 CASF (PATCH 1.0.0 -> 1.1.0)

Mathilde apprend en trente secondes que son RSA majore augmente de soixante-six euros par mois. Sans appeler la CAF, sans avocat, sans formulaire. Le compilateur lui livre la mise a jour juridique comme npm lui livrerait une mise a jour de bibliotheque. Le diagnostic CIT003 est type (cf. Partie 12 — Les six regimes d'usage), l'article est reference, le delta est calcule par le cadre lui-meme. C'est le sixieme regime d'usage a l'etat pur : le citoyen comme auteur de son propre cas, le compilateur comme guide vers ses droits.

Lockfile cryptographique — reproductibilite parfaite

dotnet restore --use-lock-file genere un packages.lock.json qui fige l'etat exact des dependances :

// packages.lock.json (extrait)
// Law.France2026.Etalab.Dsl :
//   type = Direct
//   requested = [1.1.0, )
//   resolved = 1.1.0
//   contentHash = sha512-7G8Hq...
//   signedBy = CN=Etalab, O=DINUM, C=FR
//   publishedAt = 2026-03-01T10:00:00Z

Ce lockfile garantit deux proprietes essentielles. D'abord la reproductibilite : le meme build cinq ans plus tard avec le meme lockfile produit les memes diagnostics. Ensuite la preuve de temporalite : le hash, la signature et le timestamp constituent une attestation recevable en justice. Quand Mathilde joint son packages.lock.json a un courrier officiel, elle dit : voici les versions exactes du corpus juridique que j'ai consultees, signees par Etalab, a telle date.

Release notes typees — le changelog comme code

Les changelogs classiques sont du texte libre. Les release notes d'un cadre juridique sont du code C# type :

[ReleaseNotes(Version = "1.1.0", PublishedAt = "2026-03-01")]
public sealed class V1_1_0
{
    [BumpReason(SemverImpact.Minor,
        "12 nouveaux articles, 3 nouveaux biens, 0 retrait")]
    public void Summary() { }

    [Added(typeof(SocialHousingLaw2026.ArticleL353_9_2))]
    [SourceJORF("JORF n-0042 du 19 fevrier 2026, NOR: LOGL2604XXX")]
    public void NewCeilingForSocialHousingPLAI() { }

    [Modified(typeof(SocialAndFamilyActionCode.L262_9),
        FromVersion = "1.0.0",
        Effect = "RSA majore pour parent isole : 1058 EUR -> 1124 EUR/mois")]
    [SourceLegislative("LOI n 2026-156 du 15 fevrier 2026, art. 8")]
    public void IncreasedRsaForSingleParent() { }

    [BreakingForCases(
        Reason = "Nouveaux plafonds pour logement social PLAI",
        AffectedCircumstances = new[] {
            typeof(SocialHousingTenant),
            typeof(PLAIHousing)
        })]
    public void BreakingChangeSocialHousing() { }
}

L'attribut [ReleaseNotes] est genere par le Source Generator du cadre. Chaque methode represente un changement individuel, decore par des attributs qui precisent la source legislative ([SourceJORF], [SourceLegislative]), l'impact ([Added], [Modified], [Removed]), et les circonstances citoyennes affectees ([BreakingForCases]). Le tout est filtrable par circonstance : dotnet law-bridge changelog --filter-by ./MyCases.MathildeMartin produit un changelog cible sur la situation de Mathilde. Personne n'a jamais eu ca pour le droit — un changelog legislatif qui ne montre que ce qui concerne votre situation.

Multi-sources NuGet — le pattern PPA Ubuntu applique au droit

Le fichier nuget.config d'un cas citoyen peut lister plusieurs sources :

<!-- nuget.config -->
<configuration>
  <packageSources>
    <add key="lex-etalab"       value="https://lex.france.fr/v3/index.json" />
    <add key="lex-laquadrature" value="https://lex.laquadrature.net/v3/index.json" />
    <add key="lex-cgt"          value="https://lex.cgt.fr/v3/index.json" />
  </packageSources>
</configuration>

C'est le pattern PPA Ubuntu : chaque editeur (Etalab pour l'Etat, LaQuadrature pour les libertes numeriques, la CGT pour le droit du travail) publie ses propres cadres sur son propre registre NuGet. Le citoyen choisit qui il fait confiance en ajoutant ou retirant des sources. Le ConsensusScorer (cf. Partie 12 — Les six regimes d'usage) exhibe automatiquement les divergences entre cadres concurrents portant sur les memes articles.

Ce multi-sourcing est la traduction technique de la pluralite politique des cadres theorisee dans la signature META(Ex x Ty) (cf. Partie 4 — META(Ex x Ty)). Le ${Author} de la signature est concretement l'editeur du registre NuGet. Etalab et LaQuadrature ne sont pas d'accord sur le statut de l'eau potable ? Les deux cadres coexistent, le citoyen les compare, le bridge exhibe les diagnostics divergents. C'est la democratie des cadres, pas l'imposition d'un cadre unique.

Quand le Conseil constitutionnel declare un article non conforme, c'est l'equivalent d'une vulnerabilite de securite dans un package logiciel. Le mecanisme d'advisory juridique s'en inspire directement :

dotnet list package --legally-affected

Project MyCases.MathildeMartin is affected by 2 legal advisories:

  > Law.France2026.Etalab.Dsl 1.0.0
    LEGAL-2026-001 | Critical | Article L262-9 declare non-conforme
                                by Conseil constitutionnel
                                decision n-2026-XX-QPC du 12 mars 2026
                                Action: Update to 1.0.1 or later

Le format est inspire des GitHub Security Advisories, avec une echelle de severite adaptee : Critical (annulation constitutionnelle), High (revirement de jurisprudence majeure), Medium (interpretation administrative), Low (clarification). Un flux RSS d'advisories juridiques est consomme par tous les dotnet build du pays, comme les flux RSS de vulnerabilites CVE sont consommes par tous les npm audit.

Le citoyen qui lance dotnet build sur son cas est prevenu automatiquement quand un article dont il depend a ete invalide. Pas besoin de suivre le Journal officiel, pas besoin de lire les decisions du Conseil constitutionnel en PDF — le compilateur lui livre l'information, typee, avec la reference exacte et l'action requise.

Time-travel queries — git checkout pour le droit

Chaque annee de publication constitue un package distinct. Revenir en arriere est trivial :

dotnet add package Law.France2024.Etalab.Dsl --version 4.7.2
dotnet build
# Diagnostics tels qu'ils auraient ete le 1er janvier 2024

Pour les chercheurs, le time-travel devient un outil de recherche en sciences sociales. Une boucle simple produit une serie temporelle de diagnostics sur un meme cas :

for year in 2010 2012 2014 2016 2018 2020 2022 2024 2026; do
  dotnet add package Law.France${year}.Etalab.Dsl --version ${year}.0.0
  dotnet build > /tmp/case-${year}.json
done

Reproductibilite scientifique du droit — jamais possible auparavant. Un sociologue peut prouver que les droits sociaux de Mathilde ont regresse entre 2014 et 2020, puis progresse entre 2020 et 2026, avec des diagnostics types, reproductibles, versiones, verificables par quiconque relance le meme build.

Pipeline Legifrance vers .nupkg — le cycle quotidien

Le pont entre le droit vivant et les packages types est un pipeline en six etapes :

Legifrance JURI XML feed
  -> LegifranceXmlImporter (lit XML, produit CrossModel)
  -> LawDslEmitter (recrit en C# avec attributs types)
  -> git commit + git tag v1.1.0
  -> dotnet pack Law.France2026.Etalab.Dsl -> .nupkg
  -> Push to lex.france.fr NuGet feed
  -> Notification RSS aux consommateurs

Ce cycle peut tourner quotidiennement. Quand une loi est promulguee et publiee au Journal officiel, le flux XML de Legifrance est consomme par le LegifranceXmlImporter, qui produit un modele intermediaire (CrossModel). Le LawDslEmitter le recrit en classes C# decorees par les attributs du cadre. Un commit et un tag git figent la version ; dotnet pack produit le .nupkg ; le push vers le registre le rend disponible a tous les consommateurs.

C'est aussi le pont concret avec Catala (cf. Partie 3 — Filiation intellectuelle). Catala fait deja ce travail pour le calcul d'impots en collaboration avec la DGFiP. Le bridge Law.Commons peut consommer les memes flux XML, ou meme importer directement les modules Catala via un Catala.Bridge futur (Ship 6-bis de la roadmap).

Architecture du registre — trois niveaux

Le registre des packages juridiques s'organise en trois niveaux, calques sur le modele NuGet existant :

Registre Hebergement Autorite Usage
Officiel : lex.france.fr Etalab / DINUM Etat Common.France*.Etalab.Dsl, Law.France*.Etalab.Dsl
Federations : lex.laquadrature.net, lex.cgt.fr Associations Communaute reconnue Forks, interpretations alternatives
Personnel : ~/.nuget/packages/ local Citoyen Soi-meme Versions epinglees, archives

Le registre officiel est signe par une cle X.509 emise par Etalab, hebergee dans un HSM hors-ligne. Les registres de federations sont signes par leurs propres cles. Le registre personnel est le cache local standard de NuGet — une fois qu'un package est telecharge, il vit indefiniment sur la machine du citoyen.

Aucune de ces trois couches n'est une nouveaute technique. C'est exactement ce que NuGet supporte depuis 2010, ce que npm supporte depuis 2012, ce que les PPA Ubuntu supportent depuis 2004. L'innovation est dans le contenu, pas dans l'infrastructure. Et c'est precisement cette banalite technique qui rend le projet credible : on ne demande a personne d'adopter un nouveau systeme de distribution. On remplit le systeme existant avec du droit type.

Attestation cryptographique — inversion de la charge de la preuve

A chaque dotnet build, le compilateur genere un obj/build-attestation.json signe qui recapitule les dependances, les diagnostics et le hash de l'ensemble :

// obj/build-attestation.json (structure)
// schemaVersion = 1.0
// caseFile = MyCases.MathildeMartin
// builtAt = 2026-04-10T14:23:17Z
// builtBy = { machineFingerprint: did:peer:zQ3sh..., anonymized: true }
// dependencies = [
//   { name: Law.France2026.Etalab.Dsl, version: 1.1.0, hash: sha512-7G8Hq... },
//   { name: Common.France2026.Etalab.Dsl, version: 1.1.0, hash: sha512-9P2Lm... }
// ]
// diagnostics = [
//   { code: CIT001, article: L353-9-2, outcome: RsaMajore active },
//   { code: CIT003, article: L262-9, outcome: 1124 EUR/mois }
// ]
// signature = MEYCIQDx...
// signedBy = CN=MyCases-Tool, O=Self

Mathilde joint cette attestation a un courrier officiel : Selon la version 1.1.0 du corpus juridique francais signee par Etalab, j'ai droit a ces aides — voici la preuve cryptographique. L'agent CAF verifie en cinq secondes en relancant le build. C'est une inversion de la charge de la preuve : l'administration doit refuter l'attestation, pas le citoyen prouver son droit. Aujourd'hui, Mathilde doit prouver qu'elle a droit au RSA majore. Demain, le compilateur le prouve pour elle, et c'est a la CAF de prouver qu'il se trompe.

⬇ Download