{"openapi":"3.1.0","info":{"title":"Aurora Liderança Contabilidade — interface programática pública","version":"2.0.0","summary":"Leitura pública do acervo editorial publicado e exame de saúde da instância.","description":"Superfície pública do apex (AURORA-ADR-005 S4). Anônima, somente leitura e sem cookie (RI-14): nenhuma rota declarada aqui lê sessão. Toda leitura sai da projeção única de acervo publicado (RI-01) — peça não publicada é indistinguível de peça inexistente.\n2.0.0 — mudança incompatível em `/api/v1/blog` (AURORA-SPEC-013 D-06): o filtro e o endereço por disciplina saem; entram `categoria` (público) e `servico` (tag), sem período de transição.","license":{"name":"MIT"}},"servers":[{"url":"/","description":"A própria instância. Toda superfície é alcançável por caminho (RI-15)."}],"tags":[{"name":"acervo","description":"Leitura pública do acervo editorial publicado."},{"name":"plataforma","description":"Exame de saúde da instância — contrato da plataforma, sem versão."},{"name":"medicao","description":"Configuração pública de medição de audiência, lida só depois do aceite de cookies."},{"name":"contatos","description":"Pedido de atendimento enviado pelo formulário do site (rodada E)."},{"name":"blog","description":"O blog exatamente como o site mostra (AURORA-ADR-012)."},{"name":"contrato","description":"Este contrato, servido pela própria aplicação."},{"name":"mcp","description":"Servidor MCP no mesmo processo (AURORA-ADR-012)."}],"paths":{"/api/health":{"get":{"tags":["plataforma"],"operationId":"exame_de_saude","summary":"Estado da instância e dos seis serviços canônicos.","description":"Contrato C-2 de AURORA-SPEC-002. Serviço ausente responde `not_configured` e NÃO degrada o agregado: instância sem variável nenhuma está íntegra, porque declarou honestamente o que não tem. Apenas `status: down` responde 503.","responses":{"200":{"description":"Instância íntegra (`ok`) ou degradada (`degraded`).","headers":{"Cache-Control":{"description":"Sempre `no-store` — estado de saúde não se guarda.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Saude"}}}},"503":{"description":"Instância indisponível (`down`) ou em drenagem.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Saude"}}}}}}},"/api/v1/acervo":{"get":{"tags":["acervo"],"operationId":"buscar_acervo","summary":"Lista as peças publicadas do acervo editorial.","description":"Ordenada da mais recente para a mais antiga, com desempate por identificador para que a paginação seja estável. O total é o da projeção filtrada, apurado na mesma consulta da página.","parameters":[{"name":"limite","in":"query","required":false,"description":"Quantidade de peças por página.","schema":{"type":"integer","minimum":1,"maximum":50,"default":20}},{"name":"deslocamento","in":"query","required":false,"description":"Quantas peças pular antes de começar a página.","schema":{"type":"integer","minimum":0,"default":0}},{"name":"tipo","in":"query","required":false,"description":"Filtra por tipo de ativo. O conjunto de valores é configuração da instância, não estrutura — por isso é texto, e não enumeração fechada (AURORA-SPEC-004 D-01).","schema":{"type":"string","maxLength":120}}],"responses":{"200":{"description":"Página do acervo. Lista vazia é resposta válida, não erro.","headers":{"Cache-Control":{"description":"`public, max-age=60`.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginaDoAcervo"}}}},"400":{"$ref":"#/components/responses/EntradaInvalida"},"429":{"$ref":"#/components/responses/LimiteDeRequisicoes"},"500":{"$ref":"#/components/responses/ErroInterno"},"503":{"$ref":"#/components/responses/ServicoIndisponivel"}}}},"/api/v1/acervo/{identificador}":{"get":{"tags":["acervo"],"operationId":"obter_peca","summary":"Devolve uma peça publicada do acervo.","description":"Peça EXISTENTE e não publicada responde exatamente como identificador inexistente — mesmo estado, mesmo corpo, mesmos cabeçalhos (AURORA-SPEC-007 B-13). Distinguir os dois casos vazaria a existência do rascunho.","parameters":[{"name":"identificador","in":"path","required":true,"description":"Identificador da peça, no formato UUID.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"A peça publicada.","headers":{"Cache-Control":{"description":"`public, max-age=60`.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PecaDoAcervo"}}}},"400":{"$ref":"#/components/responses/EntradaInvalida"},"404":{"description":"Não existe peça publicada com este identificador.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"},"examples":{"recurso_inexistente":{"value":{"erro":"recurso_inexistente","mensagem":"Não existe peça publicada com este identificador."}}}}}},"429":{"$ref":"#/components/responses/LimiteDeRequisicoes"},"500":{"$ref":"#/components/responses/ErroInterno"},"503":{"$ref":"#/components/responses/ServicoIndisponivel"}}}},"/api/v1/medicao":{"get":{"tags":["medicao"],"operationId":"configuracao_de_medicao","summary":"ID público do Google Analytics 4, quando configurado.","description":"O navegador só consulta esta rota depois que o visitante aceita \"todos\" no modal de cookies (rodada I). `ga4` é `null` enquanto `GA_MEASUREMENT_ID` não estiver definido. O ID de medição é público por natureza; nada aqui é segredo.","responses":{"200":{"description":"Configuração de medição.","headers":{"Cache-Control":{"description":"`public, max-age=300`.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Medicao"}}}}}}},"/api/v1/contatos":{"post":{"tags":["contatos"],"operationId":"enviar_contato","summary":"Recebe um pedido de atendimento do formulário do site.","description":"Grava o contato na etapa \"aguardando\" do funil do hub. Base legal: procedimentos preliminares a contrato, a pedido do titular (LGPD art. 7º, V); `versaoDoAviso` precisa ser a versão vigente da Política de Privacidade. `site` é um campo-isca: preenchido, a resposta é a mesma e nada é gravado. Limite próprio de 5 envios a cada 10 minutos por IP. A resposta não devolve identificador.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NovoContato"}}}},"responses":{"201":{"description":"Recebido.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["recebido"],"properties":{"recebido":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/EntradaInvalida"},"429":{"$ref":"#/components/responses/LimiteDeRequisicoes"},"500":{"$ref":"#/components/responses/ErroInterno"},"503":{"$ref":"#/components/responses/ServicoIndisponivel"}}}},"/api/v1/openapi.json":{"get":{"tags":["contrato"],"operationId":"ler_contrato","summary":"Este contrato, em JSON (AURORA-SPEC-007 C-03, AURORA-ADR-012).","responses":{"200":{"description":"Documento OpenAPI 3.1 da interface pública.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/blog":{"get":{"tags":["blog"],"operationId":"listar_blog","summary":"Artigos publicados no blog, como o site mostra.","description":"Os artigos redigidos no código somados aos publicados pelo hub (projeção do AURORA-ADR-011), do mais recente ao mais antigo, com assinatura e ressalva. Busca sem acento e sem caixa; filtros por categoria (público), por serviço (tag) e por quem assina. É leitura de apresentação; `GET /api/v1/acervo` continua sendo a leitura de integração (versão e impressão digital).","parameters":[{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":120}},{"name":"categoria","in":"query","required":false,"description":"Grupo de público do catálogo.","schema":{"type":"string","enum":["empresas","mei","pessoa-fisica","produtor-rural","gestao-e-patrimonio","parceiros"]}},{"name":"servico","in":"query","required":false,"description":"`id` de um serviço do catálogo; filtra os artigos com essa tag. Combina com `categoria` por E lógico.","schema":{"type":"string","enum":["contabilidade-mensal","contabilidade-para-mei","abertura-alteracao-e-baixa","bpo-societario","bpo-financeiro","holdings","irpf","carne-leao","contabilidade-rural","itr-ditr","folha-de-empregada-domestica","notas-fiscais-de-servico","per-dcomp","registro-de-marcas","licitacoes","certificado-digital","parcelamentos-e-regularizacao"]}},{"name":"autor","in":"query","required":false,"description":"Nome de quem assina, exatamente como aparece no artigo.","schema":{"type":"string","maxLength":120}}],"responses":{"200":{"description":"Artigos e total.","content":{"application/json":{"schema":{"type":"object","required":["itens","total"],"properties":{"itens":{"type":"array","items":{"$ref":"#/components/schemas/ArtigoDoBlog"}},"total":{"type":"integer","minimum":0}}}}}},"400":{"$ref":"#/components/responses/EntradaInvalida"},"503":{"$ref":"#/components/responses/ServicoIndisponivel"}}}},"/api/v1/blog/{categoria}/{slug}":{"get":{"tags":["blog"],"operationId":"obter_artigo_do_blog","summary":"Um artigo publicado, pelo endereço que ele tem no site.","description":"Categoria diferente da do artigo responde 404.","parameters":[{"name":"categoria","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9-]+$","maxLength":40}},{"name":"slug","in":"path","required":true,"schema":{"type":"string","pattern":"^[a-z0-9-]+$","maxLength":120}}],"responses":{"200":{"description":"O artigo.","content":{"application/json":{"schema":{"type":"object","required":["peca"],"properties":{"peca":{"$ref":"#/components/schemas/ArtigoDoBlog"}}}}}},"400":{"$ref":"#/components/responses/EntradaInvalida"},"404":{"description":"Não existe artigo publicado neste endereço.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"503":{"$ref":"#/components/responses/ServicoIndisponivel"}}}},"/mcp":{"post":{"tags":["mcp"],"operationId":"mcp","summary":"Servidor MCP (Streamable HTTP, sem estado, resposta em JSON).","description":"Mensagens JSON-RPC 2.0 do Model Context Protocol (`initialize`, `tools/list`, `tools/call`). Sem `Authorization`: só as ferramentas públicas (blog, acervo, medição, saúde, envio de contato). Com `Authorization: Bearer aurora_…` (token pessoal criado no hub): também as ferramentas do hub do papel da pessoa. O cliente envia `Accept: application/json, text/event-stream`.","security":[{},{"tokenPessoal":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Mensagem JSON-RPC 2.0."}}}},"responses":{"200":{"description":"Resposta JSON-RPC 2.0.","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Token inválido, revogado ou de conta desativada.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"429":{"$ref":"#/components/responses/LimiteDeRequisicoes"}}},"get":{"tags":["mcp"],"operationId":"mcp_sem_sessao","summary":"Não há fluxo de eventos nem sessão (sem estado).","responses":{"405":{"description":"Use POST.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}}}},"delete":{"tags":["mcp"],"operationId":"mcp_sem_sessao_para_encerrar","summary":"Não há sessão a encerrar (sem estado).","responses":{"405":{"description":"Use POST.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}}}}}},"components":{"securitySchemes":{"tokenPessoal":{"type":"http","scheme":"bearer","description":"Token pessoal do MCP (`aurora_…`), criado em Minha conta no hub."}},"responses":{"EntradaInvalida":{"description":"Entrada recusada na borda (C-3 de AURORA-SPEC-002). O corpo carrega campo e motivo; nunca o valor recebido, nunca rastro de pilha.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"},"examples":{"entrada_invalida":{"value":{"erro":"entrada_invalida","detalhes":[{"campo":"identificador","motivo":"formato inválido — esperado uuid"}],"mensagem":"A requisição não satisfaz o contrato desta rota."}}}}}},"LimiteDeRequisicoes":{"description":"Limite de taxa do prefixo `/api` excedido. É um mecanismo só, montado em `server/http/aplicacao.ts`; nenhuma rota tem contenção própria.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"ErroInterno":{"description":"Falha não prevista. O corpo carrega APENAS o identificador de correlação — a mensagem e a pilha vão para o registro estruturado, onde quem opera as lê, e não para onde qualquer visitante as leria.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"}}}},"ServicoIndisponivel":{"description":"A leitura depende de banco de dados. Os dois códigos são deliberadamente distintos porque a ação de quem opera é oposta: `capacidade_nao_configurada` resolve-se definindo uma variável de ambiente; `servico_indisponivel` resolve-se investigando um serviço que deveria estar no ar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Erro"},"examples":{"capacidade_nao_configurada":{"value":{"erro":"capacidade_nao_configurada","capacidade":"banco_de_dados","mensagem":"Esta ação depende de banco de dados, que não está provisionado nesta instância."}},"servico_indisponivel":{"value":{"erro":"servico_indisponivel","servico":"db","mensagem":"Esta leitura depende de banco de dados, que está indisponível nesta instância."}}}}}}},"schemas":{"NovoContato":{"type":"object","additionalProperties":false,"required":["nome","email","whatsapp","mensagem","versaoDoAviso"],"properties":{"nome":{"type":"string","minLength":2,"maxLength":120},"email":{"type":"string","format":"email","maxLength":254},"whatsapp":{"type":"string","maxLength":30,"description":"Telefone com DDD; o servidor guarda só os dígitos (10 a 13)."},"empresa":{"type":"string","maxLength":120},"mensagem":{"type":"string","minLength":10,"maxLength":2000},"origem":{"type":"string","maxLength":200,"pattern":"^/[^\\s?#]*$","description":"Caminho da página de onde o formulário foi enviado."},"versaoDoAviso":{"type":"string","description":"Versão vigente da Política de Privacidade (`VERSAO_DA_POLITICA` em `shared/legal.ts`)."},"site":{"type":"string","maxLength":200,"description":"Campo-isca. Deve chegar vazio ou ausente."}}},"Medicao":{"type":"object","additionalProperties":false,"required":["ga4"],"properties":{"ga4":{"type":["string","null"],"pattern":"^G-[A-Z0-9]{4,20}$","description":"ID de medição do GA4 (ex. `G-ABC123XYZ`), ou `null`."}}},"ArtigoDoBlog":{"type":"object","description":"`PecaPublicada` de `client/src/content/peca.ts`.","required":["id","categoria","tags","slug","titulo","subtitulo","perguntaRespondida","respostaDireta","corpo","termosRelacionados","publicadaEm","signatario","ressalvaConsultiva"],"properties":{"id":{"type":"string"},"categoria":{"type":"string","enum":["empresas","mei","pessoa-fisica","produtor-rural","gestao-e-patrimonio","parceiros"]},"tags":{"type":"array","items":{"type":"string","enum":["contabilidade-mensal","contabilidade-para-mei","abertura-alteracao-e-baixa","bpo-societario","bpo-financeiro","holdings","irpf","carne-leao","contabilidade-rural","itr-ditr","folha-de-empregada-domestica","notas-fiscais-de-servico","per-dcomp","registro-de-marcas","licitacoes","certificado-digital","parcelamentos-e-regularizacao"]}},"slug":{"type":"string"},"titulo":{"type":"string"},"subtitulo":{"type":"string"},"perguntaRespondida":{"type":"string"},"respostaDireta":{"type":"string"},"corpo":{"type":"array","items":{"type":"object","required":["tipo","titulo"],"properties":{"tipo":{"type":"string","enum":["texto","lista","tabela"]},"titulo":{"type":"string"},"paragrafos":{"type":"array","items":{"type":"string"}},"itens":{"type":"array","items":{"type":"string"}},"colunas":{"type":"array","items":{"type":"string"}},"linhas":{"type":"array","items":{"type":"array","items":{"type":"string"}}}}}},"termosRelacionados":{"type":"array","items":{"type":"string"}},"publicadaEm":{"type":"string","format":"date"},"signatario":{"type":"object","required":["nome","cargo","credencial","caminhoDeVerificacaoDaCredencial"],"properties":{"nome":{"type":"string"},"cargo":{"type":"string"},"credencial":{"type":"string"},"caminhoDeVerificacaoDaCredencial":{"type":"string"}}},"ressalvaConsultiva":{"type":"string"},"emDestaque":{"type":"boolean"}}},"EstadoDeServico":{"type":"string","description":"Doutrina de três estados (AURORA-ADR-003 §7.1). `not_configured` é estado declarado, não falha: significa que a instância não tem aquele serviço provisionado e sabe disso.","enum":["ok","down","not_configured"]},"Saude":{"type":"object","description":"Corpo do exame de saúde. Estados apenas — zero valor de ambiente (RI-12).","required":["status","app","db","redis","integrations","superficies","version","environment","uptime"],"additionalProperties":false,"properties":{"status":{"type":"string","enum":["ok","degraded","down"]},"app":{"type":"string","enum":["ok","down"]},"db":{"$ref":"#/components/schemas/EstadoDeServico"},"redis":{"$ref":"#/components/schemas/EstadoDeServico"},"integrations":{"type":"object","required":["storage","vector","rag","llm"],"additionalProperties":false,"properties":{"storage":{"$ref":"#/components/schemas/EstadoDeServico"},"vector":{"$ref":"#/components/schemas/EstadoDeServico"},"rag":{"$ref":"#/components/schemas/EstadoDeServico"},"llm":{"$ref":"#/components/schemas/EstadoDeServico"}}},"superficies":{"type":"object","description":"Estado de cada superfície declarada (AURORA-SPEC-002-v2 C-2-v2). `com_falha` degrada o agregado; `nao_configurada` fica fora dele. Nunca nome de host. `links` e `docs` são servidas em `/links` e `/docs` (subdomínio opcional por `URL_LINKS` e `URL_DOCS`); o MCP é servido pelo caminho `/mcp` (AURORA-ADR-012). Servida só por caminho é `nao_configurada`.","required":["apex","links","docs","app","mcp"],"additionalProperties":false,"properties":{"apex":{"$ref":"#/components/schemas/EstadoDeSuperficie"},"links":{"$ref":"#/components/schemas/EstadoDeSuperficie"},"docs":{"$ref":"#/components/schemas/EstadoDeSuperficie"},"app":{"$ref":"#/components/schemas/EstadoDeSuperficie"},"mcp":{"$ref":"#/components/schemas/EstadoDeSuperficie"}}},"version":{"type":"string"},"environment":{"type":"string"},"uptime":{"type":"integer","description":"Segundos desde a subida do processo."}}},"EstadoDeSuperficie":{"type":"string","enum":["ok","nao_configurada","com_falha"]},"PecaDoAcervo":{"type":"object","description":"Uma peça publicada, como o público a vê. Os campos derivam das tabelas `ativo` e `versao` de AURORA-SPEC-004 — não há segunda declaração.","required":["id","tipo","atualizadoEm","versao","conteudo"],"additionalProperties":false,"properties":{"id":{"type":"string","format":"uuid"},"tipo":{"type":"string","description":"Tipo de ativo, vocabulário configurável da instância."},"atualizadoEm":{"type":"string","format":"date-time"},"versao":{"type":"object","required":["numero","publicadaEm","impressaoDigital"],"additionalProperties":false,"properties":{"numero":{"type":"integer"},"publicadaEm":{"type":"string","format":"date-time"},"impressaoDigital":{"type":"string","description":"Resumo criptográfico do conteúdo daquela versão. É o que permite a um terceiro afirmar que leu exatamente o que foi publicado."}}},"conteudo":{"type":"object","description":"Conteúdo editorial da versão vigente, como gravado. A forma interna é do conteúdo, não do transporte, e por isso é aberta aqui.","additionalProperties":true}}},"PaginaDoAcervo":{"type":"object","required":["itens","pagina"],"additionalProperties":false,"properties":{"itens":{"type":"array","items":{"$ref":"#/components/schemas/PecaDoAcervo"}},"pagina":{"type":"object","required":["limite","deslocamento","total"],"additionalProperties":false,"properties":{"limite":{"type":"integer"},"deslocamento":{"type":"integer"},"total":{"type":"integer","description":"Total de peças na projeção filtrada, não apenas nesta página."}}}}},"Erro":{"type":"object","description":"Envelope único de erro (C-3 de AURORA-SPEC-002). `erro` é sempre um código em minúsculas com separador de sublinhado — erro nomeado é erro verificável.","required":["erro"],"properties":{"erro":{"type":"string","enum":["entrada_invalida","recurso_inexistente","nao_encontrado","limite_de_requisicoes","capacidade_nao_configurada","servico_indisponivel","encerrando","erro_interno"]},"capacidade":{"type":"string","description":"O que falta provisionar. Presente em `capacidade_nao_configurada`."},"servico":{"type":"string","description":"O que investigar. Presente em `servico_indisponivel`."},"correlacao":{"type":"string","description":"Identificador para o suporte. Presente em `erro_interno`."},"detalhes":{"type":"array","description":"Campo e motivo. Presente em `entrada_invalida`.","items":{"type":"object","required":["campo","motivo"],"additionalProperties":false,"properties":{"campo":{"type":"string"},"motivo":{"type":"string"}}}},"mensagem":{"type":"string"}}}}}}