# Document 14 : Structure YAML du Registraire ## L'Alliance Boréale — Source de Vérité Technique **Version:** 1.0 **Date:** 23 octobre 2025 **Statut:** Document technique **Adopté par :** Cercle Opérationnel **Licence:** CC BY-SA 4.0 --- ## PRÉAMBULE Le Registraire est **la source de vérité unique** de L'Alliance Boréale. **Tout ce qui compte est dans le Registraire :** - Membres (actifs, probation, sortis) - Services fédérés (DNS, email, Matrix) - Labels et scores - Décisions de gouvernance - Zones DNS **Format : YAML + Git** **Pourquoi YAML ?** - ✅ Lisible par humains (contrairement à JSON) - ✅ Éditable manuellement (pas besoin d'interface web) - ✅ Versionnable (Git track changes) - ✅ Validable (schemas, linters) - ✅ Parsable par machines (Ansible, scripts) **Pourquoi Git ?** - ✅ Historique complet (qui a changé quoi, quand, pourquoi) - ✅ Pull requests (review avant merge) - ✅ Branches (test modifications avant prod) - ✅ Réversibilité (rollback si erreur) - ✅ Distribution (chaque membre peut cloner) **Principe :** Une seule source de vérité, maintenue collectivement, auditable par tous. --- ## SECTION 1 : STRUCTURE DU DÉPÔT GIT ### 1.1 Arborescence Complète ``` registraire/ ├── README.md # Documentation générale ├── CONTRIBUTING.md # Guide contribution ├── LICENSE # CC BY-SA 4.0 │ ├── schemas/ # Schémas de validation │ ├── member.schema.json # JSON Schema fiche membre │ ├── decision.schema.json # JSON Schema décision │ └── label.schema.json # JSON Schema label │ ├── membres/ # Fiches membres │ ├── m001-chezlepro.yml # Membre 001 │ ├── m002-technolibre.yml # Membre 002 │ ├── m003-coop-nordique.yml # Membre 003 │ └── ... │ ├── gouvernance/ # Décisions & gouvernance │ ├── decisions/ │ │ ├── 2025-001-admission-m001.yml │ │ ├── 2025-002-admission-m002.yml │ │ └── 2025-042-amendement-charte.yml │ │ │ ├── cercles/ │ │ ├── strategique.yml # Composition cercle │ │ ├── operationnel.yml │ │ └── ethique.yml │ │ │ └── assemblees/ │ ├── 2025-01-ag-annuelle.yml # PV assemblée générale │ └── 2026-01-ag-annuelle.yml │ ├── labels/ # Labellisation │ ├── attributions/ │ │ ├── m001-2025-Q4.yml # Label attribué │ │ ├── m002-2025-Q4.yml │ │ └── ... │ │ │ └── audits/ │ ├── m001-2025-Q4-rapport.yml # Rapport audit (synthèse) │ └── ... │ ├── dns/ # Configuration DNS │ ├── zones/ │ │ ├── boreal.ca.zone # Zone racine │ │ ├── chezlepro.boreal.ca.zone # Zones membres │ │ └── technolibre.boreal.ca.zone │ │ │ └── delegations/ │ └── delegations.yml # Liste délégations actives │ ├── incidents/ # Post-mortems │ ├── 2025-10-incident-dns-p1.yml │ └── 2025-11-incident-cert-p0.yml │ └── banque-temps/ # Transactions (si implémentée) └── transactions-2025-Q4.yml ``` --- ### 1.2 Nomenclature des Fichiers **Règles strictes :** | Type | Format | Exemple | |------|--------|---------| | **Membre** | `mXXX-[slug].yml` | `m001-chezlepro.yml` | | **Décision** | `YYYY-NNN-[titre-court].yml` | `2025-042-amendement-charte.yml` | | **Label** | `mXXX-YYYY-QN.yml` | `m001-2025-Q4.yml` | | **Audit** | `mXXX-YYYY-QN-rapport.yml` | `m001-2025-Q4-rapport.yml` | | **Incident** | `YYYY-MM-incident-[titre]-[prio].yml` | `2025-10-incident-dns-p1.yml` | | **Zone DNS** | `[domain].zone` | `chezlepro.boreal.ca.zone` | **Avantages :** - Tri alphabétique = tri chronologique (pour décisions, incidents) - ID membre visible (mXXX) - Parsing facile (scripts) --- ### 1.3 Branches et Workflow Git **Branches :** ``` main → Production (fiches validées) ├── dev → Développement (intégration continue) └── feature/* → Branches de travail (1 feature = 1 branch) ├── feature/add-member-m004 ├── feature/update-label-m001 └── feature/dns-delegation-m002 ``` **Workflow Pull Request :** 1. **Créer branche** : `git checkout -b feature/add-member-m004` 2. **Modifier fichier(s)** : Éditer `membres/m004-nouveau.yml` 3. **Commit** : `git commit -m "feat: Add member m004 (Nouveau OBNL)"` 4. **Push** : `git push origin feature/add-member-m004` 5. **Ouvrir Pull Request** sur Forge 6. **Review** : 1+ membre (vérification conformité) 7. **CI/CD** : Tests automatiques (yamllint, schema validation) 8. **Merge** : Si tests ✅ + review ✅ → merge dans `main` **Protection branche `main` :** - Aucun push direct (seulement via PR) - Review obligatoire (1+ personne) - CI/CD doit passer (tests) --- ## SECTION 2 : SCHÉMA FICHE MEMBRE ### 2.1 Structure Complète (Commentée) **Fichier : `membres/m001-chezlepro.yml`** ```yaml # ============================================================================ # FICHE MEMBRE — L'Alliance Boréale # ============================================================================ # ID: m001 # Slug: chezlepro # Nom légal: Chez le Pro Technologies Inc. # Statut: actif # Dernière mise à jour: 2025-10-23 # ============================================================================ # ---------------------------------------------------------------------------- # SECTION 1 : IDENTITÉ # ---------------------------------------------------------------------------- member_id: m001 slug: chezlepro status: active # active | probation | suspended | exited identity: legal_name: "Chez le Pro Technologies Inc." legal_form: corporation # corporation | coop | npo | sole_proprietorship jurisdiction: QC # Juridiction d'enregistrement registration_number: "1234567890" # NEQ (Québec) ou équivalent operating_name: "Chez le Pro" # Nom commercial (si différent) website: "https://chezle.pro" founded_date: "2018-03-15" joined_alliance_date: "2025-01-15" probation_end_date: "2025-04-15" # null si membre actif confirmé description: | Chez le Pro offre des services d'hébergement web éthique et de développement logiciel sur mesure pour PME québécoises. Membre fondateur de L'Alliance Boréale. # ---------------------------------------------------------------------------- # SECTION 2 : CONTACTS # ---------------------------------------------------------------------------- contacts: primary: name: "Jean Tremblay" role: "Président" email: "jean@chezle.pro" phone: "+1-514-555-0100" matrix: "@jean:matrix.chezlepro.boreal.ca" technical: name: "Marie Gagnon" role: "Directrice technique" email: "marie@chezle.pro" phone: "+1-514-555-0101" matrix: "@marie:matrix.chezlepro.boreal.ca" security: email: "security@chezle.pro" pgp_key: "0x1234567890ABCDEF" pgp_fingerprint: "1234 5678 90AB CDEF 1234 5678 90AB CDEF 1234 5678" legal: name: "Sophie Lavoie" role: "Conseillère juridique" email: "legal@chezle.pro" # ---------------------------------------------------------------------------- # SECTION 3 : INFRASTRUCTURE # ---------------------------------------------------------------------------- infrastructure: hosting: provider: "OVH Canada" datacenter_location: "Montreal, QC, Canada" owned: false # true = hardware propre, false = loué network: ipv4_public: - "203.0.113.10/32" - "203.0.113.20/28" ipv6_public: - "2001:db8:1234::/48" ipv4_private: "10.1.0.0/16" # Selon Doc 5 asn: null # Autonomous System Number (si applicable) dns: primary_ns: "ns1.chezlepro.boreal.ca" secondary_ns: "ns2.chezlepro.boreal.ca" ns_ips: ns1: "203.0.113.10" ns2: "203.0.113.11" dnssec_enabled: true dnssec_ds_records: - "12345 8 2 1234567890ABCDEF..." # DS record pour parent servers: count: 3 summary: | - 1x serveur compute (Proxmox) - 1x serveur storage (ZFS) - 1x serveur backup (dédié) # ---------------------------------------------------------------------------- # SECTION 4 : SERVICES PUBLICS # ---------------------------------------------------------------------------- services: email: enabled: true domain: "chezle.pro" mx_records: - priority: 10 host: "mail.chezlepro.boreal.ca" protocols: - smtp - smtps - imap - imaps security: dkim: true spf: true dmarc: true tls_min_version: "1.2" web: enabled: true urls: - "https://chezle.pro" - "https://www.chezle.pro" technologies: - nginx - php-fpm - postgresql cloud_storage: enabled: true platform: nextcloud url: "https://cloud.chezlepro.boreal.ca" version: "28.0.1" matrix: enabled: true homeserver_url: "https://matrix.chezlepro.boreal.ca" federation_enabled: true server_name: "chezlepro.boreal.ca" status_page: enabled: true url: "https://status.chezlepro.boreal.ca" platform: "upptime" # upptime | cachet | custom monitoring: prometheus_endpoint: "https://prometheus.chezlepro.boreal.ca" grafana_url: "https://grafana.chezlepro.boreal.ca" public_metrics: true # Métriques partagées avec Alliance # ---------------------------------------------------------------------------- # SECTION 5 : STANDARDS ET CONFORMITÉ # ---------------------------------------------------------------------------- standards: open_source_percentage: 85 # % de stack en logiciels libres protocols_supported: - smtp - imap - caldav - carddav - webdav - matrix certifications: - name: "ISO 27001" issued_by: "BSI Group" valid_until: "2026-12-31" certificate_url: "https://chezle.pro/certs/iso27001.pdf" compliance: loi_25: true # Conformité Loi 25 (Québec) rgpd: true # Conformité RGPD (EU) pipeda: true # Conformité PIPEDA (Canada) # ---------------------------------------------------------------------------- # SECTION 6 : LABEL DE PRESTIGE # ---------------------------------------------------------------------------- label: current: level: gold # bronze | silver | gold | platinum | null score_global: 82 scores_by_domain: infrastructure: 85 security: 88 interoperability: 78 open_source: 90 operations: 75 sustainability: 72 issued_date: "2025-10-01" valid_until: "2026-10-01" audited_by: "m002" # Membre auditeur report_url: "registraire/labels/audits/m001-2025-Q4-rapport.yml" history: - level: silver score_global: 68 issued_date: "2025-04-01" valid_until: "2026-04-01" - level: bronze score_global: 52 issued_date: "2025-01-15" valid_until: "2026-01-15" # ---------------------------------------------------------------------------- # SECTION 7 : PARTICIPATION & CONTRIBUTIONS # ---------------------------------------------------------------------------- participation: cercles: - name: "Cercle Stratégique" role: "membre" since: "2025-01-15" - name: "Cercle Opérationnel" role: "président" since: "2025-07-01" until: "2026-01-01" contributions: - type: "code" description: "Développement Registraire YAML (validation, CI/CD)" date: "2025-03-20" hours: 15 - type: "documentation" description: "Rédaction runbooks DNS & DNSSEC" date: "2025-05-10" hours: 8 - type: "mentoring" description: "Parrainage membre m003 (probation)" date: "2025-08-01" status: "en_cours" banque_temps: balance: 42 # Crédits (heures) last_updated: "2025-10-20" # ---------------------------------------------------------------------------- # SECTION 8 : MÉTADONNÉES # ---------------------------------------------------------------------------- metadata: created_at: "2025-01-15T10:30:00Z" updated_at: "2025-10-23T14:22:00Z" updated_by: "m001" # Dernière modification par version: 2 # Numéro de version du schéma notes: | Membre fondateur. Infrastructure solide. Contributions régulières. Candidat potentiel Platine en 2026 si maintien niveau actuel. tags: - fondateur - hebergement - quebec - infrastructure-mature ``` --- ### 2.2 Champs Obligatoires vs Optionnels **Obligatoires (validation bloquante) :** - `member_id` - `slug` - `status` - `identity.legal_name` - `identity.legal_form` - `identity.joined_alliance_date` - `contacts.primary` (name, email) - `contacts.technical.email` - `contacts.security.email` - `infrastructure.dns.primary_ns` - `services.status_page.url` **Recommandés (warning si absent) :** - `identity.website` - `infrastructure.dns.dnssec_enabled` - `services.email` (si service email offert) - `standards.open_source_percentage` - `label.current` (si labellisé) **Optionnels (sans warning) :** - `infrastructure.network.asn` - `standards.certifications` - `participation.contributions` - `metadata.notes` --- ### 2.3 Valeurs Enum (Contrôlées) **Statut membre (`status`) :** - `probation` : En période probatoire (3 mois) - `active` : Membre actif confirmé - `suspended` : Suspendu temporairement - `exited` : Sorti de L'Alliance (volontaire ou radiation) **Forme légale (`identity.legal_form`) :** - `corporation` : Entreprise incorporée - `coop` : Coopérative - `npo` : Organisme à but non lucratif - `sole_proprietorship` : Travailleur autonome **Niveau label (`label.current.level`) :** - `bronze` - `silver` - `gold` - `platinum` - `null` : Non labellisé **Type contribution (`participation.contributions.type`) :** - `code` : Contribution code (forge) - `documentation` : Rédaction wiki/runbooks - `mentoring` : Parrainage nouveau membre - `audit` : Audit pair-à-pair - `governance` : Participation cercle - `infrastructure` : Support technique mutuel --- ## SECTION 3 : VALIDATION AUTOMATIQUE ### 3.1 YAML Lint (Syntaxe) **Outil : `yamllint`** **Configuration : `.yamllint`** ```yaml extends: default rules: line-length: max: 120 level: warning indentation: spaces: 2 comments: min-spaces-from-content: 2 document-start: present: true ``` **Commande :** ```bash yamllint membres/*.yml ``` **Résultat attendu :** ``` membres/m001-chezlepro.yml 0:0 warning missing document start "---" (document-start) membres/m002-technolibre.yml 0:0 warning missing document start "---" (document-start) ``` --- ### 3.2 JSON Schema (Structure) **Schéma : `schemas/member.schema.json`** ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://registraire.alliance-boreale.ca/schemas/member.schema.json", "title": "Alliance Boréale - Fiche Membre", "description": "Schéma de validation pour fiche membre", "type": "object", "required": [ "member_id", "slug", "status", "identity", "contacts", "infrastructure", "services" ], "properties": { "member_id": { "type": "string", "pattern": "^m[0-9]{3}$", "description": "ID unique membre (format: mXXX)" }, "slug": { "type": "string", "pattern": "^[a-z0-9-]{3,20}$", "description": "Slug textuel unique (3-20 car, minuscules)" }, "status": { "type": "string", "enum": ["probation", "active", "suspended", "exited"] }, "identity": { "type": "object", "required": ["legal_name", "legal_form", "joined_alliance_date"], "properties": { "legal_name": { "type": "string", "minLength": 3 }, "legal_form": { "type": "string", "enum": ["corporation", "coop", "npo", "sole_proprietorship"] }, "jurisdiction": { "type": "string", "pattern": "^[A-Z]{2}$" }, "registration_number": { "type": "string" }, "website": { "type": "string", "format": "uri" }, "joined_alliance_date": { "type": "string", "format": "date" }, "description": { "type": "string" } } }, "contacts": { "type": "object", "required": ["primary", "technical", "security"], "properties": { "primary": { "type": "object", "required": ["name", "email"], "properties": { "name": { "type": "string" }, "role": { "type": "string" }, "email": { "type": "string", "format": "email" }, "phone": { "type": "string" }, "matrix": { "type": "string" } } }, "technical": { "type": "object", "required": ["email"], "properties": { "name": { "type": "string" }, "email": { "type": "string", "format": "email" } } }, "security": { "type": "object", "required": ["email"], "properties": { "email": { "type": "string", "format": "email" }, "pgp_key": { "type": "string" } } } } }, "infrastructure": { "type": "object", "required": ["dns"], "properties": { "dns": { "type": "object", "required": ["primary_ns"], "properties": { "primary_ns": { "type": "string", "format": "hostname" }, "secondary_ns": { "type": "string", "format": "hostname" }, "dnssec_enabled": { "type": "boolean" } } } } }, "services": { "type": "object", "required": ["status_page"], "properties": { "status_page": { "type": "object", "required": ["url"], "properties": { "enabled": { "type": "boolean" }, "url": { "type": "string", "format": "uri" } } } } }, "label": { "type": "object", "properties": { "current": { "type": "object", "required": ["level", "score_global", "issued_date", "valid_until"], "properties": { "level": { "type": "string", "enum": ["bronze", "silver", "gold", "platinum"] }, "score_global": { "type": "integer", "minimum": 0, "maximum": 100 }, "scores_by_domain": { "type": "object", "properties": { "infrastructure": { "type": "integer", "minimum": 0, "maximum": 100 }, "security": { "type": "integer", "minimum": 0, "maximum": 100 }, "interoperability": { "type": "integer", "minimum": 0, "maximum": 100 }, "open_source": { "type": "integer", "minimum": 0, "maximum": 100 }, "operations": { "type": "integer", "minimum": 0, "maximum": 100 }, "sustainability": { "type": "integer", "minimum": 0, "maximum": 100 } } }, "issued_date": { "type": "string", "format": "date" }, "valid_until": { "type": "string", "format": "date" } } } } } } } ``` **Validation :** ```bash # Outil: ajv-cli (JSON Schema validator) ajv validate -s schemas/member.schema.json -d "membres/*.yml" ``` --- ### 3.3 CI/CD Pipeline **Fichier : `.gitlab-ci.yml` (ou `.github/workflows/validate.yml`)** ```yaml stages: - validate - test - deploy # Job 1: Validation syntaxe YAML yaml-lint: stage: validate image: python:3.11-alpine before_script: - pip install yamllint script: - yamllint membres/*.yml gouvernance/**/*.yml labels/**/*.yml only: - merge_requests - main # Job 2: Validation structure (JSON Schema) schema-validation: stage: validate image: node:18-alpine before_script: - npm install -g ajv-cli ajv-formats script: - ajv validate -s schemas/member.schema.json -d "membres/*.yml" - ajv validate -s schemas/decision.schema.json -d "gouvernance/decisions/*.yml" - ajv validate -s schemas/label.schema.json -d "labels/attributions/*.yml" only: - merge_requests - main # Job 3: Vérification unicité slug/ID uniqueness-check: stage: test image: python:3.11-alpine before_script: - pip install pyyaml script: - python scripts/check-uniqueness.py only: - merge_requests - main # Job 4: Génération site web statique (optionnel) generate-website: stage: deploy image: python:3.11-alpine before_script: - pip install pyyaml jinja2 script: - python scripts/generate-website.py - mkdir -p public - cp -r website/* public/ artifacts: paths: - public only: - main ``` **Script `scripts/check-uniqueness.py` :** ```python #!/usr/bin/env python3 """Vérifier unicité des IDs et slugs membres.""" import sys from pathlib import Path import yaml def check_uniqueness(): members_dir = Path("membres") ids = [] slugs = [] for file in members_dir.glob("*.yml"): with open(file) as f: data = yaml.safe_load(f) member_id = data.get("member_id") slug = data.get("slug") if member_id in ids: print(f"❌ ERREUR: ID {member_id} dupliqué dans {file}") sys.exit(1) ids.append(member_id) if slug in slugs: print(f"❌ ERREUR: Slug {slug} dupliqué dans {file}") sys.exit(1) slugs.append(slug) print(f"✅ Validation OK: {len(ids)} membres, IDs et slugs uniques") return 0 if __name__ == "__main__": sys.exit(check_uniqueness()) ``` --- ## SECTION 4 : PROCESSUS DE MISE À JOUR ### 4.1 Modification par le Membre Lui-Même **Cas d'usage :** Mise à jour contact technique, ajout service, etc. **Processus :** 1. **Cloner le dépôt** ```bash git clone https://forge.boreal.ca/alliance/registraire.git cd registraire ``` 2. **Créer branche** ```bash git checkout -b update/m001-add-matrix-service ``` 3. **Éditer fiche** ```bash vim membres/m001-chezlepro.yml # Ajouter section services.matrix ``` 4. **Valider localement** ```bash yamllint membres/m001-chezlepro.yml ajv validate -s schemas/member.schema.json -d membres/m001-chezlepro.yml ``` 5. **Commit** ```bash git add membres/m001-chezlepro.yml git commit -m "feat(m001): Add Matrix federation service" ``` 6. **Push et Pull Request** ```bash git push origin update/m001-add-matrix-service # Ouvrir PR sur forge.boreal.ca ``` 7. **Review + Merge** - Cercle Opérationnel review (vérification cohérence) - CI/CD valide (tests automatiques) - Merge dans `main` **Délai typique :** 1-3 jours. --- ### 4.2 Modification par Cercle Opérationnel **Cas d'usage :** Changement statut, attribution label, décision gouvernance. **Processus similaire, mais :** - Commit signé GPG (authentification) - Mention dans commit message : `[CERCLE-OPS]` - Review par 2+ membres du Cercle Opérationnel **Exemple :** ```bash git commit -S -m "[CERCLE-OPS] feat(m001): Promote to Gold label (Q4 2025)" ``` --- ### 4.3 Modification Urgente (Incident) **Cas d'usage :** Révocation certificat, changement IP urgent. **Processus accéléré :** - Commit direct sur `main` autorisé (exception) - Notification Matrix #incidents immédiate - Justification dans commit message **Exemple :** ```bash git commit -m "fix(m001): Update DNS IP after datacenter migration (P1 incident)" git push origin main # Post dans Matrix: "🚨 Update urgent registraire m001 (migration datacenter)" ``` **Post-mortem :** Documentation de l'incident + amélioration du processus si nécessaire. --- ## SECTION 5 : GÉNÉRATION DE VUES ### 5.1 Site Web Public **Concept :** Générer site web statique à partir des YAML (lecture seule). **URL :** `https://registraire.alliance-boreale.ca` **Pages générées :** - `/` : Liste membres actifs - `/membres/m001` : Fiche membre détaillée (infos publiques) - `/labels` : Tableau de bord labels - `/decisions` : Liste décisions publiques - `/stats` : Statistiques agrégées **Technologie :** Python + Jinja2, ou Jekyll, ou Hugo. **Script `scripts/generate-website.py` (squelette) :** ```python #!/usr/bin/env python3 """Générer site web statique à partir des YAML.""" from pathlib import Path import yaml from jinja2 import Environment, FileSystemLoader def generate(): # Charger tous les membres members = [] for file in Path("membres").glob("*.yml"): with open(file) as f: data = yaml.safe_load(f) if data["status"] in ["active", "probation"]: members.append(data) # Trier par joined_date members.sort(key=lambda m: m["identity"]["joined_alliance_date"]) # Générer HTML env = Environment(loader=FileSystemLoader("templates")) template = env.get_template("index.html") html = template.render(members=members) Path("website").mkdir(exist_ok=True) with open("website/index.html", "w") as f: f.write(html) print(f"✅ Site généré: {len(members)} membres") if __name__ == "__main__": generate() ``` **Template `templates/index.html` :** ```html Registraire — L'Alliance Boréale

