Os exemplos de código virão em uma revisão posterior.
Nesta página
Propriedades de arquitetura tratadas
- P-1Um esquema de tempo de execução como contrato, o tipo estático derivado dele e, no padrão de referência, uma factory como único caminho para um valor verificado.
- P-4Contexto do OpenTelemetry via AsyncLocalStorage, e a identidade de auditoria como campo obrigatório de toda mensagem e de todo job.
- P-5Procedência declarada no esquema e preservada pelo serializador da resposta.
- P-6Regras de dependência e checagens de esquema na integração contínua, cada uma com uma falha plantada.
- P-7Portas no pacote de domínio; um pacote adaptador por sistema externo.
- P-8Uma interface de política sobre um motor, via HTTP ou compilado para WebAssembly, com a revisão em cada decisão.
- P-2, P-3Apenas na profundidade que o COADF publica.
Intenção de arquitetura
O TypeScript dá à fronteira um vocabulário e nenhum meio de impô-la. Anotações de tipo nunca mudam o comportamento de um programa em tempo de execução: elas descrevem o que um valor deveria ser e desaparecem antes de ele rodar, enquanto os dados que chegam de um modelo, de uma fila ou de uma requisição têm a forma que têm. As tipagens padrão declaram o resultado de JSON.parse como any, que o compilador então deixa tratar como qualquer coisa.
Por isso, neste ecossistema, a fronteira é o esquema de tempo de execução, e o tipo estático é derivado do esquema, nunca o contrário. Todo o resto deste perfil decorre dessa inversão. Zod, Ajv, Fastify e NestJS são exemplos: o COADF não exige nenhum deles, e qualquer validador de tempo de execução que recuse o que o contrato não declara mantém a propriedade.
Correspondência tecnológica
| Propriedade de arquitetura | TypeScript e Node |
|---|---|
| Tipo de fronteira | Um esquema de tempo de execução (Zod, ou JSON Schema com Ajv) como fonte, com o tipo estático inferido dele. O sistema de tipos do TypeScript é estrutural, então um valor verificado que não pode ser confundido com uma proposta precisa de um brand, e só uma factory o aplica. |
| Validação em tempo de execução | parse ou safeParse em todo lado receptor. O parse do Zod lança exceção com dados inválidos, e o safeParse devolve um resultado em vez disso. |
| Chaves desconhecidas | Uma escolha explícita por esquema. No Zod 4, z.object() remove chaves desconhecidas e z.strictObject() as rejeita. |
| Validação do framework | Esquemas de rota do Fastify, validados com Ajv e serializados com fast-json-stringify; ou o ValidationPipe do NestJS com whitelist e forbidNonWhitelisted. |
| Regra de arquitetura | Regras de dependência checadas na CI: dependency-cruiser, regras de fronteira do ESLint ou project references do TypeScript que tornam uma importação ilegal um erro de compilação. |
| Contexto de execução | OpenTelemetry JS, cujo context manager para Node é baseado em AsyncLocalStorage. |
| Trilha de auditoria | O mesmo esquema PostgreSQL, por meio de um driver; entradas escritas na transação de negócio. |
| Isolamento de normas | Interfaces de porta no pacote de domínio; cada cliente de fornecedor confinado a um pacote adaptador no workspace. |
| Política | Open Policy Agent via HTTP, ou Rego compilado para WebAssembly e avaliado no próprio processo pelo SDK JavaScript do OPA; a revisão em cada decisão. |
Padrão de referência
Os exemplos de código virão em uma revisão posterior. Eles ficam adiados até que uma pessoa revisora que trabalhe neste ecossistema os tenha lido, em vez de serem escritos para que os quatro perfis pareçam iguais. A estrutura abaixo é o padrão de referência que esses exemplos vão implementar.
Pacotes
schemascontém os esquemas de tempo de execução de todos os contratos: a proposta com sua procedência, a entrada de auditoria com os campos publicados, a decisão de política com sua revisão. Todos os outros pacotes importam seus tipos daqui, inferidos dos esquemas.inferencechama o modelo e devolve o resultado do parse da resposta com o esquema de proposta. Ele não pode importarrecordsnemaudit, e uma regra de dependência na CI afirma isso.recordsexporta uma factory que recebe uma proposta e a verificação de uma pessoa nomeada e devolve um valor verificado com brand. O tipo do brand não pode ser construído em outro lugar sem um cast, e uma regra de lint proíbe esse cast fora deste pacote.audit,classificationcom seu adaptador de fornecedor, epolicyseguem a mesma forma que nos outros perfis.
Fronteiras em tempo de execução
Todo lado receptor faz o parse: a rota HTTP, o consumidor de mensagens, o executor de jobs e a factory do domínio. Um esquema de rota no Fastify ou um pipe no NestJS cobre apenas o ponto de entrada web.
O SDK do OpenTelemetry é carregado antes dos módulos da própria aplicação. Uma aplicação em ES modules precisa do loader hook do OpenTelemetry para a instrumentação automática, além do pré-carregamento do SDK.
Modos de falha
Uma anotação de tipo confundida com validação
Fazer cast do resultado de
JSON.parsepara o tipo de proposta compila, e não verifica nada. O cast é a fronteira mais comum em código TypeScript, e não é uma fronteira.Remover confundido com recusar
Um objeto Zod padrão remove chaves desconhecidas. Uma resposta que afirma estar verificada não é recusada; a afirmação é removida em silêncio, e com ela se perde o fato de que o modelo afirmou além do que podia. Onde a própria afirmação é evidência, convém usar um objeto estrito e registrar a rejeição.
Conversão por padrão no Fastify
As opções padrão do Ajv no Fastify incluem
coerceTypes,useDefaultseremoveAdditional. Um número enviado como texto chega como número, e um valor ausente pode chegar como um valor padrão. O validador das rotas de fronteira precisa ser configurado explicitamente.Procedência descartada pelo serializador da resposta
Com um esquema de resposta, as propriedades que o esquema não lista ficam de fora, a menos que ele permita propriedades adicionais. Um esquema de resposta escrito para a tela, sem a procedência, a remove de todas as respostas.
Um pipe do NestJS que deixa tudo passar
whitelistremove propriedades sem decorators de validação, eforbidNonWhitelistedlança exceção em vez de remover. Sem nenhum dos dois, uma propriedade que o DTO não declara chega ao handler.Contexto perdido no trabalho assíncrono
AsyncLocalStorageguarda dados durante o tempo de vida de uma requisição ou de outra duração assíncrona, e acompanha as continuações que o Node consegue ver. Trabalho que reentra a partir de um callback de pool ou da fila própria de uma biblioteca pode chegar sem ele; a identidade de auditoria precisa estar na mensagem, e não ser recuperada do contexto.Instrumentação automática ausente em silêncio
Um serviço em ES modules iniciado sem o loader hook roda normalmente, e as bibliotecas que o hook teria instrumentado não produzem spans. Nada falha; o trace é apenas mais curto do que a execução.
Um brand forjado com um cast
Um cast para o tipo verificado compila em qualquer lugar. Brand mais factory é uma convenção que o compilador não consegue impor sozinho; a regra de lint e a revisão de código são o que a fazem valer.
Duas versões dos esquemas compartilhados
Produtor e consumidor dependem de releases diferentes do pacote
schemas, e cada um valida corretamente contra um contrato diferente. Testes de contrato entre as versões de fato implantadas pegam isso; testes unitários, não.
Verificação
Teste unitário
Passa quando: Respostas malformadas são rejeitadas pelo esquema de proposta: chave desconhecida, tipo errado, procedência ausente, atributo inesperado.
Prova de dentes: Trocar o objeto estrito por um padrão em uma branch descartável: o teste da chave desconhecida falha.
Teste unitário
Passa quando: Um teste no nível de tipos afirma que uma proposta não é atribuível a um valor verificado.
Prova de dentes: Remover o brand: o teste no nível de tipos deixa de compilar.
Teste de arquitetura
Passa quando: As regras de dependência passam: nenhuma importação de
inferencepararecordsouaudit, nenhum cliente de fornecedor fora do seu adaptador.Prova de dentes: Plantar a importação proibida: a CI falha.
Teste de contrato
Passa quando: A resposta de toda rota que serve uma proposta contém os campos de procedência.
Prova de dentes: Remover uma propriedade de procedência do esquema de resposta: o teste falha, porque o serializador a descartou.
Teste de integração
Passa quando: Com um exportador de spans em memória, o trabalho assíncrono aparece no trace da requisição, e as entradas de auditoria persistidas carregam uma única identidade.
Teste de integração
Passa quando: As decisões de política carregam a revisão do material de política que as produziu; respostas sem ela são recusadas.
Realizações alternativas
- Outras bibliotecas de esquema (Valibot, TypeBox com Ajv, io-ts). A propriedade é um esquema de tempo de execução que é a fonte do tipo; a biblioteca é uma escolha.
- Transportes schema-first como GraphQL ou Protocol Buffers, em que o contrato é um artefato separado a partir do qual os dois lados são gerados.
- Um motor de políticas no próprio processo via WebAssembly, em vez de via HTTP, para remover o salto de rede; a exigência quanto à revisão da política não muda.
Escolhas de compromisso
- Schema-first desloca a fonte da verdade para fora das declarações de tipo, o que algumas equipes acham pouco natural; type-first deixa o tempo de execução desprotegido.
- Validadores compilados são rápidos e trazem padrões que convertem e preenchem; a configuração mais rápida não é a mais estrita.
- Objetos estritos rejeitam mais do que um modelo produz, e cada rejeição exige uma decisão sobre o que registrar.
- Um workspace de pacotes pequenos torna as regras de dependência expressáveis, e custa maquinário de build e de release.
Limitações
- Nenhum código é publicado para este perfil no Companion 1.0, e nenhum exemplo foi executado. O comportamento descrito foi tirado da documentação oficial atual, conferida em 11 de setembro de 2026, do Zod 4, Fastify 5, NestJS, Node.js 24 e OpenTelemetry JS 2.
- Nada aqui mostra como a confiança é representada, quando a revisão é exigida ou como a revisão é organizada; o COADF não publica essas partes de P-2 e P-3.
O que este perfil não estabelece
Seguir este perfil não estabelece conformidade regulatória, certificação nem avaliação da conformidade, e nem o TypeScript nem o Node são exigidos pelo COADF.
Ambiente de referência testado
Nenhum exemplo foi executado para este perfil.
Fontes
- TypeScript: The Basics: erased types · documentação oficial · Verificado em 2026-09-11
- TypeScript: lib.es5.d.ts: JSON.parse · repositório do projeto · Verificado em 2026-09-11
- TypeScript: Type compatibility · documentação oficial · Verificado em 2026-09-11
- Zod: Basic usage: handling errors · documentação oficial · Zod 4 · Verificado em 2026-09-11
- Zod: Objects and z.strictObject · documentação oficial · Zod 4 · Verificado em 2026-09-11
- Fastify: Validation and serialization · documentação oficial · Fastify 5.12 · Verificado em 2026-09-11
- Fastify: fast-json-stringify: additionalProperties · repositório do projeto · Verificado em 2026-09-11
- NestJS: Validation: stripping properties · documentação oficial · Verificado em 2026-09-11
- Node.js: Asynchronous context tracking: AsyncLocalStorage · documentação oficial · Node.js 24 · Verificado em 2026-09-11
- OpenTelemetry: Context manager (JavaScript) · repositório do projeto · OpenTelemetry JS 2.11.0 · Verificado em 2026-09-11
- OpenTelemetry JS: ESM support · repositório do projeto · Verificado em 2026-09-11
- Open Policy Agent: WebAssembly · documentação oficial · OPA 1.20 · Verificado em 2026-09-11
