Appearance
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
aiseparado 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_URLda IA aponta só paracontrasync_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, roleai_readernem viewsai_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:
BffTokenGuardvalida assinatura HS256 comJWT_SECRETcompartilhado.- 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.