🌲 L'Alliance Boréale — Registraire Public

Fédération de services numériques éthiques

Membres Actifs ({{ members|length }})

{% for member in members %}

{{ member.identity.legal_name }}

ID: {{ member.member_id }}

Slug: {{ member.slug }}

Statut: {{ member.status }}

{% if member.label.current %}

Label: {{ member.label.current.level }} ({{ member.label.current.score_global }}/100)

{% endif %}

Site web

{% endfor %}
``` --- ### 5.2 API REST (Optionnel) **Concept :** Exposer données via API REST (lecture seule). **URL :** `https://api.registraire.alliance-boreale.ca` **Endpoints :** ``` GET /members → Liste membres actifs GET /members/{id} → Fiche membre détaillée GET /members/{id}/label → Label actuel GET /labels → Tous les labels actifs GET /decisions → Décisions publiques GET /stats → Statistiques agrégées ``` **Technologie :** FastAPI (Python) ou Express (Node.js). **Réponse JSON (exemple) :** ```json GET /members/m001 { "member_id": "m001", "slug": "chezlepro", "status": "active", "identity": { "legal_name": "Chez le Pro Technologies Inc.", "website": "https://chezle.pro" }, "label": { "level": "gold", "score_global": 82, "issued_date": "2025-10-01", "valid_until": "2026-10-01" } } ``` **Avantages :** - Intégration facilitée (scripts, apps) - Versioning API (v1, v2) - Rate limiting (prévention abus) --- ## SECTION 6 : SÉCURITÉ ET PERMISSIONS ### 6.1 Accès en Lecture (Public) **Qui :** Tout le monde (internet public). **Quoi :** - Fiches membres (infos publiques) - Décisions publiées - Labels attribués - Zones DNS publiques **Comment :** Git clone (HTTPS), site web, API. --- ### 6.2 Accès en Écriture (Restreint) **Qui :** - Membres actifs (modification de LEUR fiche uniquement) - Cercle Opérationnel (modification toutes fiches + gouvernance) - Cercle Éthique (modification labels) **Authentification :** SSH keys + GPG signing. **Permissions Git :** ``` # Exemple .gitignore permissions (conceptuel, pas standard Git) membres/m001-*.yml → Éditable par m001 + Cercle Ops membres/m002-*.yml → Éditable par m002 + Cercle Ops gouvernance/* → Éditable par Cercle Stratégique + Ops labels/* → Éditable par Cercle Éthique uniquement dns/* → Éditable par Cercle Ops uniquement ``` **Implémentation réelle :** Forge (GitLab/Gitea) avec roles et protected branches. --- ### 6.3 Audit Trail (Traçabilité) **Git = Audit trail natif :** - Chaque commit = auteur, date, message - Signature GPG = authentification cryptographique - Historique complet (`git log`) **Exemple :** ```bash git log --oneline --graph membres/m001-chezlepro.yml * a3b4c5d (HEAD -> main) feat(m001): Update Matrix federation URL * 9f8e7d6 feat(m001): Add Gold label (Q4 2025) * 2c3d4e5 fix(m001): Correct technical contact email * 1a2b3c4 feat: Add member m001 (Chez le Pro) ``` **Requêtes utiles :** ```bash # Qui a modifié quoi ? git log --all --author="jean@chezle.pro" # Quand ce champ a-t-il changé ? git log -p -S "mail.chezlepro.boreal.ca" membres/m001-chezlepro.yml # Liste des commits entre deux dates git log --since="2025-10-01" --until="2025-10-31" ``` --- ## CONCLUSION Le Registraire YAML est **simple mais puissant** : ✅ **Lisible** : N'importe qui peut lire un fichier YAML ✅ **Versionné** : Git track tous les changements ✅ **Validé** : Schemas + CI/CD garantissent cohérence ✅ **Auditable** : Historique complet, signatures GPG ✅ **Extensible** : Facile d'ajouter champs (rétrocompatible) ✅ **Distribué** : Chaque membre peut cloner ✅ **Machine-readable** : Scripts, Ansible, APIs **Ce n'est pas une base de données relationnelle complexe. C'est mieux : c'est Git.** La complexité ne vient pas de l'outil, mais de la rigueur des processus. Avec des conventions claires, des reviews systématiques, et des tests automatiques, le Registraire devient la colonne vertébrale informationnelle de L'Alliance. **Bienvenue dans le registraire boréal.** 🌲 --- ## ANNEXES ### Annexe A : Exemple Membre Complet (m002) **Fichier : `membres/m002-technolibre.yml`** ```yaml --- member_id: m002 slug: technolibre status: active identity: legal_name: "TechnoLibre SENC" legal_form: coop jurisdiction: QC registration_number: "9876543210" website: "https://technolibre.ca" joined_alliance_date: "2025-02-01" probation_end_date: null description: | TechnoLibre est une coopérative de développeurs offrant du développement logiciel sur mesure et de l'hébergement souverain. Spécialisés en Odoo et Python/Django. contacts: primary: name: "Sophie Lavoie" role: "Présidente" email: "sophie@technolibre.ca" phone: "+1-418-555-0200" matrix: "@sophie:matrix.technolibre.boreal.ca" technical: name: "Marc Dubois" role: "Lead DevOps" email: "marc@technolibre.ca" matrix: "@marc:matrix.technolibre.boreal.ca" security: email: "security@technolibre.ca" pgp_key: "0xABCDEF1234567890" infrastructure: hosting: provider: "OVH France" datacenter_location: "Strasbourg, France" owned: false network: ipv4_public: - "198.51.100.20/32" ipv4_private: "10.2.0.0/16" dns: primary_ns: "ns1.technolibre.boreal.ca" secondary_ns: "ns2.technolibre.boreal.ca" ns_ips: ns1: "198.51.100.20" ns2: "198.51.100.21" dnssec_enabled: false services: email: enabled: true domain: "technolibre.ca" mx_records: - priority: 10 host: "mail.technolibre.boreal.ca" protocols: [smtp, imap] security: dkim: true spf: true dmarc: true cloud_storage: enabled: true platform: nextcloud url: "https://cloud.technolibre.boreal.ca" status_page: enabled: true url: "https://status.technolibre.boreal.ca" platform: cachet standards: open_source_percentage: 95 protocols_supported: [smtp, imap, caldav, carddav, webdav] compliance: loi_25: true rgpd: true label: current: level: silver score_global: 70 issued_date: "2025-06-01" valid_until: "2026-06-01" audited_by: "m001" participation: cercles: - name: "Cercle Stratégique" role: "membre" since: "2025-02-01" metadata: created_at: "2025-02-01T09:00:00Z" updated_at: "2025-10-20T11:15:00Z" version: 2 ``` --- ### Annexe B : Schéma Décision **Fichier : `schemas/decision.schema.json` (extrait)** ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "Décision de Gouvernance", "type": "object", "required": ["decision_id", "date", "circle", "type", "outcome"], "properties": { "decision_id": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{3}$", "description": "Format: YYYY-NNN" }, "date": { "type": "string", "format": "date" }, "circle": { "type": "string", "enum": ["strategic", "operational", "ethics", "referents"] }, "type": { "type": "string", "enum": ["admission", "policy", "budget", "label", "amendment", "other"] }, "outcome": { "type": "string", "enum": ["approved", "rejected", "amended"] } } } ``` --- ### Annexe C : Commandes Utiles **Recherche membre par slug :** ```bash grep -l "slug: chezlepro" membres/*.yml ``` **Liste membres actifs :** ```bash grep -l "status: active" membres/*.yml | wc -l ``` **Extraction infos avec `yq` :** ```bash # Installer: apt install yq yq eval '.identity.legal_name' membres/m001-chezlepro.yml # Output: Chez le Pro Technologies Inc. yq eval '.label.current.level' membres/m001-chezlepro.yml # Output: gold ``` **Statistiques labels :** ```bash for file in membres/*.yml; do level=$(yq eval '.label.current.level // "none"' "$file") echo "$level" done | sort | uniq -c # Output: # 5 gold # 8 silver # 3 bronze # 2 none ``` --- ## MÉTADONNÉES **Document :** 14_Structure_YAML_Registraire.md **Version :** 1.0 **Date de création :** 23 octobre 2025 **Auteur :** Claude (profils #5 IaC, #12 Documentaliste) **Révision par :** Cercle Opérationnel **Statut :** À adopter par Cercle Stratégique **Longueur :** ~6 000 mots (12 pages) **Licence :** CC BY-SA 4.0 **Sources utilisées :** - `00_Glossaire_et_Definitions.md` - `05_Architecture_Reference_Standards_Techniques.md` - `03_Cadre_Conformite_Label_Prestige.md` - `devis_alliance_boreale_v2.md` **Prochaine révision prévue :** Octobre 2026 (après 1 an d'usage) --- **Changelog :** - 2025-10-23 v1.0 : Création initiale Structure YAML Registraire --- **FIN DE LA STRUCTURE YAML** *"La donnée bien structurée est la moitié du travail accompli."* 🌲 **L'Alliance Boréale** *YAML + Git = Source de vérité vivante.*