Fecha agente.md secao 95-103. Primeira peca do modulo de IA — a
abstracao de provider, os adapters OpenAI/Anthropic, capabilities, e o
cadastro de providers/modelos (global + BYOK). O pipeline que aciona
isso depois de uma chamada terminar (transcricao, analise, jobs
assincronos, prompts, scorecards, usage metering — secao 104-124) fica
pra proxima fase.
## Schema completo do modulo de IA numa unica migration
Todas as tabelas das secoes 95-124 de uma vez (ai_providers/ai_models/
ai_prompt_templates+versions/ai_jobs/call_transcriptions+segments/
call_ai_analyses/quality_scorecards+items+evaluations/ai_usage_records) —
mais barato revisar o desenho relacional inteiro numa unica passada do
que fatiar em migrations pequenas que se emendam. O codigo que usa essas
tabelas vem em fases separadas, so' Provider/Model nesta.
## packages/ai
Interface AIProvider (secao 96: nunca hardcoda OpenAI no dominio).
OpenAIProvider/AnthropicProvider (secao 97-98, nomenclatura "OpenAI API"/
"Anthropic API", nunca "ChatGPT") via fetch nativo direto contra cada API
— sem SDK oficial, request/response inteiramente visivel no proprio
codigo (relevante ja' que manda dado de cliente pra fora, secao 122-123).
transcribe so' na OpenAI (Anthropic nao tem endpoint de audio, secao 102:
"nem todo provider tem todas as capacidades"); analyze/structuredGenerate
via Structured Outputs na OpenAI e "tool use" forcado na Anthropic.
SensitiveDataRedactor (secao 123): CPF/CNPJ/telefone/email/cartao.
**Nunca exercitados contra rede real** — esta sessao so' tem autorizacao
de rede pro servidor git (restricao definida desde o primeiro pedido do
usuario). Mesmo padrao de honestidade ja' usado pro S3ObjectStorageProvider
e o caminho PSTN real.
## ai_providers/ai_models — global vs. BYOK
scope=GLOBAL (platform admin, tenant_id null) visivel de qualquer tenant;
scope=TENANT (BYOK) so' do dono. RLS hibrida (tenant_id = current OR
tenant_id IS NULL, mesma tecnica de tenant_memberships no login); quem
pode ESCREVER num GLOBAL e' decidido na camada de servico
(isPlatformUser), nao pela RLS. Key nunca reexposta (so' apiKeyPreview).
## Dois bugs reais achados testando esta fase
- Delete de provider fazia hard delete, bloqueado por FK quando um
AIModel (mesmo soft-deleted) ainda referenciava — inconsistente com o
resto do sistema (tudo soft delete). Corrigido; GET /ai/providers
tambem nao filtrava desabilitados, corrigido junto.
- SensitiveDataRedactor: \b antes de \(? opcional falha quando o char
anterior tambem nao e' de palavra (espaco + "("), vazando um parenteses
solto (nenhum dado sensivel de verdade vazava). Corrigido com (?<!\w).
Verificado ponta a ponta com 2 tenants + platform admin: GLOBAL so'
platform admin cria/apaga, BYOK isolado por RLS (tenant B nunca ve' BYOK
do tenant A, 404 em id direto), modelo de provider GLOBAL visivel dos
dois tenants, redactor com 5 tipos de dado sensivel todos corretos.
typecheck do workspace inteiro limpo.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X1HxY46WGU4G1zmVDNKcWw
42 lines
1.1 KiB
JSON
42 lines
1.1 KiB
JSON
{
|
|
"name": "@b2bcall/api",
|
|
"version": "0.0.1",
|
|
"private": true,
|
|
"scripts": {
|
|
"dev": "tsc -p tsconfig.json && tsx dist/main.js",
|
|
"build": "tsc -p tsconfig.json",
|
|
"start": "tsx dist/main.js",
|
|
"typecheck": "tsc --noEmit"
|
|
},
|
|
"dependencies": {
|
|
"@b2bcall/ai": "workspace:*",
|
|
"@b2bcall/auth": "workspace:*",
|
|
"@b2bcall/database": "workspace:*",
|
|
"@b2bcall/entitlements": "workspace:*",
|
|
"@b2bcall/shared": "workspace:*",
|
|
"@b2bcall/storage": "workspace:*",
|
|
"@b2bcall/telephony": "workspace:*",
|
|
"@fastify/cors": "11.3.0",
|
|
"@fastify/helmet": "13.1.1",
|
|
"@fastify/rate-limit": "11.2.0",
|
|
"@nestjs/common": "^12.0.1",
|
|
"@nestjs/core": "^12.0.1",
|
|
"@nestjs/platform-fastify": "^12.0.1",
|
|
"@nestjs/platform-socket.io": "12.0.1",
|
|
"@nestjs/websockets": "12.0.1",
|
|
"class-transformer": "^0.5.1",
|
|
"class-validator": "^0.15.1",
|
|
"fast-xml-parser": "5.11.1",
|
|
"fastify": "5.12.1",
|
|
"ioredis": "^6.0.0",
|
|
"reflect-metadata": "^0.2.2",
|
|
"rxjs": "^7.8.2",
|
|
"socket.io": "4.8.3"
|
|
},
|
|
"devDependencies": {
|
|
"@types/node": "^22.0.0",
|
|
"tsx": "^4.23.12",
|
|
"typescript": "^5.7.0"
|
|
}
|
|
}
|