From 97bcb4125a76aa617d25b7c0a1a6492b50ae50aa Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Aug 2026 09:44:37 +0000 Subject: [PATCH 1/4] feat(kb): retire ttl_days de toutes les fiches et des conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le champ imposait une péremption automatique que rien n'appliquait : aucun outil ne le lisait, aucune revue ne s'en servait. Il donnait une fausse impression de fraîcheur pilotée. - clé ttl_days retirée des 29 fiches active/**/*.json et des entrées d'index.json - KB-CONVENTIONS.md : champ retiré du schéma, règle de passage en `suspect` réécrite comme une décision de revue explicite, `validated` restant le marqueur de dernière vérification - deux fiches citaient ttl_days dans leur contenu (codex-models, splunk-cim-data-models) : phrases reformulées sans changer le fond Closes #8 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF --- KB-CONVENTIONS.md | 4 ++-- ...-domain-controller-security-hardening.json | 1 - ...s-domain-forest-gpo-security-baseline.json | 1 - .../ad-ds-gpo-acl-lifecycle-governance.json | 1 - ...-ds-security-control-assurance-levels.json | 1 - ...ds-security-hardening-study-synthesis.json | 1 - .../ad-ds-threat-driven-control-map.json | 1 - active/ad-ds/reference.json | 1 - active/ad-ds/unattended-deployment.json | 1 - .../agent-skills-cross-tool-integration.json | 1 - active/aws/ecs-fargate-task-isolation.json | 1 - .../claude-config/claude-md-hierarchie.json | 1 - .../claude-md-import-mechanism.json | 1 - .../codex-config/codex-agents-md-nesting.json | 1 - active/engine-catalog/claude-code-models.json | 1 - active/engine-catalog/codex-models.json | 3 +-- active/engine-catalog/copilot-models.json | 1 - active/governance/sailpoint-identityiq.json | 1 - .../servicenow-itsm-change-management.json | 1 - ...ntity-entra-security-impact-inventory.json | 1 - .../powershell/native-exe-json-quoting.json | 1 - ...el-microsoft-reference-implementation.json | 1 - ...ad-ds-tiered-administration-hardening.json | 1 - .../enterprise-access-model.json | 1 - .../zero-standing-access.json | 1 - ...security-framework-role-and-crosswalk.json | 1 - active/siem/splunk-cim-data-models.json | 3 +-- .../copilot-instructions-merge.json | 1 - .../vscode-copilot-builtin-tools.json | 1 - ...-2022-plus-hardening-source-baselines.json | 1 - index.json | 19 ------------------- 31 files changed, 4 insertions(+), 52 deletions(-) diff --git a/KB-CONVENTIONS.md b/KB-CONVENTIONS.md index f78552e..683f750 100644 --- a/KB-CONVENTIONS.md +++ b/KB-CONVENTIONS.md @@ -33,7 +33,6 @@ Fiche JSON avec attributs courts/contrôlés et un seul champ texte libre (`cont "source": "URL / PR / discussion (libre)", "validated": "YYYY-MM-DD", "created": "YYYY-MM-DD", - "ttl_days": 90, "links": ["autres-ids-liés"], "content": "Corps de la fiche, Markdown en texte libre" } @@ -46,7 +45,8 @@ concision (texte libre par nature). - Nommage : `active//.json`, `id` = nom de fichier sans extension. - Une fiche = un sujet précis. Pas de fourre-tout. -- Statut `suspect` si la fiche n'a pas été revalidée dans le délai `ttl_days`. +- Statut `suspect` posé explicitement lors d'une revue, quand la fiche n'est plus + sûre ; `validated` porte la date de dernière vérification. - Archiver (déplacer dans `archived/`) plutôt que supprimer. - Mettre à jour `index.json` (sans `content`, plus champ `path`) à chaque ajout, archivage ou changement d'attribut. diff --git a/active/ad-ds-security/ad-ds-domain-controller-security-hardening.json b/active/ad-ds-security/ad-ds-domain-controller-security-hardening.json index 85d0417..18cddd2 100644 --- a/active/ad-ds-security/ad-ds-domain-controller-security-hardening.json +++ b/active/ad-ds-security/ad-ds-domain-controller-security-hardening.json @@ -28,7 +28,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "windows-server-2022-plus-hardening-source-baselines", "ad-ds-tiered-administration-hardening", diff --git a/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.json b/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.json index 2f1e131..9a43d53 100644 --- a/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.json +++ b/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.json @@ -27,7 +27,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "ad-ds-security-hardening-study-synthesis", "ad-ds-domain-controller-security-hardening", diff --git a/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.json b/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.json index 1bfb666..8b822d3 100644 --- a/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.json +++ b/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.json @@ -25,7 +25,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "ad-ds-domain-forest-gpo-security-baseline", "ad-ds-tiered-administration-hardening", diff --git a/active/ad-ds-security/ad-ds-security-control-assurance-levels.json b/active/ad-ds-security/ad-ds-security-control-assurance-levels.json index e7113d0..4f05d99 100644 --- a/active/ad-ds-security/ad-ds-security-control-assurance-levels.json +++ b/active/ad-ds-security/ad-ds-security-control-assurance-levels.json @@ -26,7 +26,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "ad-ds-security-hardening-study-synthesis", "ad-ds-threat-driven-control-map", diff --git a/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.json b/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.json index 0b89b9b..eb544a0 100644 --- a/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.json +++ b/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.json @@ -25,7 +25,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "windows-server-2022-plus-hardening-source-baselines", "ad-ds-domain-forest-gpo-security-baseline", diff --git a/active/ad-ds-security/ad-ds-threat-driven-control-map.json b/active/ad-ds-security/ad-ds-threat-driven-control-map.json index 1eac47d..66e7080 100644 --- a/active/ad-ds-security/ad-ds-threat-driven-control-map.json +++ b/active/ad-ds-security/ad-ds-threat-driven-control-map.json @@ -30,7 +30,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "ad-ds-domain-controller-security-hardening", "ad-ds-domain-forest-gpo-security-baseline", diff --git a/active/ad-ds/reference.json b/active/ad-ds/reference.json index 2d9ecb9..b1eb49a 100644 --- a/active/ad-ds/reference.json +++ b/active/ad-ds/reference.json @@ -25,7 +25,6 @@ ], "validated": "2026-07-16", "created": "2026-06-16", - "ttl_days": 180, "links": [ "unattended-deployment" ], diff --git a/active/ad-ds/unattended-deployment.json b/active/ad-ds/unattended-deployment.json index 4bfdd64..aeec6e4 100644 --- a/active/ad-ds/unattended-deployment.json +++ b/active/ad-ds/unattended-deployment.json @@ -23,7 +23,6 @@ ], "validated": "2026-07-16", "created": "2026-06-16", - "ttl_days": 180, "links": [ "reference" ], diff --git a/active/agent-tooling/agent-skills-cross-tool-integration.json b/active/agent-tooling/agent-skills-cross-tool-integration.json index b2ae05f..01b04b2 100644 --- a/active/agent-tooling/agent-skills-cross-tool-integration.json +++ b/active/agent-tooling/agent-skills-cross-tool-integration.json @@ -11,7 +11,6 @@ "source": ["https://agentskills.io", "https://github.com/microsoft/vscode/issues/293276", "https://github.com/microsoft/vscode/issues/307630"], "validated": "2026-07-13", "created": "2026-07-13", - "ttl_days": 90, "links": ["vscode-copilot-builtin-tools"], "content": "# Agent Skills — standard ouvert cross-outil (Claude Code, Copilot/VS Code, Codex)\n\nStatut : `.new` — capture de recherche du 2026-07-13, déclenchée par une observation\nréelle de Philippe (Copilot Chat allait chercher `.agents/skills/maxime-review`\nau lieu du `.github/prompts/maxime-review.prompt.md` attendu). Savoir générique\nréutilisable, sourcé sur la documentation officielle de chaque outil.\n\n## Le déclencheur\n\nPhilippe, dans GitHub Copilot Chat, demande \"Maxime Review\" → Copilot va chercher\ndans `.agents/skills/maxime-review` (chemin qu'on pensait réservé à Codex),\npas dans `.github/prompts/maxime-review.prompt.md` (le fichier Copilot généré\npar `generate-adapters.*`). Question : pourquoi, et est-ce grave ?\n\n## Ce qui est confirmé (sourcé)\n\n### Agent Skills est un standard ouvert, pas une convention par outil\n\nD'après [agentskills.io](https://agentskills.io) : le format **Agent Skills**\n(dossier + `SKILL.md`, frontmatter minimal `name`+`description`) a été créé par\nAnthropic puis publié comme **standard ouvert**, adopté par une liste large et\npublique d'outils : Claude Code, GitHub Copilot, VS Code, OpenAI Codex, Cursor,\nGemini CLI, Goose, Roo Code, JetBrains Junie, et des dizaines d'autres (voir la\npage pour la liste complète). Fonctionnement en 3 étapes (\"progressive\ndisclosure\") : *discovery* (nom+description seulement au démarrage) → *activation*\n(le corps du SKILL.md charge en contexte si la tâche correspond) → *execution*.\n\n**Conséquence directe pour mA.xI.me** : `.agents/skills/` n'est pas \"le dossier\nCodex\" — c'est un des emplacements génériques que plusieurs outils scannent en\nmême temps, dont Copilot.\n\n### Emplacements scannés, par outil\n\n| Outil | Emplacements projet | Emplacements personnels | Configurable ? |\n| --- | --- | --- | --- |\n| **Claude Code** | `.claude/skills/`, dossier `--add-dir` | `~/.claude/skills/` | non documenté |\n| **GitHub Copilot (VS Code, CLI, cloud agent)** | `.github/skills/`, **`.claude/skills/`**, **`.agents/skills/`** | `~/.copilot/skills/`, `~/.claude/skills/`, `~/.agents/skills/` | oui, `chat.agentSkillsLocations` — **ajoute** des emplacements, ne permet pas d'en exclure |\n| **OpenAI Codex** | `.agents/skills/`, scanné à chaque niveau du cwd jusqu'à la racine du repo Git | `$HOME/.agents/skills/` | non documenté |\n\nSources : [code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills),\n[docs.github.com — About custom agents](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-custom-agents)\net une recherche dédiée sur `chat.agentSkillsLocations`,\n[developers.openai.com/codex/skills](https://developers.openai.com/codex/skills)\n(redirige vers `learn.chatgpt.com/docs/codex/skills`).\n\n**Point clé** : Copilot scanne **les trois** conventions (la sienne + celle de\nClaude + celle de Codex/du standard). C'est documenté, pas un bug — Microsoft a\ndélibérément rendu Copilot compatible avec les skills écrits pour les autres\noutils.\n\n### Aucune restriction d'outils dans le standard de base\n\nChamps frontmatter du standard Agent Skills (confirmés via la doc VS Code) :\n`name`, `description`, `argument-hint`, `user-invocable`,\n`disable-model-invocation`, `context` (`inline` ou `fork`). **Aucun champ ne\nrestreint les outils disponibles** — ni `allowed-tools`, ni équivalent, dans le\nstandard lui-même.\n\n- **Claude Code étend le standard** avec `allowed-tools` (extension propriétaire,\n ignorée par les autres outils).\n- **Codex n'ajoute rien** — ses skills n'ont jamais de frontmatter de\n restriction (déjà documenté côté mA.xI.me, décision du 2026-07-12).\n- **Copilot/VS Code n'ajoute rien non plus au niveau Skill** — la restriction\n d'outils existe uniquement au niveau des **Custom Agents** (`.agent.md`,\n champ `tools:`), pas au niveau Skill.\n\n### Custom Agents VS Code (`.agent.md`) — rappel et nuance\n\nEmplacements : `.github/agents/` (projet), `~/.copilot/agents/` (utilisateur),\nextensible via `chat.agentFilesLocations`. Frontmatter : `name`, `description`,\n`tools`, `model`, `agents` (sous-agents autorisés), `handoffs`, `mcp-servers`.\nQuand un agent personnalisé est actif, seuls les outils listés dans `tools:`\nsont disponibles — confirmé.\n\n**Ce qui reste flou (la doc ne le dit pas explicitement)** : comment cette\nrestriction s'articule avec un Skill chargé pendant que l'agent est actif. Seul\nindice trouvé : *\"la priorité des outils favorise les fichiers de prompt sur\nles agents personnalisés\"* — ce qui suggère qu'un **prompt file** avec son\npropre `tools:` (comme `.github/prompts/maxime-review.prompt.md`, qui déclare\n`tools: [read, search]`) prendrait le pas sur l'agent actif s'il est invoqué\ncomme prompt/commande slash. Mais rien ne confirme ce qui se passe quand c'est\nun **Skill** (sans son propre `tools:`) qui est chargé à la place — hérite-t-il\ndes restrictions de l'agent actif, ou tourne-t-il avec la palette complète ?\n\nSources : [code.visualstudio.com/docs/agent-customization/custom-agents](https://code.visualstudio.com/docs/agent-customization/custom-agents),\n[code.visualstudio.com/docs/agent-customization/overview](https://code.visualstudio.com/docs/agent-customization/overview).\n\n## Implication concrète pour mA.xI.me\n\nLe workflow `maxime-review` est censé garantir une revue **lecture seule**\nsous Copilot via `.github/prompts/maxime-review.prompt.md`\n(`tools: [read, search]`) et/ou l'agent dédié `maxi-copilot-reviewer`\n(`.github/agents/maxime-reviewer.agent.md`, aussi `tools: [read, search]`).\n\nCe qu'on sait maintenant :\n\n1. Copilot scanne aussi `.claude/skills/maxime-review` et\n `.agents/skills/maxime-review` — deux fichiers **sans aucune restriction\n d'outils utilisable par Copilot** (le premier a `allowed-tools`, mais c'est\n une extension Claude que Copilot ignore ; le second n'a rien du tout).\n2. Rien ne garantit lequel des trois emplacements (`.github/skills/`\n — absent chez nous —, `.claude/skills/`, `.agents/skills/`) Copilot choisit\n quand plusieurs portent le même nom `maxime-review`. La doc ne documente\n pas de règle de priorité entre emplacements.\n3. Si Copilot charge le Skill (plutôt que le prompt file) **et** que le\n contexte d'exécution du Skill n'hérite pas des restrictions de l'agent\n actif, alors la garantie lecture-seule de `maxime-review` sous Copilot n'est\n plus mécanique — elle retombe sur la même situation déjà documentée pour\n Codex (\"consigne textuelle, pas garantie technique\").\n\nC'est le même trou que celui déjà noté dans `docs/ARCHITECTURE.md` §Limites\nassumées pour Codex, mais potentiellement **aussi vrai pour Copilot**.\n\n**Correction d'une hypothèse initiale** : en relisant `.wip/adr/decisions-log.md`,\nle verdict Tier 2 du 2026-07-12 précise explicitement que *\"prompts 4 (handoff)\net 5 (review) [n'ont pas été] executes, juges non necessaires vu la force des\nresultats deja obtenus\"*. Le workflow `maxime-review` n'a donc **jamais été\ntesté en conditions réelles sous Copilot** — ce n'est pas une régression par\nrapport à une garantie déjà validée, c'est une hypothèse non testée qu'on\ndécouvre seulement maintenant.\n\nChronologie confirmée : Agent Skills est arrivé dans GitHub Copilot le\n2025-12-18 ([GitHub Changelog](https://github.blog/changelog/2025-12-18-github-copilot-now-supports-agent-skills/)),\net dans VS Code (canal stable, expérimental) vers janvier 2026 via la version\n1.108 ([Visual Studio Magazine, 2026-01-11](https://visualstudiomagazine.com/articles/2026/01/11/hand-on-with-new-github-copilot-agent-skills-in-vs-code.aspx)) —\ndonc bien avant le Tier 2 du 2026-07-12. La fonctionnalité était déjà active\nau moment du Tier 2 ; c'est le scénario précis (invocation naturelle de\n\"Maxime Review\" plutôt que sélection explicite de l'agent ou du prompt) qui\nn'a jamais été exercé.\n\n**Recherche complémentaire (3 sources officielles distinctes)** : ni la doc\nGitHub ([about-agent-skills](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)),\nni le blog Microsoft ([Agent Skills in Visual Studio](https://devblogs.microsoft.com/visualstudio/agent-skills-in-visual-studio/),\nmai 2026, statut encore Insiders pour Visual Studio à cette date), ni la doc\nVS Code ne mentionnent la moindre notion de sécurité, de sandbox ou de\nrestriction d'outils au niveau Skill. L'absence est cohérente à travers les\ntrois sources — ce n'est pas un trou de recherche, la question semble\nsimplement ne pas être adressée par l'écosystème à ce stade.\n\n## Question résolue par les issues GitHub officielles (pas par la doc)\n\nLa doc ne tranchait pas la question d'héritage des permissions. Les issues\nGitHub réelles du dépôt VS Code (`microsoft/vscode`, ex-`vscode-copilot-chat`\narchivé et fusionné dedans le 2026-05-20) la tranchent, avec confirmation\ndirecte par un membre de l'équipe VS Code :\n\n### `SKILL.md` n'a aucun moyen de restreindre ou d'élargir les outils — confirmé par le code lui-même\n\n[Issue #293276](https://github.com/microsoft/vscode/issues/293276) (« Skills:\nScoped tool permissions ») cite le message d'erreur exact du validateur\nVS Code actuel quand on tente d'ajouter `allowed-tools` à un `SKILL.md` :\n\n> *\"Attribute 'allowed-tools' is not supported in skill files. Supported:\n> compatibility, description, license, metadata, name.\"*\n\n— message confirmé par `anladwig` (membre de l'équipe VS Code), qui note que\n`allowed-tools` fait pourtant partie du standard ouvert (`agentskills.io`)\nmais n'est **pas encore implémenté côté VS Code**. Un commentateur\n(`siegenthalerroger`) demande explicitement *\"Is the `tools` field available\nin a SKILL.md frontmatter?\"* — réponse : non, ni documenté ni accepté par le\nvalidateur.\n\n**Conséquence directe, confirmée** : un `SKILL.md`, quel que soit l'outil qui\nle charge (Claude Code excepté, qui honore sa propre extension\n`allowed-tools`), ne peut ni accorder ni retirer de capacité — c'est du texte\npur, injecté dans le contexte de l'agent déjà actif.\n\n### La restriction d'outils vient donc uniquement de l'agent actif — et elle s'applique bien aux skills\n\n[Issue #307630](https://github.com/microsoft/vscode/issues/307630) (« per-agent\nskill scoping ») confirme, en creusant le problème inverse (pas de moyen de\nrestreindre QUELS skills un agent voit) :\n\n> *\"Custom agents (`.agent.md`) support a `tools` property to restrict which\n> tools are available per agent. However, there is no equivalent mechanism for\n> **skills**... All skills from all discovery locations... are visible to all\n> agents simultaneously.\"*\n\nEt cite comme cas d'usage non résolu, mot pour mot notre situation :\n\n> *\"Security/principle of least privilege: Some agents should be read-only\n> (already possible via `tools`), but they also shouldn't have access to\n> skills that trigger write operations via their instructions.\"*\n\n**Ce que ça confirme pour mA.xI.me** : `tools:` sur un Custom Agent (`.agent.md`)\nest un mécanisme **réel et fonctionnel** — c'est le seul niveau où la\nrestriction d'outils existe concrètement côté Copilot. Un Skill chargé\npendant que `maxi-copilot-reviewer` (`tools: [read, search]`) est actif ne\npeut **pas** faire apparaître `edit`/`execute` : ces outils ne sont\nsimplement pas dans la liste dont dispose le modèle à ce moment-là, peu\nimporte ce que le texte du skill suggère. **La garantie lecture-seule tient\ndonc, à condition que l'agent restreint soit explicitement actif au moment\nde l'invocation.**\n\nLe risque réel n'est donc pas \"le skill contourne la restriction\" — c'est\n\"aucune restriction n'est active si l'utilisateur invoque le workflow depuis\nun contexte non restreint\" (chat par défaut, ou l'agent `maxi-copilot` lui-même,\nqui a `edit`+`execute`). Dans ce cas, peu importe lequel des trois SKILL.md\nhomonymes charge : aucun n'a jamais eu la capacité de restreindre quoi que ce\nsoit — c'était déjà vrai avant même la découverte de `.agents/skills/`.\n\n### Contournement documenté par la communauté (imparfait, mais réel)\n\nUn des commentaires sur #307630 documente le seul palliatif existant\naujourd'hui : ajouter dans le corps de l'agent (`.agent.md`) une consigne\nexplicite du type *\"only load skills from this directory\"* — *\"this works\nreasonably well because the model follows instructions, but it's not\nenforced by the system and doesn't filter the `/` menu\"*. C'est exactement le\nmême type de garantie que celle déjà documentée pour Codex dans\n`docs/ARCHITECTURE.md` (consigne textuelle, pas verrou technique) — pas une\nsolution, une atténuation.\n\n### Suivi amont (pour re-vérifier plus tard si le paysage change)\n\n- [#293276](https://github.com/microsoft/vscode/issues/293276) — auto-approbation d'outils scopée à un skill (ouvert)\n- [#307630](https://github.com/microsoft/vscode/issues/307630) — scoper quels skills un agent peut voir (ouvert)\n- [#313951](https://github.com/microsoft/vscode/issues/313951) / [#311166](https://github.com/microsoft/vscode/issues/311166) — déclaration de capacités (`tools`, `mcp-servers`, `hooks`, `model`) dans le frontmatter `SKILL.md` (ouverts, doublons du même besoin)\n- [#294520](https://github.com/microsoft/vscode/issues/294520) — validation du frontmatter rejetait des attributs inconnus, cassant l'extensibilité du standard (fermé)\n\n## Ce qui reste réellement incertain\n\n- Priorité exacte entre `.github/skills/`, `.claude/skills/`, `.agents/skills/`\n quand le même nom existe aux trois emplacements — non documentée, et sans\n incidence pratique vu ce qui précède (aucun des trois ne restreint quoi que\n ce soit de toute façon).\n- Le paramètre `chat.useAgentSkills` doit être actif pour que la découverte de\n skills fonctionne du tout (confirmé, notes de version VS Code 1.108) — le\n désactiver empêcherait Copilot de charger `.agents/skills/maxime-review`,\n au prix de perdre Agent Skills partout dans le workspace, pas seulement\n pour mA.xI.me.\n\n## Sources consultées\n\n- [agentskills.io — Agent Skills Overview](https://agentskills.io)\n- [code.claude.com/docs/en/skills — Extend Claude with skills](https://code.claude.com/docs/en/skills)\n- [code.claude.com/docs/en/vs-code — Use Claude Code in VS Code](https://code.claude.com/docs/en/vs-code)\n- [code.visualstudio.com/docs/agent-customization/overview](https://code.visualstudio.com/docs/agent-customization/overview)\n- [code.visualstudio.com/docs/agent-customization/custom-agents](https://code.visualstudio.com/docs/agent-customization/custom-agents)\n- [code.visualstudio.com/docs/agent-customization/agent-skills](https://code.visualstudio.com/docs/agent-customization/agent-skills) (déjà utilisée dans la fiche KB du 2026-07-12 sur les outils built-in)\n- [docs.github.com — About custom agents](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-custom-agents)\n- [learn.chatgpt.com/docs/codex/ide](https://learn.chatgpt.com/docs/codex/ide) (Codex IDE extension, redirigé depuis developers.openai.com/codex/ide)\n- [learn.chatgpt.com/docs/agent-configuration/agents-md](https://learn.chatgpt.com/docs/agent-configuration/agents-md) (redirigé depuis developers.openai.com/codex/guides/agents-md)\n- [developers.openai.com/codex/skills](https://developers.openai.com/codex/skills)\n- [agentskills.io/specification](https://agentskills.io/specification) — spécification complète du format\n- [github.com/microsoft/vscode/issues/293276](https://github.com/microsoft/vscode/issues/293276) — confirmation directe (membre équipe VS Code) que `allowed-tools` n'est pas implémenté\n- [github.com/microsoft/vscode/issues/307630](https://github.com/microsoft/vscode/issues/307630) — absence de scoping skill/agent, cas d'usage identique au nôtre\n- [learn.microsoft.com/.../copilot-agent-skills](https://learn.microsoft.com/en-us/visualstudio/ide/copilot-agent-skills?view=visualstudio) — doc Visual Studio (IDE complet, pas VS Code), mêmes trois emplacements confirmés\n- [code.visualstudio.com/updates/v1_108](https://code.visualstudio.com/updates/v1_108) — notes de version, confirme `.claude/skills/` scanné \"for backwards compatibility\" et le paramètre `chat.useAgentSkills`\n\n## Liens\n\nVoir aussi [[20260712.new.vscode-copilot-builtin-tools]] (catégories d'outils\nbuilt-in Copilot/VS Code — sujet voisin mais distinct : celui-là porte sur les\noutils, celui-ci sur la découverte de skills/agents).\n" } \ No newline at end of file diff --git a/active/aws/ecs-fargate-task-isolation.json b/active/aws/ecs-fargate-task-isolation.json index a91b930..4869c2d 100644 --- a/active/aws/ecs-fargate-task-isolation.json +++ b/active/aws/ecs-fargate-task-isolation.json @@ -20,7 +20,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "zero-standing-access" ], diff --git a/active/claude-config/claude-md-hierarchie.json b/active/claude-config/claude-md-hierarchie.json index c6b178d..fe0eaa2 100644 --- a/active/claude-config/claude-md-hierarchie.json +++ b/active/claude-config/claude-md-hierarchie.json @@ -11,7 +11,6 @@ "source": ["https://code.claude.com/docs/en/memory"], "validated": "2026-06-16", "created": "2026-06-16", - "ttl_days": 90, "links": ["claude-md-import-mechanism"], "content": "# Hiérarchie & chargement des CLAUDE.md (Claude Code)\n\nStatut : `.new` — capture brute de recherche du 2026-06-16 (bootstrap du\nprojet), déplacée de `docs/CLAUDE-MD-HIERARCHIE.md` le 2026-07-13 : contenu\ngénérique réutilisable sur la plateforme Claude Code, sans donnée de\nprojet/client/employeur, pas encore relu/validé comme fiche KB stable.\n\nSource officielle (lue et vérifiée) : [claude memory docs](https://code.claude.com/docs/en/memory)\n\n---\n\n## 1. Les 4 niveaux (par ordre de chargement, du plus large au plus spécifique)\n\n| Scope | Emplacement | Rôle | Partagé avec |\n| - | - | - | - |\n| **Managed policy** | macOS : `/Library/Application Support/ClaudeCode/CLAUDE.md`
Linux/WSL : `/etc/claude-code/CLAUDE.md`
Windows : `C:\\Program Files\\ClaudeCode\\CLAUDE.md` | Instructions imposées par l'organisation (IT/DevOps) : standards, sécurité, conformité | Tous les utilisateurs de la machine/org |\n| **User instructions** | `~/.claude/CLAUDE.md` | Préférences personnelles, tous projets | Moi seul (tous projets) |\n| **Project instructions** | `./CLAUDE.md` ou `./.claude/CLAUDE.md` | Instructions partagées de l'équipe | L'équipe via le contrôle de source |\n| **Local instructions** | `./CLAUDE.local.md` | Préférences perso d'un projet ; à mettre dans `.gitignore` | Moi seul (projet courant) |\n\nLes niveaux se **cumulent** (concaténés), ils ne s'écrasent pas.\n\n---\n\n## 2. Comment le chargement fonctionne RÉELLEMENT (le point clé)\n\nClaude Code ne lit pas une liste fixe d'emplacements. Il **remonte l'arborescence**\ndepuis le répertoire de travail (cwd) jusqu'à la racine, et charge chaque\n`CLAUDE.md` et `CLAUDE.local.md` rencontré en chemin.\n\nExemple : lancé dans `foo/bar/`, il charge `foo/bar/CLAUDE.md`, puis `foo/CLAUDE.md`,\nplus les `CLAUDE.local.md` à côté.\n\n**Ordre dans le contexte** : de la racine du système vers le cwd. Donc les\ninstructions les plus proches de l'endroit où tu lances Claude sont lues **en\ndernier**. En cas de contradiction, le \"dernier lu\" agit comme un signal de priorité.\nDans chaque dossier, `CLAUDE.local.md` est ajouté APRÈS `CLAUDE.md`.\n\nLes `CLAUDE.md` des sous-dossiers (sous le cwd) ne sont PAS chargés au lancement :\nils se chargent à la demande quand Claude lit un fichier de ce sous-dossier.\n\n### ⚠️ Piège vécu (2026-06-16)\n\nLe niveau \"Project\" est relatif au cwd. Lancer Claude Code depuis un dossier qui\nn'est pas un repo git (ex : `C:\\Users\\` ou `...\\source\\repos`) fait que\n`./CLAUDE.md` se rabat sur le `CLAUDE.md` de CE dossier. C'est ce qui avait créé\nl'illusion d'un \"CLAUDE.md à la racine du profil\" : ce n'était pas un emplacement\nofficiel séparé, juste un palier de la remontée d'arbre.\n→ **Toujours lancer Claude Code depuis un vrai repo git** pour que le niveau\nProject pointe au bon endroit.\n\n---\n\n## 3. CLAUDE.md ≠ configuration imposée (TRÈS important)\n\n> Les CLAUDE.md (et l'auto memory) sont traités comme du **contexte**, pas comme\n> de la configuration appliquée de force. Pour bloquer une action quoi que Claude\n> décide, il faut un **hook PreToolUse**, pas une ligne de texte.\n\nConséquence directe pour nos \"règles inviolables\" (jamais `git add -A`, jamais main) :\n\n- Écrites dans le CLAUDE.md = instructions FORTES, mais pas un verrou.\n- Pour un vrai blocage technique → **hook** (`PreToolUse`) ou **managed settings**\n (`permissions.deny`). À considérer pour les garde-fous critiques.\n\nCLAUDE.md content est délivré comme un message utilisateur après le system prompt :\nClaude le lit et tente de le suivre, sans garantie de conformité stricte —\nsurtout si les instructions sont vagues ou contradictoires.\n\n---\n\n## 4. Bonnes pratiques d'écriture (officiel)\n\n- **Taille** : viser **< 200 lignes** par CLAUDE.md. Plus long = plus de contexte\n consommé et **moins bonne adhérence**. (Cette limite des 200 lignes / 25 KB\n s'applique à `MEMORY.md` de l'auto-memory ; les CLAUDE.md, eux, sont chargés en\n entier quelle que soit la longueur — mais plus court = mieux suivi.)\n- **Spécificité** : \"Use 2-space indentation\" plutôt que \"format code properly\".\n \"Run `npm test` before committing\" plutôt que \"test your changes\".\n- **Structure** : titres markdown + bullets. Claude scanne la structure comme un lecteur.\n- **Cohérence** : si deux règles se contredisent, Claude en choisit une arbitrairement.\n Revoir périodiquement pour retirer le contradictoire ou l'obsolète.\n\n---\n\n## 5. Astuces utiles découvertes\n\n### Commentaires HTML = notes gratuites\n\nLes commentaires HTML de niveau bloc `` sont **retirés avant injection**\ndans le contexte. → Laisser des notes aux mainteneurs humains SANS consommer de\ntokens. (Les commentaires DANS un bloc de code sont, eux, préservés. Et `Read`\nsur le fichier les montre.)\n\n### Imports `@path`\n\nUn CLAUDE.md peut importer d'autres fichiers via `@chemin/fichier`. Chemins relatifs\n(résolus par rapport au fichier qui importe) ou absolus. Récursif, max 4 niveaux.\n⚠️ Les fichiers importés sont chargés au lancement → ça n'économise PAS de contexte,\nça organise seulement.\nExemple : `# git workflow @docs/git-instructions.md`\nPartager du perso entre worktrees : `@~/.claude/my-project-instructions.md`.\n\n### `/init` pour démarrer un CLAUDE.md projet\n\nAnalyse le codebase et génère un CLAUDE.md de départ (build, tests, conventions).\nS'il existe déjà, `/init` propose des améliorations au lieu d'écraser.\n`CLAUDE_CODE_NEW_INIT=1` active un flux interactif multi-phases.\n\n### AGENTS.md\n\nClaude Code lit `CLAUDE.md`, pas `AGENTS.md`. Si un repo a déjà un AGENTS.md :\ncréer un CLAUDE.md qui l'importe → `@AGENTS.md` (puis ajouter des instructions\nClaude-spécifiques en dessous). Sur Windows, préférer l'import `@AGENTS.md` au\nsymlink (le symlink exige les droits admin / mode développeur).\n\n### `.claude/rules/` pour les gros projets\n\nDécouper en fichiers par sujet (`testing.md`, `security.md`...). Chargés à chaque\nsession avec la même priorité que `.claude/CLAUDE.md`. Peuvent être **scopés par\nchemin** via frontmatter `paths:` (glob) → ne se chargent que quand Claude touche\nles fichiers correspondants = moins de bruit, contexte économisé.\nRègles user-level : `~/.claude/rules/` (préférences perso, tous projets).\nPartage entre projets via symlinks.\n\n### Skills vs rules vs CLAUDE.md (quand utiliser quoi)\n\n- **CLAUDE.md** : faits à garder chaque session (build, conventions, \"always X\").\n- **Rules** (`.claude/rules/`) : modulaire, scopable par chemin, chargé en contexte.\n- **Skills** : workflows répétables, chargés UNIQUEMENT à l'invocation ou quand\n Claude juge pertinent. Pour les procédures qui n'ont pas à être en contexte tout le temps.\n\n### Monorepo — exclure des CLAUDE.md parasites\n\n`claudeMdExcludes` (dans `.claude/settings.local.json`) saute des CLAUDE.md\nd'autres équipes par chemin/glob. Les managed policy ne peuvent PAS être exclus.\n\n### Survie au /compact\n\nLe CLAUDE.md de racine de projet survit au `/compact` (re-lu depuis le disque).\nLes CLAUDE.md de sous-dossiers ne sont pas réinjectés auto : ils rechargent au\nprochain accès à un fichier de ce sous-dossier. → Mettre dans CLAUDE.md ce qui\nne doit pas se perdre (pas seulement dans la conversation).\n\n### Débogage \"Claude ne suit pas mon CLAUDE.md\"\n\n1. `/memory` → vérifier que le fichier est bien listé (sinon Claude ne le voit pas).\n2. Vérifier que l'emplacement est bien chargé pour la session (cf. remontée d'arbre).\n3. Rendre les instructions plus spécifiques.\n4. Chercher les contradictions entre fichiers.\n5. Si ça doit s'exécuter à un moment précis (avant chaque commit...) → **hook**, pas CLAUDE.md.\nAstuce : hook `InstructionsLoaded` pour logger quels fichiers d'instructions\nsont chargés, quand et pourquoi.\n\n---\n\n## 6. CLAUDE_CONFIG_DIR (notre cas)\n\nDéplace le dossier de config (`~/.claude` → dossier choisi). Vérifié sur la\nmachine : elle ne redirige pas le chargement des CLAUDE.md comme on pourrait le\ncroire ; elle déplace surtout l'état local (auto-memory, sessions).\n→ Par défaut : NE PAS la définir. Rester au standard. (On l'a retirée le 2026-06-16.)\n\nNB auto-memory : chaque projet a `~/.claude/projects//memory/` avec un\n`MEMORY.md` (index, 200 lignes / 25 KB chargées par session) + fichiers par sujet\nchargés à la demande. `` dérive du repo git → hors repo git, c'est la\nracine du dossier qui sert. Raison de plus pour travailler dans de vrais repos git.\n\n---\n\n## 7. Application à mA.xI.me (déjà documenté ailleurs, gardé pour mémoire)\n\nCe document décrit les mécanismes propres à Claude Code ; il ne définit pas le socle\nuniversel de mA.xI.me (voir `core/socle.md` et `docs/ARCHITECTURE.md`).\n\n- **Socle mA.xI.me** → `core/socle.md`, projeté dans le `CLAUDE.md` du repository\n cible par l'installateur repo-only.\n- **Orchestrateur** → agent `maxi-claude` et workflows sous `.claude/` dans le\n repository cible, sans installation sous `~/.claude/` par mA.xI.me.\n- **État partagé** → `.wip/`, lu également par les adaptateurs Copilot et Codex.\n- **Garde-fous critiques** → le hook Claude peut compléter le texte, mais n'est pas\n une garantie portable aux autres hôtes.\n- **KB** → submodule `knowledge-base/` relatif au repository si le projet l'utilise.\n" } \ No newline at end of file diff --git a/active/claude-config/claude-md-import-mechanism.json b/active/claude-config/claude-md-import-mechanism.json index 3233f0a..a500a0c 100644 --- a/active/claude-config/claude-md-import-mechanism.json +++ b/active/claude-config/claude-md-import-mechanism.json @@ -11,7 +11,6 @@ "source": ["https://code.claude.com/docs/en/memory", "https://github.com/anthropics/claude-code/issues/2950", "https://github.com/anthropics/claude-code/issues/8533", "https://github.com/anthropics/claude-code/issues/1041", "https://github.com/anthropics/claude-code/issues/5231", "https://github.com/anthropics/claude-code/issues/7768"], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 90, "links": ["claude-md-hierarchie", "copilot-instructions-merge", "codex-agents-md-nesting"], "content": "# Claude Code — mécanisme d'import @fichier pour CLAUDE.md\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27 (l'installateur écrase un CLAUDE.md project-specific existant).\n\n## Ce qui est confirmé (sourcé)\n\n- La syntaxe `@chemin/fichier` est un import officiel et documenté : chemins relatifs (résolus par rapport au fichier qui importe, pas au cwd) ou absolus. Récursion jusqu'à 4 niveaux. Le parseur d'imports ignore les blocs de code et le code inline (`@README` entre backticks reste littéral). Source : https://code.claude.com/docs/en/memory\n- **Directement pertinent** : la documentation Anthropic elle-même recommande exactement le pattern inverse de notre cas d'usage — pour un repo qui a déjà un AGENTS.md, créer un CLAUDE.md qui fait `@AGENTS.md` puis ajoute du contenu Claude-spécifique en dessous. Ça confirme qu'une ligne `@import` est un contenu stable, générable par un outil : le générateur peut toujours émettre la même ligne d'import, elle continuera à se résoudre tant que le fichier cible existe.\n- Les CLAUDE.md de l'arborescence sont concaténés, jamais remplacés — le fichier du dossier parent charge avant celui du cwd, et `CLAUDE.local.md` est ajouté après `CLAUDE.md` dans le même dossier.\n- `/init` ne réécrit jamais un CLAUDE.md existant — il propose seulement des améliorations.\n- Alternative sans syntaxe d'import du tout : `.claude/rules/*.md` — tout fichier `.md` déposé là charge automatiquement (même priorité que `.claude/CLAUDE.md`), scopable par `paths:` en frontmatter. Symlinks supportés pour partager des règles entre repos.\n- La première utilisation d'un import externe déclenche une boîte de dialogue d'approbation ponctuelle ; refuser désactive silencieusement les imports pour le projet en permanence (risque d'échec silencieux si l'utilisateur a cliqué \"non\" une fois).\n\n## Incertitudes explicites\n\n- Aucune confirmation de mainteneur que les imports sont fiables à 100% : issue GitHub ouverte #2950 (anthropics/claude-code) rapporte que l'import est chargé en contexte mais Claude n'agit pas toujours dessus de façon déterministe (problème d'adhérence du modèle, pas de résolution de fichier).\n- Plusieurs rapports de bugs de résolution/imbrication de chemins @ : #8533 (Claude n'écrit pas toujours la syntaxe @ correctement quand on le lui demande), #1041 (l'import échoue spécifiquement dans le CLAUDE.md global ~/.claude/CLAUDE.md), #5231, #7768 (comportement erratique sur des imports imbriqués/relatifs). Rien n'indique que ce soit corrigé à la date de cette recherche.\n- Aucun fil Reddit/Discord trouvé spécifiquement sur un outil générateur qui réécrit CLAUDE.md pendant que les imports survivent — le cas le plus proche est l'exemple AGENTS.md d'Anthropic ci-dessus, direct mais pas issu de la communauté.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nDeux mécanismes natifs viables : (a) le générateur émet toujours une ligne fixe `@project-conventions.md` (ou nom similaire) — la doc Anthropic elle-même valide ce pattern exact ; ou (b) ne jamais toucher CLAUDE.md pour du contenu projet, et faire écrire par l'installateur dans `.claude/rules/*.md` à la place — élimine le problème à la racine puisque le générateur ne possède jamais ce fichier.\n\n## Sources\n- https://code.claude.com/docs/en/memory\n- https://github.com/anthropics/claude-code/issues/2950\n- https://github.com/anthropics/claude-code/issues/8533\n- https://github.com/anthropics/claude-code/issues/1041\n- https://github.com/anthropics/claude-code/issues/5231\n- https://github.com/anthropics/claude-code/issues/7768" } \ No newline at end of file diff --git a/active/codex-config/codex-agents-md-nesting.json b/active/codex-config/codex-agents-md-nesting.json index 3900683..5ec04e2 100644 --- a/active/codex-config/codex-agents-md-nesting.json +++ b/active/codex-config/codex-agents-md-nesting.json @@ -11,7 +11,6 @@ "source": ["https://learn.chatgpt.com/docs/agent-configuration/agents-md"], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 90, "links": ["claude-md-import-mechanism", "copilot-instructions-merge"], "content": "# OpenAI Codex — imbrication et fusion des fichiers AGENTS.md\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27.\n\n## Ce qui est confirmé (sourcé)\n\n- Support officiel de fichiers AGENTS.md imbriqués, fusionnés de la racine vers la feuille, concaténés avec des lignes vides ; les fichiers les plus proches du cwd sont ajoutés en dernier et peuvent surcharger les instructions précédentes. Source : https://learn.chatgpt.com/docs/agent-configuration/agents-md\n- Un mécanisme explicite AGENTS.override.md existe, au niveau global (~/.codex/) comme à tout niveau de dossier projet ; Codex vérifie d'abord la présence d'un override, puis se rabat sur AGENTS.md, puis sur les noms de fallback configurés — au plus un fichier utilisé par dossier.\n- Aucune syntaxe d'import/inclusion à l'intérieur d'un seul AGENTS.md — la fusion est purement basée sur la hiérarchie de dossiers.\n- Plafond de taille : 32 KiB combinés par défaut (project_doc_max_bytes), configurable.\n- Le site de spécification communautaire agents.md corrobore : \"le AGENTS.md le plus proche gagne\", conçu explicitement pour des instructions par paquet dans des monorepos (cite le repo d'OpenAI lui-même utilisant 88 fichiers AGENTS.md).\n\n## Incertitudes explicites\n\n- Aucune issue GitHub ni fil Reddit/HN trouvé spécifiquement sur un outil qui réécrit un contenu AGENTS.md écrit à la main — les recherches n'ont renvoyé que de la documentation officielle ou dérivée, aucun fil de plainte concret.\n- Aucune couverture YouTube trouvée traitant spécifiquement de ce problème de coexistence.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nPartielle : pas de syntaxe d'import, mais le mécanisme override + fichiers imbriqués donne une voie équivalente — plus directement, faire écrire par le générateur dans AGENTS.override.md au lieu de AGENTS.md au même niveau de dossier, laissant tout AGENTS.md pré-existant écrit à la main intact et toujours utilisé comme couche de base que l'override étend. C'est un détournement du mécanisme (les fichiers override étaient conçus pour restreindre, pas pour séparer outil/humain) — à traiter comme fonctionnel mais non validé par la doc pour cet usage précis.\n\n## Sources\n- https://learn.chatgpt.com/docs/agent-configuration/agents-md" } \ No newline at end of file diff --git a/active/engine-catalog/claude-code-models.json b/active/engine-catalog/claude-code-models.json index 96dfd17..4233ed9 100644 --- a/active/engine-catalog/claude-code-models.json +++ b/active/engine-catalog/claude-code-models.json @@ -16,7 +16,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 60, "links": ["copilot-models", "codex-models"], "content": "# Claude Code — moteurs (modèles) et effort\n\n## Deux axes distincts, pas un seul\n\nClaude Code expose deux réglages indépendants, avec des règles d'auto-configuration différentes pour chacun — à ne pas confondre :\n\n1. **`model`** (moteur) : `sonnet`, `opus`, `haiku`, `fable`, `inherit`, ou un ID de modèle complet (ex. `claude-opus-4-8`).\n2. **`effort`** : `low`, `medium`, `high` (défaut), `xhigh`, `max` — contrôle la profondeur de réflexion et le volume de tokens dépensés, indépendamment du modèle choisi.\n\nCorrection par rapport à une hypothèse de recherche antérieure (2026-07-16, avant cette fiche) : l'effort n'est **plus** \"encodé dans le choix du modèle\" — c'est un paramètre API à part entière (`output_config.effort`), disponible sur Claude Fable 5, Claude Mythos 5, Opus 4.5 à 4.8, Sonnet 5, Sonnet 4.6. Il affecte tous les tokens de la réponse (texte, appels d'outils, réflexion étendue), pas seulement la réflexion.\n\n## Qui peut configurer quoi\n\n- **`model` par sous-agent : auto-configurable, confirmé.** Le paramètre `model` de l'outil `Agent`/`Task` (dans cet environnement même) prend le pas sur la définition de l'agent (frontmatter `model:`), documenté \"takes precedence over the agent definition's model frontmatter\". Un orchestrateur peut donc choisir le modèle d'un sous-agent qu'il délègue, sans intervention humaine à chaque appel. Défaut du frontmatter : `inherit` (même modèle que la session principale) si non précisé.\n- **`model` pour l'agent en cours (pas un sous-agent) : PAS auto-configurable.** Rien ne permet à l'agent en cours d'exécution de changer son propre modèle en cours de session par une action programmatique (un humain peut le faire via `/fast` ou le picker, mais c'est une commande, pas une action de l'agent lui-même).\n- **`effort` : PAS configurable par sous-agent, contrairement au modèle.** Sourcé sur une issue GitHub officielle (`anthropics/claude-code#25669`, feature request encore ouverte) : \"All subagents inherit the session default as there is no way to set the main agent to high and subagents to low.\" C'est un réglage de session, pas un paramètre de l'outil `Agent`/`Task` (vérifié directement : le schéma de cet outil dans cet environnement n'expose que `model`, aucun paramètre d'effort).\n\n## Conséquence pour Maxime\n\nMaxime (l'orchestrateur Claude) peut choisir lui-même le **modèle** d'un sous-agent qu'il délègue, informé par la taille de la tâche (S/M/L/XL) — capacité technique réelle, sans confirmation humaine requise à chaque appel. Il ne peut en revanche pas différencier l'**effort** par sous-agent : c'est un réglage de session, identique pour tous les agents de la conversation en cours, changé par un humain (menu effort de Claude Code, ou API `output_config.effort` en dehors de Claude Code).\n\n## Note annexe — \"ultracode\"\n\n\"ultracode\" apparaît dans le menu effort de Claude Code mais n'est pas un niveau d'effort API supplémentaire : ça combine `xhigh` avec une permission permanente de lancer des workflows multi-agents (mécanisme \"Mid-conversation system messages\"). Mentionné pour éviter de le confondre avec un 6e niveau d'effort — il n'y en a que 5 (`low`/`medium`/`high`/`xhigh`/`max`), tous documentés sur la page source `effort`.\n\n## Ce qui reste incertain\n\n- Le menu effort de Claude Code (accessible par un humain) n'a pas de commande/flag documenté officiellement pour être piloté par un script/agent plutôt qu'une interaction utilisateur directe — non vérifié plus loin, hors périmètre de cette fiche.\n" } diff --git a/active/engine-catalog/codex-models.json b/active/engine-catalog/codex-models.json index cad967b..a391fc4 100644 --- a/active/engine-catalog/codex-models.json +++ b/active/engine-catalog/codex-models.json @@ -15,7 +15,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 60, "links": ["claude-code-models", "copilot-models"], - "content": "# Codex — moteurs (modèles) et effort\n\n## Correction d'une hypothèse de recherche antérieure\n\nLa spec de travail précédente (2026-07-16, avant cette fiche) citait une source tierce non officielle (`codex.danielvaughan.com`, un blog) affirmant que Codex serait \"probablement auto-configurable via un fichier de config par agent\". **Vérifié sur source officielle OpenAI ce jour et infirmé** : `model` et `model_reasoning_effort` sont des réglages **globaux/de profil**, pas par agent ou sous-agent.\n\n## Ce qui est confirmé sur source officielle\n\n- **`model`** (ex. `gpt-5.5`) et **`model_reasoning_effort`** (`none`/`minimal`/`low`/`medium`/`high`/`xhigh` — `xhigh` dépend du modèle ; s'applique à la Responses API uniquement) sont définis dans `~/.codex/config.toml`, au niveau global de l'utilisateur.\n- **Profils** : des couches de configuration nommées, activées via `--profile nom-du-profil` en CLI, qui surchargent la config de base — un choix fait **avant le lancement**, par un humain (ou un script qui invoque la CLI), jamais pendant une session en cours.\n- **Aucune surcharge par agent, sous-agent, session ou requête individuelle n'est documentée** pour `model`/`model_reasoning_effort`. Une section `[agents]` existe bien dans `config.toml` pour configurer des **rôles** de sous-agents, mais rien dans la documentation officielle ne montre qu'elle couvre le modèle ou l'effort — elle configure autre chose (comportement/rôle, pas moteur).\n- **Aucun mécanisme documenté pour qu'une session Codex en cours change son propre modèle ou effort en cours de route** — fixé au lancement par la configuration.\n- Confirmation supplémentaire par l'absence : une issue GitHub officielle du dépôt `openai/codex`, encore ouverte, demande explicitement cette capacité (\"Allow configuring subagent model and reasoning_effort in config\", [#11795](https://github.com/openai/codex/issues/11795)) — la demande elle-même confirme que ça n'existe pas encore.\n\n## Conséquence pour Maxime\n\nTraiter Codex comme Copilot, pas comme Claude Code : Maxime ne peut pas configurer lui-même le modèle ou l'effort pour une tâche ou un sous-agent Codex. Il peut seulement **recommander** un modèle/effort informé par le catalogue et **demander** à l'utilisateur de le sélectionner (choix de profil ou flag `--model`/`--config model_reasoning_effort=...` avant le lancement). Repasser en mode \"auto-configurable comme Claude\" seulement si OpenAI documente officiellement une surcharge par agent/sous-agent dans une future version — revalider via `ttl_days` avant de considérer ce point comme stable.\n\n## Ce qui reste incertain\n\n- Le contenu exact de la section `[agents]` (quels attributs de \"rôle\" elle couvre réellement) n'a pas été creusé en détail — hors périmètre de cette fiche, qui se limite à la question modèle/effort.\n" + "content": "# Codex — moteurs (modèles) et effort\n\n## Correction d'une hypothèse de recherche antérieure\n\nLa spec de travail précédente (2026-07-16, avant cette fiche) citait une source tierce non officielle (`codex.danielvaughan.com`, un blog) affirmant que Codex serait \"probablement auto-configurable via un fichier de config par agent\". **Vérifié sur source officielle OpenAI ce jour et infirmé** : `model` et `model_reasoning_effort` sont des réglages **globaux/de profil**, pas par agent ou sous-agent.\n\n## Ce qui est confirmé sur source officielle\n\n- **`model`** (ex. `gpt-5.5`) et **`model_reasoning_effort`** (`none`/`minimal`/`low`/`medium`/`high`/`xhigh` — `xhigh` dépend du modèle ; s'applique à la Responses API uniquement) sont définis dans `~/.codex/config.toml`, au niveau global de l'utilisateur.\n- **Profils** : des couches de configuration nommées, activées via `--profile nom-du-profil` en CLI, qui surchargent la config de base — un choix fait **avant le lancement**, par un humain (ou un script qui invoque la CLI), jamais pendant une session en cours.\n- **Aucune surcharge par agent, sous-agent, session ou requête individuelle n'est documentée** pour `model`/`model_reasoning_effort`. Une section `[agents]` existe bien dans `config.toml` pour configurer des **rôles** de sous-agents, mais rien dans la documentation officielle ne montre qu'elle couvre le modèle ou l'effort — elle configure autre chose (comportement/rôle, pas moteur).\n- **Aucun mécanisme documenté pour qu'une session Codex en cours change son propre modèle ou effort en cours de route** — fixé au lancement par la configuration.\n- Confirmation supplémentaire par l'absence : une issue GitHub officielle du dépôt `openai/codex`, encore ouverte, demande explicitement cette capacité (\"Allow configuring subagent model and reasoning_effort in config\", [#11795](https://github.com/openai/codex/issues/11795)) — la demande elle-même confirme que ça n'existe pas encore.\n\n## Conséquence pour Maxime\n\nTraiter Codex comme Copilot, pas comme Claude Code : Maxime ne peut pas configurer lui-même le modèle ou l'effort pour une tâche ou un sous-agent Codex. Il peut seulement **recommander** un modèle/effort informé par le catalogue et **demander** à l'utilisateur de le sélectionner (choix de profil ou flag `--model`/`--config model_reasoning_effort=...` avant le lancement). Repasser en mode \"auto-configurable comme Claude\" seulement si OpenAI documente officiellement une surcharge par agent/sous-agent dans une future version — revalider ce point avant de le considérer comme stable.\n\n## Ce qui reste incertain\n\n- Le contenu exact de la section `[agents]` (quels attributs de \"rôle\" elle couvre réellement) n'a pas été creusé en détail — hors périmètre de cette fiche, qui se limite à la question modèle/effort.\n" } diff --git a/active/engine-catalog/copilot-models.json b/active/engine-catalog/copilot-models.json index 04ab6b0..7e660a3 100644 --- a/active/engine-catalog/copilot-models.json +++ b/active/engine-catalog/copilot-models.json @@ -18,7 +18,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 60, "links": ["claude-code-models", "codex-models"], "content": "# GitHub Copilot — moteurs (modèles) et effort\n\nDeux surfaces distinctes chez Copilot, vérifiées séparément : les agents personnalisés CLI/VS Code (fichiers `.agent.md`) et le **cloud agent** (github.com — issues assignées, commentaires `@copilot`, agents tab). Conclusion identique sur le fond pour les deux : **jamais auto-configurable par l'agent lui-même**, mais les mécanismes diffèrent.\n\n## CLI / VS Code (agents personnalisés `.agent.md`)\n\n- **`model` : fixé par un humain à l'écriture du fichier, jamais changé par l'agent en cours d'exécution.** Le frontmatter `model:` d'un agent personnalisé contrôle le modèle utilisé (VS Code, JetBrains, Eclipse, Xcode). Un `model` passé programmatiquement à un appel `task()` est **silencieusement ramené au modèle de session par défaut** — confirmé par une issue GitHub officielle du dépôt `github/copilot-cli` encore ouverte ([#2758](https://github.com/github/copilot-cli/issues/2758), présentée comme un garde-fou de coût intentionnel, pas un bug).\n- **`effort` : n'existe pas dans le frontmatter d'agent personnalisé aujourd'hui.** Feature request encore ouverte ([#2904](https://github.com/github/copilot-cli/issues/2904), \"Custom Agent YAML Frontmatter Should Support Reasoning Effort\") — pas de mécanisme équivalent au `effort`/`model_reasoning_effort` de Claude ou Codex côté Copilot à ce jour. Seul un humain change le modèle, via `/model` ou le picker VS Code ; il n'y a rien d'équivalent à changer pour l'effort.\n\n## Cloud agent (github.com)\n\n- **`model` : sélection humaine uniquement, confirmée explicitement.** \"Only human users select the model. The agent does not programmatically choose or change its model during a task.\" Disponible aux points d'entrée supportés : assignation d'issue, mention `@copilot` en commentaire de PR, agents tab/panel, GitHub Mobile, lanceur Raycast. Modèles proposés (2026) : Claude Opus 4.5/4.6, Claude Sonnet 4.5/4.6, Claude Haiku 4.5, GPT-5.1-Codex-Max, GPT-5.2/5.3-Codex, GPT-5.4-mini.\n- **Option \"Auto\" : une troisième voie, ni humaine au cas par cas, ni agent.** Si l'utilisateur sélectionne \"Auto\" dans le picker (choix humain fait une fois, avant la tâche), la plateforme elle-même choisit ensuite le modèle \"based on system health and model performance\" — routage de plateforme, pas une décision de l'agent en cours de tâche. Avantage : remise de 10% sur le multiplicateur, exempté des limites de débit hebdomadaires.\n- **`effort` : aucune mention dans la documentation officielle du cloud agent.** Pas de sélecteur d'effort trouvé pour cette surface.\n\n## Conséquence pour Maxime\n\nSur les trois surfaces Copilot (CLI, VS Code, cloud agent), Maxime ne peut ni choisir ni faire varier le modèle ou l'effort par lui-même : il peut seulement **recommander** un choix informé par le catalogue et **demander** à l'utilisateur de le faire (via `/model`, le picker VS Code, ou le picker du cloud agent) — contrainte de plateforme, pas un choix de conception mA.xI.me.\n\n## Ce qui reste incertain\n\n- Aucune source officielle ne documente un sélecteur d'effort pour le cloud agent — absence constatée dans les pages consultées, pas une confirmation qu'il n'existe nulle part sur la plateforme.\n" } diff --git a/active/governance/sailpoint-identityiq.json b/active/governance/sailpoint-identityiq.json index e88c033..29442e0 100644 --- a/active/governance/sailpoint-identityiq.json +++ b/active/governance/sailpoint-identityiq.json @@ -22,7 +22,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "servicenow-itsm-change-management" ], diff --git a/active/governance/servicenow-itsm-change-management.json b/active/governance/servicenow-itsm-change-management.json index a333cbd..1330b6e 100644 --- a/active/governance/servicenow-itsm-change-management.json +++ b/active/governance/servicenow-itsm-change-management.json @@ -21,7 +21,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "sailpoint-identityiq" ], diff --git a/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.json b/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.json index 7346386..7c20b9f 100644 --- a/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.json +++ b/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.json @@ -31,7 +31,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 90, "links": [ "enterprise-access-model", "ad-ds-tiered-administration-hardening", diff --git a/active/powershell/native-exe-json-quoting.json b/active/powershell/native-exe-json-quoting.json index 716357b..e356f90 100644 --- a/active/powershell/native-exe-json-quoting.json +++ b/active/powershell/native-exe-json-quoting.json @@ -18,7 +18,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 180, "links": [ "unattended-deployment" ], diff --git a/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json b/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json index d46cab7..0a0e62b 100644 --- a/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json +++ b/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json @@ -32,7 +32,6 @@ ], "validated": "2026-08-08", "created": "2026-08-08", - "ttl_days": 180, "links": [ "enterprise-access-model", "ad-ds-tiered-administration-hardening", diff --git a/active/security-architecture/ad-ds-tiered-administration-hardening.json b/active/security-architecture/ad-ds-tiered-administration-hardening.json index 73e3b8d..0f9f158 100644 --- a/active/security-architecture/ad-ds-tiered-administration-hardening.json +++ b/active/security-architecture/ad-ds-tiered-administration-hardening.json @@ -26,7 +26,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "enterprise-access-model", "zero-standing-access", diff --git a/active/security-architecture/enterprise-access-model.json b/active/security-architecture/enterprise-access-model.json index 7d697f3..e754050 100644 --- a/active/security-architecture/enterprise-access-model.json +++ b/active/security-architecture/enterprise-access-model.json @@ -20,7 +20,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "zero-standing-access" ], diff --git a/active/security-architecture/zero-standing-access.json b/active/security-architecture/zero-standing-access.json index 8696673..a8ed2d9 100644 --- a/active/security-architecture/zero-standing-access.json +++ b/active/security-architecture/zero-standing-access.json @@ -20,7 +20,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "enterprise-access-model" ], diff --git a/active/security-governance/security-framework-role-and-crosswalk.json b/active/security-governance/security-framework-role-and-crosswalk.json index d39dcc5..e99cdc6 100644 --- a/active/security-governance/security-framework-role-and-crosswalk.json +++ b/active/security-governance/security-framework-role-and-crosswalk.json @@ -36,7 +36,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "ad-ds-security-control-assurance-levels", "ad-ds-security-hardening-study-synthesis" diff --git a/active/siem/splunk-cim-data-models.json b/active/siem/splunk-cim-data-models.json index a4ff417..c3b0976 100644 --- a/active/siem/splunk-cim-data-models.json +++ b/active/siem/splunk-cim-data-models.json @@ -22,7 +22,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 60, "links": [], - "content": "# Splunk Common Information Model (CIM) — Authentication et Change\n\n**Statut `suspect`/`hypothesis` dès la création** : récupéré via un outil de résumé automatique, `docs.splunk.com` retournait 403 sur un accès direct. La liste du modèle Change en particulier n'a pas confirmé explicitement le statut requis/recommandé par champ. À revalider contre l'add-on CIM réellement installé sur l'instance Splunk cible avant tout usage en production (`ttl_days` volontairement court : 60).\n\n## Pourquoi CIM\n\nAligner un log applicatif sur un modèle CIM existant permet aux détections et rapports de conformité déjà construits côté SOC (Splunk Enterprise Security) de reconnaître l'événement automatiquement, sans parsing custom.\n\n## Data model Authentication\n\nÉvénement de validation d'identité (login, validation de jeton).\n\n**Champs requis** : `action`, `app`, `user`, `src`, `dest`.\n\n**Champs recommandés** : `src_user`, `user_id`, `user_role`, `user_type`, `authentication_method`, `authentication_service`, `duration`, `process`, `reason_id`, `response_time`, `signature`, `signature_id`, `user_agent`, `user_bunit`, `user_category`, `user_priority`.\n\n## Data model Change\n\nÉvénement de type Create/Read/Update/Delete sur un objet quelconque — c'est le modèle naturel pour une API qui fait du CRUD sur des objets d'annuaire ou toute ressource administrée.\n\n**Champs observés** (statut requis/recommandé non confirmé) : `action`, `change_type`, `command`, `dest`, `dest_bunit`, `dest_category`, `dest_ip_range`, `dest_nt_domain`, `dest_port_range`, `dest_priority`, `direction`, `dvc`, `image_id`, `instance_type`, `object`, `object_attrs`, `object_category`, `object_id`, `object_path`, `result`, `status`, `user`, `vendor_product`.\n\nSémantique à retenir : dans ce modèle, `user` désigne **qui effectue l'action**, pas l'objet ciblé par l'action — la cible se décrit via `object`/`object_category`/`object_id`/`object_path`.\n\n## Champs d'enveloppe d'indexation Splunk (hors CIM)\n\nDistincts des champs de contenu CIM ci-dessus : `time`/`timestamp`, `host`, `source`, `sourcetype`, `index` — gérés à l'ingestion, pas dans le corps de l'événement applicatif." + "content": "# Splunk Common Information Model (CIM) — Authentication et Change\n\n**Statut `suspect`/`hypothesis` dès la création** : récupéré via un outil de résumé automatique, `docs.splunk.com` retournait 403 sur un accès direct. La liste du modèle Change en particulier n'a pas confirmé explicitement le statut requis/recommandé par champ. À revalider contre l'add-on CIM réellement installé sur l'instance Splunk cible avant tout usage en production (fiche délibérément marquée à revalider tôt).\n\n## Pourquoi CIM\n\nAligner un log applicatif sur un modèle CIM existant permet aux détections et rapports de conformité déjà construits côté SOC (Splunk Enterprise Security) de reconnaître l'événement automatiquement, sans parsing custom.\n\n## Data model Authentication\n\nÉvénement de validation d'identité (login, validation de jeton).\n\n**Champs requis** : `action`, `app`, `user`, `src`, `dest`.\n\n**Champs recommandés** : `src_user`, `user_id`, `user_role`, `user_type`, `authentication_method`, `authentication_service`, `duration`, `process`, `reason_id`, `response_time`, `signature`, `signature_id`, `user_agent`, `user_bunit`, `user_category`, `user_priority`.\n\n## Data model Change\n\nÉvénement de type Create/Read/Update/Delete sur un objet quelconque — c'est le modèle naturel pour une API qui fait du CRUD sur des objets d'annuaire ou toute ressource administrée.\n\n**Champs observés** (statut requis/recommandé non confirmé) : `action`, `change_type`, `command`, `dest`, `dest_bunit`, `dest_category`, `dest_ip_range`, `dest_nt_domain`, `dest_port_range`, `dest_priority`, `direction`, `dvc`, `image_id`, `instance_type`, `object`, `object_attrs`, `object_category`, `object_id`, `object_path`, `result`, `status`, `user`, `vendor_product`.\n\nSémantique à retenir : dans ce modèle, `user` désigne **qui effectue l'action**, pas l'objet ciblé par l'action — la cible se décrit via `object`/`object_category`/`object_id`/`object_path`.\n\n## Champs d'enveloppe d'indexation Splunk (hors CIM)\n\nDistincts des champs de contenu CIM ci-dessus : `time`/`timestamp`, `host`, `source`, `sourcetype`, `index` — gérés à l'ingestion, pas dans le corps de l'événement applicatif." } diff --git a/active/vscode-copilot/copilot-instructions-merge.json b/active/vscode-copilot/copilot-instructions-merge.json index 53b9e3c..0ee6537 100644 --- a/active/vscode-copilot/copilot-instructions-merge.json +++ b/active/vscode-copilot/copilot-instructions-merge.json @@ -11,7 +11,6 @@ "source": ["https://code.visualstudio.com/docs/agent-customization/custom-instructions", "https://github.com/orgs/community/discussions/170581"], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 90, "links": ["vscode-copilot-builtin-tools", "claude-md-import-mechanism", "codex-agents-md-nesting"], "content": "# GitHub Copilot — fusion automatique de fichiers d'instructions multiples\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27.\n\n## Ce qui est confirmé (sourcé)\n\n- Mécanisme officiel et actuel : `.github/copilot-instructions.md` (toujours actif, portée repo entier) et `.github/instructions/*.instructions.md` (application conditionnelle via un glob `applyTo` ou correspondance sémantique) sont additifs, pas exclusifs — les deux se chargent ensemble en contexte. La doc VS Code le dit explicitement : \"If you have multiple instruction files in your project, VS Code combines and adds them to the chat context, no specific order is guaranteed.\" Source : https://code.visualstudio.com/docs/agent-customization/custom-instructions\n- La doc plus récente de Copilot CLI décrit une pile à 5 niveaux (personnel → instructions scopées par chemin → copilot-instructions.md repo entier → AGENTS.md → organisation) qui fusionnent tous, les niveaux supérieurs ne l'emportant qu'en cas de conflit direct.\n- Aucune syntaxe d'inclusion à l'intérieur d'un seul fichier d'instructions — mais des liens Markdown entre fichiers d'instructions sont une convention de référence croisée douce (ex. \"Applique ces conventions\"), pas une vraie fusion/inclusion.\n- Confusion réelle constatée dans la communauté : la discussion GitHub #170581 (org community) montre des utilisateurs ayant mal lu la formulation de la doc (\"either... or...\") comme mutuellement exclusive, alors que les deux types de fichiers se combinent réellement — clarifié par la communauté, pas encore par une réécriture de la doc officielle trouvée.\n\n## Incertitudes explicites\n\n- \"Aucun ordre spécifique garanti\" est un vrai risque pour notre cas d'usage si le fichier généré et le fichier écrit à la main donnent un jour des instructions contradictoires — impossible de forcer la victoire du fichier écrit à la main juste par son emplacement.\n- Aucune page officielle docs.github.com trouvée énonçant le comportement de combinaison aussi explicitement que la page VS Code ; des sources secondaires (Medium, blog NashTech) le répètent mais ne sont pas officielles.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nMécanisme natif, standard, sans parsing custom : garder `.github/copilot-instructions.md` comme fichier possédé par le générateur, et placer le contenu spécifique au projet dans un fichier séparé `.github/instructions/project-conventions.instructions.md` (avec `applyTo: \"**\"` pour le rendre universel) — Copilot fusionne automatiquement les deux à chaque fois, sans action de notre part après la première installation.\n\n## Sources\n- https://code.visualstudio.com/docs/agent-customization/custom-instructions\n- https://github.com/orgs/community/discussions/170581" } \ No newline at end of file diff --git a/active/vscode-copilot/vscode-copilot-builtin-tools.json b/active/vscode-copilot/vscode-copilot-builtin-tools.json index e130d85..dd88703 100644 --- a/active/vscode-copilot/vscode-copilot-builtin-tools.json +++ b/active/vscode-copilot/vscode-copilot-builtin-tools.json @@ -11,7 +11,6 @@ "source": ["https://docs.github.com/en/copilot/reference/custom-agents-configuration", "https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/"], "validated": "2026-07-13", "created": "2026-07-12", - "ttl_days": 90, "links": ["agent-skills-cross-tool-integration"], "content": "# VS Code / GitHub Copilot Chat — outils built-in (tools: frontmatter)\n\nStatut : `.new` — capture brute suite à une recherche ponctuelle, pas encore\nrelue/validée comme fiche KB stable. Savoir générique réutilisable, sans\ndonnée de projet/client/employeur.\n\n## Contexte\n\nErreur corrigée le 2026-07-12 : `web` et `vscode` avaient été retirés de\n`tools:` dans `maxime.agent.md` en les supposant à tort spécifiques à la\nmachine de Philippe (au même titre que `vscode.mermaid-markdown-features` ou\n`GitHub.vscode-pull-request-github`, qui eux le sont vraiment). Correction :\n`web` et `vscode` sont des **outils built-in**, disponibles pour tout\nutilisateur de l'extension Copilot Chat, pas une config locale.\n\n## Ce qui est confirmé (sourcé)\n\nD'après la doc GitHub officielle des custom agents\n([docs.github.com/en/copilot/reference/custom-agents-configuration](https://docs.github.com/en/copilot/reference/custom-agents-configuration)),\n7 alias d'outils built-in, avec leurs alias compatibles (mapping vers les\nnoms d'outils Claude Code — clin d'œil à la portabilité cross-outil) :\n\n| Alias Copilot | Alias compatibles |\n| --- | --- |\n| `execute` | `shell`, `Bash`, `powershell` |\n| `read` | `Read`, `NotebookRead` |\n| `edit` | `Edit`, `MultiEdit`, `Write`, `NotebookEdit` |\n| `search` | `Grep`, `Glob` |\n| `agent` | `custom-agent`, `Task` |\n| `web` | `WebSearch`, `WebFetch` |\n| `todo` | `TodoWrite` |\n\nDeux serveurs MCP disponibles par défaut pour les agents cloud GitHub.com :\n`github/*` (outils GitHub en lecture seule) et `playwright/*` (automatisation\nnavigateur, localhost uniquement).\n\nD'après le blog GitHub officiel\n([github.blog/.../how-were-making-github-copilot-smarter-with-fewer-tools](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/))\n: VS Code organise un noyau de 13 outils essentiels (structure du repo,\nlecture/édition de fichiers, recherche de contexte, terminal), puis regroupe\nle reste en catégories virtuelles : **Jupyter Notebook Tools**, **Web\nInteraction Tools**, **VS Code Workspace Tools**, **Testing Tools**. Ça\ncorrobore `web` (Web Interaction Tools) et `vscode` (VS Code Workspace Tools)\ncomme catégories réelles, pas des extras personnels.\n\n## Sous-outils observés directement (captures d'écran picker VS Code, 2026-07-13)\n\nPhilippe a fourni des captures d'écran du picker d'outils (menu `#` du chat\nCopilot). Reconstitution complète, textuelle, du détail par catégorie —\nobservation directe de son environnement, `non vérifié par exécution` contre\nune doc officielle listant chaque sous-fonction.\n\n### agent — Delegate tasks to other agents\n\n- **runSubagent** — Run a task within an isolated subagent context to enable efficient organization of tasks and context window management.\n\n### browser — Open and interact with integrated browser pages *(tous décochés)*\n\n- clickElement — Click an element in a browser page\n- dragElement — Drag an element over another element\n- handleDialog — Respond to a dialog in a browser page\n- hoverElement — Hover over an element in a browser page\n- navigatePage — Navigate or reload a browser page\n- openBrowserPage — Open a URL in the integrated browser\n- readPage — Read the content of a browser page\n- runPlaywrightCode — Run a Playwright code snippet against a browser page\n- screenshotPage — Capture a screenshot of a browser page\n- typeInPage — Type text or press keys in a browser page\n\n### edit — Edit files in your workspace\n\n- createDirectory — Create new directories in your workspace\n- createFile — Create new files\n- createJupyterNotebook — Create a new Jupyter Notebook\n- editFiles — Edit files\n- editNotebook — Edit a notebook file in the workspace\n- rename — Rename a symbol across the workspace\n\n### execute — Execute code and applications on your machine\n\n- createAndRunTask — Create and run a task in the workspace\n- executionSubagent — Launch an execution-focused subagent that runs one or more terminal commands to accomplish a task. This subagent is powered by Google's Gemini-3-Flash model. It is designed to select an efficient summary of the terminal outputs to return to the main agent context.\n- getTerminalOutput — Send input text to an active terminal execution (identified by the id returned from run_in_terminal). The 'command' field may be empty or whitespace to press Enter (useful for interactive prompts). By default, returns the last 20 lines of terminal output captured shortly after sending. Set 'waitForOutput' to true for interactive programs (games, REPLs, etc.) to wait until the terminal becomes idle before returning output — this gives you the program's response to your input.\n- killTerminal — Kill a terminal by its ID. Use this to clean up terminals that are no longer needed (e.g., after stopping a server or when a long-running task completes). The terminal ID is returned by run_in_terminal in async mode (legacy: isBackground=true).\n- runInTerminal — Run commands in the terminal\n- runNotebookCell — Trigger the execution of a cell in a notebook file\n- runTask — Run tasks in the workspace\n- runTests — Run unit tests (optionally with coverage)\n- sendToTerminal — Send input text to an active terminal execution (identified by the id returned from run_in_terminal). The 'command' field may be empty or whitespace to press Enter (useful for interactive prompts). By default, returns the last 20 lines of terminal output captured shortly after sending. Set 'waitForOutput' to true for interactive programs (games, REPLs, etc.) to wait until the terminal becomes idle before returning output — this gives you the program's response to your input.\n- testFailure — Include test failure information\n\n### read — Read files in your workspace\n\n- getNotebookSummary — This is a tool returns the list of the Notebook cells along with the id, cell types, line ranges, language, execution information and output mime types for each cell. This is useful to get Cell Ids when executing a notebook or determine what cells have been executed and what order, or what cells have outputs. If required to read contents of a cell use this to determine the line range of a cells, and then use read_file tool to read a specific line range. Requery this tool if the contents of the notebook change.\n- getTaskOutput — Get the output of a task\n- problems — Check errors for a particular file\n- readFile — Read the contents of a file\n- readNotebookCellOutput — Read the output of a previously executed cell\n- terminalLastCommand — Get the last command run in the active terminal.\n- terminalSelection — Get the current selection in the active terminal.\n- viewImage — View the contents of an image file\n\n### search — Search files in your workspace\n\n- changes — Get diffs of changed files\n- codebase — Find relevant file chunks, symbols, and other information via\n semantic search\n- fileSearch — Find files by name using a glob pattern\n- listDirectory — List the contents of a directory\n- textSearch — Find text in files by regular expression\n- usages — Find references, definitions, and implementations of a symbol\n\n### todo — Manage and track todo items for task planning\n\n### vscode — Use VS Code features\n\n- askQuestions — Ask structured clarifying questions using single select, multi-select, or freeform inputs to collect task requirements before proceeding.\n- extensions — Search for VS Code extensions\n- installExtension — Install an extension in VS Code. Use this tool to install an extension in Visual Studio Code as part of a new workspace creation process only.\n- memory — Manage persistent memory across conversations\n- newWorkspace — Scaffold a new workspace in VS Code\n- resolveMemoryFileUri — Resolve a memory file path to its actual URI\n- runCommand — Run a command in VS Code. Use this tool to run a command in Visual Studio Code as part of a new workspace creation process only.\n- vscodeAPI — Use VS Code API references to answer questions about VS Code extension development.\n\n### web — Fetch information from the web\n\n- fetch — Fetch the main content from a web page. You should include the\n URL of the page you w...\n- githubRepo — Semantic Search a GitHub repository for relevant source code snippets. You can specify a repository using owner/repo\n- githubTextSearch — Text search a GitHub repository or organization for files containing specific keywords or code patterns.\n\nLe champ `todo` apparaît comme sous-outil de `search` dans le picker\nobservé, alors que la table des alias plus haut le liste comme catégorie de\npremier niveau à part (`todo` → `TodoWrite`) — à réconcilier, pas forcément\ncontradictoire (un alias top-level peut être exposé aussi comme sous-item\ndans l'UI).\n\n## Ce qui reste incertain\n\n- Aucune source *officielle écrite* ne fournit cette table de sous-outils —\n elle vient de l'observation directe de Philippe (ci-dessus), qui fait\n autorité pour son environnement mais n'est pas vérifiée contre la doc. Et Philippe observe ces outils au travail, avec un laptop travail, et a la maison avec son oridnateur de bureau.\n- `browser` : confirmé comme catégorie réelle de premier niveau dans le\n picker (10 sous-outils listés ci-dessus), avec un net recoupement\n fonctionnel avec `playwright/*` (MCP cloud) — reste à déterminer si\n `browser` est ce même MCP exposé localement, ou une implémentation VS Code\n distincte.\n- Méthode recommandée par la doc VS Code elle-même pour un inventaire\n complet et à jour : taper `#` dans le champ de saisie du chat Copilot —\n plus fiable qu'une doc statique qui peut dater vite sur ce sujet.\n\n## Sources consultées\n\n- [Custom agents configuration — GitHub Docs](https://docs.github.com/en/copilot/reference/custom-agents-configuration)\n- [Custom agents in VS Code](https://code.visualstudio.com/docs/agent-customization/custom-agents)\n- [Use tools in chat — VS Code Docs](https://code.visualstudio.com/docs/copilot/agents/agent-tools)\n- [How we're making GitHub Copilot smarter with fewer tools — GitHub Blog](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/)\n- [GitHub Copilot in VS Code cheat sheet](https://code.visualstudio.com/docs/agents/reference/copilot-vscode-features)\n\n## Application faite\n\n`tools/generate-adapters.ps1`/`.sh` : `maxime.agent.md` (orchestrateur\n`maxi-copilot` uniquement, pas les sous-agents reviewer ni les prompts de\nworkflow) déclare désormais `[read, search, execute, edit, agent, vscode,\nweb]` — reprend exactement le sous-ensemble non-ambigu de ce que Philippe a\nlui-même validé comme fonctionnel dans son environnement, moins les deux\nextensions personnelles (`vscode.mermaid-markdown-features`,\n`GitHub.vscode-pull-request-github`).\n" } \ No newline at end of file diff --git a/active/windows-server/windows-server-2022-plus-hardening-source-baselines.json b/active/windows-server/windows-server-2022-plus-hardening-source-baselines.json index 67cb298..29cf37d 100644 --- a/active/windows-server/windows-server-2022-plus-hardening-source-baselines.json +++ b/active/windows-server/windows-server-2022-plus-hardening-source-baselines.json @@ -31,7 +31,6 @@ ], "validated": "2026-07-25", "created": "2026-07-25", - "ttl_days": 180, "links": [ "ad-ds-domain-controller-security-hardening", "ad-ds-security-control-assurance-levels", diff --git a/index.json b/index.json index 4246ac7..10620c4 100644 --- a/index.json +++ b/index.json @@ -26,7 +26,6 @@ ], "validated": "2026-07-16", "created": "2026-06-16", - "ttl_days": 180, "links": [ "unattended-deployment" ], @@ -57,7 +56,6 @@ ], "validated": "2026-07-16", "created": "2026-06-16", - "ttl_days": 180, "links": [ "reference" ], @@ -85,7 +83,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "zero-standing-access" ], @@ -113,7 +110,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "enterprise-access-model" ], @@ -153,7 +149,6 @@ ], "validated": "2026-08-08", "created": "2026-08-08", - "ttl_days": 180, "links": [ "enterprise-access-model", "ad-ds-tiered-administration-hardening", @@ -185,7 +180,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "zero-standing-access" ], @@ -215,7 +209,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 60, "links": [], "path": "active/siem/splunk-cim-data-models.json" }, @@ -243,7 +236,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "servicenow-itsm-change-management" ], @@ -272,7 +264,6 @@ ], "validated": "2026-07-18", "created": "2026-07-18", - "ttl_days": 180, "links": [ "sailpoint-identityiq" ], @@ -301,7 +292,6 @@ ], "validated": "2026-07-13", "created": "2026-07-13", - "ttl_days": 90, "links": [ "vscode-copilot-builtin-tools" ], @@ -326,7 +316,6 @@ ], "validated": "2026-06-16", "created": "2026-06-16", - "ttl_days": 90, "links": [ "claude-md-import-mechanism" ], @@ -357,7 +346,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 90, "links": [ "claude-md-hierarchie", "copilot-instructions-merge", @@ -384,7 +372,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 90, "links": [ "claude-md-import-mechanism", "copilot-instructions-merge" @@ -415,7 +402,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 60, "links": [ "copilot-models", "codex-models" @@ -444,7 +430,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 60, "links": [ "claude-code-models", "copilot-models" @@ -477,7 +462,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 60, "links": [ "claude-code-models", "codex-models" @@ -504,7 +488,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 180, "links": [ "unattended-deployment" ], @@ -531,7 +514,6 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "ttl_days": 90, "links": [ "vscode-copilot-builtin-tools", "claude-md-import-mechanism", @@ -560,7 +542,6 @@ ], "validated": "2026-07-13", "created": "2026-07-12", - "ttl_days": 90, "links": [ "agent-skills-cross-tool-integration" ], From 8fa231a60435278f4ffd10abf8b0c30a7b2385fa Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Aug 2026 09:48:42 +0000 Subject: [PATCH 2/4] feat(kb): convertisseur JSON <-> Markdown, miroir md/ et garde-fou CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Une fiche JSON dont tout le corps est une chaîne échappée est illisible sur GitHub, et un changement de contenu apparaît en PR comme une unique ligne de plusieurs milliers de caractères. La KB gagne donc une projection Markdown, sans cesser d'être consommée en JSON. Le JSON sous active/ reste la source canonique : les repos consommateurs et le skill maxime-kb ne changent pas. index.json, index.md et md/ sont dérivés, jamais édités à la main. - tools/kb.py : convertisseur bidirectionnel (sync, sync --from md, check, validate), Python 3 stdlib seule. Frontmatter YAML restreint au schéma réel, parsable sans dépendance ; aller-retour sans perte, vérifié octet à octet sur les 29 fiches. - md/active/**.md : miroir généré, lisible et diffable. - index.json régénéré : il ne déclarait que 19 fiches sur 29, les 10 autres étaient invisibles pour le skill qui ne charge que l'index. - index.md devient un catalogue généré par thème ; sa prose de conventions, redondante et périmée (thèmes obsolètes), rejoint KB-CONVENTIONS.md. - fiches JSON recanonicalisées (indentation, ordre des clés, saut de ligne final) pour rendre la comparaison déterministe. - .github/workflows/kb-sync.yml : régénère et committe les fichiers dérivés à chaque push ; se rabat sur une vérification en lecture seule pour les PR de fork. - validate rejette explicitement ttl_days, pour que le champ retiré en #8 ne revienne pas par copier-coller. Closes #9 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF --- .github/workflows/kb-sync.yml | 61 ++ KB-CONVENTIONS.md | 92 +- active/ad-ds/unattended-deployment.json | 2 +- .../agent-skills-cross-tool-integration.json | 20 +- active/aws/ecs-fargate-task-isolation.json | 2 +- .../claude-config/claude-md-hierarchie.json | 16 +- .../claude-md-import-mechanism.json | 26 +- .../codex-config/codex-agents-md-nesting.json | 19 +- active/engine-catalog/claude-code-models.json | 13 +- active/engine-catalog/codex-models.json | 12 +- active/engine-catalog/copilot-models.json | 13 +- active/governance/sailpoint-identityiq.json | 2 +- .../servicenow-itsm-change-management.json | 2 +- ...el-microsoft-reference-implementation.json | 2 +- .../enterprise-access-model.json | 2 +- .../zero-standing-access.json | 2 +- active/siem/splunk-cim-data-models.json | 2 +- .../copilot-instructions-merge.json | 22 +- .../vscode-copilot-builtin-tools.json | 18 +- index.json | 748 ++++++++++---- index.md | 119 ++- ...ds-domain-controller-security-hardening.md | 109 ++ ...-ds-domain-forest-gpo-security-baseline.md | 91 ++ .../ad-ds-gpo-acl-lifecycle-governance.md | 107 ++ ...ad-ds-security-control-assurance-levels.md | 84 ++ ...d-ds-security-hardening-study-synthesis.md | 109 ++ .../ad-ds-threat-driven-control-map.md | 79 ++ md/active/ad-ds/reference.md | 927 ++++++++++++++++++ md/active/ad-ds/unattended-deployment.md | 263 +++++ .../agent-skills-cross-tool-integration.md | 279 ++++++ md/active/aws/ecs-fargate-task-isolation.md | 43 + .../claude-config/claude-md-hierarchie.md | 204 ++++ .../claude-md-import-mechanism.md | 59 ++ .../codex-config/codex-agents-md-nesting.md | 45 + .../engine-catalog/claude-code-models.md | 55 ++ md/active/engine-catalog/codex-models.md | 46 + md/active/engine-catalog/copilot-models.md | 51 + md/active/governance/sailpoint-identityiq.md | 47 + .../servicenow-itsm-change-management.md | 48 + ...dentity-entra-security-impact-inventory.md | 101 ++ .../powershell/native-exe-json-quoting.md | 63 ++ ...odel-microsoft-reference-implementation.md | 86 ++ .../ad-ds-tiered-administration-hardening.md | 105 ++ .../enterprise-access-model.md | 47 + .../zero-standing-access.md | 41 + .../security-framework-role-and-crosswalk.md | 100 ++ md/active/siem/splunk-cim-data-models.md | 52 + .../copilot-instructions-merge.md | 48 + .../vscode-copilot-builtin-tools.md | 192 ++++ ...er-2022-plus-hardening-source-baselines.md | 88 ++ tools/kb.py | 523 ++++++++++ 51 files changed, 5044 insertions(+), 243 deletions(-) create mode 100644 .github/workflows/kb-sync.yml create mode 100644 md/active/ad-ds-security/ad-ds-domain-controller-security-hardening.md create mode 100644 md/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.md create mode 100644 md/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.md create mode 100644 md/active/ad-ds-security/ad-ds-security-control-assurance-levels.md create mode 100644 md/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.md create mode 100644 md/active/ad-ds-security/ad-ds-threat-driven-control-map.md create mode 100644 md/active/ad-ds/reference.md create mode 100644 md/active/ad-ds/unattended-deployment.md create mode 100644 md/active/agent-tooling/agent-skills-cross-tool-integration.md create mode 100644 md/active/aws/ecs-fargate-task-isolation.md create mode 100644 md/active/claude-config/claude-md-hierarchie.md create mode 100644 md/active/claude-config/claude-md-import-mechanism.md create mode 100644 md/active/codex-config/codex-agents-md-nesting.md create mode 100644 md/active/engine-catalog/claude-code-models.md create mode 100644 md/active/engine-catalog/codex-models.md create mode 100644 md/active/engine-catalog/copilot-models.md create mode 100644 md/active/governance/sailpoint-identityiq.md create mode 100644 md/active/governance/servicenow-itsm-change-management.md create mode 100644 md/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.md create mode 100644 md/active/powershell/native-exe-json-quoting.md create mode 100644 md/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.md create mode 100644 md/active/security-architecture/ad-ds-tiered-administration-hardening.md create mode 100644 md/active/security-architecture/enterprise-access-model.md create mode 100644 md/active/security-architecture/zero-standing-access.md create mode 100644 md/active/security-governance/security-framework-role-and-crosswalk.md create mode 100644 md/active/siem/splunk-cim-data-models.md create mode 100644 md/active/vscode-copilot/copilot-instructions-merge.md create mode 100644 md/active/vscode-copilot/vscode-copilot-builtin-tools.md create mode 100644 md/active/windows-server/windows-server-2022-plus-hardening-source-baselines.md create mode 100755 tools/kb.py diff --git a/.github/workflows/kb-sync.yml b/.github/workflows/kb-sync.yml new file mode 100644 index 0000000..352cb22 --- /dev/null +++ b/.github/workflows/kb-sync.yml @@ -0,0 +1,61 @@ +name: kb-sync + +# Garde-fou de cohérence de la KB. Le JSON sous active/ et archived/ est la +# source canonique ; index.json, index.md et le miroir md/ en sont dérivés. +# +# Sur push, le workflow ne se contente pas de vérifier : il régénère les fichiers +# dérivés et committe le résultat, pour qu'un contributeur puisse modifier une +# fiche sans rien lancer en local. +# +# Sur pull request, il se limite à vérifier : une PR venant d'un fork ne permet +# pas de pousser sur sa branche source. + +on: + push: + pull_request: + +permissions: + contents: write + +jobs: + sync: + # Les pushes uniquement : sur une PR, le job check ci-dessous prend le relais. + if: github.event_name == 'push' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + # Nécessaire pour pouvoir committer et pousser sur la branche courante. + persist-credentials: true + + # Aucune dépendance à installer : tools/kb.py n'utilise que la stdlib + # Python 3, déjà présente sur le runner. + - name: Régénère les index et le miroir markdown + run: python3 tools/kb.py sync + + - name: Committe le résultat si quelque chose a changé + run: | + if git diff --quiet; then + echo "Rien à régénérer : la KB est déjà cohérente." + exit 0 + fi + echo "Fichiers dérivés régénérés :" + git diff --name-only + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add -A + git commit -m 'chore(kb): régénère les index et le miroir markdown [skip ci]' + # Un push fait avec GITHUB_TOKEN ne redéclenche pas les workflows : pas + # de boucle. Le [skip ci] ci-dessus est une ceinture supplémentaire. + git push origin HEAD:"${GITHUB_REF_NAME}" + + check: + # Sur PR (typiquement depuis un fork), on vérifie sans écrire. + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v4 + - name: Vérifie que JSON et Markdown sont synchronisés + run: python3 tools/kb.py check diff --git a/KB-CONVENTIONS.md b/KB-CONVENTIONS.md index 683f750..2021395 100644 --- a/KB-CONVENTIONS.md +++ b/KB-CONVENTIONS.md @@ -10,11 +10,23 @@ partagé entre l'état local de ma.xi.me et ce repo dès le départ. ## Structure ``` -index.json ← index léger, un objet par fiche sans "content" (seul fichier chargé systématiquement) -active//.json ← une fiche = attributs + "content", chargée à la demande par thème +active//.json ← SOURCE CANONIQUE : une fiche = attributs + "content" archived/ ← fiches obsolètes, jamais chargées sauf demande explicite +index.json ← index machine généré, un objet par fiche sans "content" +md/active//.md← miroir généré, lisible par un humain +index.md ← catalogue généré, lisible par un humain +tools/kb.py ← convertisseur JSON <-> Markdown ``` +**Une seule source de vérité : le JSON.** Le Markdown existe parce qu'une fiche +JSON, dont tout le corps est une chaîne échappée, est illisible sur GitHub et +donne des diffs de PR non relisables. C'est une projection régénérable, pas une +deuxième base à tenir à jour à la main. + +`index.json`, `index.md` et tout `md/` sont **entièrement dérivés** des fiches : +ne jamais les éditer directement, ils seront écrasés à la prochaine +régénération. + ## Format de fiche (obligatoire) Fiche JSON avec attributs courts/contrôlés et un seul champ texte libre (`content`) : @@ -30,7 +42,7 @@ Fiche JSON avec attributs courts/contrôlés et un seul champ texte libre (`cont "status": "draft | active | suspect | obsolete | archived", "confidence": "fact | hypothesis | opinion", "audience": "generic | project | secret", - "source": "URL / PR / discussion (libre)", + "source": ["URL / PR / discussion (libre)"], "validated": "YYYY-MM-DD", "created": "YYYY-MM-DD", "links": ["autres-ids-liés"], @@ -41,15 +53,83 @@ Fiche JSON avec attributs courts/contrôlés et un seul champ texte libre (`cont Seuls `title`, `source` et `content` sont exemptés de la contrainte de concision (texte libre par nature). +## Format Markdown (miroir) + +La même fiche, côté `md/` : les attributs deviennent le frontmatter, `content` +devient le corps. + +```markdown +--- +id: slug-kebab-case +type: reference +title: Titre lisible +theme: thème court +tags: + - mots-clés + - courts +scope: global +status: active +confidence: fact +audience: generic +source: + - https://exemple.invalid/page +validated: 2026-08-09 +created: 2026-08-09 +links: + - autre-id-lié +--- + +# Titre lisible + +Corps de la fiche, Markdown en texte libre. +``` + +Le frontmatter est un sous-ensemble YAML volontairement restreint au schéma +réel — scalaires texte et séquences de textes — pour se parser sans dépendance. +Une valeur n'est mise entre guillemets doubles (échappement JSON) que si elle +le nécessite : vide, espace en tête ou en fin, `: ` ou ` #` à l'intérieur, ou +premier caractère qui est un indicateur YAML. + +L'aller-retour est **sans perte** : reconstruire le JSON depuis le Markdown +redonne exactement le JSON de départ, octet pour octet. + +## Outillage — `tools/kb.py` + +Python 3, bibliothèque standard seule, rien à installer. + +```bash +python3 tools/kb.py sync # JSON -> Markdown + index (sens par défaut) +python3 tools/kb.py sync --from md # Markdown -> JSON + index +python3 tools/kb.py check # vérifie sans écrire, sort en 1 si écart +python3 tools/kb.py validate # contrôles de schéma seuls +``` + +`sync` recanonicalise aussi les fiches JSON (indentation 2, ordre des clés fixe, +`content` terminé par exactement un saut de ligne) : c'est ce qui rend la +comparaison de `check` fiable. + +`validate` vérifie la présence et le type des 14 attributs, les valeurs +contrôlées, `id` = nom de fichier, `theme` = dossier parent, le format des +dates, l'unicité des `id` et le fait que chaque `links` pointe vers une fiche +existante. Les champs retirés du schéma (`ttl_days`) sont rejetés explicitement, +pour qu'ils ne reviennent pas par copier-coller d'une ancienne fiche. + +Le workflow `.github/workflows/kb-sync.yml` lance `sync` à chaque push et +committe lui-même les fichiers dérivés s'ils ont bougé ; sur pull request depuis +un fork, où pousser est impossible, il se rabat sur `check`. + ## Conventions -- Nommage : `active//.json`, `id` = nom de fichier sans extension. +- Nommage : `active//.json`, `id` = nom de fichier sans extension, + `theme` = nom du dossier parent. - Une fiche = un sujet précis. Pas de fourre-tout. - Statut `suspect` posé explicitement lors d'une revue, quand la fiche n'est plus sûre ; `validated` porte la date de dernière vérification. - Archiver (déplacer dans `archived/`) plutôt que supprimer. -- Mettre à jour `index.json` (sans `content`, plus champ `path`) à chaque - ajout, archivage ou changement d'attribut. +- Après tout ajout, archivage ou modification — d'un côté ou de l'autre — + lancer `python3 tools/kb.py sync` (ou `sync --from md`) et committer les deux + côtés. Les index ne se mettent plus à jour à la main. Si c'est oublié, le + workflow le fait au push. ## Ajout comme submodule dans un repo consommateur diff --git a/active/ad-ds/unattended-deployment.json b/active/ad-ds/unattended-deployment.json index aeec6e4..16aa5b5 100644 --- a/active/ad-ds/unattended-deployment.json +++ b/active/ad-ds/unattended-deployment.json @@ -26,5 +26,5 @@ "links": [ "reference" ], - "content": "# Unattended Active Directory Domain Services (AD DS) Deployment\n\n## Overview\n\nUnattended AD DS promotion requires:\n1. **Answer file** (Unattend.xml or DCPROMO answer file) with all configuration parameters\n2. **Network configuration** (static IP, DNS pointing to self)\n3. **Role installation** (DNS Server, AD-Domain-Services)\n4. **Promotion script** executed after prerequisites\n\n**Reference:** [DCPROMO Answer File Syntax - Microsoft Learn](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo)\n\n## Network Prerequisites (Critical)\n\n### 1. Static IP Address (REQUIRED for DNS)\n\nDNS Server cannot start without a static IP address. DHCP will cause immediate failure.\n\n```powershell\n# Get current DHCP-assigned config\n$adapter = Get-NetAdapter | Where-Object Status -eq 'Up' | Select-Object -First 1\n$config = Get-NetIPConfiguration -InterfaceIndex $adapter.InterfaceIndex\n$currentIp = $config.IPv4Address[0].IPAddress\n$currentGateway = $config.IPv4DefaultGateway[0].NextHop\n\n# Convert to static\nSet-NetIPInterface -InterfaceIndex $adapter.InterfaceIndex -DHCP Disabled\nRemove-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -AddressFamily IPv4 -Confirm:$false\nNew-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -IPAddress $currentIp -PrefixLength 24\nNew-NetRoute -InterfaceIndex $adapter.InterfaceIndex -DestinationPrefix \"0.0.0.0/0\" -NextHop $currentGateway\n\n# Set DNS to self (critical for DNS service startup)\nSet-DnsClientServerAddress -InterfaceIndex $adapter.InterfaceIndex -ServerAddresses @(\"127.0.0.1\", \"8.8.8.8\")\n```\n\n### 2. DNS Configuration\n\nDNS must resolve itself during promotion:\n- **Primary DNS:** 127.0.0.1 (localhost - the DC being promoted)\n- **Secondary DNS:** 8.8.8.8 (external fallback)\n\nWithout self-reference, DNS service fails to start with \"No static IP\" errors.\n\n## DCPROMO Answer File Format\n\n**File location in EC2:** `C:\\Windows\\System32\\dcpromo.answer`\n\n**Minimal example for forest root DC:**\n\n```ini\n[DCINSTALL]\n; Unattended forest promotion\nAutoConfigDNS=1\nCreateDNSDelegation=0\nDatabasePath=\"C:\\Windows\\NTDS\"\nLogPath=\"C:\\Windows\\NTDS\"\nSYSVOLPath=\"C:\\Windows\\SYSVOL\"\nSiteName=\"Default-First-Site-Name\"\nInstallDNS=Yes\nAllowAnonymousAccess=No\nAnswerFile=\"C:\\Windows\\System32\\dcpromo.answer\"\n\n; Forest and domain settings\nDomainNetBiosName=CORP\nDomainName=corp.local\nForestFunctionality=2012R2\nDomainFunctionality=2012R2\nReplicaOrNewDomain=Forest\nNewDomainDNSName=corp.local\n\n; Safe Mode Admin password\nSafeModeAdminPassword=YourPasswordHere123!\nRebootOnCompletion=Yes\n```\n\n**Critical parameters:**\n- `InstallDNS=Yes` - Installs DNS during promotion\n- `AutoConfigDNS=1` - Configures DNS automatically\n- `SafeModeAdminPassword` - Directory Services Restore Mode password (REQUIRED)\n- `RebootOnCompletion=Yes` - Reboot after successful promotion\n\n**Reference:** [Installing a New Forest Using Answer File - Microsoft Learn](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc770303)\n\n## Installation Sequence (Order Matters)\n\n```powershell\n# 1. Configure static IP first\nSet-NetIPInterface -DHCP Disabled\n# ... (see Network Prerequisites above)\n\n# 2. Install DNS Server role\nInstall-WindowsFeature DNS -IncludeManagementTools\n\n# 3. Install AD-Domain-Services role\nInstall-WindowsFeature AD-Domain-Services -IncludeManagementTools\n\n# 4. Create DCPROMO answer file dynamically\n$answerFile = @\"\n[DCINSTALL]\nAutoConfigDNS=1\nDatabasePath=\"C:\\Windows\\NTDS\"\nLogPath=\"C:\\Windows\\NTDS\"\nSYSVOLPath=\"C:\\Windows\\SYSVOL\"\nSiteName=\"Default-First-Site-Name\"\nInstallDNS=Yes\nAllowAnonymousAccess=No\nDomainNetBiosName=CORP\nDomainName=corp.local\nForestFunctionality=2012R2\nDomainFunctionality=2012R2\nReplicaOrNewDomain=Forest\nNewDNSName=corp.local\nSafeModeAdminPassword=Password123!\nRebootOnCompletion=Yes\n\"@\n$answerFile | Set-Content -Path \"C:\\Windows\\System32\\dcpromo.answer\" -Encoding ASCII\n\n# 5. Run DCPROMO with answer file\ndcpromo.exe /answer:\"C:\\Windows\\System32\\dcpromo.answer\" /unattend\n```\n\n## AWS EC2 Considerations\n\n**Reference:** [Active Directory Domain Services on AWS - AWS Whitepapers](https://aws.amazon.com/whitepapers/active-directory-domain-services/)\n\n### Security Groups\n\nAllow these ports for AD DS:\n- **TCP/UDP 53** - DNS\n- **TCP/UDP 88** - Kerberos\n- **TCP/UDP 389** - LDAP\n- **TCP 636** - LDAPS\n- **TCP 3389** - RDP (for troubleshooting)\n- **TCP 445** - SMB (replication)\n- **UDP 123** - NTP\n\n### EC2 UserData Execution\n\nUserData runs as SYSTEM with full privileges:\n```powershell\n\n# Code runs as SYSTEM\n# Can execute any privileged operations\n\n```\n\n**Key points:**\n- Execution is asynchronous (starts in background)\n- Monitor progress via `C:\\ProgramData\\Amazon\\EC2Launch\\log\\agent.log`\n- Can take 20-30 minutes total (network config + role install + promotion + reboot)\n\n### IAM Instance Profile Permissions\n\nIf promoting via AWS Systems Manager, instance needs:\n- `ssm:GetDocument`\n- `ssm:StartAutomationExecution`\n- `ec2:DescribeInstances`\n- `ec2messages:*`\n\n## Common Errors and Solutions\n\n| Error | Cause | Solution |\n|-------|-------|----------|\n| \"DNS Server Error: No static IP\" | Interface using DHCP | Set `Set-NetIPInterface -DHCP Disabled` first |\n| \"Install-ADDSForest: Cannot validate domain\" | DNS not responding | Verify DNS started and self-reference (127.0.0.1) is set |\n| \"DCPROMO: File not found\" | Answer file path wrong | Use full path: `C:\\Windows\\System32\\dcpromo.answer` |\n| \"Replication Issues\" | DNS resolution failing | Ensure all DNS forwarders configured, test with `nslookup` |\n| \"The specified domain either does not exist or could not be contacted\" | Network isolation | Check security group allows LDAP/DNS ports |\n\n## Verification Commands (Post-Promotion)\n\n```powershell\n# Verify DC promotion\nGet-ADDomain\nGet-ADForest\nGet-ADDomainController\n\n# Check DNS\nnslookup corp.local\nGet-Service DNS\n\n# Verify replication\nrepadmin /replsummary\n```\n\n## References\n\n- [DCPROMO Answer File Syntax](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo)\n- [Installing a New Forest Using Answer File](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc770303)\n- [Active Directory Domain Services on AWS](https://aws-solutions-library-samples.github.io/cfn-ps-microsoft-activedirectory/)\n- [AD on AWS EC2 Design Considerations](https://docs.aws.amazon.com/whitepapers/latest/active-directory-domain-services/design-considerations-for-running-active-directory-on-ec2-instances.html)\n- [AWS Directory Service for AD Trusts](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/microsoftadtrusttep1.html)\n\n---\n\n## EC2Launch v2 blocks legacy UserData — use SSM RunCommand instead\n\nConfirmed 2026-07-16 against a real EC2-provisioned DC (coreapi Spec 0), after the\napproach below failed silently for ~4 hours of debugging.\n\n**Problem:** Windows Server 2022 Base AMI ships **EC2Launch v2**, not v1. EC2Launch v2\nexpects YAML/XML config, not a base64-encoded `...` block, and\ndoes **not** auto-decode/execute it like older AMIs did. Result: the DCPROMO UserData\nscript silently never runs — no error, just a promotion that never happens and an LDAP\nreadiness check that times out after 30 min.\n\n**Fix:** Don't rely on UserData for anything beyond the most trivial bootstrap. Launch\nthe instance bare, then drive the promotion via **SSM RunCommand**\n(`AWS-RunPowerShellScript`) instead:\n\n```powershell\n# 1. Wait for the SSM agent to actually register before sending anything --\n# sending too early is a second, separate failure mode (command hangs\n# forever in \"Sending SSM command\", no error).\ndo {\n $info = aws ssm describe-instance-information `\n --filters \"Key=InstanceIds,Values=$instanceId\" | ConvertFrom-Json\n $status = $info.InstanceInformationList[0].PingStatus\n Start-Sleep -Seconds 5\n} while ($status -ne 'Online')\n\n# 2. Only then send the promotion script via SSM\naws ssm send-command `\n --instance-ids $instanceId `\n --document-name \"AWS-RunPowerShellScript\" `\n --parameters commands=\"$dcpromoScript\"\n```\n\n**Alternatives considered and rejected:** reverting to an older AMI with EC2Launch v1\n(region availability not guaranteed, fragile to depend on); rewriting UserData as\nEC2Launch v2 YAML (untested extra complexity for no benefit over SSM, which was needed\nanyway for other provisioning steps).\n\n**Verification:** `Get-ADDomain` over SSM (without transmitting the password through SSM\ncommand history) confirms promotion health before declaring success — checking process\nexit code alone is not enough.\n\n" + "content": "# Unattended Active Directory Domain Services (AD DS) Deployment\n\n## Overview\n\nUnattended AD DS promotion requires:\n1. **Answer file** (Unattend.xml or DCPROMO answer file) with all configuration parameters\n2. **Network configuration** (static IP, DNS pointing to self)\n3. **Role installation** (DNS Server, AD-Domain-Services)\n4. **Promotion script** executed after prerequisites\n\n**Reference:** [DCPROMO Answer File Syntax - Microsoft Learn](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo)\n\n## Network Prerequisites (Critical)\n\n### 1. Static IP Address (REQUIRED for DNS)\n\nDNS Server cannot start without a static IP address. DHCP will cause immediate failure.\n\n```powershell\n# Get current DHCP-assigned config\n$adapter = Get-NetAdapter | Where-Object Status -eq 'Up' | Select-Object -First 1\n$config = Get-NetIPConfiguration -InterfaceIndex $adapter.InterfaceIndex\n$currentIp = $config.IPv4Address[0].IPAddress\n$currentGateway = $config.IPv4DefaultGateway[0].NextHop\n\n# Convert to static\nSet-NetIPInterface -InterfaceIndex $adapter.InterfaceIndex -DHCP Disabled\nRemove-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -AddressFamily IPv4 -Confirm:$false\nNew-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -IPAddress $currentIp -PrefixLength 24\nNew-NetRoute -InterfaceIndex $adapter.InterfaceIndex -DestinationPrefix \"0.0.0.0/0\" -NextHop $currentGateway\n\n# Set DNS to self (critical for DNS service startup)\nSet-DnsClientServerAddress -InterfaceIndex $adapter.InterfaceIndex -ServerAddresses @(\"127.0.0.1\", \"8.8.8.8\")\n```\n\n### 2. DNS Configuration\n\nDNS must resolve itself during promotion:\n- **Primary DNS:** 127.0.0.1 (localhost - the DC being promoted)\n- **Secondary DNS:** 8.8.8.8 (external fallback)\n\nWithout self-reference, DNS service fails to start with \"No static IP\" errors.\n\n## DCPROMO Answer File Format\n\n**File location in EC2:** `C:\\Windows\\System32\\dcpromo.answer`\n\n**Minimal example for forest root DC:**\n\n```ini\n[DCINSTALL]\n; Unattended forest promotion\nAutoConfigDNS=1\nCreateDNSDelegation=0\nDatabasePath=\"C:\\Windows\\NTDS\"\nLogPath=\"C:\\Windows\\NTDS\"\nSYSVOLPath=\"C:\\Windows\\SYSVOL\"\nSiteName=\"Default-First-Site-Name\"\nInstallDNS=Yes\nAllowAnonymousAccess=No\nAnswerFile=\"C:\\Windows\\System32\\dcpromo.answer\"\n\n; Forest and domain settings\nDomainNetBiosName=CORP\nDomainName=corp.local\nForestFunctionality=2012R2\nDomainFunctionality=2012R2\nReplicaOrNewDomain=Forest\nNewDomainDNSName=corp.local\n\n; Safe Mode Admin password\nSafeModeAdminPassword=YourPasswordHere123!\nRebootOnCompletion=Yes\n```\n\n**Critical parameters:**\n- `InstallDNS=Yes` - Installs DNS during promotion\n- `AutoConfigDNS=1` - Configures DNS automatically\n- `SafeModeAdminPassword` - Directory Services Restore Mode password (REQUIRED)\n- `RebootOnCompletion=Yes` - Reboot after successful promotion\n\n**Reference:** [Installing a New Forest Using Answer File - Microsoft Learn](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc770303)\n\n## Installation Sequence (Order Matters)\n\n```powershell\n# 1. Configure static IP first\nSet-NetIPInterface -DHCP Disabled\n# ... (see Network Prerequisites above)\n\n# 2. Install DNS Server role\nInstall-WindowsFeature DNS -IncludeManagementTools\n\n# 3. Install AD-Domain-Services role\nInstall-WindowsFeature AD-Domain-Services -IncludeManagementTools\n\n# 4. Create DCPROMO answer file dynamically\n$answerFile = @\"\n[DCINSTALL]\nAutoConfigDNS=1\nDatabasePath=\"C:\\Windows\\NTDS\"\nLogPath=\"C:\\Windows\\NTDS\"\nSYSVOLPath=\"C:\\Windows\\SYSVOL\"\nSiteName=\"Default-First-Site-Name\"\nInstallDNS=Yes\nAllowAnonymousAccess=No\nDomainNetBiosName=CORP\nDomainName=corp.local\nForestFunctionality=2012R2\nDomainFunctionality=2012R2\nReplicaOrNewDomain=Forest\nNewDNSName=corp.local\nSafeModeAdminPassword=Password123!\nRebootOnCompletion=Yes\n\"@\n$answerFile | Set-Content -Path \"C:\\Windows\\System32\\dcpromo.answer\" -Encoding ASCII\n\n# 5. Run DCPROMO with answer file\ndcpromo.exe /answer:\"C:\\Windows\\System32\\dcpromo.answer\" /unattend\n```\n\n## AWS EC2 Considerations\n\n**Reference:** [Active Directory Domain Services on AWS - AWS Whitepapers](https://aws.amazon.com/whitepapers/active-directory-domain-services/)\n\n### Security Groups\n\nAllow these ports for AD DS:\n- **TCP/UDP 53** - DNS\n- **TCP/UDP 88** - Kerberos\n- **TCP/UDP 389** - LDAP\n- **TCP 636** - LDAPS\n- **TCP 3389** - RDP (for troubleshooting)\n- **TCP 445** - SMB (replication)\n- **UDP 123** - NTP\n\n### EC2 UserData Execution\n\nUserData runs as SYSTEM with full privileges:\n```powershell\n\n# Code runs as SYSTEM\n# Can execute any privileged operations\n\n```\n\n**Key points:**\n- Execution is asynchronous (starts in background)\n- Monitor progress via `C:\\ProgramData\\Amazon\\EC2Launch\\log\\agent.log`\n- Can take 20-30 minutes total (network config + role install + promotion + reboot)\n\n### IAM Instance Profile Permissions\n\nIf promoting via AWS Systems Manager, instance needs:\n- `ssm:GetDocument`\n- `ssm:StartAutomationExecution`\n- `ec2:DescribeInstances`\n- `ec2messages:*`\n\n## Common Errors and Solutions\n\n| Error | Cause | Solution |\n|-------|-------|----------|\n| \"DNS Server Error: No static IP\" | Interface using DHCP | Set `Set-NetIPInterface -DHCP Disabled` first |\n| \"Install-ADDSForest: Cannot validate domain\" | DNS not responding | Verify DNS started and self-reference (127.0.0.1) is set |\n| \"DCPROMO: File not found\" | Answer file path wrong | Use full path: `C:\\Windows\\System32\\dcpromo.answer` |\n| \"Replication Issues\" | DNS resolution failing | Ensure all DNS forwarders configured, test with `nslookup` |\n| \"The specified domain either does not exist or could not be contacted\" | Network isolation | Check security group allows LDAP/DNS ports |\n\n## Verification Commands (Post-Promotion)\n\n```powershell\n# Verify DC promotion\nGet-ADDomain\nGet-ADForest\nGet-ADDomainController\n\n# Check DNS\nnslookup corp.local\nGet-Service DNS\n\n# Verify replication\nrepadmin /replsummary\n```\n\n## References\n\n- [DCPROMO Answer File Syntax](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo)\n- [Installing a New Forest Using Answer File](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc770303)\n- [Active Directory Domain Services on AWS](https://aws-solutions-library-samples.github.io/cfn-ps-microsoft-activedirectory/)\n- [AD on AWS EC2 Design Considerations](https://docs.aws.amazon.com/whitepapers/latest/active-directory-domain-services/design-considerations-for-running-active-directory-on-ec2-instances.html)\n- [AWS Directory Service for AD Trusts](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/microsoftadtrusttep1.html)\n\n---\n\n## EC2Launch v2 blocks legacy UserData — use SSM RunCommand instead\n\nConfirmed 2026-07-16 against a real EC2-provisioned DC (coreapi Spec 0), after the\napproach below failed silently for ~4 hours of debugging.\n\n**Problem:** Windows Server 2022 Base AMI ships **EC2Launch v2**, not v1. EC2Launch v2\nexpects YAML/XML config, not a base64-encoded `...` block, and\ndoes **not** auto-decode/execute it like older AMIs did. Result: the DCPROMO UserData\nscript silently never runs — no error, just a promotion that never happens and an LDAP\nreadiness check that times out after 30 min.\n\n**Fix:** Don't rely on UserData for anything beyond the most trivial bootstrap. Launch\nthe instance bare, then drive the promotion via **SSM RunCommand**\n(`AWS-RunPowerShellScript`) instead:\n\n```powershell\n# 1. Wait for the SSM agent to actually register before sending anything --\n# sending too early is a second, separate failure mode (command hangs\n# forever in \"Sending SSM command\", no error).\ndo {\n $info = aws ssm describe-instance-information `\n --filters \"Key=InstanceIds,Values=$instanceId\" | ConvertFrom-Json\n $status = $info.InstanceInformationList[0].PingStatus\n Start-Sleep -Seconds 5\n} while ($status -ne 'Online')\n\n# 2. Only then send the promotion script via SSM\naws ssm send-command `\n --instance-ids $instanceId `\n --document-name \"AWS-RunPowerShellScript\" `\n --parameters commands=\"$dcpromoScript\"\n```\n\n**Alternatives considered and rejected:** reverting to an older AMI with EC2Launch v1\n(region availability not guaranteed, fragile to depend on); rewriting UserData as\nEC2Launch v2 YAML (untested extra complexity for no benefit over SSM, which was needed\nanyway for other provisioning steps).\n\n**Verification:** `Get-ADDomain` over SSM (without transmitting the password through SSM\ncommand history) confirms promotion health before declaring success — checking process\nexit code alone is not enough.\n" } diff --git a/active/agent-tooling/agent-skills-cross-tool-integration.json b/active/agent-tooling/agent-skills-cross-tool-integration.json index 01b04b2..9df9749 100644 --- a/active/agent-tooling/agent-skills-cross-tool-integration.json +++ b/active/agent-tooling/agent-skills-cross-tool-integration.json @@ -3,14 +3,26 @@ "type": "reference", "title": "Agent Skills -- standard ouvert cross-outil (Claude Code, Copilot/VS Code, Codex)", "theme": "agent-tooling", - "tags": ["skills", "vscode", "copilot", "codex", "tool-scoping"], + "tags": [ + "skills", + "vscode", + "copilot", + "codex", + "tool-scoping" + ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", - "source": ["https://agentskills.io", "https://github.com/microsoft/vscode/issues/293276", "https://github.com/microsoft/vscode/issues/307630"], + "source": [ + "https://agentskills.io", + "https://github.com/microsoft/vscode/issues/293276", + "https://github.com/microsoft/vscode/issues/307630" + ], "validated": "2026-07-13", "created": "2026-07-13", - "links": ["vscode-copilot-builtin-tools"], + "links": [ + "vscode-copilot-builtin-tools" + ], "content": "# Agent Skills — standard ouvert cross-outil (Claude Code, Copilot/VS Code, Codex)\n\nStatut : `.new` — capture de recherche du 2026-07-13, déclenchée par une observation\nréelle de Philippe (Copilot Chat allait chercher `.agents/skills/maxime-review`\nau lieu du `.github/prompts/maxime-review.prompt.md` attendu). Savoir générique\nréutilisable, sourcé sur la documentation officielle de chaque outil.\n\n## Le déclencheur\n\nPhilippe, dans GitHub Copilot Chat, demande \"Maxime Review\" → Copilot va chercher\ndans `.agents/skills/maxime-review` (chemin qu'on pensait réservé à Codex),\npas dans `.github/prompts/maxime-review.prompt.md` (le fichier Copilot généré\npar `generate-adapters.*`). Question : pourquoi, et est-ce grave ?\n\n## Ce qui est confirmé (sourcé)\n\n### Agent Skills est un standard ouvert, pas une convention par outil\n\nD'après [agentskills.io](https://agentskills.io) : le format **Agent Skills**\n(dossier + `SKILL.md`, frontmatter minimal `name`+`description`) a été créé par\nAnthropic puis publié comme **standard ouvert**, adopté par une liste large et\npublique d'outils : Claude Code, GitHub Copilot, VS Code, OpenAI Codex, Cursor,\nGemini CLI, Goose, Roo Code, JetBrains Junie, et des dizaines d'autres (voir la\npage pour la liste complète). Fonctionnement en 3 étapes (\"progressive\ndisclosure\") : *discovery* (nom+description seulement au démarrage) → *activation*\n(le corps du SKILL.md charge en contexte si la tâche correspond) → *execution*.\n\n**Conséquence directe pour mA.xI.me** : `.agents/skills/` n'est pas \"le dossier\nCodex\" — c'est un des emplacements génériques que plusieurs outils scannent en\nmême temps, dont Copilot.\n\n### Emplacements scannés, par outil\n\n| Outil | Emplacements projet | Emplacements personnels | Configurable ? |\n| --- | --- | --- | --- |\n| **Claude Code** | `.claude/skills/`, dossier `--add-dir` | `~/.claude/skills/` | non documenté |\n| **GitHub Copilot (VS Code, CLI, cloud agent)** | `.github/skills/`, **`.claude/skills/`**, **`.agents/skills/`** | `~/.copilot/skills/`, `~/.claude/skills/`, `~/.agents/skills/` | oui, `chat.agentSkillsLocations` — **ajoute** des emplacements, ne permet pas d'en exclure |\n| **OpenAI Codex** | `.agents/skills/`, scanné à chaque niveau du cwd jusqu'à la racine du repo Git | `$HOME/.agents/skills/` | non documenté |\n\nSources : [code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills),\n[docs.github.com — About custom agents](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-custom-agents)\net une recherche dédiée sur `chat.agentSkillsLocations`,\n[developers.openai.com/codex/skills](https://developers.openai.com/codex/skills)\n(redirige vers `learn.chatgpt.com/docs/codex/skills`).\n\n**Point clé** : Copilot scanne **les trois** conventions (la sienne + celle de\nClaude + celle de Codex/du standard). C'est documenté, pas un bug — Microsoft a\ndélibérément rendu Copilot compatible avec les skills écrits pour les autres\noutils.\n\n### Aucune restriction d'outils dans le standard de base\n\nChamps frontmatter du standard Agent Skills (confirmés via la doc VS Code) :\n`name`, `description`, `argument-hint`, `user-invocable`,\n`disable-model-invocation`, `context` (`inline` ou `fork`). **Aucun champ ne\nrestreint les outils disponibles** — ni `allowed-tools`, ni équivalent, dans le\nstandard lui-même.\n\n- **Claude Code étend le standard** avec `allowed-tools` (extension propriétaire,\n ignorée par les autres outils).\n- **Codex n'ajoute rien** — ses skills n'ont jamais de frontmatter de\n restriction (déjà documenté côté mA.xI.me, décision du 2026-07-12).\n- **Copilot/VS Code n'ajoute rien non plus au niveau Skill** — la restriction\n d'outils existe uniquement au niveau des **Custom Agents** (`.agent.md`,\n champ `tools:`), pas au niveau Skill.\n\n### Custom Agents VS Code (`.agent.md`) — rappel et nuance\n\nEmplacements : `.github/agents/` (projet), `~/.copilot/agents/` (utilisateur),\nextensible via `chat.agentFilesLocations`. Frontmatter : `name`, `description`,\n`tools`, `model`, `agents` (sous-agents autorisés), `handoffs`, `mcp-servers`.\nQuand un agent personnalisé est actif, seuls les outils listés dans `tools:`\nsont disponibles — confirmé.\n\n**Ce qui reste flou (la doc ne le dit pas explicitement)** : comment cette\nrestriction s'articule avec un Skill chargé pendant que l'agent est actif. Seul\nindice trouvé : *\"la priorité des outils favorise les fichiers de prompt sur\nles agents personnalisés\"* — ce qui suggère qu'un **prompt file** avec son\npropre `tools:` (comme `.github/prompts/maxime-review.prompt.md`, qui déclare\n`tools: [read, search]`) prendrait le pas sur l'agent actif s'il est invoqué\ncomme prompt/commande slash. Mais rien ne confirme ce qui se passe quand c'est\nun **Skill** (sans son propre `tools:`) qui est chargé à la place — hérite-t-il\ndes restrictions de l'agent actif, ou tourne-t-il avec la palette complète ?\n\nSources : [code.visualstudio.com/docs/agent-customization/custom-agents](https://code.visualstudio.com/docs/agent-customization/custom-agents),\n[code.visualstudio.com/docs/agent-customization/overview](https://code.visualstudio.com/docs/agent-customization/overview).\n\n## Implication concrète pour mA.xI.me\n\nLe workflow `maxime-review` est censé garantir une revue **lecture seule**\nsous Copilot via `.github/prompts/maxime-review.prompt.md`\n(`tools: [read, search]`) et/ou l'agent dédié `maxi-copilot-reviewer`\n(`.github/agents/maxime-reviewer.agent.md`, aussi `tools: [read, search]`).\n\nCe qu'on sait maintenant :\n\n1. Copilot scanne aussi `.claude/skills/maxime-review` et\n `.agents/skills/maxime-review` — deux fichiers **sans aucune restriction\n d'outils utilisable par Copilot** (le premier a `allowed-tools`, mais c'est\n une extension Claude que Copilot ignore ; le second n'a rien du tout).\n2. Rien ne garantit lequel des trois emplacements (`.github/skills/`\n — absent chez nous —, `.claude/skills/`, `.agents/skills/`) Copilot choisit\n quand plusieurs portent le même nom `maxime-review`. La doc ne documente\n pas de règle de priorité entre emplacements.\n3. Si Copilot charge le Skill (plutôt que le prompt file) **et** que le\n contexte d'exécution du Skill n'hérite pas des restrictions de l'agent\n actif, alors la garantie lecture-seule de `maxime-review` sous Copilot n'est\n plus mécanique — elle retombe sur la même situation déjà documentée pour\n Codex (\"consigne textuelle, pas garantie technique\").\n\nC'est le même trou que celui déjà noté dans `docs/ARCHITECTURE.md` §Limites\nassumées pour Codex, mais potentiellement **aussi vrai pour Copilot**.\n\n**Correction d'une hypothèse initiale** : en relisant `.wip/adr/decisions-log.md`,\nle verdict Tier 2 du 2026-07-12 précise explicitement que *\"prompts 4 (handoff)\net 5 (review) [n'ont pas été] executes, juges non necessaires vu la force des\nresultats deja obtenus\"*. Le workflow `maxime-review` n'a donc **jamais été\ntesté en conditions réelles sous Copilot** — ce n'est pas une régression par\nrapport à une garantie déjà validée, c'est une hypothèse non testée qu'on\ndécouvre seulement maintenant.\n\nChronologie confirmée : Agent Skills est arrivé dans GitHub Copilot le\n2025-12-18 ([GitHub Changelog](https://github.blog/changelog/2025-12-18-github-copilot-now-supports-agent-skills/)),\net dans VS Code (canal stable, expérimental) vers janvier 2026 via la version\n1.108 ([Visual Studio Magazine, 2026-01-11](https://visualstudiomagazine.com/articles/2026/01/11/hand-on-with-new-github-copilot-agent-skills-in-vs-code.aspx)) —\ndonc bien avant le Tier 2 du 2026-07-12. La fonctionnalité était déjà active\nau moment du Tier 2 ; c'est le scénario précis (invocation naturelle de\n\"Maxime Review\" plutôt que sélection explicite de l'agent ou du prompt) qui\nn'a jamais été exercé.\n\n**Recherche complémentaire (3 sources officielles distinctes)** : ni la doc\nGitHub ([about-agent-skills](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)),\nni le blog Microsoft ([Agent Skills in Visual Studio](https://devblogs.microsoft.com/visualstudio/agent-skills-in-visual-studio/),\nmai 2026, statut encore Insiders pour Visual Studio à cette date), ni la doc\nVS Code ne mentionnent la moindre notion de sécurité, de sandbox ou de\nrestriction d'outils au niveau Skill. L'absence est cohérente à travers les\ntrois sources — ce n'est pas un trou de recherche, la question semble\nsimplement ne pas être adressée par l'écosystème à ce stade.\n\n## Question résolue par les issues GitHub officielles (pas par la doc)\n\nLa doc ne tranchait pas la question d'héritage des permissions. Les issues\nGitHub réelles du dépôt VS Code (`microsoft/vscode`, ex-`vscode-copilot-chat`\narchivé et fusionné dedans le 2026-05-20) la tranchent, avec confirmation\ndirecte par un membre de l'équipe VS Code :\n\n### `SKILL.md` n'a aucun moyen de restreindre ou d'élargir les outils — confirmé par le code lui-même\n\n[Issue #293276](https://github.com/microsoft/vscode/issues/293276) (« Skills:\nScoped tool permissions ») cite le message d'erreur exact du validateur\nVS Code actuel quand on tente d'ajouter `allowed-tools` à un `SKILL.md` :\n\n> *\"Attribute 'allowed-tools' is not supported in skill files. Supported:\n> compatibility, description, license, metadata, name.\"*\n\n— message confirmé par `anladwig` (membre de l'équipe VS Code), qui note que\n`allowed-tools` fait pourtant partie du standard ouvert (`agentskills.io`)\nmais n'est **pas encore implémenté côté VS Code**. Un commentateur\n(`siegenthalerroger`) demande explicitement *\"Is the `tools` field available\nin a SKILL.md frontmatter?\"* — réponse : non, ni documenté ni accepté par le\nvalidateur.\n\n**Conséquence directe, confirmée** : un `SKILL.md`, quel que soit l'outil qui\nle charge (Claude Code excepté, qui honore sa propre extension\n`allowed-tools`), ne peut ni accorder ni retirer de capacité — c'est du texte\npur, injecté dans le contexte de l'agent déjà actif.\n\n### La restriction d'outils vient donc uniquement de l'agent actif — et elle s'applique bien aux skills\n\n[Issue #307630](https://github.com/microsoft/vscode/issues/307630) (« per-agent\nskill scoping ») confirme, en creusant le problème inverse (pas de moyen de\nrestreindre QUELS skills un agent voit) :\n\n> *\"Custom agents (`.agent.md`) support a `tools` property to restrict which\n> tools are available per agent. However, there is no equivalent mechanism for\n> **skills**... All skills from all discovery locations... are visible to all\n> agents simultaneously.\"*\n\nEt cite comme cas d'usage non résolu, mot pour mot notre situation :\n\n> *\"Security/principle of least privilege: Some agents should be read-only\n> (already possible via `tools`), but they also shouldn't have access to\n> skills that trigger write operations via their instructions.\"*\n\n**Ce que ça confirme pour mA.xI.me** : `tools:` sur un Custom Agent (`.agent.md`)\nest un mécanisme **réel et fonctionnel** — c'est le seul niveau où la\nrestriction d'outils existe concrètement côté Copilot. Un Skill chargé\npendant que `maxi-copilot-reviewer` (`tools: [read, search]`) est actif ne\npeut **pas** faire apparaître `edit`/`execute` : ces outils ne sont\nsimplement pas dans la liste dont dispose le modèle à ce moment-là, peu\nimporte ce que le texte du skill suggère. **La garantie lecture-seule tient\ndonc, à condition que l'agent restreint soit explicitement actif au moment\nde l'invocation.**\n\nLe risque réel n'est donc pas \"le skill contourne la restriction\" — c'est\n\"aucune restriction n'est active si l'utilisateur invoque le workflow depuis\nun contexte non restreint\" (chat par défaut, ou l'agent `maxi-copilot` lui-même,\nqui a `edit`+`execute`). Dans ce cas, peu importe lequel des trois SKILL.md\nhomonymes charge : aucun n'a jamais eu la capacité de restreindre quoi que ce\nsoit — c'était déjà vrai avant même la découverte de `.agents/skills/`.\n\n### Contournement documenté par la communauté (imparfait, mais réel)\n\nUn des commentaires sur #307630 documente le seul palliatif existant\naujourd'hui : ajouter dans le corps de l'agent (`.agent.md`) une consigne\nexplicite du type *\"only load skills from this directory\"* — *\"this works\nreasonably well because the model follows instructions, but it's not\nenforced by the system and doesn't filter the `/` menu\"*. C'est exactement le\nmême type de garantie que celle déjà documentée pour Codex dans\n`docs/ARCHITECTURE.md` (consigne textuelle, pas verrou technique) — pas une\nsolution, une atténuation.\n\n### Suivi amont (pour re-vérifier plus tard si le paysage change)\n\n- [#293276](https://github.com/microsoft/vscode/issues/293276) — auto-approbation d'outils scopée à un skill (ouvert)\n- [#307630](https://github.com/microsoft/vscode/issues/307630) — scoper quels skills un agent peut voir (ouvert)\n- [#313951](https://github.com/microsoft/vscode/issues/313951) / [#311166](https://github.com/microsoft/vscode/issues/311166) — déclaration de capacités (`tools`, `mcp-servers`, `hooks`, `model`) dans le frontmatter `SKILL.md` (ouverts, doublons du même besoin)\n- [#294520](https://github.com/microsoft/vscode/issues/294520) — validation du frontmatter rejetait des attributs inconnus, cassant l'extensibilité du standard (fermé)\n\n## Ce qui reste réellement incertain\n\n- Priorité exacte entre `.github/skills/`, `.claude/skills/`, `.agents/skills/`\n quand le même nom existe aux trois emplacements — non documentée, et sans\n incidence pratique vu ce qui précède (aucun des trois ne restreint quoi que\n ce soit de toute façon).\n- Le paramètre `chat.useAgentSkills` doit être actif pour que la découverte de\n skills fonctionne du tout (confirmé, notes de version VS Code 1.108) — le\n désactiver empêcherait Copilot de charger `.agents/skills/maxime-review`,\n au prix de perdre Agent Skills partout dans le workspace, pas seulement\n pour mA.xI.me.\n\n## Sources consultées\n\n- [agentskills.io — Agent Skills Overview](https://agentskills.io)\n- [code.claude.com/docs/en/skills — Extend Claude with skills](https://code.claude.com/docs/en/skills)\n- [code.claude.com/docs/en/vs-code — Use Claude Code in VS Code](https://code.claude.com/docs/en/vs-code)\n- [code.visualstudio.com/docs/agent-customization/overview](https://code.visualstudio.com/docs/agent-customization/overview)\n- [code.visualstudio.com/docs/agent-customization/custom-agents](https://code.visualstudio.com/docs/agent-customization/custom-agents)\n- [code.visualstudio.com/docs/agent-customization/agent-skills](https://code.visualstudio.com/docs/agent-customization/agent-skills) (déjà utilisée dans la fiche KB du 2026-07-12 sur les outils built-in)\n- [docs.github.com — About custom agents](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-custom-agents)\n- [learn.chatgpt.com/docs/codex/ide](https://learn.chatgpt.com/docs/codex/ide) (Codex IDE extension, redirigé depuis developers.openai.com/codex/ide)\n- [learn.chatgpt.com/docs/agent-configuration/agents-md](https://learn.chatgpt.com/docs/agent-configuration/agents-md) (redirigé depuis developers.openai.com/codex/guides/agents-md)\n- [developers.openai.com/codex/skills](https://developers.openai.com/codex/skills)\n- [agentskills.io/specification](https://agentskills.io/specification) — spécification complète du format\n- [github.com/microsoft/vscode/issues/293276](https://github.com/microsoft/vscode/issues/293276) — confirmation directe (membre équipe VS Code) que `allowed-tools` n'est pas implémenté\n- [github.com/microsoft/vscode/issues/307630](https://github.com/microsoft/vscode/issues/307630) — absence de scoping skill/agent, cas d'usage identique au nôtre\n- [learn.microsoft.com/.../copilot-agent-skills](https://learn.microsoft.com/en-us/visualstudio/ide/copilot-agent-skills?view=visualstudio) — doc Visual Studio (IDE complet, pas VS Code), mêmes trois emplacements confirmés\n- [code.visualstudio.com/updates/v1_108](https://code.visualstudio.com/updates/v1_108) — notes de version, confirme `.claude/skills/` scanné \"for backwards compatibility\" et le paramètre `chat.useAgentSkills`\n\n## Liens\n\nVoir aussi [[20260712.new.vscode-copilot-builtin-tools]] (catégories d'outils\nbuilt-in Copilot/VS Code — sujet voisin mais distinct : celui-là porte sur les\noutils, celui-ci sur la découverte de skills/agents).\n" -} \ No newline at end of file +} diff --git a/active/aws/ecs-fargate-task-isolation.json b/active/aws/ecs-fargate-task-isolation.json index 4869c2d..39c6cfc 100644 --- a/active/aws/ecs-fargate-task-isolation.json +++ b/active/aws/ecs-fargate-task-isolation.json @@ -23,5 +23,5 @@ "links": [ "zero-standing-access" ], - "content": "# ECS — launch type EC2 vs Fargate, isolation\n\n## EC2 launch type\n\nLes tasks ECS s'exécutent comme des conteneurs sur des instances EC2 gérées par le client, en partageant le **même noyau hôte**. La documentation AWS elle-même est explicite : les conteneurs ne sont pas une frontière d'isolation de sécurité garantie — un conteneur compromis peut potentiellement atteindre des ressources d'autres tasks colocalisées sur le même hôte (évasion de conteneur, attaque via le noyau partagé).\n\n## Fargate launch type\n\nChaque task tourne dans sa **propre micro-VM** dédiée — frontière d'isolation matérielle réelle entre tasks, même si elles appartiennent à des services différents sur le même compte. Compromis : moins de contrôle sur l'instance sous-jacente (pas d'accès SSH à l'hôte, pas de choix du type d'instance EC2), en échange d'une isolation plus forte par défaut.\n\n## gMSA sur Fargate\n\nSupport depuis **mars 2024**, mais **limité aux conteneurs Linux**, via le mode **domainless gMSA** et le daemon `credentials-fetcher` packagé par AWS. Pas de support équivalent documenté pour des conteneurs Windows sur Fargate — vérifier ce point avant de bâtir une architecture qui en dépendrait.\n\nEn mode domainless, le conteneur n'est **pas** joint au domaine. `credentials-fetcher` récupère un identifiant AD **statique** (utilisateur + mot de passe + nom de domaine) stocké dans un secret AWS Secrets Manager, référencé par le fichier CredSpec de la task — ce n'est donc **pas une chaîne entièrement secretless** : il existe un credential AD permanent au bootstrap, protégé par IAM (accès au secret scoped au rôle d'exécution de la task), pas par une rotation JIT. Le conteneur applicatif, lui, ne voit jamais ce mot de passe — `credentials-fetcher` le consomme et expose un ticket Kerberos au conteneur.\n\n## Quand privilégier Fargate\n\nPertinent quand la charge de travail est une **passerelle privilégiée** vers un système sensible (ex. LDAP/AD) où la compromission d'un voisin de conteneur serait un risque inacceptable — le coût de l'isolation micro-VM se justifie par l'enjeu, pas par défaut pour toute charge de travail." + "content": "# ECS — launch type EC2 vs Fargate, isolation\n\n## EC2 launch type\n\nLes tasks ECS s'exécutent comme des conteneurs sur des instances EC2 gérées par le client, en partageant le **même noyau hôte**. La documentation AWS elle-même est explicite : les conteneurs ne sont pas une frontière d'isolation de sécurité garantie — un conteneur compromis peut potentiellement atteindre des ressources d'autres tasks colocalisées sur le même hôte (évasion de conteneur, attaque via le noyau partagé).\n\n## Fargate launch type\n\nChaque task tourne dans sa **propre micro-VM** dédiée — frontière d'isolation matérielle réelle entre tasks, même si elles appartiennent à des services différents sur le même compte. Compromis : moins de contrôle sur l'instance sous-jacente (pas d'accès SSH à l'hôte, pas de choix du type d'instance EC2), en échange d'une isolation plus forte par défaut.\n\n## gMSA sur Fargate\n\nSupport depuis **mars 2024**, mais **limité aux conteneurs Linux**, via le mode **domainless gMSA** et le daemon `credentials-fetcher` packagé par AWS. Pas de support équivalent documenté pour des conteneurs Windows sur Fargate — vérifier ce point avant de bâtir une architecture qui en dépendrait.\n\nEn mode domainless, le conteneur n'est **pas** joint au domaine. `credentials-fetcher` récupère un identifiant AD **statique** (utilisateur + mot de passe + nom de domaine) stocké dans un secret AWS Secrets Manager, référencé par le fichier CredSpec de la task — ce n'est donc **pas une chaîne entièrement secretless** : il existe un credential AD permanent au bootstrap, protégé par IAM (accès au secret scoped au rôle d'exécution de la task), pas par une rotation JIT. Le conteneur applicatif, lui, ne voit jamais ce mot de passe — `credentials-fetcher` le consomme et expose un ticket Kerberos au conteneur.\n\n## Quand privilégier Fargate\n\nPertinent quand la charge de travail est une **passerelle privilégiée** vers un système sensible (ex. LDAP/AD) où la compromission d'un voisin de conteneur serait un risque inacceptable — le coût de l'isolation micro-VM se justifie par l'enjeu, pas par défaut pour toute charge de travail.\n" } diff --git a/active/claude-config/claude-md-hierarchie.json b/active/claude-config/claude-md-hierarchie.json index fe0eaa2..3f8718f 100644 --- a/active/claude-config/claude-md-hierarchie.json +++ b/active/claude-config/claude-md-hierarchie.json @@ -3,14 +3,22 @@ "type": "reference", "title": "Hiérarchie & chargement des CLAUDE.md (Claude Code)", "theme": "claude-config", - "tags": ["claude-code", "claude-md", "memory"], + "tags": [ + "claude-code", + "claude-md", + "memory" + ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", - "source": ["https://code.claude.com/docs/en/memory"], + "source": [ + "https://code.claude.com/docs/en/memory" + ], "validated": "2026-06-16", "created": "2026-06-16", - "links": ["claude-md-import-mechanism"], + "links": [ + "claude-md-import-mechanism" + ], "content": "# Hiérarchie & chargement des CLAUDE.md (Claude Code)\n\nStatut : `.new` — capture brute de recherche du 2026-06-16 (bootstrap du\nprojet), déplacée de `docs/CLAUDE-MD-HIERARCHIE.md` le 2026-07-13 : contenu\ngénérique réutilisable sur la plateforme Claude Code, sans donnée de\nprojet/client/employeur, pas encore relu/validé comme fiche KB stable.\n\nSource officielle (lue et vérifiée) : [claude memory docs](https://code.claude.com/docs/en/memory)\n\n---\n\n## 1. Les 4 niveaux (par ordre de chargement, du plus large au plus spécifique)\n\n| Scope | Emplacement | Rôle | Partagé avec |\n| - | - | - | - |\n| **Managed policy** | macOS : `/Library/Application Support/ClaudeCode/CLAUDE.md`
Linux/WSL : `/etc/claude-code/CLAUDE.md`
Windows : `C:\\Program Files\\ClaudeCode\\CLAUDE.md` | Instructions imposées par l'organisation (IT/DevOps) : standards, sécurité, conformité | Tous les utilisateurs de la machine/org |\n| **User instructions** | `~/.claude/CLAUDE.md` | Préférences personnelles, tous projets | Moi seul (tous projets) |\n| **Project instructions** | `./CLAUDE.md` ou `./.claude/CLAUDE.md` | Instructions partagées de l'équipe | L'équipe via le contrôle de source |\n| **Local instructions** | `./CLAUDE.local.md` | Préférences perso d'un projet ; à mettre dans `.gitignore` | Moi seul (projet courant) |\n\nLes niveaux se **cumulent** (concaténés), ils ne s'écrasent pas.\n\n---\n\n## 2. Comment le chargement fonctionne RÉELLEMENT (le point clé)\n\nClaude Code ne lit pas une liste fixe d'emplacements. Il **remonte l'arborescence**\ndepuis le répertoire de travail (cwd) jusqu'à la racine, et charge chaque\n`CLAUDE.md` et `CLAUDE.local.md` rencontré en chemin.\n\nExemple : lancé dans `foo/bar/`, il charge `foo/bar/CLAUDE.md`, puis `foo/CLAUDE.md`,\nplus les `CLAUDE.local.md` à côté.\n\n**Ordre dans le contexte** : de la racine du système vers le cwd. Donc les\ninstructions les plus proches de l'endroit où tu lances Claude sont lues **en\ndernier**. En cas de contradiction, le \"dernier lu\" agit comme un signal de priorité.\nDans chaque dossier, `CLAUDE.local.md` est ajouté APRÈS `CLAUDE.md`.\n\nLes `CLAUDE.md` des sous-dossiers (sous le cwd) ne sont PAS chargés au lancement :\nils se chargent à la demande quand Claude lit un fichier de ce sous-dossier.\n\n### ⚠️ Piège vécu (2026-06-16)\n\nLe niveau \"Project\" est relatif au cwd. Lancer Claude Code depuis un dossier qui\nn'est pas un repo git (ex : `C:\\Users\\` ou `...\\source\\repos`) fait que\n`./CLAUDE.md` se rabat sur le `CLAUDE.md` de CE dossier. C'est ce qui avait créé\nl'illusion d'un \"CLAUDE.md à la racine du profil\" : ce n'était pas un emplacement\nofficiel séparé, juste un palier de la remontée d'arbre.\n→ **Toujours lancer Claude Code depuis un vrai repo git** pour que le niveau\nProject pointe au bon endroit.\n\n---\n\n## 3. CLAUDE.md ≠ configuration imposée (TRÈS important)\n\n> Les CLAUDE.md (et l'auto memory) sont traités comme du **contexte**, pas comme\n> de la configuration appliquée de force. Pour bloquer une action quoi que Claude\n> décide, il faut un **hook PreToolUse**, pas une ligne de texte.\n\nConséquence directe pour nos \"règles inviolables\" (jamais `git add -A`, jamais main) :\n\n- Écrites dans le CLAUDE.md = instructions FORTES, mais pas un verrou.\n- Pour un vrai blocage technique → **hook** (`PreToolUse`) ou **managed settings**\n (`permissions.deny`). À considérer pour les garde-fous critiques.\n\nCLAUDE.md content est délivré comme un message utilisateur après le system prompt :\nClaude le lit et tente de le suivre, sans garantie de conformité stricte —\nsurtout si les instructions sont vagues ou contradictoires.\n\n---\n\n## 4. Bonnes pratiques d'écriture (officiel)\n\n- **Taille** : viser **< 200 lignes** par CLAUDE.md. Plus long = plus de contexte\n consommé et **moins bonne adhérence**. (Cette limite des 200 lignes / 25 KB\n s'applique à `MEMORY.md` de l'auto-memory ; les CLAUDE.md, eux, sont chargés en\n entier quelle que soit la longueur — mais plus court = mieux suivi.)\n- **Spécificité** : \"Use 2-space indentation\" plutôt que \"format code properly\".\n \"Run `npm test` before committing\" plutôt que \"test your changes\".\n- **Structure** : titres markdown + bullets. Claude scanne la structure comme un lecteur.\n- **Cohérence** : si deux règles se contredisent, Claude en choisit une arbitrairement.\n Revoir périodiquement pour retirer le contradictoire ou l'obsolète.\n\n---\n\n## 5. Astuces utiles découvertes\n\n### Commentaires HTML = notes gratuites\n\nLes commentaires HTML de niveau bloc `` sont **retirés avant injection**\ndans le contexte. → Laisser des notes aux mainteneurs humains SANS consommer de\ntokens. (Les commentaires DANS un bloc de code sont, eux, préservés. Et `Read`\nsur le fichier les montre.)\n\n### Imports `@path`\n\nUn CLAUDE.md peut importer d'autres fichiers via `@chemin/fichier`. Chemins relatifs\n(résolus par rapport au fichier qui importe) ou absolus. Récursif, max 4 niveaux.\n⚠️ Les fichiers importés sont chargés au lancement → ça n'économise PAS de contexte,\nça organise seulement.\nExemple : `# git workflow @docs/git-instructions.md`\nPartager du perso entre worktrees : `@~/.claude/my-project-instructions.md`.\n\n### `/init` pour démarrer un CLAUDE.md projet\n\nAnalyse le codebase et génère un CLAUDE.md de départ (build, tests, conventions).\nS'il existe déjà, `/init` propose des améliorations au lieu d'écraser.\n`CLAUDE_CODE_NEW_INIT=1` active un flux interactif multi-phases.\n\n### AGENTS.md\n\nClaude Code lit `CLAUDE.md`, pas `AGENTS.md`. Si un repo a déjà un AGENTS.md :\ncréer un CLAUDE.md qui l'importe → `@AGENTS.md` (puis ajouter des instructions\nClaude-spécifiques en dessous). Sur Windows, préférer l'import `@AGENTS.md` au\nsymlink (le symlink exige les droits admin / mode développeur).\n\n### `.claude/rules/` pour les gros projets\n\nDécouper en fichiers par sujet (`testing.md`, `security.md`...). Chargés à chaque\nsession avec la même priorité que `.claude/CLAUDE.md`. Peuvent être **scopés par\nchemin** via frontmatter `paths:` (glob) → ne se chargent que quand Claude touche\nles fichiers correspondants = moins de bruit, contexte économisé.\nRègles user-level : `~/.claude/rules/` (préférences perso, tous projets).\nPartage entre projets via symlinks.\n\n### Skills vs rules vs CLAUDE.md (quand utiliser quoi)\n\n- **CLAUDE.md** : faits à garder chaque session (build, conventions, \"always X\").\n- **Rules** (`.claude/rules/`) : modulaire, scopable par chemin, chargé en contexte.\n- **Skills** : workflows répétables, chargés UNIQUEMENT à l'invocation ou quand\n Claude juge pertinent. Pour les procédures qui n'ont pas à être en contexte tout le temps.\n\n### Monorepo — exclure des CLAUDE.md parasites\n\n`claudeMdExcludes` (dans `.claude/settings.local.json`) saute des CLAUDE.md\nd'autres équipes par chemin/glob. Les managed policy ne peuvent PAS être exclus.\n\n### Survie au /compact\n\nLe CLAUDE.md de racine de projet survit au `/compact` (re-lu depuis le disque).\nLes CLAUDE.md de sous-dossiers ne sont pas réinjectés auto : ils rechargent au\nprochain accès à un fichier de ce sous-dossier. → Mettre dans CLAUDE.md ce qui\nne doit pas se perdre (pas seulement dans la conversation).\n\n### Débogage \"Claude ne suit pas mon CLAUDE.md\"\n\n1. `/memory` → vérifier que le fichier est bien listé (sinon Claude ne le voit pas).\n2. Vérifier que l'emplacement est bien chargé pour la session (cf. remontée d'arbre).\n3. Rendre les instructions plus spécifiques.\n4. Chercher les contradictions entre fichiers.\n5. Si ça doit s'exécuter à un moment précis (avant chaque commit...) → **hook**, pas CLAUDE.md.\nAstuce : hook `InstructionsLoaded` pour logger quels fichiers d'instructions\nsont chargés, quand et pourquoi.\n\n---\n\n## 6. CLAUDE_CONFIG_DIR (notre cas)\n\nDéplace le dossier de config (`~/.claude` → dossier choisi). Vérifié sur la\nmachine : elle ne redirige pas le chargement des CLAUDE.md comme on pourrait le\ncroire ; elle déplace surtout l'état local (auto-memory, sessions).\n→ Par défaut : NE PAS la définir. Rester au standard. (On l'a retirée le 2026-06-16.)\n\nNB auto-memory : chaque projet a `~/.claude/projects//memory/` avec un\n`MEMORY.md` (index, 200 lignes / 25 KB chargées par session) + fichiers par sujet\nchargés à la demande. `` dérive du repo git → hors repo git, c'est la\nracine du dossier qui sert. Raison de plus pour travailler dans de vrais repos git.\n\n---\n\n## 7. Application à mA.xI.me (déjà documenté ailleurs, gardé pour mémoire)\n\nCe document décrit les mécanismes propres à Claude Code ; il ne définit pas le socle\nuniversel de mA.xI.me (voir `core/socle.md` et `docs/ARCHITECTURE.md`).\n\n- **Socle mA.xI.me** → `core/socle.md`, projeté dans le `CLAUDE.md` du repository\n cible par l'installateur repo-only.\n- **Orchestrateur** → agent `maxi-claude` et workflows sous `.claude/` dans le\n repository cible, sans installation sous `~/.claude/` par mA.xI.me.\n- **État partagé** → `.wip/`, lu également par les adaptateurs Copilot et Codex.\n- **Garde-fous critiques** → le hook Claude peut compléter le texte, mais n'est pas\n une garantie portable aux autres hôtes.\n- **KB** → submodule `knowledge-base/` relatif au repository si le projet l'utilise.\n" -} \ No newline at end of file +} diff --git a/active/claude-config/claude-md-import-mechanism.json b/active/claude-config/claude-md-import-mechanism.json index a500a0c..d2b3ee1 100644 --- a/active/claude-config/claude-md-import-mechanism.json +++ b/active/claude-config/claude-md-import-mechanism.json @@ -3,14 +3,30 @@ "type": "reference", "title": "Claude Code — mécanisme d'import @fichier pour CLAUDE.md", "theme": "claude-config", - "tags": ["claude-code", "claude-md", "import", "config-merge"], + "tags": [ + "claude-code", + "claude-md", + "import", + "config-merge" + ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", - "source": ["https://code.claude.com/docs/en/memory", "https://github.com/anthropics/claude-code/issues/2950", "https://github.com/anthropics/claude-code/issues/8533", "https://github.com/anthropics/claude-code/issues/1041", "https://github.com/anthropics/claude-code/issues/5231", "https://github.com/anthropics/claude-code/issues/7768"], + "source": [ + "https://code.claude.com/docs/en/memory", + "https://github.com/anthropics/claude-code/issues/2950", + "https://github.com/anthropics/claude-code/issues/8533", + "https://github.com/anthropics/claude-code/issues/1041", + "https://github.com/anthropics/claude-code/issues/5231", + "https://github.com/anthropics/claude-code/issues/7768" + ], "validated": "2026-07-16", "created": "2026-07-16", - "links": ["claude-md-hierarchie", "copilot-instructions-merge", "codex-agents-md-nesting"], - "content": "# Claude Code — mécanisme d'import @fichier pour CLAUDE.md\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27 (l'installateur écrase un CLAUDE.md project-specific existant).\n\n## Ce qui est confirmé (sourcé)\n\n- La syntaxe `@chemin/fichier` est un import officiel et documenté : chemins relatifs (résolus par rapport au fichier qui importe, pas au cwd) ou absolus. Récursion jusqu'à 4 niveaux. Le parseur d'imports ignore les blocs de code et le code inline (`@README` entre backticks reste littéral). Source : https://code.claude.com/docs/en/memory\n- **Directement pertinent** : la documentation Anthropic elle-même recommande exactement le pattern inverse de notre cas d'usage — pour un repo qui a déjà un AGENTS.md, créer un CLAUDE.md qui fait `@AGENTS.md` puis ajoute du contenu Claude-spécifique en dessous. Ça confirme qu'une ligne `@import` est un contenu stable, générable par un outil : le générateur peut toujours émettre la même ligne d'import, elle continuera à se résoudre tant que le fichier cible existe.\n- Les CLAUDE.md de l'arborescence sont concaténés, jamais remplacés — le fichier du dossier parent charge avant celui du cwd, et `CLAUDE.local.md` est ajouté après `CLAUDE.md` dans le même dossier.\n- `/init` ne réécrit jamais un CLAUDE.md existant — il propose seulement des améliorations.\n- Alternative sans syntaxe d'import du tout : `.claude/rules/*.md` — tout fichier `.md` déposé là charge automatiquement (même priorité que `.claude/CLAUDE.md`), scopable par `paths:` en frontmatter. Symlinks supportés pour partager des règles entre repos.\n- La première utilisation d'un import externe déclenche une boîte de dialogue d'approbation ponctuelle ; refuser désactive silencieusement les imports pour le projet en permanence (risque d'échec silencieux si l'utilisateur a cliqué \"non\" une fois).\n\n## Incertitudes explicites\n\n- Aucune confirmation de mainteneur que les imports sont fiables à 100% : issue GitHub ouverte #2950 (anthropics/claude-code) rapporte que l'import est chargé en contexte mais Claude n'agit pas toujours dessus de façon déterministe (problème d'adhérence du modèle, pas de résolution de fichier).\n- Plusieurs rapports de bugs de résolution/imbrication de chemins @ : #8533 (Claude n'écrit pas toujours la syntaxe @ correctement quand on le lui demande), #1041 (l'import échoue spécifiquement dans le CLAUDE.md global ~/.claude/CLAUDE.md), #5231, #7768 (comportement erratique sur des imports imbriqués/relatifs). Rien n'indique que ce soit corrigé à la date de cette recherche.\n- Aucun fil Reddit/Discord trouvé spécifiquement sur un outil générateur qui réécrit CLAUDE.md pendant que les imports survivent — le cas le plus proche est l'exemple AGENTS.md d'Anthropic ci-dessus, direct mais pas issu de la communauté.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nDeux mécanismes natifs viables : (a) le générateur émet toujours une ligne fixe `@project-conventions.md` (ou nom similaire) — la doc Anthropic elle-même valide ce pattern exact ; ou (b) ne jamais toucher CLAUDE.md pour du contenu projet, et faire écrire par l'installateur dans `.claude/rules/*.md` à la place — élimine le problème à la racine puisque le générateur ne possède jamais ce fichier.\n\n## Sources\n- https://code.claude.com/docs/en/memory\n- https://github.com/anthropics/claude-code/issues/2950\n- https://github.com/anthropics/claude-code/issues/8533\n- https://github.com/anthropics/claude-code/issues/1041\n- https://github.com/anthropics/claude-code/issues/5231\n- https://github.com/anthropics/claude-code/issues/7768" -} \ No newline at end of file + "links": [ + "claude-md-hierarchie", + "copilot-instructions-merge", + "codex-agents-md-nesting" + ], + "content": "# Claude Code — mécanisme d'import @fichier pour CLAUDE.md\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27 (l'installateur écrase un CLAUDE.md project-specific existant).\n\n## Ce qui est confirmé (sourcé)\n\n- La syntaxe `@chemin/fichier` est un import officiel et documenté : chemins relatifs (résolus par rapport au fichier qui importe, pas au cwd) ou absolus. Récursion jusqu'à 4 niveaux. Le parseur d'imports ignore les blocs de code et le code inline (`@README` entre backticks reste littéral). Source : https://code.claude.com/docs/en/memory\n- **Directement pertinent** : la documentation Anthropic elle-même recommande exactement le pattern inverse de notre cas d'usage — pour un repo qui a déjà un AGENTS.md, créer un CLAUDE.md qui fait `@AGENTS.md` puis ajoute du contenu Claude-spécifique en dessous. Ça confirme qu'une ligne `@import` est un contenu stable, générable par un outil : le générateur peut toujours émettre la même ligne d'import, elle continuera à se résoudre tant que le fichier cible existe.\n- Les CLAUDE.md de l'arborescence sont concaténés, jamais remplacés — le fichier du dossier parent charge avant celui du cwd, et `CLAUDE.local.md` est ajouté après `CLAUDE.md` dans le même dossier.\n- `/init` ne réécrit jamais un CLAUDE.md existant — il propose seulement des améliorations.\n- Alternative sans syntaxe d'import du tout : `.claude/rules/*.md` — tout fichier `.md` déposé là charge automatiquement (même priorité que `.claude/CLAUDE.md`), scopable par `paths:` en frontmatter. Symlinks supportés pour partager des règles entre repos.\n- La première utilisation d'un import externe déclenche une boîte de dialogue d'approbation ponctuelle ; refuser désactive silencieusement les imports pour le projet en permanence (risque d'échec silencieux si l'utilisateur a cliqué \"non\" une fois).\n\n## Incertitudes explicites\n\n- Aucune confirmation de mainteneur que les imports sont fiables à 100% : issue GitHub ouverte #2950 (anthropics/claude-code) rapporte que l'import est chargé en contexte mais Claude n'agit pas toujours dessus de façon déterministe (problème d'adhérence du modèle, pas de résolution de fichier).\n- Plusieurs rapports de bugs de résolution/imbrication de chemins @ : #8533 (Claude n'écrit pas toujours la syntaxe @ correctement quand on le lui demande), #1041 (l'import échoue spécifiquement dans le CLAUDE.md global ~/.claude/CLAUDE.md), #5231, #7768 (comportement erratique sur des imports imbriqués/relatifs). Rien n'indique que ce soit corrigé à la date de cette recherche.\n- Aucun fil Reddit/Discord trouvé spécifiquement sur un outil générateur qui réécrit CLAUDE.md pendant que les imports survivent — le cas le plus proche est l'exemple AGENTS.md d'Anthropic ci-dessus, direct mais pas issu de la communauté.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nDeux mécanismes natifs viables : (a) le générateur émet toujours une ligne fixe `@project-conventions.md` (ou nom similaire) — la doc Anthropic elle-même valide ce pattern exact ; ou (b) ne jamais toucher CLAUDE.md pour du contenu projet, et faire écrire par l'installateur dans `.claude/rules/*.md` à la place — élimine le problème à la racine puisque le générateur ne possède jamais ce fichier.\n\n## Sources\n- https://code.claude.com/docs/en/memory\n- https://github.com/anthropics/claude-code/issues/2950\n- https://github.com/anthropics/claude-code/issues/8533\n- https://github.com/anthropics/claude-code/issues/1041\n- https://github.com/anthropics/claude-code/issues/5231\n- https://github.com/anthropics/claude-code/issues/7768\n" +} diff --git a/active/codex-config/codex-agents-md-nesting.json b/active/codex-config/codex-agents-md-nesting.json index 5ec04e2..8af50e5 100644 --- a/active/codex-config/codex-agents-md-nesting.json +++ b/active/codex-config/codex-agents-md-nesting.json @@ -3,14 +3,23 @@ "type": "reference", "title": "OpenAI Codex — imbrication et fusion des fichiers AGENTS.md", "theme": "codex-config", - "tags": ["codex", "agents-md", "config-merge"], + "tags": [ + "codex", + "agents-md", + "config-merge" + ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", - "source": ["https://learn.chatgpt.com/docs/agent-configuration/agents-md"], + "source": [ + "https://learn.chatgpt.com/docs/agent-configuration/agents-md" + ], "validated": "2026-07-16", "created": "2026-07-16", - "links": ["claude-md-import-mechanism", "copilot-instructions-merge"], - "content": "# OpenAI Codex — imbrication et fusion des fichiers AGENTS.md\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27.\n\n## Ce qui est confirmé (sourcé)\n\n- Support officiel de fichiers AGENTS.md imbriqués, fusionnés de la racine vers la feuille, concaténés avec des lignes vides ; les fichiers les plus proches du cwd sont ajoutés en dernier et peuvent surcharger les instructions précédentes. Source : https://learn.chatgpt.com/docs/agent-configuration/agents-md\n- Un mécanisme explicite AGENTS.override.md existe, au niveau global (~/.codex/) comme à tout niveau de dossier projet ; Codex vérifie d'abord la présence d'un override, puis se rabat sur AGENTS.md, puis sur les noms de fallback configurés — au plus un fichier utilisé par dossier.\n- Aucune syntaxe d'import/inclusion à l'intérieur d'un seul AGENTS.md — la fusion est purement basée sur la hiérarchie de dossiers.\n- Plafond de taille : 32 KiB combinés par défaut (project_doc_max_bytes), configurable.\n- Le site de spécification communautaire agents.md corrobore : \"le AGENTS.md le plus proche gagne\", conçu explicitement pour des instructions par paquet dans des monorepos (cite le repo d'OpenAI lui-même utilisant 88 fichiers AGENTS.md).\n\n## Incertitudes explicites\n\n- Aucune issue GitHub ni fil Reddit/HN trouvé spécifiquement sur un outil qui réécrit un contenu AGENTS.md écrit à la main — les recherches n'ont renvoyé que de la documentation officielle ou dérivée, aucun fil de plainte concret.\n- Aucune couverture YouTube trouvée traitant spécifiquement de ce problème de coexistence.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nPartielle : pas de syntaxe d'import, mais le mécanisme override + fichiers imbriqués donne une voie équivalente — plus directement, faire écrire par le générateur dans AGENTS.override.md au lieu de AGENTS.md au même niveau de dossier, laissant tout AGENTS.md pré-existant écrit à la main intact et toujours utilisé comme couche de base que l'override étend. C'est un détournement du mécanisme (les fichiers override étaient conçus pour restreindre, pas pour séparer outil/humain) — à traiter comme fonctionnel mais non validé par la doc pour cet usage précis.\n\n## Sources\n- https://learn.chatgpt.com/docs/agent-configuration/agents-md" -} \ No newline at end of file + "links": [ + "claude-md-import-mechanism", + "copilot-instructions-merge" + ], + "content": "# OpenAI Codex — imbrication et fusion des fichiers AGENTS.md\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27.\n\n## Ce qui est confirmé (sourcé)\n\n- Support officiel de fichiers AGENTS.md imbriqués, fusionnés de la racine vers la feuille, concaténés avec des lignes vides ; les fichiers les plus proches du cwd sont ajoutés en dernier et peuvent surcharger les instructions précédentes. Source : https://learn.chatgpt.com/docs/agent-configuration/agents-md\n- Un mécanisme explicite AGENTS.override.md existe, au niveau global (~/.codex/) comme à tout niveau de dossier projet ; Codex vérifie d'abord la présence d'un override, puis se rabat sur AGENTS.md, puis sur les noms de fallback configurés — au plus un fichier utilisé par dossier.\n- Aucune syntaxe d'import/inclusion à l'intérieur d'un seul AGENTS.md — la fusion est purement basée sur la hiérarchie de dossiers.\n- Plafond de taille : 32 KiB combinés par défaut (project_doc_max_bytes), configurable.\n- Le site de spécification communautaire agents.md corrobore : \"le AGENTS.md le plus proche gagne\", conçu explicitement pour des instructions par paquet dans des monorepos (cite le repo d'OpenAI lui-même utilisant 88 fichiers AGENTS.md).\n\n## Incertitudes explicites\n\n- Aucune issue GitHub ni fil Reddit/HN trouvé spécifiquement sur un outil qui réécrit un contenu AGENTS.md écrit à la main — les recherches n'ont renvoyé que de la documentation officielle ou dérivée, aucun fil de plainte concret.\n- Aucune couverture YouTube trouvée traitant spécifiquement de ce problème de coexistence.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nPartielle : pas de syntaxe d'import, mais le mécanisme override + fichiers imbriqués donne une voie équivalente — plus directement, faire écrire par le générateur dans AGENTS.override.md au lieu de AGENTS.md au même niveau de dossier, laissant tout AGENTS.md pré-existant écrit à la main intact et toujours utilisé comme couche de base que l'override étend. C'est un détournement du mécanisme (les fichiers override étaient conçus pour restreindre, pas pour séparer outil/humain) — à traiter comme fonctionnel mais non validé par la doc pour cet usage précis.\n\n## Sources\n- https://learn.chatgpt.com/docs/agent-configuration/agents-md\n" +} diff --git a/active/engine-catalog/claude-code-models.json b/active/engine-catalog/claude-code-models.json index 4233ed9..d601dd3 100644 --- a/active/engine-catalog/claude-code-models.json +++ b/active/engine-catalog/claude-code-models.json @@ -3,7 +3,13 @@ "type": "reference", "title": "Claude Code — moteurs (modèles) et effort, catalogue + qui décide", "theme": "engine-catalog", - "tags": ["claude-code", "models", "effort", "subagents", "engine-catalog"], + "tags": [ + "claude-code", + "models", + "effort", + "subagents", + "engine-catalog" + ], "scope": "global", "status": "active", "confidence": "fact", @@ -16,6 +22,9 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "links": ["copilot-models", "codex-models"], + "links": [ + "copilot-models", + "codex-models" + ], "content": "# Claude Code — moteurs (modèles) et effort\n\n## Deux axes distincts, pas un seul\n\nClaude Code expose deux réglages indépendants, avec des règles d'auto-configuration différentes pour chacun — à ne pas confondre :\n\n1. **`model`** (moteur) : `sonnet`, `opus`, `haiku`, `fable`, `inherit`, ou un ID de modèle complet (ex. `claude-opus-4-8`).\n2. **`effort`** : `low`, `medium`, `high` (défaut), `xhigh`, `max` — contrôle la profondeur de réflexion et le volume de tokens dépensés, indépendamment du modèle choisi.\n\nCorrection par rapport à une hypothèse de recherche antérieure (2026-07-16, avant cette fiche) : l'effort n'est **plus** \"encodé dans le choix du modèle\" — c'est un paramètre API à part entière (`output_config.effort`), disponible sur Claude Fable 5, Claude Mythos 5, Opus 4.5 à 4.8, Sonnet 5, Sonnet 4.6. Il affecte tous les tokens de la réponse (texte, appels d'outils, réflexion étendue), pas seulement la réflexion.\n\n## Qui peut configurer quoi\n\n- **`model` par sous-agent : auto-configurable, confirmé.** Le paramètre `model` de l'outil `Agent`/`Task` (dans cet environnement même) prend le pas sur la définition de l'agent (frontmatter `model:`), documenté \"takes precedence over the agent definition's model frontmatter\". Un orchestrateur peut donc choisir le modèle d'un sous-agent qu'il délègue, sans intervention humaine à chaque appel. Défaut du frontmatter : `inherit` (même modèle que la session principale) si non précisé.\n- **`model` pour l'agent en cours (pas un sous-agent) : PAS auto-configurable.** Rien ne permet à l'agent en cours d'exécution de changer son propre modèle en cours de session par une action programmatique (un humain peut le faire via `/fast` ou le picker, mais c'est une commande, pas une action de l'agent lui-même).\n- **`effort` : PAS configurable par sous-agent, contrairement au modèle.** Sourcé sur une issue GitHub officielle (`anthropics/claude-code#25669`, feature request encore ouverte) : \"All subagents inherit the session default as there is no way to set the main agent to high and subagents to low.\" C'est un réglage de session, pas un paramètre de l'outil `Agent`/`Task` (vérifié directement : le schéma de cet outil dans cet environnement n'expose que `model`, aucun paramètre d'effort).\n\n## Conséquence pour Maxime\n\nMaxime (l'orchestrateur Claude) peut choisir lui-même le **modèle** d'un sous-agent qu'il délègue, informé par la taille de la tâche (S/M/L/XL) — capacité technique réelle, sans confirmation humaine requise à chaque appel. Il ne peut en revanche pas différencier l'**effort** par sous-agent : c'est un réglage de session, identique pour tous les agents de la conversation en cours, changé par un humain (menu effort de Claude Code, ou API `output_config.effort` en dehors de Claude Code).\n\n## Note annexe — \"ultracode\"\n\n\"ultracode\" apparaît dans le menu effort de Claude Code mais n'est pas un niveau d'effort API supplémentaire : ça combine `xhigh` avec une permission permanente de lancer des workflows multi-agents (mécanisme \"Mid-conversation system messages\"). Mentionné pour éviter de le confondre avec un 6e niveau d'effort — il n'y en a que 5 (`low`/`medium`/`high`/`xhigh`/`max`), tous documentés sur la page source `effort`.\n\n## Ce qui reste incertain\n\n- Le menu effort de Claude Code (accessible par un humain) n'a pas de commande/flag documenté officiellement pour être piloté par un script/agent plutôt qu'une interaction utilisateur directe — non vérifié plus loin, hors périmètre de cette fiche.\n" } diff --git a/active/engine-catalog/codex-models.json b/active/engine-catalog/codex-models.json index a391fc4..fa84d50 100644 --- a/active/engine-catalog/codex-models.json +++ b/active/engine-catalog/codex-models.json @@ -3,7 +3,12 @@ "type": "reference", "title": "Codex — moteurs (modèles) et effort, catalogue + qui décide", "theme": "engine-catalog", - "tags": ["codex", "models", "effort", "engine-catalog"], + "tags": [ + "codex", + "models", + "effort", + "engine-catalog" + ], "scope": "global", "status": "active", "confidence": "fact", @@ -15,6 +20,9 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "links": ["claude-code-models", "copilot-models"], + "links": [ + "claude-code-models", + "copilot-models" + ], "content": "# Codex — moteurs (modèles) et effort\n\n## Correction d'une hypothèse de recherche antérieure\n\nLa spec de travail précédente (2026-07-16, avant cette fiche) citait une source tierce non officielle (`codex.danielvaughan.com`, un blog) affirmant que Codex serait \"probablement auto-configurable via un fichier de config par agent\". **Vérifié sur source officielle OpenAI ce jour et infirmé** : `model` et `model_reasoning_effort` sont des réglages **globaux/de profil**, pas par agent ou sous-agent.\n\n## Ce qui est confirmé sur source officielle\n\n- **`model`** (ex. `gpt-5.5`) et **`model_reasoning_effort`** (`none`/`minimal`/`low`/`medium`/`high`/`xhigh` — `xhigh` dépend du modèle ; s'applique à la Responses API uniquement) sont définis dans `~/.codex/config.toml`, au niveau global de l'utilisateur.\n- **Profils** : des couches de configuration nommées, activées via `--profile nom-du-profil` en CLI, qui surchargent la config de base — un choix fait **avant le lancement**, par un humain (ou un script qui invoque la CLI), jamais pendant une session en cours.\n- **Aucune surcharge par agent, sous-agent, session ou requête individuelle n'est documentée** pour `model`/`model_reasoning_effort`. Une section `[agents]` existe bien dans `config.toml` pour configurer des **rôles** de sous-agents, mais rien dans la documentation officielle ne montre qu'elle couvre le modèle ou l'effort — elle configure autre chose (comportement/rôle, pas moteur).\n- **Aucun mécanisme documenté pour qu'une session Codex en cours change son propre modèle ou effort en cours de route** — fixé au lancement par la configuration.\n- Confirmation supplémentaire par l'absence : une issue GitHub officielle du dépôt `openai/codex`, encore ouverte, demande explicitement cette capacité (\"Allow configuring subagent model and reasoning_effort in config\", [#11795](https://github.com/openai/codex/issues/11795)) — la demande elle-même confirme que ça n'existe pas encore.\n\n## Conséquence pour Maxime\n\nTraiter Codex comme Copilot, pas comme Claude Code : Maxime ne peut pas configurer lui-même le modèle ou l'effort pour une tâche ou un sous-agent Codex. Il peut seulement **recommander** un modèle/effort informé par le catalogue et **demander** à l'utilisateur de le sélectionner (choix de profil ou flag `--model`/`--config model_reasoning_effort=...` avant le lancement). Repasser en mode \"auto-configurable comme Claude\" seulement si OpenAI documente officiellement une surcharge par agent/sous-agent dans une future version — revalider ce point avant de le considérer comme stable.\n\n## Ce qui reste incertain\n\n- Le contenu exact de la section `[agents]` (quels attributs de \"rôle\" elle couvre réellement) n'a pas été creusé en détail — hors périmètre de cette fiche, qui se limite à la question modèle/effort.\n" } diff --git a/active/engine-catalog/copilot-models.json b/active/engine-catalog/copilot-models.json index 7e660a3..fb568b5 100644 --- a/active/engine-catalog/copilot-models.json +++ b/active/engine-catalog/copilot-models.json @@ -3,7 +3,13 @@ "type": "reference", "title": "GitHub Copilot — moteurs (modèles) et effort, catalogue + qui décide (CLI/VS Code et cloud agent)", "theme": "engine-catalog", - "tags": ["copilot", "models", "effort", "cloud-agent", "engine-catalog"], + "tags": [ + "copilot", + "models", + "effort", + "cloud-agent", + "engine-catalog" + ], "scope": "global", "status": "active", "confidence": "fact", @@ -18,6 +24,9 @@ ], "validated": "2026-07-16", "created": "2026-07-16", - "links": ["claude-code-models", "codex-models"], + "links": [ + "claude-code-models", + "codex-models" + ], "content": "# GitHub Copilot — moteurs (modèles) et effort\n\nDeux surfaces distinctes chez Copilot, vérifiées séparément : les agents personnalisés CLI/VS Code (fichiers `.agent.md`) et le **cloud agent** (github.com — issues assignées, commentaires `@copilot`, agents tab). Conclusion identique sur le fond pour les deux : **jamais auto-configurable par l'agent lui-même**, mais les mécanismes diffèrent.\n\n## CLI / VS Code (agents personnalisés `.agent.md`)\n\n- **`model` : fixé par un humain à l'écriture du fichier, jamais changé par l'agent en cours d'exécution.** Le frontmatter `model:` d'un agent personnalisé contrôle le modèle utilisé (VS Code, JetBrains, Eclipse, Xcode). Un `model` passé programmatiquement à un appel `task()` est **silencieusement ramené au modèle de session par défaut** — confirmé par une issue GitHub officielle du dépôt `github/copilot-cli` encore ouverte ([#2758](https://github.com/github/copilot-cli/issues/2758), présentée comme un garde-fou de coût intentionnel, pas un bug).\n- **`effort` : n'existe pas dans le frontmatter d'agent personnalisé aujourd'hui.** Feature request encore ouverte ([#2904](https://github.com/github/copilot-cli/issues/2904), \"Custom Agent YAML Frontmatter Should Support Reasoning Effort\") — pas de mécanisme équivalent au `effort`/`model_reasoning_effort` de Claude ou Codex côté Copilot à ce jour. Seul un humain change le modèle, via `/model` ou le picker VS Code ; il n'y a rien d'équivalent à changer pour l'effort.\n\n## Cloud agent (github.com)\n\n- **`model` : sélection humaine uniquement, confirmée explicitement.** \"Only human users select the model. The agent does not programmatically choose or change its model during a task.\" Disponible aux points d'entrée supportés : assignation d'issue, mention `@copilot` en commentaire de PR, agents tab/panel, GitHub Mobile, lanceur Raycast. Modèles proposés (2026) : Claude Opus 4.5/4.6, Claude Sonnet 4.5/4.6, Claude Haiku 4.5, GPT-5.1-Codex-Max, GPT-5.2/5.3-Codex, GPT-5.4-mini.\n- **Option \"Auto\" : une troisième voie, ni humaine au cas par cas, ni agent.** Si l'utilisateur sélectionne \"Auto\" dans le picker (choix humain fait une fois, avant la tâche), la plateforme elle-même choisit ensuite le modèle \"based on system health and model performance\" — routage de plateforme, pas une décision de l'agent en cours de tâche. Avantage : remise de 10% sur le multiplicateur, exempté des limites de débit hebdomadaires.\n- **`effort` : aucune mention dans la documentation officielle du cloud agent.** Pas de sélecteur d'effort trouvé pour cette surface.\n\n## Conséquence pour Maxime\n\nSur les trois surfaces Copilot (CLI, VS Code, cloud agent), Maxime ne peut ni choisir ni faire varier le modèle ou l'effort par lui-même : il peut seulement **recommander** un choix informé par le catalogue et **demander** à l'utilisateur de le faire (via `/model`, le picker VS Code, ou le picker du cloud agent) — contrainte de plateforme, pas un choix de conception mA.xI.me.\n\n## Ce qui reste incertain\n\n- Aucune source officielle ne documente un sélecteur d'effort pour le cloud agent — absence constatée dans les pages consultées, pas une confirmation qu'il n'existe nulle part sur la plateforme.\n" } diff --git a/active/governance/sailpoint-identityiq.json b/active/governance/sailpoint-identityiq.json index 29442e0..1431adc 100644 --- a/active/governance/sailpoint-identityiq.json +++ b/active/governance/sailpoint-identityiq.json @@ -25,5 +25,5 @@ "links": [ "servicenow-itsm-change-management" ], - "content": "# SailPoint IdentityIQ (IIQ)\n\nPlateforme IGA (Identity Governance and Administration). Rôle générique : gérer le cycle de vie complet des demandes d'accès — de la demande à l'approbation puis au provisioning — avec un contrôle de politique et une trace d'audit à chaque étape.\n\n## Flux de demande d'accès type\n\nUn utilisateur (ou son manager) demande un accès (rôle, entitlement, groupe) → IdentityIQ vérifie la demande contre les politiques de séparation des tâches (SoD — Segregation/Separation of Duties) et autres règles → la demande est routée vers le ou les approbateurs pertinents → une fois approuvée, l'accès est provisionné automatiquement. Chaque étape est journalisée — c'est la trace d'audit sur laquelle s'appuient les équipes conformité.\n\n## Chemins d'approbation configurables\n\nPour un entitlement/access profile : approbation par le owner de l'access profile, le owner de l'application, le owner de la source, le manager du demandeur, ou un groupe de gouvernance dédié.\nPour un rôle : mêmes options (owner du rôle, manager, groupe de gouvernance).\nDes chemins d'approbation dynamiques peuvent varier selon le type d'accès demandé, le rôle du demandeur, et un niveau de risque calculé — les demandes à haut risque déclenchent une revue plus stricte, les demandes à faible risque peuvent être accélérées.\n\n## Gouvernance des rôles (Role Lifecycle)\n\nIdentityIQ gère le cycle de vie complet d'un rôle : création/modification via le Role Editor, avec possibilité de déclencher un workflow d'approbation avant qu'un changement de rôle ne soit promu en production. Pertinent pour la gouvernance de l'appartenance à un groupe AD sensible (ex. groupe Tier 0/Control Plane) : la double approbation pour rejoindre un tel groupe s'appuie typiquement sur ce mécanisme.\n\n## API REST\n\nIdentityIQ expose une API REST pour les demandes d'accès et leurs approbations (`access-request-approvals`). Pertinent pour toute vérification API-à-API future entre un système consommateur et IIQ, plutôt qu'une simple confiance déclarative dans un jeton émis." + "content": "# SailPoint IdentityIQ (IIQ)\n\nPlateforme IGA (Identity Governance and Administration). Rôle générique : gérer le cycle de vie complet des demandes d'accès — de la demande à l'approbation puis au provisioning — avec un contrôle de politique et une trace d'audit à chaque étape.\n\n## Flux de demande d'accès type\n\nUn utilisateur (ou son manager) demande un accès (rôle, entitlement, groupe) → IdentityIQ vérifie la demande contre les politiques de séparation des tâches (SoD — Segregation/Separation of Duties) et autres règles → la demande est routée vers le ou les approbateurs pertinents → une fois approuvée, l'accès est provisionné automatiquement. Chaque étape est journalisée — c'est la trace d'audit sur laquelle s'appuient les équipes conformité.\n\n## Chemins d'approbation configurables\n\nPour un entitlement/access profile : approbation par le owner de l'access profile, le owner de l'application, le owner de la source, le manager du demandeur, ou un groupe de gouvernance dédié.\nPour un rôle : mêmes options (owner du rôle, manager, groupe de gouvernance).\nDes chemins d'approbation dynamiques peuvent varier selon le type d'accès demandé, le rôle du demandeur, et un niveau de risque calculé — les demandes à haut risque déclenchent une revue plus stricte, les demandes à faible risque peuvent être accélérées.\n\n## Gouvernance des rôles (Role Lifecycle)\n\nIdentityIQ gère le cycle de vie complet d'un rôle : création/modification via le Role Editor, avec possibilité de déclencher un workflow d'approbation avant qu'un changement de rôle ne soit promu en production. Pertinent pour la gouvernance de l'appartenance à un groupe AD sensible (ex. groupe Tier 0/Control Plane) : la double approbation pour rejoindre un tel groupe s'appuie typiquement sur ce mécanisme.\n\n## API REST\n\nIdentityIQ expose une API REST pour les demandes d'accès et leurs approbations (`access-request-approvals`). Pertinent pour toute vérification API-à-API future entre un système consommateur et IIQ, plutôt qu'une simple confiance déclarative dans un jeton émis.\n" } diff --git a/active/governance/servicenow-itsm-change-management.json b/active/governance/servicenow-itsm-change-management.json index 1330b6e..a46e68f 100644 --- a/active/governance/servicenow-itsm-change-management.json +++ b/active/governance/servicenow-itsm-change-management.json @@ -24,5 +24,5 @@ "links": [ "sailpoint-identityiq" ], - "content": "# ServiceNow — ITSM Change Management\n\nOutil ITSM (IT Service Management), suit les pratiques ITIL. Rôle générique pertinent ici : gérer un ticket (change request) à travers un cycle de vie standardisé, avec approbation avant exécution — utilisable comme preuve d'autorisation pour des flux qui n'exigent pas une gouvernance IGA complète (voir IIQ) mais où une trace de validation formelle reste requise.\n\n## Types de demande de changement\n\nTrois catégories, chacune avec son propre niveau de revue et d'évaluation du risque :\n- **Standard** — changement pré-approuvé, à faible risque, répétitif\n- **Normal** — passe par le cycle de revue complet\n- **Emergency** — changement urgent, cycle de revue accéléré mais toujours tracé\n\n## Étapes du workflow d'approbation type\n\n1. **Évaluation initiale** — le Change Coordinator évalue la demande et la soumet à l'approbation du manager\n2. **Approbation manager** — approuve (la demande passe au CAB) ou rejette\n3. **Revue CAB** (Change Advisory Board) — approuve, ou propose des modifications\n4. **Implémentation** — un changement ne peut pas passer en implémentation tant que toutes les approbations requises ne sont pas obtenues\n\nRôles impliqués : Change Owner, Change Manager, Change Initiator, membres du CAB, équipes techniques.\n\n## Pertinence pour un modèle d'autorisation\n\nUn ticket ServiceNow correctement approuvé peut servir de preuve d'autorisation suffisante pour des flux à risque modéré, sans exiger le passage par un outil de gouvernance IGA complet (IIQ) à chaque appel — utile pour distinguer les cas où une gouvernance humaine légère suffit de ceux qui exigent le cycle complet." + "content": "# ServiceNow — ITSM Change Management\n\nOutil ITSM (IT Service Management), suit les pratiques ITIL. Rôle générique pertinent ici : gérer un ticket (change request) à travers un cycle de vie standardisé, avec approbation avant exécution — utilisable comme preuve d'autorisation pour des flux qui n'exigent pas une gouvernance IGA complète (voir IIQ) mais où une trace de validation formelle reste requise.\n\n## Types de demande de changement\n\nTrois catégories, chacune avec son propre niveau de revue et d'évaluation du risque :\n- **Standard** — changement pré-approuvé, à faible risque, répétitif\n- **Normal** — passe par le cycle de revue complet\n- **Emergency** — changement urgent, cycle de revue accéléré mais toujours tracé\n\n## Étapes du workflow d'approbation type\n\n1. **Évaluation initiale** — le Change Coordinator évalue la demande et la soumet à l'approbation du manager\n2. **Approbation manager** — approuve (la demande passe au CAB) ou rejette\n3. **Revue CAB** (Change Advisory Board) — approuve, ou propose des modifications\n4. **Implémentation** — un changement ne peut pas passer en implémentation tant que toutes les approbations requises ne sont pas obtenues\n\nRôles impliqués : Change Owner, Change Manager, Change Initiator, membres du CAB, équipes techniques.\n\n## Pertinence pour un modèle d'autorisation\n\nUn ticket ServiceNow correctement approuvé peut servir de preuve d'autorisation suffisante pour des flux à risque modéré, sans exiger le passage par un outil de gouvernance IGA complet (IIQ) à chaque appel — utile pour distinguer les cas où une gouvernance humaine légère suffit de ceux qui exigent le cycle complet.\n" } diff --git a/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json b/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json index 0a0e62b..c6de60c 100644 --- a/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json +++ b/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json @@ -39,5 +39,5 @@ "ad-ds-security-control-assurance-levels", "ad-ds-threat-driven-control-map" ], - "content": "# Statut de cette fiche : référence historique/comparative — PAS le modèle cible\n\nCette fiche indexe l'implémentation open-source de Microsoft du **Tier Model AD DS classique** (`microsoft/ActiveDirectoryTierModel` sur GitHub, doc publiée à https://microsoft.github.io/ActiveDirectoryTierModel/). Elle documente *comment Microsoft outille et déploie* le tiering Tier 0/1/2 en PowerShell.\n\n**Elle ne remplace ni ne prime sur les fiches EAM existantes** (`enterprise-access-model`, `zero-standing-access`, `security-framework-role-and-crosswalk`) ni sur le modèle de tiering appliqué dans ce repo (`ad-ds-tiered-administration-hardening`, `ad-ds-gpo-acl-lifecycle-governance`, `ad-ds-threat-driven-control-map`, `ad-ds-security-control-assurance-levels`). Le Tier Model classique est le **prédécesseur** de l'Enterprise Access Model (voir `enterprise-access-model`) — Microsoft continue de documenter et outiller le premier pour les organisations qui n'ont pas encore migré vers le second, pas comme direction recommandée future.\n\n**Usage prévu** : comparer une méthodologie d'outillage (déploiement idempotent, drift detection, structure de GPO, architecture de cmdlets) à ce qui existe déjà dans ce repo — pas y piocher un modèle de classification ou de gouvernance cible.\n\n# 1. Méthodologie de déploiement (`deployment-methodology`)\n\n- Approche **séquentielle et dépendante** en 10 phases, alignée sur un plan d'autorité (`plan.md`) pour satisfaire les dépendances et permettre la convergence : OUs → Groupes → Utilisateurs → délégations ACL → GPO (import/création/liaison) → templates ADMX → délégations optionnelles MSA/gMSA/dMSA/Windows LAPS.\n- **Validation en couches** : pré-déploiement (schéma JSON, connectivité, permissions, dépendances), post-déploiement (création d'objets, application des ACL, liens GPO, comptage de fichiers), audit continu (rapports avec opérations ignorées documentées).\n- **Idempotence** par \"skip-rather-than-fail\" : un objet existant déclenche un message INFO et n'est pas recréé — sauf les templates ADMX, toujours écrasés pour supporter les mises à jour. Les délégations sont vérifiées par présence du groupe de délégation dans le security descriptor de l'OU (pas de comparaison ACE par ACE). Support WhatIf/ShouldProcess pour dry-run.\n- **Décision de conception notable** : la validation ne teste pas le contenu détaillé des GPO (User Rights Assignments, Restricted Groups, valeurs de registre) — seulement l'intégrité structurelle, car ces réglages \"sont complexes et peuvent changer post-déploiement\".\n- Aucune correction automatique de l'ordre de liaison des GPO en cas de désalignement — intervention manuelle requise, pour éviter de casser accidentellement une séquence d'application de policy.\n- Philosophie de rollback conservatrice : la plupart des objets sont conservés tels quels post-déploiement (les OU contiennent des enfants, les groupes peuvent avoir des membres ajoutés manuellement, etc.) — priorité à la stabilité et à la préservation des personnalisations locales plutôt qu'à un contrôle centralisé total.\n\n# 2. Drift detection (`drift-detection-details`)\n\n- Script `Audit-TierModel.ps1`, **lecture seule** (ne modifie jamais l'état), qui compare l'état AD réel à la configuration déclarée.\n- Cmdlets modulaires `Test-TierModel*` par composant : `Test-TierModelOu`, `Test-TierModelGroup`, `Test-TierModelUser`, `Test-TierModelGpo`, `Test-TierModelGPOLink`, `Test-TierModelOuAcl`, `Test-TierModelAdmx` (hash MD5). Flags optionnels `-IncludeMsa`, `-IncludeGmsa`, `-IncludeDmsa`, `-IncludeWinLaps`.\n- Constats catégorisés : `Missing`, `Mismatch`, `ExtraProtection`, `HashMismatch` — chacun avec type de ressource, identifiant, état attendu vs réel, sévérité.\n- Sorties JSON (automatisation), HTML (parties prenantes), NUnit XML (intégration CI/CD).\n- Boucle de remédiation : audit → revue des constats → plan correctif → `Deploy-TierModel.ps1` ciblé → nouvel audit pour confirmer la fermeture de l'écart.\n- Export JSON horodaté permettant le suivi de conformité dans le temps ; intégration CI/CD (GitHub Actions, Azure DevOps) pour audits automatisés quotidiens ou déclenchés par événement.\n\n# 3. GPO management strategy (`gpo-management-strategy`)\n\n- Approche **à deux niveaux par OU** : `ImportOnlyGpo` (GPO créées depuis un template sans configuration post-déploiement, modes `create` / `createAndImport` / setup manuel) et `PostConfigureGpo` (GPO nécessitant une configuration dynamique des User Rights Assignments et Restricted Groups après import).\n- Trois modes de déploiement : `create` (GPO vide), `createAndImport` (import de baseline/template Microsoft), `createImportAndConfigure` (import + configuration dynamique URA/RG).\n- Configuration pilotée par JSON : liaison dynamique de principals (groupes résolvables, assignation forest-root-only, inclusion conditionnelle selon l'existence d'un groupe, comptes de service en dur), contrôle des groupes locaux (Restricted Groups) via SID, security filtering via `denyApplyGroupPolicy`. Dédoublonnage des SID avant génération des blocs ; ordre déterministe suivant la définition JSON.\n- Optimisation : propriété `gpoStatus` désactivant les sections de traitement inutilisées (ex. `UserSettingsDisabled` pour les policies machine uniquement) ; logique conditionnelle adaptant la configuration entre forest root et domaines enfants.\n\n# 4. Cmdlet architecture (`cmdlet-architecture`)\n\n- Séparation stricte de deux modes pour éviter les conflits de validation :\n - **Phase-Specific** : validation \"fail fast\", suppose que les prérequis existent déjà (déploiement incrémental piloté manuellement phase par phase).\n - **Full Deployment** : validation plus légère, suppose que les dépendances seront créées dans le bon ordre pendant une exécution automatisée complète.\n- Pattern : duplication des cmdlets `Get-TierModel*` existants en variantes \"Fd\" (Full Deployment) plutôt que modification des cmdlets phase-specific — ex. `Get-TierModelGroup` → `Get-TierModelGroupFd`. Les cmdlets phase-specific restent inchangés et stables, ce qui permet un test indépendant de chaque mode sans risque de régression.\n- Les phases optionnelles (MSA/gMSA/dMSA/Windows LAPS) suivent le même pattern avec des jeux de cmdlets Get/New/Test parallèles pour planification, application et audit.\n\n# Ce que cette fiche n'est pas\n\n- Pas un modèle de classification de sensibilité (→ voir `enterprise-access-model` pour les control/management/data-workload planes).\n- Pas la référence de durcissement appliquée dans ce repo (→ voir `ad-ds-tiered-administration-hardening`, `ad-ds-gpo-acl-lifecycle-governance`, `ad-ds-threat-driven-control-map`, `ad-ds-security-control-assurance-levels`).\n- Pas une recommandation de migrer vers ce tooling précis — c'est un point de comparaison pour évaluer/valider des choix de conception (idempotence, drift detection, structure GPO, séparation phase-specific/full-deployment) déjà pris ou à prendre ailleurs dans ce repo." + "content": "# Statut de cette fiche : référence historique/comparative — PAS le modèle cible\n\nCette fiche indexe l'implémentation open-source de Microsoft du **Tier Model AD DS classique** (`microsoft/ActiveDirectoryTierModel` sur GitHub, doc publiée à https://microsoft.github.io/ActiveDirectoryTierModel/). Elle documente *comment Microsoft outille et déploie* le tiering Tier 0/1/2 en PowerShell.\n\n**Elle ne remplace ni ne prime sur les fiches EAM existantes** (`enterprise-access-model`, `zero-standing-access`, `security-framework-role-and-crosswalk`) ni sur le modèle de tiering appliqué dans ce repo (`ad-ds-tiered-administration-hardening`, `ad-ds-gpo-acl-lifecycle-governance`, `ad-ds-threat-driven-control-map`, `ad-ds-security-control-assurance-levels`). Le Tier Model classique est le **prédécesseur** de l'Enterprise Access Model (voir `enterprise-access-model`) — Microsoft continue de documenter et outiller le premier pour les organisations qui n'ont pas encore migré vers le second, pas comme direction recommandée future.\n\n**Usage prévu** : comparer une méthodologie d'outillage (déploiement idempotent, drift detection, structure de GPO, architecture de cmdlets) à ce qui existe déjà dans ce repo — pas y piocher un modèle de classification ou de gouvernance cible.\n\n# 1. Méthodologie de déploiement (`deployment-methodology`)\n\n- Approche **séquentielle et dépendante** en 10 phases, alignée sur un plan d'autorité (`plan.md`) pour satisfaire les dépendances et permettre la convergence : OUs → Groupes → Utilisateurs → délégations ACL → GPO (import/création/liaison) → templates ADMX → délégations optionnelles MSA/gMSA/dMSA/Windows LAPS.\n- **Validation en couches** : pré-déploiement (schéma JSON, connectivité, permissions, dépendances), post-déploiement (création d'objets, application des ACL, liens GPO, comptage de fichiers), audit continu (rapports avec opérations ignorées documentées).\n- **Idempotence** par \"skip-rather-than-fail\" : un objet existant déclenche un message INFO et n'est pas recréé — sauf les templates ADMX, toujours écrasés pour supporter les mises à jour. Les délégations sont vérifiées par présence du groupe de délégation dans le security descriptor de l'OU (pas de comparaison ACE par ACE). Support WhatIf/ShouldProcess pour dry-run.\n- **Décision de conception notable** : la validation ne teste pas le contenu détaillé des GPO (User Rights Assignments, Restricted Groups, valeurs de registre) — seulement l'intégrité structurelle, car ces réglages \"sont complexes et peuvent changer post-déploiement\".\n- Aucune correction automatique de l'ordre de liaison des GPO en cas de désalignement — intervention manuelle requise, pour éviter de casser accidentellement une séquence d'application de policy.\n- Philosophie de rollback conservatrice : la plupart des objets sont conservés tels quels post-déploiement (les OU contiennent des enfants, les groupes peuvent avoir des membres ajoutés manuellement, etc.) — priorité à la stabilité et à la préservation des personnalisations locales plutôt qu'à un contrôle centralisé total.\n\n# 2. Drift detection (`drift-detection-details`)\n\n- Script `Audit-TierModel.ps1`, **lecture seule** (ne modifie jamais l'état), qui compare l'état AD réel à la configuration déclarée.\n- Cmdlets modulaires `Test-TierModel*` par composant : `Test-TierModelOu`, `Test-TierModelGroup`, `Test-TierModelUser`, `Test-TierModelGpo`, `Test-TierModelGPOLink`, `Test-TierModelOuAcl`, `Test-TierModelAdmx` (hash MD5). Flags optionnels `-IncludeMsa`, `-IncludeGmsa`, `-IncludeDmsa`, `-IncludeWinLaps`.\n- Constats catégorisés : `Missing`, `Mismatch`, `ExtraProtection`, `HashMismatch` — chacun avec type de ressource, identifiant, état attendu vs réel, sévérité.\n- Sorties JSON (automatisation), HTML (parties prenantes), NUnit XML (intégration CI/CD).\n- Boucle de remédiation : audit → revue des constats → plan correctif → `Deploy-TierModel.ps1` ciblé → nouvel audit pour confirmer la fermeture de l'écart.\n- Export JSON horodaté permettant le suivi de conformité dans le temps ; intégration CI/CD (GitHub Actions, Azure DevOps) pour audits automatisés quotidiens ou déclenchés par événement.\n\n# 3. GPO management strategy (`gpo-management-strategy`)\n\n- Approche **à deux niveaux par OU** : `ImportOnlyGpo` (GPO créées depuis un template sans configuration post-déploiement, modes `create` / `createAndImport` / setup manuel) et `PostConfigureGpo` (GPO nécessitant une configuration dynamique des User Rights Assignments et Restricted Groups après import).\n- Trois modes de déploiement : `create` (GPO vide), `createAndImport` (import de baseline/template Microsoft), `createImportAndConfigure` (import + configuration dynamique URA/RG).\n- Configuration pilotée par JSON : liaison dynamique de principals (groupes résolvables, assignation forest-root-only, inclusion conditionnelle selon l'existence d'un groupe, comptes de service en dur), contrôle des groupes locaux (Restricted Groups) via SID, security filtering via `denyApplyGroupPolicy`. Dédoublonnage des SID avant génération des blocs ; ordre déterministe suivant la définition JSON.\n- Optimisation : propriété `gpoStatus` désactivant les sections de traitement inutilisées (ex. `UserSettingsDisabled` pour les policies machine uniquement) ; logique conditionnelle adaptant la configuration entre forest root et domaines enfants.\n\n# 4. Cmdlet architecture (`cmdlet-architecture`)\n\n- Séparation stricte de deux modes pour éviter les conflits de validation :\n - **Phase-Specific** : validation \"fail fast\", suppose que les prérequis existent déjà (déploiement incrémental piloté manuellement phase par phase).\n - **Full Deployment** : validation plus légère, suppose que les dépendances seront créées dans le bon ordre pendant une exécution automatisée complète.\n- Pattern : duplication des cmdlets `Get-TierModel*` existants en variantes \"Fd\" (Full Deployment) plutôt que modification des cmdlets phase-specific — ex. `Get-TierModelGroup` → `Get-TierModelGroupFd`. Les cmdlets phase-specific restent inchangés et stables, ce qui permet un test indépendant de chaque mode sans risque de régression.\n- Les phases optionnelles (MSA/gMSA/dMSA/Windows LAPS) suivent le même pattern avec des jeux de cmdlets Get/New/Test parallèles pour planification, application et audit.\n\n# Ce que cette fiche n'est pas\n\n- Pas un modèle de classification de sensibilité (→ voir `enterprise-access-model` pour les control/management/data-workload planes).\n- Pas la référence de durcissement appliquée dans ce repo (→ voir `ad-ds-tiered-administration-hardening`, `ad-ds-gpo-acl-lifecycle-governance`, `ad-ds-threat-driven-control-map`, `ad-ds-security-control-assurance-levels`).\n- Pas une recommandation de migrer vers ce tooling précis — c'est un point de comparaison pour évaluer/valider des choix de conception (idempotence, drift detection, structure GPO, séparation phase-specific/full-deployment) déjà pris ou à prendre ailleurs dans ce repo.\n" } diff --git a/active/security-architecture/enterprise-access-model.json b/active/security-architecture/enterprise-access-model.json index e754050..31368e4 100644 --- a/active/security-architecture/enterprise-access-model.json +++ b/active/security-architecture/enterprise-access-model.json @@ -23,5 +23,5 @@ "links": [ "zero-standing-access" ], - "content": "# Enterprise Access Model (EAM)\n\nSuccesseur du modèle de tiering AD classique (Tier 0/1/2). Remplace la hiérarchie linéaire par trois **plans de sensibilité**. Un plan décrit *où vit un actif et à quel niveau de sensibilité*, pas *comment on y accède* — c'est un axe distinct du chemin d'accès/gouvernance (voir la nuance dans les décisions spécifiques à chaque projet, pas dans cette fiche générique).\n\n## Les trois plans\n\n| Plan | Contenu | Exemple |\n|---|---|---|\n| **Control Plane** | Les systèmes qui contrôlent l'identité et la sécurité elles-mêmes — équivaut à l'ancien Tier 0 | Domain Admins, Enterprise Admins, Schema Admins, structure des ACL, systèmes d'identité centralisés |\n| **Management Plane** | Fonctions de gestion IT à l'échelle de l'entreprise — gouverne les workloads et l'infrastructure qui les héberge | Outils de gouvernance/gestion (IIQ, ServiceNow, PAM), gestion d'infrastructure on-prem/cloud |\n| **Data/Workload Plane** | Les applications et données — l'essentiel de la valeur métier à protéger | Applications métier, services applicatifs, bases de données, données métier |\n\n## Principe clé\n\n**Enforce hierarchy** — empêcher qu'un plan de niveau supérieur (plus sensible) soit contrôlé depuis un plan inférieur, que ce soit par attaque ou par abus d'un processus légitime. Le Data/Workload plane est gouverné par le Management plane, qui est lui-même protégé par le Control plane — jamais l'inverse.\n\n## Erreur fréquente à éviter\n\nNe pas faire correspondre les plans 1-pour-1 avec des \"chemins d'accès techniques\" (ex. compte utilisateur / compte applicatif / compte privilégié). Le nombre de chemins d'accès techniques qu'une organisation choisit d'implémenter est une décision d'architecture propre à chaque système — pas une conséquence mécanique du nombre de plans EAM.\n\n## Cas particulier : objets d'un système d'identité (ex. Active Directory)\n\nUn système d'identité (AD DS et équivalents) est lui-même structurellement adjacent au Control Plane, quel que soit le type d'objet qu'il contient — administrer un objet, même un compte utilisateur ordinaire, n'est pas une opération Data/Workload (qui désigne la donnée métier/applicative, pas l'infrastructure d'identité qui la protège). Ne pas classer les comptes utilisateurs/de service/groupes comme des exemples de Data/Workload. La classification correcte pour ce type d'objet passe par une cascade de tier (Tier 0/1/2, avec défaut fail-secure sur Tier 0 en cas d'ambiguïté) combinée à la capacité de contrôle exercée par le geste — voir la fiche `zero-standing-access` et, pour un modèle complet appliqué à AD DS, la documentation du projet consommateur concerné (ex. `ad-ds-governance-model.md` dans coreapi)." + "content": "# Enterprise Access Model (EAM)\n\nSuccesseur du modèle de tiering AD classique (Tier 0/1/2). Remplace la hiérarchie linéaire par trois **plans de sensibilité**. Un plan décrit *où vit un actif et à quel niveau de sensibilité*, pas *comment on y accède* — c'est un axe distinct du chemin d'accès/gouvernance (voir la nuance dans les décisions spécifiques à chaque projet, pas dans cette fiche générique).\n\n## Les trois plans\n\n| Plan | Contenu | Exemple |\n|---|---|---|\n| **Control Plane** | Les systèmes qui contrôlent l'identité et la sécurité elles-mêmes — équivaut à l'ancien Tier 0 | Domain Admins, Enterprise Admins, Schema Admins, structure des ACL, systèmes d'identité centralisés |\n| **Management Plane** | Fonctions de gestion IT à l'échelle de l'entreprise — gouverne les workloads et l'infrastructure qui les héberge | Outils de gouvernance/gestion (IIQ, ServiceNow, PAM), gestion d'infrastructure on-prem/cloud |\n| **Data/Workload Plane** | Les applications et données — l'essentiel de la valeur métier à protéger | Applications métier, services applicatifs, bases de données, données métier |\n\n## Principe clé\n\n**Enforce hierarchy** — empêcher qu'un plan de niveau supérieur (plus sensible) soit contrôlé depuis un plan inférieur, que ce soit par attaque ou par abus d'un processus légitime. Le Data/Workload plane est gouverné par le Management plane, qui est lui-même protégé par le Control plane — jamais l'inverse.\n\n## Erreur fréquente à éviter\n\nNe pas faire correspondre les plans 1-pour-1 avec des \"chemins d'accès techniques\" (ex. compte utilisateur / compte applicatif / compte privilégié). Le nombre de chemins d'accès techniques qu'une organisation choisit d'implémenter est une décision d'architecture propre à chaque système — pas une conséquence mécanique du nombre de plans EAM.\n\n## Cas particulier : objets d'un système d'identité (ex. Active Directory)\n\nUn système d'identité (AD DS et équivalents) est lui-même structurellement adjacent au Control Plane, quel que soit le type d'objet qu'il contient — administrer un objet, même un compte utilisateur ordinaire, n'est pas une opération Data/Workload (qui désigne la donnée métier/applicative, pas l'infrastructure d'identité qui la protège). Ne pas classer les comptes utilisateurs/de service/groupes comme des exemples de Data/Workload. La classification correcte pour ce type d'objet passe par une cascade de tier (Tier 0/1/2, avec défaut fail-secure sur Tier 0 en cas d'ambiguïté) combinée à la capacité de contrôle exercée par le geste — voir la fiche `zero-standing-access` et, pour un modèle complet appliqué à AD DS, la documentation du projet consommateur concerné (ex. `ad-ds-governance-model.md` dans coreapi).\n" } diff --git a/active/security-architecture/zero-standing-access.json b/active/security-architecture/zero-standing-access.json index a8ed2d9..d6b6b69 100644 --- a/active/security-architecture/zero-standing-access.json +++ b/active/security-architecture/zero-standing-access.json @@ -23,5 +23,5 @@ "links": [ "enterprise-access-model" ], - "content": "# Zero standing access, secretless, gMSA\n\nTrois principes distincts, souvent combinés, à ne pas confondre.\n\n## Zero standing access (zero standing privilege)\n\nUn compte ne détient **aucun privilège actif en permanence** — le privilège est accordé (élévation, activation, bail temporaire) seulement pour la fenêtre d'usage, puis retiré. Différent de \"least privilege\" (qui limite la *portée* du privilège) : zero standing access limite la *durée*. Typiquement implémenté via un système PAM externe (ex. HashiCorp Vault, CyberArk) qui orchestre l'activation/désactivation ou la rotation JIT (just-in-time) d'un credential.\n\n## Secretless\n\nDirection architecturale : éliminer la manipulation de secrets statiques (mots de passe en clair, clés API en dur) par le code applicatif. Concrètement pour l'authentification Windows/AD : préférer un mécanisme qui produit un **ticket Kerberos** (via délégation, gMSA + `credentials-fetcher`, etc.) plutôt qu'un bind LDAP avec `AuthType.Basic` et un mot de passe explicite. Le processus applicatif ne voit jamais le secret sous-jacent.\n\n## gMSA (Group Managed Service Account)\n\nType de compte de service AD dont le mot de passe est **généré et tourné automatiquement par AD** (~30 jours par défaut), jamais connu d'un humain ni stocké en dur par une application. Un gMSA seul règle \"pas de mot de passe statique connu\" mais **pas** zero standing access : le compte reste activé et utilisable en continu entre deux rotations. Pour obtenir zero standing access, combiner le gMSA avec une couche JIT supplémentaire (ex. compte désactivé par défaut, activé seulement pour la fenêtre d'usage via un système externe) — les deux mécanismes sont complémentaires, pas substituables l'un à l'autre.\n\nSur AWS ECS/Fargate (conteneurs Linux uniquement, mode domainless — voir la fiche `ecs-fargate-task-isolation`), le daemon `credentials-fetcher` récupère le mot de passe géré du gMSA (`msDS-ManagedPassword`) via LDAPS et produit un ticket Kerberos mis à disposition du conteneur — le conteneur applicatif ne manipule jamais ce mot de passe. Nuance importante : `credentials-fetcher` lui-même s'appuie sur un identifiant AD statique stocké dans AWS Secrets Manager pour s'authentifier et effectuer cette récupération — ce credential de bootstrap est permanent (protégé par IAM, pas par une rotation JIT), donc la chaîne complète n'est secretless que du point de vue du conteneur applicatif, pas de bout en bout." + "content": "# Zero standing access, secretless, gMSA\n\nTrois principes distincts, souvent combinés, à ne pas confondre.\n\n## Zero standing access (zero standing privilege)\n\nUn compte ne détient **aucun privilège actif en permanence** — le privilège est accordé (élévation, activation, bail temporaire) seulement pour la fenêtre d'usage, puis retiré. Différent de \"least privilege\" (qui limite la *portée* du privilège) : zero standing access limite la *durée*. Typiquement implémenté via un système PAM externe (ex. HashiCorp Vault, CyberArk) qui orchestre l'activation/désactivation ou la rotation JIT (just-in-time) d'un credential.\n\n## Secretless\n\nDirection architecturale : éliminer la manipulation de secrets statiques (mots de passe en clair, clés API en dur) par le code applicatif. Concrètement pour l'authentification Windows/AD : préférer un mécanisme qui produit un **ticket Kerberos** (via délégation, gMSA + `credentials-fetcher`, etc.) plutôt qu'un bind LDAP avec `AuthType.Basic` et un mot de passe explicite. Le processus applicatif ne voit jamais le secret sous-jacent.\n\n## gMSA (Group Managed Service Account)\n\nType de compte de service AD dont le mot de passe est **généré et tourné automatiquement par AD** (~30 jours par défaut), jamais connu d'un humain ni stocké en dur par une application. Un gMSA seul règle \"pas de mot de passe statique connu\" mais **pas** zero standing access : le compte reste activé et utilisable en continu entre deux rotations. Pour obtenir zero standing access, combiner le gMSA avec une couche JIT supplémentaire (ex. compte désactivé par défaut, activé seulement pour la fenêtre d'usage via un système externe) — les deux mécanismes sont complémentaires, pas substituables l'un à l'autre.\n\nSur AWS ECS/Fargate (conteneurs Linux uniquement, mode domainless — voir la fiche `ecs-fargate-task-isolation`), le daemon `credentials-fetcher` récupère le mot de passe géré du gMSA (`msDS-ManagedPassword`) via LDAPS et produit un ticket Kerberos mis à disposition du conteneur — le conteneur applicatif ne manipule jamais ce mot de passe. Nuance importante : `credentials-fetcher` lui-même s'appuie sur un identifiant AD statique stocké dans AWS Secrets Manager pour s'authentifier et effectuer cette récupération — ce credential de bootstrap est permanent (protégé par IAM, pas par une rotation JIT), donc la chaîne complète n'est secretless que du point de vue du conteneur applicatif, pas de bout en bout.\n" } diff --git a/active/siem/splunk-cim-data-models.json b/active/siem/splunk-cim-data-models.json index c3b0976..b6eed42 100644 --- a/active/siem/splunk-cim-data-models.json +++ b/active/siem/splunk-cim-data-models.json @@ -23,5 +23,5 @@ "validated": "2026-07-18", "created": "2026-07-18", "links": [], - "content": "# Splunk Common Information Model (CIM) — Authentication et Change\n\n**Statut `suspect`/`hypothesis` dès la création** : récupéré via un outil de résumé automatique, `docs.splunk.com` retournait 403 sur un accès direct. La liste du modèle Change en particulier n'a pas confirmé explicitement le statut requis/recommandé par champ. À revalider contre l'add-on CIM réellement installé sur l'instance Splunk cible avant tout usage en production (fiche délibérément marquée à revalider tôt).\n\n## Pourquoi CIM\n\nAligner un log applicatif sur un modèle CIM existant permet aux détections et rapports de conformité déjà construits côté SOC (Splunk Enterprise Security) de reconnaître l'événement automatiquement, sans parsing custom.\n\n## Data model Authentication\n\nÉvénement de validation d'identité (login, validation de jeton).\n\n**Champs requis** : `action`, `app`, `user`, `src`, `dest`.\n\n**Champs recommandés** : `src_user`, `user_id`, `user_role`, `user_type`, `authentication_method`, `authentication_service`, `duration`, `process`, `reason_id`, `response_time`, `signature`, `signature_id`, `user_agent`, `user_bunit`, `user_category`, `user_priority`.\n\n## Data model Change\n\nÉvénement de type Create/Read/Update/Delete sur un objet quelconque — c'est le modèle naturel pour une API qui fait du CRUD sur des objets d'annuaire ou toute ressource administrée.\n\n**Champs observés** (statut requis/recommandé non confirmé) : `action`, `change_type`, `command`, `dest`, `dest_bunit`, `dest_category`, `dest_ip_range`, `dest_nt_domain`, `dest_port_range`, `dest_priority`, `direction`, `dvc`, `image_id`, `instance_type`, `object`, `object_attrs`, `object_category`, `object_id`, `object_path`, `result`, `status`, `user`, `vendor_product`.\n\nSémantique à retenir : dans ce modèle, `user` désigne **qui effectue l'action**, pas l'objet ciblé par l'action — la cible se décrit via `object`/`object_category`/`object_id`/`object_path`.\n\n## Champs d'enveloppe d'indexation Splunk (hors CIM)\n\nDistincts des champs de contenu CIM ci-dessus : `time`/`timestamp`, `host`, `source`, `sourcetype`, `index` — gérés à l'ingestion, pas dans le corps de l'événement applicatif." + "content": "# Splunk Common Information Model (CIM) — Authentication et Change\n\n**Statut `suspect`/`hypothesis` dès la création** : récupéré via un outil de résumé automatique, `docs.splunk.com` retournait 403 sur un accès direct. La liste du modèle Change en particulier n'a pas confirmé explicitement le statut requis/recommandé par champ. À revalider contre l'add-on CIM réellement installé sur l'instance Splunk cible avant tout usage en production (fiche délibérément marquée à revalider tôt).\n\n## Pourquoi CIM\n\nAligner un log applicatif sur un modèle CIM existant permet aux détections et rapports de conformité déjà construits côté SOC (Splunk Enterprise Security) de reconnaître l'événement automatiquement, sans parsing custom.\n\n## Data model Authentication\n\nÉvénement de validation d'identité (login, validation de jeton).\n\n**Champs requis** : `action`, `app`, `user`, `src`, `dest`.\n\n**Champs recommandés** : `src_user`, `user_id`, `user_role`, `user_type`, `authentication_method`, `authentication_service`, `duration`, `process`, `reason_id`, `response_time`, `signature`, `signature_id`, `user_agent`, `user_bunit`, `user_category`, `user_priority`.\n\n## Data model Change\n\nÉvénement de type Create/Read/Update/Delete sur un objet quelconque — c'est le modèle naturel pour une API qui fait du CRUD sur des objets d'annuaire ou toute ressource administrée.\n\n**Champs observés** (statut requis/recommandé non confirmé) : `action`, `change_type`, `command`, `dest`, `dest_bunit`, `dest_category`, `dest_ip_range`, `dest_nt_domain`, `dest_port_range`, `dest_priority`, `direction`, `dvc`, `image_id`, `instance_type`, `object`, `object_attrs`, `object_category`, `object_id`, `object_path`, `result`, `status`, `user`, `vendor_product`.\n\nSémantique à retenir : dans ce modèle, `user` désigne **qui effectue l'action**, pas l'objet ciblé par l'action — la cible se décrit via `object`/`object_category`/`object_id`/`object_path`.\n\n## Champs d'enveloppe d'indexation Splunk (hors CIM)\n\nDistincts des champs de contenu CIM ci-dessus : `time`/`timestamp`, `host`, `source`, `sourcetype`, `index` — gérés à l'ingestion, pas dans le corps de l'événement applicatif.\n" } diff --git a/active/vscode-copilot/copilot-instructions-merge.json b/active/vscode-copilot/copilot-instructions-merge.json index 0ee6537..2c49d50 100644 --- a/active/vscode-copilot/copilot-instructions-merge.json +++ b/active/vscode-copilot/copilot-instructions-merge.json @@ -3,14 +3,26 @@ "type": "reference", "title": "GitHub Copilot — fusion automatique de fichiers d'instructions multiples", "theme": "vscode-copilot", - "tags": ["copilot", "vscode", "instructions", "config-merge"], + "tags": [ + "copilot", + "vscode", + "instructions", + "config-merge" + ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", - "source": ["https://code.visualstudio.com/docs/agent-customization/custom-instructions", "https://github.com/orgs/community/discussions/170581"], + "source": [ + "https://code.visualstudio.com/docs/agent-customization/custom-instructions", + "https://github.com/orgs/community/discussions/170581" + ], "validated": "2026-07-16", "created": "2026-07-16", - "links": ["vscode-copilot-builtin-tools", "claude-md-import-mechanism", "codex-agents-md-nesting"], - "content": "# GitHub Copilot — fusion automatique de fichiers d'instructions multiples\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27.\n\n## Ce qui est confirmé (sourcé)\n\n- Mécanisme officiel et actuel : `.github/copilot-instructions.md` (toujours actif, portée repo entier) et `.github/instructions/*.instructions.md` (application conditionnelle via un glob `applyTo` ou correspondance sémantique) sont additifs, pas exclusifs — les deux se chargent ensemble en contexte. La doc VS Code le dit explicitement : \"If you have multiple instruction files in your project, VS Code combines and adds them to the chat context, no specific order is guaranteed.\" Source : https://code.visualstudio.com/docs/agent-customization/custom-instructions\n- La doc plus récente de Copilot CLI décrit une pile à 5 niveaux (personnel → instructions scopées par chemin → copilot-instructions.md repo entier → AGENTS.md → organisation) qui fusionnent tous, les niveaux supérieurs ne l'emportant qu'en cas de conflit direct.\n- Aucune syntaxe d'inclusion à l'intérieur d'un seul fichier d'instructions — mais des liens Markdown entre fichiers d'instructions sont une convention de référence croisée douce (ex. \"Applique ces conventions\"), pas une vraie fusion/inclusion.\n- Confusion réelle constatée dans la communauté : la discussion GitHub #170581 (org community) montre des utilisateurs ayant mal lu la formulation de la doc (\"either... or...\") comme mutuellement exclusive, alors que les deux types de fichiers se combinent réellement — clarifié par la communauté, pas encore par une réécriture de la doc officielle trouvée.\n\n## Incertitudes explicites\n\n- \"Aucun ordre spécifique garanti\" est un vrai risque pour notre cas d'usage si le fichier généré et le fichier écrit à la main donnent un jour des instructions contradictoires — impossible de forcer la victoire du fichier écrit à la main juste par son emplacement.\n- Aucune page officielle docs.github.com trouvée énonçant le comportement de combinaison aussi explicitement que la page VS Code ; des sources secondaires (Medium, blog NashTech) le répètent mais ne sont pas officielles.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nMécanisme natif, standard, sans parsing custom : garder `.github/copilot-instructions.md` comme fichier possédé par le générateur, et placer le contenu spécifique au projet dans un fichier séparé `.github/instructions/project-conventions.instructions.md` (avec `applyTo: \"**\"` pour le rendre universel) — Copilot fusionne automatiquement les deux à chaque fois, sans action de notre part après la première installation.\n\n## Sources\n- https://code.visualstudio.com/docs/agent-customization/custom-instructions\n- https://github.com/orgs/community/discussions/170581" -} \ No newline at end of file + "links": [ + "vscode-copilot-builtin-tools", + "claude-md-import-mechanism", + "codex-agents-md-nesting" + ], + "content": "# GitHub Copilot — fusion automatique de fichiers d'instructions multiples\n\nRecherche du 2026-07-16, motivée par l'issue mA.xI.me #27.\n\n## Ce qui est confirmé (sourcé)\n\n- Mécanisme officiel et actuel : `.github/copilot-instructions.md` (toujours actif, portée repo entier) et `.github/instructions/*.instructions.md` (application conditionnelle via un glob `applyTo` ou correspondance sémantique) sont additifs, pas exclusifs — les deux se chargent ensemble en contexte. La doc VS Code le dit explicitement : \"If you have multiple instruction files in your project, VS Code combines and adds them to the chat context, no specific order is guaranteed.\" Source : https://code.visualstudio.com/docs/agent-customization/custom-instructions\n- La doc plus récente de Copilot CLI décrit une pile à 5 niveaux (personnel → instructions scopées par chemin → copilot-instructions.md repo entier → AGENTS.md → organisation) qui fusionnent tous, les niveaux supérieurs ne l'emportant qu'en cas de conflit direct.\n- Aucune syntaxe d'inclusion à l'intérieur d'un seul fichier d'instructions — mais des liens Markdown entre fichiers d'instructions sont une convention de référence croisée douce (ex. \"Applique ces conventions\"), pas une vraie fusion/inclusion.\n- Confusion réelle constatée dans la communauté : la discussion GitHub #170581 (org community) montre des utilisateurs ayant mal lu la formulation de la doc (\"either... or...\") comme mutuellement exclusive, alors que les deux types de fichiers se combinent réellement — clarifié par la communauté, pas encore par une réécriture de la doc officielle trouvée.\n\n## Incertitudes explicites\n\n- \"Aucun ordre spécifique garanti\" est un vrai risque pour notre cas d'usage si le fichier généré et le fichier écrit à la main donnent un jour des instructions contradictoires — impossible de forcer la victoire du fichier écrit à la main juste par son emplacement.\n- Aucune page officielle docs.github.com trouvée énonçant le comportement de combinaison aussi explicitement que la page VS Code ; des sources secondaires (Medium, blog NashTech) le répètent mais ne sont pas officielles.\n\n## Recommandation pour mA.xI.me (issue #27)\n\nMécanisme natif, standard, sans parsing custom : garder `.github/copilot-instructions.md` comme fichier possédé par le générateur, et placer le contenu spécifique au projet dans un fichier séparé `.github/instructions/project-conventions.instructions.md` (avec `applyTo: \"**\"` pour le rendre universel) — Copilot fusionne automatiquement les deux à chaque fois, sans action de notre part après la première installation.\n\n## Sources\n- https://code.visualstudio.com/docs/agent-customization/custom-instructions\n- https://github.com/orgs/community/discussions/170581\n" +} diff --git a/active/vscode-copilot/vscode-copilot-builtin-tools.json b/active/vscode-copilot/vscode-copilot-builtin-tools.json index dd88703..3207235 100644 --- a/active/vscode-copilot/vscode-copilot-builtin-tools.json +++ b/active/vscode-copilot/vscode-copilot-builtin-tools.json @@ -3,14 +3,24 @@ "type": "reference", "title": "VS Code / GitHub Copilot Chat -- outils built-in (tools: frontmatter)", "theme": "vscode-copilot", - "tags": ["vscode", "copilot", "tools", "builtin"], + "tags": [ + "vscode", + "copilot", + "tools", + "builtin" + ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", - "source": ["https://docs.github.com/en/copilot/reference/custom-agents-configuration", "https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/"], + "source": [ + "https://docs.github.com/en/copilot/reference/custom-agents-configuration", + "https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/" + ], "validated": "2026-07-13", "created": "2026-07-12", - "links": ["agent-skills-cross-tool-integration"], + "links": [ + "agent-skills-cross-tool-integration" + ], "content": "# VS Code / GitHub Copilot Chat — outils built-in (tools: frontmatter)\n\nStatut : `.new` — capture brute suite à une recherche ponctuelle, pas encore\nrelue/validée comme fiche KB stable. Savoir générique réutilisable, sans\ndonnée de projet/client/employeur.\n\n## Contexte\n\nErreur corrigée le 2026-07-12 : `web` et `vscode` avaient été retirés de\n`tools:` dans `maxime.agent.md` en les supposant à tort spécifiques à la\nmachine de Philippe (au même titre que `vscode.mermaid-markdown-features` ou\n`GitHub.vscode-pull-request-github`, qui eux le sont vraiment). Correction :\n`web` et `vscode` sont des **outils built-in**, disponibles pour tout\nutilisateur de l'extension Copilot Chat, pas une config locale.\n\n## Ce qui est confirmé (sourcé)\n\nD'après la doc GitHub officielle des custom agents\n([docs.github.com/en/copilot/reference/custom-agents-configuration](https://docs.github.com/en/copilot/reference/custom-agents-configuration)),\n7 alias d'outils built-in, avec leurs alias compatibles (mapping vers les\nnoms d'outils Claude Code — clin d'œil à la portabilité cross-outil) :\n\n| Alias Copilot | Alias compatibles |\n| --- | --- |\n| `execute` | `shell`, `Bash`, `powershell` |\n| `read` | `Read`, `NotebookRead` |\n| `edit` | `Edit`, `MultiEdit`, `Write`, `NotebookEdit` |\n| `search` | `Grep`, `Glob` |\n| `agent` | `custom-agent`, `Task` |\n| `web` | `WebSearch`, `WebFetch` |\n| `todo` | `TodoWrite` |\n\nDeux serveurs MCP disponibles par défaut pour les agents cloud GitHub.com :\n`github/*` (outils GitHub en lecture seule) et `playwright/*` (automatisation\nnavigateur, localhost uniquement).\n\nD'après le blog GitHub officiel\n([github.blog/.../how-were-making-github-copilot-smarter-with-fewer-tools](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/))\n: VS Code organise un noyau de 13 outils essentiels (structure du repo,\nlecture/édition de fichiers, recherche de contexte, terminal), puis regroupe\nle reste en catégories virtuelles : **Jupyter Notebook Tools**, **Web\nInteraction Tools**, **VS Code Workspace Tools**, **Testing Tools**. Ça\ncorrobore `web` (Web Interaction Tools) et `vscode` (VS Code Workspace Tools)\ncomme catégories réelles, pas des extras personnels.\n\n## Sous-outils observés directement (captures d'écran picker VS Code, 2026-07-13)\n\nPhilippe a fourni des captures d'écran du picker d'outils (menu `#` du chat\nCopilot). Reconstitution complète, textuelle, du détail par catégorie —\nobservation directe de son environnement, `non vérifié par exécution` contre\nune doc officielle listant chaque sous-fonction.\n\n### agent — Delegate tasks to other agents\n\n- **runSubagent** — Run a task within an isolated subagent context to enable efficient organization of tasks and context window management.\n\n### browser — Open and interact with integrated browser pages *(tous décochés)*\n\n- clickElement — Click an element in a browser page\n- dragElement — Drag an element over another element\n- handleDialog — Respond to a dialog in a browser page\n- hoverElement — Hover over an element in a browser page\n- navigatePage — Navigate or reload a browser page\n- openBrowserPage — Open a URL in the integrated browser\n- readPage — Read the content of a browser page\n- runPlaywrightCode — Run a Playwright code snippet against a browser page\n- screenshotPage — Capture a screenshot of a browser page\n- typeInPage — Type text or press keys in a browser page\n\n### edit — Edit files in your workspace\n\n- createDirectory — Create new directories in your workspace\n- createFile — Create new files\n- createJupyterNotebook — Create a new Jupyter Notebook\n- editFiles — Edit files\n- editNotebook — Edit a notebook file in the workspace\n- rename — Rename a symbol across the workspace\n\n### execute — Execute code and applications on your machine\n\n- createAndRunTask — Create and run a task in the workspace\n- executionSubagent — Launch an execution-focused subagent that runs one or more terminal commands to accomplish a task. This subagent is powered by Google's Gemini-3-Flash model. It is designed to select an efficient summary of the terminal outputs to return to the main agent context.\n- getTerminalOutput — Send input text to an active terminal execution (identified by the id returned from run_in_terminal). The 'command' field may be empty or whitespace to press Enter (useful for interactive prompts). By default, returns the last 20 lines of terminal output captured shortly after sending. Set 'waitForOutput' to true for interactive programs (games, REPLs, etc.) to wait until the terminal becomes idle before returning output — this gives you the program's response to your input.\n- killTerminal — Kill a terminal by its ID. Use this to clean up terminals that are no longer needed (e.g., after stopping a server or when a long-running task completes). The terminal ID is returned by run_in_terminal in async mode (legacy: isBackground=true).\n- runInTerminal — Run commands in the terminal\n- runNotebookCell — Trigger the execution of a cell in a notebook file\n- runTask — Run tasks in the workspace\n- runTests — Run unit tests (optionally with coverage)\n- sendToTerminal — Send input text to an active terminal execution (identified by the id returned from run_in_terminal). The 'command' field may be empty or whitespace to press Enter (useful for interactive prompts). By default, returns the last 20 lines of terminal output captured shortly after sending. Set 'waitForOutput' to true for interactive programs (games, REPLs, etc.) to wait until the terminal becomes idle before returning output — this gives you the program's response to your input.\n- testFailure — Include test failure information\n\n### read — Read files in your workspace\n\n- getNotebookSummary — This is a tool returns the list of the Notebook cells along with the id, cell types, line ranges, language, execution information and output mime types for each cell. This is useful to get Cell Ids when executing a notebook or determine what cells have been executed and what order, or what cells have outputs. If required to read contents of a cell use this to determine the line range of a cells, and then use read_file tool to read a specific line range. Requery this tool if the contents of the notebook change.\n- getTaskOutput — Get the output of a task\n- problems — Check errors for a particular file\n- readFile — Read the contents of a file\n- readNotebookCellOutput — Read the output of a previously executed cell\n- terminalLastCommand — Get the last command run in the active terminal.\n- terminalSelection — Get the current selection in the active terminal.\n- viewImage — View the contents of an image file\n\n### search — Search files in your workspace\n\n- changes — Get diffs of changed files\n- codebase — Find relevant file chunks, symbols, and other information via\n semantic search\n- fileSearch — Find files by name using a glob pattern\n- listDirectory — List the contents of a directory\n- textSearch — Find text in files by regular expression\n- usages — Find references, definitions, and implementations of a symbol\n\n### todo — Manage and track todo items for task planning\n\n### vscode — Use VS Code features\n\n- askQuestions — Ask structured clarifying questions using single select, multi-select, or freeform inputs to collect task requirements before proceeding.\n- extensions — Search for VS Code extensions\n- installExtension — Install an extension in VS Code. Use this tool to install an extension in Visual Studio Code as part of a new workspace creation process only.\n- memory — Manage persistent memory across conversations\n- newWorkspace — Scaffold a new workspace in VS Code\n- resolveMemoryFileUri — Resolve a memory file path to its actual URI\n- runCommand — Run a command in VS Code. Use this tool to run a command in Visual Studio Code as part of a new workspace creation process only.\n- vscodeAPI — Use VS Code API references to answer questions about VS Code extension development.\n\n### web — Fetch information from the web\n\n- fetch — Fetch the main content from a web page. You should include the\n URL of the page you w...\n- githubRepo — Semantic Search a GitHub repository for relevant source code snippets. You can specify a repository using owner/repo\n- githubTextSearch — Text search a GitHub repository or organization for files containing specific keywords or code patterns.\n\nLe champ `todo` apparaît comme sous-outil de `search` dans le picker\nobservé, alors que la table des alias plus haut le liste comme catégorie de\npremier niveau à part (`todo` → `TodoWrite`) — à réconcilier, pas forcément\ncontradictoire (un alias top-level peut être exposé aussi comme sous-item\ndans l'UI).\n\n## Ce qui reste incertain\n\n- Aucune source *officielle écrite* ne fournit cette table de sous-outils —\n elle vient de l'observation directe de Philippe (ci-dessus), qui fait\n autorité pour son environnement mais n'est pas vérifiée contre la doc. Et Philippe observe ces outils au travail, avec un laptop travail, et a la maison avec son oridnateur de bureau.\n- `browser` : confirmé comme catégorie réelle de premier niveau dans le\n picker (10 sous-outils listés ci-dessus), avec un net recoupement\n fonctionnel avec `playwright/*` (MCP cloud) — reste à déterminer si\n `browser` est ce même MCP exposé localement, ou une implémentation VS Code\n distincte.\n- Méthode recommandée par la doc VS Code elle-même pour un inventaire\n complet et à jour : taper `#` dans le champ de saisie du chat Copilot —\n plus fiable qu'une doc statique qui peut dater vite sur ce sujet.\n\n## Sources consultées\n\n- [Custom agents configuration — GitHub Docs](https://docs.github.com/en/copilot/reference/custom-agents-configuration)\n- [Custom agents in VS Code](https://code.visualstudio.com/docs/agent-customization/custom-agents)\n- [Use tools in chat — VS Code Docs](https://code.visualstudio.com/docs/copilot/agents/agent-tools)\n- [How we're making GitHub Copilot smarter with fewer tools — GitHub Blog](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/)\n- [GitHub Copilot in VS Code cheat sheet](https://code.visualstudio.com/docs/agents/reference/copilot-vscode-features)\n\n## Application faite\n\n`tools/generate-adapters.ps1`/`.sh` : `maxime.agent.md` (orchestrateur\n`maxi-copilot` uniquement, pas les sous-agents reviewer ni les prompts de\nworkflow) déclare désormais `[read, search, execute, edit, agent, vscode,\nweb]` — reprend exactement le sous-ensemble non-ambigu de ce que Philippe a\nlui-même validé comme fonctionnel dans son environnement, moins les deux\nextensions personnelles (`vscode.mermaid-markdown-features`,\n`GitHub.vscode-pull-request-github`).\n" -} \ No newline at end of file +} diff --git a/index.json b/index.json index 10620c4..8666098 100644 --- a/index.json +++ b/index.json @@ -1,273 +1,287 @@ [ { - "id": "reference", - "type": "reference", - "title": "AD DS Reference", - "theme": "ad-ds", + "id": "ad-ds-domain-controller-security-hardening", + "type": "pattern", + "title": "Contrôleurs de domaine AD DS — durcissement de sécurité", + "theme": "ad-ds-security", "tags": [ - "acl", - "auth", - "dotnet", - "kerberos", - "ldap", - "rest-api" + "domain-controller", + "tier-0", + "windows-server", + "hardening", + "logging", + "backup", + "ldap-signing" ], "scope": "global", - "status": "active", - "confidence": "fact", + "status": "draft", + "confidence": "hypothesis", "audience": "generic", "source": [ - "ouritres/coreapi/.claude/knowledge-base/ad-ds-reference.md", - "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/d2435927-0999-4c62-8c6d-13ba31a52e1a", - "https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.protocols", - "https://github.com/dotnet/dotnet-api-docs", - "https://github.com/KopiCloud-AD-API", - "ouritres/coreapi/.claude/handoff/spec-0-status.md" - ], - "validated": "2026-07-16", - "created": "2026-06-16", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/securing-domain-controllers-against-attack", + "https://learn.microsoft.com/en-us/windows-server/security/secured-core-server", + "https://www.cyber.gov.au/business-government/asds-cyber-security-frameworks/ism/cyber-security-guidelines/guidelines-for-system-hardening", + "https://www.cisa.gov/stopransomware/ransomware-guide", + "https://messervices.cyber.gouv.fr/guides/mise-en-oeuvre-securisee-dun-serveur-windows", + "https://adsecurity.org/?p=5036", + "https://adsecurity.org/?p=3377" + ], + "validated": "2026-07-25", + "created": "2026-07-25", "links": [ - "unattended-deployment" + "windows-server-2022-plus-hardening-source-baselines", + "ad-ds-tiered-administration-hardening", + "ad-ds-threat-driven-control-map" ], - "path": "active/ad-ds/reference.json" + "path": "active/ad-ds-security/ad-ds-domain-controller-security-hardening.json" }, { - "id": "unattended-deployment", - "type": "procedure", - "title": "Unattended Active Directory Domain Services (AD DS) Deployment", - "theme": "ad-ds", + "id": "ad-ds-domain-forest-gpo-security-baseline", + "type": "pattern", + "title": "AD DS — baseline de sécurité des domaines, forêts et politiques GPO", + "theme": "ad-ds-security", "tags": [ - "aws-ec2", - "dcpromo", - "dns", - "ec2launch", - "ssm", - "unattend" + "ad-ds", + "forest", + "domain", + "gpo", + "trust", + "authentication", + "policy", + "baseline" ], "scope": "global", - "status": "active", - "confidence": "fact", + "status": "draft", + "confidence": "hypothesis", "audience": "generic", "source": [ - "ouritres/coreapi/.claude/knowledge-base/ad-ds-unattended-deployment.md", - "https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo", - "https://aws.amazon.com/whitepapers/active-directory-domain-services/", - "ouritres/coreapi/.claude/handoff/spec-0-status.md" - ], - "validated": "2026-07-16", - "created": "2026-06-16", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory", + "https://www.cyber.gc.ca/en/guidance/guidance-securing-microsoft-active-directory-services-your-organization-itsm60100", + "https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100", + "https://www.cyber.gov.au/business-government/detecting-responding-to-threats/detecting-and-mitigating-active-directory-compromises", + "https://public.cyber.mil/stigs/downloads/", + "https://www.pingcastle.com/methodology/" + ], + "validated": "2026-07-25", + "created": "2026-07-25", "links": [ - "reference" + "ad-ds-security-hardening-study-synthesis", + "ad-ds-domain-controller-security-hardening", + "ad-ds-gpo-acl-lifecycle-governance", + "ad-ds-threat-driven-control-map" ], - "path": "active/ad-ds/unattended-deployment.json" + "path": "active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.json" }, { - "id": "enterprise-access-model", - "type": "glossary", - "title": "Enterprise Access Model (EAM) — plans de sensibilité Microsoft", - "theme": "security-architecture", + "id": "ad-ds-gpo-acl-lifecycle-governance", + "type": "pattern", + "title": "AD DS — gouvernance du cycle de vie des GPO et ACL", + "theme": "ad-ds-security", "tags": [ - "eam", - "tiering", - "control-plane", - "management-plane", - "data-workload-plane", - "microsoft" + "gpo", + "acl", + "delegation", + "ownership", + "change-management", + "evidence", + "lifecycle" ], "scope": "global", - "status": "active", - "confidence": "fact", + "status": "draft", + "confidence": "hypothesis", "audience": "generic", "source": [ - "https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model" - ], - "validated": "2026-07-18", - "created": "2026-07-18", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/advanced-audit-policy-configuration", + "https://public.cyber.mil/stigs/gpo/", + "https://attack.mitre.org/techniques/T1484/001/", + "https://adsecurity.org/?p=5061", + "https://www.trimarcsecurity.com/hub-post/securing-active-directory-performing-an-active-directory-security-review" + ], + "validated": "2026-07-25", + "created": "2026-07-25", "links": [ - "zero-standing-access" + "ad-ds-domain-forest-gpo-security-baseline", + "ad-ds-tiered-administration-hardening", + "ad-ds-threat-driven-control-map" ], - "path": "active/security-architecture/enterprise-access-model.json" + "path": "active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.json" }, { - "id": "zero-standing-access", - "type": "glossary", - "title": "Zero standing access, secretless, et gMSA — principes", - "theme": "security-architecture", + "id": "ad-ds-security-control-assurance-levels", + "type": "pattern", + "title": "AD DS — niveaux proposés de contrôle et d'assurance", + "theme": "ad-ds-security", "tags": [ - "zero-standing-access", - "secretless", - "gmsa", - "jit", - "pam" + "baseline", + "assurance", + "control-levels", + "maturity", + "hardening", + "evidence" ], "scope": "global", - "status": "active", - "confidence": "fact", + "status": "draft", + "confidence": "hypothesis", "audience": "generic", "source": [ - "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/group-managed-service-accounts/group-managed-service-accounts-overview", - "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-linux-gmsa.html" - ], - "validated": "2026-07-18", - "created": "2026-07-18", + "https://www.nist.gov/cyberframework", + "https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final", + "https://www.cisecurity.org/controls/v8", + "https://www.cisecurity.org/benchmark/microsoft_windows_server", + "https://public.cyber.mil/stigs/downloads/", + "https://www.pingcastle.com/methodology/", + "https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100" + ], + "validated": "2026-07-25", + "created": "2026-07-25", "links": [ - "enterprise-access-model" + "ad-ds-security-hardening-study-synthesis", + "ad-ds-threat-driven-control-map", + "security-framework-role-and-crosswalk" ], - "path": "active/security-architecture/zero-standing-access.json" + "path": "active/ad-ds-security/ad-ds-security-control-assurance-levels.json" }, { - "id": "ad-ds-tier-model-microsoft-reference-implementation", + "id": "ad-ds-security-hardening-study-synthesis", "type": "reference", - "title": "AD DS Tier Model (Microsoft OSS) — référence historique/comparative, PAS le modèle cible", - "theme": "security-architecture", + "title": "Étude indépendante — durcissement Windows Server et sécurité AD DS", + "theme": "ad-ds-security", "tags": [ "ad-ds", + "hardening", + "windows-server", + "gpo", + "acl", "tiering", - "tier-0", - "tier-1", - "tier-2", - "reference-historique", - "comparatif", - "non-cible", - "deployment-methodology", - "drift-detection", - "gpo-management", - "cmdlet-architecture", - "powershell", - "microsoft" + "baseline", + "study" ], "scope": "global", - "status": "active", - "confidence": "fact", + "status": "draft", + "confidence": "hypothesis", "audience": "generic", "source": [ - "https://microsoft.github.io/ActiveDirectoryTierModel/", - "https://microsoft.github.io/ActiveDirectoryTierModel/deployment-methodology/", - "https://microsoft.github.io/ActiveDirectoryTierModel/drift-detection-details/", - "https://microsoft.github.io/ActiveDirectoryTierModel/gpo-management-strategy/", - "https://microsoft.github.io/ActiveDirectoryTierModel/cmdlet-architecture/" + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory", + "https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100", + "https://www.cyber.gov.au/business-government/detecting-responding-to-threats/detecting-and-mitigating-active-directory-compromises", + "https://messervices.cyber.gouv.fr/guides/recommandations-pour-ladministration-securisee-des-si-reposant-sur-ad" ], - "validated": "2026-08-08", - "created": "2026-08-08", + "validated": "2026-07-25", + "created": "2026-07-25", "links": [ - "enterprise-access-model", + "windows-server-2022-plus-hardening-source-baselines", + "ad-ds-domain-forest-gpo-security-baseline", + "ad-ds-domain-controller-security-hardening", "ad-ds-tiered-administration-hardening", "ad-ds-gpo-acl-lifecycle-governance", + "ad-ds-threat-driven-control-map", "ad-ds-security-control-assurance-levels", - "ad-ds-threat-driven-control-map" + "hybrid-identity-entra-security-impact-inventory", + "security-framework-role-and-crosswalk" ], - "path": "active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json" - }, - { - "id": "ecs-fargate-task-isolation", - "type": "reference", - "title": "ECS EC2 vs Fargate — isolation des tasks", - "theme": "aws", - "tags": [ - "ecs", - "fargate", - "ec2", - "isolation", - "containers" - ], - "scope": "global", - "status": "active", - "confidence": "fact", - "audience": "generic", - "source": [ - "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html", - "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-linux-gmsa.html" - ], - "validated": "2026-07-18", - "created": "2026-07-18", - "links": [ - "zero-standing-access" - ], - "path": "active/aws/ecs-fargate-task-isolation.json" + "path": "active/ad-ds-security/ad-ds-security-hardening-study-synthesis.json" }, { - "id": "splunk-cim-data-models", + "id": "ad-ds-threat-driven-control-map", "type": "reference", - "title": "Splunk CIM — modèles Authentication et Change", - "theme": "siem", + "title": "AD DS — carte menaces vers domaines de contrôle", + "theme": "ad-ds-security", "tags": [ - "splunk", - "cim", - "audit-log", - "authentication", - "change" + "mitre-attack", + "kerberoasting", + "dcsync", + "golden-ticket", + "password-spraying", + "gpo", + "detection" ], "scope": "global", - "status": "suspect", + "status": "draft", "confidence": "hypothesis", "audience": "generic", "source": [ - "https://help.splunk.com/en/data-management/common-information-model/6.2/data-models/authentication", - "https://help.splunk.com/en/splunk-cloud-platform/common-information-model/6.1/data-models/cim-fields-per-associated-data-model", - "https://help.splunk.com/en/data-management/common-information-model/6.2/field-mappings/change-field-mapping", - "https://help.splunk.com/en/splunk-enterprise/common-information-model" + "https://attack.mitre.org/techniques/T1558/003/", + "https://attack.mitre.org/techniques/T1558/001/", + "https://attack.mitre.org/techniques/T1003/006/", + "https://attack.mitre.org/techniques/T1003/003/", + "https://attack.mitre.org/techniques/T1110/003/", + "https://attack.mitre.org/techniques/T1484/001/", + "https://www.cyber.gov.au/business-government/detecting-responding-to-threats/detecting-and-mitigating-active-directory-compromises", + "https://www.cisa.gov/stopransomware/ransomware-guide", + "https://www.pingcastle.com/methodology/", + "https://www.trimarcsecurity.com/hub-post/securing-active-directory-performing-an-active-directory-security-review" + ], + "validated": "2026-07-25", + "created": "2026-07-25", + "links": [ + "ad-ds-domain-controller-security-hardening", + "ad-ds-domain-forest-gpo-security-baseline", + "ad-ds-security-control-assurance-levels" ], - "validated": "2026-07-18", - "created": "2026-07-18", - "links": [], - "path": "active/siem/splunk-cim-data-models.json" + "path": "active/ad-ds-security/ad-ds-threat-driven-control-map.json" }, { - "id": "sailpoint-identityiq", + "id": "reference", "type": "reference", - "title": "SailPoint IdentityIQ (IIQ) — gouvernance d'accès et workflows d'approbation", - "theme": "governance", + "title": "AD DS Reference", + "theme": "ad-ds", "tags": [ - "iam", - "iga", - "sailpoint", - "access-request", - "approval", - "sod" + "acl", + "auth", + "dotnet", + "kerberos", + "ldap", + "rest-api" ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", "source": [ - "https://documentation.sailpoint.com/saas/help/requests/index.html", - "https://documentation.sailpoint.com/saas/help/requests/config_ap_roles.html", - "https://developer.sailpoint.com/docs/api/v3/access-request-approvals/" + "ouritres/coreapi/.claude/knowledge-base/ad-ds-reference.md", + "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/d2435927-0999-4c62-8c6d-13ba31a52e1a", + "https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.protocols", + "https://github.com/dotnet/dotnet-api-docs", + "https://github.com/KopiCloud-AD-API", + "ouritres/coreapi/.claude/handoff/spec-0-status.md" ], - "validated": "2026-07-18", - "created": "2026-07-18", + "validated": "2026-07-16", + "created": "2026-06-16", "links": [ - "servicenow-itsm-change-management" + "unattended-deployment" ], - "path": "active/governance/sailpoint-identityiq.json" + "path": "active/ad-ds/reference.json" }, { - "id": "servicenow-itsm-change-management", - "type": "reference", - "title": "ServiceNow — tickets et workflow d'approbation (ITSM Change Management)", - "theme": "governance", + "id": "unattended-deployment", + "type": "procedure", + "title": "Unattended Active Directory Domain Services (AD DS) Deployment", + "theme": "ad-ds", "tags": [ - "itsm", - "servicenow", - "change-management", - "ticket", - "cab", - "approval" + "aws-ec2", + "dcpromo", + "dns", + "ec2launch", + "ssm", + "unattend" ], "scope": "global", "status": "active", "confidence": "fact", "audience": "generic", "source": [ - "https://www.servicenow.com/community/itsm-articles/change-management-process-workflow/ta-p/2299141", - "https://www.servicenow.com/community/itsm-forum/change-management-in-servicenow-everything-you-need-to-know/m-p/3439058" + "ouritres/coreapi/.claude/knowledge-base/ad-ds-unattended-deployment.md", + "https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo", + "https://aws.amazon.com/whitepapers/active-directory-domain-services/", + "ouritres/coreapi/.claude/handoff/spec-0-status.md" ], - "validated": "2026-07-18", - "created": "2026-07-18", + "validated": "2026-07-16", + "created": "2026-06-16", "links": [ - "sailpoint-identityiq" + "reference" ], - "path": "active/governance/servicenow-itsm-change-management.json" + "path": "active/ad-ds/unattended-deployment.json" }, { "id": "agent-skills-cross-tool-integration", @@ -297,6 +311,33 @@ ], "path": "active/agent-tooling/agent-skills-cross-tool-integration.json" }, + { + "id": "ecs-fargate-task-isolation", + "type": "reference", + "title": "ECS EC2 vs Fargate — isolation des tasks", + "theme": "aws", + "tags": [ + "ecs", + "fargate", + "ec2", + "isolation", + "containers" + ], + "scope": "global", + "status": "active", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html", + "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-linux-gmsa.html" + ], + "validated": "2026-07-18", + "created": "2026-07-18", + "links": [ + "zero-standing-access" + ], + "path": "active/aws/ecs-fargate-task-isolation.json" + }, { "id": "claude-md-hierarchie", "type": "reference", @@ -468,6 +509,103 @@ ], "path": "active/engine-catalog/copilot-models.json" }, + { + "id": "sailpoint-identityiq", + "type": "reference", + "title": "SailPoint IdentityIQ (IIQ) — gouvernance d'accès et workflows d'approbation", + "theme": "governance", + "tags": [ + "iam", + "iga", + "sailpoint", + "access-request", + "approval", + "sod" + ], + "scope": "global", + "status": "active", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://documentation.sailpoint.com/saas/help/requests/index.html", + "https://documentation.sailpoint.com/saas/help/requests/config_ap_roles.html", + "https://developer.sailpoint.com/docs/api/v3/access-request-approvals/" + ], + "validated": "2026-07-18", + "created": "2026-07-18", + "links": [ + "servicenow-itsm-change-management" + ], + "path": "active/governance/sailpoint-identityiq.json" + }, + { + "id": "servicenow-itsm-change-management", + "type": "reference", + "title": "ServiceNow — tickets et workflow d'approbation (ITSM Change Management)", + "theme": "governance", + "tags": [ + "itsm", + "servicenow", + "change-management", + "ticket", + "cab", + "approval" + ], + "scope": "global", + "status": "active", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://www.servicenow.com/community/itsm-articles/change-management-process-workflow/ta-p/2299141", + "https://www.servicenow.com/community/itsm-forum/change-management-in-servicenow-everything-you-need-to-know/m-p/3439058" + ], + "validated": "2026-07-18", + "created": "2026-07-18", + "links": [ + "sailpoint-identityiq" + ], + "path": "active/governance/servicenow-itsm-change-management.json" + }, + { + "id": "hybrid-identity-entra-security-impact-inventory", + "type": "reference", + "title": "Environnement hybride AD DS / Microsoft Entra ID — inventaire des impacts de sécurité à résoudre", + "theme": "hybrid-identity", + "tags": [ + "ad-ds", + "entra-id", + "hybrid-identity", + "entra-connect", + "cloud-sync", + "pta", + "phs", + "adfs", + "control-plane" + ], + "scope": "global", + "status": "draft", + "confidence": "hypothesis", + "audience": "generic", + "source": [ + "https://learn.microsoft.com/en-us/entra/architecture/security-operations-introduction", + "https://learn.microsoft.com/en-us/entra/architecture/security-operations-infrastructure", + "https://learn.microsoft.com/en-us/entra/architecture/resilience-in-hybrid", + "https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/choose-ad-authn", + "https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-install-prerequisites", + "https://learn.microsoft.com/en-us/entra/identity/hybrid/cloud-sync/what-is-cloud-sync", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/tier-model", + "https://attack.mitre.org/techniques/T1484/", + "https://www.cyber.gov.au/business-government/asds-cyber-security-frameworks/ism/cyber-security-guidelines/guidelines-for-system-hardening" + ], + "validated": "2026-07-25", + "created": "2026-07-25", + "links": [ + "enterprise-access-model", + "ad-ds-tiered-administration-hardening", + "ad-ds-threat-driven-control-map" + ], + "path": "active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.json" + }, { "id": "native-exe-json-quoting", "type": "pattern", @@ -493,6 +631,210 @@ ], "path": "active/powershell/native-exe-json-quoting.json" }, + { + "id": "ad-ds-tier-model-microsoft-reference-implementation", + "type": "reference", + "title": "AD DS Tier Model (Microsoft OSS) — référence historique/comparative, PAS le modèle cible", + "theme": "security-architecture", + "tags": [ + "ad-ds", + "tiering", + "tier-0", + "tier-1", + "tier-2", + "reference-historique", + "comparatif", + "non-cible", + "deployment-methodology", + "drift-detection", + "gpo-management", + "cmdlet-architecture", + "powershell", + "microsoft" + ], + "scope": "global", + "status": "active", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://microsoft.github.io/ActiveDirectoryTierModel/", + "https://microsoft.github.io/ActiveDirectoryTierModel/deployment-methodology/", + "https://microsoft.github.io/ActiveDirectoryTierModel/drift-detection-details/", + "https://microsoft.github.io/ActiveDirectoryTierModel/gpo-management-strategy/", + "https://microsoft.github.io/ActiveDirectoryTierModel/cmdlet-architecture/" + ], + "validated": "2026-08-08", + "created": "2026-08-08", + "links": [ + "enterprise-access-model", + "ad-ds-tiered-administration-hardening", + "ad-ds-gpo-acl-lifecycle-governance", + "ad-ds-security-control-assurance-levels", + "ad-ds-threat-driven-control-map" + ], + "path": "active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.json" + }, + { + "id": "ad-ds-tiered-administration-hardening", + "type": "pattern", + "title": "AD DS — durcissement de l'administration Tier 0, Tier 1 et Tier 2", + "theme": "security-architecture", + "tags": [ + "ad-ds", + "tier-0", + "tier-1", + "tier-2", + "paw", + "privileged-access", + "least-privilege" + ], + "scope": "global", + "status": "draft", + "confidence": "hypothesis", + "audience": "generic", + "source": [ + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/tier-model", + "https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model", + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory", + "https://messervices.cyber.gouv.fr/guides/recommandations-pour-ladministration-securisee-des-si-reposant-sur-ad", + "https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100", + "https://public.cyber.mil/stigs/downloads/" + ], + "validated": "2026-07-25", + "created": "2026-07-25", + "links": [ + "enterprise-access-model", + "zero-standing-access", + "ad-ds-domain-controller-security-hardening", + "ad-ds-gpo-acl-lifecycle-governance" + ], + "path": "active/security-architecture/ad-ds-tiered-administration-hardening.json" + }, + { + "id": "enterprise-access-model", + "type": "glossary", + "title": "Enterprise Access Model (EAM) — plans de sensibilité Microsoft", + "theme": "security-architecture", + "tags": [ + "eam", + "tiering", + "control-plane", + "management-plane", + "data-workload-plane", + "microsoft" + ], + "scope": "global", + "status": "active", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model" + ], + "validated": "2026-07-18", + "created": "2026-07-18", + "links": [ + "zero-standing-access" + ], + "path": "active/security-architecture/enterprise-access-model.json" + }, + { + "id": "zero-standing-access", + "type": "glossary", + "title": "Zero standing access, secretless, et gMSA — principes", + "theme": "security-architecture", + "tags": [ + "zero-standing-access", + "secretless", + "gmsa", + "jit", + "pam" + ], + "scope": "global", + "status": "active", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/group-managed-service-accounts/group-managed-service-accounts-overview", + "https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-linux-gmsa.html" + ], + "validated": "2026-07-18", + "created": "2026-07-18", + "links": [ + "enterprise-access-model" + ], + "path": "active/security-architecture/zero-standing-access.json" + }, + { + "id": "security-framework-role-and-crosswalk", + "type": "reference", + "title": "Référentiels sécurité — rôle dans une baseline AD DS et Windows Server", + "theme": "security-governance", + "tags": [ + "nist", + "cis", + "iso-27001", + "cobit", + "pci-dss", + "hipaa", + "soc-2", + "anssi", + "cisa", + "disa", + "crosswalk" + ], + "scope": "global", + "status": "draft", + "confidence": "hypothesis", + "audience": "generic", + "source": [ + "https://www.nist.gov/cyberframework", + "https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final", + "https://www.cisecurity.org/controls/v8", + "https://www.cisecurity.org/benchmark/microsoft_windows_server", + "https://www.iso.org/standard/27001", + "https://www.isaca.org/resources/cobit", + "https://www.pcisecuritystandards.org/standards/pci-dss/", + "https://www.hhs.gov/hipaa/for-professionals/security/index.html", + "https://www.aicpa-cima.com/resources/download/soc-for-service-organizations-engagements-overview", + "https://public.cyber.mil/stigs/downloads/", + "https://www.cyber.gc.ca/en/guidance/guidance-securing-microsoft-active-directory-services-your-organization-itsm60100", + "https://messervices.cyber.gouv.fr/guides/recommandations-pour-ladministration-securisee-des-si-reposant-sur-ad" + ], + "validated": "2026-07-25", + "created": "2026-07-25", + "links": [ + "ad-ds-security-control-assurance-levels", + "ad-ds-security-hardening-study-synthesis" + ], + "path": "active/security-governance/security-framework-role-and-crosswalk.json" + }, + { + "id": "splunk-cim-data-models", + "type": "reference", + "title": "Splunk CIM — modèles Authentication et Change", + "theme": "siem", + "tags": [ + "splunk", + "cim", + "audit-log", + "authentication", + "change" + ], + "scope": "global", + "status": "suspect", + "confidence": "hypothesis", + "audience": "generic", + "source": [ + "https://help.splunk.com/en/data-management/common-information-model/6.2/data-models/authentication", + "https://help.splunk.com/en/splunk-cloud-platform/common-information-model/6.1/data-models/cim-fields-per-associated-data-model", + "https://help.splunk.com/en/data-management/common-information-model/6.2/field-mappings/change-field-mapping", + "https://help.splunk.com/en/splunk-enterprise/common-information-model" + ], + "validated": "2026-07-18", + "created": "2026-07-18", + "links": [], + "path": "active/siem/splunk-cim-data-models.json" + }, { "id": "copilot-instructions-merge", "type": "reference", @@ -546,5 +888,45 @@ "agent-skills-cross-tool-integration" ], "path": "active/vscode-copilot/vscode-copilot-builtin-tools.json" + }, + { + "id": "windows-server-2022-plus-hardening-source-baselines", + "type": "reference", + "title": "Windows Server 2022 et versions ultérieures — sources de baseline et règles d'adoption", + "theme": "windows-server", + "tags": [ + "windows-server-2022", + "windows-server-2025", + "security-baseline", + "sct", + "osconfig", + "secured-core", + "cis", + "stig" + ], + "scope": "global", + "status": "draft", + "confidence": "fact", + "audience": "generic", + "source": [ + "https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/security-compliance-toolkit-10", + "https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-overview", + "https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-how-to-configure-security-baselines", + "https://learn.microsoft.com/en-us/windows-server/security/secured-core-server", + "https://learn.microsoft.com/en-us/windows-server/security/configure-secured-core-server", + "https://www.cisecurity.org/benchmark/microsoft_windows_server", + "https://public.cyber.mil/stigs/downloads/", + "https://public.cyber.mil/stigs/gpo/", + "https://messervices.cyber.gouv.fr/guides/mise-en-oeuvre-securisee-dun-serveur-windows", + "https://www.cyber.gov.au/business-government/asds-cyber-security-frameworks/ism/cyber-security-guidelines/guidelines-for-system-hardening" + ], + "validated": "2026-07-25", + "created": "2026-07-25", + "links": [ + "ad-ds-domain-controller-security-hardening", + "ad-ds-security-control-assurance-levels", + "security-framework-role-and-crosswalk" + ], + "path": "active/windows-server/windows-server-2022-plus-hardening-source-baselines.json" } ] diff --git a/index.md b/index.md index 46783cc..3ce8c53 100644 --- a/index.md +++ b/index.md @@ -1,21 +1,114 @@ + + # Knowledge Base — ouritres -> L'index des fiches vit dans [`index.json`](index.json) (format JSON, un objet -> par fiche, sans `content`). Ce fichier ne documente que les conventions -> humaines du repo ; le skill `maxime-kb` lit `index.json`, pas ce fichier. +29 fiche(s). Les conventions et le format de fiche sont décrits dans +[`KB-CONVENTIONS.md`](KB-CONVENTIONS.md). L'index machine, lu par le skill +`maxime-kb`, est [`index.json`](index.json) ; ce catalogue-ci est sa contrepartie +lisible, avec un lien vers la version Markdown de chaque fiche. + +## Fiches actives + +### `ad-ds` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [AD DS Reference](md/active/ad-ds/reference.md) | reference | active | fact | 2026-07-16 | +| [Unattended Active Directory Domain Services (AD DS) Deployment](md/active/ad-ds/unattended-deployment.md) | procedure | active | fact | 2026-07-16 | + +### `ad-ds-security` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Contrôleurs de domaine AD DS — durcissement de sécurité](md/active/ad-ds-security/ad-ds-domain-controller-security-hardening.md) | pattern | draft | hypothesis | 2026-07-25 | +| [AD DS — baseline de sécurité des domaines, forêts et politiques GPO](md/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.md) | pattern | draft | hypothesis | 2026-07-25 | +| [AD DS — gouvernance du cycle de vie des GPO et ACL](md/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.md) | pattern | draft | hypothesis | 2026-07-25 | +| [AD DS — niveaux proposés de contrôle et d'assurance](md/active/ad-ds-security/ad-ds-security-control-assurance-levels.md) | pattern | draft | hypothesis | 2026-07-25 | +| [Étude indépendante — durcissement Windows Server et sécurité AD DS](md/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.md) | reference | draft | hypothesis | 2026-07-25 | +| [AD DS — carte menaces vers domaines de contrôle](md/active/ad-ds-security/ad-ds-threat-driven-control-map.md) | reference | draft | hypothesis | 2026-07-25 | + +### `agent-tooling` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Agent Skills -- standard ouvert cross-outil (Claude Code, Copilot/VS Code, Codex)](md/active/agent-tooling/agent-skills-cross-tool-integration.md) | reference | active | fact | 2026-07-13 | + +### `aws` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [ECS EC2 vs Fargate — isolation des tasks](md/active/aws/ecs-fargate-task-isolation.md) | reference | active | fact | 2026-07-18 | + +### `claude-config` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Hiérarchie & chargement des CLAUDE.md (Claude Code)](md/active/claude-config/claude-md-hierarchie.md) | reference | active | fact | 2026-06-16 | +| [Claude Code — mécanisme d'import @fichier pour CLAUDE.md](md/active/claude-config/claude-md-import-mechanism.md) | reference | active | fact | 2026-07-16 | + +### `codex-config` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [OpenAI Codex — imbrication et fusion des fichiers AGENTS.md](md/active/codex-config/codex-agents-md-nesting.md) | reference | active | fact | 2026-07-16 | + +### `engine-catalog` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Claude Code — moteurs (modèles) et effort, catalogue + qui décide](md/active/engine-catalog/claude-code-models.md) | reference | active | fact | 2026-07-16 | +| [Codex — moteurs (modèles) et effort, catalogue + qui décide](md/active/engine-catalog/codex-models.md) | reference | active | fact | 2026-07-16 | +| [GitHub Copilot — moteurs (modèles) et effort, catalogue + qui décide (CLI/VS Code et cloud agent)](md/active/engine-catalog/copilot-models.md) | reference | active | fact | 2026-07-16 | + +### `governance` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [SailPoint IdentityIQ (IIQ) — gouvernance d'accès et workflows d'approbation](md/active/governance/sailpoint-identityiq.md) | reference | active | fact | 2026-07-18 | +| [ServiceNow — tickets et workflow d'approbation (ITSM Change Management)](md/active/governance/servicenow-itsm-change-management.md) | reference | active | fact | 2026-07-18 | + +### `hybrid-identity` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Environnement hybride AD DS / Microsoft Entra ID — inventaire des impacts de sécurité à résoudre](md/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.md) | reference | draft | hypothesis | 2026-07-25 | + +### `powershell` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [PowerShell 5.1 strips quotes when passing JSON to native executables](md/active/powershell/native-exe-json-quoting.md) | pattern | active | fact | 2026-07-16 | + +### `security-architecture` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [AD DS Tier Model (Microsoft OSS) — référence historique/comparative, PAS le modèle cible](md/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.md) | reference | active | fact | 2026-08-08 | +| [AD DS — durcissement de l'administration Tier 0, Tier 1 et Tier 2](md/active/security-architecture/ad-ds-tiered-administration-hardening.md) | pattern | draft | hypothesis | 2026-07-25 | +| [Enterprise Access Model (EAM) — plans de sensibilité Microsoft](md/active/security-architecture/enterprise-access-model.md) | glossary | active | fact | 2026-07-18 | +| [Zero standing access, secretless, et gMSA — principes](md/active/security-architecture/zero-standing-access.md) | glossary | active | fact | 2026-07-18 | + +### `security-governance` + +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Référentiels sécurité — rôle dans une baseline AD DS et Windows Server](md/active/security-governance/security-framework-role-and-crosswalk.md) | reference | draft | hypothesis | 2026-07-25 | -## Thèmes disponibles +### `siem` -- `ad-ds` — Active Directory Domain Services (LDAP, .NET DirectoryServices, déploiement) -- `coreapi` — contexte et décisions architecturales du repo coreapi -- `powershell` — patterns PowerShell/Windows génériques (pas spécifiques à AD DS) +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Splunk CIM — modèles Authentication et Change](md/active/siem/splunk-cim-data-models.md) | reference | suspect | hypothesis | 2026-07-18 | -## Consommation +### `vscode-copilot` -Ce repo est monté comme submodule à `knowledge-base/` dans chaque repo consommateur : +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [GitHub Copilot — fusion automatique de fichiers d'instructions multiples](md/active/vscode-copilot/copilot-instructions-merge.md) | reference | active | fact | 2026-07-16 | +| [VS Code / GitHub Copilot Chat -- outils built-in (tools: frontmatter)](md/active/vscode-copilot/vscode-copilot-builtin-tools.md) | reference | active | fact | 2026-07-13 | -```bash -git submodule add knowledge-base -``` +### `windows-server` -Voir `CLAUDE.md` pour le schéma complet des fiches JSON. +| Fiche | Type | Statut | Confiance | Validée | +| - | - | - | - | - | +| [Windows Server 2022 et versions ultérieures — sources de baseline et règles d'adoption](md/active/windows-server/windows-server-2022-plus-hardening-source-baselines.md) | reference | draft | fact | 2026-07-25 | diff --git a/md/active/ad-ds-security/ad-ds-domain-controller-security-hardening.md b/md/active/ad-ds-security/ad-ds-domain-controller-security-hardening.md new file mode 100644 index 0000000..a97aac8 --- /dev/null +++ b/md/active/ad-ds-security/ad-ds-domain-controller-security-hardening.md @@ -0,0 +1,109 @@ +--- +id: ad-ds-domain-controller-security-hardening +type: pattern +title: Contrôleurs de domaine AD DS — durcissement de sécurité +theme: ad-ds-security +tags: + - domain-controller + - tier-0 + - windows-server + - hardening + - logging + - backup + - ldap-signing +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/securing-domain-controllers-against-attack + - https://learn.microsoft.com/en-us/windows-server/security/secured-core-server + - https://www.cyber.gov.au/business-government/asds-cyber-security-frameworks/ism/cyber-security-guidelines/guidelines-for-system-hardening + - https://www.cisa.gov/stopransomware/ransomware-guide + - https://messervices.cyber.gouv.fr/guides/mise-en-oeuvre-securisee-dun-serveur-windows + - https://adsecurity.org/?p=5036 + - https://adsecurity.org/?p=3377 +validated: 2026-07-25 +created: 2026-07-25 +links: + - windows-server-2022-plus-hardening-source-baselines + - ad-ds-tiered-administration-hardening + - ad-ds-threat-driven-control-map +--- + +# Position de sécurité + +Un contrôleur de domaine est un actif Tier 0. Il contient ou peut produire des secrets d'authentification, applique les politiques de domaine et participe au contrôle de tous les actifs dépendants de la forêt. + +# Baseline candidate + +## Plateforme + +- version Windows Server supportée et corrigée ; +- rôle dédié : aucun workload non nécessaire ; +- installation minimale compatible avec l'exploitation ; +- Secure Boot, TPM 2.0 et Secured-core lorsque supportés ; +- firmware, hyperviseur, console et stockage classés selon leur capacité de contrôle ; +- inventaire et approbation explicite de chaque agent installé. + +## Exposition + +- aucune navigation, messagerie ou usage bureautique ; +- absence d'accès Internet direct sauf exception documentée ; +- pare-feu local restrictif par rôle ; +- administration seulement depuis des chemins Tier 0 ; +- réduction des services, ports et protocoles hérités ; +- Print Spooler désactivé sauf besoin démontré ; +- LDAP signing et protections associées évaluées et imposées selon compatibilité ; +- SMB et RPC limités aux flux nécessaires. + +## Identités et privilèges + +- comptes d'administration dédiés, non utilisés ailleurs ; +- aucun compte partagé entre tiers ; +- groupes privilégiés minimisés et revus ; +- droits de logon locaux/distants restreints ; +- comptes de service dédiés et gMSA lorsque compatibles ; +- comptes de secours contrôlés, surveillés et testés ; +- MFA résistante au phishing sur les chemins qui le permettent, sans supposer que Windows logon natif protège à lui seul tous les accès. + +## Secrets + +- protection LSASS, Credential Guard/PPL et réduction de la délégation ; +- refus des secrets dans GPP, scripts et tâches ; +- gestion sécurisée de DSRM ; +- protection des clés, certificats, sauvegardes et copies de `NTDS.dit` ; +- contrôle strict des droits de réplication. + +## Journalisation et détection + +- politique d'audit avancée ; +- Directory Service Access/Changes avec SACL ciblées ; +- changements GPO, comptes, groupes, trusts, ACL et réplication ; +- événements PowerShell et outils d'administration ; +- centralisation vers une infrastructure protégée ; +- supervision des arrêts de collecte, effacements, baisses de volume et dérive. + +## Résilience + +- sauvegardes chiffrées, isolées et accessibles seulement aux rôles autorisés ; +- sauvegarde/hyperviseur considérés Tier 0 lorsqu'ils peuvent restaurer ou copier un DC ; +- plan de récupération de forêt testé ; +- synchronisation de temps, DNS et réplication surveillés ; +- procédures de remplacement d'un DC plutôt que réparation manuelle non maîtrisée. + +# Agents et outils de sécurité + +Un agent sur DC hérite d'un risque Tier 0 s'il peut exécuter du code, collecter des secrets ou modifier la configuration. Chaque agent EDR, monitoring, sauvegarde, inventaire ou gestion doit faire l'objet d'une analyse de privilège, de chaîne de mise à jour, de dépendance réseau et de compromission du plan de contrôle. + +# Non-conclusions + +Cette fiche ne décide pas : + +- quels agents précis sont approuvés ; +- si Server Core est obligatoire ; +- si tous les DC doivent être Secured-core ; +- les ports exacts autorisés ; +- l'outil de sauvegarde, SIEM ou PAM ; +- la cadence de patching finale. diff --git a/md/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.md b/md/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.md new file mode 100644 index 0000000..b4866fe --- /dev/null +++ b/md/active/ad-ds-security/ad-ds-domain-forest-gpo-security-baseline.md @@ -0,0 +1,91 @@ +--- +id: ad-ds-domain-forest-gpo-security-baseline +type: pattern +title: AD DS — baseline de sécurité des domaines, forêts et politiques GPO +theme: ad-ds-security +tags: + - ad-ds + - forest + - domain + - gpo + - trust + - authentication + - policy + - baseline +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory + - https://www.cyber.gc.ca/en/guidance/guidance-securing-microsoft-active-directory-services-your-organization-itsm60100 + - https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100 + - https://www.cyber.gov.au/business-government/detecting-responding-to-threats/detecting-and-mitigating-active-directory-compromises + - https://public.cyber.mil/stigs/downloads/ + - https://www.pingcastle.com/methodology/ +validated: 2026-07-25 +created: 2026-07-25 +links: + - ad-ds-security-hardening-study-synthesis + - ad-ds-domain-controller-security-hardening + - ad-ds-gpo-acl-lifecycle-governance + - ad-ds-threat-driven-control-map +--- + +# Principe + +La forêt est la frontière de sécurité AD DS principale. Une baseline domaine/forêt doit protéger les politiques d'authentification, les relations d'approbation, les privilèges, la réplication, la délégation et les mécanismes centraux de configuration. + +# Domaines de contrôle + +| Domaine | Contrôles attendus | +|---|---| +| Inventaire | Forêts, domaines, trusts, DC, sites, niveaux fonctionnels, propriétaires et dépendances | +| Gouvernance | Propriétaire de forêt/domaine, RACI, changements approuvés, exceptions, revue périodique | +| Politiques de compte | Mots de passe, verrouillage, Kerberos et stratégies affinées lorsque justifiées | +| Protocoles | LDAP signing/channel binding, réduction NTLM, SMB signing, Kerberos moderne, restrictions héritées | +| Trusts | Inventaire, finalité, propriétaire, SID filtering, selective authentication et revue | +| Comptes privilégiés | Groupes natifs, délégations, comptes dormants, comptes de secours, séparation des rôles | +| Réplication | Droits DCSync, comptes/objets DC, réplication non autorisée et surveillance | +| GPO | Baselines par rôle/tier, propriétaires, délégations, liens, filtres et journalisation | +| ACL | Domaine racine, OU, AdminSDHolder, objets de stratégie, délégations et droits étendus | +| Schéma/configuration | Modifications du schéma, Configuration NC, services d'identité associés | +| Détection | Changements AD/GPO/trust, événements d'authentification, réplication, comptes et ACL | +| Récupération | Sauvegardes protégées, restauration autoritaire/non autoritaire, plan de récupération forêt | + +# Architecture GPO candidate + +La structure suivante est un modèle à tester, pas une convention acquise : + +1. politiques de compte et Kerberos au niveau du domaine ; +2. baseline contrôleurs de domaine ; +3. baseline d'audit et journalisation ; +4. baseline protocoles et chiffrement ; +5. baselines Tier 0, Tier 1 et Tier 2 ; +6. baselines PAW et postes d'administration ; +7. baselines par rôle serveur lorsque nécessaires ; +8. GPO d'exception petites, temporaires et explicitement approuvées. + +Une GPO monolithique facilite rarement l'analyse d'impact, le retour arrière, la responsabilité ou la preuve. + +# Preuves minimales futures + +- export versionné des GPO et rapports lisibles ; +- empreinte de version et date d'application ; +- inventaire des liens, filtres et héritages ; +- propriétaires et ACL de chaque GPO ; +- résultat effectif (`gpresult`/RSoP ou équivalent) sur des actifs représentatifs ; +- événements de changement AD et SYSVOL ; +- évaluation par outil indépendant ; +- preuve de restauration de la configuration ; +- registre des exceptions avec expiration. + +# Questions à résoudre dans la future baseline + +- quelles politiques doivent rester dans les GPO par défaut ; +- quelle granularité de GPO optimise sécurité et opérabilité ; +- quels paramètres sont imposés par rôle/tier ; +- comment gérer les applications héritées ; +- quelles permissions sur les GPO, OU et liens sont acceptables ; +- comment corréler AD, SYSVOL et système de changement ; +- comment tester automatiquement l'héritage et les conflits. diff --git a/md/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.md b/md/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.md new file mode 100644 index 0000000..f6e2838 --- /dev/null +++ b/md/active/ad-ds-security/ad-ds-gpo-acl-lifecycle-governance.md @@ -0,0 +1,107 @@ +--- +id: ad-ds-gpo-acl-lifecycle-governance +type: pattern +title: AD DS — gouvernance du cycle de vie des GPO et ACL +theme: ad-ds-security +tags: + - gpo + - acl + - delegation + - ownership + - change-management + - evidence + - lifecycle +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/advanced-audit-policy-configuration + - https://public.cyber.mil/stigs/gpo/ + - https://attack.mitre.org/techniques/T1484/001/ + - https://adsecurity.org/?p=5061 + - https://www.trimarcsecurity.com/hub-post/securing-active-directory-performing-an-active-directory-security-review +validated: 2026-07-25 +created: 2026-07-25 +links: + - ad-ds-domain-forest-gpo-security-baseline + - ad-ds-tiered-administration-hardening + - ad-ds-threat-driven-control-map +--- + +# Principe + +Une GPO ou une ACL n'est pas seulement un paramètre : c'est un actif de contrôle. Son tier correspond au niveau maximal des objets qu'elle peut influencer. Son propriétaire, ses éditeurs, ses liens, SYSVOL et les outils qui la déploient font partie du chemin de contrôle. + +# Acteurs standards + +| Acteur | Responsabilité principale | +|---|---| +| Asset/Service Owner AD DS | Risque, priorité, acceptation et cycle de vie | +| Propriétaire forêt/domaine | Intégrité du périmètre et décisions structurantes | +| Équipe AD DS | Conception et exploitation de l'annuaire | +| Équipe Windows/OS | Baseline OS, patching, images et compatibilité | +| Gouvernance GPO | Catalogue, ownership, délégation, liens et version | +| IAM/IGA | Cycle de vie des identités et accès délégués | +| PAM | Chemins privilégiés, sessions, secrets et élévation | +| Sécurité architecture | Modèles de confiance, tiering et exigences | +| SOC/Detection Engineering | Sources, règles, alertes et investigation | +| Vulnerability/Patch | Vulnérabilités, priorisation et conformité | +| Backup/Recovery | Sauvegarde, restauration et tests de reprise | +| Réseau/DNS/PKI/Virtualisation | Dépendances pouvant modifier le niveau de contrôle | +| Change/Release | Approbation, calendrier, rollback et traçabilité | +| Audit/Risk/Compliance | Assurance indépendante et exceptions | +| Support | Diagnostic et escalade sans privilèges excessifs | +| Incident Response | Confinement, éradication et récupération | + +# Cycle de vie + +| Phase | Obligations | +|---|---| +| Concevoir | objectif, source, tier, population cible, dépendances, risques | +| Construire | environnement non production, propriétaire, ACL minimales, version | +| Vérifier | comparaison baseline, test fonctionnel, sécurité, héritage et conflits | +| Approuver | approbateurs, séparation des rôles et acceptation des écarts | +| Déployer | anneaux, fenêtre, preuve, sauvegarde et rollback | +| Exploiter | dérive, échecs d'application, événements et performance | +| Modifier | nouveau diff, revalidation et impact transverse | +| Répondre | identification rapide du changement et retour à un état sûr | +| Retirer | suppression des liens, archives, dépendances et preuve | +| Revoir | cadence, sources nouvelles, menace et versions OS | + +# ACL à gouverner + +- objets GPO dans AD ; +- fichiers et dossiers SYSVOL ; +- domaine racine et OU ; +- AdminSDHolder et objets protégés ; +- groupes privilégiés ; +- droits de réplication ; +- Extended Rights et propriétés sensibles ; +- comptes de service et SPN ; +- objets de confiance ; +- délégations de création, suppression, modification et lien de GPO. + +# Garde-fous candidats + +1. propriétaire autorisé et stable ; +2. éditeurs limités au tier cible ; +3. séparation création/approbation/déploiement ; +4. aucun héritage ou filtrage implicite non documenté ; +5. version/export avant changement ; +6. diff lisible et testable ; +7. journalisation AD et SYSVOL ; +8. détection de changement hors fenêtre ; +9. rollback testé ; +10. exception avec échéance ; +11. inventaire des GPO non liées, désactivées ou orphelines ; +12. revue périodique des droits de liaison et modification. + +# FAQ/support futures + +Cette fiche pourra alimenter notamment : + +- « Pourquoi une GPO liée aux DC est-elle Tier 0 ? » +- « Qui peut modifier une GPO sans être dans Domain Admins ? » +- « Pourquoi le résultat effectif diffère-t-il de la GPO attendue ? » +- « Comment distinguer problème de lien, filtrage, héritage ou réplication SYSVOL ? » diff --git a/md/active/ad-ds-security/ad-ds-security-control-assurance-levels.md b/md/active/ad-ds-security/ad-ds-security-control-assurance-levels.md new file mode 100644 index 0000000..55d2997 --- /dev/null +++ b/md/active/ad-ds-security/ad-ds-security-control-assurance-levels.md @@ -0,0 +1,84 @@ +--- +id: ad-ds-security-control-assurance-levels +type: pattern +title: AD DS — niveaux proposés de contrôle et d'assurance +theme: ad-ds-security +tags: + - baseline + - assurance + - control-levels + - maturity + - hardening + - evidence +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://www.nist.gov/cyberframework + - https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final + - https://www.cisecurity.org/controls/v8 + - https://www.cisecurity.org/benchmark/microsoft_windows_server + - https://public.cyber.mil/stigs/downloads/ + - https://www.pingcastle.com/methodology/ + - https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100 +validated: 2026-07-25 +created: 2026-07-25 +links: + - ad-ds-security-hardening-study-synthesis + - ad-ds-threat-driven-control-map + - security-framework-role-and-crosswalk +--- + +# Avertissement + +Ces niveaux sont une synthèse proposée pour organiser une future baseline. Ils ne correspondent pas directement à CIS Level 1/2, aux catégories STIG, aux niveaux ANSSI, aux Implementation Groups CIS ou à la maturité PingCastle. + +# Profils proposés + +| Niveau | Finalité | Exigences caractéristiques | +|---|---|---| +| B0 — Supported Foundation | Éliminer l'obsolescence et rendre l'actif maîtrisable | OS supporté, inventaire, propriétaire, patching, sauvegarde, logs minimaux, configuration connue | +| B1 — Enterprise Baseline | Établir une configuration standard défendable | baseline Microsoft, durcissement réseau/auth, audit avancé, Defender/EDR, LAPS, gestion de changement, dérive | +| B2 — Privileged / Tier-aware | Protéger les actifs administratifs et critiques | tiering, PAW, comptes dédiés, privilèges minimaux, chemins d'admin, GPO/ACL protégées, logs centralisés | +| B3 — High Assurance | Faire face à un contexte de menace élevé | Secured-core si supporté, application control strict, protocoles hérités fortement restreints, contrôles renforcés, restauration de forêt testée | +| B4 — Continuously Verified | Maintenir la confiance dans le temps | conformité automatisée, détection de dérive, tests de contrôle, attack-path management, preuves continues, exercices IR/recovery | + +# Règles d'utilisation + +1. Le niveau s'applique par actif ou classe d'actifs, pas uniquement à l'organisation entière. +2. Un actif doit satisfaire les niveaux inférieurs avant le niveau déclaré, sauf équivalence documentée. +3. Le niveau minimal dépend du pouvoir maximal de l'actif. +4. Un DC ou un système capable de le contrôler ne devrait pas rester à B0/B1. +5. La conformité d'un paramètre ne suffit pas : fonctionnement, preuve, détection et récupération sont nécessaires. +6. Les exceptions sont explicites, temporaires, approuvées et compensées. +7. Les contrôles doivent être mappés à une source, une menace, une méthode de vérification et une preuve. +8. Les profils sont révisés lors des changements de version, rôle, menace ou dépendance. + +# Axes d'assurance + +Chaque niveau doit être évalué sur les six fonctions NIST CSF 2.0 : + +- Govern ; +- Identify ; +- Protect ; +- Detect ; +- Respond ; +- Recover. + +Une baseline très forte en `Protect` mais faible en `Detect` ou `Recover` ne constitue pas un haut niveau d'assurance global. + +# Exemple d'application à valider + +| Actif | Niveau minimal candidat | +|---|---| +| Contrôleur de domaine | B2, B3 selon menace/criticité | +| PAW Tier 0 | B2/B3 | +| Entra Connect / PTA / AD FS | B2/B3 | +| Serveur membre Tier 1 | B1, B2 si contrôle étendu | +| Poste support Tier 2 | B1/B2 | +| Poste utilisateur standard | B1 | +| Infrastructure de récupération forêt | B2/B3 | +| Système de preuve continue | B4 pour les contrôles qu'il mesure | + +Ces affectations sont proposées pour revue et ne constituent pas encore une politique. diff --git a/md/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.md b/md/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.md new file mode 100644 index 0000000..c69de29 --- /dev/null +++ b/md/active/ad-ds-security/ad-ds-security-hardening-study-synthesis.md @@ -0,0 +1,109 @@ +--- +id: ad-ds-security-hardening-study-synthesis +type: reference +title: Étude indépendante — durcissement Windows Server et sécurité AD DS +theme: ad-ds-security +tags: + - ad-ds + - hardening + - windows-server + - gpo + - acl + - tiering + - baseline + - study +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory + - https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100 + - https://www.cyber.gov.au/business-government/detecting-responding-to-threats/detecting-and-mitigating-active-directory-compromises + - https://messervices.cyber.gouv.fr/guides/recommandations-pour-ladministration-securisee-des-si-reposant-sur-ad +validated: 2026-07-25 +created: 2026-07-25 +links: + - windows-server-2022-plus-hardening-source-baselines + - ad-ds-domain-forest-gpo-security-baseline + - ad-ds-domain-controller-security-hardening + - ad-ds-tiered-administration-hardening + - ad-ds-gpo-acl-lifecycle-governance + - ad-ds-threat-driven-control-map + - ad-ds-security-control-assurance-levels + - hybrid-identity-entra-security-impact-inventory + - security-framework-role-and-crosswalk +--- + +# Objet + +Étude technique et sécurité indépendante de tout produit. Elle vise à établir les fondations d'une future baseline versionnée couvrant : + +- Windows Server 2022 et versions ultérieures ; +- forêts, domaines et politiques de sécurité AD DS ; +- contrôleurs de domaine ; +- Tier 0, Tier 1 et Tier 2 ; +- GPO, délégations et ACL ; +- acteurs et responsabilités sur tout le cycle de vie ; +- niveaux gradués de contrôle et d'assurance ; +- impacts d'un environnement hybride Microsoft Entra ID, identifiés sans choix de solution. + +# Méthode mA.xI.me améliorée + +## SPEC + +Le besoin est une connaissance générique, technique et sécurité. Aucun dépôt produit, aucune architecture applicative et aucune contrainte client ne déterminent les conclusions. + +## ALIGN-ÉTUDE + +L'étude est alignée sur : + +1. le rôle réel de chaque source ; +2. les versions Windows Server concernées ; +3. la séparation OS / AD DS / administration / détection / récupération ; +4. la distinction entre fait normatif, recommandation et synthèse proposée ; +5. la nécessité de tester toute baseline en environnement représentatif ; +6. la production de fiches granulaires plutôt qu'un document monolithique. + +## PLAN + +Les domaines sont séparés en fiches liées : sources OS, domaine/forêt, DC, tiering, gouvernance GPO/ACL, menaces, niveaux d'assurance, hybride et rôle des référentiels. + +## LIVRABLE + +Les fiches de cette branche restent `draft`. Elles décrivent une baseline cible et les décisions de conception à prendre, mais ne constituent pas encore des GPO, ACL ou scripts applicables. + +## VERIFY + +Chaque axe a été confronté à plusieurs familles de sources : Microsoft, NIST, CIS, DISA, ANSSI, CCCS, ASD/ACSC, CISA, MITRE ATT&CK, PingCastle et expertise AD indépendante. + +## REVIEW → IMPROVE + +### Boucle 1 + +- **COMPARE** : les référentiels ne jouent pas le même rôle. +- **REVIEW** : une fusion naïve de toutes les recommandations produit des contradictions, des doublons et des paramètres non supportés. +- **IMPROVE** : séparer sources normatives, guides de configuration, modèles de menace, gouvernance et conformité. + +### Boucle 2 + +- **RECOMPARE** : une baseline unique ne couvre pas correctement DC, Tier 0, serveurs Tier 1 et postes Tier 2. +- **REVIEW** : le niveau de contrôle dépend du pouvoir de l'actif, de son rôle et de la menace. +- **IMPROVE** : utiliser des profils par rôle/tier et des niveaux d'assurance, avec héritage et exceptions explicites. + +# Conclusions structurantes + +1. Le durcissement AD DS n'est pas une simple liste de paramètres OS. +2. La forêt constitue la frontière de sécurité principale ; un compromis de contrôle dans un domaine peut menacer la forêt entière. +3. Les GPO et leurs ACL sont elles-mêmes des actifs de contrôle et doivent être classées selon le niveau maximal des cibles qu'elles peuvent modifier. +4. Les systèmes capables d'administrer, sauvegarder, restaurer, virtualiser, synchroniser ou surveiller avec privilèges un DC héritent d'une sensibilité Tier 0. +5. La prévention doit être complétée par détection, réponse et récupération. +6. Les paramètres doivent être versionnés par OS, rôle, tier, niveau d'assurance et état de compatibilité. +7. L'hybridation Entra étend le control plane et introduit des dépendances bidirectionnelles qui doivent faire l'objet d'une étude dédiée avant arbitrage. + +# Limites + +- Aucun paramètre GPO détaillé n'est déclaré directement applicable en production. +- Aucun benchmark CIS ou STIG propriétaire n'est reproduit. +- Les exigences sectorielles ne s'appliquent que si l'organisation relève de leur champ. +- Les niveaux proposés sont une synthèse de travail ; ils ne sont pas équivalents aux niveaux CIS, DISA, ANSSI ou PingCastle. diff --git a/md/active/ad-ds-security/ad-ds-threat-driven-control-map.md b/md/active/ad-ds-security/ad-ds-threat-driven-control-map.md new file mode 100644 index 0000000..06215e1 --- /dev/null +++ b/md/active/ad-ds-security/ad-ds-threat-driven-control-map.md @@ -0,0 +1,79 @@ +--- +id: ad-ds-threat-driven-control-map +type: reference +title: AD DS — carte menaces vers domaines de contrôle +theme: ad-ds-security +tags: + - mitre-attack + - kerberoasting + - dcsync + - golden-ticket + - password-spraying + - gpo + - detection +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://attack.mitre.org/techniques/T1558/003/ + - https://attack.mitre.org/techniques/T1558/001/ + - https://attack.mitre.org/techniques/T1003/006/ + - https://attack.mitre.org/techniques/T1003/003/ + - https://attack.mitre.org/techniques/T1110/003/ + - https://attack.mitre.org/techniques/T1484/001/ + - https://www.cyber.gov.au/business-government/detecting-responding-to-threats/detecting-and-mitigating-active-directory-compromises + - https://www.cisa.gov/stopransomware/ransomware-guide + - https://www.pingcastle.com/methodology/ + - https://www.trimarcsecurity.com/hub-post/securing-active-directory-performing-an-active-directory-security-review +validated: 2026-07-25 +created: 2026-07-25 +links: + - ad-ds-domain-controller-security-hardening + - ad-ds-domain-forest-gpo-security-baseline + - ad-ds-security-control-assurance-levels +--- + +# Usage + +Cette carte relie des techniques d'attaque documentées à des domaines de contrôle. Elle ne constitue ni un playbook offensif ni une garantie de couverture. + +| Menace | Risque principal | Contrôles préventifs | Détection/assurance | +|---|---|---|---| +| Password spraying — T1110.003 | Acquisition de comptes sans verrouillage massif | mots de passe résistants, MFA disponible, réduction surfaces auth, comptes admin distincts | corrélation multi-comptes, faible fréquence, on-prem et cloud | +| Kerberoasting — T1558.003 | Cassage hors ligne de tickets de comptes SPN | gMSA, secrets longs, AES, réduction SPN/privilèges | requêtes TGS anormales, inventaire SPN et comptes à risque | +| Golden Ticket — T1558.001 | Forge de TGT après compromission KRBTGT | protection Tier 0, DC, réplication, sauvegardes, secrets | signaux Kerberos, comportements impossibles, procédure de récupération KRBTGT | +| DCSync — T1003.006 | Extraction des secrets par droits de réplication | réduction/audit des droits de réplication, comptes DC protégés | opérations de réplication depuis acteurs non autorisés | +| Vol/copie NTDS — T1003.003 | Extraction hors ligne de la base et secrets | DC/backup/hyperviseur Tier 0, accès stockage strict | usages VSS/ntdsutil, accès sauvegardes, copies anormales | +| Modification GPO — T1484.001 | Exécution, persistance ou affaiblissement à grande échelle | ownership/ACL GPO, séparation des rôles, change control | changements AD + SYSVOL, propriétaire/ACL/lien modifiés | +| Création de compte domaine — T1136.002 | Persistance et privilèges | délégations minimales, workflows, groupes contrôlés | 4720, création LDAP, élévation rapide ou usage inattendu | +| Modification de trust — T1484.002 | Extension de confiance ou contournement | gouvernance trust, SID filtering, selective authentication | changements objets de trust et configuration | +| Pass-the-Hash/Ticket | Mouvement latéral et réutilisation de secrets | tiering, PAW, Credential Guard, Remote Credential Guard, restrictions logon | authentifications et sessions inter-tiers anormales | +| Compromission hybride | Pivot AD ↔ Entra | protection composants sync/fédération et rôles cloud | changements de méthode auth, sync, fédération et rôles | + +# Défense en profondeur + +Chaque menace doit être traitée par plusieurs familles : + +1. réduire la surface ; +2. protéger les identités et secrets ; +3. limiter le rayon d'action ; +4. détecter l'abus ; +5. préserver des preuves ; +6. contenir et répondre ; +7. restaurer un état de confiance. + +# Assurance + +Les scores PingCastle et autres outils servent à découvrir et prioriser. Ils ne remplacent pas : + +- l'inventaire des propriétaires ; +- le modèle de menace ; +- les tests de contrôles ; +- la revue des exceptions ; +- la preuve de récupération ; +- la surveillance continue. + +# Limites + +Les événements et règles détaillés doivent être adaptés à la version Windows, au mode d'authentification, aux volumes et aux outils de collecte. Une absence d'alerte ne prouve pas l'absence d'attaque. diff --git a/md/active/ad-ds/reference.md b/md/active/ad-ds/reference.md new file mode 100644 index 0000000..08a2adc --- /dev/null +++ b/md/active/ad-ds/reference.md @@ -0,0 +1,927 @@ +--- +id: reference +type: reference +title: AD DS Reference +theme: ad-ds +tags: + - acl + - auth + - dotnet + - kerberos + - ldap + - rest-api +scope: global +status: active +confidence: fact +audience: generic +source: + - ouritres/coreapi/.claude/knowledge-base/ad-ds-reference.md + - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/d2435927-0999-4c62-8c6d-13ba31a52e1a + - https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.protocols + - https://github.com/dotnet/dotnet-api-docs + - https://github.com/KopiCloud-AD-API + - ouritres/coreapi/.claude/handoff/spec-0-status.md +validated: 2026-07-16 +created: 2026-06-16 +links: + - unattended-deployment +--- + +# AD DS Reference + +## Key protocol specifications + +| Protocol | Code | What it covers | URL | +|----------|------|---------------|-----| +| Active Directory Technical Spec | MS-ADTS | Core AD schema, LDAP extensions, Kerberos integration, replication | https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/d2435927-0999-4c62-8c6d-13ba31a52e1a | +| SAM Remote Protocol | MS-SAMR | User, group, and computer account management operations | https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-samr/4df07fab-1bbc-452f-8e92-7853a3c7e380 | +| Kerberos Protocol Extensions | MS-KILE | Windows-specific Kerberos extensions, PAC, S4U | https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/2a32282e-dd48-4ad9-a542-609804b02cc9 | +| LSAD Remote Protocol | MS-LSAD | Local Security Authority domain policy, trust management | https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lsad/1b5471ef-4c33-4a91-b079-dfcbb82f05cc | +| Authorization Protocols Overview | MS-AUTHSOD | How Windows evaluates access tokens and ACLs | https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-authsod/953992f8-4f5e-4f6a-a2d1-24d95d188d72 | +| Windows Protocols top level | MS-WINPROTLP | Index of all Windows protocols | https://learn.microsoft.com/en-us/openspecs/windows_protocols/MS-WINPROTLP/92b33e19-6fff-496b-86c3-d168206f9845 | + +--- + +## Canonical LDAP attribute names + +These are case-sensitive in filter construction and must match exactly. + +### User attributes + +| Attribute | Type | Notes | +|-----------|------|-------| +| `sAMAccountName` | String | Logon name (pre-Win2000). Max 20 chars. Unique per domain. | +| `userPrincipalName` | String | UPN: `user@domain.com`. Must be unique in forest. | +| `distinguishedName` | DN | Full path: `CN=John,OU=Users,DC=corp,DC=local`. Read-only via LDAP writes — set implicitly by placement. | +| `cn` | String | Common Name. Used as the RDN in the DN. | +| `displayName` | String | Display name in UI. | +| `givenName` | String | First name. | +| `sn` | String | Surname / last name. | +| `mail` | String | Email address. Not enforced unique by AD (only Exchange enforces uniqueness). | +| `telephoneNumber` | String | Primary phone. | +| `department` | String | Department. | +| `title` | String | Job title. | +| `manager` | DN | DN of the manager object. | +| `memberOf` | DN (multi) | Groups the user belongs to. **Read-only** — manage via group's `member` attribute. | +| `userAccountControl` | Integer | Bitmask controlling account state. See flags below. | +| `accountExpires` | LargeInteger | Windows FILETIME. 0 or `9223372036854775807` = never expires. | +| `pwdLastSet` | LargeInteger | Set to 0 to force password change; -1 to clear the force-change flag. | +| `objectSid` | SID | Security Identifier. Binary. Immutable once created. | +| `objectGUID` | GUID | Globally unique. Binary. Use for stable cross-rename references. | +| `objectClass` | String (multi) | Always includes `top`, `person`, `organizationalPerson`, `user` for user objects. | +| `whenCreated` | GeneralizedTime | UTC creation time. Format: `YYYYMMDDHHmmss.0Z` | +| `whenChanged` | GeneralizedTime | UTC last-modified time. | + +### userAccountControl flags (most relevant) + +| Flag | Value (hex) | Meaning | +|------|------------|---------| +| `ACCOUNTDISABLE` | 0x0002 | Account disabled | +| `HOMEDIR_REQUIRED` | 0x0008 | Home directory required | +| `LOCKOUT` | 0x0010 | Account locked out | +| `PASSWD_NOTREQD` | 0x0020 | No password required | +| `PASSWD_CANT_CHANGE` | 0x0040 | User cannot change password | +| `NORMAL_ACCOUNT` | 0x0200 | Standard user account (always set for users) | +| `DONT_EXPIRE_PASSWD` | 0x10000 | Password never expires | +| `SMARTCARD_REQUIRED` | 0x40000 | Smart card required for logon | +| `TRUSTED_FOR_DELEGATION` | 0x80000 | Kerberos unconstrained delegation | +| `NOT_DELEGATED` | 0x100000 | Account is sensitive, cannot be delegated | +| `PASSWORD_EXPIRED` | 0x800000 | Password has expired | + +A normal enabled account = `0x200` (512 decimal). A normal disabled account = `0x202` (514). + +### Service account attributes (differences from users) + +Service accounts are user objects (`objectClass: user`) with specific conventions: +- Typically placed in a dedicated OU (e.g., `OU=ServiceAccounts,DC=corp,DC=local`) +- `servicePrincipalName` (multi-value): SPNs registered for Kerberos delegation. Format: `ServiceClass/FQDN:Port` +- `userAccountControl` typically includes `DONT_EXPIRE_PASSWD` (`0x10200`) +- `description` should document the owning application +- For gMSA: `objectClass` includes `msDS-GroupManagedServiceAccount`; password managed automatically by AD +- For sMSA: `objectClass` includes `msDS-ManagedServiceAccount`; bound to a single computer + +### Group attributes + +| Attribute | Notes | +|-----------|-------| +| `cn` | Group name | +| `sAMAccountName` | Pre-Win2000 name. Same value as `cn` typically. | +| `member` | Multi-value DN list of members. **Write here to add/remove members.** | +| `memberOf` | Groups this group belongs to (nesting). Read-only. | +| `groupType` | Bitmask: scope (local/global/universal) + type (security/distribution). See below. | +| `description` | Free-text description. | +| `mail` | Email for mail-enabled groups. | + +### groupType bitmask values + +| Type | Value (hex) | Notes | +|------|------------|-------| +| Global Security | 0x80000002 | Most common for user groups | +| Domain Local Security | 0x80000004 | Resource access groups | +| Universal Security | 0x80000008 | Cross-domain | +| Global Distribution | 0x00000002 | Mail distribution only | + +### OU attributes + +| Attribute | Notes | +|-----------|-------| +| `ou` | The OU name (used as RDN) | +| `name` | Same as `ou` | +| `description` | Free text | +| `gPLink` | GPOs linked to this OU | + +--- + +## LDAP filter syntax + +### Operators + +| Operator | Syntax | Example | +|----------|--------|---------| +| Equality | `(attr=value)` | `(sAMAccountName=jsmith)` | +| Presence | `(attr=*)` | `(mail=*)` | +| Substring | `(attr=*sub*)` | `(cn=John*)` | +| AND | `(&(...)(...))` | `(&(objectClass=user)(department=IT))` | +| OR | `(\|(...)(...))` | `(\|(sAMAccountName=a)(sAMAccountName=b))` | +| NOT | `(!(...))` | `(!(userAccountControl:1.2.840.113556.1.4.803:=2))` | +| Bitwise AND (extensible) | `(attr:1.2.840.113556.1.4.803:=value)` | Used for `userAccountControl` flag checks | +| Bitwise OR (extensible) | `(attr:1.2.840.113556.1.4.803:=value)` | Less common | + +### Common filters + +``` +# All enabled users +(&(objectClass=user)(objectCategory=person)(!(userAccountControl:1.2.840.113556.1.4.803:=2))) + +# All disabled users +(&(objectClass=user)(objectCategory=person)(userAccountControl:1.2.840.113556.1.4.803:=2)) + +# User by sAMAccountName +(&(objectClass=user)(sAMAccountName=jsmith)) + +# All security groups +(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=2147483648)) + +# Members of a specific group (direct only) +(&(objectClass=user)(memberOf=CN=MyGroup,OU=Groups,DC=corp,DC=local)) + +# Service accounts (by OU) +(&(objectClass=user)(distinguishedName=*OU=ServiceAccounts*)) + +# All OUs under a base +(objectClass=organizationalUnit) +``` + +### LDAP injection prevention + +**Never build filters by string concatenation.** Always escape user-supplied values. + +Characters that must be escaped in filter values: + +| Character | Escaped form | +|-----------|-------------| +| `*` | `\2a` | +| `(` | `\28` | +| `)` | `\29` | +| `\` | `\5c` | +| `NUL` | `\00` | + +In .NET with `System.DirectoryServices.Protocols`, use `DirectoryAttributeModification` and parameterized `SearchRequest` with escaped values. Never use `string.Format` or interpolation to build filter strings. + +--- + +## ACL / DACL structure in AD + +AD security is based on Windows Security Descriptors (defined in MS-DTYP). Key concepts: + +- **Security Descriptor**: attached to every AD object. Contains Owner SID, Group SID, DACL, SACL. +- **DACL** (Discretionary ACL): list of ACEs that control access. Order matters — DENY ACEs evaluated before ALLOW. +- **SACL** (System ACL): auditing rules. Requires `SeSecurityPrivilege` to read/write. +- **ACE** (Access Control Entry): `(Type, Flags, Rights, ObjectType, InheritedObjectType, SID)` + - Type: Allow or Deny + - Rights: bitmask of `ActiveDirectoryRights` values + - ObjectType GUID: scopes the ACE to a specific attribute or object class (property-specific ACEs) + - Inheritance flags: whether ACE propagates to child objects + +### ActiveDirectoryRights values (most used) + +| Right | Notes | +|-------|-------| +| `GenericAll` | Full control | +| `GenericRead` | Read all properties + list object | +| `ReadProperty` | Read a specific property (use with ObjectType GUID) | +| `WriteProperty` | Write a specific property | +| `CreateChild` | Create child objects (use with ObjectType = object class GUID) | +| `DeleteChild` | Delete child objects | +| `DeleteTree` | Delete object and all children | +| `ExtendedRight` | Extended rights (reset password, etc.) — use with ObjectType = right GUID | +| `WriteDacl` | Modify the DACL | +| `WriteOwner` | Change owner | + +### Common extended right GUIDs + +| Right | GUID | +|-------|------| +| Reset Password | `00299570-246d-11d0-a768-00aa006e0529` | +| Force Change Password | `00299570-246d-11d0-a768-00aa006e0529` | +| Add/Remove self as member | `bf9679c0-0de6-11d0-a285-00aa003049e2` | +| Send As | `ab721a54-1e2f-11d0-9819-00aa0040529b` | +| Receive As | `ab721a56-1e2f-11d0-9819-00aa0040529b` | + +### Reading ACLs in .NET + +```csharp +// Using System.DirectoryServices +using var entry = new DirectoryEntry($"LDAP://CN=user,OU=Users,DC=corp,DC=local"); +var security = entry.ObjectSecurity; +var dacl = security.GetAccessRules(true, true, typeof(SecurityIdentifier)); +``` + +**Important:** `GetAccessRules(includeExplicit, includeInherited, ...)` — always pass `true` for both unless you intentionally want to exclude inherited ACEs. + +--- + +## Kerberos / LDAP connection notes for .NET + +- `LdapConnection` from `System.DirectoryServices.Protocols` is the correct class for raw LDAP. +- `LdapDirectoryIdentifier` takes host and port (default 389 for LDAP, 636 for LDAPS, 3268 for GC, 3269 for GC over SSL). +- For Kerberos auth: use `AuthType.Kerberos` with `NetworkCredential`. On Linux, requires a valid keytab or ticket cache. +- For simple bind (service account): use `AuthType.Basic` over LDAPS only — never over plain LDAP. + **Username format matters:** AD DS simple bind accepts a UPN (`user@domain.com`) or a full DN — it does **not** accept the NetBIOS `DOMAIN\user` form, which will fail the bind. Confirmed 2026-07-16 (coreapi regression: a WIP change had switched the bind username to NetBIOS format, breaking `DirectoryConnectionTests` against a real DC; reverting to UPN fixed it). +- `DirectoryServices.AccountManagement` (`PrincipalContext`) is a higher-level wrapper but loses precision for complex filters and ACL operations. Prefer it for Spec 4/5/6 user/group CRUD, avoid it for Spec 7 ACL work. +- TLS: set `LdapSessionOptions.SecureSocketLayer = true` for LDAPS. For StartTLS, use `StartTransportLayerSecurity()`. +- Connection timeout: set `LdapConnection.Timeout` — default is infinite. Always set explicitly. + +--- + +## LDAP port reference + +| Port | Protocol | Use | +| --- | --- | --- | +| 389 | LDAP | Standard — use StartTLS before binding | +| 636 | LDAPS | LDAP over SSL/TLS | +| 3268 | GC LDAP | Global Catalog — cross-domain searches (read only) | +| 3269 | GC LDAPS | Global Catalog over SSL | + +--- + +## AD DS logical structure and DN conventions + +The hierarchy from largest to smallest: **Forest → Tree → Domain → Site → OU → Object**. + +DN construction rules: + +- Each DNS label of the domain name becomes one `DC=` component. `corp.local` → `DC=corp,DC=local`. +- Child domain `child.corp.local` → `DC=child,DC=corp,DC=local`. +- DN reads right-to-left: the rightmost component is the forest root. +- OU path in the DN is bottom-up: `OU=Paris,OU=France,OU=EMEA` means EMEA contains France contains Paris. +- Regular containers (not OUs) use `CN=` — e.g. the built-in `CN=Users,DC=corp,DC=local`. +- Object placement determines the `distinguishedName` — changing OU requires a Move operation (LDAP ModifyDN), not an attribute write. + +--- + +## AD naming contexts (partitions) + +Every DC exposes these partitions. Query RootDSE to discover them programmatically. + +| Partition | Base DN | Contains | +| --- | --- | --- | +| Domain NC | `DC=corp,DC=local` | Users, groups, computers, OUs — all day-to-day objects | +| Configuration NC | `CN=Configuration,DC=corp,DC=local` | Forest-wide: sites, services, schema links, partitions | +| Schema NC | `CN=Schema,CN=Configuration,DC=corp,DC=local` | Class and attribute definitions | +| Application NC (example) | `DC=DomainDnsZones,DC=corp,DC=local` | Optional, e.g. AD-integrated DNS zones | + +--- + +## RootDSE — discovery attributes + +Always query empty string `""` with `SearchScope.Base` to bootstrap connection config: + +| Attribute | Value example | Use | +| --- | --- | --- | +| `defaultNamingContext` | `DC=corp,DC=local` | Base DN for domain searches | +| `configurationNamingContext` | `CN=Configuration,DC=corp,DC=local` | Sites, services, partitions | +| `schemaNamingContext` | `CN=Schema,CN=Configuration,DC=corp,DC=local` | Schema queries | +| `rootDomainNamingContext` | `DC=corp,DC=local` | Forest root domain | +| `domainFunctionality` | `7` | Domain Functional Level (0=2000 … 7=2016+) | +| `forestFunctionality` | `7` | Forest Functional Level | +| `highestCommittedUSN` | `12345678` | Current USN — baseline for change tracking | +| `supportedSASLMechanisms` | `GSSAPI GSS-SPNEGO` | Available auth methods | +| `dsServiceName` | DN of the DC | Identifies which DC you're talking to | + +--- + +## Global Catalog + +- Holds a **partial attribute set** from every domain in the forest — enough to locate and identify objects. +- Attributes replicated to GC have `isMemberOfPartialAttributeSet = TRUE` in the schema. +- **Read-only via GC port** — writes must go to the object's home domain DC. +- Use GC (3268/3269) when: searching across domains, resolving UPN to domain, or locating a user without knowing their domain. +- Common attributes in GC: `sAMAccountName`, `userPrincipalName`, `mail`, `displayName`, `objectSid`, `objectGUID`, `memberOf`. +- Attributes often NOT in GC: custom/extended attributes, `thumbnailPhoto`, operational attributes. + +--- + +## FSMO roles — relevance for LDAP code + +Five roles, two scopes: + +**Per-forest (one DC total):** + +- **Schema Master**: only DC that accepts schema modifications. Target explicitly for schema extension operations. +- **Domain Naming Master**: manages adding/removing domains. Not relevant for application LDAP. + +**Per-domain (one DC per domain):** + +- **PDC Emulator**: handles password change replication, account lockout propagation, and is the authoritative time source. **Always target the PDC Emulator for password set/reset operations** and for reading the most current lockout state. +- **RID Master**: allocates RID pools for SID generation. No direct LDAP operation impact. +- **Infrastructure Master**: maintains cross-domain group membership phantoms. Relevant only when group members span multiple domains. + +Finding the PDC Emulator: query `fSMORoleOwner` attribute on the domain NC root object, or read `pdcEmulatorName` from a Windows-side API. In code, connect to the target DC and query its RootDSE `dsServiceName`, then compare to the `fSMORoleOwner` on the domain object. + +--- + +## LDAP controls for production searches + +Register controls on `SearchRequest.Controls` before sending. + +| Control | OID | Purpose | +| --- | --- | --- | +| Paged Results | `1.2.840.113556.1.4.319` | Required for result sets > 1000. Use `PageResultRequestControl`. | +| Sort | `1.2.840.113556.1.4.473` | Server-side sort. Combine with paged results. | +| DirSync | `1.2.840.113556.1.4.841` | Incremental change feed. Requires `DS-Replication-Get-Changes`. | +| Show Deleted | `1.2.840.113556.1.4.417` | Include tombstoned objects in results. | +| Show Recycled | `1.2.840.113556.1.4.2064` | Include recycled objects (AD Recycle Bin enabled). | +| SD Flags | `1.2.840.113556.1.4.801` | Control which SD parts are returned. Flags: 1=Owner, 2=Group, 4=DACL, 8=SACL. | + +Paged search pattern: + +```csharp +var pageControl = new PageResultRequestControl(pageSize: 1000); +request.Controls.Add(pageControl); +do { + var response = (SearchResponse)connection.SendRequest(request); + var pageResponse = (PageResultResponseControl)response.Controls + .OfType().FirstOrDefault(); + // process response.Entries + pageControl.Cookie = pageResponse?.Cookie ?? Array.Empty(); +} while (pageControl.Cookie.Length > 0); +``` + +--- + +## Object lifecycle — deletion, tombstones, Recycle Bin + +**Standard deletion (no Recycle Bin):** + +- Object is converted to a tombstone: moved to `CN=Deleted Objects,DC=corp,DC=local`, `isDeleted=TRUE`, most attributes stripped. +- Tombstone lifetime: default 180 days. After that, permanently purged. + +**AD Recycle Bin** (requires Forest Functional Level 2008 R2 / level 4+): + +- Deleted objects retain ALL attributes. `isDeleted=TRUE`, `isRecycled` NOT set. +- Fully recycled objects (past recycle stage): `isDeleted=TRUE` AND `isRecycled=TRUE`. +- Original OU stored in `msDS-LastKnownRDN`. +- Restore: clear `isDeleted`, move back to original OU — requires `Recycle-a-Deleted-Object` extended right (GUID `69ae6200-7f46-11d2-b9ad-00c04f79f805`). + +Search for deleted objects: + +```csharp +var request = new SearchRequest( + "CN=Deleted Objects,DC=corp,DC=local", + "(&(isDeleted=TRUE)(cn=TargetUser*))", + SearchScope.OneLevel, null); +request.Controls.Add(new ShowDeletedControl()); +``` + +--- + +## LDAP referrals + +When a DC receives a search that spans domain boundaries, it may return LDAP referrals (pointers to other DCs). + +- `LdapConnection` follows referrals by default (`ReferralChasingOptions.All`). +- Referral chasing reuses the same credentials — will fail across untrusted domains or when the referred DC is unreachable. +- Disable when search scope is intentionally single-domain: + +```csharp +connection.SessionOptions.ReferralChasing = ReferralChasingOptions.None; +``` + +- For cross-domain searches, prefer the **Global Catalog (port 3268)** instead of chasing referrals. + +--- + +## Schema queries + +To discover class or attribute definitions at runtime: + +```text +BaseDN: CN=Schema,CN=Configuration,DC=corp,DC=local +Scope: OneLevel + +Class definition: + Filter: (&(objectClass=classSchema)(lDAPDisplayName=user)) + Attributes: subClassOf, systemMustContain, systemMayContain, mustContain, mayContain + +Attribute definition: + Filter: (&(objectClass=attributeSchema)(lDAPDisplayName=sAMAccountName)) + Attributes: attributeSyntax, oMSyntax, isSingleValued, rangeLower, rangeUpper, schemaIDGUID +``` + +`objectClass` hierarchy for common types: + +- user → organizationalPerson → person → top +- group → top +- organizationalUnit → top +- computer → user → organizationalPerson → person → top (computers are a subclass of user) + +--- + +## Password policies + +**Default Domain Password Policy** — one per domain, applied to all accounts without a PSO. +Read from the domain NC root object (`DC=corp,DC=local`): `pwdHistoryLength`, `maxPwdAge`, `minPwdAge`, `minPwdLength`, `lockoutThreshold`, `lockoutDuration`, `lockoutObservationWindow`. + +**Fine-Grained Password Policy (PSO)** — requires Domain Functional Level 2008 (level 3+): + +- Stored in: `CN=Password Settings Container,CN=System,DC=corp,DC=local` +- Object class: `msDS-PasswordSettings` +- Applied to users/groups via: `msDS-PSOAppliesTo` (multi-value DN) +- Resultant PSO for a user: read `msDS-ResultantPSO` attribute on the user object (computed by DC, not stored) +- PSO with lowest `msDS-PasswordSettingsPrecedence` value wins when multiple PSOs apply + +--- + +## Tracking changes (USN / DirSync) + +**USN-based polling** (simpler, no special rights): + +- Every write increments the DC's USN. Each object stores `uSNChanged` and `uSNCreated`. +- Baseline: read `highestCommittedUSN` from RootDSE at startup. +- Poll with filter: `(uSNChanged>=)` ordered by `uSNChanged` ascending. Update baseline after each batch. +- Limitation: USNs are per-DC. If load-balanced across DCs, track USN per target DC. + +**DirSync control** (replication-style, requires `DS-Replication-Get-Changes` extended right): + +- Returns only changed objects/attributes since the last cookie. +- Cookie is opaque and DC-specific — store and reuse per target DC. +- Use OID `1.2.840.113556.1.4.841` with `DirectorySynchronizationOptions` in `System.DirectoryServices.Protocols`. + +--- + +## Microsoft Learn reference URLs + +| Topic | URL | +| --- | --- | +| AD DS Overview | [AD DS Overview on Microsoft Learn](https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/get-started/virtual-dc/active-directory-domain-services-overview) | +| Win32 AD Programming Guide | [Using AD DS — Win32 apps](https://learn.microsoft.com/en-us/windows/win32/ad/using-active-directory-domain-services) | +| Searching in AD DS (Win32) | [Searching in Active Directory Domain Services](https://learn.microsoft.com/en-us/windows/win32/ad/searching-in-active-directory-domain-services) | +| Creating and Deleting Objects | [Creating and Deleting Objects in AD DS](https://learn.microsoft.com/en-us/windows/win32/ad/creating-and-deleting-objects-in-active-directory-domain-services) | +| Controlling Access to Objects | [Controlling Access to Objects in AD DS](https://learn.microsoft.com/en-us/windows/win32/ad/controlling-access-to-objects-in-active-directory-domain-services) | +| Global Catalog (Win32) | [Global Catalog — Win32 reference](https://learn.microsoft.com/en-us/windows/win32/ad/global-catalog) | +| Application Directory Partitions | [Application Directory Partitions](https://learn.microsoft.com/en-us/windows/win32/ad/application-directory-partitions) | +| Tracking Changes (DirSync) | [Tracking Changes with DirSync](https://learn.microsoft.com/en-us/windows/win32/ad/tracking-changes) | +| System.DirectoryServices.Protocols | [System.DirectoryServices.Protocols API reference](https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.protocols) | +| MS-ADTS (core AD spec) | [MS-ADTS Open Specification](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/d2435927-0999-4c62-8c6d-13ba31a52e1a) | +| .NET API docs source (GitHub) | [dotnet/dotnet-api-docs](https://github.com/dotnet/dotnet-api-docs) | + +--- + +## System.DirectoryServices.Protocols — type reference + +This is the raw LDAP layer used for all wire-level operations. Source: `xml/System.DirectoryServices.Protocols/` in dotnet/dotnet-api-docs. + +### LdapConnection + +Implements `IDisposable`. Inherits `DirectoryConnection`. Always wrap in `using`. + +```csharp +// Preferred constructor — explicit credentials + auth type +var conn = new LdapConnection( + new LdapDirectoryIdentifier("dc.corp.local", 636), + new NetworkCredential("svc-coreapi", "password", "corp.local"), + AuthType.Kerberos); +conn.SessionOptions.SecureSocketLayer = true; +conn.SessionOptions.ProtocolVersion = 3; +conn.Timeout = TimeSpan.FromSeconds(30); +conn.Bind(); // explicit bind; without this, LDAP v3 runs as anonymous +``` + +Key members: + +| Member | Notes | +| --- | --- | +| `AuthType` | See AuthType enum below. Set before `Bind()`. | +| `Timeout` | `TimeSpan`. Default is infinite — **always set explicitly**. | +| `SessionOptions` | Returns `LdapSessionOptions`. Set TLS, referrals, signing here. | +| `AutoBind` | When `true`, binds automatically on first request. Prefer explicit `Bind()`. | +| `Bind()` | Sends LDAP bind. Throws `LdapException` on failure. | +| `Bind(NetworkCredential)` | Bind with different credentials than constructor. | +| `SendRequest(DirectoryRequest)` | Synchronous. Returns `DirectoryResponse`. Throws `LdapException`, `DirectoryOperationException`. | +| `SendRequest(DirectoryRequest, TimeSpan)` | With per-request timeout override. | +| `BeginSendRequest(...)` / `EndSendRequest(...)` | Async pair. Use for long-running searches. | + +### AuthType enum + +| Value | Int | When to use | +| --- | --- | --- | +| `Anonymous` | 0 | Never in production. | +| `Basic` | 1 | Simple bind with username/password. **LDAPS only** — plaintext over LDAP is forbidden. | +| `Negotiate` | 2 | Windows auto-selects Kerberos or NTLM. Default when no authType specified. | +| `Ntlm` | 3 | Force NTLM. Avoid — Kerberos is preferred. | +| `Kerberos` | 9 | Explicit Kerberos. Use for service account binds in domain-joined environments. | +| `External` | 8 | Client certificate authentication (TLS mutual auth). | + +### LdapSessionOptions (key properties) + +| Property | Type | Notes | +| --- | --- | --- | +| `SecureSocketLayer` | bool | `true` = LDAPS. Set before `Bind()`. | +| `ProtocolVersion` | int | Always set to `3`. | +| `ReferralChasing` | `ReferralChasingOptions` | Default `All`. Set to `None` for single-domain scope. | +| `Signing` | bool | Kerberos message integrity. Set alongside `Sealing`. | +| `Sealing` | bool | Kerberos message encryption. Pairs with `Signing`. | +| `VerifyServerCertificate` | delegate | Callback to validate the DC's TLS certificate. | +| `SendTimeout` | TimeSpan | Per-send operation timeout. Throws on negative. | +| `PingKeepAliveTimeout` | TimeSpan | Interval before keep-alive ping is sent. | + +### SearchRequest / SearchResponse + +```csharp +var request = new SearchRequest( + distinguishedName: "OU=Users,DC=corp,DC=local", + ldapFilter: "(&(objectClass=user)(sAMAccountName=jsmith))", + searchScope: SearchScope.Subtree, + attributeList: new[] { "cn", "mail", "userAccountControl" }); + +request.SizeLimit = 0; // 0 = server default +request.TimeLimit = TimeSpan.FromSeconds(30); +request.TypesOnly = false; // false = return names AND values + +var response = (SearchResponse)connection.SendRequest(request); +foreach (SearchResultEntry entry in response.Entries) +{ + string dn = entry.DistinguishedName; + string cn = entry.Attributes["cn"]?[0] as string; +} +``` + +`Attributes` property: pass `null` to retrieve all attributes. Pass `new[] { "1.1" }` to retrieve DN only (no attributes, fastest). + +`Filter` accepts either an LDAP filter string or a DSML v2 XML document — anything else throws `ArgumentException`. + +### AddRequest — creating objects + +```csharp +var req = new AddRequest("CN=NewUser,OU=Users,DC=corp,DC=local", + new DirectoryAttribute("objectClass", "user"), + new DirectoryAttribute("sAMAccountName", "newuser"), + new DirectoryAttribute("userAccountControl", "512"), // enabled normal account + new DirectoryAttribute("unicodePwd", EncodePassword("P@ssw0rd"))); + +connection.SendRequest(req); +``` + +`Attributes` collection is read-only after construction — populate via the params array in the constructor or `req.Attributes.Add(new DirectoryAttribute(...))`. + +### ModifyRequest — updating attributes + +Three operations via `DirectoryAttributeOperation` enum: + +| Value | Int | Meaning | +| --- | --- | --- | +| `Add` | 0 | Add value(s) to a multi-valued attribute. Error if attribute doesn't exist. | +| `Delete` | 1 | Remove specific value(s). Pass no values to remove the entire attribute. | +| `Replace` | 2 | Replace all current values with the supplied values. Pass no values to clear the attribute. | + +```csharp +var mod = new DirectoryAttributeModification +{ + Name = "mail", + Operation = DirectoryAttributeOperation.Replace +}; +mod.Add("newmail@corp.local"); + +var req = new ModifyRequest("CN=User,OU=Users,DC=corp,DC=local", mod); +connection.SendRequest(req); +``` + +Alternative single-operation constructor: + +```csharp +var req = new ModifyRequest( + "CN=User,OU=Users,DC=corp,DC=local", + DirectoryAttributeOperation.Replace, + "mail", + new object[] { "newmail@corp.local" }); +``` + +### DeleteRequest + +```csharp +connection.SendRequest(new DeleteRequest("CN=User,OU=Users,DC=corp,DC=local")); +``` + +Deletes a leaf object. To delete a container with children, use a DeleteTree extended operation or delete children first. + +### ModifyDNRequest — rename or move + +```csharp +// Rename only (same OU) +var rename = new ModifyDNRequest( + distinguishedName: "CN=OldName,OU=Users,DC=corp,DC=local", + newParentDistinguishedName: null, // null = same parent + newName: "CN=NewName") +{ DeleteOldRdn = true }; // always true unless preserving old CN value + +// Move to different OU (can also rename in one operation) +var move = new ModifyDNRequest( + distinguishedName: "CN=User,OU=OldOU,DC=corp,DC=local", + newParentDistinguishedName: "OU=NewOU,DC=corp,DC=local", + newName: "CN=User") +{ DeleteOldRdn = true }; + +connection.SendRequest(move); +``` + +`DeleteOldRdn = true` is the correct value for all normal rename/move operations. Set to `false` only if the schema allows multi-valued RDN (rare). + +--- + +## System.DirectoryServices.AccountManagement — type reference + +Higher-level wrapper over ADSI. Prefer for Specs 4/5/6 (user/group CRUD). Avoid for Spec 7 (ACL) and complex filter operations. Source: `xml/System.DirectoryServices.AccountManagement/` in dotnet/dotnet-api-docs. + +### PrincipalContext + +The connection context. Must be `Dispose()`d. Always use `ContextType.Domain` for AD DS. + +```csharp +using var ctx = new PrincipalContext( + ContextType.Domain, + "corp.local", // domain name or DC FQDN + "OU=Users,DC=corp,DC=local", // default container for new objects + ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing, + "svc-coreapi@corp.local", // service account UPN + "password"); +``` + +`container` parameter: the OU where `Save()` places new objects by default. Pass `null` for domain root. + +`ConnectedServer` property: the actual DC the context is bound to (useful for logging). + +`ValidateCredentials(userName, password)` — returns `bool`. Username: bare name only (not `DOMAIN\user`). + +### UserPrincipal + +Maps to AD user objects. Key members: + +| Property | AD Attribute | Notes | +| --- | --- | --- | +| `SamAccountName` | `sAMAccountName` | Required. Max 20 chars. | +| `UserPrincipalName` | `userPrincipalName` | UPN format `user@domain`. | +| `DisplayName` | `displayName` | | +| `GivenName` | `givenName` | First name. | +| `Surname` | `sn` | Last name. | +| `EmailAddress` | `mail` | | +| `VoiceTelephoneNumber` | `telephoneNumber` | | +| `EmployeeId` | `employeeID` | | +| `Enabled` | `userAccountControl` bit | `true`/`false`/`null`. | +| `PasswordNeverExpires` | `userAccountControl` bit | | +| `PasswordNotRequired` | `userAccountControl` bit | | +| `AccountExpirationDate` | `accountExpires` | `DateTime?` | +| `LastPasswordSet` | `pwdLastSet` | Read-only. | + +Lifecycle: + +```csharp +// Create +using var user = new UserPrincipal(ctx, "jsmith", "P@ssw0rd!", enabled: true); +user.DisplayName = "John Smith"; +user.Save(); // writes to AD; must call before using the object further + +// Find +using var found = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "jsmith"); + +// Update +found.DisplayName = "John A. Smith"; +found.Save(); + +// Password +found.SetPassword("NewP@ss!"); +found.ExpirePasswordNow(); // force change on next logon + +// Delete +found.Delete(); +``` + +`IdentityType` values: `SamAccountName`, `DistinguishedName`, `Sid`, `Guid`, `UserPrincipalName`, `Name`. + +### GroupPrincipal + +Maps to AD group objects. Key members: + +| Property | Notes | +| --- | --- | +| `SamAccountName` | Group name. | +| `IsSecurityGroup` | `Nullable`. `true` = security group. `null` before first `Save()`. | +| `GroupScope` | `GroupScope` enum: `Local`, `Global`, `Universal`. | +| `Members` | `PrincipalCollection` — read/write. Call `Save()` to commit changes. | + +Lifecycle and membership: + +```csharp +// Create +using var grp = new GroupPrincipal(ctx) { Name = "AppAdmins", IsSecurityGroup = true }; +grp.Save(); + +// Add member +using var user = UserPrincipal.FindByIdentity(ctx, "jsmith"); +grp.Members.Add(user); +grp.Save(); + +// Remove member +grp.Members.Remove(user); +grp.Save(); + +// Recursive membership check +bool isMember = grp.GetMembers(recursive: true).Contains(user); + +// Find +using var found = GroupPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "AppAdmins"); +``` + +Important limitation: members linked via `primaryGroupID` (e.g. default "Domain Users") cannot be removed via the Members collection. + +--- + +## API design reference (KopiCloud-AD-API patterns) + +Source: [github.com/KopiCloud-AD-API](https://github.com/KopiCloud-AD-API) — a real-world production AD REST API. Use these patterns as a proven reference for controller design and DTO field lists. Their implementation runs on Windows (IIS + domain-joined), but the API surface design and AD field mappings apply directly. + +### REST endpoint conventions + +| Resource | List | Get | Create | Update | Delete | Special | +| --- | --- | --- | --- | --- | --- | --- | +| User | `GET /v1/users` | `GET /v1/users/{username}` | `POST /v1/users/{username}` | `PUT /v1/users/{username}` | `DELETE /v1/users/{username}` | Enable/Disable/Unlock/ResetPassword/Rename | +| Group | `GET /v1/groups` | `GET /v1/groups/{name}` | `POST /v1/groups/{name}/security` | — | `DELETE /v1/groups/{name}` | Rename | +| Membership | — | `GET /v1/users/{u}/groups/{g}` | `POST /v1/users/{u}/groups/{g}` | — | `DELETE /v1/users/{u}/groups/{g}` | List all groups for user | +| OU | `GET /v1/ous` | `GET /v1/ous` (by path) | `POST /v1/ous` | `PUT /v1/ous` | `DELETE /v1/ous/{path}` | Move, Rename | + +URL design notes: + +- Separate endpoints for `Enable`, `Disable`, `Unlock`, `ResetPassword`, `Rename` — don't fold them into generic PUT (makes intent explicit and auditable) +- List endpoints accept `OUPath` and `Recursive` query params for scoped searches +- Both username and GUID should be supported as identifiers (GUID is stable across renames) + +### Response envelope + +```json +{ + "output": "Operation completed successfully.", + "result": { /* single object or array */ } +} +``` + +For errors, use RFC 7807 Problem Details (as required by coreapi evaluation criteria), not this envelope. + +### User DTO — complete field reference + +Derived from KopiCloud's 45-field user object. The AD attribute mapping is shown where it differs from the camelCase field name. + +**Identity:** + +| DTO field | AD attribute | Notes | +| --- | --- | --- | +| `guid` | `objectGUID` | Binary → format as UUID string. Stable across renames. | +| `username` / `samAccountName` | `sAMAccountName` | Max 20 chars, unique per domain. | +| `userPrincipalName` | `userPrincipalName` | UPN format. | +| `displayName` | `displayName` | | + +**Name components:** + +| DTO field | AD attribute | +| --- | --- | +| `firstName` | `givenName` | +| `lastName` | `sn` | +| `initials` | `initials` | + +**Contact:** + +| DTO field | AD attribute | +| --- | --- | +| `emailAddress` | `mail` | +| `officePhone` | `telephoneNumber` | +| `homePhone` | `homePhone` | +| `mobilePhone` | `mobile` | + +**Organization:** + +| DTO field | AD attribute | +| --- | --- | +| `jobTitle` | `title` | +| `department` | `department` | +| `company` | `company` | +| `office` | `physicalDeliveryOfficeName` | +| `manager` | `manager` (DN value) | +| `description` | `description` | +| `ouPath` | parent path from `distinguishedName` | + +**Address:** + +| DTO field | AD attribute | +| --- | --- | +| `streetAddress` | `streetAddress` | +| `streetPoBox` | `postOfficeBox` | +| `city` | `l` (lowercase L) | +| `state` | `st` | +| `postalCode` | `postalCode` | +| `country` | `c` (ISO 3166-1 alpha-2) / `co` (display name) / `countryCode` (numeric) | + +**Security flags** (all `userAccountControl` bits): + +| DTO field | AD attribute / bit | +| --- | --- | +| `enabled` | `userAccountControl` bit `ACCOUNTDISABLE` (0x0002) inverted | +| `passwordNeverExpired` | `userAccountControl` bit `DONT_EXPIRE_PASSWD` (0x10000) | +| `passwordNotRequired` | `userAccountControl` bit `PASSWD_NOTREQD` (0x0020) | +| `changePasswordNextLogon` | `pwdLastSet = 0` (set to 0 to force; -1 to clear) | + +**Profile paths:** + +| DTO field | AD attribute | +| --- | --- | +| `profilePath` | `profilePath` | +| `profileLogonScript` | `scriptPath` | +| `homeFolderPath` | `homeDirectory` | +| `homeFolderDrive` | `homeDrive` (e.g. `H:`) | +| `homeFolderDirectory` | same as `homeDirectory` | + +**Remote Desktop Services (RDS/Terminal Services) attributes:** +These are NOT standard LDAP attributes — they are packed into the binary `userParameters` blob. They can only be read/written reliably via ADSI (`DirectoryEntry`), NOT via `LdapConnection` raw attribute reads. Use `DirectoryEntry.InvokeSet()`/`InvokeGet()` with the property name, or set via the `IADsTSUserEx` COM interface. + +| DTO field | ADSI property name | +| --- | --- | +| `rdsProfilePath` | `TerminalServicesProfilePath` | +| `rdsHomeFolderPath` | `TerminalServicesHomeDirectory` | +| `rdsHomeFolderDrive` | `TerminalServicesHomeDrive` | +| `rdsAllowLogon` | `AllowLogon` (1=allow, 0=deny) | +| `rdsConnectDrive` | `ConnectClientDrives` | + +For Specs 4/5 (User/Service account CRUD), skip RDS fields unless explicitly required — they need ADSI COM interop and add significant complexity. + +### Group DTO + +| DTO field | AD attribute / value | +| --- | --- | +| `guid` | `objectGUID` | +| `name` | `cn` / `sAMAccountName` | +| `description` | `description` | +| `email` | `mail` | +| `ouPath` | parent path from `distinguishedName` | +| `type` | Derived from `groupType` bit: `Security` or `Distribution` | +| `scope` | Derived from `groupType` bits: `Global`, `DomainLocal`, `Universal` | + +`type` and `scope` are both packed into the single `groupType` integer — decode separately. + +### OU DTO + +| DTO field | AD attribute | Notes | +| --- | --- | --- | +| `guid` | `objectGUID` | | +| `name` | `ou` | The OU name (RDN) | +| `description` | `description` | | +| `path` | `distinguishedName` | Full DN | +| `protected` | DACL DENY ACE | See below | + +**OU `protected` flag** — how "Protect from accidental deletion" works in AD: +This is NOT a stored attribute. It is implemented as a DENY ACE on the object's DACL: + +- DENY `Delete` and `DeleteTree` rights for `Everyone` (SID `S-1-1-0`) on the object itself +- AND a DENY `DeleteChild` ACE for `Everyone` on the **parent** object scoped to this object's class + +To read: inspect the DACL for a DENY ACE with `Everyone` and `Delete`/`DeleteTree` rights. +To set (protect): add those DENY ACEs. +To unset (unprotect): remove those DENY ACEs before deleting the OU. +This is a Spec 7 (ACL) concern — OU delete in Spec 6 must call the unprotect logic first when `force=true`. + +### Service account minimum AD permissions + +KopiCloud runs as Domain Admin, which is too broad. For coreapi, scope to minimum: + +| Operation | Required AD permission | +| --- | --- | +| Read users/groups/OUs | `ReadProperty` on target OU subtree | +| Create users | `CreateChild` (user class) on target OU | +| Modify user attributes | `WriteProperty` on user objects in target OU | +| Delete users | `DeleteChild` on parent OU + `Delete` on user objects | +| Reset password | `ExtendedRight` — Reset Password GUID on user objects | +| Enable/Disable accounts | `WriteProperty` on `userAccountControl` | +| Create/delete groups | `CreateChild`/`DeleteChild` (group class) on target OU | +| Modify group membership | `WriteProperty` on `member` attribute of group objects | +| Create/delete OUs | `CreateChild`/`DeleteChild` (organizationalUnit class) on parent OU | +| Rename/move objects | `WriteProperty` on `cn`/`ou` + `DeleteChild` (source) + `CreateChild` (destination) | +| Read/write DACLs | `ReadControl` + `WriteDacl` on target objects | + +Document these permissions explicitly and grant them at the OU level rather than domain-wide — required by Spec 9 evaluation criteria. diff --git a/md/active/ad-ds/unattended-deployment.md b/md/active/ad-ds/unattended-deployment.md new file mode 100644 index 0000000..b427ef2 --- /dev/null +++ b/md/active/ad-ds/unattended-deployment.md @@ -0,0 +1,263 @@ +--- +id: unattended-deployment +type: procedure +title: Unattended Active Directory Domain Services (AD DS) Deployment +theme: ad-ds +tags: + - aws-ec2 + - dcpromo + - dns + - ec2launch + - ssm + - unattend +scope: global +status: active +confidence: fact +audience: generic +source: + - ouritres/coreapi/.claude/knowledge-base/ad-ds-unattended-deployment.md + - https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo + - https://aws.amazon.com/whitepapers/active-directory-domain-services/ + - ouritres/coreapi/.claude/handoff/spec-0-status.md +validated: 2026-07-16 +created: 2026-06-16 +links: + - reference +--- + +# Unattended Active Directory Domain Services (AD DS) Deployment + +## Overview + +Unattended AD DS promotion requires: +1. **Answer file** (Unattend.xml or DCPROMO answer file) with all configuration parameters +2. **Network configuration** (static IP, DNS pointing to self) +3. **Role installation** (DNS Server, AD-Domain-Services) +4. **Promotion script** executed after prerequisites + +**Reference:** [DCPROMO Answer File Syntax - Microsoft Learn](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo) + +## Network Prerequisites (Critical) + +### 1. Static IP Address (REQUIRED for DNS) + +DNS Server cannot start without a static IP address. DHCP will cause immediate failure. + +```powershell +# Get current DHCP-assigned config +$adapter = Get-NetAdapter | Where-Object Status -eq 'Up' | Select-Object -First 1 +$config = Get-NetIPConfiguration -InterfaceIndex $adapter.InterfaceIndex +$currentIp = $config.IPv4Address[0].IPAddress +$currentGateway = $config.IPv4DefaultGateway[0].NextHop + +# Convert to static +Set-NetIPInterface -InterfaceIndex $adapter.InterfaceIndex -DHCP Disabled +Remove-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -AddressFamily IPv4 -Confirm:$false +New-NetIPAddress -InterfaceIndex $adapter.InterfaceIndex -IPAddress $currentIp -PrefixLength 24 +New-NetRoute -InterfaceIndex $adapter.InterfaceIndex -DestinationPrefix "0.0.0.0/0" -NextHop $currentGateway + +# Set DNS to self (critical for DNS service startup) +Set-DnsClientServerAddress -InterfaceIndex $adapter.InterfaceIndex -ServerAddresses @("127.0.0.1", "8.8.8.8") +``` + +### 2. DNS Configuration + +DNS must resolve itself during promotion: +- **Primary DNS:** 127.0.0.1 (localhost - the DC being promoted) +- **Secondary DNS:** 8.8.8.8 (external fallback) + +Without self-reference, DNS service fails to start with "No static IP" errors. + +## DCPROMO Answer File Format + +**File location in EC2:** `C:\Windows\System32\dcpromo.answer` + +**Minimal example for forest root DC:** + +```ini +[DCINSTALL] +; Unattended forest promotion +AutoConfigDNS=1 +CreateDNSDelegation=0 +DatabasePath="C:\Windows\NTDS" +LogPath="C:\Windows\NTDS" +SYSVOLPath="C:\Windows\SYSVOL" +SiteName="Default-First-Site-Name" +InstallDNS=Yes +AllowAnonymousAccess=No +AnswerFile="C:\Windows\System32\dcpromo.answer" + +; Forest and domain settings +DomainNetBiosName=CORP +DomainName=corp.local +ForestFunctionality=2012R2 +DomainFunctionality=2012R2 +ReplicaOrNewDomain=Forest +NewDomainDNSName=corp.local + +; Safe Mode Admin password +SafeModeAdminPassword=YourPasswordHere123! +RebootOnCompletion=Yes +``` + +**Critical parameters:** +- `InstallDNS=Yes` - Installs DNS during promotion +- `AutoConfigDNS=1` - Configures DNS automatically +- `SafeModeAdminPassword` - Directory Services Restore Mode password (REQUIRED) +- `RebootOnCompletion=Yes` - Reboot after successful promotion + +**Reference:** [Installing a New Forest Using Answer File - Microsoft Learn](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc770303) + +## Installation Sequence (Order Matters) + +```powershell +# 1. Configure static IP first +Set-NetIPInterface -DHCP Disabled +# ... (see Network Prerequisites above) + +# 2. Install DNS Server role +Install-WindowsFeature DNS -IncludeManagementTools + +# 3. Install AD-Domain-Services role +Install-WindowsFeature AD-Domain-Services -IncludeManagementTools + +# 4. Create DCPROMO answer file dynamically +$answerFile = @" +[DCINSTALL] +AutoConfigDNS=1 +DatabasePath="C:\Windows\NTDS" +LogPath="C:\Windows\NTDS" +SYSVOLPath="C:\Windows\SYSVOL" +SiteName="Default-First-Site-Name" +InstallDNS=Yes +AllowAnonymousAccess=No +DomainNetBiosName=CORP +DomainName=corp.local +ForestFunctionality=2012R2 +DomainFunctionality=2012R2 +ReplicaOrNewDomain=Forest +NewDNSName=corp.local +SafeModeAdminPassword=Password123! +RebootOnCompletion=Yes +"@ +$answerFile | Set-Content -Path "C:\Windows\System32\dcpromo.answer" -Encoding ASCII + +# 5. Run DCPROMO with answer file +dcpromo.exe /answer:"C:\Windows\System32\dcpromo.answer" /unattend +``` + +## AWS EC2 Considerations + +**Reference:** [Active Directory Domain Services on AWS - AWS Whitepapers](https://aws.amazon.com/whitepapers/active-directory-domain-services/) + +### Security Groups + +Allow these ports for AD DS: +- **TCP/UDP 53** - DNS +- **TCP/UDP 88** - Kerberos +- **TCP/UDP 389** - LDAP +- **TCP 636** - LDAPS +- **TCP 3389** - RDP (for troubleshooting) +- **TCP 445** - SMB (replication) +- **UDP 123** - NTP + +### EC2 UserData Execution + +UserData runs as SYSTEM with full privileges: +```powershell + +# Code runs as SYSTEM +# Can execute any privileged operations + +``` + +**Key points:** +- Execution is asynchronous (starts in background) +- Monitor progress via `C:\ProgramData\Amazon\EC2Launch\log\agent.log` +- Can take 20-30 minutes total (network config + role install + promotion + reboot) + +### IAM Instance Profile Permissions + +If promoting via AWS Systems Manager, instance needs: +- `ssm:GetDocument` +- `ssm:StartAutomationExecution` +- `ec2:DescribeInstances` +- `ec2messages:*` + +## Common Errors and Solutions + +| Error | Cause | Solution | +|-------|-------|----------| +| "DNS Server Error: No static IP" | Interface using DHCP | Set `Set-NetIPInterface -DHCP Disabled` first | +| "Install-ADDSForest: Cannot validate domain" | DNS not responding | Verify DNS started and self-reference (127.0.0.1) is set | +| "DCPROMO: File not found" | Answer file path wrong | Use full path: `C:\Windows\System32\dcpromo.answer` | +| "Replication Issues" | DNS resolution failing | Ensure all DNS forwarders configured, test with `nslookup` | +| "The specified domain either does not exist or could not be contacted" | Network isolation | Check security group allows LDAP/DNS ports | + +## Verification Commands (Post-Promotion) + +```powershell +# Verify DC promotion +Get-ADDomain +Get-ADForest +Get-ADDomainController + +# Check DNS +nslookup corp.local +Get-Service DNS + +# Verify replication +repadmin /replsummary +``` + +## References + +- [DCPROMO Answer File Syntax](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/dcpromo) +- [Installing a New Forest Using Answer File](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-r2-and-2008/cc770303) +- [Active Directory Domain Services on AWS](https://aws-solutions-library-samples.github.io/cfn-ps-microsoft-activedirectory/) +- [AD on AWS EC2 Design Considerations](https://docs.aws.amazon.com/whitepapers/latest/active-directory-domain-services/design-considerations-for-running-active-directory-on-ec2-instances.html) +- [AWS Directory Service for AD Trusts](https://docs.aws.amazon.com/directoryservice/latest/admin-guide/microsoftadtrusttep1.html) + +--- + +## EC2Launch v2 blocks legacy UserData — use SSM RunCommand instead + +Confirmed 2026-07-16 against a real EC2-provisioned DC (coreapi Spec 0), after the +approach below failed silently for ~4 hours of debugging. + +**Problem:** Windows Server 2022 Base AMI ships **EC2Launch v2**, not v1. EC2Launch v2 +expects YAML/XML config, not a base64-encoded `...` block, and +does **not** auto-decode/execute it like older AMIs did. Result: the DCPROMO UserData +script silently never runs — no error, just a promotion that never happens and an LDAP +readiness check that times out after 30 min. + +**Fix:** Don't rely on UserData for anything beyond the most trivial bootstrap. Launch +the instance bare, then drive the promotion via **SSM RunCommand** +(`AWS-RunPowerShellScript`) instead: + +```powershell +# 1. Wait for the SSM agent to actually register before sending anything -- +# sending too early is a second, separate failure mode (command hangs +# forever in "Sending SSM command", no error). +do { + $info = aws ssm describe-instance-information ` + --filters "Key=InstanceIds,Values=$instanceId" | ConvertFrom-Json + $status = $info.InstanceInformationList[0].PingStatus + Start-Sleep -Seconds 5 +} while ($status -ne 'Online') + +# 2. Only then send the promotion script via SSM +aws ssm send-command ` + --instance-ids $instanceId ` + --document-name "AWS-RunPowerShellScript" ` + --parameters commands="$dcpromoScript" +``` + +**Alternatives considered and rejected:** reverting to an older AMI with EC2Launch v1 +(region availability not guaranteed, fragile to depend on); rewriting UserData as +EC2Launch v2 YAML (untested extra complexity for no benefit over SSM, which was needed +anyway for other provisioning steps). + +**Verification:** `Get-ADDomain` over SSM (without transmitting the password through SSM +command history) confirms promotion health before declaring success — checking process +exit code alone is not enough. diff --git a/md/active/agent-tooling/agent-skills-cross-tool-integration.md b/md/active/agent-tooling/agent-skills-cross-tool-integration.md new file mode 100644 index 0000000..cf3f690 --- /dev/null +++ b/md/active/agent-tooling/agent-skills-cross-tool-integration.md @@ -0,0 +1,279 @@ +--- +id: agent-skills-cross-tool-integration +type: reference +title: Agent Skills -- standard ouvert cross-outil (Claude Code, Copilot/VS Code, Codex) +theme: agent-tooling +tags: + - skills + - vscode + - copilot + - codex + - tool-scoping +scope: global +status: active +confidence: fact +audience: generic +source: + - https://agentskills.io + - https://github.com/microsoft/vscode/issues/293276 + - https://github.com/microsoft/vscode/issues/307630 +validated: 2026-07-13 +created: 2026-07-13 +links: + - vscode-copilot-builtin-tools +--- + +# Agent Skills — standard ouvert cross-outil (Claude Code, Copilot/VS Code, Codex) + +Statut : `.new` — capture de recherche du 2026-07-13, déclenchée par une observation +réelle de Philippe (Copilot Chat allait chercher `.agents/skills/maxime-review` +au lieu du `.github/prompts/maxime-review.prompt.md` attendu). Savoir générique +réutilisable, sourcé sur la documentation officielle de chaque outil. + +## Le déclencheur + +Philippe, dans GitHub Copilot Chat, demande "Maxime Review" → Copilot va chercher +dans `.agents/skills/maxime-review` (chemin qu'on pensait réservé à Codex), +pas dans `.github/prompts/maxime-review.prompt.md` (le fichier Copilot généré +par `generate-adapters.*`). Question : pourquoi, et est-ce grave ? + +## Ce qui est confirmé (sourcé) + +### Agent Skills est un standard ouvert, pas une convention par outil + +D'après [agentskills.io](https://agentskills.io) : le format **Agent Skills** +(dossier + `SKILL.md`, frontmatter minimal `name`+`description`) a été créé par +Anthropic puis publié comme **standard ouvert**, adopté par une liste large et +publique d'outils : Claude Code, GitHub Copilot, VS Code, OpenAI Codex, Cursor, +Gemini CLI, Goose, Roo Code, JetBrains Junie, et des dizaines d'autres (voir la +page pour la liste complète). Fonctionnement en 3 étapes ("progressive +disclosure") : *discovery* (nom+description seulement au démarrage) → *activation* +(le corps du SKILL.md charge en contexte si la tâche correspond) → *execution*. + +**Conséquence directe pour mA.xI.me** : `.agents/skills/` n'est pas "le dossier +Codex" — c'est un des emplacements génériques que plusieurs outils scannent en +même temps, dont Copilot. + +### Emplacements scannés, par outil + +| Outil | Emplacements projet | Emplacements personnels | Configurable ? | +| --- | --- | --- | --- | +| **Claude Code** | `.claude/skills/`, dossier `--add-dir` | `~/.claude/skills/` | non documenté | +| **GitHub Copilot (VS Code, CLI, cloud agent)** | `.github/skills/`, **`.claude/skills/`**, **`.agents/skills/`** | `~/.copilot/skills/`, `~/.claude/skills/`, `~/.agents/skills/` | oui, `chat.agentSkillsLocations` — **ajoute** des emplacements, ne permet pas d'en exclure | +| **OpenAI Codex** | `.agents/skills/`, scanné à chaque niveau du cwd jusqu'à la racine du repo Git | `$HOME/.agents/skills/` | non documenté | + +Sources : [code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills), +[docs.github.com — About custom agents](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-custom-agents) +et une recherche dédiée sur `chat.agentSkillsLocations`, +[developers.openai.com/codex/skills](https://developers.openai.com/codex/skills) +(redirige vers `learn.chatgpt.com/docs/codex/skills`). + +**Point clé** : Copilot scanne **les trois** conventions (la sienne + celle de +Claude + celle de Codex/du standard). C'est documenté, pas un bug — Microsoft a +délibérément rendu Copilot compatible avec les skills écrits pour les autres +outils. + +### Aucune restriction d'outils dans le standard de base + +Champs frontmatter du standard Agent Skills (confirmés via la doc VS Code) : +`name`, `description`, `argument-hint`, `user-invocable`, +`disable-model-invocation`, `context` (`inline` ou `fork`). **Aucun champ ne +restreint les outils disponibles** — ni `allowed-tools`, ni équivalent, dans le +standard lui-même. + +- **Claude Code étend le standard** avec `allowed-tools` (extension propriétaire, + ignorée par les autres outils). +- **Codex n'ajoute rien** — ses skills n'ont jamais de frontmatter de + restriction (déjà documenté côté mA.xI.me, décision du 2026-07-12). +- **Copilot/VS Code n'ajoute rien non plus au niveau Skill** — la restriction + d'outils existe uniquement au niveau des **Custom Agents** (`.agent.md`, + champ `tools:`), pas au niveau Skill. + +### Custom Agents VS Code (`.agent.md`) — rappel et nuance + +Emplacements : `.github/agents/` (projet), `~/.copilot/agents/` (utilisateur), +extensible via `chat.agentFilesLocations`. Frontmatter : `name`, `description`, +`tools`, `model`, `agents` (sous-agents autorisés), `handoffs`, `mcp-servers`. +Quand un agent personnalisé est actif, seuls les outils listés dans `tools:` +sont disponibles — confirmé. + +**Ce qui reste flou (la doc ne le dit pas explicitement)** : comment cette +restriction s'articule avec un Skill chargé pendant que l'agent est actif. Seul +indice trouvé : *"la priorité des outils favorise les fichiers de prompt sur +les agents personnalisés"* — ce qui suggère qu'un **prompt file** avec son +propre `tools:` (comme `.github/prompts/maxime-review.prompt.md`, qui déclare +`tools: [read, search]`) prendrait le pas sur l'agent actif s'il est invoqué +comme prompt/commande slash. Mais rien ne confirme ce qui se passe quand c'est +un **Skill** (sans son propre `tools:`) qui est chargé à la place — hérite-t-il +des restrictions de l'agent actif, ou tourne-t-il avec la palette complète ? + +Sources : [code.visualstudio.com/docs/agent-customization/custom-agents](https://code.visualstudio.com/docs/agent-customization/custom-agents), +[code.visualstudio.com/docs/agent-customization/overview](https://code.visualstudio.com/docs/agent-customization/overview). + +## Implication concrète pour mA.xI.me + +Le workflow `maxime-review` est censé garantir une revue **lecture seule** +sous Copilot via `.github/prompts/maxime-review.prompt.md` +(`tools: [read, search]`) et/ou l'agent dédié `maxi-copilot-reviewer` +(`.github/agents/maxime-reviewer.agent.md`, aussi `tools: [read, search]`). + +Ce qu'on sait maintenant : + +1. Copilot scanne aussi `.claude/skills/maxime-review` et + `.agents/skills/maxime-review` — deux fichiers **sans aucune restriction + d'outils utilisable par Copilot** (le premier a `allowed-tools`, mais c'est + une extension Claude que Copilot ignore ; le second n'a rien du tout). +2. Rien ne garantit lequel des trois emplacements (`.github/skills/` + — absent chez nous —, `.claude/skills/`, `.agents/skills/`) Copilot choisit + quand plusieurs portent le même nom `maxime-review`. La doc ne documente + pas de règle de priorité entre emplacements. +3. Si Copilot charge le Skill (plutôt que le prompt file) **et** que le + contexte d'exécution du Skill n'hérite pas des restrictions de l'agent + actif, alors la garantie lecture-seule de `maxime-review` sous Copilot n'est + plus mécanique — elle retombe sur la même situation déjà documentée pour + Codex ("consigne textuelle, pas garantie technique"). + +C'est le même trou que celui déjà noté dans `docs/ARCHITECTURE.md` §Limites +assumées pour Codex, mais potentiellement **aussi vrai pour Copilot**. + +**Correction d'une hypothèse initiale** : en relisant `.wip/adr/decisions-log.md`, +le verdict Tier 2 du 2026-07-12 précise explicitement que *"prompts 4 (handoff) +et 5 (review) [n'ont pas été] executes, juges non necessaires vu la force des +resultats deja obtenus"*. Le workflow `maxime-review` n'a donc **jamais été +testé en conditions réelles sous Copilot** — ce n'est pas une régression par +rapport à une garantie déjà validée, c'est une hypothèse non testée qu'on +découvre seulement maintenant. + +Chronologie confirmée : Agent Skills est arrivé dans GitHub Copilot le +2025-12-18 ([GitHub Changelog](https://github.blog/changelog/2025-12-18-github-copilot-now-supports-agent-skills/)), +et dans VS Code (canal stable, expérimental) vers janvier 2026 via la version +1.108 ([Visual Studio Magazine, 2026-01-11](https://visualstudiomagazine.com/articles/2026/01/11/hand-on-with-new-github-copilot-agent-skills-in-vs-code.aspx)) — +donc bien avant le Tier 2 du 2026-07-12. La fonctionnalité était déjà active +au moment du Tier 2 ; c'est le scénario précis (invocation naturelle de +"Maxime Review" plutôt que sélection explicite de l'agent ou du prompt) qui +n'a jamais été exercé. + +**Recherche complémentaire (3 sources officielles distinctes)** : ni la doc +GitHub ([about-agent-skills](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)), +ni le blog Microsoft ([Agent Skills in Visual Studio](https://devblogs.microsoft.com/visualstudio/agent-skills-in-visual-studio/), +mai 2026, statut encore Insiders pour Visual Studio à cette date), ni la doc +VS Code ne mentionnent la moindre notion de sécurité, de sandbox ou de +restriction d'outils au niveau Skill. L'absence est cohérente à travers les +trois sources — ce n'est pas un trou de recherche, la question semble +simplement ne pas être adressée par l'écosystème à ce stade. + +## Question résolue par les issues GitHub officielles (pas par la doc) + +La doc ne tranchait pas la question d'héritage des permissions. Les issues +GitHub réelles du dépôt VS Code (`microsoft/vscode`, ex-`vscode-copilot-chat` +archivé et fusionné dedans le 2026-05-20) la tranchent, avec confirmation +directe par un membre de l'équipe VS Code : + +### `SKILL.md` n'a aucun moyen de restreindre ou d'élargir les outils — confirmé par le code lui-même + +[Issue #293276](https://github.com/microsoft/vscode/issues/293276) (« Skills: +Scoped tool permissions ») cite le message d'erreur exact du validateur +VS Code actuel quand on tente d'ajouter `allowed-tools` à un `SKILL.md` : + +> *"Attribute 'allowed-tools' is not supported in skill files. Supported: +> compatibility, description, license, metadata, name."* + +— message confirmé par `anladwig` (membre de l'équipe VS Code), qui note que +`allowed-tools` fait pourtant partie du standard ouvert (`agentskills.io`) +mais n'est **pas encore implémenté côté VS Code**. Un commentateur +(`siegenthalerroger`) demande explicitement *"Is the `tools` field available +in a SKILL.md frontmatter?"* — réponse : non, ni documenté ni accepté par le +validateur. + +**Conséquence directe, confirmée** : un `SKILL.md`, quel que soit l'outil qui +le charge (Claude Code excepté, qui honore sa propre extension +`allowed-tools`), ne peut ni accorder ni retirer de capacité — c'est du texte +pur, injecté dans le contexte de l'agent déjà actif. + +### La restriction d'outils vient donc uniquement de l'agent actif — et elle s'applique bien aux skills + +[Issue #307630](https://github.com/microsoft/vscode/issues/307630) (« per-agent +skill scoping ») confirme, en creusant le problème inverse (pas de moyen de +restreindre QUELS skills un agent voit) : + +> *"Custom agents (`.agent.md`) support a `tools` property to restrict which +> tools are available per agent. However, there is no equivalent mechanism for +> **skills**... All skills from all discovery locations... are visible to all +> agents simultaneously."* + +Et cite comme cas d'usage non résolu, mot pour mot notre situation : + +> *"Security/principle of least privilege: Some agents should be read-only +> (already possible via `tools`), but they also shouldn't have access to +> skills that trigger write operations via their instructions."* + +**Ce que ça confirme pour mA.xI.me** : `tools:` sur un Custom Agent (`.agent.md`) +est un mécanisme **réel et fonctionnel** — c'est le seul niveau où la +restriction d'outils existe concrètement côté Copilot. Un Skill chargé +pendant que `maxi-copilot-reviewer` (`tools: [read, search]`) est actif ne +peut **pas** faire apparaître `edit`/`execute` : ces outils ne sont +simplement pas dans la liste dont dispose le modèle à ce moment-là, peu +importe ce que le texte du skill suggère. **La garantie lecture-seule tient +donc, à condition que l'agent restreint soit explicitement actif au moment +de l'invocation.** + +Le risque réel n'est donc pas "le skill contourne la restriction" — c'est +"aucune restriction n'est active si l'utilisateur invoque le workflow depuis +un contexte non restreint" (chat par défaut, ou l'agent `maxi-copilot` lui-même, +qui a `edit`+`execute`). Dans ce cas, peu importe lequel des trois SKILL.md +homonymes charge : aucun n'a jamais eu la capacité de restreindre quoi que ce +soit — c'était déjà vrai avant même la découverte de `.agents/skills/`. + +### Contournement documenté par la communauté (imparfait, mais réel) + +Un des commentaires sur #307630 documente le seul palliatif existant +aujourd'hui : ajouter dans le corps de l'agent (`.agent.md`) une consigne +explicite du type *"only load skills from this directory"* — *"this works +reasonably well because the model follows instructions, but it's not +enforced by the system and doesn't filter the `/` menu"*. C'est exactement le +même type de garantie que celle déjà documentée pour Codex dans +`docs/ARCHITECTURE.md` (consigne textuelle, pas verrou technique) — pas une +solution, une atténuation. + +### Suivi amont (pour re-vérifier plus tard si le paysage change) + +- [#293276](https://github.com/microsoft/vscode/issues/293276) — auto-approbation d'outils scopée à un skill (ouvert) +- [#307630](https://github.com/microsoft/vscode/issues/307630) — scoper quels skills un agent peut voir (ouvert) +- [#313951](https://github.com/microsoft/vscode/issues/313951) / [#311166](https://github.com/microsoft/vscode/issues/311166) — déclaration de capacités (`tools`, `mcp-servers`, `hooks`, `model`) dans le frontmatter `SKILL.md` (ouverts, doublons du même besoin) +- [#294520](https://github.com/microsoft/vscode/issues/294520) — validation du frontmatter rejetait des attributs inconnus, cassant l'extensibilité du standard (fermé) + +## Ce qui reste réellement incertain + +- Priorité exacte entre `.github/skills/`, `.claude/skills/`, `.agents/skills/` + quand le même nom existe aux trois emplacements — non documentée, et sans + incidence pratique vu ce qui précède (aucun des trois ne restreint quoi que + ce soit de toute façon). +- Le paramètre `chat.useAgentSkills` doit être actif pour que la découverte de + skills fonctionne du tout (confirmé, notes de version VS Code 1.108) — le + désactiver empêcherait Copilot de charger `.agents/skills/maxime-review`, + au prix de perdre Agent Skills partout dans le workspace, pas seulement + pour mA.xI.me. + +## Sources consultées + +- [agentskills.io — Agent Skills Overview](https://agentskills.io) +- [code.claude.com/docs/en/skills — Extend Claude with skills](https://code.claude.com/docs/en/skills) +- [code.claude.com/docs/en/vs-code — Use Claude Code in VS Code](https://code.claude.com/docs/en/vs-code) +- [code.visualstudio.com/docs/agent-customization/overview](https://code.visualstudio.com/docs/agent-customization/overview) +- [code.visualstudio.com/docs/agent-customization/custom-agents](https://code.visualstudio.com/docs/agent-customization/custom-agents) +- [code.visualstudio.com/docs/agent-customization/agent-skills](https://code.visualstudio.com/docs/agent-customization/agent-skills) (déjà utilisée dans la fiche KB du 2026-07-12 sur les outils built-in) +- [docs.github.com — About custom agents](https://docs.github.com/en/copilot/concepts/agents/cloud-agent/about-custom-agents) +- [learn.chatgpt.com/docs/codex/ide](https://learn.chatgpt.com/docs/codex/ide) (Codex IDE extension, redirigé depuis developers.openai.com/codex/ide) +- [learn.chatgpt.com/docs/agent-configuration/agents-md](https://learn.chatgpt.com/docs/agent-configuration/agents-md) (redirigé depuis developers.openai.com/codex/guides/agents-md) +- [developers.openai.com/codex/skills](https://developers.openai.com/codex/skills) +- [agentskills.io/specification](https://agentskills.io/specification) — spécification complète du format +- [github.com/microsoft/vscode/issues/293276](https://github.com/microsoft/vscode/issues/293276) — confirmation directe (membre équipe VS Code) que `allowed-tools` n'est pas implémenté +- [github.com/microsoft/vscode/issues/307630](https://github.com/microsoft/vscode/issues/307630) — absence de scoping skill/agent, cas d'usage identique au nôtre +- [learn.microsoft.com/.../copilot-agent-skills](https://learn.microsoft.com/en-us/visualstudio/ide/copilot-agent-skills?view=visualstudio) — doc Visual Studio (IDE complet, pas VS Code), mêmes trois emplacements confirmés +- [code.visualstudio.com/updates/v1_108](https://code.visualstudio.com/updates/v1_108) — notes de version, confirme `.claude/skills/` scanné "for backwards compatibility" et le paramètre `chat.useAgentSkills` + +## Liens + +Voir aussi [[20260712.new.vscode-copilot-builtin-tools]] (catégories d'outils +built-in Copilot/VS Code — sujet voisin mais distinct : celui-là porte sur les +outils, celui-ci sur la découverte de skills/agents). diff --git a/md/active/aws/ecs-fargate-task-isolation.md b/md/active/aws/ecs-fargate-task-isolation.md new file mode 100644 index 0000000..a97e1e3 --- /dev/null +++ b/md/active/aws/ecs-fargate-task-isolation.md @@ -0,0 +1,43 @@ +--- +id: ecs-fargate-task-isolation +type: reference +title: ECS EC2 vs Fargate — isolation des tasks +theme: aws +tags: + - ecs + - fargate + - ec2 + - isolation + - containers +scope: global +status: active +confidence: fact +audience: generic +source: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-linux-gmsa.html +validated: 2026-07-18 +created: 2026-07-18 +links: + - zero-standing-access +--- + +# ECS — launch type EC2 vs Fargate, isolation + +## EC2 launch type + +Les tasks ECS s'exécutent comme des conteneurs sur des instances EC2 gérées par le client, en partageant le **même noyau hôte**. La documentation AWS elle-même est explicite : les conteneurs ne sont pas une frontière d'isolation de sécurité garantie — un conteneur compromis peut potentiellement atteindre des ressources d'autres tasks colocalisées sur le même hôte (évasion de conteneur, attaque via le noyau partagé). + +## Fargate launch type + +Chaque task tourne dans sa **propre micro-VM** dédiée — frontière d'isolation matérielle réelle entre tasks, même si elles appartiennent à des services différents sur le même compte. Compromis : moins de contrôle sur l'instance sous-jacente (pas d'accès SSH à l'hôte, pas de choix du type d'instance EC2), en échange d'une isolation plus forte par défaut. + +## gMSA sur Fargate + +Support depuis **mars 2024**, mais **limité aux conteneurs Linux**, via le mode **domainless gMSA** et le daemon `credentials-fetcher` packagé par AWS. Pas de support équivalent documenté pour des conteneurs Windows sur Fargate — vérifier ce point avant de bâtir une architecture qui en dépendrait. + +En mode domainless, le conteneur n'est **pas** joint au domaine. `credentials-fetcher` récupère un identifiant AD **statique** (utilisateur + mot de passe + nom de domaine) stocké dans un secret AWS Secrets Manager, référencé par le fichier CredSpec de la task — ce n'est donc **pas une chaîne entièrement secretless** : il existe un credential AD permanent au bootstrap, protégé par IAM (accès au secret scoped au rôle d'exécution de la task), pas par une rotation JIT. Le conteneur applicatif, lui, ne voit jamais ce mot de passe — `credentials-fetcher` le consomme et expose un ticket Kerberos au conteneur. + +## Quand privilégier Fargate + +Pertinent quand la charge de travail est une **passerelle privilégiée** vers un système sensible (ex. LDAP/AD) où la compromission d'un voisin de conteneur serait un risque inacceptable — le coût de l'isolation micro-VM se justifie par l'enjeu, pas par défaut pour toute charge de travail. diff --git a/md/active/claude-config/claude-md-hierarchie.md b/md/active/claude-config/claude-md-hierarchie.md new file mode 100644 index 0000000..b0f2de0 --- /dev/null +++ b/md/active/claude-config/claude-md-hierarchie.md @@ -0,0 +1,204 @@ +--- +id: claude-md-hierarchie +type: reference +title: Hiérarchie & chargement des CLAUDE.md (Claude Code) +theme: claude-config +tags: + - claude-code + - claude-md + - memory +scope: global +status: active +confidence: fact +audience: generic +source: + - https://code.claude.com/docs/en/memory +validated: 2026-06-16 +created: 2026-06-16 +links: + - claude-md-import-mechanism +--- + +# Hiérarchie & chargement des CLAUDE.md (Claude Code) + +Statut : `.new` — capture brute de recherche du 2026-06-16 (bootstrap du +projet), déplacée de `docs/CLAUDE-MD-HIERARCHIE.md` le 2026-07-13 : contenu +générique réutilisable sur la plateforme Claude Code, sans donnée de +projet/client/employeur, pas encore relu/validé comme fiche KB stable. + +Source officielle (lue et vérifiée) : [claude memory docs](https://code.claude.com/docs/en/memory) + +--- + +## 1. Les 4 niveaux (par ordre de chargement, du plus large au plus spécifique) + +| Scope | Emplacement | Rôle | Partagé avec | +| - | - | - | - | +| **Managed policy** | macOS : `/Library/Application Support/ClaudeCode/CLAUDE.md`
Linux/WSL : `/etc/claude-code/CLAUDE.md`
Windows : `C:\Program Files\ClaudeCode\CLAUDE.md` | Instructions imposées par l'organisation (IT/DevOps) : standards, sécurité, conformité | Tous les utilisateurs de la machine/org | +| **User instructions** | `~/.claude/CLAUDE.md` | Préférences personnelles, tous projets | Moi seul (tous projets) | +| **Project instructions** | `./CLAUDE.md` ou `./.claude/CLAUDE.md` | Instructions partagées de l'équipe | L'équipe via le contrôle de source | +| **Local instructions** | `./CLAUDE.local.md` | Préférences perso d'un projet ; à mettre dans `.gitignore` | Moi seul (projet courant) | + +Les niveaux se **cumulent** (concaténés), ils ne s'écrasent pas. + +--- + +## 2. Comment le chargement fonctionne RÉELLEMENT (le point clé) + +Claude Code ne lit pas une liste fixe d'emplacements. Il **remonte l'arborescence** +depuis le répertoire de travail (cwd) jusqu'à la racine, et charge chaque +`CLAUDE.md` et `CLAUDE.local.md` rencontré en chemin. + +Exemple : lancé dans `foo/bar/`, il charge `foo/bar/CLAUDE.md`, puis `foo/CLAUDE.md`, +plus les `CLAUDE.local.md` à côté. + +**Ordre dans le contexte** : de la racine du système vers le cwd. Donc les +instructions les plus proches de l'endroit où tu lances Claude sont lues **en +dernier**. En cas de contradiction, le "dernier lu" agit comme un signal de priorité. +Dans chaque dossier, `CLAUDE.local.md` est ajouté APRÈS `CLAUDE.md`. + +Les `CLAUDE.md` des sous-dossiers (sous le cwd) ne sont PAS chargés au lancement : +ils se chargent à la demande quand Claude lit un fichier de ce sous-dossier. + +### ⚠️ Piège vécu (2026-06-16) + +Le niveau "Project" est relatif au cwd. Lancer Claude Code depuis un dossier qui +n'est pas un repo git (ex : `C:\Users\` ou `...\source\repos`) fait que +`./CLAUDE.md` se rabat sur le `CLAUDE.md` de CE dossier. C'est ce qui avait créé +l'illusion d'un "CLAUDE.md à la racine du profil" : ce n'était pas un emplacement +officiel séparé, juste un palier de la remontée d'arbre. +→ **Toujours lancer Claude Code depuis un vrai repo git** pour que le niveau +Project pointe au bon endroit. + +--- + +## 3. CLAUDE.md ≠ configuration imposée (TRÈS important) + +> Les CLAUDE.md (et l'auto memory) sont traités comme du **contexte**, pas comme +> de la configuration appliquée de force. Pour bloquer une action quoi que Claude +> décide, il faut un **hook PreToolUse**, pas une ligne de texte. + +Conséquence directe pour nos "règles inviolables" (jamais `git add -A`, jamais main) : + +- Écrites dans le CLAUDE.md = instructions FORTES, mais pas un verrou. +- Pour un vrai blocage technique → **hook** (`PreToolUse`) ou **managed settings** + (`permissions.deny`). À considérer pour les garde-fous critiques. + +CLAUDE.md content est délivré comme un message utilisateur après le system prompt : +Claude le lit et tente de le suivre, sans garantie de conformité stricte — +surtout si les instructions sont vagues ou contradictoires. + +--- + +## 4. Bonnes pratiques d'écriture (officiel) + +- **Taille** : viser **< 200 lignes** par CLAUDE.md. Plus long = plus de contexte + consommé et **moins bonne adhérence**. (Cette limite des 200 lignes / 25 KB + s'applique à `MEMORY.md` de l'auto-memory ; les CLAUDE.md, eux, sont chargés en + entier quelle que soit la longueur — mais plus court = mieux suivi.) +- **Spécificité** : "Use 2-space indentation" plutôt que "format code properly". + "Run `npm test` before committing" plutôt que "test your changes". +- **Structure** : titres markdown + bullets. Claude scanne la structure comme un lecteur. +- **Cohérence** : si deux règles se contredisent, Claude en choisit une arbitrairement. + Revoir périodiquement pour retirer le contradictoire ou l'obsolète. + +--- + +## 5. Astuces utiles découvertes + +### Commentaires HTML = notes gratuites + +Les commentaires HTML de niveau bloc `` sont **retirés avant injection** +dans le contexte. → Laisser des notes aux mainteneurs humains SANS consommer de +tokens. (Les commentaires DANS un bloc de code sont, eux, préservés. Et `Read` +sur le fichier les montre.) + +### Imports `@path` + +Un CLAUDE.md peut importer d'autres fichiers via `@chemin/fichier`. Chemins relatifs +(résolus par rapport au fichier qui importe) ou absolus. Récursif, max 4 niveaux. +⚠️ Les fichiers importés sont chargés au lancement → ça n'économise PAS de contexte, +ça organise seulement. +Exemple : `# git workflow @docs/git-instructions.md` +Partager du perso entre worktrees : `@~/.claude/my-project-instructions.md`. + +### `/init` pour démarrer un CLAUDE.md projet + +Analyse le codebase et génère un CLAUDE.md de départ (build, tests, conventions). +S'il existe déjà, `/init` propose des améliorations au lieu d'écraser. +`CLAUDE_CODE_NEW_INIT=1` active un flux interactif multi-phases. + +### AGENTS.md + +Claude Code lit `CLAUDE.md`, pas `AGENTS.md`. Si un repo a déjà un AGENTS.md : +créer un CLAUDE.md qui l'importe → `@AGENTS.md` (puis ajouter des instructions +Claude-spécifiques en dessous). Sur Windows, préférer l'import `@AGENTS.md` au +symlink (le symlink exige les droits admin / mode développeur). + +### `.claude/rules/` pour les gros projets + +Découper en fichiers par sujet (`testing.md`, `security.md`...). Chargés à chaque +session avec la même priorité que `.claude/CLAUDE.md`. Peuvent être **scopés par +chemin** via frontmatter `paths:` (glob) → ne se chargent que quand Claude touche +les fichiers correspondants = moins de bruit, contexte économisé. +Règles user-level : `~/.claude/rules/` (préférences perso, tous projets). +Partage entre projets via symlinks. + +### Skills vs rules vs CLAUDE.md (quand utiliser quoi) + +- **CLAUDE.md** : faits à garder chaque session (build, conventions, "always X"). +- **Rules** (`.claude/rules/`) : modulaire, scopable par chemin, chargé en contexte. +- **Skills** : workflows répétables, chargés UNIQUEMENT à l'invocation ou quand + Claude juge pertinent. Pour les procédures qui n'ont pas à être en contexte tout le temps. + +### Monorepo — exclure des CLAUDE.md parasites + +`claudeMdExcludes` (dans `.claude/settings.local.json`) saute des CLAUDE.md +d'autres équipes par chemin/glob. Les managed policy ne peuvent PAS être exclus. + +### Survie au /compact + +Le CLAUDE.md de racine de projet survit au `/compact` (re-lu depuis le disque). +Les CLAUDE.md de sous-dossiers ne sont pas réinjectés auto : ils rechargent au +prochain accès à un fichier de ce sous-dossier. → Mettre dans CLAUDE.md ce qui +ne doit pas se perdre (pas seulement dans la conversation). + +### Débogage "Claude ne suit pas mon CLAUDE.md" + +1. `/memory` → vérifier que le fichier est bien listé (sinon Claude ne le voit pas). +2. Vérifier que l'emplacement est bien chargé pour la session (cf. remontée d'arbre). +3. Rendre les instructions plus spécifiques. +4. Chercher les contradictions entre fichiers. +5. Si ça doit s'exécuter à un moment précis (avant chaque commit...) → **hook**, pas CLAUDE.md. +Astuce : hook `InstructionsLoaded` pour logger quels fichiers d'instructions +sont chargés, quand et pourquoi. + +--- + +## 6. CLAUDE_CONFIG_DIR (notre cas) + +Déplace le dossier de config (`~/.claude` → dossier choisi). Vérifié sur la +machine : elle ne redirige pas le chargement des CLAUDE.md comme on pourrait le +croire ; elle déplace surtout l'état local (auto-memory, sessions). +→ Par défaut : NE PAS la définir. Rester au standard. (On l'a retirée le 2026-06-16.) + +NB auto-memory : chaque projet a `~/.claude/projects//memory/` avec un +`MEMORY.md` (index, 200 lignes / 25 KB chargées par session) + fichiers par sujet +chargés à la demande. `` dérive du repo git → hors repo git, c'est la +racine du dossier qui sert. Raison de plus pour travailler dans de vrais repos git. + +--- + +## 7. Application à mA.xI.me (déjà documenté ailleurs, gardé pour mémoire) + +Ce document décrit les mécanismes propres à Claude Code ; il ne définit pas le socle +universel de mA.xI.me (voir `core/socle.md` et `docs/ARCHITECTURE.md`). + +- **Socle mA.xI.me** → `core/socle.md`, projeté dans le `CLAUDE.md` du repository + cible par l'installateur repo-only. +- **Orchestrateur** → agent `maxi-claude` et workflows sous `.claude/` dans le + repository cible, sans installation sous `~/.claude/` par mA.xI.me. +- **État partagé** → `.wip/`, lu également par les adaptateurs Copilot et Codex. +- **Garde-fous critiques** → le hook Claude peut compléter le texte, mais n'est pas + une garantie portable aux autres hôtes. +- **KB** → submodule `knowledge-base/` relatif au repository si le projet l'utilise. diff --git a/md/active/claude-config/claude-md-import-mechanism.md b/md/active/claude-config/claude-md-import-mechanism.md new file mode 100644 index 0000000..475876e --- /dev/null +++ b/md/active/claude-config/claude-md-import-mechanism.md @@ -0,0 +1,59 @@ +--- +id: claude-md-import-mechanism +type: reference +title: Claude Code — mécanisme d'import @fichier pour CLAUDE.md +theme: claude-config +tags: + - claude-code + - claude-md + - import + - config-merge +scope: global +status: active +confidence: fact +audience: generic +source: + - https://code.claude.com/docs/en/memory + - https://github.com/anthropics/claude-code/issues/2950 + - https://github.com/anthropics/claude-code/issues/8533 + - https://github.com/anthropics/claude-code/issues/1041 + - https://github.com/anthropics/claude-code/issues/5231 + - https://github.com/anthropics/claude-code/issues/7768 +validated: 2026-07-16 +created: 2026-07-16 +links: + - claude-md-hierarchie + - copilot-instructions-merge + - codex-agents-md-nesting +--- + +# Claude Code — mécanisme d'import @fichier pour CLAUDE.md + +Recherche du 2026-07-16, motivée par l'issue mA.xI.me #27 (l'installateur écrase un CLAUDE.md project-specific existant). + +## Ce qui est confirmé (sourcé) + +- La syntaxe `@chemin/fichier` est un import officiel et documenté : chemins relatifs (résolus par rapport au fichier qui importe, pas au cwd) ou absolus. Récursion jusqu'à 4 niveaux. Le parseur d'imports ignore les blocs de code et le code inline (`@README` entre backticks reste littéral). Source : https://code.claude.com/docs/en/memory +- **Directement pertinent** : la documentation Anthropic elle-même recommande exactement le pattern inverse de notre cas d'usage — pour un repo qui a déjà un AGENTS.md, créer un CLAUDE.md qui fait `@AGENTS.md` puis ajoute du contenu Claude-spécifique en dessous. Ça confirme qu'une ligne `@import` est un contenu stable, générable par un outil : le générateur peut toujours émettre la même ligne d'import, elle continuera à se résoudre tant que le fichier cible existe. +- Les CLAUDE.md de l'arborescence sont concaténés, jamais remplacés — le fichier du dossier parent charge avant celui du cwd, et `CLAUDE.local.md` est ajouté après `CLAUDE.md` dans le même dossier. +- `/init` ne réécrit jamais un CLAUDE.md existant — il propose seulement des améliorations. +- Alternative sans syntaxe d'import du tout : `.claude/rules/*.md` — tout fichier `.md` déposé là charge automatiquement (même priorité que `.claude/CLAUDE.md`), scopable par `paths:` en frontmatter. Symlinks supportés pour partager des règles entre repos. +- La première utilisation d'un import externe déclenche une boîte de dialogue d'approbation ponctuelle ; refuser désactive silencieusement les imports pour le projet en permanence (risque d'échec silencieux si l'utilisateur a cliqué "non" une fois). + +## Incertitudes explicites + +- Aucune confirmation de mainteneur que les imports sont fiables à 100% : issue GitHub ouverte #2950 (anthropics/claude-code) rapporte que l'import est chargé en contexte mais Claude n'agit pas toujours dessus de façon déterministe (problème d'adhérence du modèle, pas de résolution de fichier). +- Plusieurs rapports de bugs de résolution/imbrication de chemins @ : #8533 (Claude n'écrit pas toujours la syntaxe @ correctement quand on le lui demande), #1041 (l'import échoue spécifiquement dans le CLAUDE.md global ~/.claude/CLAUDE.md), #5231, #7768 (comportement erratique sur des imports imbriqués/relatifs). Rien n'indique que ce soit corrigé à la date de cette recherche. +- Aucun fil Reddit/Discord trouvé spécifiquement sur un outil générateur qui réécrit CLAUDE.md pendant que les imports survivent — le cas le plus proche est l'exemple AGENTS.md d'Anthropic ci-dessus, direct mais pas issu de la communauté. + +## Recommandation pour mA.xI.me (issue #27) + +Deux mécanismes natifs viables : (a) le générateur émet toujours une ligne fixe `@project-conventions.md` (ou nom similaire) — la doc Anthropic elle-même valide ce pattern exact ; ou (b) ne jamais toucher CLAUDE.md pour du contenu projet, et faire écrire par l'installateur dans `.claude/rules/*.md` à la place — élimine le problème à la racine puisque le générateur ne possède jamais ce fichier. + +## Sources +- https://code.claude.com/docs/en/memory +- https://github.com/anthropics/claude-code/issues/2950 +- https://github.com/anthropics/claude-code/issues/8533 +- https://github.com/anthropics/claude-code/issues/1041 +- https://github.com/anthropics/claude-code/issues/5231 +- https://github.com/anthropics/claude-code/issues/7768 diff --git a/md/active/codex-config/codex-agents-md-nesting.md b/md/active/codex-config/codex-agents-md-nesting.md new file mode 100644 index 0000000..cee290d --- /dev/null +++ b/md/active/codex-config/codex-agents-md-nesting.md @@ -0,0 +1,45 @@ +--- +id: codex-agents-md-nesting +type: reference +title: OpenAI Codex — imbrication et fusion des fichiers AGENTS.md +theme: codex-config +tags: + - codex + - agents-md + - config-merge +scope: global +status: active +confidence: fact +audience: generic +source: + - https://learn.chatgpt.com/docs/agent-configuration/agents-md +validated: 2026-07-16 +created: 2026-07-16 +links: + - claude-md-import-mechanism + - copilot-instructions-merge +--- + +# OpenAI Codex — imbrication et fusion des fichiers AGENTS.md + +Recherche du 2026-07-16, motivée par l'issue mA.xI.me #27. + +## Ce qui est confirmé (sourcé) + +- Support officiel de fichiers AGENTS.md imbriqués, fusionnés de la racine vers la feuille, concaténés avec des lignes vides ; les fichiers les plus proches du cwd sont ajoutés en dernier et peuvent surcharger les instructions précédentes. Source : https://learn.chatgpt.com/docs/agent-configuration/agents-md +- Un mécanisme explicite AGENTS.override.md existe, au niveau global (~/.codex/) comme à tout niveau de dossier projet ; Codex vérifie d'abord la présence d'un override, puis se rabat sur AGENTS.md, puis sur les noms de fallback configurés — au plus un fichier utilisé par dossier. +- Aucune syntaxe d'import/inclusion à l'intérieur d'un seul AGENTS.md — la fusion est purement basée sur la hiérarchie de dossiers. +- Plafond de taille : 32 KiB combinés par défaut (project_doc_max_bytes), configurable. +- Le site de spécification communautaire agents.md corrobore : "le AGENTS.md le plus proche gagne", conçu explicitement pour des instructions par paquet dans des monorepos (cite le repo d'OpenAI lui-même utilisant 88 fichiers AGENTS.md). + +## Incertitudes explicites + +- Aucune issue GitHub ni fil Reddit/HN trouvé spécifiquement sur un outil qui réécrit un contenu AGENTS.md écrit à la main — les recherches n'ont renvoyé que de la documentation officielle ou dérivée, aucun fil de plainte concret. +- Aucune couverture YouTube trouvée traitant spécifiquement de ce problème de coexistence. + +## Recommandation pour mA.xI.me (issue #27) + +Partielle : pas de syntaxe d'import, mais le mécanisme override + fichiers imbriqués donne une voie équivalente — plus directement, faire écrire par le générateur dans AGENTS.override.md au lieu de AGENTS.md au même niveau de dossier, laissant tout AGENTS.md pré-existant écrit à la main intact et toujours utilisé comme couche de base que l'override étend. C'est un détournement du mécanisme (les fichiers override étaient conçus pour restreindre, pas pour séparer outil/humain) — à traiter comme fonctionnel mais non validé par la doc pour cet usage précis. + +## Sources +- https://learn.chatgpt.com/docs/agent-configuration/agents-md diff --git a/md/active/engine-catalog/claude-code-models.md b/md/active/engine-catalog/claude-code-models.md new file mode 100644 index 0000000..8fb5afb --- /dev/null +++ b/md/active/engine-catalog/claude-code-models.md @@ -0,0 +1,55 @@ +--- +id: claude-code-models +type: reference +title: Claude Code — moteurs (modèles) et effort, catalogue + qui décide +theme: engine-catalog +tags: + - claude-code + - models + - effort + - subagents + - engine-catalog +scope: global +status: active +confidence: fact +audience: generic +source: + - https://code.claude.com/docs/en/sub-agents + - https://code.claude.com/docs/en/agent-sdk/subagents + - https://platform.claude.com/docs/en/build-with-claude/effort + - https://github.com/anthropics/claude-code/issues/25669 +validated: 2026-07-16 +created: 2026-07-16 +links: + - copilot-models + - codex-models +--- + +# Claude Code — moteurs (modèles) et effort + +## Deux axes distincts, pas un seul + +Claude Code expose deux réglages indépendants, avec des règles d'auto-configuration différentes pour chacun — à ne pas confondre : + +1. **`model`** (moteur) : `sonnet`, `opus`, `haiku`, `fable`, `inherit`, ou un ID de modèle complet (ex. `claude-opus-4-8`). +2. **`effort`** : `low`, `medium`, `high` (défaut), `xhigh`, `max` — contrôle la profondeur de réflexion et le volume de tokens dépensés, indépendamment du modèle choisi. + +Correction par rapport à une hypothèse de recherche antérieure (2026-07-16, avant cette fiche) : l'effort n'est **plus** "encodé dans le choix du modèle" — c'est un paramètre API à part entière (`output_config.effort`), disponible sur Claude Fable 5, Claude Mythos 5, Opus 4.5 à 4.8, Sonnet 5, Sonnet 4.6. Il affecte tous les tokens de la réponse (texte, appels d'outils, réflexion étendue), pas seulement la réflexion. + +## Qui peut configurer quoi + +- **`model` par sous-agent : auto-configurable, confirmé.** Le paramètre `model` de l'outil `Agent`/`Task` (dans cet environnement même) prend le pas sur la définition de l'agent (frontmatter `model:`), documenté "takes precedence over the agent definition's model frontmatter". Un orchestrateur peut donc choisir le modèle d'un sous-agent qu'il délègue, sans intervention humaine à chaque appel. Défaut du frontmatter : `inherit` (même modèle que la session principale) si non précisé. +- **`model` pour l'agent en cours (pas un sous-agent) : PAS auto-configurable.** Rien ne permet à l'agent en cours d'exécution de changer son propre modèle en cours de session par une action programmatique (un humain peut le faire via `/fast` ou le picker, mais c'est une commande, pas une action de l'agent lui-même). +- **`effort` : PAS configurable par sous-agent, contrairement au modèle.** Sourcé sur une issue GitHub officielle (`anthropics/claude-code#25669`, feature request encore ouverte) : "All subagents inherit the session default as there is no way to set the main agent to high and subagents to low." C'est un réglage de session, pas un paramètre de l'outil `Agent`/`Task` (vérifié directement : le schéma de cet outil dans cet environnement n'expose que `model`, aucun paramètre d'effort). + +## Conséquence pour Maxime + +Maxime (l'orchestrateur Claude) peut choisir lui-même le **modèle** d'un sous-agent qu'il délègue, informé par la taille de la tâche (S/M/L/XL) — capacité technique réelle, sans confirmation humaine requise à chaque appel. Il ne peut en revanche pas différencier l'**effort** par sous-agent : c'est un réglage de session, identique pour tous les agents de la conversation en cours, changé par un humain (menu effort de Claude Code, ou API `output_config.effort` en dehors de Claude Code). + +## Note annexe — "ultracode" + +"ultracode" apparaît dans le menu effort de Claude Code mais n'est pas un niveau d'effort API supplémentaire : ça combine `xhigh` avec une permission permanente de lancer des workflows multi-agents (mécanisme "Mid-conversation system messages"). Mentionné pour éviter de le confondre avec un 6e niveau d'effort — il n'y en a que 5 (`low`/`medium`/`high`/`xhigh`/`max`), tous documentés sur la page source `effort`. + +## Ce qui reste incertain + +- Le menu effort de Claude Code (accessible par un humain) n'a pas de commande/flag documenté officiellement pour être piloté par un script/agent plutôt qu'une interaction utilisateur directe — non vérifié plus loin, hors périmètre de cette fiche. diff --git a/md/active/engine-catalog/codex-models.md b/md/active/engine-catalog/codex-models.md new file mode 100644 index 0000000..a4fc832 --- /dev/null +++ b/md/active/engine-catalog/codex-models.md @@ -0,0 +1,46 @@ +--- +id: codex-models +type: reference +title: Codex — moteurs (modèles) et effort, catalogue + qui décide +theme: engine-catalog +tags: + - codex + - models + - effort + - engine-catalog +scope: global +status: active +confidence: fact +audience: generic +source: + - https://learn.chatgpt.com/docs/config-file/config-reference + - https://learn.chatgpt.com/docs/config-file/config-advanced + - https://github.com/openai/codex/issues/11795 +validated: 2026-07-16 +created: 2026-07-16 +links: + - claude-code-models + - copilot-models +--- + +# Codex — moteurs (modèles) et effort + +## Correction d'une hypothèse de recherche antérieure + +La spec de travail précédente (2026-07-16, avant cette fiche) citait une source tierce non officielle (`codex.danielvaughan.com`, un blog) affirmant que Codex serait "probablement auto-configurable via un fichier de config par agent". **Vérifié sur source officielle OpenAI ce jour et infirmé** : `model` et `model_reasoning_effort` sont des réglages **globaux/de profil**, pas par agent ou sous-agent. + +## Ce qui est confirmé sur source officielle + +- **`model`** (ex. `gpt-5.5`) et **`model_reasoning_effort`** (`none`/`minimal`/`low`/`medium`/`high`/`xhigh` — `xhigh` dépend du modèle ; s'applique à la Responses API uniquement) sont définis dans `~/.codex/config.toml`, au niveau global de l'utilisateur. +- **Profils** : des couches de configuration nommées, activées via `--profile nom-du-profil` en CLI, qui surchargent la config de base — un choix fait **avant le lancement**, par un humain (ou un script qui invoque la CLI), jamais pendant une session en cours. +- **Aucune surcharge par agent, sous-agent, session ou requête individuelle n'est documentée** pour `model`/`model_reasoning_effort`. Une section `[agents]` existe bien dans `config.toml` pour configurer des **rôles** de sous-agents, mais rien dans la documentation officielle ne montre qu'elle couvre le modèle ou l'effort — elle configure autre chose (comportement/rôle, pas moteur). +- **Aucun mécanisme documenté pour qu'une session Codex en cours change son propre modèle ou effort en cours de route** — fixé au lancement par la configuration. +- Confirmation supplémentaire par l'absence : une issue GitHub officielle du dépôt `openai/codex`, encore ouverte, demande explicitement cette capacité ("Allow configuring subagent model and reasoning_effort in config", [#11795](https://github.com/openai/codex/issues/11795)) — la demande elle-même confirme que ça n'existe pas encore. + +## Conséquence pour Maxime + +Traiter Codex comme Copilot, pas comme Claude Code : Maxime ne peut pas configurer lui-même le modèle ou l'effort pour une tâche ou un sous-agent Codex. Il peut seulement **recommander** un modèle/effort informé par le catalogue et **demander** à l'utilisateur de le sélectionner (choix de profil ou flag `--model`/`--config model_reasoning_effort=...` avant le lancement). Repasser en mode "auto-configurable comme Claude" seulement si OpenAI documente officiellement une surcharge par agent/sous-agent dans une future version — revalider ce point avant de le considérer comme stable. + +## Ce qui reste incertain + +- Le contenu exact de la section `[agents]` (quels attributs de "rôle" elle couvre réellement) n'a pas été creusé en détail — hors périmètre de cette fiche, qui se limite à la question modèle/effort. diff --git a/md/active/engine-catalog/copilot-models.md b/md/active/engine-catalog/copilot-models.md new file mode 100644 index 0000000..17c7ab6 --- /dev/null +++ b/md/active/engine-catalog/copilot-models.md @@ -0,0 +1,51 @@ +--- +id: copilot-models +type: reference +title: GitHub Copilot — moteurs (modèles) et effort, catalogue + qui décide (CLI/VS Code et cloud agent) +theme: engine-catalog +tags: + - copilot + - models + - effort + - cloud-agent + - engine-catalog +scope: global +status: active +confidence: fact +audience: generic +source: + - https://docs.github.com/en/copilot/reference/custom-agents-configuration + - https://github.com/github/copilot-cli/issues/2758 + - https://github.com/github/copilot-cli/issues/2904 + - https://docs.github.com/en/copilot/how-tos/use-copilot-agents/coding-agent/changing-the-ai-model + - https://github.blog/changelog/2026-05-14-copilot-cloud-agent-supports-auto-model-selection/ + - https://github.blog/changelog/2026-04-14-model-selection-for-claude-and-codex-agents-on-github-com/ +validated: 2026-07-16 +created: 2026-07-16 +links: + - claude-code-models + - codex-models +--- + +# GitHub Copilot — moteurs (modèles) et effort + +Deux surfaces distinctes chez Copilot, vérifiées séparément : les agents personnalisés CLI/VS Code (fichiers `.agent.md`) et le **cloud agent** (github.com — issues assignées, commentaires `@copilot`, agents tab). Conclusion identique sur le fond pour les deux : **jamais auto-configurable par l'agent lui-même**, mais les mécanismes diffèrent. + +## CLI / VS Code (agents personnalisés `.agent.md`) + +- **`model` : fixé par un humain à l'écriture du fichier, jamais changé par l'agent en cours d'exécution.** Le frontmatter `model:` d'un agent personnalisé contrôle le modèle utilisé (VS Code, JetBrains, Eclipse, Xcode). Un `model` passé programmatiquement à un appel `task()` est **silencieusement ramené au modèle de session par défaut** — confirmé par une issue GitHub officielle du dépôt `github/copilot-cli` encore ouverte ([#2758](https://github.com/github/copilot-cli/issues/2758), présentée comme un garde-fou de coût intentionnel, pas un bug). +- **`effort` : n'existe pas dans le frontmatter d'agent personnalisé aujourd'hui.** Feature request encore ouverte ([#2904](https://github.com/github/copilot-cli/issues/2904), "Custom Agent YAML Frontmatter Should Support Reasoning Effort") — pas de mécanisme équivalent au `effort`/`model_reasoning_effort` de Claude ou Codex côté Copilot à ce jour. Seul un humain change le modèle, via `/model` ou le picker VS Code ; il n'y a rien d'équivalent à changer pour l'effort. + +## Cloud agent (github.com) + +- **`model` : sélection humaine uniquement, confirmée explicitement.** "Only human users select the model. The agent does not programmatically choose or change its model during a task." Disponible aux points d'entrée supportés : assignation d'issue, mention `@copilot` en commentaire de PR, agents tab/panel, GitHub Mobile, lanceur Raycast. Modèles proposés (2026) : Claude Opus 4.5/4.6, Claude Sonnet 4.5/4.6, Claude Haiku 4.5, GPT-5.1-Codex-Max, GPT-5.2/5.3-Codex, GPT-5.4-mini. +- **Option "Auto" : une troisième voie, ni humaine au cas par cas, ni agent.** Si l'utilisateur sélectionne "Auto" dans le picker (choix humain fait une fois, avant la tâche), la plateforme elle-même choisit ensuite le modèle "based on system health and model performance" — routage de plateforme, pas une décision de l'agent en cours de tâche. Avantage : remise de 10% sur le multiplicateur, exempté des limites de débit hebdomadaires. +- **`effort` : aucune mention dans la documentation officielle du cloud agent.** Pas de sélecteur d'effort trouvé pour cette surface. + +## Conséquence pour Maxime + +Sur les trois surfaces Copilot (CLI, VS Code, cloud agent), Maxime ne peut ni choisir ni faire varier le modèle ou l'effort par lui-même : il peut seulement **recommander** un choix informé par le catalogue et **demander** à l'utilisateur de le faire (via `/model`, le picker VS Code, ou le picker du cloud agent) — contrainte de plateforme, pas un choix de conception mA.xI.me. + +## Ce qui reste incertain + +- Aucune source officielle ne documente un sélecteur d'effort pour le cloud agent — absence constatée dans les pages consultées, pas une confirmation qu'il n'existe nulle part sur la plateforme. diff --git a/md/active/governance/sailpoint-identityiq.md b/md/active/governance/sailpoint-identityiq.md new file mode 100644 index 0000000..0c1a816 --- /dev/null +++ b/md/active/governance/sailpoint-identityiq.md @@ -0,0 +1,47 @@ +--- +id: sailpoint-identityiq +type: reference +title: SailPoint IdentityIQ (IIQ) — gouvernance d'accès et workflows d'approbation +theme: governance +tags: + - iam + - iga + - sailpoint + - access-request + - approval + - sod +scope: global +status: active +confidence: fact +audience: generic +source: + - https://documentation.sailpoint.com/saas/help/requests/index.html + - https://documentation.sailpoint.com/saas/help/requests/config_ap_roles.html + - https://developer.sailpoint.com/docs/api/v3/access-request-approvals/ +validated: 2026-07-18 +created: 2026-07-18 +links: + - servicenow-itsm-change-management +--- + +# SailPoint IdentityIQ (IIQ) + +Plateforme IGA (Identity Governance and Administration). Rôle générique : gérer le cycle de vie complet des demandes d'accès — de la demande à l'approbation puis au provisioning — avec un contrôle de politique et une trace d'audit à chaque étape. + +## Flux de demande d'accès type + +Un utilisateur (ou son manager) demande un accès (rôle, entitlement, groupe) → IdentityIQ vérifie la demande contre les politiques de séparation des tâches (SoD — Segregation/Separation of Duties) et autres règles → la demande est routée vers le ou les approbateurs pertinents → une fois approuvée, l'accès est provisionné automatiquement. Chaque étape est journalisée — c'est la trace d'audit sur laquelle s'appuient les équipes conformité. + +## Chemins d'approbation configurables + +Pour un entitlement/access profile : approbation par le owner de l'access profile, le owner de l'application, le owner de la source, le manager du demandeur, ou un groupe de gouvernance dédié. +Pour un rôle : mêmes options (owner du rôle, manager, groupe de gouvernance). +Des chemins d'approbation dynamiques peuvent varier selon le type d'accès demandé, le rôle du demandeur, et un niveau de risque calculé — les demandes à haut risque déclenchent une revue plus stricte, les demandes à faible risque peuvent être accélérées. + +## Gouvernance des rôles (Role Lifecycle) + +IdentityIQ gère le cycle de vie complet d'un rôle : création/modification via le Role Editor, avec possibilité de déclencher un workflow d'approbation avant qu'un changement de rôle ne soit promu en production. Pertinent pour la gouvernance de l'appartenance à un groupe AD sensible (ex. groupe Tier 0/Control Plane) : la double approbation pour rejoindre un tel groupe s'appuie typiquement sur ce mécanisme. + +## API REST + +IdentityIQ expose une API REST pour les demandes d'accès et leurs approbations (`access-request-approvals`). Pertinent pour toute vérification API-à-API future entre un système consommateur et IIQ, plutôt qu'une simple confiance déclarative dans un jeton émis. diff --git a/md/active/governance/servicenow-itsm-change-management.md b/md/active/governance/servicenow-itsm-change-management.md new file mode 100644 index 0000000..d79f347 --- /dev/null +++ b/md/active/governance/servicenow-itsm-change-management.md @@ -0,0 +1,48 @@ +--- +id: servicenow-itsm-change-management +type: reference +title: ServiceNow — tickets et workflow d'approbation (ITSM Change Management) +theme: governance +tags: + - itsm + - servicenow + - change-management + - ticket + - cab + - approval +scope: global +status: active +confidence: fact +audience: generic +source: + - https://www.servicenow.com/community/itsm-articles/change-management-process-workflow/ta-p/2299141 + - https://www.servicenow.com/community/itsm-forum/change-management-in-servicenow-everything-you-need-to-know/m-p/3439058 +validated: 2026-07-18 +created: 2026-07-18 +links: + - sailpoint-identityiq +--- + +# ServiceNow — ITSM Change Management + +Outil ITSM (IT Service Management), suit les pratiques ITIL. Rôle générique pertinent ici : gérer un ticket (change request) à travers un cycle de vie standardisé, avec approbation avant exécution — utilisable comme preuve d'autorisation pour des flux qui n'exigent pas une gouvernance IGA complète (voir IIQ) mais où une trace de validation formelle reste requise. + +## Types de demande de changement + +Trois catégories, chacune avec son propre niveau de revue et d'évaluation du risque : +- **Standard** — changement pré-approuvé, à faible risque, répétitif +- **Normal** — passe par le cycle de revue complet +- **Emergency** — changement urgent, cycle de revue accéléré mais toujours tracé + +## Étapes du workflow d'approbation type + +1. **Évaluation initiale** — le Change Coordinator évalue la demande et la soumet à l'approbation du manager +2. **Approbation manager** — approuve (la demande passe au CAB) ou rejette +3. **Revue CAB** (Change Advisory Board) — approuve, ou propose des modifications +4. **Implémentation** — un changement ne peut pas passer en implémentation tant que toutes les approbations requises ne sont pas obtenues + +Rôles impliqués : Change Owner, Change Manager, Change Initiator, membres du CAB, équipes techniques. + +## Pertinence pour un modèle d'autorisation + +Un ticket ServiceNow correctement approuvé peut servir de preuve d'autorisation suffisante pour des flux à risque modéré, sans exiger le passage par un outil de gouvernance IGA complet (IIQ) à chaque appel — utile pour distinguer les cas où une gouvernance humaine légère suffit de ceux qui exigent le cycle complet. diff --git a/md/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.md b/md/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.md new file mode 100644 index 0000000..2e9e00e --- /dev/null +++ b/md/active/hybrid-identity/hybrid-identity-entra-security-impact-inventory.md @@ -0,0 +1,101 @@ +--- +id: hybrid-identity-entra-security-impact-inventory +type: reference +title: Environnement hybride AD DS / Microsoft Entra ID — inventaire des impacts de sécurité à résoudre +theme: hybrid-identity +tags: + - ad-ds + - entra-id + - hybrid-identity + - entra-connect + - cloud-sync + - pta + - phs + - adfs + - control-plane +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://learn.microsoft.com/en-us/entra/architecture/security-operations-introduction + - https://learn.microsoft.com/en-us/entra/architecture/security-operations-infrastructure + - https://learn.microsoft.com/en-us/entra/architecture/resilience-in-hybrid + - https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/choose-ad-authn + - https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-install-prerequisites + - https://learn.microsoft.com/en-us/entra/identity/hybrid/cloud-sync/what-is-cloud-sync + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/tier-model + - https://attack.mitre.org/techniques/T1484/ + - https://www.cyber.gov.au/business-government/asds-cyber-security-frameworks/ism/cyber-security-guidelines/guidelines-for-system-hardening +validated: 2026-07-25 +created: 2026-07-25 +links: + - enterprise-access-model + - ad-ds-tiered-administration-hardening + - ad-ds-threat-driven-control-map +--- + +# Statut + +Deuxième phase de l'étude. Cette fiche identifie les changements de périmètre et questions de sécurité créés par l'hybridation. Elle ne choisit ni méthode d'authentification, ni architecture de synchronisation, ni produit. + +# Changement de frontière + +L'hybridation crée une identité commune entre ressources on-premises et cloud et introduit de nouveaux flux de provisioning, synchronisation, authentification, administration et télémétrie. Les composants hybrides peuvent étendre le Tier 0/control plane. + +# Composants à classifier + +- Microsoft Entra Connect Sync ; +- Microsoft Entra Cloud Sync agents ; +- Pass-through Authentication agents ; +- AD FS et Web Application Proxy ; +- Entra Connect Health agents ; +- Private Network / Application Proxy connectors ; +- comptes de connecteur AD et Entra ; +- comptes de service/gMSA ; +- serveurs de staging ; +- clés, certificats et secrets ; +- rôles Entra et comptes d'urgence ; +- Conditional Access, PIM et Identity Protection ; +- Intune et autorités de politique des appareils ; +- SIEM, Azure Monitor et journaux Entra. + +# Impacts à analyser sans les résoudre + +| Domaine | Questions ouvertes | +|---|---| +| Source d'autorité | Quels attributs et objets sont maîtrisés dans AD, Entra ou une source tierce ? | +| Synchronisation | Quels objets, attributs, filtres, suppressions et transformations traversent la frontière ? | +| Authentification | PHS, PTA ou fédération : dépendances, résilience, surface d'attaque et mode de secours ? | +| Writeback | Quels changements cloud peuvent modifier AD DS et avec quels privilèges ? | +| Tiering | Quels composants, rôles cloud, consoles et opérateurs deviennent control plane/Tier 0 ? | +| Administration | Quels comptes, PAW, PIM/JIT, MFA et chemins sont nécessaires ? | +| Policy | Coexistence GPO, Intune, Conditional Access et autres autorités ; conflits et préséance ? | +| Appareils | AD Join, Hybrid Join, Entra Join, conformité et effets sur Tier 2 ? | +| Détection | Corrélation sign-ins, audit Entra, sync, AD FS/PTA, AD DS et endpoint ? | +| Résilience | Dépendance on-prem lors du sign-in, staging, panne cloud, panne WAN, perte de tenant ? | +| Compromission | Pivot AD vers Entra, Entra vers AD, fédération malveillante, compte cloud persistant ? | +| Récupération | Ordre de restauration, secrets de connecteur, configuration tenant et preuves ? | +| Réseau | Sorties Internet, endpoints, proxies, inspection TLS et segmentation ? | +| Cycle de vie | Version/auto-upgrade des agents, fin de support et ownership ? | +| Conformité | Résidence, journaux, licences, rôles et exigences sectorielles ? | + +# Faits structurants + +- PHS réduit la dépendance on-premises au moment de l'authentification cloud, mais synchronise un dérivé du hash de mot de passe. +- PTA dépend d'agents on-premises ayant accès aux DC ; Microsoft indique de traiter leur serveur comme un DC. +- La fédération ajoute une infrastructure de confiance, des certificats et des endpoints critiques. +- Entra Connect et les agents hybrides ajoutent une surface d'attaque et doivent être baselinés, surveillés et maintenus. +- Cloud Sync change le modèle opérationnel : agents légers on-premises et configuration davantage pilotée dans le cloud. +- Les méthodes peuvent exiger PHS comme résilience ou pour certaines fonctions de protection, même lorsque PHS n'est pas le mode principal. + +# Point d'arrêt + +La prochaine étape devra comparer des scénarios hybrides précis et leur modèle de menace. Cette fiche n'autorise pas à : + +- sélectionner PHS/PTA/fédération ; +- déclarer tous les composants identiques ; +- fusionner automatiquement GPO et Intune ; +- supposer que MFA cloud protège les accès natifs AD DS ; +- résoudre les conflits de source d'autorité ; +- décider de la cible Entra. diff --git a/md/active/powershell/native-exe-json-quoting.md b/md/active/powershell/native-exe-json-quoting.md new file mode 100644 index 0000000..8eaf3c2 --- /dev/null +++ b/md/active/powershell/native-exe-json-quoting.md @@ -0,0 +1,63 @@ +--- +id: native-exe-json-quoting +type: pattern +title: PowerShell 5.1 strips quotes when passing JSON to native executables +theme: powershell +tags: + - powershell + - aws-cli + - windows + - quoting +scope: global +status: active +confidence: fact +audience: generic +source: + - ouritres/coreapi/.claude/memory/spec-0-learnings.md +validated: 2026-07-16 +created: 2026-07-16 +links: + - unattended-deployment +--- + +# PowerShell 5.1 strips quotes when passing JSON to native executables + +## Problem + +When calling a Windows native executable (e.g. `aws.exe`, or any CLI outside the +PowerShell/.NET world) from PowerShell 5.1 with a JSON string argument, bare `"` +characters in that string get silently stripped before the native process ever sees +them. The native CLI then receives malformed JSON and fails to parse it — often with a +confusing error that looks like a CLI bug, not a quoting bug. + +## Why + +PowerShell does not perform the quote-escaping itself when marshalling arguments to a +native executable — argument parsing at that boundary is handled by Windows' +`CommandLineToArgvW`, which has its own (different) quoting rules. PowerShell's own +string quoting and the native process's argv parsing disagree, and bare `"` in the +value gets lost in translation. + +## Fix + +Escape every `"` in the JSON string as `\"` before passing it as an argument to a +native exe: + +```powershell +$escaped = $json -replace '"', '\"' +aws.exe some-command --cli-input-json $escaped +``` + +## Concrete case this was found in + +Generating an IAM trust policy / DCPROMO answer file as JSON and passing it to +`aws.exe` from a PowerShell 5.1 provisioning script (coreapi Spec 0) — parsing failed +until quotes were escaped this way. Several other approaches (writing to `file://`, +`ConvertTo-Json` piping, base64 encoding) were tried first; the root cause was only +found by running the exact `aws.exe` invocation manually and inspecting what it +actually received, rather than guessing at the JSON-generation side. + +## Applies to + +Any PowerShell 5.1 script that shells out to a native executable with a JSON (or any +quote-containing) string argument — not specific to AWS CLI or Active Directory. diff --git a/md/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.md b/md/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.md new file mode 100644 index 0000000..5b133c6 --- /dev/null +++ b/md/active/security-architecture/ad-ds-tier-model-microsoft-reference-implementation.md @@ -0,0 +1,86 @@ +--- +id: ad-ds-tier-model-microsoft-reference-implementation +type: reference +title: AD DS Tier Model (Microsoft OSS) — référence historique/comparative, PAS le modèle cible +theme: security-architecture +tags: + - ad-ds + - tiering + - tier-0 + - tier-1 + - tier-2 + - reference-historique + - comparatif + - non-cible + - deployment-methodology + - drift-detection + - gpo-management + - cmdlet-architecture + - powershell + - microsoft +scope: global +status: active +confidence: fact +audience: generic +source: + - https://microsoft.github.io/ActiveDirectoryTierModel/ + - https://microsoft.github.io/ActiveDirectoryTierModel/deployment-methodology/ + - https://microsoft.github.io/ActiveDirectoryTierModel/drift-detection-details/ + - https://microsoft.github.io/ActiveDirectoryTierModel/gpo-management-strategy/ + - https://microsoft.github.io/ActiveDirectoryTierModel/cmdlet-architecture/ +validated: 2026-08-08 +created: 2026-08-08 +links: + - enterprise-access-model + - ad-ds-tiered-administration-hardening + - ad-ds-gpo-acl-lifecycle-governance + - ad-ds-security-control-assurance-levels + - ad-ds-threat-driven-control-map +--- + +# Statut de cette fiche : référence historique/comparative — PAS le modèle cible + +Cette fiche indexe l'implémentation open-source de Microsoft du **Tier Model AD DS classique** (`microsoft/ActiveDirectoryTierModel` sur GitHub, doc publiée à https://microsoft.github.io/ActiveDirectoryTierModel/). Elle documente *comment Microsoft outille et déploie* le tiering Tier 0/1/2 en PowerShell. + +**Elle ne remplace ni ne prime sur les fiches EAM existantes** (`enterprise-access-model`, `zero-standing-access`, `security-framework-role-and-crosswalk`) ni sur le modèle de tiering appliqué dans ce repo (`ad-ds-tiered-administration-hardening`, `ad-ds-gpo-acl-lifecycle-governance`, `ad-ds-threat-driven-control-map`, `ad-ds-security-control-assurance-levels`). Le Tier Model classique est le **prédécesseur** de l'Enterprise Access Model (voir `enterprise-access-model`) — Microsoft continue de documenter et outiller le premier pour les organisations qui n'ont pas encore migré vers le second, pas comme direction recommandée future. + +**Usage prévu** : comparer une méthodologie d'outillage (déploiement idempotent, drift detection, structure de GPO, architecture de cmdlets) à ce qui existe déjà dans ce repo — pas y piocher un modèle de classification ou de gouvernance cible. + +# 1. Méthodologie de déploiement (`deployment-methodology`) + +- Approche **séquentielle et dépendante** en 10 phases, alignée sur un plan d'autorité (`plan.md`) pour satisfaire les dépendances et permettre la convergence : OUs → Groupes → Utilisateurs → délégations ACL → GPO (import/création/liaison) → templates ADMX → délégations optionnelles MSA/gMSA/dMSA/Windows LAPS. +- **Validation en couches** : pré-déploiement (schéma JSON, connectivité, permissions, dépendances), post-déploiement (création d'objets, application des ACL, liens GPO, comptage de fichiers), audit continu (rapports avec opérations ignorées documentées). +- **Idempotence** par "skip-rather-than-fail" : un objet existant déclenche un message INFO et n'est pas recréé — sauf les templates ADMX, toujours écrasés pour supporter les mises à jour. Les délégations sont vérifiées par présence du groupe de délégation dans le security descriptor de l'OU (pas de comparaison ACE par ACE). Support WhatIf/ShouldProcess pour dry-run. +- **Décision de conception notable** : la validation ne teste pas le contenu détaillé des GPO (User Rights Assignments, Restricted Groups, valeurs de registre) — seulement l'intégrité structurelle, car ces réglages "sont complexes et peuvent changer post-déploiement". +- Aucune correction automatique de l'ordre de liaison des GPO en cas de désalignement — intervention manuelle requise, pour éviter de casser accidentellement une séquence d'application de policy. +- Philosophie de rollback conservatrice : la plupart des objets sont conservés tels quels post-déploiement (les OU contiennent des enfants, les groupes peuvent avoir des membres ajoutés manuellement, etc.) — priorité à la stabilité et à la préservation des personnalisations locales plutôt qu'à un contrôle centralisé total. + +# 2. Drift detection (`drift-detection-details`) + +- Script `Audit-TierModel.ps1`, **lecture seule** (ne modifie jamais l'état), qui compare l'état AD réel à la configuration déclarée. +- Cmdlets modulaires `Test-TierModel*` par composant : `Test-TierModelOu`, `Test-TierModelGroup`, `Test-TierModelUser`, `Test-TierModelGpo`, `Test-TierModelGPOLink`, `Test-TierModelOuAcl`, `Test-TierModelAdmx` (hash MD5). Flags optionnels `-IncludeMsa`, `-IncludeGmsa`, `-IncludeDmsa`, `-IncludeWinLaps`. +- Constats catégorisés : `Missing`, `Mismatch`, `ExtraProtection`, `HashMismatch` — chacun avec type de ressource, identifiant, état attendu vs réel, sévérité. +- Sorties JSON (automatisation), HTML (parties prenantes), NUnit XML (intégration CI/CD). +- Boucle de remédiation : audit → revue des constats → plan correctif → `Deploy-TierModel.ps1` ciblé → nouvel audit pour confirmer la fermeture de l'écart. +- Export JSON horodaté permettant le suivi de conformité dans le temps ; intégration CI/CD (GitHub Actions, Azure DevOps) pour audits automatisés quotidiens ou déclenchés par événement. + +# 3. GPO management strategy (`gpo-management-strategy`) + +- Approche **à deux niveaux par OU** : `ImportOnlyGpo` (GPO créées depuis un template sans configuration post-déploiement, modes `create` / `createAndImport` / setup manuel) et `PostConfigureGpo` (GPO nécessitant une configuration dynamique des User Rights Assignments et Restricted Groups après import). +- Trois modes de déploiement : `create` (GPO vide), `createAndImport` (import de baseline/template Microsoft), `createImportAndConfigure` (import + configuration dynamique URA/RG). +- Configuration pilotée par JSON : liaison dynamique de principals (groupes résolvables, assignation forest-root-only, inclusion conditionnelle selon l'existence d'un groupe, comptes de service en dur), contrôle des groupes locaux (Restricted Groups) via SID, security filtering via `denyApplyGroupPolicy`. Dédoublonnage des SID avant génération des blocs ; ordre déterministe suivant la définition JSON. +- Optimisation : propriété `gpoStatus` désactivant les sections de traitement inutilisées (ex. `UserSettingsDisabled` pour les policies machine uniquement) ; logique conditionnelle adaptant la configuration entre forest root et domaines enfants. + +# 4. Cmdlet architecture (`cmdlet-architecture`) + +- Séparation stricte de deux modes pour éviter les conflits de validation : + - **Phase-Specific** : validation "fail fast", suppose que les prérequis existent déjà (déploiement incrémental piloté manuellement phase par phase). + - **Full Deployment** : validation plus légère, suppose que les dépendances seront créées dans le bon ordre pendant une exécution automatisée complète. +- Pattern : duplication des cmdlets `Get-TierModel*` existants en variantes "Fd" (Full Deployment) plutôt que modification des cmdlets phase-specific — ex. `Get-TierModelGroup` → `Get-TierModelGroupFd`. Les cmdlets phase-specific restent inchangés et stables, ce qui permet un test indépendant de chaque mode sans risque de régression. +- Les phases optionnelles (MSA/gMSA/dMSA/Windows LAPS) suivent le même pattern avec des jeux de cmdlets Get/New/Test parallèles pour planification, application et audit. + +# Ce que cette fiche n'est pas + +- Pas un modèle de classification de sensibilité (→ voir `enterprise-access-model` pour les control/management/data-workload planes). +- Pas la référence de durcissement appliquée dans ce repo (→ voir `ad-ds-tiered-administration-hardening`, `ad-ds-gpo-acl-lifecycle-governance`, `ad-ds-threat-driven-control-map`, `ad-ds-security-control-assurance-levels`). +- Pas une recommandation de migrer vers ce tooling précis — c'est un point de comparaison pour évaluer/valider des choix de conception (idempotence, drift detection, structure GPO, séparation phase-specific/full-deployment) déjà pris ou à prendre ailleurs dans ce repo. diff --git a/md/active/security-architecture/ad-ds-tiered-administration-hardening.md b/md/active/security-architecture/ad-ds-tiered-administration-hardening.md new file mode 100644 index 0000000..b54e426 --- /dev/null +++ b/md/active/security-architecture/ad-ds-tiered-administration-hardening.md @@ -0,0 +1,105 @@ +--- +id: ad-ds-tiered-administration-hardening +type: pattern +title: AD DS — durcissement de l'administration Tier 0, Tier 1 et Tier 2 +theme: security-architecture +tags: + - ad-ds + - tier-0 + - tier-1 + - tier-2 + - paw + - privileged-access + - least-privilege +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/tier-model + - https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/best-practices-for-securing-active-directory + - https://messervices.cyber.gouv.fr/guides/recommandations-pour-ladministration-securisee-des-si-reposant-sur-ad + - https://www.cyber.gc.ca/en/guidance/practitioner-guidance-securing-microsoft-active-directory-services-your-organization-itsp60100 + - https://public.cyber.mil/stigs/downloads/ +validated: 2026-07-25 +created: 2026-07-25 +links: + - enterprise-access-model + - zero-standing-access + - ad-ds-domain-controller-security-hardening + - ad-ds-gpo-acl-lifecycle-governance +--- + +# Modèle + +Le tiering sépare identités, postes d'administration, intermédiaires et actifs selon leur pouvoir de contrôle. La confiance commence sur le poste où le secret est saisi, pas seulement sur la destination. + +| Tier | Portée | Exemples | +|---|---|---| +| Tier 0 | Control plane identité | DC, AD CS, AD FS, Entra Connect, comptes/groupes et outils capables de les contrôler | +| Tier 1 | Serveurs et applications d'entreprise | Serveurs membres, plateformes, applications métier et leurs administrateurs | +| Tier 2 | Utilisateurs et terminaux | Comptes utilisateurs, postes, support et administration de terminaux | + +Le modèle Enterprise Access Model élargit cette lecture aux control, management et data/workload planes. Il ne rend pas inutile la séparation technique des tiers AD DS. + +# Principes de durcissement + +1. Aucune identité administrative ne traverse plusieurs tiers. +2. Aucun secret d'un tier supérieur n'est saisi, stocké ou mis en cache dans un tier inférieur. +3. Tout poste, bastion, coffre, hyperviseur ou agent hérite du tier maximal des secrets ou capacités qu'il touche. +4. Les PAW sont dédiées, durcies, sans messagerie ni navigation générale. +5. Les comptes personnels et administratifs sont distincts. +6. Les groupes d'administration sont fonctionnels et minimaux ; Domain Admins n'est pas un rôle quotidien. +7. Les délégations remplacent les appartenances permanentes quand elles suffisent. +8. Les accès temporaires/JIT et l'absence de droits permanents sont préférés lorsqu'ils sont techniquement et opérationnellement maîtrisés. +9. Les chemins d'administration et leurs intermédiaires sont inventoriés, surveillés et testés. +10. Les tiers sont des frontières de contrôle, pas seulement des OU ou des VLAN. + +# Contrôles par tier + +## Tier 0 + +- PAW Tier 0 ; +- accès restreint aux fonctions de contrôle identité ; +- authentification forte et mécanismes résistants au phishing sur les interfaces disponibles ; +- aucune dépendance de gestion contrôlée depuis Tier 1/2 ; +- surveillance renforcée et preuve des changements ; +- reprise et comptes de secours séparés. + +## Tier 1 + +- comptes et PAW serveur distincts ; +- interdiction de contrôler Tier 0 ; +- segmentation par rôle/zone lorsque nécessaire ; +- administration distante sans exposition inutile de credentials ; +- service accounts limités au Tier 1. + +## Tier 2 + +- support des utilisateurs et terminaux avec comptes dédiés ; +- LAPS et contrôle de l'administration locale ; +- réduction des mouvements latéraux ; +- aucune présence de credentials Tier 0/1 ; +- postes d'administration distincts lorsque le support dispose de privilèges étendus. + +# Actifs dont le tier est souvent sous-estimé + +- hyperviseurs hébergeant des DC ; +- sauvegarde et restauration de DC ; +- PKI d'entreprise ; +- GPO et comptes pouvant les modifier ; +- outils de déploiement/patching sur DC ; +- systèmes EDR/SIEM avec contrôle actif ; +- DNS et temps lorsqu'une compromission permet le contrôle identité ; +- Entra Connect, PTA, AD FS et agents hybrides ; +- consoles matérielles et opérateurs d'hébergement. + +# Preuves futures + +- matrice identité × poste × cible × intermédiaire ; +- règles de refus de logon par tier ; +- inventaire des comptes/groupes/services ; +- sessions et chemins administratifs ; +- tests d'absence de credential exposure ; +- revue des systèmes qui peuvent modifier, restaurer ou exécuter sur chaque tier. diff --git a/md/active/security-architecture/enterprise-access-model.md b/md/active/security-architecture/enterprise-access-model.md new file mode 100644 index 0000000..3d28a22 --- /dev/null +++ b/md/active/security-architecture/enterprise-access-model.md @@ -0,0 +1,47 @@ +--- +id: enterprise-access-model +type: glossary +title: Enterprise Access Model (EAM) — plans de sensibilité Microsoft +theme: security-architecture +tags: + - eam + - tiering + - control-plane + - management-plane + - data-workload-plane + - microsoft +scope: global +status: active +confidence: fact +audience: generic +source: + - https://learn.microsoft.com/en-us/security/privileged-access-workstations/privileged-access-access-model +validated: 2026-07-18 +created: 2026-07-18 +links: + - zero-standing-access +--- + +# Enterprise Access Model (EAM) + +Successeur du modèle de tiering AD classique (Tier 0/1/2). Remplace la hiérarchie linéaire par trois **plans de sensibilité**. Un plan décrit *où vit un actif et à quel niveau de sensibilité*, pas *comment on y accède* — c'est un axe distinct du chemin d'accès/gouvernance (voir la nuance dans les décisions spécifiques à chaque projet, pas dans cette fiche générique). + +## Les trois plans + +| Plan | Contenu | Exemple | +|---|---|---| +| **Control Plane** | Les systèmes qui contrôlent l'identité et la sécurité elles-mêmes — équivaut à l'ancien Tier 0 | Domain Admins, Enterprise Admins, Schema Admins, structure des ACL, systèmes d'identité centralisés | +| **Management Plane** | Fonctions de gestion IT à l'échelle de l'entreprise — gouverne les workloads et l'infrastructure qui les héberge | Outils de gouvernance/gestion (IIQ, ServiceNow, PAM), gestion d'infrastructure on-prem/cloud | +| **Data/Workload Plane** | Les applications et données — l'essentiel de la valeur métier à protéger | Applications métier, services applicatifs, bases de données, données métier | + +## Principe clé + +**Enforce hierarchy** — empêcher qu'un plan de niveau supérieur (plus sensible) soit contrôlé depuis un plan inférieur, que ce soit par attaque ou par abus d'un processus légitime. Le Data/Workload plane est gouverné par le Management plane, qui est lui-même protégé par le Control plane — jamais l'inverse. + +## Erreur fréquente à éviter + +Ne pas faire correspondre les plans 1-pour-1 avec des "chemins d'accès techniques" (ex. compte utilisateur / compte applicatif / compte privilégié). Le nombre de chemins d'accès techniques qu'une organisation choisit d'implémenter est une décision d'architecture propre à chaque système — pas une conséquence mécanique du nombre de plans EAM. + +## Cas particulier : objets d'un système d'identité (ex. Active Directory) + +Un système d'identité (AD DS et équivalents) est lui-même structurellement adjacent au Control Plane, quel que soit le type d'objet qu'il contient — administrer un objet, même un compte utilisateur ordinaire, n'est pas une opération Data/Workload (qui désigne la donnée métier/applicative, pas l'infrastructure d'identité qui la protège). Ne pas classer les comptes utilisateurs/de service/groupes comme des exemples de Data/Workload. La classification correcte pour ce type d'objet passe par une cascade de tier (Tier 0/1/2, avec défaut fail-secure sur Tier 0 en cas d'ambiguïté) combinée à la capacité de contrôle exercée par le geste — voir la fiche `zero-standing-access` et, pour un modèle complet appliqué à AD DS, la documentation du projet consommateur concerné (ex. `ad-ds-governance-model.md` dans coreapi). diff --git a/md/active/security-architecture/zero-standing-access.md b/md/active/security-architecture/zero-standing-access.md new file mode 100644 index 0000000..77552c9 --- /dev/null +++ b/md/active/security-architecture/zero-standing-access.md @@ -0,0 +1,41 @@ +--- +id: zero-standing-access +type: glossary +title: Zero standing access, secretless, et gMSA — principes +theme: security-architecture +tags: + - zero-standing-access + - secretless + - gmsa + - jit + - pam +scope: global +status: active +confidence: fact +audience: generic +source: + - https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/group-managed-service-accounts/group-managed-service-accounts-overview + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-linux-gmsa.html +validated: 2026-07-18 +created: 2026-07-18 +links: + - enterprise-access-model +--- + +# Zero standing access, secretless, gMSA + +Trois principes distincts, souvent combinés, à ne pas confondre. + +## Zero standing access (zero standing privilege) + +Un compte ne détient **aucun privilège actif en permanence** — le privilège est accordé (élévation, activation, bail temporaire) seulement pour la fenêtre d'usage, puis retiré. Différent de "least privilege" (qui limite la *portée* du privilège) : zero standing access limite la *durée*. Typiquement implémenté via un système PAM externe (ex. HashiCorp Vault, CyberArk) qui orchestre l'activation/désactivation ou la rotation JIT (just-in-time) d'un credential. + +## Secretless + +Direction architecturale : éliminer la manipulation de secrets statiques (mots de passe en clair, clés API en dur) par le code applicatif. Concrètement pour l'authentification Windows/AD : préférer un mécanisme qui produit un **ticket Kerberos** (via délégation, gMSA + `credentials-fetcher`, etc.) plutôt qu'un bind LDAP avec `AuthType.Basic` et un mot de passe explicite. Le processus applicatif ne voit jamais le secret sous-jacent. + +## gMSA (Group Managed Service Account) + +Type de compte de service AD dont le mot de passe est **généré et tourné automatiquement par AD** (~30 jours par défaut), jamais connu d'un humain ni stocké en dur par une application. Un gMSA seul règle "pas de mot de passe statique connu" mais **pas** zero standing access : le compte reste activé et utilisable en continu entre deux rotations. Pour obtenir zero standing access, combiner le gMSA avec une couche JIT supplémentaire (ex. compte désactivé par défaut, activé seulement pour la fenêtre d'usage via un système externe) — les deux mécanismes sont complémentaires, pas substituables l'un à l'autre. + +Sur AWS ECS/Fargate (conteneurs Linux uniquement, mode domainless — voir la fiche `ecs-fargate-task-isolation`), le daemon `credentials-fetcher` récupère le mot de passe géré du gMSA (`msDS-ManagedPassword`) via LDAPS et produit un ticket Kerberos mis à disposition du conteneur — le conteneur applicatif ne manipule jamais ce mot de passe. Nuance importante : `credentials-fetcher` lui-même s'appuie sur un identifiant AD statique stocké dans AWS Secrets Manager pour s'authentifier et effectuer cette récupération — ce credential de bootstrap est permanent (protégé par IAM, pas par une rotation JIT), donc la chaîne complète n'est secretless que du point de vue du conteneur applicatif, pas de bout en bout. diff --git a/md/active/security-governance/security-framework-role-and-crosswalk.md b/md/active/security-governance/security-framework-role-and-crosswalk.md new file mode 100644 index 0000000..675322a --- /dev/null +++ b/md/active/security-governance/security-framework-role-and-crosswalk.md @@ -0,0 +1,100 @@ +--- +id: security-framework-role-and-crosswalk +type: reference +title: Référentiels sécurité — rôle dans une baseline AD DS et Windows Server +theme: security-governance +tags: + - nist + - cis + - iso-27001 + - cobit + - pci-dss + - hipaa + - soc-2 + - anssi + - cisa + - disa + - crosswalk +scope: global +status: draft +confidence: hypothesis +audience: generic +source: + - https://www.nist.gov/cyberframework + - https://csrc.nist.gov/pubs/sp/800/53/r5/upd1/final + - https://www.cisecurity.org/controls/v8 + - https://www.cisecurity.org/benchmark/microsoft_windows_server + - https://www.iso.org/standard/27001 + - https://www.isaca.org/resources/cobit + - https://www.pcisecuritystandards.org/standards/pci-dss/ + - https://www.hhs.gov/hipaa/for-professionals/security/index.html + - https://www.aicpa-cima.com/resources/download/soc-for-service-organizations-engagements-overview + - https://public.cyber.mil/stigs/downloads/ + - https://www.cyber.gc.ca/en/guidance/guidance-securing-microsoft-active-directory-services-your-organization-itsm60100 + - https://messervices.cyber.gouv.fr/guides/recommandations-pour-ladministration-securisee-des-si-reposant-sur-ad +validated: 2026-07-25 +created: 2026-07-25 +links: + - ad-ds-security-control-assurance-levels + - ad-ds-security-hardening-study-synthesis +--- + +# Principe + +Les référentiels ne sont pas interchangeables. Ils doivent être utilisés selon leur fonction, leur autorité, leur version et leur applicabilité. + +| Famille | Rôle dans la baseline | +|---|---| +| Microsoft | Source produit, support, paramètres, rôles et compatibilité | +| CIS Benchmarks | Configuration consensuelle et profils L1/L2/STIG selon édition | +| DISA STIG | Durcissement élevé, critères et artefacts GPO/SCAP ; test local obligatoire | +| NIST CSF 2.0 | Organisation des résultats de risque : Govern, Identify, Protect, Detect, Respond, Recover | +| NIST SP 800-53 | Catalogue de contrôles et familles d'assurance | +| CIS Controls | Priorisation de safeguards à l'échelle organisationnelle | +| MITRE ATT&CK | Comportements adverses et couverture de détection/mitigation | +| ANSSI | Administration sécurisée, zones de confiance, Windows et journalisation | +| CCCS | Conseils stratégiques et praticiens spécifiques AD DS | +| ASD/ACSC | Contrôles ISM, hardening et menaces AD observées | +| CISA | Pratiques de réduction de risque et réponse, notamment ransomware et identité | +| PingCastle | Découverte, scoring et maturité opérationnelle AD | +| Trimarc/ADSecurity | Retour d'expérience et contrôles AD spécialisés, source secondaire | +| ISO/IEC 27001 | Système de management et processus de risque | +| COBIT | Gouvernance et management de l'information et de la technologie | +| PCI DSS | Exigences applicables aux environnements de données de paiement | +| HIPAA Security Rule | Sauvegardes administratives, physiques et techniques pour ePHI | +| SOC 2 | Attestation des contrôles d'un service selon les Trust Services Criteria | + +# Hiérarchie d'usage proposée + +1. Déterminer l'applicabilité légale, contractuelle et métier. +2. Définir les résultats de risque et l'ownership. +3. Prendre la baseline Microsoft supportée comme point de départ technique. +4. Comparer CIS et STIG pour les écarts de durcissement. +5. Ajouter ANSSI, CCCS, ASD/ACSC et CISA pour l'architecture, l'administration, la menace et la résilience. +6. Mapper aux techniques MITRE et aux capacités de détection. +7. Utiliser PingCastle et outils comparables pour mesurer, pas comme unique autorité. +8. Documenter les conflits et décisions ; ne jamais combiner par « valeur la plus stricte » sans test. + +# Règles de crosswalk + +Chaque contrôle futur devrait porter : + +- identifiant interne stable ; +- source et version ; +- type : exigence, recommandation, mesure ou preuve ; +- OS/rôle/tier applicable ; +- objectif de sécurité ; +- menace(s) ; +- paramètres d'implémentation ; +- méthode de test ; +- preuve attendue ; +- conflit/exception ; +- statut d'adoption. + +# Limites d'applicabilité + +- PCI DSS, HIPAA et SOC 2 ne s'appliquent pas automatiquement à toute forêt AD DS. +- ISO 27001 et COBIT ne fournissent pas une liste de paramètres GPO. +- NIST CSF décrit des résultats, pas une baseline Windows. +- CIS L1/L2 et les niveaux proposés dans cette étude ne sont pas équivalents. +- Les guides experts privés complètent les sources officielles mais ne les remplacent pas. diff --git a/md/active/siem/splunk-cim-data-models.md b/md/active/siem/splunk-cim-data-models.md new file mode 100644 index 0000000..456839f --- /dev/null +++ b/md/active/siem/splunk-cim-data-models.md @@ -0,0 +1,52 @@ +--- +id: splunk-cim-data-models +type: reference +title: Splunk CIM — modèles Authentication et Change +theme: siem +tags: + - splunk + - cim + - audit-log + - authentication + - change +scope: global +status: suspect +confidence: hypothesis +audience: generic +source: + - https://help.splunk.com/en/data-management/common-information-model/6.2/data-models/authentication + - https://help.splunk.com/en/splunk-cloud-platform/common-information-model/6.1/data-models/cim-fields-per-associated-data-model + - https://help.splunk.com/en/data-management/common-information-model/6.2/field-mappings/change-field-mapping + - https://help.splunk.com/en/splunk-enterprise/common-information-model +validated: 2026-07-18 +created: 2026-07-18 +links: [] +--- + +# Splunk Common Information Model (CIM) — Authentication et Change + +**Statut `suspect`/`hypothesis` dès la création** : récupéré via un outil de résumé automatique, `docs.splunk.com` retournait 403 sur un accès direct. La liste du modèle Change en particulier n'a pas confirmé explicitement le statut requis/recommandé par champ. À revalider contre l'add-on CIM réellement installé sur l'instance Splunk cible avant tout usage en production (fiche délibérément marquée à revalider tôt). + +## Pourquoi CIM + +Aligner un log applicatif sur un modèle CIM existant permet aux détections et rapports de conformité déjà construits côté SOC (Splunk Enterprise Security) de reconnaître l'événement automatiquement, sans parsing custom. + +## Data model Authentication + +Événement de validation d'identité (login, validation de jeton). + +**Champs requis** : `action`, `app`, `user`, `src`, `dest`. + +**Champs recommandés** : `src_user`, `user_id`, `user_role`, `user_type`, `authentication_method`, `authentication_service`, `duration`, `process`, `reason_id`, `response_time`, `signature`, `signature_id`, `user_agent`, `user_bunit`, `user_category`, `user_priority`. + +## Data model Change + +Événement de type Create/Read/Update/Delete sur un objet quelconque — c'est le modèle naturel pour une API qui fait du CRUD sur des objets d'annuaire ou toute ressource administrée. + +**Champs observés** (statut requis/recommandé non confirmé) : `action`, `change_type`, `command`, `dest`, `dest_bunit`, `dest_category`, `dest_ip_range`, `dest_nt_domain`, `dest_port_range`, `dest_priority`, `direction`, `dvc`, `image_id`, `instance_type`, `object`, `object_attrs`, `object_category`, `object_id`, `object_path`, `result`, `status`, `user`, `vendor_product`. + +Sémantique à retenir : dans ce modèle, `user` désigne **qui effectue l'action**, pas l'objet ciblé par l'action — la cible se décrit via `object`/`object_category`/`object_id`/`object_path`. + +## Champs d'enveloppe d'indexation Splunk (hors CIM) + +Distincts des champs de contenu CIM ci-dessus : `time`/`timestamp`, `host`, `source`, `sourcetype`, `index` — gérés à l'ingestion, pas dans le corps de l'événement applicatif. diff --git a/md/active/vscode-copilot/copilot-instructions-merge.md b/md/active/vscode-copilot/copilot-instructions-merge.md new file mode 100644 index 0000000..828d1ae --- /dev/null +++ b/md/active/vscode-copilot/copilot-instructions-merge.md @@ -0,0 +1,48 @@ +--- +id: copilot-instructions-merge +type: reference +title: GitHub Copilot — fusion automatique de fichiers d'instructions multiples +theme: vscode-copilot +tags: + - copilot + - vscode + - instructions + - config-merge +scope: global +status: active +confidence: fact +audience: generic +source: + - https://code.visualstudio.com/docs/agent-customization/custom-instructions + - https://github.com/orgs/community/discussions/170581 +validated: 2026-07-16 +created: 2026-07-16 +links: + - vscode-copilot-builtin-tools + - claude-md-import-mechanism + - codex-agents-md-nesting +--- + +# GitHub Copilot — fusion automatique de fichiers d'instructions multiples + +Recherche du 2026-07-16, motivée par l'issue mA.xI.me #27. + +## Ce qui est confirmé (sourcé) + +- Mécanisme officiel et actuel : `.github/copilot-instructions.md` (toujours actif, portée repo entier) et `.github/instructions/*.instructions.md` (application conditionnelle via un glob `applyTo` ou correspondance sémantique) sont additifs, pas exclusifs — les deux se chargent ensemble en contexte. La doc VS Code le dit explicitement : "If you have multiple instruction files in your project, VS Code combines and adds them to the chat context, no specific order is guaranteed." Source : https://code.visualstudio.com/docs/agent-customization/custom-instructions +- La doc plus récente de Copilot CLI décrit une pile à 5 niveaux (personnel → instructions scopées par chemin → copilot-instructions.md repo entier → AGENTS.md → organisation) qui fusionnent tous, les niveaux supérieurs ne l'emportant qu'en cas de conflit direct. +- Aucune syntaxe d'inclusion à l'intérieur d'un seul fichier d'instructions — mais des liens Markdown entre fichiers d'instructions sont une convention de référence croisée douce (ex. "Applique ces conventions"), pas une vraie fusion/inclusion. +- Confusion réelle constatée dans la communauté : la discussion GitHub #170581 (org community) montre des utilisateurs ayant mal lu la formulation de la doc ("either... or...") comme mutuellement exclusive, alors que les deux types de fichiers se combinent réellement — clarifié par la communauté, pas encore par une réécriture de la doc officielle trouvée. + +## Incertitudes explicites + +- "Aucun ordre spécifique garanti" est un vrai risque pour notre cas d'usage si le fichier généré et le fichier écrit à la main donnent un jour des instructions contradictoires — impossible de forcer la victoire du fichier écrit à la main juste par son emplacement. +- Aucune page officielle docs.github.com trouvée énonçant le comportement de combinaison aussi explicitement que la page VS Code ; des sources secondaires (Medium, blog NashTech) le répètent mais ne sont pas officielles. + +## Recommandation pour mA.xI.me (issue #27) + +Mécanisme natif, standard, sans parsing custom : garder `.github/copilot-instructions.md` comme fichier possédé par le générateur, et placer le contenu spécifique au projet dans un fichier séparé `.github/instructions/project-conventions.instructions.md` (avec `applyTo: "**"` pour le rendre universel) — Copilot fusionne automatiquement les deux à chaque fois, sans action de notre part après la première installation. + +## Sources +- https://code.visualstudio.com/docs/agent-customization/custom-instructions +- https://github.com/orgs/community/discussions/170581 diff --git a/md/active/vscode-copilot/vscode-copilot-builtin-tools.md b/md/active/vscode-copilot/vscode-copilot-builtin-tools.md new file mode 100644 index 0000000..1adf4b7 --- /dev/null +++ b/md/active/vscode-copilot/vscode-copilot-builtin-tools.md @@ -0,0 +1,192 @@ +--- +id: vscode-copilot-builtin-tools +type: reference +title: "VS Code / GitHub Copilot Chat -- outils built-in (tools: frontmatter)" +theme: vscode-copilot +tags: + - vscode + - copilot + - tools + - builtin +scope: global +status: active +confidence: fact +audience: generic +source: + - https://docs.github.com/en/copilot/reference/custom-agents-configuration + - https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/ +validated: 2026-07-13 +created: 2026-07-12 +links: + - agent-skills-cross-tool-integration +--- + +# VS Code / GitHub Copilot Chat — outils built-in (tools: frontmatter) + +Statut : `.new` — capture brute suite à une recherche ponctuelle, pas encore +relue/validée comme fiche KB stable. Savoir générique réutilisable, sans +donnée de projet/client/employeur. + +## Contexte + +Erreur corrigée le 2026-07-12 : `web` et `vscode` avaient été retirés de +`tools:` dans `maxime.agent.md` en les supposant à tort spécifiques à la +machine de Philippe (au même titre que `vscode.mermaid-markdown-features` ou +`GitHub.vscode-pull-request-github`, qui eux le sont vraiment). Correction : +`web` et `vscode` sont des **outils built-in**, disponibles pour tout +utilisateur de l'extension Copilot Chat, pas une config locale. + +## Ce qui est confirmé (sourcé) + +D'après la doc GitHub officielle des custom agents +([docs.github.com/en/copilot/reference/custom-agents-configuration](https://docs.github.com/en/copilot/reference/custom-agents-configuration)), +7 alias d'outils built-in, avec leurs alias compatibles (mapping vers les +noms d'outils Claude Code — clin d'œil à la portabilité cross-outil) : + +| Alias Copilot | Alias compatibles | +| --- | --- | +| `execute` | `shell`, `Bash`, `powershell` | +| `read` | `Read`, `NotebookRead` | +| `edit` | `Edit`, `MultiEdit`, `Write`, `NotebookEdit` | +| `search` | `Grep`, `Glob` | +| `agent` | `custom-agent`, `Task` | +| `web` | `WebSearch`, `WebFetch` | +| `todo` | `TodoWrite` | + +Deux serveurs MCP disponibles par défaut pour les agents cloud GitHub.com : +`github/*` (outils GitHub en lecture seule) et `playwright/*` (automatisation +navigateur, localhost uniquement). + +D'après le blog GitHub officiel +([github.blog/.../how-were-making-github-copilot-smarter-with-fewer-tools](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/)) +: VS Code organise un noyau de 13 outils essentiels (structure du repo, +lecture/édition de fichiers, recherche de contexte, terminal), puis regroupe +le reste en catégories virtuelles : **Jupyter Notebook Tools**, **Web +Interaction Tools**, **VS Code Workspace Tools**, **Testing Tools**. Ça +corrobore `web` (Web Interaction Tools) et `vscode` (VS Code Workspace Tools) +comme catégories réelles, pas des extras personnels. + +## Sous-outils observés directement (captures d'écran picker VS Code, 2026-07-13) + +Philippe a fourni des captures d'écran du picker d'outils (menu `#` du chat +Copilot). Reconstitution complète, textuelle, du détail par catégorie — +observation directe de son environnement, `non vérifié par exécution` contre +une doc officielle listant chaque sous-fonction. + +### agent — Delegate tasks to other agents + +- **runSubagent** — Run a task within an isolated subagent context to enable efficient organization of tasks and context window management. + +### browser — Open and interact with integrated browser pages *(tous décochés)* + +- clickElement — Click an element in a browser page +- dragElement — Drag an element over another element +- handleDialog — Respond to a dialog in a browser page +- hoverElement — Hover over an element in a browser page +- navigatePage — Navigate or reload a browser page +- openBrowserPage — Open a URL in the integrated browser +- readPage — Read the content of a browser page +- runPlaywrightCode — Run a Playwright code snippet against a browser page +- screenshotPage — Capture a screenshot of a browser page +- typeInPage — Type text or press keys in a browser page + +### edit — Edit files in your workspace + +- createDirectory — Create new directories in your workspace +- createFile — Create new files +- createJupyterNotebook — Create a new Jupyter Notebook +- editFiles — Edit files +- editNotebook — Edit a notebook file in the workspace +- rename — Rename a symbol across the workspace + +### execute — Execute code and applications on your machine + +- createAndRunTask — Create and run a task in the workspace +- executionSubagent — Launch an execution-focused subagent that runs one or more terminal commands to accomplish a task. This subagent is powered by Google's Gemini-3-Flash model. It is designed to select an efficient summary of the terminal outputs to return to the main agent context. +- getTerminalOutput — Send input text to an active terminal execution (identified by the id returned from run_in_terminal). The 'command' field may be empty or whitespace to press Enter (useful for interactive prompts). By default, returns the last 20 lines of terminal output captured shortly after sending. Set 'waitForOutput' to true for interactive programs (games, REPLs, etc.) to wait until the terminal becomes idle before returning output — this gives you the program's response to your input. +- killTerminal — Kill a terminal by its ID. Use this to clean up terminals that are no longer needed (e.g., after stopping a server or when a long-running task completes). The terminal ID is returned by run_in_terminal in async mode (legacy: isBackground=true). +- runInTerminal — Run commands in the terminal +- runNotebookCell — Trigger the execution of a cell in a notebook file +- runTask — Run tasks in the workspace +- runTests — Run unit tests (optionally with coverage) +- sendToTerminal — Send input text to an active terminal execution (identified by the id returned from run_in_terminal). The 'command' field may be empty or whitespace to press Enter (useful for interactive prompts). By default, returns the last 20 lines of terminal output captured shortly after sending. Set 'waitForOutput' to true for interactive programs (games, REPLs, etc.) to wait until the terminal becomes idle before returning output — this gives you the program's response to your input. +- testFailure — Include test failure information + +### read — Read files in your workspace + +- getNotebookSummary — This is a tool returns the list of the Notebook cells along with the id, cell types, line ranges, language, execution information and output mime types for each cell. This is useful to get Cell Ids when executing a notebook or determine what cells have been executed and what order, or what cells have outputs. If required to read contents of a cell use this to determine the line range of a cells, and then use read_file tool to read a specific line range. Requery this tool if the contents of the notebook change. +- getTaskOutput — Get the output of a task +- problems — Check errors for a particular file +- readFile — Read the contents of a file +- readNotebookCellOutput — Read the output of a previously executed cell +- terminalLastCommand — Get the last command run in the active terminal. +- terminalSelection — Get the current selection in the active terminal. +- viewImage — View the contents of an image file + +### search — Search files in your workspace + +- changes — Get diffs of changed files +- codebase — Find relevant file chunks, symbols, and other information via + semantic search +- fileSearch — Find files by name using a glob pattern +- listDirectory — List the contents of a directory +- textSearch — Find text in files by regular expression +- usages — Find references, definitions, and implementations of a symbol + +### todo — Manage and track todo items for task planning + +### vscode — Use VS Code features + +- askQuestions — Ask structured clarifying questions using single select, multi-select, or freeform inputs to collect task requirements before proceeding. +- extensions — Search for VS Code extensions +- installExtension — Install an extension in VS Code. Use this tool to install an extension in Visual Studio Code as part of a new workspace creation process only. +- memory — Manage persistent memory across conversations +- newWorkspace — Scaffold a new workspace in VS Code +- resolveMemoryFileUri — Resolve a memory file path to its actual URI +- runCommand — Run a command in VS Code. Use this tool to run a command in Visual Studio Code as part of a new workspace creation process only. +- vscodeAPI — Use VS Code API references to answer questions about VS Code extension development. + +### web — Fetch information from the web + +- fetch — Fetch the main content from a web page. You should include the + URL of the page you w... +- githubRepo — Semantic Search a GitHub repository for relevant source code snippets. You can specify a repository using owner/repo +- githubTextSearch — Text search a GitHub repository or organization for files containing specific keywords or code patterns. + +Le champ `todo` apparaît comme sous-outil de `search` dans le picker +observé, alors que la table des alias plus haut le liste comme catégorie de +premier niveau à part (`todo` → `TodoWrite`) — à réconcilier, pas forcément +contradictoire (un alias top-level peut être exposé aussi comme sous-item +dans l'UI). + +## Ce qui reste incertain + +- Aucune source *officielle écrite* ne fournit cette table de sous-outils — + elle vient de l'observation directe de Philippe (ci-dessus), qui fait + autorité pour son environnement mais n'est pas vérifiée contre la doc. Et Philippe observe ces outils au travail, avec un laptop travail, et a la maison avec son oridnateur de bureau. +- `browser` : confirmé comme catégorie réelle de premier niveau dans le + picker (10 sous-outils listés ci-dessus), avec un net recoupement + fonctionnel avec `playwright/*` (MCP cloud) — reste à déterminer si + `browser` est ce même MCP exposé localement, ou une implémentation VS Code + distincte. +- Méthode recommandée par la doc VS Code elle-même pour un inventaire + complet et à jour : taper `#` dans le champ de saisie du chat Copilot — + plus fiable qu'une doc statique qui peut dater vite sur ce sujet. + +## Sources consultées + +- [Custom agents configuration — GitHub Docs](https://docs.github.com/en/copilot/reference/custom-agents-configuration) +- [Custom agents in VS Code](https://code.visualstudio.com/docs/agent-customization/custom-agents) +- [Use tools in chat — VS Code Docs](https://code.visualstudio.com/docs/copilot/agents/agent-tools) +- [How we're making GitHub Copilot smarter with fewer tools — GitHub Blog](https://github.blog/ai-and-ml/github-copilot/how-were-making-github-copilot-smarter-with-fewer-tools/) +- [GitHub Copilot in VS Code cheat sheet](https://code.visualstudio.com/docs/agents/reference/copilot-vscode-features) + +## Application faite + +`tools/generate-adapters.ps1`/`.sh` : `maxime.agent.md` (orchestrateur +`maxi-copilot` uniquement, pas les sous-agents reviewer ni les prompts de +workflow) déclare désormais `[read, search, execute, edit, agent, vscode, +web]` — reprend exactement le sous-ensemble non-ambigu de ce que Philippe a +lui-même validé comme fonctionnel dans son environnement, moins les deux +extensions personnelles (`vscode.mermaid-markdown-features`, +`GitHub.vscode-pull-request-github`). diff --git a/md/active/windows-server/windows-server-2022-plus-hardening-source-baselines.md b/md/active/windows-server/windows-server-2022-plus-hardening-source-baselines.md new file mode 100644 index 0000000..1e46826 --- /dev/null +++ b/md/active/windows-server/windows-server-2022-plus-hardening-source-baselines.md @@ -0,0 +1,88 @@ +--- +id: windows-server-2022-plus-hardening-source-baselines +type: reference +title: Windows Server 2022 et versions ultérieures — sources de baseline et règles d'adoption +theme: windows-server +tags: + - windows-server-2022 + - windows-server-2025 + - security-baseline + - sct + - osconfig + - secured-core + - cis + - stig +scope: global +status: draft +confidence: fact +audience: generic +source: + - https://learn.microsoft.com/en-us/windows/security/operating-system-security/device-management/windows-security-configuration-framework/security-compliance-toolkit-10 + - https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-overview + - https://learn.microsoft.com/en-us/windows-server/security/osconfig/osconfig-how-to-configure-security-baselines + - https://learn.microsoft.com/en-us/windows-server/security/secured-core-server + - https://learn.microsoft.com/en-us/windows-server/security/configure-secured-core-server + - https://www.cisecurity.org/benchmark/microsoft_windows_server + - https://public.cyber.mil/stigs/downloads/ + - https://public.cyber.mil/stigs/gpo/ + - https://messervices.cyber.gouv.fr/guides/mise-en-oeuvre-securisee-dun-serveur-windows + - https://www.cyber.gov.au/business-government/asds-cyber-security-frameworks/ism/cyber-security-guidelines/guidelines-for-system-hardening +validated: 2026-07-25 +created: 2026-07-25 +links: + - ad-ds-domain-controller-security-hardening + - ad-ds-security-control-assurance-levels + - security-framework-role-and-crosswalk +--- + +# Faits établis + +## Windows Server 2022 + +Le Microsoft Security Compliance Toolkit (SCT) fournit les baselines Microsoft et les outils permettant de comparer, personnaliser, sauvegarder et appliquer des GPO. Il s'applique notamment à Windows Server 2022. + +Les benchmarks CIS et les STIG DISA fournissent des profils supplémentaires. Ils doivent être utilisés comme sources contrôlées et versionnées, jamais copiés sans analyse de compatibilité. + +## Windows Server 2025 + +OSConfig fournit des scénarios role-aware pour contrôleur de domaine, serveur membre et serveur en workgroup, avec vérification de conformité et protection contre la dérive. OSConfig ne prend pas en charge les versions antérieures à Windows Server 2025. + +## Secured-core + +Secured-core ajoute des protections matérielles, firmware et OS, notamment une racine de confiance matérielle, Secure Boot, TPM 2.0 et des protections d'intégrité renforcées. Sa disponibilité dépend du matériel et de la virtualisation. + +# Règles d'adoption + +1. Conserver une baseline distincte par version majeure de Windows Server. +2. Distinguer au minimum les rôles `DomainController`, `MemberServer` et `Standalone`. +3. Ne jamais appliquer une baseline Windows Server 2025 à Windows Server 2022 par analogie. +4. Commencer par la baseline Microsoft supportée pour le rôle et la version. +5. Comparer ensuite CIS, DISA, ANSSI, ASD/ACSC et exigences locales. +6. Documenter chaque écart : source, justification, compatibilité, risque, preuve de test et date de revue. +7. Tester dans des anneaux représentatifs avant production. +8. Prévoir une procédure de retour arrière ; la suppression d'une baseline ne garantit pas toujours le retour exact à l'état antérieur. +9. Surveiller la dérive et ne pas considérer le déploiement initial comme une preuve durable. +10. Versionner les ADMX/ADML, sauvegardes GPO, rapports, matrices et résultats d'évaluation. + +# Familles de paramètres à couvrir + +- démarrage sécurisé, TPM, VBS et intégrité du code ; +- réduction des protocoles et algorithmes hérités ; +- pare-feu et exposition réseau ; +- SMB, RPC, RDP, WinRM et administration distante ; +- LSASS, Credential Guard et protection des secrets ; +- Microsoft Defender, ASR, application control et AMSI ; +- comptes locaux, LAPS et droits utilisateur ; +- audit avancé, PowerShell, Sysmon selon besoin et rétention ; +- services, fonctionnalités et logiciels non nécessaires ; +- correctifs, pilotes, firmware et chaîne de mise à jour ; +- sauvegarde, restauration, chiffrement et protection des preuves ; +- configuration des agents de gestion et de sécurité. + +# Éléments non résolus + +- choix entre GPO, OSConfig, Azure Policy/Arc, DSC ou autre autorité de configuration ; +- ordre de préséance entre autorités ; +- profil Secured-core obligatoire ou conditionnel ; +- traitement des incompatibilités applicatives ; +- calendrier de migration 2022 vers 2025. diff --git a/tools/kb.py b/tools/kb.py new file mode 100755 index 0000000..aee81a8 --- /dev/null +++ b/tools/kb.py @@ -0,0 +1,523 @@ +#!/usr/bin/env python3 +"""Convertisseur JSON <-> Markdown de la knowledge base. + +Le JSON sous active/ et archived/ est la source canonique : c'est lui que lisent +les repos consommateurs (submodule + skill maxime-kb). Le miroir Markdown sous +md/ est une projection lisible par un humain, régénérable dans les deux sens et +sans perte. index.json et index.md sont entièrement dérivés des fiches. + +Sous-commandes : + sync JSON -> Markdown : régénère md/, index.json, index.md et + recanonicalise les fiches JSON. + sync --from md Markdown -> JSON : régénère active/ et archived/ depuis md/, + puis les index. + check N'écrit rien ; sort en 1 si un fichier n'est pas à jour. + validate Contrôles de schéma seuls. + +Python 3 uniquement, bibliothèque standard seule : aucune dépendance à installer, +ni en local ni sur le runner CI. +""" + +from __future__ import annotations + +import argparse +import json +import re +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parent.parent + +# Racines de fiches JSON, miroitées telles quelles sous md/. +FICHE_ROOTS = ("active", "archived") +MD_ROOT = "md" + +# Ordre canonique des clés d'une fiche. `content` est toujours en dernier : +# c'est le corps du Markdown, les autres clés forment le frontmatter. +ATTRS = ( + "id", + "type", + "title", + "theme", + "tags", + "scope", + "status", + "confidence", + "audience", + "source", + "validated", + "created", + "links", +) +FICHE_KEYS = ATTRS + ("content",) +# Entrée d'index : les attributs sans le contenu, plus le chemin de la fiche. +INDEX_KEYS = ATTRS + ("path",) + +LIST_ATTRS = frozenset({"tags", "source", "links"}) + +ENUMS = { + "type": ("reference", "decision", "procedure", "pattern", "contact", "glossary"), + "status": ("draft", "active", "suspect", "obsolete", "archived"), + "confidence": ("fact", "hypothesis", "opinion"), + "audience": ("generic", "project", "secret"), +} + +DATE_RE = re.compile(r"^\d{4}-\d{2}-\d{2}$") +ID_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$") + +# Champs supprimés du schéma : rejetés explicitement pour qu'ils ne reviennent +# pas par copier-coller d'une ancienne fiche. +REMOVED_ATTRS = ("ttl_days",) + + +class KBError(Exception): + """Erreur de schéma ou de format, rapportée à l'utilisateur sans traceback.""" + + +# -------------------------------------------------------------------------- +# Frontmatter : sous-ensemble YAML volontairement restreint au schéma réel +# (scalaires string et séquences de strings). Reste du YAML valide, donc GitHub +# l'affiche en tableau, mais se parse sans PyYAML. +# -------------------------------------------------------------------------- + +# Une valeur doit être mise entre guillemets si elle est vide, porte une espace +# en tête/fin, contient un séparateur YAML (`: ` ou ` #`), ou commence par un +# caractère indicateur. +_NEEDS_QUOTES = re.compile(r"^$|^\s|\s$|:\s|\s#|^[-?:,\[\]{}#&*!|>'\"%@`]") + + +def _dump_scalar(value: str) -> str: + if _NEEDS_QUOTES.search(value): + return json.dumps(value, ensure_ascii=False) + return value + + +def _load_scalar(raw: str) -> str: + raw = raw.strip() + if raw.startswith('"'): + return json.loads(raw) + return raw + + +def dump_frontmatter(fiche: dict) -> str: + lines = [] + for key in ATTRS: + value = fiche[key] + if key in LIST_ATTRS: + if not value: + lines.append(f"{key}: []") + continue + lines.append(f"{key}:") + lines.extend(f" - {_dump_scalar(item)}" for item in value) + else: + lines.append(f"{key}: {_dump_scalar(value)}") + return "\n".join(lines) + + +def parse_frontmatter(text: str, where: str) -> tuple[dict, str]: + """Découpe un document Markdown en (attributs, contenu).""" + if not text.startswith("---\n"): + raise KBError(f"{where}: frontmatter manquant (le fichier doit commencer par '---')") + end = text.find("\n---\n", 3) + if end == -1: + raise KBError(f"{where}: frontmatter non refermé (délimiteur '---' attendu)") + block = text[4:end] + content = text[end + 5 :] + # Un saut de ligne sépare le frontmatter du corps ; il n'appartient pas au corps. + if content.startswith("\n"): + content = content[1:] + + attrs: dict = {} + current_list: list | None = None + for lineno, line in enumerate(block.split("\n"), start=2): + if not line.strip(): + continue + if line.startswith(" - "): + if current_list is None: + raise KBError(f"{where}:{lineno}: élément de liste hors d'une clé de liste") + current_list.append(_load_scalar(line[4:])) + continue + match = re.match(r"^([a-z_]+):(.*)$", line) + if not match: + raise KBError(f"{where}:{lineno}: ligne de frontmatter illisible : {line!r}") + key, raw = match.group(1), match.group(2).strip() + if key in attrs: + raise KBError(f"{where}:{lineno}: clé '{key}' en double") + if key in LIST_ATTRS: + if raw == "[]": + attrs[key] = [] + current_list = None + elif raw: + raise KBError( + f"{where}:{lineno}: '{key}' doit être une séquence en blocs " + f"(' - valeur' par ligne) ou '[]'" + ) + else: + current_list = attrs[key] = [] + else: + attrs[key] = _load_scalar(raw) + current_list = None + return attrs, content + + +# -------------------------------------------------------------------------- +# Sérialisation canonique +# -------------------------------------------------------------------------- + + +def dump_json(data) -> str: + return json.dumps(data, indent=2, ensure_ascii=False) + "\n" + + +def canonical_fiche(fiche: dict) -> dict: + """Réordonne les clés et normalise le contenu (exactement un \\n final). + + Cette normalisation est ce qui rend l'aller-retour déterministe : sans elle, + `check` signalerait en permanence des écarts purement cosmétiques. + """ + out = {k: fiche[k] for k in ATTRS} + out["content"] = fiche["content"].rstrip("\n") + "\n" + return out + + +def dump_fiche_md(fiche: dict) -> str: + return f"---\n{dump_frontmatter(fiche)}\n---\n\n{fiche['content'].rstrip(chr(10))}\n" + + +# -------------------------------------------------------------------------- +# Validation +# -------------------------------------------------------------------------- + + +def validate_fiche(fiche: dict, rel: Path, errors: list[str]) -> None: + where = rel.as_posix() + + for attr in REMOVED_ATTRS: + if attr in fiche: + errors.append( + f"{where}: champ '{attr}' retiré du schéma (issue #8) — le supprimer" + ) + unknown = sorted(set(fiche) - set(FICHE_KEYS) - set(REMOVED_ATTRS)) + if unknown: + errors.append(f"{where}: champ(s) hors schéma : {', '.join(unknown)}") + missing = [k for k in FICHE_KEYS if k not in fiche] + if missing: + errors.append(f"{where}: champ(s) manquant(s) : {', '.join(missing)}") + return + + for key in FICHE_KEYS: + value = fiche[key] + if key in LIST_ATTRS: + if not isinstance(value, list) or not all(isinstance(v, str) for v in value): + errors.append(f"{where}: '{key}' doit être une liste de chaînes") + elif not isinstance(value, str): + errors.append(f"{where}: '{key}' doit être une chaîne") + + for key, allowed in ENUMS.items(): + if isinstance(fiche.get(key), str) and fiche[key] not in allowed: + errors.append( + f"{where}: '{key}' = {fiche[key]!r} hors des valeurs admises " + f"({', '.join(allowed)})" + ) + + for key in ("validated", "created"): + if isinstance(fiche.get(key), str) and not DATE_RE.match(fiche[key]): + errors.append(f"{where}: '{key}' = {fiche[key]!r} n'est pas au format YYYY-MM-DD") + + if isinstance(fiche.get("id"), str): + if not ID_RE.match(fiche["id"]): + errors.append(f"{where}: 'id' = {fiche['id']!r} n'est pas un slug kebab-case") + if fiche["id"] != rel.stem: + errors.append( + f"{where}: 'id' = {fiche['id']!r} ne correspond pas au nom de fichier " + f"{rel.stem!r}" + ) + # active//.json : le thème est porté par le dossier parent. + if rel.parts[0] == "active" and len(rel.parts) == 3: + if fiche.get("theme") != rel.parts[1]: + errors.append( + f"{where}: 'theme' = {fiche.get('theme')!r} ne correspond pas au dossier " + f"{rel.parts[1]!r}" + ) + elif rel.parts[0] == "active": + errors.append(f"{where}: une fiche active doit vivre dans active//.json") + + if isinstance(fiche.get("content"), str) and not fiche["content"].strip(): + errors.append(f"{where}: 'content' vide") + + +def validate_all(fiches: dict[Path, dict]) -> list[str]: + errors: list[str] = [] + for rel, fiche in sorted(fiches.items()): + validate_fiche(fiche, rel, errors) + + ids: dict[str, Path] = {} + for rel, fiche in sorted(fiches.items()): + fid = fiche.get("id") + if isinstance(fid, str): + if fid in ids: + errors.append( + f"{rel.as_posix()}: 'id' {fid!r} déjà utilisé par {ids[fid].as_posix()}" + ) + else: + ids[fid] = rel + for rel, fiche in sorted(fiches.items()): + for link in fiche.get("links", []) or []: + if isinstance(link, str) and link not in ids: + errors.append(f"{rel.as_posix()}: lien {link!r} ne pointe vers aucune fiche") + return errors + + +# -------------------------------------------------------------------------- +# Lecture des deux côtés +# -------------------------------------------------------------------------- + + +def json_paths() -> list[Path]: + paths: list[Path] = [] + for root in FICHE_ROOTS: + paths += [p.relative_to(ROOT) for p in sorted((ROOT / root).rglob("*.json"))] + return paths + + +def md_paths() -> list[Path]: + md_root = ROOT / MD_ROOT + if not md_root.is_dir(): + return [] + return [p.relative_to(ROOT) for p in sorted(md_root.rglob("*.md"))] + + +def md_rel_for(json_rel: Path) -> Path: + return Path(MD_ROOT) / json_rel.with_suffix(".md") + + +def json_rel_for(md_rel: Path) -> Path: + return Path(*md_rel.parts[1:]).with_suffix(".json") + + +def read_json_fiches() -> dict[Path, dict]: + fiches: dict[Path, dict] = {} + for rel in json_paths(): + try: + fiches[rel] = json.loads((ROOT / rel).read_text(encoding="utf-8")) + except json.JSONDecodeError as exc: + raise KBError(f"{rel.as_posix()}: JSON invalide : {exc}") from exc + return fiches + + +def read_md_fiches() -> dict[Path, dict]: + fiches: dict[Path, dict] = {} + for md_rel in md_paths(): + attrs, content = parse_frontmatter( + (ROOT / md_rel).read_text(encoding="utf-8"), md_rel.as_posix() + ) + attrs["content"] = content + fiches[json_rel_for(md_rel)] = attrs + return fiches + + +# -------------------------------------------------------------------------- +# Index dérivés +# -------------------------------------------------------------------------- + + +def build_index_json(fiches: dict[Path, dict]) -> list[dict]: + entries = [] + for rel, fiche in sorted(fiches.items(), key=lambda kv: kv[0].as_posix()): + entry = {k: fiche[k] for k in ATTRS} + entry["path"] = rel.as_posix() + entries.append(entry) + return entries + + +def build_index_md(fiches: dict[Path, dict]) -> str: + active = {r: f for r, f in fiches.items() if r.parts[0] == "active"} + archived = {r: f for r, f in fiches.items() if r.parts[0] == "archived"} + + out = [ + "", + "", + "# Knowledge Base — ouritres", + "", + f"{len(fiches)} fiche(s). Les conventions et le format de fiche sont décrits dans", + "[`KB-CONVENTIONS.md`](KB-CONVENTIONS.md). L'index machine, lu par le skill", + "`maxime-kb`, est [`index.json`](index.json) ; ce catalogue-ci est sa contrepartie", + "lisible, avec un lien vers la version Markdown de chaque fiche.", + "", + ] + + def table(subset: dict[Path, dict]) -> None: + by_theme: dict[str, list[tuple[Path, dict]]] = {} + for rel, fiche in subset.items(): + by_theme.setdefault(fiche["theme"], []).append((rel, fiche)) + for theme in sorted(by_theme): + out.append(f"### `{theme}`") + out.append("") + out.append("| Fiche | Type | Statut | Confiance | Validée |") + out.append("| - | - | - | - | - |") + for rel, fiche in sorted(by_theme[theme], key=lambda kv: kv[1]["id"]): + link = md_rel_for(rel).as_posix() + title = fiche["title"].replace("|", "\\|") + out.append( + f"| [{title}]({link}) | {fiche['type']} | {fiche['status']} " + f"| {fiche['confidence']} | {fiche['validated']} |" + ) + out.append("") + + out.append("## Fiches actives") + out.append("") + if active: + table(active) + else: + out.append("_Aucune._") + out.append("") + + if archived: + out.append("## Fiches archivées") + out.append("") + out.append("Conservées pour mémoire, jamais chargées sauf demande explicite.") + out.append("") + table(archived) + + return "\n".join(out).rstrip("\n") + "\n" + + +# -------------------------------------------------------------------------- +# Génération de l'arbre attendu +# -------------------------------------------------------------------------- + + +def expected_tree(fiches: dict[Path, dict]) -> dict[Path, str]: + """Contenu attendu de chaque fichier généré, à partir des fiches en mémoire.""" + files: dict[Path, str] = {} + for rel, fiche in fiches.items(): + files[rel] = dump_json(fiche) + files[md_rel_for(rel)] = dump_fiche_md(fiche) + files[Path("index.json")] = dump_json(build_index_json(fiches)) + files[Path("index.md")] = build_index_md(fiches) + return files + + +def load_fiches(source: str) -> dict[Path, dict]: + fiches = read_md_fiches() if source == "md" else read_json_fiches() + if not fiches: + raise KBError( + f"aucune fiche trouvée côté {source} — rien à synchroniser " + f"(lancer 'kb.py sync' depuis l'autre sens ?)" + ) + errors = validate_all(fiches) + if errors: + raise KBError( + "schéma invalide :\n - " + "\n - ".join(errors) + ) + return {rel: canonical_fiche(f) for rel, f in fiches.items()} + + +def stale_paths(files: dict[Path, str]) -> list[Path]: + """Fichiers générés absents ou différents de ce qu'ils devraient être.""" + stale = [ + rel + for rel, text in sorted(files.items(), key=lambda kv: kv[0].as_posix()) + if not (ROOT / rel).is_file() or (ROOT / rel).read_text(encoding="utf-8") != text + ] + # Un .md sans fiche JSON correspondante (fiche supprimée, renommée) est un orphelin. + stale += [rel for rel in md_paths() if rel not in files] + return stale + + +def write_tree(files: dict[Path, str]) -> list[Path]: + written = [] + for rel, text in sorted(files.items(), key=lambda kv: kv[0].as_posix()): + target = ROOT / rel + if target.is_file() and target.read_text(encoding="utf-8") == text: + continue + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(text, encoding="utf-8") + written.append(rel) + for rel in md_paths(): + if rel not in files: + (ROOT / rel).unlink() + written.append(rel) + # Nettoie les dossiers de thème vidés par une suppression de fiche. + for path in sorted((ROOT / MD_ROOT).rglob("*"), reverse=True): + if path.is_dir() and not any(path.iterdir()): + path.rmdir() + return written + + +# -------------------------------------------------------------------------- +# Commandes +# -------------------------------------------------------------------------- + + +def cmd_sync(args) -> int: + files = expected_tree(load_fiches(args.source)) + written = write_tree(files) + if not written: + print(f"kb: déjà à jour ({len(files)} fichier(s) vérifié(s)).") + return 0 + print(f"kb: {len(written)} fichier(s) mis à jour depuis {args.source} :") + for rel in written: + print(f" {rel.as_posix()}") + return 0 + + +def cmd_check(_args) -> int: + files = expected_tree(load_fiches("json")) + stale = stale_paths(files) + if not stale: + print(f"kb: OK — {len(files)} fichier(s) synchronisés.") + return 0 + print("kb: les fichiers suivants ne sont pas à jour :", file=sys.stderr) + for rel in stale: + print(f" {rel.as_posix()}", file=sys.stderr) + print( + "\nRégénérer avec : python3 tools/kb.py sync" + "\n(ou, si la modification a été faite côté Markdown : " + "python3 tools/kb.py sync --from md)", + file=sys.stderr, + ) + return 1 + + +def cmd_validate(args) -> int: + load_fiches(args.source) + print(f"kb: schéma valide côté {args.source}.") + return 0 + + +def main(argv: list[str] | None = None) -> int: + parser = argparse.ArgumentParser( + prog="kb.py", description="Convertisseur JSON <-> Markdown de la knowledge base." + ) + sub = parser.add_subparsers(dest="command", required=True) + + p_sync = sub.add_parser("sync", help="régénère le côté dérivé et les index") + p_sync.add_argument( + "--from", + dest="source", + choices=("json", "md"), + default="json", + help="côté faisant foi pour cette synchronisation (défaut : json)", + ) + p_sync.set_defaults(func=cmd_sync) + + p_check = sub.add_parser("check", help="vérifie sans rien écrire ; sort en 1 si écart") + p_check.set_defaults(func=cmd_check) + + p_validate = sub.add_parser("validate", help="contrôles de schéma seuls") + p_validate.add_argument( + "--from", dest="source", choices=("json", "md"), default="json" + ) + p_validate.set_defaults(func=cmd_validate) + + args = parser.parse_args(argv) + try: + return args.func(args) + except KBError as exc: + print(f"kb: {exc}", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) From ca4e5e5301253099d60ae15e0a8d5a368a4e36e3 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Aug 2026 09:49:52 +0000 Subject: [PATCH 3/4] =?UTF-8?q?ci(kb):=20passe=20actions/checkout=20en=20v?= =?UTF-8?q?5=20(Node=2020=20d=C3=A9pr=C3=A9ci=C3=A9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF --- .github/workflows/kb-sync.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/kb-sync.yml b/.github/workflows/kb-sync.yml index 352cb22..bd3d82f 100644 --- a/.github/workflows/kb-sync.yml +++ b/.github/workflows/kb-sync.yml @@ -23,7 +23,7 @@ jobs: if: github.event_name == 'push' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: # Nécessaire pour pouvoir committer et pousser sur la branche courante. persist-credentials: true @@ -56,6 +56,6 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Vérifie que JSON et Markdown sont synchronisés run: python3 tools/kb.py check From 9d8acb67c9fd2453ec98831b2a3146611e5ec9df Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Aug 2026 10:05:41 +0000 Subject: [PATCH 4/4] =?UTF-8?q?feat(kb):=20rend=20fiable=20le=20filtrage?= =?UTF-8?q?=20des=20fiches=20archiv=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit index.json liste toutes les fiches, archivées comprises, pour qu'une fiche archivée reste trouvable sur demande explicite. Mais c'est aussi le seul fichier chargé systématiquement : si un consommateur ne filtre pas, une fiche archivée peut être resservie comme connaissance courante, et l'archivage devient cosmétique. Le filtre repose sur `status`, donc `status` ne doit jamais pouvoir diverger du dossier : - validate refuse une fiche dans archived/ dont le statut n'est pas `archived` ; - validate refuse une fiche marquée `archived` restée dans active/ — archiver, c'est la déplacer. - KB-CONVENTIONS.md documente explicitement le contrat : le consommateur filtre sur `status` ou sur le préfixe `archived/` du champ `path`. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Vh5PK8eE5U3PKNQ9tu8GxF --- KB-CONVENTIONS.md | 12 ++++++++++++ tools/kb.py | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/KB-CONVENTIONS.md b/KB-CONVENTIONS.md index 2021395..7a848f0 100644 --- a/KB-CONVENTIONS.md +++ b/KB-CONVENTIONS.md @@ -27,6 +27,18 @@ deuxième base à tenir à jour à la main. ne jamais les éditer directement, ils seront écrasés à la prochaine régénération. +### Fiches archivées et contrat de chargement + +`index.json` liste **toutes** les fiches, actives comme archivées, pour qu'une +fiche archivée reste trouvable sur demande explicite. Un consommateur qui charge +la connaissance courante doit donc **filtrer lui-même** — sur `status` (une +fiche archivée vaut toujours `archived`) ou sur `path` (préfixe `archived/`) — +sous peine de resservir une fiche périmée comme si elle était à jour. + +`tools/kb.py validate` garantit que ce filtre est fiable : une fiche dans +`archived/` doit porter `"status": "archived"`, et une fiche marquée `archived` +ne peut pas rester dans `active/`. Dossier et statut ne peuvent pas diverger. + ## Format de fiche (obligatoire) Fiche JSON avec attributs courts/contrôlés et un seul champ texte libre (`content`) : diff --git a/tools/kb.py b/tools/kb.py index aee81a8..cd6f137 100755 --- a/tools/kb.py +++ b/tools/kb.py @@ -242,6 +242,21 @@ def validate_fiche(fiche: dict, rel: Path, errors: list[str]) -> None: elif rel.parts[0] == "active": errors.append(f"{where}: une fiche active doit vivre dans active//.json") + # index.json liste aussi les fiches archivées : le seul moyen pour un + # consommateur de les écarter d'un chargement courant est le champ 'status'. + # On garantit donc que dossier et statut ne peuvent pas diverger. + if rel.parts[0] == "archived" and fiche.get("status") != "archived": + errors.append( + f"{where}: une fiche dans archived/ doit avoir 'status': 'archived' " + f"(trouvé {fiche.get('status')!r}) — sinon les consommateurs qui filtrent " + f"sur le statut la resserviront comme connaissance courante" + ) + if rel.parts[0] == "active" and fiche.get("status") == "archived": + errors.append( + f"{where}: 'status' vaut 'archived' mais la fiche est encore dans active/ — " + f"archiver, c'est la déplacer dans archived/" + ) + if isinstance(fiche.get("content"), str) and not fiche["content"].strip(): errors.append(f"{where}: 'content' vide")