Les exemples de code suivront dans une révision ultérieure.
Sur cette page
Propriétés d'architecture traitées
- P-1Un schéma d'exécution comme contrat, le type statique qui en est dérivé et, dans le pattern de référence, une fabrique comme seul chemin vers une valeur vérifiée.
- P-4Le contexte OpenTelemetry via AsyncLocalStorage, et l'identité d'audit comme champ obligatoire de chaque message et de chaque job.
- P-5La provenance déclarée dans le schéma, et préservée par le sérialiseur de réponse.
- P-6Des règles de dépendances et des contrôles de schéma dans l'intégration continue, chacun avec un échec planté.
- P-7Des ports dans le paquet du domaine ; un paquet d'adaptateur par système externe.
- P-8Une interface de politique au-dessus d'un moteur, via HTTP ou compilé en WebAssembly, avec la révision sur chaque décision.
- P-2, P-3Seulement à la profondeur que COADF publie.
Intention d'architecture
TypeScript donne à la frontière un vocabulaire, et rien de son application. Les annotations de type ne changent jamais le comportement d'un programme à l'exécution : elles décrivent ce qu'une valeur devrait être et disparaissent avant l'exécution, tandis que les données qui arrivent d'un modèle, d'une file ou d'une requête ont la forme qu'elles ont. Les typages standard déclarent le résultat de JSON.parse comme any, que le compilateur laisse ensuite traiter comme n'importe quoi.
Dans cet écosystème, la frontière est donc le schéma d'exécution, et le type statique est dérivé du schéma, jamais l'inverse. Tout le reste de ce profil découle de ce renversement. Zod, Ajv, Fastify et NestJS sont des exemples : COADF n'en exige aucun, et tout validateur d'exécution qui refuse ce que le contrat ne déclare pas tient la propriété.
Correspondance technologique
| Propriété d'architecture | TypeScript et Node |
|---|---|
| Type de frontière | Un schéma d'exécution (Zod, ou JSON Schema avec Ajv) comme source, avec le type statique inféré à partir de lui. Le système de types de TypeScript est structurel : une valeur vérifiée qui ne doit pas être confondue avec une proposition a donc besoin d'une marque (brand), et seule une fabrique l'applique. |
| Validation à l'exécution | parse ou safeParse de chaque côté récepteur. Le parse de Zod lève une exception sur des données invalides, et safeParse renvoie un résultat à la place. |
| Clés inconnues | Un choix explicite par schéma. Dans Zod 4, z.object() retire les clés inconnues et z.strictObject() les rejette. |
| Validation du framework | Les schémas de route de Fastify, validés avec Ajv et sérialisés avec fast-json-stringify ; ou le ValidationPipe de NestJS avec whitelist et forbidNonWhitelisted. |
| Règle d'architecture | Des règles de dépendances contrôlées dans la CI : dependency-cruiser, des règles de frontière ESLint, ou des références de projet TypeScript qui font d'un import illégal une erreur de compilation. |
| Contexte d'exécution | OpenTelemetry JS, dont le gestionnaire de contexte pour Node est fondé sur AsyncLocalStorage. |
| Piste d'audit | Le même schéma PostgreSQL via un driver ; des entrées écrites dans la transaction métier. |
| Isolation des normes | Des interfaces de port dans le paquet du domaine ; chaque client de fournisseur cantonné à un paquet d'adaptateur dans le workspace. |
| Politique | Open Policy Agent via HTTP, ou Rego compilé en WebAssembly et évalué dans le processus grâce au SDK JavaScript d'OPA ; la révision sur chaque décision. |
Pattern de référence
Les exemples de code suivront dans une révision ultérieure. Ils sont reportés jusqu'à ce qu'une personne qui vérifie et travaille dans cet écosystème les ait lus, plutôt qu'écrits pour que les quatre profils se ressemblent. La structure ci-dessous est le pattern de référence que ces exemples mettront en œuvre.
Paquets
schemascontient les schémas d'exécution de chaque contrat : la proposition avec sa provenance, l'entrée d'audit avec les champs publiés, la décision de politique avec sa révision. Tous les autres paquets importent leurs types d'ici, inférés à partir des schémas.inferenceappelle le modèle et renvoie le résultat de l'analyse de la réponse avec le schéma de proposition. Il ne peut pas importerrecordsouaudit, et une règle de dépendances dans la CI l'affirme.recordsexporte une fabrique qui prend une proposition et la vérification d'une personne nommée et renvoie une valeur vérifiée marquée. Le type de la marque ne peut pas être construit ailleurs sans cast, et une règle de lint interdit ce cast hors de ce paquet.audit,classificationavec son adaptateur de fournisseur, etpolicysuivent la même forme que dans les autres profils.
Les frontières à l'exécution
Chaque côté récepteur analyse : la route HTTP, le consommateur de messages, l'exécuteur de jobs et la fabrique du domaine. Un schéma de route dans Fastify ou un pipe dans NestJS ne couvre que le point d'entrée web.
Le SDK OpenTelemetry est chargé avant les propres modules de l'application. Une application en modules ES a besoin du hook de chargement d'OpenTelemetry pour l'instrumentation automatique, en plus du préchargement du SDK.
Modes de défaillance
Une annotation de type prise pour une validation
Caster le résultat de
JSON.parsevers le type de proposition compile, et ne contrôle rien. Le cast est la frontière la plus courante dans le code TypeScript, et ce n'est pas une frontière.Retirer pris pour refuser
Un objet Zod par défaut retire les clés inconnues. Une réponse qui se dit vérifiée n'est pas refusée ; l'affirmation est discrètement retirée, et le fait que le modèle en ait trop affirmé disparaît avec elle. Là où l'affirmation elle-même constitue une preuve, utiliser un objet strict et enregistrer le rejet.
La conversion par défaut dans Fastify
Les options Ajv par défaut de Fastify incluent
coerceTypes,useDefaultsetremoveAdditional. Un nombre envoyé sous forme de texte arrive comme nombre, et une valeur manquante peut arriver comme valeur par défaut. Configurer explicitement le validateur pour les routes de frontière.La provenance perdue par le sérialiseur de réponse
Avec un schéma de réponse, les propriétés que le schéma ne liste pas sont omises, sauf s'il autorise des propriétés supplémentaires. Un schéma de réponse écrit pour l'écran, sans la provenance, la retire de chaque réponse.
Un pipe NestJS qui laisse tout passer
whitelistretire les propriétés sans décorateurs de validation, etforbidNonWhitelistedlève une exception au lieu de les retirer. Sans l'une ni l'autre, une propriété que le DTO ne déclare pas atteint le handler.Le contexte perdu à travers le travail asynchrone
AsyncLocalStorageconserve des données pendant la durée de vie d'une requête ou d'une autre durée asynchrone, et suit les continuations que Node peut voir. Le travail qui revient depuis un callback mutualisé ou depuis la file propre à une bibliothèque peut arriver sans lui ; l'identité d'audit doit se trouver dans le message, et non être récupérée depuis le contexte.L'instrumentation automatique absente sans bruit
Un service en modules ES démarré sans le hook de chargement fonctionne normalement, et les bibliothèques que le hook aurait instrumentées ne produisent aucun span. Rien n'échoue ; la trace est simplement plus courte que l'exécution.
Une marque contrefaite par un cast
Un cast vers le type vérifié compile n'importe où. La marque avec sa fabrique est une convention que le compilateur ne peut pas imposer à lui seul ; ce sont la règle de lint et la revue de code qui la font tenir.
Deux versions des schémas partagés
Le producteur et le consommateur dépendent de versions différentes du paquet
schemas, et chacun valide correctement contre un contrat différent. Les tests de contrat entre les versions réellement déployées le détectent ; les tests unitaires, non.
Vérification
Test unitaire
Réussit quand : Les réponses mal formées sont rejetées par le schéma de proposition : clé inconnue, type erroné, provenance manquante, attribut inattendu.
Preuve de dents : Remplacer l'objet strict par un objet par défaut dans une branche jetable : le test de la clé inconnue échoue.
Test unitaire
Réussit quand : Un test au niveau des types affirme qu'une proposition n'est pas assignable à une valeur vérifiée.
Preuve de dents : Retirer la marque : le test au niveau des types ne compile plus.
Test d'architecture
Réussit quand : Les règles de dépendances passent : aucun import de
inferenceversrecordsouaudit, aucun client de fournisseur hors de son adaptateur.Preuve de dents : Planter l'import interdit : la CI échoue.
Test de contrat
Réussit quand : La réponse de chaque route qui sert une proposition contient les champs de provenance.
Preuve de dents : Retirer une propriété de provenance du schéma de réponse : le test échoue, parce que le sérialiseur l'a supprimée.
Test d'intégration
Réussit quand : Avec un exportateur de spans en mémoire, le travail asynchrone apparaît dans la trace de la requête, et les entrées d'audit persistées portent une seule identité.
Test d'intégration
Réussit quand : Les décisions de politique portent la révision du matériau de politique qui les a produites ; les réponses qui n'en ont pas sont refusées.
Réalisations alternatives
- D'autres bibliothèques de schémas (Valibot, TypeBox avec Ajv, io-ts). La propriété est un schéma d'exécution qui est la source du type ; la bibliothèque est un choix.
- Des transports fondés sur le schéma, comme GraphQL ou Protocol Buffers, où le contrat est un artefact séparé à partir duquel les deux côtés sont générés.
- Un moteur de politiques dans le processus via WebAssembly, plutôt que via HTTP, pour supprimer le saut réseau ; l'exigence de révision ne change pas.
Compromis
- Partir du schéma déplace la source de vérité hors des déclarations de types, ce que certaines équipes trouvent peu naturel ; partir des types laisse l'exécution sans protection.
- Les validateurs compilés sont rapides et apportent des réglages par défaut qui convertissent et complètent ; la configuration la plus rapide n'est pas la plus stricte.
- Les objets stricts rejettent davantage de ce que produit un modèle, et chaque rejet demande une décision sur ce qu'il faut enregistrer.
- Un workspace de petits paquets rend les règles de dépendances exprimables, et coûte en outillage de build et de livraison.
Limites
- Aucun code n'est publié pour ce profil dans Companion 1.0, et aucun exemple n'a été exécuté. Le comportement décrit est tiré de la documentation officielle actuelle, consultée le 11 septembre 2026, pour Zod 4, Fastify 5, NestJS, Node.js 24 et OpenTelemetry JS 2.
- Rien ici ne montre comment la confiance est représentée, quand une revue est requise, ni comment la revue est organisée ; COADF ne publie pas ces parties de P-2 et P-3.
Ce que ce profil n'établit pas
Suivre ce profil n'établit ni la conformité réglementaire, ni une certification, ni une évaluation de la conformité, et COADF n'exige ni TypeScript ni Node.
Environnement de référence testé
Aucun exemple n'a été exécuté pour ce profil.
Sources
- TypeScript: The Basics: erased types · documentation officielle · Vérifié le 2026-09-11
- TypeScript: lib.es5.d.ts: JSON.parse · dépôt du projet · Vérifié le 2026-09-11
- TypeScript: Type compatibility · documentation officielle · Vérifié le 2026-09-11
- Zod: Basic usage: handling errors · documentation officielle · Zod 4 · Vérifié le 2026-09-11
- Zod: Objects and z.strictObject · documentation officielle · Zod 4 · Vérifié le 2026-09-11
- Fastify: Validation and serialization · documentation officielle · Fastify 5.12 · Vérifié le 2026-09-11
- Fastify: fast-json-stringify: additionalProperties · dépôt du projet · Vérifié le 2026-09-11
- NestJS: Validation: stripping properties · documentation officielle · Vérifié le 2026-09-11
- Node.js: Asynchronous context tracking: AsyncLocalStorage · documentation officielle · Node.js 24 · Vérifié le 2026-09-11
- OpenTelemetry: Context manager (JavaScript) · dépôt du projet · OpenTelemetry JS 2.11.0 · Vérifié le 2026-09-11
- OpenTelemetry JS: ESM support · dépôt du projet · Vérifié le 2026-09-11
- Open Policy Agent: WebAssembly · documentation officielle · OPA 1.20 · Vérifié le 2026-09-11
