{
  "slug": "crm-lab",
  "title": "Plataforma de operações com IA",
  "auditDate": "2026-10-04",
  "recordType": "Resumo público derivado de registros privados; não é certificação independente.",
  "scope": "Testes locais de componentes. Provedores, transportes e stores substituídos conforme a suíte. Sem certificação integrada de produção.",
  "reproduction": "Fontes e logs originais são privados. Os hashes foram conferidos nesta etapa; as suítes foram executadas na auditoria anterior do mesmo dia.",
  "suites": [
    {
      "name": "Backend de assistência com LLMs",
      "passed": 23,
      "exitCode": 0,
      "recordSha256": "793709bdbe72159790c723623e7608c29247f5a6cc7d1920caa04a13e1876df4",
      "environment": "Local; sem container Windows; sem chamada paga de modelo",
      "scenarios": [
        "POST /api/ai/chat requires page.ai_assistant permission",
        "POST /api/ai/chat returns 503 when OpenRouter key is not configured and never asks the frontend for a key",
        "GET /api/ai/settings exposes user preferences, agent settings and management flags",
        "GET /api/ai/status derives context limit from the active registry model",
        "PUT /api/ai/settings/agent requires ai.agent.manage or settings.manage",
        "agent settings override OpenRouter model and generation parameters used by chat",
        "POST /api/ai/chat enables OpenRouter reasoning only for compatible models",
        "POST /api/ai/chat omits parallel tool calls when the active OpenRouter model does not support the parameter",
        "POST /api/ai/models validates and stores an eligible OpenRouter model",
        "POST /api/ai/models rejects models without CRM-required capabilities",
        "validateOpenRouterModel uses the documented single model lookup endpoint",
        "listOpenRouterModelCandidates sends server-side filters, sort and pagination",
        "fallback chain sends OpenRouter models array and returns the actual model used",
        "AI tool list sent to the LLM exposes semantic tools only",
        "POST /api/ai/chat calls OpenRouter with Bearer token and executes read-only semantic tools",
        "POST /api/ai/chat never retries invalid OpenRouter credentials",
        "POST /api/ai/chat retries one recoverable provider failure and accounts every attempt",
        "POST /api/ai/chat deterministically reads active ads campaigns before answering",
        "POST /api/ai/chat blocks legacy raw SQL tool calls without executing repository queries",
        "softenAiCertaintyLanguage removes absolute smoke-test wording before persistence",
        "buildListMemoryEntriesQuery keeps optional PostgreSQL parameters typed",
        "GET /api/ai/memories forwards shared memory management permission to the runner",
        "sanitizeAiToolRows removes sensitive fields before tool results are sent to the LLM"
      ]
    },
    {
      "name": "Contratos e privacidade de métricas — componente complementar",
      "passed": 9,
      "exitCode": 0,
      "recordSha256": "ecad184ffc7c74955a704226194e7f53da21f70889eadc3938660e6a700c1ef3",
      "environment": "Local; sem container Windows; sem chamada paga de modelo",
      "scenarios": []
    },
    {
      "name": "Consentimento e minimização — componente complementar",
      "passed": 3,
      "exitCode": 0,
      "recordSha256": "a22817a597ec67fda0cd4832750e02cf49f61995a88a40ad9e7947be7fb89cfc",
      "environment": "Local; sem container Windows; sem chamada paga de modelo",
      "scenarios": [
        "requires explicit analytics consent",
        "hashes IP without exposing the original value",
        "tracker keeps the production collect endpoint"
      ]
    }
  ],
  "capabilities": [
    {
      "id": "E01",
      "name": "LLMs, OpenRouter e API compatível OpenAI",
      "status": "comprovada no recorte local",
      "sourceSha256": "b9d13e0db0c9e7dd6661d9b6e88a9258c38520cbcb689c8f5bd7aa1f5733206b",
      "limitation": "Fetch substituído por mocks; sem chamada paga ou certificação em produção."
    },
    {
      "id": "E02",
      "name": "Tool calling e guardrails",
      "status": "comprovada no recorte local",
      "sourceSha256": "b9d13e0db0c9e7dd6661d9b6e88a9258c38520cbcb689c8f5bd7aa1f5733206b",
      "limitation": "Ferramentas semânticas controladas; não equivalem a LangChain, LangGraph ou MCP server."
    },
    {
      "id": "E03",
      "name": "Memória persistente e busca textual SQL",
      "status": "parcialmente comprovada — implementação sem validação integrada",
      "sourceSha256": "b9d13e0db0c9e7dd6661d9b6e88a9258c38520cbcb689c8f5bd7aa1f5733206b",
      "limitation": "Consulta/mapeamento testados sem PostgreSQL real; tsvector não é embedding nem busca vetorial."
    },
    {
      "id": "E04",
      "name": "Custos, tokens e contexto LLM",
      "status": "comprovada no recorte local",
      "sourceSha256": "b9d13e0db0c9e7dd6661d9b6e88a9258c38520cbcb689c8f5bd7aa1f5733206b",
      "limitation": "Custos declarados pelo provedor; unavailable/partial não viram zero. Sem FinOps cloud certificado."
    },
    {
      "id": "E05",
      "name": "Privacidade nos resultados de ferramentas",
      "status": "comprovada no recorte local",
      "sourceSha256": "b9d13e0db0c9e7dd6661d9b6e88a9258c38520cbcb689c8f5bd7aa1f5733206b",
      "limitation": "Sanitização coberta; não comprova conformidade legal integral ou ausência de todo vazamento."
    },
    {
      "id": "E06",
      "name": "Permissões e tenant no backend",
      "status": "comprovada no recorte local",
      "sourceSha256": "4f0d83ab73a091e8bea8ae3e71e2b5a51483d7b089b8598c0c61aa252cbba10e",
      "limitation": "Rotas com usuário/tenant servidor; não afirmar RLS uniforme em todo CRM."
    },
    {
      "id": "E07",
      "name": "Timeout e retry de provedor",
      "status": "comprovada no recorte local",
      "sourceSha256": "b9d13e0db0c9e7dd6661d9b6e88a9258c38520cbcb689c8f5bd7aa1f5733206b",
      "limitation": "Retry recuperável exercitado; não é teste de carga/distribuição em produção."
    },
    {
      "id": "E08",
      "name": "TypeScript, Node.js, Fastify e APIs",
      "status": "comprovada no recorte local",
      "sourceSha256": "faecfefca682a05b8404fac46485a7253d6dcf8cd6542d0d5f5a4ab9c723a7c8",
      "limitation": "API real via inject com repositórios substituídos. Não equivale a FastAPI/Pydantic em Python."
    },
    {
      "id": "E09",
      "name": "Zod e validação de contratos",
      "status": "comprovada no recorte local",
      "sourceSha256": "4f0d83ab73a091e8bea8ae3e71e2b5a51483d7b089b8598c0c61aa252cbba10e",
      "limitation": "Validação TS; habilidade conceitual transferível a Pydantic, sem uso dessa biblioteca."
    },
    {
      "id": "E19",
      "name": "Analytics, contratos e qualidade de métricas",
      "status": "comprovada no recorte local",
      "sourceSha256": "28cca68a08f5c9c214acd0586fc6a0a83919409a95f9983de53d416429abac10",
      "limitation": "9 testes focais com privacidade e disponibilidade; sem dados externos reais ou ganho de negócio medido."
    },
    {
      "id": "E20",
      "name": "Coleta, consentimento e IP minimizado",
      "status": "comprovada no recorte local",
      "sourceSha256": "df251b31506846fb1349f65c5fa587aad3911e32d7dd11ac6cc6cb9b1c694bfa",
      "limitation": "3 testes locais; sem commit Git no diretório, usar hash de arquivo."
    },
    {
      "id": "E21",
      "name": "React e aplicação web CRM",
      "status": "parcialmente comprovada — implementação sem validação integrada",
      "sourceSha256": "3d2e1f15a4a06356a9b54efb64fe3b412ebea10ef8bd0bc58fe94601084c4498",
      "limitation": "Imports referenciados em bibliotecas.csv; não foi executado E2E comercial nesta auditoria."
    },
    {
      "id": "E23",
      "name": "SQL/PostgreSQL e migrations",
      "status": "parcialmente comprovada — implementação sem validação integrada",
      "sourceSha256": "ab90782073dabafe1d3f8cdd87c74e8074a1587ae3ff1a1a4f69a1b4a8a0016e",
      "limitation": "75 arquivos SQL tracked no CRM; quantidade não prova SQL avançado nem desempenho."
    }
  ]
}