Skip to content

ADRs: AI API

ADR-000: Repositório separado contrasync-ai-api

Status: Accepted (2026-05-15) Contexto: Roadmap IA-CLM Fase 0, D0.0.

Decisão: Criar repositório separado em vez de subdiretório no contrasync-nest-api.

Motivação:

  • Deploy independente, IA não compartilha pipeline com cobrança/auth/contratos.
  • Tooling distinto, Anthropic SDK, eval harness, pgvector não pertencem ao produto.
  • Risco isolado, bug em prompt não derruba checkout/assinatura.
  • Schema ai separado no mesmo Postgres mantém custo zero de infra extra.

Consequências:

  • Dois node_modules, dois CIs, dois containers.
  • Auth precisa propagar via BFF: não há shortcut "no monorepo eu chamo o service direto".
  • Compartilhamento de tipos via OpenAPI (/v1/openapi.json), não import direto.

Alternativas descartadas:

  • Subdiretório contrasync-nest-api/src/modules/ai: acopla deploy + pollui domain do produto.
  • Repositório monorepo (Nx/Turbo): overhead de tooling sem ganho concreto no MVP.

ADR-001: Modelo padrão claude-haiku-3-5

Status: Accepted (2026-05-15) Contexto: Lean cost strategy (governance/lean-cost-strategy.md).

Decisão: Default AI_DEFAULT_MODEL=claude-haiku-3-5.

Motivação:

  • US$ 0,80 / 1M input vs Sonnet US$ 3,00, economia ~73% no MVP.
  • Suporta prompt caching (TTL 5min) reduzindo custo de prompts longos.
  • Suporta tool use + structured output, atende todos requisitos D0.3/D0.4.
  • Tier 1 Anthropic (pay-as-you-go) sem compromisso.

Trigger de upgrade:

  • Eval baseline de drafting < 3,5/5 → testa Haiku 4.5 (+25%).
  • Cliente paga modo premium → Sonnet 4.6 (~3x).
  • Decisão por env var, sem PR.

Consequências:

  • Provider abstraction (AIProvider) preserva troca sem código novo.
  • Eval suite mede impacto antes de upgrade.

ADR-002: Banco Postgres próprio e isolado da IA

Status: Accepted (2026-05-16), substitui a decisão anterior de schema compartilhado. Contexto: Decisão founder 2026-05-16, a IA é um produto único do Contrasync, com banco próprio. Não conecta no Postgres do produto.

Decisão: contrasync-ai-api tem database Postgres dedicado (contrasync_ai, schema ai, pgvector). Nenhuma conexão com o banco do produto, nem leitura. Dados do produto chegam só via REST pelo Product API (ProductApiClient). Não existe ProductDbReader, role ai_reader nem views ai_v_*.

Motivação:

  • Isolamento total de falha e de dados, bug/carga da IA não toca o produto.
  • Fronteira única e auditável (REST) para todo dado do produto.
  • pgvector e tabelas ai_* vivem no banco da IA, sem poluir o produto.

Garantias:

  • DATABASE_URL da IA aponta só para contrasync_ai.
  • Toda leitura/escrita de dado do produto passa por endpoint REST do Product API com o token do usuário propagado pelo gateway.
  • Sessões/turns/tool-calls/embeddings persistem no banco da IA.

Consequências:

  • Custo de uma instância Postgres a mais (aceito pelo founder pelo isolamento).
  • Sem JOIN cross-schema; a IA compõe dados via chamadas REST.

A IA nunca conecta no Postgres do produto: não existem ProductDbReader, role ai_reader nem views ai_v_*. Todo dado do produto é acessado apenas via REST no Product API com o token do usuário propagado pelo gateway.


ADR-003: Token de usuário propagado pelo gateway

Status: Accepted (2026-05-15, atualizado 2026-05-16) Contexto: Restrição founder, sem service-account no MVP.

Decisão: AI API valida Authorization: Bearer <user-jwt> que o gateway contrasync-bff propaga (token real do usuário, sem cunhar). Nenhuma service-account ou chave compartilhada.

Motivação:

  • Auditoria natural, toda ação rastreada ao usuário humano.
  • RBAC do produto continua sendo autoridade final (toda leitura/escrita de dado do produto é REST com esse token).
  • Sem proliferação de credenciais.

Garantias:

  • BffTokenGuard valida assinatura HS256 com JWT_SECRET compartilhado.
  • AI API persiste apenas SHA-256 do token (user_jwt_ref), nunca texto plano.
  • TTL do token = TTL da sessão AI.

Consequências:

  • Sessões longas precisam refresh, front renova token, BFF propaga novo.
  • Background jobs internos no Product API que querem chamar AI API precisam de ticket especial, fora do escopo do MVP.