Projeto RelataTEAStack Laravel · LivewireVersão 1.0
Landing Factory ↗
CL Soluções · PRD · Arquitetura · Regras de negócio

RelataTEA

SaaS para profissionais de TEA (fono, psicólogo, ABA, T.O.): relatórios clínicos cruzando seletores visuais com uma conversa guiada por IA, e resumo em áudio na voz clonada do próprio profissional.

PRDSRSArquiteturaRegras de negócio
01

Visão geral

SaaS para profissionais de TEA (Fonoaudiólogos, Psicólogos, Analistas do Comportamento/ABA, T.O.) gerarem relatórios clínicos cruzando seletores visuais com uma conversa guiada por IA, e entregarem aos pais um resumo em áudio com a voz clonada do próprio profissional.

Índice

Doc Conteúdo
01-PLANO-EXECUCAO.md Roadmap completo em fases (sistema completo, não MVP). É por aqui que executamos "aos poucos".
02-ARQUITETURA.md Stack, infraestrutura Hostinger, filas, storage, segurança.
03-MODELO-DADOS.md Schema do banco (MariaDB), tabelas e migrations.
04-IA-E-PROMPTS.md Groq (LLM + Whisper), Hugging Face XTTS, system prompts, regra de tempo do áudio.
05-DESIGN-SYSTEM.md Tokens visuais, tipografia, regras anti-overflow. Vira o theme do Tailwind.
06-PLANO-RETOMADA.md Ordem de retomada: voz → go-live → billing.
07-PRONTUARIO-E-SESSOES.md Prontuário por paciente, sessões (chat datado), anexos (foto/áudio). Modelo de dados.
08-PROTOCOLOS-AVALIACAO.md Framework "executar protocolo X", catálogo conhecido (só metadados), registro de resultados.
09-MODELOS-RELATORIO-E-AUDIO.md Tipos de documento e de áudio configuráveis; modelos por profissional; guardrail de tom.
10-CBO-E-CONSELHOS.md Mapa especialidade → CBO → conselho; derivado, não digitado.
11-PROCESSO-CLINICO.md O processo clínico completo (anamnese → devolutiva) na voz de uma psicopedagoga.
12-LGPD-MIDIA.md Tratamento de fotos/áudios de crianças: disco privado, EXIF, acesso autorizado.
13-PLANO-EXPANSAO.md Plano faseado da expansão (Fases 14→21): prontuário, sessões, protocolos, modelos, base de conhecimento.
14-BASE-DE-CONHECIMENTO-E-MODELOS-IA.md "Cérebro" da IA: contexto em camadas, memória por prontuário, modelos/personas configuráveis e reversíveis, correções que viram conhecimento.
HANDOFF.md Estado atual, decisões tomadas, perguntas em aberto, próximo passo. Leia primeiro ao retomar.

Convenções do projeto

  • Stack idêntica ao CRM existente (crm.clsolucoes.com): Laravel 13, Livewire 4, Tailwind 4, Vite 8, PHP 8.3, MariaDB 10.11.
  • Idioma de UI e conteúdo: pt-BR.
  • A pasta design/ contém protótipos HTML standalone (fonte da verdade visual) que portamos para Blade/Livewire.
  • Princípio de produto: baixa carga sensorial e alta legibilidade — é uma ferramenta de uso clínico diário.

Como abrir o protótipo da interface

cd public_html/design && php -S 127.0.0.1:8899
# abrir http://127.0.0.1:8899/relatorio-builder.html
02

Plano de execução

Cada fase é entregável e testável de forma independente. Executamos aos poucos, na ordem. Marque [x] ao concluir. As fases 0→6 já entregam o fluxo "relatório por chat"; 7→9 entregam o áudio com voz clonada; 10→13 completam o produto.


Fase 0 — Fundação & DevOps ✅

  • composer create-project laravel/laravel em public_html/ (Laravel 13.16, espelha o CRM).
  • Instalar Livewire 4, Tailwind 4 (@tailwindcss/vite), @tailwindcss/typography.
  • .env: conexão MariaDB (banco+usuário relatafacil criados), APP_* pt-BR, chaves GROQ_API_KEY, HF_TOKEN, HF_XTTS_SPACE_URL (placeholders).
  • Fila/sessão/cache com driver database. (worker Supervisor a configurar no deploy)
  • Discos de storage voices/audios + storage:link — fazer na Fase 9.
  • FFmpeg: ausente; Groq Whisper aceita formatos direto → instalar só se necessário (Fase 5).
  • Saída: ✅ app sobe, migrate roda em MariaDB, assets buildam.

Fase 1 — Identidade, multi-tenant & LGPD ✅ (revisada)

  • Autenticação de profissionais (guard profissional, model Profissional com senha_hash), login com rate-limit, logout.
  • Perfil editável: nome, e-mail, registro de conselho, especialidade, troca de senha.
  • Landing page pública (/) com planos. Sem auto-cadastro — conta vem da assinatura (decisão 18/06). Registro removido.
  • Conta demo provisionada via DemoSeeder ([email protected] / RelataDemo2026).
  • Billing/checkout real (Stripe/Mercado Pago?) — fase futura. Hoje "Assinar" abre e-mail.
  • Capturar consentimento LGPD no onboarding (não há mais registro). TODO.
  • Saída: ✅ landing + login demo validados no domínio.

Fase 2 — Pacientes & histórico ✅

  • CRUD de pacientes (Livewire Pacientes) com geração automática de codigo_anonimo (PAC-XXXX), busca, modal de form, exclusão com confirmação. Tudo escopado ao profissional logado.
  • Página de detalhe (PacienteDetalhe) com cabeçalho (idade, nível, CID, responsável) e timeline de evolução (vazia até a Fase 6). Autorização via abort_unless (404 se não for dono).
  • Nav "Pacientes" no topbar; contador real no painel.
  • Saída: ✅ validado no navegador (cadastro → card com PAC-B0IU → detalhe).

Fase 3 — Design system & shell ✅

  • Tokens em app.css (cores petro/clay/sage/paper) + fontes Fraunces/Hanken via <x-fonts>.
  • layouts.app (topbar extraído p/ x-app.topbar) e layouts.studio (viewport fixo, 3 zonas, anti-overflow).
  • Saída: ✅ shell de 3 zonas idêntico ao protótipo, funcionando no domínio.

Fase 4 — Seletores & motor de coleta (chat) — Livewire ✅

  • ConstrutorRelatorio com seletores reativos (especialidade, tipo, nível, metas, data) — clique persiste.
  • Conversa: stream de mensagens + composer de texto; notas viram texto_terapeuta. (mic/IA = Fases 5-6)
  • Persiste em relatorios_clinicos (seletores_json, mensagens_json, texto_terapeuta), autosave por ação.
  • Painel direito mostra o material capturado (metas + observações) — pré-IA.
  • Timeline do paciente lista os relatórios; botão "Novo relatório" cria rascunho e abre o construtor.
  • Saída: ✅ validado no domínio (criar rascunho → marcar metas → registrar nota → persistido).

Fase 5 — Transcrição de áudio (Whisper via Groq) ✅ (código pronto, aguarda chave)

  • Gravação (MediaRecorder/Alpine) + upload de arquivo no composer; envio via $wire.upload.
  • GroqWhisperService (whisper-large-v3, aceita webm/ogg/mp3/m4a sem FFmpeg); transcrição síncrona com estados de loading.
  • Texto transcrito entra na nota para o terapeuta revisar antes de registrar.
  • Sem chave: microfone desabilitado + aviso amigável (validado).
  • Saída: ⏳ ativa ao colar GROQ_API_KEY.

Fase 6 — Motor de relatório (LLM) ✅ (código pronto, aguarda chave)

  • GroqLlmService + system prompt resources/prompts/relatorio_tecnico.txt.
  • Geração do relatorio_tecnico cruzando seletores + notas + relatório anterior (continuidade). Pseudonimizado (envia codigo_anonimo, nunca o nome).
  • Botão "Gerar relatório com IA" + regenerar; status gerandopronto; erro tratado (validado sem-chave via tinker).
  • Edição manual do texto gerado + versionamento — refinar depois.
  • Saída: ⏳ ativa ao colar GROQ_API_KEY (transcrição e geração juntas).

Fase 7 — Banco de metas/protocolos ✅

  • Tabela metas_catalogo + model MetaCatalogo + MetasCatalogoSeeder (22 metas: VB-MAPP, ABLLS-R, Vineland) agrupadas por área.
  • Seletor no construtor agora é DB-driven, agrupado por área e filtrado pela especialidade (geral + da especialidade; ex.: metas de ABA ocultas para fono).
  • Toggle persiste em seletores_json (binding @js — seguro com acentos/parênteses). DatabaseSeeder chama metas + demo.
  • Saída: ✅ validado no domínio (filtro por especialidade + persistência).

Fase 8 — Resumo para os pais & roteirização ✅

  • GroqLlmService::gerarResumoPais() + prompt resources/prompts/resumo_pais.txt (acolhedor, sem nome real).
  • Validação rígida de palavras com re-prompt se > 510; cálculo de duração (palavras/150*60).
  • Tabela resumos_pais + model ResumoPais; botão no card de áudio + exibição do roteiro com contagem/duração.
  • Saída: ✅ validado ao vivo — 402-433 palavras, ~2,7-2,9 min, tom acolhedor.

Fase 9 — Clonagem de voz (TTS) 🟡 (código pronto; falta HF + worker)

  • Upload da amostra de voz (+ consentimento biométrico LGPD) em Meu perfil → disco privado voices. Status pendente/ativa/revogada. Validado ao vivo (voz ativa).
  • interface TextToSpeechProvider + HuggingFaceXttsProvider (Gradio), binding trocável via TTS_PROVIDER.
  • GerarAudioResumoJob (fila, timeout 600s): texto + amostra → provider → salva .mp3 no disco audios; failed() trata erro.
  • Card de áudio: botão dispara o job, wire:poll durante gerando_audio, player + download quando concluido. Rota /audios/resumo/{resumo} privada (autorizada).
  • Pendências de ativação: HF_TOKEN + HF_XTTS_SPACE_URL (Space XTTS duplicado) no .env; e ligar o worker da fila (docs/deploy-queue-worker.ini — requer aprovação do usuário, é serviço de sistema).
  • Saída: 🟡 upload de voz funcionando; geração de áudio ativa após HF + worker.

Fase 10 — Exportação & entrega ✅ (PDF/download)

  • PDF via barryvdh/laravel-dompdf (resources/views/pdf/relatorio.blade.php): cabeçalho do profissional, identificação real do paciente (nome/CID/nível), corpo do relatório (converte **negrito**), e linha de assinatura com registro do conselho.
  • Rota autorizada /relatorios/{relatorio}/pdf → download; nome do arquivo usa codigo_anonimo (não vaza nome). Botão "⤓ PDF" no construtor. Validado ao vivo (download OK).
  • Entrega via link/WhatsApp/e-mail — futuro (por ora: download, profissional envia no zap).
  • Saída: ✅ relatório em PDF baixável.

Fase 11 — Evolução comparativa & dashboards ✅

  • Painel com métricas reais (pacientes, relatórios, resumos) + lista de relatórios recentes (substituiu o roadmap estático que estava na tela).
  • Detalhe do paciente: card "Metas mais trabalhadas" (barras de frequência das metas ao longo das sessões) + nº de sessões.
  • Comparação narrada entre sessões (a IA já recebe o relatório anterior na geração) — refinar com gráfico temporal depois.
  • Saída: ✅ validado no domínio (painel real + evolução de metas).

Fase 12 — Diferenciais (sugestões de produto) ✅ (núcleo)

  • Gerador de justificativa para convênio — via tipo de documento justificativa; prompt reforçado p/ indicar carga horária semanal + riscos + ganhos. Validado (output cita horas).
  • Gerador de PEI/PDI — via tipo pei; objetivos mensuráveis com critério de domínio. Validado.
  • Modo escolar / mediador — via tipo escolar.
  • Biblioteca de modelos por profissional — futuro.

Implementado como tipos de documento no construtor (seleciona o tipo → "Gerar relatório"), não como botões separados. Mais limpo e tudo no mesmo fluxo.

Fase 13 — Hardening & lançamento 🟡 (segurança feita; lançamento pende decisões)

  • Testes de isolamento multi-tenant (IsolamentoMultiTenantTest, 8 testes): intruso recebe 404 em paciente/relatório/PDF/áudio de outro; visitante → login; código anônimo gerado. Suite: 10 passando.
  • Rate limit de IA: 60 gerações/hora por profissional (protege cota/custo do Groq).
  • Limpeza de código morto (METAS_VBMAPP removido — virou DB na Fase 7).
  • Billing/checkout real — aguarda decisão do provedor (Stripe/Mercado Pago) e modelo de provisionamento.
  • Consentimento LGPD no onboarding (não há mais registro) — depende do fluxo de provisionamento.
  • APP_ENV=production + APP_DEBUG=false no go-live; retenção/exclusão de dados a pedido (LGPD); voz (Fase 9).
  • Saída: 🟡 seguro para piloto; lançamento comercial pende billing + go-live.

Sugestões extras de produto (backlog)

  • Histórico de evolução comparativo narrado ("na semana passada… e hoje…").
  • Detecção de comorbidades citadas para sugerir encaminhamentos multidisciplinares.
  • Modo offline-first para registrar nota rápida pós-sessão pelo celular.
  • Compartilhamento seguro com a escola (link expira).
  • Lembretes de "relatório vence em 6 meses" (laudos perdem validade prática).
03

Arquitetura

Stack (espelha o CRM crm.clsolucoes.com)

Camada Tecnologia Observação
Runtime PHP 8.3 já disponível na Hostinger
Framework Laravel 13 mesmo do CRM
UI reativa Livewire 4 + Alpine sem build de SPA separada; deploy simples
CSS Tailwind 4 (@tailwindcss/vite) + typography tokens em 05-DESIGN-SYSTEM.md
Build Vite 8 npm run build no deploy
Banco MariaDB 10.11 incluso na Hostinger
Fila Laravel Queue (driver database) obrigatória p/ IA assíncrona
Storage disks voices + audios nunca guardar binário no banco
Áudio FFmpeg normaliza upload (ogg/m4a → wav 16k mono)

Por que NÃO rodar IA no servidor

Hospedagem web não tem GPU; XTTS/Whisper locais travam. Todo processamento pesado é delegado a APIs externas via HTTP (Guzzle):

  • Texto e transcrição → Groq (gratuito, rápido).
  • Clonagem de voz → Hugging Face Space (XTTS v2), atrás de interface trocável.

Fluxo assíncrono (regra de ouro)

Profissional clica "Gerar"  ──>  cria registro status='aguardando'  ──>  retorna HTTP 202
                                          │
                                   Job em fila (background)
                                          │
        ┌─────────────────────────────────┼─────────────────────────────────┐
   gerando_texto (Groq LLM)        gerando_audio (HF XTTS)              concluido / erro
                                          │
                            Frontend faz polling no status

Nunca processar IA dentro da request HTTP (timeout ~30-60s; áudio leva mais).

Camada de providers (anti-lock-in)

TextToSpeechProvider (interface)
 ├─ HuggingFaceXttsProvider   (grátis, validação)
 └─ ReplicateProvider / FishProvider / PlayHtProvider  (pago, produção)   ← troca via .env

LlmProvider (interface)
 ├─ GroqProvider     (grátis)
 └─ OpenAiProvider / AnthropicProvider  (fallback de qualidade)

Binding no AppServiceProvider; trocar provider = mudar 1 linha. Ver 04-IA-E-PROMPTS.md.

Deploy na Hostinger

  • App Laravel completo vive em public_html/ (mesmo padrão do CRM); document root → public_html/public.
  • Worker de fila: se VPS, supervisor/systemd rodando php artisan queue:work. Se plano com cron, queue:work --stop-when-empty via cron a cada minuto (degradação aceitável). Confirmar com o cliente (ver HANDOFF).
  • Assets: npm run build no deploy.

Segurança & LGPD (resumo — detalhe na Fase 13)

  • Dado clínico de criança = sensível de saúde; voz = biométrico. Consentimento explícito + minimização.
  • Pseudonimização: LLM recebe codigo_anonimo, nunca PII.
  • .env fora do controle de versão; chaves de IA só no servidor.
04

Modelo de dados

Princípios: separar PII (identificação) de dado clínico; pseudonimizar para a IA via codigo_anonimo; nunca guardar binário de áudio no banco (só path/URL no storage); status como máquina de estados para o fluxo assíncrono.

Abaixo o SQL de referência. Na implementação viram migrations Laravel (Fase 0/2/6/9).

-- Profissionais (terapeutas)
CREATE TABLE profissionais (
    id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    nome                VARCHAR(160)  NOT NULL,
    email               VARCHAR(190)  NOT NULL UNIQUE,
    senha_hash          VARCHAR(255)  NOT NULL,
    registro_conselho   VARCHAR(60)   NULL,            -- CRP, CRFa, CREFITO...
    especialidade       VARCHAR(120)  NULL,            -- Fono, Psicologia, ABA, T.O.

    voz_referencia_url     VARCHAR(512) NULL,          -- path no disco 'voices'
    voz_consentimento_em   TIMESTAMP    NULL,          -- LGPD: consentimento de clonagem
    voz_status             ENUM('pendente','ativa','revogada') NOT NULL DEFAULT 'pendente',

    consentimento_lgpd_em  TIMESTAMP    NULL,
    ativo               BOOLEAN       NOT NULL DEFAULT TRUE,
    created_at          TIMESTAMP NULL, updated_at TIMESTAMP NULL
);

-- Pacientes (crianças/adolescentes)
CREATE TABLE pacientes (
    id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    profissional_id     BIGINT UNSIGNED NOT NULL,
    nome                VARCHAR(160)  NOT NULL,         -- PII
    data_nascimento     DATE          NULL,
    responsavel_nome    VARCHAR(160)  NULL,
    responsavel_contato VARCHAR(120)  NULL,             -- WhatsApp/e-mail dos pais
    codigo_anonimo      VARCHAR(20)   NOT NULL,         -- "PAC-7F2A" → vai p/ a LLM
    cid                 VARCHAR(20)   NULL,             -- 6A02 (CID-11) / F84 (CID-10)
    nivel_suporte       TINYINT       NULL,             -- 1,2,3 (DSM-5)
    observacoes         TEXT          NULL,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    CONSTRAINT fk_pac_prof FOREIGN KEY (profissional_id) REFERENCES profissionais(id) ON DELETE CASCADE,
    UNIQUE KEY uk_codigo_anonimo (codigo_anonimo),
    INDEX idx_pac_prof (profissional_id)
);

-- Relatórios clínicos (material técnico)
CREATE TABLE relatorios_clinicos (
    id                  BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    paciente_id         BIGINT UNSIGNED NOT NULL,
    profissional_id     BIGINT UNSIGNED NOT NULL,
    data_sessao         DATE          NOT NULL,
    especialidade       VARCHAR(40)   NULL,             -- snapshot do seletor
    tipo_documento      VARCHAR(40)   NOT NULL,         -- evolucao, justificativa, pei, escolar
    seletores_json      JSON          NULL,             -- estado completo dos seletores da tela
    texto_terapeuta     LONGTEXT      NULL,             -- digitado
    audio_origem_url    VARCHAR(512)  NULL,             -- upload do terapeuta
    transcricao         LONGTEXT      NULL,             -- saída do Whisper/Groq
    relatorio_tecnico   LONGTEXT      NULL,             -- texto final gerado pela LLM
    status              ENUM('rascunho','transcrevendo','gerando','pronto','erro') NOT NULL DEFAULT 'rascunho',
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    CONSTRAINT fk_rel_pac  FOREIGN KEY (paciente_id)     REFERENCES pacientes(id)      ON DELETE CASCADE,
    CONSTRAINT fk_rel_prof FOREIGN KEY (profissional_id) REFERENCES profissionais(id) ON DELETE CASCADE,
    INDEX idx_rel_pac_data (paciente_id, data_sessao)
);

-- Resumos para os pais (com histórico de evolução / versionamento)
CREATE TABLE resumos_pais (
    id                   BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    relatorio_id         BIGINT UNSIGNED NOT NULL,
    paciente_id          BIGINT UNSIGNED NOT NULL,      -- desnormalizado p/ timeline rápida
    roteiro_texto        TEXT          NOT NULL,
    contagem_palavras    SMALLINT UNSIGNED NULL,
    duracao_estimada_seg SMALLINT UNSIGNED NULL,        -- palavras/150*60
    audio_final_url      VARCHAR(512)  NULL,            -- path no disco 'audios'
    provider_tts         VARCHAR(40)   NULL,            -- hf_xtts, replicate...
    status               ENUM('aguardando','gerando_texto','gerando_audio','concluido','erro') NOT NULL DEFAULT 'aguardando',
    erro_detalhe         TEXT          NULL,
    versao               SMALLINT UNSIGNED NOT NULL DEFAULT 1,
    enviado_pais_em      TIMESTAMP     NULL,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    CONSTRAINT fk_res_rel FOREIGN KEY (relatorio_id) REFERENCES relatorios_clinicos(id) ON DELETE CASCADE,
    CONSTRAINT fk_res_pac FOREIGN KEY (paciente_id)  REFERENCES pacientes(id)           ON DELETE CASCADE,
    INDEX idx_res_pac_hist (paciente_id, created_at)
);

-- Metas/protocolos (Fase 7) — catálogo selecionável por chip
CREATE TABLE metas_catalogo (
    id          BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    protocolo   VARCHAR(40)  NOT NULL,                  -- VB-MAPP, ABLLS-R, Vineland
    area        VARCHAR(80)  NOT NULL,                  -- Mando, Tato, Imitação...
    descricao   VARCHAR(255) NOT NULL,
    especialidade VARCHAR(40) NULL,
    INDEX idx_meta_prot (protocolo, area)
);

Notas

  • seletores_json guarda o estado da tela (nível, metas marcadas, tipo) — é o que cruzamos com a transcrição no prompt.
  • Versionamento de resumos_pais permite regenerar o áudio sem perder o histórico (campo versao).
  • Para "evolução comparativa" (Fase 11), busca-se o resumos_pais/relatorios_clinicos anterior do mesmo paciente_id.
05

IA — fornecedores & prompts

Mapa de fornecedores

Tarefa Fornecedor Modelo / endpoint Custo
Transcrição (áudio→texto) Groq whisper-large-v3 · POST /openai/v1/audio/transcriptions grátis (rate-limited)
Geração de relatório/resumo Groq llama-3.3-70b-versatile · POST /openai/v1/chat/completions grátis (rate-limited)
Fallback de qualidade OpenAI / Anthropic gpt-4o-mini / claude-haiku-4-5 centavos/uso
Clonagem de voz Hugging Face Space XTTS v2 (Space duplicado) via gradio HTTP grátis (instável)
Voz em produção Replicate / Fish / PlayHT pay-per-use barato

Por que Groq para Whisper (e não HF)

O Groq hospeda Whisper na mesma chave/SDK do LLM, é muito rápido e aceita vários formatos de áudio — elimina um fornecedor e parte da necessidade de FFmpeg.

XTTS v2 — atenção

  • Não existe na Inference API serverless estável → usar um Space duplicado na sua conta HF (botão "Duplicate this space"), para a API não sumir.
  • Spaces grátis: CPU (lento) ou ZeroGPU (precisa HF Pro ~US$9/mês — recomendado para isso).
  • ⚠️ Licença XTTS v2 (Coqui CPML) é não-comercial. Para cobrar pelo SaaS, validar a licença do Space/modelo ou migrar para provider comercial. Pendência jurídica registrada no HANDOFF.
  • O formato exato dos endpoints Gradio varia por Space — isolar tudo em HuggingFaceXttsProvider (ver abaixo) e conferir a aba /?view=api do Space.

Regra de tempo do áudio (matemática, não "tempo")

TTS não entende duração; controla-se pela contagem de palavras. Fala ≈ 150 palavras/min.

  • 3 min ≈ 450 palavras · 5 min ≈ 750 palavras → alvo 400–480 palavras (folga de segurança → ~3-4 min).
  • O backend valida a contagem e re-pede se estourar (não confiar só no prompt).

System Prompt — Resumo em áudio para os pais

resources/prompts/resumo_pais.txt

Você é um assistente especializado em comunicação clínica para famílias de
crianças e adolescentes com Transtorno do Espectro Autista (TEA). Sua função é
transformar um relatório técnico de sessão em um ROTEIRO FALADO que será
convertido em áudio (com a voz do próprio terapeuta) e enviado aos pais.

== RESTRIÇÃO DE TAMANHO (INVIOLÁVEL) ==
No máximo 480 palavras, no mínimo 400. Isso garante áudio de 3 a 5 minutos
(~150 palavras/min). Conte as palavras antes de finalizar. Se exceder, corte
conteúdo secundário, nunca o acolhimento. Não escreva nada além do roteiro.

== FORMATO ==
- Texto corrido em pt-BR, pronto para ser LIDO EM VOZ ALTA.
- SEM marcadores, títulos, asteriscos, emojis, parênteses ou listas.
- Frases curtas, pausas naturais (vírgulas/pontos). Números por extenso.
- Comece de forma calorosa e natural (não "Olá pais" genérico).

== TOM E CONTEÚDO (não anuncie as seções) ==
1. Acolhimento e como foi o encontro de hoje, em poucas palavras.
2. Um a três avanços concretos e positivos da sessão.
3. Um ponto de atenção, enquadrado com gentileza, como oportunidade.
4. Uma orientação prática e simples para a família aplicar em casa.
5. Encerramento de parceria e incentivo.
- Empático e honesto: nunca prometa cura, nunca alarme, nunca minimize.
- Traduza jargão (ex.: "estereotipias" → "movimentos repetitivos que ajudam
  a criança a se autorregular").

== PRIVACIDADE ==
- Use o primeiro nome da criança só se fornecido; senão "seu filho"/"sua filha".
- Nunca invente dados, diagnósticos ou resultados ausentes no relatório.

== ENTRADA ==
Você receberá o relatório técnico e, se houver, o resumo da sessão anterior
para dar continuidade ("na semana passada... e hoje...").

Gere agora apenas o roteiro falado, respeitando o limite de 480 palavras.

System Prompt — Relatório técnico (esqueleto, Fase 6)

Um template por especialidade × tipo de documento, todos com este núcleo:

Você é um(a) [ESPECIALIDADE] redigindo um [TIPO_DOCUMENTO] para uma criança com
TEA, seguindo os padrões dos conselhos federais e exigências de planos de saúde.
Receberá: (a) seletores estruturados (nível de suporte, metas trabalhadas,
período), (b) notas/transcrição da sessão, (c) resumo da sessão anterior.

Regras:
- Refira-se à criança como "o paciente" ou pelo código fornecido. NUNCA invente.
- Cite metodologia/protocolo quando informado (ex.: VB-MAPP).
- Descreva frequência, duração e contexto dos comportamentos observados.
- Para justificativa de horas: fundamente tecnicamente a intensidade pedida.
- Estruture nas seções técnicas da especialidade. Linguagem clínica, sem floreio.
- Marque lacunas como "não avaliado nesta sessão" em vez de preencher com suposição.

Integração — Laravel (referência para Fases 5, 6, 8, 9)

Config (config/services.php)

'groq' => ['key' => env('GROQ_API_KEY')],
'hf'   => ['token' => env('HF_TOKEN'), 'xtts_space_url' => env('HF_XTTS_SPACE_URL')],

Transcrição (Groq Whisper)

$resp = Http::withToken(config('services.groq.key'))
    ->attach('file', file_get_contents($path), 'audio.wav')
    ->post('https://api.groq.com/openai/v1/audio/transcriptions', [
        'model' => 'whisper-large-v3', 'language' => 'pt',
    ]);
$texto = $resp->json('text');

LLM com validação de palavras (resumo)

class GroqResumoService {
    public function gerarRoteiro(string $relatorio, ?string $anterior = null): array {
        $system = file_get_contents(resource_path('prompts/resumo_pais.txt'));
        $user = "RELATÓRIO TÉCNICO:\n{$relatorio}"
              . ($anterior ? "\n\nSESSÃO ANTERIOR:\n{$anterior}" : '');
        $texto = $this->chat($system, $user);
        $n = str_word_count(strip_tags($texto));
        if ($n > 510) {                                   // re-prompt se estourar
            $texto = $this->chat($system, $user."\n\nA versão teve {$n} palavras. "
                                  ."Reescreva com NO MÁXIMO 480, cortando o secundário.");
            $n = str_word_count(strip_tags($texto));
        }
        return ['texto'=>trim($texto), 'palavras'=>$n, 'duracao_seg'=>(int)round($n/150*60)];
    }
    private function chat(string $sys, string $usr): string {
        return Http::withToken(config('services.groq.key'))->timeout(60)
            ->post('https://api.groq.com/openai/v1/chat/completions', [
                'model'=>'llama-3.3-70b-versatile','temperature'=>0.6,'max_tokens'=>1200,
                'messages'=>[['role'=>'system','content'=>$sys],['role'=>'user','content'=>$usr]],
            ])->throw()->json('choices.0.message.content','');
    }
}

Provider de voz (interface trocável)

interface TextToSpeechProvider {
    /** @return string binário do áudio (mp3/wav) */
    public function clonarFala(string $texto, string $vozReferenciaPath): string;
}

HuggingFaceXttsProvider implementa via HTTP do Gradio (upload da amostra → /call/predict → polling do event_id → download do áudio). Binding no AppServiceProvider; trocar provider = 1 linha.

Job assíncrono

GerarResumoAudioJob (timeout 600s, tries 2): gerando_textoGroqResumoServicegerando_audioTextToSpeechProvider->clonarFala() → salva .mp3 no disco audiosstatus='concluido'. failed() grava erro_detalhe. Controller despacha o job e retorna HTTP 202 + poll_url.

06

Design system

Fonte da verdade visual: design/relatorio-builder.html. Estes tokens viram o theme do Tailwind 4 na Fase 3.

Princípios

  1. Baixa carga sensorial — é uma ferramenta de uso clínico diário, no contexto de neurodiversidade. Sem cores estridentes, sem clichê de quebra-cabeça/arco-íris, sem gradiente roxo.
  2. Alta legibilidade — serif quente (Fraunces) para conteúdo humano (relatório/resumo); sans humanista (Hanken Grotesk) para a UI.
  3. Nunca transbordar — toda zona tem scroll próprio; texto sempre quebra; chips fazem wrap. Ver regras abaixo.

Tipografia

  • Display/conteúdo: Fraunces (serif variável, calorosa) — títulos, texto do relatório, números de nível.
  • UI/corpo: Hanken Grotesk — navegação, seletores, labels, chat.
  • Carregar via Google Fonts (mesmo padrão <x-fonts> do CRM).

Cores (CSS vars → Tailwind theme)

Token Hex Uso
paper #FBF8F2 fundo do app (papel quente)
paper-deep #F4EEE3 fundos sutis
surface #FFFFFF cards, painéis
ink #2B3138 texto principal (slate, não preto puro)
ink-soft #5D6772 texto secundário
ink-faint #97A0A8 labels, dicas
line #ECE5D8 hairlines quentes
teal / teal-deep / teal-tint #176E69 / #0E514D / #E4F0EE primária — confiança clínica, seleção
clay / clay-deep / clay-tint #C16B45 / #A4552F / #F8E9DF acento humano — áudio p/ pais, nível, voz
sage / sage-tint #5E8C63 / #E7F0E5 positivo — metas alcançadas, evolução
amber-tint / amber-ink #FBEFD6 / #8A6320 atenção/avisos

Raios: 8/12/18/24px. Sombras suaves (ver --shadow-sm/md/lg no protótipo). Animação de entrada: rise escalonado por zona (sutil).

Regras anti-overflow (requisito explícito do cliente)

  • body{overflow:hidden} — o app gerencia scroll, não a página.
  • Layout em flex/grid com min-width:0 e min-height:0 nos filhos flex (senão o conteúdo "empurra" e estoura).
  • Cada zona scrollável usa a classe .scroll (overflow-y:auto + scrollbar fina).
  • Texto longo: overflow-wrap:anywhere; nomes/títulos de uma linha: text-overflow:ellipsis + white-space:nowrap.
  • Chips e seletores: flex-wrap:wrap; nada com largura fixa que corte rótulo.
  • Larguras das colunas com flex-basis + breakpoint em 1180px (encolhe painéis, preserva a conversa).

Mapa de componentes → Blade/Livewire (Fase 3-4)

Protótipo Componente alvo
topbar + shell x-layouts.app
coluna seletores livewire: report-selectors
conversa + composer livewire: report-chat
coluna relatório livewire: report-preview
card de áudio livewire: parent-audio-card
status bar partial x-app.statusbar
07

Plano de retomada

Continuação do 01-PLANO-EXECUCAO.md (Fases 0-13 ✅, exceto voz e lançamento). Ordem definida com o cliente em 19/06/2026: 1) Voz → 2) Go-live → 3) Billing. Legenda: [CLIENTE] = depende de insumo/decisão do cliente · [DEV] = trabalho de código/infra · [ROOT] = exige aprovação (serviço de sistema).


FRENTE 1 — Voz clonada (Fase 9) 🟡 → ✅ (prioridade atual)

Código completo (HuggingFaceXttsProvider, GerarAudioResumoJob, upload+consentimento, player+download). Falta ativar a infra e calibrar o provider à API real do Space. Pipeline já é assíncrono e a camada é trocável (TTS_PROVIDER).

1.1 — Worker da fila (pré-requisito de TODA geração de áudio) [ROOT]

  • Copiar docs/deploy-queue-worker.ini/etc/supervisord.d/relatatea-worker.ini.
  • supervisorctl reread && supervisorctl update && supervisorctl start relatatea-worker:* (precedente: pulse-worker.ini já roda na VPS).
  • Validar: dispatch de um job de teste e conferir consumo em storage/logs/queue-worker.log.
  • Plano B sem aprovação: cron * * * * * php artisan queue:work database --stop-when-empty --max-time=55 (linha pronta no .ini).
  • Saída: worker persistente consumindo a fila database.

1.2 — Decisão de provider de voz [CLIENTE]

Ponto de decisão (interface já trocável, então é 1 classe nova se mudar):

  • Opção A — XTTS v2 via HF Space (grátis): valida o pipeline ponta-a-ponta hoje, custo zero. ⚠️ Space grátis é instável (cold start/fila) e licença XTTS/Coqui CPML é não-comercial → não pode cobrar com ela.
  • Opção B — provider pago (recomendado p/ produção): Fish Audio / PlayHT / ElevenLabs. Estável, licença comercial limpa. Implica nova classe …Provider + TTS_PROVIDER.
  • Recomendação: validar agora com A (prova o fluxo, barato), migrar para B antes do lançamento comercial.

1.3a — Caminho A: ativar XTTS Space

  • [CLIENTE] Gerar HF_TOKEN (já está no .env) e duplicar um Space XTTS v2 na conta HF; pôr HF_XTTS_SPACE_URL no .env (hoje vazio).
  • [CLIENTE+DEV] Abrir …/?view=api do Space e conferir endpoints/ordem do data (/upload, /call/predict, índice da função). A API Gradio varia por Space — é o ponto frágil.
  • [DEV] Calibrar HuggingFaceXttsProvider (ordem de $data, event_id, parse do SSE) ao Space real — iteração ao vivo.

1.3b — Caminho B: provider pago (quando decidido)

  • [DEV] Criar app/Services/Tts/{Fish|PlayHt|ElevenLabs}Provider.php implementando TextToSpeechProvider (configurado/clonarFala/nome).
  • [DEV] Registrar binding por TTS_PROVIDER no service provider; chaves no .env.
  • [CLIENTE] Conta + créditos no provider.

1.4 — Validação ponta-a-ponta [DEV]

  • Profissional com voz ativa (upload + consentimento já existe em "Meu perfil").
  • Gerar resumo p/ pais → botão "Gerar áudio" → job na fila → polling vira concluido → player toca + download funciona.
  • Erro/cold-start: tries=2+backoff já no job; conferir mensagem amigável no player quando status=erro.
  • Saída: ✅ áudio com voz clonada entregue ponta-a-ponta.

FRENTE 2 — Go-live (produção) 🟡

App é multi-tenant testado; falta endurecer para produção real.

2.1 — Configuração de produção [DEV+ROOT]

  • .env: APP_ENV=production, APP_DEBUG=false, APP_URL=https://relatatea.clsolucoes.com.
  • php artisan config:cache route:cache view:cache (cache de produção).
  • npm run build (assets) + conferir vhost.conf (docRoot public_html/public, lsphp83 — ver HANDOFF).
  • Rotacionar GROQ_API_KEY (foi compartilhada em chat) e validar IA pós-rotação.

2.2 — Consentimento LGPD no onboarding [DEV]

  • Registro público foi removido → migrar captura de consentimento_lgpd_em para a primeira sessão do profissional (tela/modal de aceite antes de usar) ou para os termos da assinatura.
  • Bloquear uso até aceite; gravar timestamp + versão dos termos.

2.3 — Retenção / direitos do titular (LGPD) [DEV+CLIENTE]

  • [CLIENTE] Definir política de retenção (dado clínico infantil = sensível; voz = biométrico).
  • [DEV] Exclusão de paciente/relatórios/áudios em cascata + rota de "exportar/excluir meus dados".
  • Saída: ✅ produção com APP_DEBUG=false, consentimento e exclusão atendidos.

FRENTE 3 — Billing & provisionamento 🔴 (provider a decidir)

Hoje "Assinar" abre mailto: e a conta é provisionada à mão (DemoSeeder). Planejar agnóstico ao provedor (Mercado Pago / Stripe / Asaas) atrás de uma interface, como já se fez com IA e voz.

3.1 — Camada de pagamento trocável [DEV]

  • Interface BillingProvider (criar assinatura, webhook de status, cancelar) — espelha o padrão TextToSpeechProvider.
  • Tabela assinaturas (profissional, plano, status, provider, ids externos, período).

3.2 — Checkout + provisionamento automático [DEV+CLIENTE]

  • [CLIENTE] Escolher provedor + conta/credenciais (Pix/boleto/cartão).
  • [DEV] Botão "Assinar" → checkout do provider → webhook cria/ativa a conta (substitui o seeder manual) → e-mail de boas-vindas com acesso.
  • [DEV] Gate: conta sem assinatura ativa = somente leitura / bloqueada.
  • Saída: ✅ auto-provisionamento pós-pagamento, sem intervenção manual.

Sequência recomendada

  1. 1.1 worker (destrava qualquer áudio) → 1.2 decisão1.3/1.4 voz validada.
  2. 2.1 + 2.2 (produção + LGPD mínimo) — pode rodar piloto com contas provisionadas à mão.
  3. Frente 3 billing quando o modelo comercial estiver fechado.

Atualizar HANDOFF.md ao fim de cada etapa concluída.

08

Prontuário & sessões

Como o RelataTEA organiza o dia a dia clínico. Decisão: o paciente é uma pasta (prontuário); o trabalho acontece em sessões (chat datado); cada sessão finalizada gera documentos e mídia organizados por data.

Conceito: o paciente como pasta

Cada paciente tem um prontuário — a "pasta" onde tudo se acumula ao longo do acompanhamento:

Paciente "Lucas Martins" (PAC-7F2A)
└── Prontuário  [fase: intervenção]
    ├── Anamnese (sessão 1)        — chat + documento de anamnese
    ├── Avaliação (sessões 2–8)    — chat + aplicações de protocolo + fotos
    │   ├── Aplicação: Portage     — resultados + observações
    │   └── Aplicação: IAR         — resultados + observações
    ├── Relatório técnico + acolhedor
    ├── PEI                        — objetivos mensuráveis
    ├── Intervenção (sessões 9…)   — chat + fotos + planejamento por sessão
    └── Devolutiva                 — documento + áudio para os pais

Na prática, "a pasta" é a visão agregada de sessoes + relatorios_clinicos + anexos + aplicacoes_protocolo filtrados por paciente_id, ordenada por data — exatamente o que PacienteDetalhe já faz, agora enriquecido.

O prontuario em si guarda o estado do ciclo clínico (não é um wrapper vazio):

  • fase_clinica: anamnese → avaliacao → correcao → relatorio → pei → intervencao → devolutiva
  • sínteses transversais: queixa_inicial, hipotese_clinica, sintese_avaliacao, plano_terapeutico

A sessão (camada de trabalho)

Uma sessão é o registro datado de um encontro. É onde a profissional conversa com o chat durante/depois do atendimento. Tudo que entra no chat fica salvo na sessão:

  • Texto — anotações livres, ditado.
  • Áudio — gravado no navegador ou enviado; transcrito automaticamente (Groq Whisper) e anexado com a transcrição. Tempo real é meta futura; o baseline transcreve ao enviar.
  • Foto — registro do atendimento (material, produção da criança, setting); salva na pasta da sessão (disco privado). Fotos não são enviadas à IA — são documentação clínica armazenada.

Ciclo de vida:

aberta ──(conversa: texto/áudio/foto)──> finalizando ──(LLM)──> finalizada
                                                          │
                                          gera: relatório(s) + planejamento da próxima

Ao finalizar a sessão:

  1. A conversa consolidada vira relatório(s) (relatorios_clinicos com sessao_id), no tom escolhido (técnico e/ou acolhedor).
  2. A IA produz o planejamento da próxima sessão (planejamento_proxima).
  3. A sessão passa a ser listada no prontuário, com seus documentos e anexos.

Modelo de dados

Implementação em migrations (Fase 14). SQL de referência.

-- Prontuário: 1:1 com paciente; estado do ciclo clínico
CREATE TABLE prontuarios (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    paciente_id     BIGINT UNSIGNED NOT NULL UNIQUE,
    profissional_id BIGINT UNSIGNED NOT NULL,
    fase_clinica    ENUM('anamnese','avaliacao','correcao','relatorio','pei','intervencao','devolutiva')
                        NOT NULL DEFAULT 'anamnese',
    queixa_inicial  TEXT NULL,
    hipotese_clinica LONGTEXT NULL,
    sintese_avaliacao LONGTEXT NULL,
    plano_terapeutico LONGTEXT NULL,
    abertura_em     TIMESTAMP NULL,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    FOREIGN KEY (paciente_id) REFERENCES pacientes(id) ON DELETE CASCADE
);

-- Sessão: camada de trabalho (o chat datado)
CREATE TABLE sessoes (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    paciente_id     BIGINT UNSIGNED NOT NULL,
    profissional_id BIGINT UNSIGNED NOT NULL,
    prontuario_id   BIGINT UNSIGNED NOT NULL,
    data_sessao     DATE NOT NULL,
    numero          SMALLINT UNSIGNED NULL,           -- "sessão 3" (rótulo)
    tipo_sessao     ENUM('anamnese','avaliacao','intervencao','devolutiva',
                         'orientacao_parental','orientacao_educacional','livre')
                        NOT NULL DEFAULT 'intervencao',
    especialidade   VARCHAR(40) NULL,                 -- snapshot
    titulo          VARCHAR(160) NULL,
    seletores_json  JSON NULL,                        -- nível + metas (mesmo formato de relatorios_clinicos)
    mensagens_json  JSON NULL,                        -- log do chat (autor/tipo/texto/anexo_id/em)
    texto_terapeuta LONGTEXT NULL,                    -- consolidado
    resumo_sessao   LONGTEXT NULL,                    -- síntese gerada na finalização
    planejamento_proxima LONGTEXT NULL,               -- plano da próxima sessão
    status          ENUM('aberta','finalizando','finalizada') NOT NULL DEFAULT 'aberta',
    finalizada_em   TIMESTAMP NULL,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    INDEX (paciente_id, data_sessao),
    FOREIGN KEY (paciente_id) REFERENCES pacientes(id) ON DELETE CASCADE
);

-- Anexo: mídia por sessão (foto/áudio/documento)
CREATE TABLE anexos (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    sessao_id       BIGINT UNSIGNED NOT NULL,
    paciente_id     BIGINT UNSIGNED NOT NULL,         -- desnormalizado p/ listagem
    profissional_id BIGINT UNSIGNED NOT NULL,
    tipo            ENUM('foto','audio','documento') NOT NULL,
    disco           VARCHAR(40) NOT NULL DEFAULT 'anexos',
    caminho         VARCHAR(512) NOT NULL,            -- pac_{id}/sessao_{id}/{ulid}.{ext}
    nome_original   VARCHAR(255) NULL,
    mime            VARCHAR(120) NULL,
    tamanho_bytes   INT UNSIGNED NULL,
    transcricao     LONGTEXT NULL,                    -- preenchida on-send p/ áudio
    descricao       VARCHAR(255) NULL,                -- legenda da foto
    largura         INT UNSIGNED NULL,
    altura          INT UNSIGNED NULL,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    FOREIGN KEY (sessao_id) REFERENCES sessoes(id) ON DELETE CASCADE
);

-- relatorios_clinicos ganha vínculo com a sessão e o tom
ALTER TABLE relatorios_clinicos
    ADD COLUMN sessao_id BIGINT UNSIGNED NULL,        -- null = legado/demo
    ADD COLUMN tom ENUM('tecnico','acolhedor') NOT NULL DEFAULT 'tecnico';

Organização da mídia no disco

Disco privado novo anexos (espelha voices/audios), com uma pasta por sessão:

storage/app/anexos/
└── pac_12/
    ├── sessao_45/
    │   ├── 01J9XR…ABC.jpg     (foto, EXIF removido)
    │   └── 01J9XS…DEF.webm    (áudio)
    └── sessao_46/
        └── 01J9XT…GHI.jpg

Servida só por rota autorizada /anexos/{anexo} com checagem de dono (abort_unless($anexo->profissional_id === auth('profissional')->id(), 404)), nunca por URL pública. Detalhes de LGPD em 12-LGPD-MIDIA.md.

Retrocompatibilidade

  • Migração aditiva (nada é removido).
  • Migração de dados (uma vez): cada relatorio_clinico existente vira uma sessao espelhada, com sessao_id ligando de volta — a conta demo continua "viva".
  • relatorios_clinicos segue sendo a camada de documento (PDF, ResumoPais, prompts, testes preservados).

Risco conhecido

numero sequencial por paciente sob concorrência: calcular dentro de transação com lock no prontuário, ou tratar numero como rótulo derivado de created_at.

09

Protocolos de avaliação

Modelo de uso: "executar protocolo X". A profissional aplica o instrumento presencialmente (com seu próprio material licenciado) e registra no sistema os resultados e observações. O RelataTEA organiza, cruza com as sessões e alimenta os relatórios.

Disclaimer de direitos autorais (regra de produto)

O sistema armazena apenas:

  1. Metadados do protocolo (nome, sigla, o que avalia, faixa etária, área, referência) — informação factual, pública.
  2. Os registros do profissional (resultados, escores, checklist, observações) que ele mesmo digitou.

O sistema não reproduz o conteúdo protegido dos instrumentos (itens, pranchas, folhas de resposta, critérios de pontuação proprietários). Vários protocolos (Portage, Vineland, PEP-3, ABLLS-R, etc.) são comerciais/licenciados — o material em si continua sendo de responsabilidade do profissional. O RelataTEA é o caderno de registro, não uma cópia do teste.

Como funciona no app

  1. Numa sessão de tipo = avaliacao, a profissional abre o painel "Aplicar protocolo".
  2. A lista é filtrada por especialidade do profissional e faixa etária do paciente (a avaliação depende da idade).
  3. Ela escolhe o protocolo, aplica presencialmente, e registra:
    • Resultados (resultados_json): pares área → escore/nível, livres e estruturados.
    • Checklist (checklist_json): checklist de observações e checklist de acertos.
    • Observações comportamentais (observacoes): texto livre.
    • Conclusão/pontuação parciais.
  4. Esses registros entram (pseudonimizados) no prompt do relatório de avaliação — o relatório cita "conforme o protocolo X" usando os dados dela, sem reproduzir o instrumento.

Modelo de dados

-- Catálogo de protocolos (metadados) — espelha metas_catalogo
CREATE TABLE protocolos_catalogo (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    nome            VARCHAR(160) NOT NULL,
    sigla           VARCHAR(40)  NOT NULL,
    avalia          VARCHAR(255) NULL,                 -- o que mede (metadado)
    area            VARCHAR(80)  NULL,                 -- linguagem, comportamento, global, sensorial, adaptativo, acadêmico
    tipo            ENUM('rastreio','avaliacao','inventario') NOT NULL DEFAULT 'avaliacao',
    faixa_min_meses SMALLINT UNSIGNED NULL,
    faixa_max_meses SMALLINT UNSIGNED NULL,
    especialidade   VARCHAR(40)  NULL,                 -- null = geral
    referencia      VARCHAR(255) NULL,                 -- autor/fonte (metadado)
    ativo           BOOLEAN NOT NULL DEFAULT TRUE,
    ordem           SMALLINT UNSIGNED NOT NULL DEFAULT 0,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    INDEX (especialidade, area)
);

-- Aplicação ("executei o protocolo X")
CREATE TABLE aplicacoes_protocolo (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    protocolo_id    BIGINT UNSIGNED NOT NULL,
    sessao_id       BIGINT UNSIGNED NULL,
    paciente_id     BIGINT UNSIGNED NOT NULL,
    profissional_id BIGINT UNSIGNED NOT NULL,
    data_aplicacao  DATE NOT NULL,
    resultados_json JSON NULL,                          -- área → escore/nível (digitado pelo profissional)
    checklist_json  JSON NULL,                          -- checklist de observações / de acertos
    observacoes     LONGTEXT NULL,                      -- observações comportamentais
    pontuacao_total VARCHAR(60) NULL,
    conclusao       LONGTEXT NULL,
    status          ENUM('em_andamento','concluida') NOT NULL DEFAULT 'em_andamento',
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    FOREIGN KEY (protocolo_id) REFERENCES protocolos_catalogo(id)
);

Model ProtocoloCatalogo com scopeParaEspecialidade() (copiar de MetaCatalogo) e scopeParaIdade($meses) (filtra por faixa_min_meses/faixa_max_meses). A idade vem de Paciente::idade().

Catálogo conhecido a semear (metadados)

Lista de partida; o catálogo é configurável — a profissional pode ativar/cadastrar outros. Faixas etárias são aproximadas, para o filtro por idade. Apenas metadados.

Sigla Nome / o que avalia Área Faixa Especialidade
IAR Inventário de avaliação de repertórios básicos (linha ABA) Comportamento pré-escolar ABA, fono
PROAD Protocolo de avaliação do desenvolvimento Desenvolvimento global infantil geral
Portage Inventário operacionalizado de Portage (desenvolvimento) Desenvolvimento global 0–6 anos psicopedagogia, T.O., psicologia
VB-MAPP Marcos verbais e comportamentais Comunicação/comportamento 0–48 meses ABA, fono
ABLLS-R Avaliação de repertório de habilidades básicas e de linguagem Comunicação/comportamento pré-escolar/escolar ABA, fono
VABS (Vineland) Comportamento adaptativo Adaptativo 0–adulto psicologia
PEP-3 Perfil psicoeducacional (linha TEACCH) Desenvolvimento/educacional 2–7 anos psicopedagogia, psicologia
M-CHAT-R/F Rastreio de risco para TEA Rastreio 16–30 meses geral
Denver II Triagem de desenvolvimento Desenvolvimento global 0–6 anos geral
Sensory Profile Perfil sensorial Sensorial infantil T.O.
AHEMD Ambiente domiciliar e desenvolvimento motor Motor/AVD 0–3 anos T.O.
Aval. fonoaudiológica de linguagem Linguagem (compreensiva/expressiva) Linguagem infantil fono

Campos especialidade e faixa etária permitem o escopo automático na UI (por especialidade do profissional e idade do paciente). Itens sem especialidade (null) aparecem para todos.

Verificação (Fase 18)

Aplicar IAR/PROADE/IPO numa sessão de avaliação, registrar resultados/observações, gerar o relatório de avaliação e confirmar que ele cita "conforme protocolo X" usando os dados do profissional — sem reproduzir o conteúdo do instrumento.

Atualização (25/06/2026) — catálogo expandido + registro estruturado

Catálogo verificado (62 protocolos ativos) semeado por ProtocolosCatalogoSeeder, gerado por pesquisa multi-agente com verificação na web (nomes/autores/referências conferidos). Distribuição: psicopedagogia 9, fono 11, T.O. 12, psicologia 13, ABA 11, geral 6. Correções de verdade-base (documentos reais da profissional): IAR = "Instrumento de Avaliação do Repertório Básico para Alfabetização" (Leite, EDICON 2015), psicopedagogia/Acadêmico, 13 dimensões — não mais "ABA"; PROAD → PROADE ("Proposta de Avaliação das Dificuldades Escolares", Bacha/Booktoy). Siglas legadas superadas (PROAD, PortageIPO, VABSVineland-3, Perfil SensorialSP-2, AHEMDAHEMD-SR/IS, Aval. de linguagem) ficam ativo=false (idempotente no seeder). As colunas avalia/referencia viraram TEXT (descrições clínicas completas).

Duas colunas novas (metadado factual) em protocolos_catalogo (migration 2026_06_25_120000): dimensoes (json — domínios avaliados, ex. IAR → 13 áreas) e escala_niveis (json — mapa nível→rótulo; IAR usa "Acerto total/Alguma dificuldade/Muita dificuldade", os demais caem em ProtocoloCatalogo::ESCALA_PADRAO = OK/Parcial/Déficit). Helpers temDimensoes()/escalaNiveis(). Continuam sendo apenas metadados — nunca itens/pranchas/critérios.

Registro estruturado por dimensão (SessaoEstudio + sessao-estudio.blade.php): quando o protocolo tem dimensões, o painel "Aplicar protocolo" mostra uma linha por domínio com seletor segmentado de nível + nota; senão, cai no texto livre legado. resultados_json versionado: {modo:'estruturado', escala:{snapshot}, dimensoes:[{area,nivel,nota}], texto} (retrocompat: a chave texto segue viva; níveis validados server-side contra a escala). GroqLlmService::montarEntrada renderiza "Resultados por dimensão (conforme o {sigla})" pseudonimizando só as notas livres. Testes: ProtocoloTest (6, inclui estruturado + nível inválido). Suíte 79/79.

10

Modelos de relatório & áudio

Os tipos de documento e os tipos de áudio para os pais saem de consts hardcoded e passam a ser catálogos em banco, com modelos editáveis por profissional. Tom acolhedor com guardrail inviolável.

Tipos de documento

Hoje RelatorioClinico::TIPOS é uma const PHP (evolucao/justificativa/pei/escolar). Passa a ser o catálogo tipos_documento_catalogo.

CREATE TABLE tipos_documento_catalogo (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    chave           VARCHAR(40)  NOT NULL UNIQUE,       -- evolucao, anamnese, devolutiva...
    rotulo          VARCHAR(120) NOT NULL,
    descricao       VARCHAR(255) NULL,
    tom             ENUM('tecnico','acolhedor') NOT NULL DEFAULT 'tecnico',
    prompt_arquivo  VARCHAR(120) NULL,                  -- arquivo em resources/prompts/
    prompt_texto    LONGTEXT NULL,                      -- override editável (sem deploy)
    especialidade   VARCHAR(40)  NULL,
    profissional_id BIGINT UNSIGNED NULL,               -- null = modelo do sistema; preenchido = modelo do profissional
    ativo           BOOLEAN NOT NULL DEFAULT TRUE,
    ordem           SMALLINT UNSIGNED NOT NULL DEFAULT 0,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL
);

Chaves a semear:

Chave Rótulo Tom Quando
anamnese Anamnese técnico início do acompanhamento
evolucao Relatório de evolução técnico sessões de intervenção (existente)
acolhedor Relatório acolhedor acolhedor versão calorosa do técnico, p/ a família
devolutiva Relatório de devolutiva acolhedor fechamento do ciclo de avaliação (importante)
pei PEI / PDI clínico técnico após o relatório (existente)
justificativa Justificativa de carga horária técnico convênios (existente)
escolar Relatório escolar / mediador técnico escola (existente)
orientacao_educacional Orientação educacional acolhedor sob demanda, p/ escola/professores
orientacao_parental Orientação parental acolhedor sob demanda, p/ os pais

Modelos editáveis por profissional

profissional_id = null → modelo do sistema (vem do .txt em resources/prompts/). Quando o profissional edita um modelo, salvamos uma linha com profissional_id preenchido e prompt_texto com o texto customizado. Na geração, a ordem de resolução é: modelo do profissional → modelo do sistema → arquivo .txt.

Prompts novos (resources/prompts/)

Mesmo estilo de relatorio_tecnico.txt (REGRAS INVIOLÁVEIS + pseudonimização):

  • anamnese.txt, devolutiva.txt, orientacao_educacional.txt, orientacao_parental.txt, relatorio_acolhedor.txt.

Guardrail de tom acolhedor (inviolável)

Embutida em todo prompt de tom acolhedor e na devolutiva:

Jamais concluir que a criança "não sabe nada", "não consegue", "não evoluiu" ou equivalentes. Sempre enquadrar por repertório atual, potenciais e próximos passos. Honesto sem alarmar e sem minimizar; nunca prometer cura. Traduzir o jargão técnico para linguagem acessível, com respeito e parceria.

É a mesma técnica das REGRAS INVIOLÁVEIS de relatorio_tecnico.txt e do tom de resumo_pais.txt (acolhimento, empatia, "nunca alarme/minimize").

Tipos de áudio para os pais (configuráveis)

Hoje só existe um roteiro (resumo_pais.txt, 400–480 palavras). Passa a ser um catálogo de tipos/tons:

CREATE TABLE tipos_audio_pais (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    chave           VARCHAR(40) NOT NULL UNIQUE,
    rotulo          VARCHAR(120) NOT NULL,
    descricao       VARCHAR(255) NULL,
    prompt_arquivo  VARCHAR(120) NULL,
    prompt_texto    LONGTEXT NULL,
    tom             VARCHAR(40) NULL,
    limite_palavras SMALLINT UNSIGNED NOT NULL DEFAULT 480,
    ativo           BOOLEAN NOT NULL DEFAULT TRUE,
    ordem           SMALLINT UNSIGNED NOT NULL DEFAULT 0,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL
);

Conjunto sugerido (minhas sugestões, conhecendo o projeto):

Chave Rótulo Tom Palavras Uso
evolucao Resumo da sessão acolhedor, leve ~480 rotina (o atual)
devolutiva Devolutiva de avaliação acolhedor, solene ~700 fechar ciclo de avaliação
orientacao Orientação prática direto, acionável ~300 "o que fazer em casa"
boas_vindas Acolhimento inicial caloroso ~250 primeira sessão
celebracao Conquista de meta comemorativo, curto ~180 quando bate uma meta

Mudanças: resumos_pais ganha coluna tipo (default evolucao); GroqLlmService::gerarResumoPais() recebe o tipo e lê prompt + limite_palavras do catálogo (hoje 480/510 hardcoded). O card de áudio ganha um seletor de tipo. O GerarAudioResumoJob (TTS) não muda.

Mudanças de código necessárias (resumo)

  • GroqLlmService::gerarRelatorioTecnico() → generalizar para gerarDocumento(relatorio, tipo), carregando o prompt do catálogo.
  • montarEntrada() → lookup no catálogo (em vez de RelatorioClinico::TIPOS) e incluir no payload: aplicações de protocolo (resultados/observações) e transcrições de áudio dos anexos da sessão. Manter pseudonimização.
  • ConstrutorRelatorio::render()/rotuloTipo() → consultar catálogo. Manter fallback const na transição.
11

CBO & conselhos

Decisão: o CBO não é campo do profissional — ele deriva da especialidade. Cada especialidade tem um CBO e um conselho de classe associados, usados no cabeçalho dos relatórios e no PDF.

Por quê derivar e não digitar

O CBO (Classificação Brasileira de Ocupações) é determinado pela profissão/ocupação, não pela pessoa. Pedir para o profissional digitar abre espaço para erro e inconsistência. Como já temos especialidade (Profissional::ESPECIALIDADES), o CBO é uma consequência — um mapa.

Onde fica

Const ao lado de ESPECIALIDADES em app/Models/Profissional.php (coesão com registro_conselho), com um método resolvedor:

const CBO_POR_ESPECIALIDADE = [
    'fono'            => ['cbo' => '2238-10', 'conselho' => 'CRFa',    'ocupacao' => 'Fonoaudiólogo'],
    'psicologia'      => ['cbo' => '2515-10', 'conselho' => 'CRP',     'ocupacao' => 'Psicólogo clínico'],
    'to'              => ['cbo' => '2239-05', 'conselho' => 'CREFITO', 'ocupacao' => 'Terapeuta ocupacional'],
    'psicopedagogia'  => ['cbo' => '2394-25', 'conselho' => null,      'ocupacao' => 'Psicopedagogo'],
    'aba'             => ['cbo' => null,      'conselho' => null,      'ocupacao' => 'Analista do comportamento'],
];

public function cbo(): ?string { return self::CBO_POR_ESPECIALIDADE[$this->especialidade]['cbo'] ?? null; }

Mapa proposto (a confirmar antes do go-live)

Especialidade CBO sugerido Conselho Observação
Fonoaudiologia 2238-10 CRFa
Psicologia 2515-10 CRP
Terapia Ocupacional 2239-05 CREFITO
Psicopedagogia 2394-25 profissão sem conselho federal próprio; sinalizar
ABA (Análise do Comportamento) não é ocupação CBO própria — usar o CBO da formação-base (geralmente Psicólogo 2515-10). Decisão do cliente.

⚠️ Os códigos acima são sugestões e devem ser conferidos na tabela oficial do CBO antes do go-live. ABA é o ponto que exige decisão: como ABA não tem código próprio, o profissional ABA normalmente reporta pelo CBO da sua formação de origem.

Uso

  • PDF resources/views/pdf/relatorio.blade.php e cabeçalho dos relatórios: exibir Nome — Ocupação · CBO {cbo} · {Conselho} {registro_conselho}.
  • registro_conselho (já existente, texto livre como "CRFa 2-1234") continua sendo o número; o CBO/conselho/ocupação vêm do mapa.

Pendência relacionada

Adicionar psicopedagogia a Profissional::ESPECIALIDADES exige atualizar a validação in:fono,psicologia,aba,to em Perfil.php — trocar por Rule::in(array_keys(Profissional::ESPECIALIDADES)) para nunca mais ficar dessincronizada.

12

Processo clínico

Documento-guia escrito na perspectiva de uma psicopedagoga, para orientar tanto a equipe de produto quanto os profissionais que usam o RelataTEA. É a fonte da verdade clínica que justifica as fases técnicas do app. Linguagem de prática, não de código.


Como eu penso o acompanhamento

Quando uma família chega até mim, ela não chega com um "caso". Chega com uma criança inteira e uma preocupação. Meu trabalho não é descobrir tudo o que a criança não faz — é entender quem ela é hoje, do que ela já é capaz, e qual o próximo passo possível. Todo o processo abaixo serve a isso. E há uma regra que atravessa tudo: nunca devolvo a uma família a ideia de que a criança "não sabe nada". Sempre falo de repertório atual, de potencial e de caminho. O RelataTEA precisa carregar essa mesma postura em cada relatório que gera.

O processo tem um começo (a anamnese) e um fim de ciclo (a devolutiva), e entre os dois há etapas que se encadeiam. Não é uma esteira rígida — é um ciclo que pode recomeçar —, mas a ordem importa.

Acolhimento → Anamnese → Avaliação (5–10 sessões, protocolos)
   → Correção/análise → Relatório → PEI → Intervenção → Devolutiva
        ↘ (sob demanda) Orientação parental · Orientação educacional

1. Acolhimento e queixa

Antes de qualquer instrumento, escuto a queixa. A queixa é o que a família (ou a escola) traz como motivo: "ela não fala", "não interage com os colegas", "tem birras intensas". A queixa não é o diagnóstico nem a anamnese — é o ponto de partida, a dor que move a procura. Registro a queixa como ela foi dita, com as palavras de quem trouxe.

No app: a queixa inicial vive no prontuário (queixa_inicial). É curta e fica visível durante todo o acompanhamento, porque é a ela que a devolutiva, lá no fim, vai responder.

2. Anamnese

A anamnese é a história. Aqui eu levanto, com calma e em entrevista com os responsáveis: gestação e parto, marcos do desenvolvimento (quando sentou, andou, falou), histórico de saúde, sono, alimentação, rotina, vida escolar, relações familiares, o que já foi tentado antes. A anamnese é mais larga que a queixa: a queixa é "o que dói agora"; a anamnese é "como chegamos até aqui".

No app: a anamnese é uma sessão do tipo anamnese, conduzida no chat (posso ditar, gravar áudio, anotar). Ao finalizar, gera um documento de anamnese estruturado. A hipótese clínica inicial — minha leitura provisória do que pode estar acontecendo — fica no prontuário (hipotese_clinica) e será testada na avaliação.

3. Avaliação (5 a 10 sessões)

Aqui está o coração do processo. A avaliação não se faz em um dia. Ao longo de 5 a 10 sessões, eu observo e aplico protocolos adequados à idade e à minha especialidade. A criança de 2 anos não é avaliada com os mesmos instrumentos da de 8 — por isso o app filtra os protocolos por faixa etária.

O que acontece em cada sessão de avaliação:

  • Observação comportamental: como a criança entra, como se separa do cuidador, como brinca, como reage a limites, como comunica o que quer. Isso eu registro como observações — muitas vezes são elas que dizem mais do que o escore.
  • Aplicação de protocolo: eu aplico o instrumento presencialmente, com meu próprio material. No sistema, registro os resultados e um checklist (de observações e de acertos). O app é meu caderno de registro — ele não substitui nem reproduz o teste.
  • Material da sessão: registros, produções da criança, fotos do setting. Tudo fica anexado à sessão, naquele dia.

Protocolos que uso conforme o caso (a lista completa, com faixas etárias, está em 08-PROTOCOLOS-AVALIACAO.md): Portage e Denver para desenvolvimento global em crianças pequenas; M-CHAT para rastreio de risco; IAR, VB-MAPP e ABLLS-R na linha do comportamento e da linguagem; Vineland para comportamento adaptativo; perfis sensoriais quando há T.O. envolvida. A escolha depende da queixa, da idade e da hipótese.

4. Correção e análise

Terminadas as sessões de avaliação, eu fecho a leitura: corrijo/pontuo o que cada protocolo pediu, cruzo os resultados entre si e com as observações, e confronto tudo com a hipótese inicial. É o momento de transformar dados soltos em entendimento. Pergunto-me: o que esses números e observações, juntos, dizem sobre como essa criança aprende, se comunica, se regula?

No app: essa síntese consolidada vive no prontuário (sintese_avaliacao). É a matéria-prima do relatório.

5. Relatório

O relatório é onde a análise vira documento. Eu trabalho com dois tons do mesmo conteúdo:

  • Relatório técnico: para conselhos, convênios, equipe multidisciplinar. Linguagem técnica, precisa, sem floreio.
  • Relatório acolhedor: o mesmo conteúdo, traduzido para a família — caloroso, claro, respeitoso, sem jargão.

Em ambos, e principalmente no acolhedor, vale a regra de ouro: nunca concluir que a criança "não sabe nada". Onde há ausência, eu escrevo "ainda não observado" ou "em desenvolvimento", e aponto o próximo passo. Honestidade sem alarme, sem minimizar, sem prometer cura.

6. PEI — Plano Educacional/Terapêutico Individualizado

Depois do relatório, faço o PEI: é ele que diz o que vamos fazer nas intervenções. O relatório descreve onde a criança está; o PEI define para onde vamos e como. Listo objetivos terapêuticos mensuráveis — cada um com comportamento-alvo e critério de domínio ("emitir o pedido de 'água' de forma independente em 8 de 10 oportunidades") — para o próximo ciclo. O PEI é vivo: revisado a cada ciclo.

No app: o PEI é um tipo de documento, gerado a partir da síntese e listado no prontuário. O plano_terapeutico do prontuário guarda o fio condutor entre ciclos.

7. Intervenção (as sessões do dia a dia)

Com o PEI na mão, começam as sessões de intervenção — o cotidiano do acompanhamento. Cada sessão é registrada no chat: o que foi trabalhado, como a criança respondeu, fotos do material, áudios com minhas impressões. Ao finalizar a sessão, o sistema:

  1. transforma a conversa em um relatório de evolução daquele dia, e
  2. me devolve um planejamento para a próxima sessão — o que faz sentido trabalhar a seguir, à luz do PEI e do que aconteceu hoje.

É assim que o acompanhamento ganha continuidade: cada sessão "conversa" com a anterior e prepara a seguinte.

8. Devolutiva (fechamento de ciclo)

A devolutiva é, para mim, um dos momentos mais importantes — e por isso merece cuidado especial. É quando sento com a família e devolvo, em linguagem que acolhe, o que entendemos sobre a criança e o que vamos fazer. A devolutiva responde diretamente à queixa do começo. Ela precisa ser verdadeira e, ao mesmo tempo, sustentar a esperança e a parceria. Aqui, mais do que em qualquer lugar, a regra de nunca dizer que a criança "não sabe nada" é inegociável: a devolutiva planta o tom de todo o trabalho que vem.

No app: a devolutiva é um tipo de documento (tom acolhedor) e pode virar também um áudio para os pais — útil para a família reescutar com calma. Os tipos de áudio são configuráveis (ver 09-MODELOS-RELATORIO-E-AUDIO.md).


Processos paralelos (sob demanda)

Não acontecem em uma etapa fixa — surgem quando a situação pede:

  • Orientação parental: quando a família precisa de direção prática para casa ("o que fazer na hora da birra", "como estruturar a rotina"). Curta, acionável, sem culpabilizar.
  • Orientação educacional: quando a escola pede apoio — orientações ao professor, ao mediador, sugestões de adaptação. Escrita para quem está na sala de aula, não para o consultório.

Ambas são tipos de documento próprios e podem ser geradas a qualquer momento do acompanhamento.


O que o RelataTEA precisa honrar

  1. O paciente é uma pasta (prontuário) que acompanha o ciclo inteiro, na ordem acima.
  2. A sessão é o lugar do trabalho — conversa, áudio transcrito, fotos —, e finalizá-la gera documento + planejamento.
  3. A avaliação depende da idade e se faz em várias sessões, com protocolos que o profissional aplica e registra.
  4. Dois tons de relatório: técnico e acolhedor.
  5. A regra de ouro, em todo texto voltado à família: nunca "a criança não sabe nada" — sempre repertório atual, potencial e próximo passo.
  6. A devolutiva responde à queixa registrada lá no início.
13

LGPD & mídia clínica

Fotos e áudios de crianças em atendimento são dados pessoais sensíveis (saúde, e de menores). Este documento define como o RelataTEA os trata.

Regras invioláveis

  1. Mídia nunca vai à IA. O LLM é texto-puro. Fotos são documentação clínica armazenada, jamais enviadas a serviços externos (Groq/HF). Áudio é transcrito (texto) e a transcrição — pseudonimizada — é o que pode ir à IA; o arquivo de áudio fica no disco privado.
  2. Binário só no disco privado, nunca no banco. No banco vai apenas o path. Disco anexos (storage/app/anexos, driver local, sem URL pública).
  3. Acesso só por rota autorizada. /anexos/{anexo} faz abort_unless($anexo->profissional_id === auth('profissional')->id(), 404). Sem link público, sem storage:link para esse disco.
  4. EXIF removido das fotos no upload (geolocalização/dispositivo). Re-encode da imagem ao salvar.
  5. Pseudonimização preservada. A pasta usa pac_{id}/sessao_{id}/ — sem nome real no caminho. O nome real do paciente nunca aparece em path de arquivo (mesma política do PDF, que nomeia por codigo_anonimo).

Organização no disco

storage/app/anexos/
└── pac_{paciente_id}/
    └── sessao_{sessao_id}/
        ├── {ulid}.jpg     (foto, EXIF removido, re-encodada)
        └── {ulid}.webm    (áudio enviado ao chat)

Ciclo de vida e retenção

  • Consentimento: o uso de imagem da criança requer consentimento do responsável. Registrar o consentimento (data) — reutilizar o padrão de consentimento_lgpd_em/voz. (A confirmar com o cliente: consentimento por paciente para imagem.)
  • Exclusão: ao excluir paciente/sessão, os anexos são removidos do disco (cascade no banco + limpeza física). Prever uma rotina de limpeza para arquivos órfãos.
  • Retenção: definir prazo de guarda conforme exigência do conselho de classe (prontuário clínico costuma exigir guarda mínima de anos). (A confirmar.)

Limites de upload (sugeridos)

  • Foto: image|mimes:jpg,jpeg,png,webp|max:8192 (8 MB), EXIF removido.
  • Áudio no chat: mimetypes:audio/* (reusar a validação de updatedAudio), até ~25 MB.

Checklist de verificação (Fase 20)

  • Anexo só acessível pelo dono (intruso → 404). Estender IsolamentoMultiTenantTest.
  • Disco anexos sem URL pública / sem symlink.
  • EXIF ausente nas fotos salvas.
  • Path sem nome real (só pac_{id}/sessao_{id}).
  • Exclusão de paciente/sessão remove os arquivos.
  • Nenhuma mídia enviada à Groq/HF (só transcrição de texto pseudonimizada).
14

Plano de expansão

Continuação de 01-PLANO-EXECUCAO.md. Mesmo princípio: cada fase é entregável e testável, executada aos poucos, na ordem. Decisões de produto coletadas com o cliente em 22/06/2026.

Por que esta expansão

O app hoje trata "1 relatório = 1 sessão" (tudo vive em relatorios_clinicos). A visão do cliente é maior: cada paciente é uma pasta (prontuário); no dia a dia a profissional conduz a sessão conversando com o chat (texto, áudio transcrito, fotos), e ao finalizar a sessão a conversa vira um relatório listado no prontuário, mais um planejamento da próxima. Em volta disso há um processo clínico completo (anamnese → avaliação por protocolos → relatório → PEI → intervenção → devolutiva) e modelos configuráveis de relatório e de áudio para os pais.

Esta expansão é aditiva e retrocompatível: relatorios_clinicos permanece como a camada de documento gerado; introduzimos sessoes como a camada de trabalho. Nada do que já funciona (PDF, resumo para pais, prompts, testes de isolamento) é quebrado.

Decisões fixas (22/06/2026)

  1. Prontuário por paciente: pasta organizada por data. Ver 07-PRONTUARIO-E-SESSOES.md.
  2. Sessão é camada própria (não refatorar relatorios_clinicos; adicionar sessoes por cima).
  3. Chat na sessão aceita texto, áudio (transcrito on-send) e fotos (salvas na pasta da sessão). Tempo real de transcrição é stretch goal.
  4. Fotos nunca vão à IA — o LLM é texto-puro; foto é documentação clínica armazenada (reforça LGPD). Ver 12-LGPD-MIDIA.md.
  5. Protocolos = "executar protocolo X": a profissional aplica presencialmente e registra resultados + observações. O sistema guarda só metadados + os registros dela, nunca o conteúdo protegido dos instrumentos. Ver 08-PROTOCOLOS-AVALIACAO.md.
  6. Tipos de documento e tipos de áudio configuráveis (catálogo em banco + modelos por profissional). Ver 09-MODELOS-RELATORIO-E-AUDIO.md.
  7. Tom acolhedor com guardrail inviolável: jamais concluir que "a criança não sabe nada" ou similar; sempre enquadrar por repertório atual, potenciais e próximos passos.
  8. CBO por especialidade, não por profissional. Ver 10-CBO-E-CONSELHOS.md.
  9. Tudo documentado em docs/ (este conjunto 07→13).

Princípios herdados (preservar)

  • Pseudonimização no limite da IAGroqLlmService::montarEntrada() só envia codigo_anonimo/CID, nunca o nome. Toda nova chamada LLM monta a entrada pelo mesmo padrão.
  • Binário nunca no banco — áudio/foto vão para disco privado, só o path no banco. Padrão voices/audios em config/filesystems.php.
  • Catálogo DB filtrado por especialidademetas_catalogo + MetaCatalogo::scopeParaEspecialidade() é o molde de todo catálogo novo.
  • Transcrição/geração síncronas on-send (worker de fila ainda não roda) — só o TTS de voz permanece em fila.
  • Rate-limit de IA 60/h por profissional (excedeuLimiteIa()) reaproveitado em toda chamada nova.
  • Isolamento multi-tenantabort_unless($x->profissional_id === auth('profissional')->id(), 404) em toda nova entidade; estender IsolamentoMultiTenantTest.

Modelo de dados (resumo)

Detalhe em 03-MODELO-DADOS.md (a atualizar) e nos docs temáticos. Tabelas novas:

Tabela Papel
prontuarios 1:1 com paciente. Estado do ciclo clínico (fase, queixa, hipótese, sínteses).
sessoes Camada de trabalho: chat datado, seletores, status, finalização → plano.
anexos Mídia por sessão (foto/áudio/documento) em disco privado, pasta por sessão.
protocolos_catalogo Catálogo de protocolos conhecidos (metadados, faixa etária, área).
aplicacoes_protocolo Registro de "executei o protocolo X": resultados + observações.
tipos_documento_catalogo Tipos de documento configuráveis + modelos por profissional.
tipos_audio_pais Tipos/tons de áudio para os pais, configuráveis.
conhecimento_ia Base de conhecimento com escopo (sistema/profissional/prontuário). A "memória" da IA. Ver 14-BASE-DE-CONHECIMENTO-E-MODELOS-IA.md.
modelos_ia + modelos_ia_versoes Personas configuráveis do chat (editáveis, reversíveis ao padrão, trocáveis na conversa).

Colunas adicionadas a relatorios_clinicos: sessao_id (FK null) e tom (tecnico/acolhedor). Coluna adicionada a resumos_pais: tipo (default evolucao).


Fases

Fase 14 — Fundação de dados: Prontuário + Sessão + Anexo ✅ (entregue 23/06/2026)

  • Migrations aditivas: prontuarios, sessoes, anexos; adicionar sessao_id/tom a relatorios_clinicos.
  • Models Prontuario, Sessao, Anexo (relações; Anexo apaga o arquivo no deleting).
  • Auto-criar Prontuario no created de Paciente (espelha o auto-codigo_anonimo).
  • Disco anexos em config/filesystems.php (privado) + rota autorizada /anexos/{anexo} (anexos.stream).
  • Migração de dados (uma vez): cada paciente → prontuário; cada relatorio_clinico → uma sessao espelhada com sessao_id apontando de volta. (Aplicada na base viva: 2 prontuários, 5 sessões, 5/5 relatórios vinculados.)
  • DemoSeeder: prontuário + 1 sessão finalizada vinculada ao relatório. (Foto e aplicação de protocolo na demo ficam para as Fases 15/18, quando upload e protocolos existirem.)
  • Verif.: ✅ migrate --force ok; tinker (prontuário auto-criado, relações, cascade sem órfãos); suíte 10/10 verde; site HTTP 200. Backup pré-migração em /tmp/relatatea-db-*.sql.

Fase 15 — Chat na sessão (SessaoEstudio) ✅ (entregue 23/06/2026)

  • Livewire SessaoEstudio (clona ConstrutorRelatorio, layout studio), rota /pacientes/{paciente}/sessoes/{sessao} (sessoes.editar; sem scopeBindingsmount() valida sessão⊂paciente⊂profissional). PacienteDetalhe ganhou novaSessao() + listagem de sessões.
  • Mensagens de texto persistem em mensagens_json (formato com tipo/anexo_id).
  • Áudio: grava → upload → salva no disco anexos (anexo tipo=audio) → transcreve sync (Groq Whisper) → vira mensagem com a transcrição + player.
  • Foto: upload, EXIF removido (re-encode GD), grava no disco anexos (pac_{id}/sessao_{id}/), cria anexo(tipo=foto), renderiza via anexos.stream.
  • "Finalizar sessão" minimal (marca finalizada); geração de documento + planejamento fica para a Fase 16.
  • Verif.: ✅ suíte 16/16 (SessaoEstudioTest: texto persiste, foto vira anexo sem EXIF na pasta da sessão, finalizar, isolamento de sessão e anexo); ✅ navegador ao vivo (login demo → prontuário com sessões → nova sessão → nota registrada e renderizada). Assets rebuildados (npm run build). Obs.: estúdio é layout desktop de 3 colunas (igual ao construtor); abaixo de ~900px as colunas se sobrepõem — responsividade fica para depois.

Fase 16 — Finalizar sessão → documento + planejamento ✅ (entregue 23/06/2026)

  • finalizarSessao(GroqLlmService): guard de material → rate-limit → cria relatorios_clinicos com sessao_id (tom=tecnico) → gerarRelatorioTecnico() (status pronto) → gerarPlanejamentoProxima() grava sessao.planejamento_proximastatus=finalizada. Erro de IA/sem chave: sessão finaliza mesmo assim, relatório fica rascunho + aviso amigável.
  • Novo prompt resources/prompts/planejamento_proxima.txt (pseudonimizado, guardrail de tom) + método GroqLlmService::gerarPlanejamentoProxima() (reusa chat()).
  • Sessão finalizada vira read-only: composer oculto, mostra planejamento + link "Ver relatório gerado" (reusa o construtor existente → PDF, resumo p/ pais).
  • (Acolhedor como 2º documento e mapeamento tipo_sessao→tipo_documento ficam para a Fase 17.)
  • Verif.: ✅ suíte 17/17 (gera com LLM falso: relatório pronto + planejamento + pseudonimização; guard sem material; sem chave fecha sessão+rascunho); ✅ ao vivo (finalizei sessão real → Groq gerou relatório técnico estruturado e planejamento, ambos referindo PAC-MFZ1, nunca o nome real). Dados de teste limpos.

Fase 17 — Tipos de documento configuráveis + novos prompts ✅ (entregue 23/06/2026)

  • tipos_documento_catalogo + model TipoDocumentoCatalogo (resolução: modelo do profissional → sistema; sistema(), rotulo() memoizado) + TiposDocumentoSeeder (9 tipos: 4 existentes + anamnese, devolutiva, orientacao_parental, orientacao_educacional, acolhedor).
  • 5 prompts novos em resources/prompts/ (REGRAS INVIOLÁVEIS + pseudonimização + guardrail de tom inviolável nos acolhedores).
  • GroqLlmService::gerarDocumento() resolve o prompt no catálogo (prompt_textoprompt_arquivo → fallback técnico); montarEntrada() usa o rótulo do catálogo. gerarRelatorioTecnico() virou wrapper.
  • ConstrutorRelatorio monta o seletor pelo catálogo + deriva tom; SessaoEstudio mapeia tipo_sessao → tipo_documento + tom na finalização; RelatorioClinico::rotuloTipo() resolve pelo catálogo.
  • Coluna profissional_id+prompt_texto suportam modelos por profissional (resolução pronta; UI de edição fica para a Fase 21).
  • (Aplicações de protocolo no prompt entram na Fase 18; relatório acolhedor como 2º doc automático na finalização fica como melhoria.)
  • Verif.: ✅ suíte 20/20 (TipoDocumentoTest: resolução do sistema, override do profissional vence, sessão de devolutiva → doc devolutiva/tom acolhedor); ✅ ao vivo (seletor mostra os 9 tipos do catálogo). Backup /tmp/relatatea-db-*-pre-f17.sql.

Fase 18 — Protocolos de avaliação ✅ (entregue 23/06/2026)

  • protocolos_catalogo + model ProtocoloCatalogo (scopes paraEspecialidade/paraIdade, faixaLegivel) + ProtocolosCatalogoSeeder (12 protocolos, só metadados; registrado no DatabaseSeeder).
  • aplicacoes_protocolo + model AplicacaoProtocolo; UI no estúdio de sessão (tipo_sessao=avaliacao): seletor filtrado por especialidade + idade (meses), aplicar → registrar observações/resultados/pontuação/conclusão → concluir/reabrir/remover. Paciente::idadeMeses().
  • GroqLlmService::montarEntrada() injeta as aplicações da sessão (registros do profissional) no prompt — pseudonimizado.
  • Verif.: ✅ suíte 24/24 (ProtocoloTest: escopo especialidade+idade, aplicar cria registro, rejeita fora de escopo, concluir persiste); ✅ ao vivo (fono/~75 meses filtrou corretamente PROAD/PEP-3/Aval. linguagem; apliquei, conclui, finalizei → relatório Groq citou o protocolo e os resultados digitados, referindo só PAC-MFZ1).

Fase 19 — Áudios para pais configuráveis + CBO por especialidade

  • tipos_audio_pais (seed: evolucao, devolutiva, orientacao, boas_vindas, celebracao); seletor no card de áudio; gerarResumoPais() lê tipo + limite de palavras do catálogo.
  • Mapa especialidade → CBO (10-CBO-E-CONSELHOS.md); usado no PDF e cabeçalho de relatórios; adicionar psicopedagogia às especialidades.
  • Verif.: gerar áudio "devolutiva" vs "evolução" com limites diferentes; PDF com CBO correto.

Fase 20 — Documentação + hardening

  • Revisar/atualizar 03-MODELO-DADOS.md e este conjunto de docs.
  • Checklist LGPD de mídia (12-LGPD-MIDIA.md): retenção, exclusão, EXIF, rota autorizada.
  • Estender IsolamentoMultiTenantTest para todas as entidades novas.
  • Verif.: leitura cruzada; suite de testes verde.

Fase 21 — Base de conhecimento + modelos de IA (o "cérebro")

Detalhe completo em 14-BASE-DE-CONHECIMENTO-E-MODELOS-IA.md.

  • conhecimento_ia (escopo sistema/profissional/prontuário), modelos_ia + modelos_ia_versoes. Coluna modelo_id na sessao.
  • Serviço MontadorDeContexto (centraliza a montagem em camadas; único leitor de conhecimento/modelos — fácil de auditar). gerarDocumento() e o chat passam a usá-lo.
  • Persona do chat trocável na conversa + ajuste de tom; "voltar ao padrão" (modelos de fábrica read-only).
  • Botão "corrigir / ensinar" no chat → pergunta o escopo a cada vez (só este paciente / sempre / só desta vez) → vira conhecimento_ia. Tela "o que a IA aprendeu" (revogar entradas).
  • Compactação de memória: sessões antigas → síntese do prontuário.
  • Verif.: editar modelo → gerar → voltar ao padrão; trocar modelo no meio da conversa muda o tom; correção "só este paciente" entra no relatório dele e não no de outro; teste de isolamento (conhecimento do prontuário A ausente no prompt do B; intruso → 404); payload só com PAC-XXXX.

Dependências

14 é pré-requisito de tudo. 15→16 sequenciais. 17 expande 16. 18 é quase independente após 14 (pode ir em paralelo). 19 depende de 17 (reusa o mecanismo de prompt). 20 fecha o ciclo de docs/hardening. 21 depende de 16/17 (precisa da geração por sessão e dos tipos de documento) e é o "cérebro" que amarra tudo — pode entrar logo após 17, antes ou em paralelo a 18/19.

Decisões em aberto (confirmar com o cliente)

  1. CBO para ABA — ABA não é ocupação CBO própria; usar o CBO da formação-base (geralmente Psicólogo). Confirmar.
  2. numero de sessão sob concorrência — usar transação/lock ou tratar como rótulo derivado de created_at.
  3. Análise de imagem pela IA — fora de escopo (modelo texto-puro). Confirmar que não é requisito.

Arquivos críticos (molde para implementação)

  • app/Livewire/ConstrutorRelatorio.php — molde do SessaoEstudio (chat, updatedAudio, seletores, autosave, rate-limit).
  • app/Services/Groq/GroqLlmService.phpmontarEntrada() (pseudonimização); generalizar gerarDocumento/gerarResumoPais.
  • app/Models/MetaCatalogo.php — molde de todo catálogo novo (scopeParaEspecialidade).
  • config/filesystems.php + routes/web.php — disco privado + rota de stream autorizado.
  • app/Models/RelatorioClinico.php (TIPOS → DB) + database/seeders/MetasCatalogoSeeder.php (molde dos seeders).
15

Base de conhecimento & IA

Como a IA "lembra", aprende e fala. Decisões do cliente (22/06/2026): a memória é por prontuário (cada paciente tem sua própria base, isolada, que acumula entre sessões e relatórios); correções perguntam o escopo a cada vez; "Modelo de IA" (persona do chat) é separado de "Tipo de documento" (template do relatório) — os dois se combinam.

Ideia central: contexto em camadas

Toda conversa e todo relatório são montados por um Montador de Contexto (serviço novo) que empilha camadas, da mais geral à mais específica. Cada camada tem um dono e um escopo de isolamento:

[1] BASE DO SISTEMA        guardrails invioláveis, pt-BR, pseudonimização,        read-only (sistema)
                           "nunca 'a criança não sabe nada'"
[2] MODELO DE IA ATIVO     persona + tom + instruções do assistente               editável (profissional)
[3] PREFERÊNCIAS DO PROF.  estilo, glossário, correções "sempre"                  editável (profissional)
[4] CONHECIMENTO DO        ⭐ A MEMÓRIA: anamnese, hipótese, sínteses,             editável (prontuário)
    PRONTUÁRIO                resultados de protocolos, resumos de TODAS as
                              sessões, correções "só este paciente"
[5] CONVERSA ATUAL         mensagens de hoje, transcrições, fotos (metadados)     efêmero (sessão)
  • Conversa do dia = camadas 1+2+3+4+5.
  • Relatório final = 1+2+3+4 (= "todo o conhecimento ao longo das sessões") combinado com o tipo de documento escolhido, mais a sessão que o gerou.
  • A camada [4] é a base de conhecimento por prontuário — é ela que "lembra". Não existe memória clínica fora do prontuário.

Recomendação técnica (v1): montagem estruturada por escopo, sem RAG vetorial. O LLM (llama-3.3-70b, ~128k de contexto) comporta a síntese + resumos + conhecimento ativo de um prontuário. Busca vetorial fica como evolução futura, só se algum prontuário crescer demais.

Peça 1 — conhecimento_ia (a base, com escopo)

Cada entrada é um pedaço de conhecimento. O escopo é o que garante o isolamento:

CREATE TABLE conhecimento_ia (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    escopo          ENUM('sistema','profissional','prontuario') NOT NULL,
    profissional_id BIGINT UNSIGNED NULL,    -- preenchido em profissional/prontuario
    prontuario_id   BIGINT UNSIGNED NULL,    -- preenchido SÓ em prontuario
    tipo            ENUM('diretriz','preferencia','correcao','fato_clinico','glossario') NOT NULL,
    conteudo        TEXT NOT NULL,           -- pseudonimizado quando fato_clinico (refere PAC-XXXX, nunca nome)
    origem          ENUM('seed','manual','derivado_de_correcao') NOT NULL DEFAULT 'manual',
    peso            SMALLINT UNSIGNED NOT NULL DEFAULT 0,   -- prioridade no prompt
    ativo           BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL,
    INDEX (escopo, profissional_id, prontuario_id, ativo)
);

Regras de escopo (decisão do cliente):

  • fato_clinico só existe no escopo prontuario. Conhecimento sobre a criança fica preso ao prontuário dela.
  • profissional guarda só estilo/persona: preferencia, glossario, e correções marcadas como "sempre".
  • sistema são as diretrizes invioláveis (seed, read-only).

Exemplos:

  • preferencia (profissional): "Frases curtas; usar 'criança', nunca 'paciente'."
  • fato_clinico (prontuário do PAC-7F2A): "Regula melhor com antecipação visual da rotina; ecolalia em redução."
  • correcao (prontuário): "Neste caso, não chamar de 'birra' e sim 'desregulação'."

Peça 2 — modelos_ia (persona do chat, editável e reversível)

O assistente do chat tem personas configuráveis. É o "vários modelos com suas próprias configurações" — separado dos tipos de documento.

CREATE TABLE modelos_ia (
    id              BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    profissional_id BIGINT UNSIGNED NULL,    -- NULL = modelo de FÁBRICA (read-only); preenchido = do profissional
    baseado_em_id   BIGINT UNSIGNED NULL,    -- aponta p/ o modelo de fábrica de origem
    nome            VARCHAR(120) NOT NULL,   -- "Evolução enxuta", "Devolutiva calorosa", "Escolar formal"
    instrucoes      LONGTEXT NULL,           -- system prompt editável
    tom             VARCHAR(40) NULL,        -- acolhedor / tecnico / direto / detalhado
    temperatura     DECIMAL(2,1) NULL,
    limite_palavras SMALLINT UNSIGNED NULL,
    padrao          BOOLEAN NOT NULL DEFAULT FALSE,
    ativo           BOOLEAN NOT NULL DEFAULT TRUE,
    created_at TIMESTAMP NULL, updated_at TIMESTAMP NULL
);

CREATE TABLE modelos_ia_versoes (   -- histórico p/ desfazer
    id          BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    modelo_id   BIGINT UNSIGNED NOT NULL,
    instrucoes  LONGTEXT NULL,
    tom         VARCHAR(40) NULL,
    params_json JSON NULL,
    criado_em   TIMESTAMP NULL
);

"Voltar ao padrão" (trivial e seguro): os modelos de fábrica (profissional_id = NULL) nunca são alterados. Editar cria/atualiza a cópia do profissional. Reverter = copiar o texto da fábrica de volta (via baseado_em_id) ou restaurar uma modelos_ia_versoes anterior. O original nunca se perde.

"Alterar na conversa": o chat tem um seletor do modelo ativo + ajuste rápido de tom. Trocar afeta as próximas gerações; gravamos modelo_id (e tom) na sessao.

Como modelo de IA e tipo de documento se combinam

Conceitos separados que se compõem na hora de gerar:

  • Conversa: [modelo_ia ativo] + camadas de conhecimento.
  • Documento: [modelo_ia ativo: persona/tom][tipo_documento: estrutura/seções] + conhecimento. O modelo dá a voz; o tipo de documento dá a forma.

Peça 3 — Correções viram conhecimento (perguntar a cada vez)

Quando a IA escreve algo e o profissional corrige, um botão "corrigir / ensinar" captura o texto e pergunta o escopo:

┌ Esta correção vale para… ─────────────┐
│  ( ) Só este paciente   → conhecimento_ia(escopo=prontuario, tipo=correcao)
│  ( ) Sempre (meu padrão)→ conhecimento_ia(escopo=profissional, tipo=correcao)
│  ( ) Só desta vez       → não persiste
└────────────────────────────────────────┘

Aprendizado sem fine-tuning: a correção entra na camada certa e é injetada nas próximas montagens. Como é só ativo=true/false, dá para revogar depois, numa tela "o que a IA aprendeu".

Memória ao longo das sessões (compactação)

O relatório usa "todo o conhecimento", mas não empilhamos sessões cruas:

  • Cada sessão finalizada gera resumo_sessao.
  • O prontuário mantém uma síntese rolante (sintese_avaliacao, plano_terapeutico). Quando o histórico cresce, sessões antigas são compactadas na síntese (memory compaction) por uma chamada de IA dedicada.
  • O Montador usa: síntese do prontuário + resumos recentes + resultados de protocolos + conhecimento_ia ativo do prontuário. Tudo pseudonimizado.

Isolamento (o ponto crítico)

  • Toda linha carrega profissional_id e, quando clínica, prontuario_id.
  • O Montador puxa somente: escopo=sistema + profissional_id = auth('profissional')->id() + prontuario_id = atual. Nada cruza entre pacientes nem entre tenants.
  • fato_clinico/correcao de paciente vivem só no prontuário — a base de um paciente nunca entra na conversa de outro.
  • Modelos de fábrica são compartilhados mas read-only; qualquer edição vira cópia privada do tenant.
  • Pseudonimização preservada: conhecimento clínico vai ao LLM, então segue a regra do montarEntrada (refere codigo_anonimo, nunca nome real).
  • Testes: estender IsolamentoMultiTenantTest — intruso → 404 em modelo/conhecimento; e um teste afirmando que conhecimento do prontuário A nunca aparece no prompt montado para o prontuário B.

Serviço novo: MontadorDeContexto

Centraliza a montagem (hoje espalhada em GroqLlmService::montarEntrada). Entrada: a sessão/relatório + o modelo ativo. Saída: o array de mensagens já em camadas e pseudonimizado. gerarDocumento() e o chat passam a chamá-lo. É o único lugar que lê conhecimento_ia/modelos_ia — fácil de auditar para isolamento.

Verificação (Fase 21)

  • Editar um modelo, gerar, voltar ao padrão e confirmar o texto de fábrica de volta.
  • Trocar o modelo no meio da conversa e ver o tom mudar na próxima geração.
  • Corrigir no chat com escopo "só este paciente" e confirmar que a correção entra no próximo relatório daquele paciente e não no de outro.
  • Teste de isolamento: conhecimento do prontuário A ausente no prompt do prontuário B; intruso → 404.
  • Auditar o payload: só PAC-XXXX, nunca nome real.
16

Pendências por decisão

Tudo que depende de uma decisão ou ação sua para avançar. O desenvolvimento das funcionalidades (Fases 0–21) está concluído; o que resta aqui é decisão de produto, jurídico, comercial ou infraestrutura. Atualizado em 24/06/2026.

Legenda de quem decide: [CLIENTE] decisão de negócio · [JURÍDICO] · [INFRA] ação técnica que exige acesso/credencial sua · [DEV] já resolvido ou resolvível sem você assim que a decisão sair.


1. Voz clonada (Fase 9) — PARADA por decisão sua

Situação: código 100% pronto (upload de voz + consentimento, TextToSpeechProvider trocável, GerarAudioResumoJob em fila, player/download). Falta ativar. Bloqueios:

  • [CLIENTE] Escolher o provider: XTTS via Hugging Face (grátis, instável — bom para validar) vs. ElevenLabs (pago/estável — recomendado p/ produção, IMPLEMENTADO 25/06: classe ElevenLabsProvider, TTS_PROVIDER=elevenlabs). A camada já é trocável.
  • [INFRA] Ativar o provider escolhido no .env: ou HF_XTTS_SPACE_URL (XTTS, hoje vazio) ou ELEVENLABS_API_KEY + TTS_PROVIDER=elevenlabs (requer plano ElevenLabs com Instant Voice Cloning).
  • [INFRA] Ligar o worker da fila (docs/deploy-queue-worker.ini → Supervisor, requer sudo). É pré-requisito de TODA geração de áudio, independente do provider.
  • [JURÍDICO] Licença do XTTS v2 (Coqui CPML) é não-comercial — para cobrar pelo SaaS, validar licença ou migrar para provider comercial.
  • [JURÍDICO] Voz clonada = dado biométrico (LGPD Art. 11) — consentimento explícito do profissional (campo já existe) e, idealmente, aviso aos pais de que o áudio é sintético.

Recomendação: provider pago barato para produção; XTTS só para um piloto curto.


2. Billing / cobrança — fase futura

Situação: sem auto-cadastro; o fluxo é landing → assinatura → conta provisionada. Hoje o botão "Assinar" abre um mailto:. Não há checkout real. Bloqueios:

  • [CLIENTE] Escolher o provider de pagamento (Stripe/Pagar.me/Asaas/Mercado Pago…). Planejar atrás de interface trocável, como IA e voz.
  • [CLIENTE] Modelo de cobrança: assinatura mensal por profissional? Plano Clínica? (a landing já mostra R$97/Profissional e Clínica sob consulta).
  • [CLIENTE] Onboarding pós-assinatura + captura de consentimento LGPD (hoje o consentimento era no registro, que foi removido — precisa migrar para o onboarding ou para os termos da assinatura).

3. Go-live (produção)

Situação: app no ar em https://relatatea.clsolucoes.com como preview (APP_ENV=local, APP_DEBUG=true). Bloqueios:

  • [INFRA/DEV] Virar APP_ENV=production e APP_DEBUG=false no .env (+ optimize).
  • [CLIENTE] Definir a ordem final: o plano combinado é Voz → Go-live → Billing (decisão 19/06).
  • [INFRA] Conta demo na base viva ainda é [email protected] (o seeder já aponta para [email protected]; muda só em reseed). Diretório/usuário/banco mantêm o nome interno antigo (invisível ao usuário) — decisão de baixo risco já tomada.

4. CBO e conselhos por especialidade (Fase 19)

Situação: CBO deriva da especialidade (mapa em Profissional::CBO_POR_ESPECIALIDADE), usado no PDF. Decidido (24/06):psicopedagogia adicionada às especialidades; ✅ ABA usa o CBO de Psicólogo (2515-10/CRP) (não tem código próprio). Pendência:

  • [CLIENTE/JURÍDICO] Conferir os códigos CBO oficiais antes do go-live (Fono 2238-10, Psicologia 2515-10, T.O. 2239-05, Psicopedagogia 2394-25). Psicopedagogia não tem conselho federal próprio (campo conselho fica vazio) — confirmar como exibir.

5. Entrega do resumo aos pais

Situação: hoje só download (o profissional baixa o mp3/PDF e envia no WhatsApp). Bloqueio:

  • [CLIENTE] Quer entrega por link, WhatsApp ou e-mail integrados? Define trabalho futuro (a UI já sinaliza "em breve").

6. Assinatura / carimbo digital no PDF

Situação: o PDF leva nome real + ocupação/CBO/registro e uma linha de assinatura manual. Bloqueio:

  • [CLIENTE] O profissional terá assinatura/carimbo digital (validade junto a conselhos/convênios)? Impacta o template do PDF.

7. Decisões técnicas menores (não bloqueiam o piloto)

  • [DEV] numero de sessão sob concorrência: hoje max(numero)+1; sob carga simultânea, usar transação/lock. Baixo risco no uso atual (1 profissional por vez no mesmo paciente).
  • [CLIENTE] Análise de imagem pela IA: fora de escopo (modelo é texto-puro; fotos são só documentação armazenada, com EXIF removido). Confirmar que segue fora.

8. Checklist técnico de go-live (auditoria pré-go-live, 24/06/2026)

Uma auditoria multi-agente do app inteiro confirmou 25 pontos. Os de código já foram corrigidos (pseudonimização do texto livre/transcrição antes da LLM via App\Services\Pseudonimizador; eliminação de arquivos órfãos ao excluir paciente; síntese do prontuário deixou de congelar após 20 sessões; resposta vazia da LLM não vira sucesso; filtros profissional_id defensivos). O que resta é ação sua:

  • [INFRA] .env de produção (hoje APP_ENV=local, APP_DEBUG=true): virar para APP_ENV=production + APP_DEBUG=false (com debug ligado, uma exceção expõe stack trace + segredos). Depois php artisan config:cache.
  • [INFRA] Rotacionar segredos que circularam em texto puro: GROQ_API_KEY (console.groq.com), senha do MariaDB (DB_PASSWORD), e avaliar APP_KEY (trocar invalida sessões/dados cifrados — planejar). HF_TOKEN idem.
  • [INFRA] SESSION_SECURE_COOKIE=true (app é HTTPS-only) e LOG_LEVEL=warning (hoje debug — reduz superfície de vazamento em log).
  • [INFRA] Conta demo: NÃO rodar DemoSeeder em produção (cria login conhecido demo@... / RelataDemo2026). Para o piloto, trocar a senha ou remover a conta.
  • Consentimento LGPD — mecanismo IMPLEMENTADO em código (24/06); falta o TEXTO LEGAL:
    • Responsável pelo MENOR (Art. 11/14): checkbox obrigatório no cadastro do paciente grava pacientes.consentimento_responsavel_em. Pacientes do piloto já receberam backfill.
    • Profissional: banner de aceite em Meu perfil grava consentimento_lgpd_em.
    • [CLIENTE/JURÍDICO] pendente: redigir o texto do termo de uso / política de privacidade (o checkbox/banner hoje têm texto-resumo placeholder) e linká-lo; idealmente bloquear o uso até o aceite do profissional (gate de onboarding).
  • [CLIENTE/JURÍDICO] Transferência internacional: áudio/texto vão à Groq (EUA). Mencionar na política de privacidade/consentimento (LGPD Art. 33).
  • [DEV/INFRA] Custo de IA na finalização: finalizar uma sessão faz 4 chamadas Groq (relatório + planejamento + resumo + síntese), sequenciais. O rate-limit conta 1 por finalização — a cota/custo real é ~4x. Decidir se ajusta o limite, paraleliza ou move parte para fila quando o volume crescer (hoje OK para piloto).
  • [DEV] Gerações presas: comando php artisan relatorios:reset-gerando reverte relatórios/resumos travados em "gerando" (> 15 min) para estado recuperável. Já agendado a cada 15 min em routes/console.phpbasta cron de schedule:run no servidor: * * * * * cd /caminho && php artisan schedule:run >> /dev/null 2>&1.

Bloco .env para produção (copiar e ajustar)

APP_ENV=production
APP_DEBUG=false
APP_URL=https://relatatea.clsolucoes.com
LOG_LEVEL=warning
SESSION_SECURE_COOKIE=true
# Rotacionar TODOS estes (circularam em texto puro):
APP_KEY=base64:<novo via `php artisan key:generate --show`>
GROQ_API_KEY=<nova em console.groq.com>
DB_PASSWORD=<nova senha do MariaDB>
HF_TOKEN=<novo se for ativar voz>

Após editar: sudo -u relat3058 php artisan config:cache. Não rodar DemoSeeder em produção (cria login conhecido). Conferir que um erro forçado mostra página genérica (não o Whoops com stack trace).

9. Residuais aceitos (verificação de completude, 24/06/2026)

Uma 2ª passada (verificar a remediação) fechou mais gaps em código — pseudonimização na fronteira da memória (blocoMemoria + compactarSinteseProntuario, cobre dado legado), correção de escopo profissional pseudonimizada, MP3 anterior apagado ao refazer áudio, exclusão de profissional limpa voz+filhos, e badge de status correto. Restam, conscientemente aceitos:

  • [ACEITO] Pseudonimização é best-effort por nome exato: troca o nome do paciente (tokens ≥ 3 letras + nome completo) por PAC-XXXX. Não pega apelidos/diminutivos ("Tuca" para "Arthur") nem erros de digitação. A garantia primária continua sendo o uso do codigo_anonimo nos campos estruturados; isto é defesa-em-profundidade sobre texto livre. Orientar o profissional a usar o código nas notas reduz o resíduo.
  • [ACEITO/GOVERNANÇA] Áudio bruto → Groq: o nome falado no áudio enviado ao Whisper não é mascarável antes da transcrição (item 8, transferência internacional). Tratar por contrato de operador (DPA) + consentimento, não por código.
  • [OPCIONAL] Status preso em 'gerando': se o PHP for morto no meio da geração síncrona, o relatório pode ficar 'gerando'. É recuperável (regenerar). Melhoria futura: comando artisan relatorios:reset-gerando (reverte itens presos há > N min).

Resumo do que destrava o quê

Para… Você precisa decidir/agir
Ativar a voz provider (1) + HF_XTTS_SPACE_URL + ligar worker (sudo) + licença
Cobrar provider de pagamento + modelo de planos + onboarding/LGPD
Go-live virar APP_ENV=production + ordem das frentes
PDF oficial conferir CBO + decidir assinatura digital
Entrega aos pais download (atual) ou link/WhatsApp/e-mail
17

Fluxo de testes

Roteiro para validar as funcionalidades principais ponta a ponta. Atualizado em 26/06/2026.

Acesso


1. Login e painel

  1. Acesse a URL → Entrar → use as credenciais demo.
  2. No Painel, confira as métricas (Pacientes, Relatórios, Resumos p/ pais).
  3. Topbar: navegue por Painel · Pacientes · Aprendizado da IA · Personas · Meu perfil.

Esperado: dashboard carrega com números reais; sem textos técnicos/emojis.


2. Pacientes

  1. PacientesNovo paciente (botão com ícone +).
  2. Preencha nome, nascimento, nível de suporte (terminologia DSM-5: Exige apoio / substancial / muito substancial), CID, responsável.
  3. Marque o consentimento do responsável (obrigatório) e salve.
  4. Na lista, use a busca (nome ou código anônimo) e abra Abrir prontuário.

Esperado: o nome real só aparece na ficha; a IA usa o código anônimo (ex.: PAC-XXXX).


3. Prontuário (timeline)

Na página do paciente, a seção Prontuário é uma timeline única (cronológica):

  • Sessões e relatórios avulsos no mesmo feed, por data.
  • O relatório final de uma sessão aparece aninhado sob ela.
  • Bloco "Metas mais trabalhadas" quando há histórico.

Botões: + Nova sessão (destaque) e Novo relatório (avulso).


4. Sessão + protocolos de avaliação

  1. No prontuário → + Nova sessão (abre o estúdio).
  2. Coluna esquerda → Tipo de sessão → escolha Avaliação.
  3. Coluna direita → painel "Protocolos de avaliação" aparece.
    • O seletor é filtrado por especialidade + idade do paciente.
    • Escolha um protocolo (ex.: para fono em criança pequena: ABFW) → Aplicar.
  4. Registro estruturado: quando o protocolo tem dimensões (ex.: IAR → 13 áreas), marque cada uma com o seletor rápido (OK / Parcial / Déficit, ou a escala própria do protocolo) + nota; senão, use o texto livre.
  5. Conduza a sessão pelo chat: texto, áudio (gravar/anexar → transcrição) e foto (anexo).
  6. Finalizar sessão → gera o relatório técnico + planejamento da próxima.

Esperado: o relatório cita "conforme o protocolo X" usando seus dados, sem reproduzir o instrumento. Catálogo com 62 protocolos ativos (psicopedagogia, fono, T.O., psicologia, ABA, gerais).

Onde aplicar protocolos = dentro de uma sessão do tipo Avaliação. Não há tela separada.


5. Relatório + PDF

  1. No prontuário, abra um relatório (final de sessão ou avulso).
  2. Ajuste seletores/observações → Gerar relatório com IA (Groq).
  3. Confira o texto técnico gerado (pseudonimizado).
  4. Baixar PDF → o PDF leva o nome real do paciente + ocupação/CBO/registro do profissional.

6. Resumo para os pais (texto + áudio)

No card de áudio (lado direito do relatório):

  1. Gerar resumo para os pais → a IA escreve o roteiro acolhedor (segundos).
  2. Gerar áudio → gera o MP3 e mostra o player + Baixar mp3.
    • Provider de voz atual: Piper (voz de catálogo PT-BR) — rápido (~segundos), grátis.
    • Aparece a nota "Áudio em voz padrão do sistema. Clonagem da sua voz: em breve."
    • Durante a geração: barra de progresso + botão Cancelar geração.

Esperado: áudio em português natural em poucos segundos.

Voz clonada do profissional — Em breve

  • Meu perfil → Minha voz: marcado "Em breve", com a lista de modelos previstos (ElevenLabs, CosyVoice 2, F5-TTS, XTTS local, Piper).
  • A gravação por microfone / upload está visível mas desabilitada até a clonagem ser ativada.

7. Base de conhecimento e personas da IA

  • Aprendizado da IA (/ia/conhecimento): ensine preferências de escrita; reveja/revogue (por paciente ou geral).
  • Personas (/ia/modelos): troque o tom da IA; edite/crie a partir das personas de fábrica; "voltar ao padrão".
  • No estúdio: o botão Corrigir / ensinar a IA vira conhecimento (com escopo: só este paciente / sempre / só desta vez).

8. Configuração de voz (infra — referência técnica)

Provider ativo via .envTTS_PROVIDER:

Valor Modelo Clona voz? Status
piper (atual) Piper PT-BR não (voz padrão) ✅ ativo
elevenlabs ElevenLabs sim requer chave paga (Starter US$5)
local_xtts XTTS v2 local sim grátis, porém lento na CPU
hf_xtts XTTS via HF Space sim requer HF_XTTS_SPACE_URL

Catálogo de modelos exibido na UI: config('services.tts.modelos').

Pré-requisitos de geração de áudio:

  • Worker da fila: systemctl status relatatea-worker (systemd, roda como relat3058).
  • Cron: schedule:run no crontab do relat3058 (destrava itens presos via relatorios:reset-gerando).
  • Piper: binário e voz em /opt/relatatea-tts/piper/ (PIPER_BIN/PIPER_MODEL/PIPER_LIB).

Para ativar a clonagem (voz do profissional): assinar ElevenLabs (ou subir um modelo open em GPU), setar ELEVENLABS_API_KEY + TTS_PROVIDER=elevenlabs, php artisan config:clear, systemctl restart relatatea-worker. A UI de "Minha voz" e o gate de cadastro de voz reativam automaticamente.


Observações

  • Áudio do Piper é WAV servido como .mp3 (toca normalmente nos navegadores/players).
  • Tudo que vai à IA é pseudonimizado (nome real → PAC-XXXX); fotos nunca vão à IA.
  • Rodar artisan sempre como sudo -u relat3058 /usr/bin/php artisan ....
18

Termos & LGPD

⚠️ MINUTA SUJEITA A REVISÃO JURÍDICA — não substitui parecer de advogado. Este material é um modelo-base. Antes de qualquer uso, deve ser revisado por profissional do Direito habilitado, adequado à realidade da operação e às normas do conselho de classe aplicável.


Versão: [Nº DA VERSÃO] — Vigência a partir de: [DATA]

Este Termo de Aceite ("Termo") regula o uso da plataforma RelataTEA ("Plataforma"), software como serviço (SaaS) operado por [RAZÃO SOCIAL], inscrita no CNPJ sob nº [CNPJ], com sede em [ENDEREÇO] ("RelataTEA", "nós"), por profissionais de saúde habilitados (fonoaudiólogos, psicólogos, terapeutas ocupacionais, psicopedagogos, analistas do comportamento/ABA e demais profissionais correlatos) ("Profissional", "você").

A Plataforma destina-se à geração de relatórios clínicos de pacientes com Transtorno do Espectro Autista (TEA), muitos dos quais crianças e adolescentes, a partir de informações inseridas pelo Profissional, incluindo transcrição de áudios e geração assistida de texto por inteligência artificial.

Ao marcar o aceite eletrônico, criar conta ou utilizar a Plataforma, você declara que leu, compreendeu e concorda com este Termo.

1. Finalidade

A Plataforma tem por finalidade auxiliar o Profissional na documentação clínica e na elaboração de relatórios, resumos e registros referentes ao acompanhamento de pacientes com TEA, incluindo: registro de evolução, transcrição de áudios de sessão, organização de anexos (fotos e áudios) e geração assistida de texto por inteligência artificial.

2. Papéis das partes (controlador e operador) — LGPD Art. 5º, VI e VII; Art. 39

2.1. O Profissional é, em regra, o CONTROLADOR dos dados pessoais de seus pacientes, pois é quem decide sobre a finalidade e os meios do tratamento, no exercício da relação clínica.

2.2. O RelataTEA atua como OPERADOR, realizando o tratamento de dados em nome e segundo as instruções do Profissional, limitado às finalidades desta Plataforma.

2.3. Quanto aos dados cadastrais do próprio Profissional (nome, registro no conselho, e-mail, dados de pagamento), o RelataTEA atua como CONTROLADOR, conforme a Política de Privacidade.

2.4. O RelataTEA tratará os dados dos pacientes somente conforme as instruções do Profissional e este Termo, não os utilizando para finalidades próprias diversas, ressalvadas obrigações legais e regulatórias.

3. Obrigações do Profissional (na qualidade de Controlador)

São responsabilidades exclusivas do Profissional:

a) Obter, registrar e conservar as bases legais adequadas para o tratamento dos dados de seus pacientes, em especial o consentimento do paciente ou, no caso de menores, de ao menos um dos pais ou do responsável legal (vide o "Termo de Consentimento do Responsável", disponibilizado como modelo); b) Garantir que possui vínculo profissional legítimo com o paciente e que atua dentro de suas competências e do seu conselho de classe; c) Inserir dados corretos, atualizados e estritamente necessários à finalidade clínica (minimização); d) Revisar criticamente todo conteúdo gerado por IA antes de qualquer uso clínico ou entrega — a IA é ferramenta de apoio e não substitui o julgamento profissional; a responsabilidade técnica pelo relatório final é exclusiva do Profissional; e) Informar adequadamente seus pacientes/responsáveis sobre o uso da Plataforma, o emprego de IA, a pseudonimização e a transferência internacional descritos neste Termo; f) Manter a confidencialidade de suas credenciais de acesso e respeitar o sigilo profissional; g) Atender, como Controlador, às requisições de direitos dos titulares (Seção 8), podendo solicitar apoio operacional ao RelataTEA.

4. Dados tratados

A Plataforma poderá tratar, conforme inserção do Profissional:

  • Dados de identificação do paciente: nome, data de nascimento, dados do responsável legal;
  • Dados pessoais sensíveis de saúde (LGPD Art. 5º, II; Art. 11): diagnóstico, evolução clínica, anotações de sessão, hipóteses, condutas;
  • Anexos: fotos e áudios de sessões;
  • Dados cadastrais do Profissional: nome, registro de conselho, e-mail, dados de cobrança;
  • Opcionalmente, amostra de voz do próprio Profissional (dado biométrico), objeto de termo específico e separado (Termo 3).

Tratamento de fotos: os metadados EXIF das fotos (que podem conter geolocalização, data e dados do dispositivo) são removidos no processamento. Fotos NUNCA são enviadas à inteligência artificial.

5. Base legal

5.1. Para os dados sensíveis de saúde dos pacientes, o tratamento se fundamenta no consentimento específico e destacado do titular ou responsável (LGPD Art. 11, I) e/ou na hipótese de tutela da saúde, em procedimento realizado por profissionais de saúde (LGPD Art. 11, II, "f"), conforme avaliação do Profissional-Controlador.

5.2. Para dados de crianças e adolescentes, observa-se o LGPD Art. 14, exigindo-se consentimento específico de ao menos um dos pais ou do responsável legal, sempre no melhor interesse da criança/adolescente.

5.3. Para os dados cadastrais do Profissional, as bases são a execução de contrato (Art. 7º, V), o cumprimento de obrigação legal/regulatória (Art. 7º, II) e o legítimo interesse (Art. 7º, IX), quando cabível.

6. Uso de inteligência artificial e transferência internacional de dados — LGPD Art. 33

6.1. A Plataforma utiliza serviços de inteligência artificial de terceiros para: (i) transcrição de áudios (modelo Whisper, via Groq) e (ii) geração de relatórios e resumos de texto (modelos da família Llama, via Groq).

6.2. Esses processamentos ocorrem em servidores localizados nos Estados Unidos da América, configurando transferência internacional de dados nos termos do LGPD Art. 33.

6.3. Pseudonimização (LGPD Art. 5º, XI; Art. 13): antes do envio à IA, o nome real do paciente é substituído por um código anônimo, de modo que os dados remetidos ao serviço de IA são pseudonimizados. O reidentificador é mantido no ambiente do RelataTEA, no Brasil.

6.4. Fotos não são enviadas à IA em nenhuma hipótese.

6.5. A transferência internacional observa as garantias do Art. 33 (entre elas cláusulas contratuais, salvaguardas de segurança e/ou consentimento específico e destacado do titular, conforme o caso). O RelataTEA buscará adotar instrumentos compatíveis e fornecedores que ofereçam grau de proteção adequado.

6.6. Cabe ao Profissional informar e, quando exigível, obter consentimento de seus pacientes/responsáveis quanto a esse uso de IA e à transferência internacional, conforme o Termo 2.

7. Armazenamento, segurança e retenção

7.1. Os dados são armazenados em infraestrutura localizada no Brasil, com medidas técnicas e administrativas de segurança (LGPD Art. 46), como controle de acesso e criptografia em trânsito.

7.2. Guarda de prontuário: os registros de natureza clínica devem observar os prazos de guarda de prontuário fixados pelo respectivo conselho de classe do Profissional (a exemplo de CFM, CFP, CFFa e outros), cuja guarda mínima costuma ser de cerca de 20 (vinte) anos, conforme a norma aplicável. O Profissional é o responsável pela definição e cumprimento do prazo de guarda, devendo consultar a regulamentação do seu conselho.

7.3. Encerrada a relação contratual, o RelataTEA disponibilizará a exportação dos dados e procederá à eliminação ou anonimização conforme instrução do Profissional, ressalvadas as hipóteses legais de conservação (LGPD Art. 16).

8. Direitos dos titulares — LGPD Art. 18

Os titulares (pacientes/responsáveis) têm direito a: confirmação da existência de tratamento; acesso; correção de dados incompletos, inexatos ou desatualizados; anonimização, bloqueio ou eliminação de dados desnecessários, excessivos ou tratados em desconformidade; portabilidade; eliminação dos dados tratados com consentimento; informação sobre compartilhamento; e revogação do consentimento. As requisições devem ser dirigidas, em primeiro plano, ao Profissional-Controlador, que poderá acionar o suporte operacional do RelataTEA.

9. Subcontratação (suboperadores)

O Profissional autoriza o RelataTEA a empregar suboperadores estritamente necessários à prestação do serviço (infraestrutura de nuvem, serviços de IA mencionados na Seção 6), mantendo-se responsável por exigir deles padrões de proteção compatíveis.

10. Incidentes de segurança

Em caso de incidente que possa acarretar risco ou dano relevante aos titulares, o RelataTEA comunicará o Profissional sem demora injustificada, prestando informações para que este, como Controlador, avalie a comunicação à ANPD e aos titulares (LGPD Art. 48).

11. Encarregado pelo Tratamento de Dados (DPO)

Encarregado do RelataTEA: [ENCARREGADO/DPO: nome e e-mail].

12. Disposições gerais

12.1. Este Termo pode ser atualizado; alterações relevantes serão comunicadas. O uso continuado após a comunicação implica concordância. 12.2. Fica eleito o foro da Comarca de [COMARCA/UF], salvo norma de proteção mais favorável ao consumidor/titular.

Declaro que li e aceito este Termo.

Profissional: [NOME] — Conselho/Registro: [CONSELHO Nº] — CPF: [CPF] Data e hora do aceite: [REGISTRO ELETRÔNICO]


TERMO 2 — TERMO DE CONSENTIMENTO DO RESPONSÁVEL PELO PACIENTE MENOR

(Tratamento de dados pessoais sensíveis de saúde de criança/adolescente)

Versão: [Nº DA VERSÃO] — Data: [DATA]

Identificação

Paciente (menor): [NOME DO PACIENTE] — Data de nascimento: [DATA] Responsável legal: [NOME DO RESPONSÁVEL] — CPF: [CPF] — Vínculo: ( ) mãe ( ) pai ( ) responsável legal: [QUAL] Profissional responsável (Controlador): [NOME DO PROFISSIONAL] — Conselho/Registro: [CONSELHO Nº] Plataforma utilizada: RelataTEA, operada por [RAZÃO SOCIAL], CNPJ [CNPJ] (Operadora).

Este documento é redigido em linguagem clara para que você compreenda como os dados de saúde do(a) menor sob sua responsabilidade serão tratados.

1. Finalidade

Autorizo o tratamento dos dados pessoais e dos dados sensíveis de saúde do(a) paciente acima identificado(a) para a finalidade de acompanhamento clínico e elaboração de relatórios, evoluções e resumos relacionados ao Transtorno do Espectro Autista (TEA), com o apoio da plataforma RelataTEA.

2. Base legal — LGPD Art. 11 e Art. 14

O tratamento se fundamenta:

  • No consentimento específico e destacado previsto no Art. 11, I, da LGPD, para dados sensíveis de saúde; e/ou na tutela da saúde por profissional de saúde (Art. 11, II, "f");
  • No Art. 14 da LGPD, que exige consentimento de ao menos um dos pais ou do responsável legal para o tratamento de dados de crianças e adolescentes, sempre realizado no melhor interesse do(a) menor.

Na qualidade de responsável legal, declaro que sou competente para consentir em nome do(a) menor.

3. Dados tratados

  • Identificação do(a) paciente e do responsável;
  • Dados de saúde: diagnóstico, histórico, evolução, anotações de sessão e informações clínicas relacionadas ao TEA;
  • Anexos, quando aplicável: fotos e áudios de sessões.

Sobre as fotos: os metadados das fotos (como localização e data) são removidos, e as fotos NUNCA são enviadas à inteligência artificial.

4. Uso de inteligência artificial, pseudonimização e transferência internacional — LGPD Art. 33

Estou ciente e concordo que:

4.1. A plataforma utiliza inteligência artificial de terceiros para transcrever áudios e auxiliar na redação de relatórios e resumos.

4.2. Esse processamento ocorre em servidores localizados nos Estados Unidos, havendo, portanto, transferência internacional de dados (LGPD Art. 33).

4.3. Antes de qualquer envio à inteligência artificial, o nome real do(a) paciente é substituído por um código anônimo (pseudonimização), de forma que o serviço de IA não recebe o nome real do(a) menor.

4.4. As fotos não são enviadas à inteligência artificial.

4.5. O conteúdo gerado pela IA é sempre revisado pelo profissional, que é o responsável técnico pelo relatório final.

( ) Li e concordo com o uso de inteligência artificial pseudonimizada e com a transferência internacional de dados acima descritos.

5. Compartilhamento

Os dados poderão ser compartilhados apenas: (i) com os prestadores de tecnologia estritamente necessários ao funcionamento da plataforma (infraestrutura de nuvem e serviços de IA citados); (ii) com você, responsável legal, mediante solicitação; (iii) quando houver obrigação legal ou ordem de autoridade competente. Não há venda de dados nem uso para publicidade.

6. Armazenamento e retenção

6.1. Os dados são armazenados em infraestrutura no Brasil, com medidas de segurança.

6.2. Por se tratar de registro clínico, os dados podem ser conservados pelo prazo de guarda de prontuário exigido pelo conselho profissional aplicável — guarda que, em regra, é de cerca de 20 (vinte) anos —, mesmo após eventual revogação do consentimento, exclusivamente para cumprimento de obrigação legal/regulatória (LGPD Art. 16, I).

7. Direitos do titular e do responsável — LGPD Art. 18

Você pode, a qualquer tempo, solicitar: confirmação do tratamento; acesso aos dados; correção; anonimização, bloqueio ou eliminação de dados desnecessários ou excessivos; portabilidade; eliminação dos dados tratados com base no consentimento (ressalvada a guarda legal de prontuário); informação sobre compartilhamentos; e revogação do consentimento.

8. Forma de revogação

8.1. O consentimento pode ser revogado a qualquer momento, de forma gratuita e facilitada, mediante solicitação ao profissional responsável [CONTATO DO PROFISSIONAL] ou ao Encarregado [ENCARREGADO/DPO: nome e e-mail].

8.2. A revogação não afeta a licitude do tratamento realizado antes dela e não impede a conservação do prontuário pelo prazo legal (item 6.2).

9. Contato do Encarregado (DPO)

[ENCARREGADO/DPO: nome e e-mail].

10. Consentimento

Declaro que li, compreendi e fui informado(a) sobre o tratamento dos dados de saúde do(a) menor, inclusive sobre o uso de IA pseudonimizada e a transferência internacional, e CONSINTO LIVRE, INFORMADA E ESPECIFICAMENTE com o tratamento descrito.

Local e data: [LOCAL], [DATA] Assinatura do responsável legal: __________________________________ Nome: [NOME] — CPF: [CPF] (Assinatura física ou eletrônica / registro de aceite: [REGISTRO])


TERMO 3 — TERMO DE CONSENTIMENTO DE CLONAGEM DE VOZ DO PROFISSIONAL

(Tratamento de dado pessoal sensível biométrico — amostra de voz)

Versão: [Nº DA VERSÃO] — Data: [DATA]

Titular (Profissional): [NOME] — CPF: [CPF] — Conselho/Registro: [CONSELHO Nº] Controlador deste tratamento específico: [RAZÃO SOCIAL], CNPJ [CNPJ] (RelataTEA).

Importante: este consentimento é específico, separado e opcional. Não é necessário para o uso geral da plataforma RelataTEA. Trata-se da voz do PROFISSIONAL, jamais da voz do paciente.

1. Finalidade

Autorizar o uso de uma amostra da minha voz para criação de um modelo de voz sintetizada ("clonagem de voz"), com a finalidade exclusiva de gerar resumos em áudio (por exemplo, orientações e sínteses destinadas aos pais/responsáveis dos pacientes), reproduzidos na minha voz.

2. Base legal — LGPD Art. 11, I

A voz, quando utilizada para este fim de identificação/reprodução vocal, é tratada como dado pessoal sensível de natureza biométrica (LGPD Art. 5º, II). A base legal é o consentimento específico e destacado do titular, nos termos do Art. 11, I, da LGPD.

3. Dados tratados

  • Amostra(s) de áudio da minha voz fornecida(s) por mim;
  • Modelo/representação vocal derivado (parâmetros do modelo de voz);
  • Áudios sintetizados gerados a partir do modelo.

4. Compartilhamento e transferência internacional — LGPD Art. 33

4.1. ( ) O processamento de síntese de voz poderá envolver fornecedor de tecnologia localizado no exterior, hipótese em que haverá transferência internacional de dados (LGPD Art. 33), com adoção das salvaguardas cabíveis. (Marque/preencha conforme a arquitetura efetiva: [INDICAR FORNECEDOR E PAÍS], se aplicável.)

4.2. A amostra de voz e o modelo não serão usados para finalidade diversa da descrita, nem comercializados, nem cedidos a terceiros para fins próprios.

5. Armazenamento, segurança e retenção

5.1. A amostra e o modelo de voz são armazenados com medidas de segurança (LGPD Art. 46) e mantidos apenas enquanto durar o consentimento e a finalidade.

5.2. Revogado o consentimento, a amostra de voz e o modelo derivado serão eliminados em prazo razoável, ressalvada eventual obrigação legal de conservação. A eliminação do modelo não afeta os áudios já legitimamente gerados e entregues antes da revogação, salvo solicitação específica.

6. Direitos do titular — LGPD Art. 18

Tenho direito a: confirmação e acesso; correção; eliminação dos dados biométricos e do modelo; portabilidade; informação sobre compartilhamentos; e revogação do consentimento a qualquer tempo.

7. Forma de revogação

A revogação é gratuita e a qualquer momento, mediante solicitação ao Encarregado [ENCARREGADO/DPO: nome e e-mail] ou pelos canais da plataforma [CANAL/CONFIGURAÇÃO DE CONTA]. A revogação interrompe novas gerações de áudio com minha voz e enseja a eliminação da amostra e do modelo (item 5.2). A revogação não afeta a licitude do tratamento anterior.

8. Caráter facultativo e ausência de prejuízo

Estou ciente de que este consentimento é opcional; a recusa não prejudica o uso das demais funcionalidades do RelataTEA.

9. Contato do Encarregado (DPO)

[ENCARREGADO/DPO: nome e e-mail].

10. Consentimento

Declaro que li, compreendi e CONSINTO LIVRE, INFORMADA, ESPECÍFICA E DESTACADAMENTE com o tratamento de amostra da minha voz (dado biométrico) para clonagem/síntese de voz com a finalidade aqui descrita, ciente de minha faculdade de revogá-lo a qualquer tempo.

( ) SIM, autorizo a clonagem de voz. ( ) NÃO autorizo.

Local e data: [LOCAL], [DATA] Assinatura: __________________________________ Nome: [NOME] — CPF: [CPF] (Registro eletrônico de aceite: [REGISTRO])


⚠️ MINUTA SUJEITA A REVISÃO JURÍDICA — não substitui parecer de advogado. Adeque os placeholders, as bases legais escolhidas e os prazos de guarda à norma do conselho de classe aplicável e à efetiva arquitetura técnica antes do uso.

19

Stripe & go-live

Fase 5 (billing) implementada com Laravel Cashier 16 sobre Stripe. A mecânica de domínio (assinaturas/planos/GuardaCota/SaldoVozService) continua sendo a fonte de verdade do enforcement; o Stripe/Cashier é a camada de pagamento e estado da assinatura, projetada no domínio pelo webhook (App\Listeners\SincronizarStripeListenerApp\Services\Pagamento\SincronizadorAssinatura).

O que foi construído

  • Cashier: billable = Profissional (Cashier::useCustomerModel), trait Billable, colunas stripe_id/pm_type/pm_last_four/trial_ends_at + tabelas subscriptions/subscription_items.
  • Planos: coluna planos.stripe_price_id (Price recorrente da Stripe), editável no admin (/admin/planos). Plano sem price = não assinável online.
  • Self-serve público: /assinar/{plano?} cria a conta gated (Assinatura suspensa, origem stripe) + Stripe Checkout (assinatura). O webhook ativa quando o pagamento confirma.
  • Gestão no app: /assinatura — assinar/trocar (swap), portal de cobrança da Stripe, cancelar, e comprar pacotes avulsos de créditos de voz (cobrança única via checkoutCharge).
  • Webhook em POST /stripe/webhook (rota cashier.webhook). Sincroniza assinatura, reseta cota mensal de voz na troca/renovação e credita pacotes avulsos (idempotente por id da sessão de checkout).
  • Termos LGPD: /termos (renderiza docs/17-TERMOS-LGPD.md); links nos pontos de consentimento.

Configuração na Stripe (uma vez)

  1. Conta Stripe → modo Teste primeiro.
  2. Produtos/Preços recorrentes (um Price por plano comercializável), moeda BRL. Copie cada price_… e cole no plano correspondente em /admin/planos (campo Stripe Price ID).
  3. Webhook: Developers → Webhooks → endpoint https://relatatea.clsolucoes.com/stripe/webhook. Eventos mínimos:
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • checkout.session.completed Copie o Signing secret (whsec_…) para STRIPE_WEBHOOK_SECRET.
  4. .env: STRIPE_KEY (pk_…), STRIPE_SECRET (sk_…), STRIPE_WEBHOOK_SECRET (whsec_…). Já existem CASHIER_CURRENCY=brl e CASHIER_CURRENCY_LOCALE=pt_BR.

Em modo teste use os cartões de teste da Stripe (ex.: 4242 4242 4242 4242). Troque para as chaves live só no go-live, com um webhook live separado.

Ativar no servidor (migrations aditivas — requer sua autorização)

As tabelas são aditivas e não alteram dados existentes, mas a migration roda no banco vivo. Rodar como o usuário do app (nunca root) e limpar caches:

sudo -u relat3058 /usr/bin/php artisan migrate --force
sudo -u relat3058 /usr/bin/php artisan config:clear
sudo -u relat3058 /usr/bin/php artisan optimize:clear
# reiniciar o worker para carregar o novo código de billing
sudo systemctl restart relatatea-worker

Backup pré-migration: /tmp/relatatea-pre-stripe-*.sql.

Go-live de produção (passo final — fora deste pacote, por decisão do cliente)

No .env, trocar para produção:

APP_ENV=production
APP_DEBUG=false
LOG_LEVEL=warning
SESSION_SECURE_COOKIE=true

# Stripe LIVE
STRIPE_KEY=pk_live_...
STRIPE_SECRET=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...   # do endpoint LIVE

Depois: config:clear + optimize + reiniciar worker. Rotacionar segredos (GROQ_API_KEY, DB_PASSWORD, APP_KEY se exposto, ELEVENLABS_API_KEY) é ação do cliente — ver docs/15 §8. Não rodar DemoSeeder em produção.

Notas de design

  • Conta self-serve nasce com Assinatura suspensa (não grandfathered) → bloqueada até o webhook confirmar. /assinatura e /conta-suspensa ficam FORA do gate para permitir regularizar.
  • Idempotência: crédito de pacote avulso usa o id da sessão de checkout como job_uuid no ledger (transacoes_voz) — reentrega de webhook não credita em dobro.
  • Reset de cota de voz acontece na troca de plano e na renovação (avanço de current_period_end), espelhando a regra do admin em ContaDetalhe::aplicarPlano.
20

Handoff & estado

Atualize este arquivo ao final de cada sessão de trabalho. É a primeira coisa a ler ao retomar.

Sessão 25-26/06/2026 — Catálogo de protocolos, UI profissional, voz (Piper)

Doc de teste ponta-a-ponta: docs/16-FLUXO-DE-TESTES.md. Suíte 85/85, build OK, site 200. Login demo: [email protected] / RelataDemo2026 (resetado e confirmado).

1) UI / prontuário

  • pacientes.blade: "Abrir histórico" → "Abrir prontuário".
  • PacienteDetalhe virou TIMELINE ÚNICA "Prontuário": funde sessões + relatórios num feed cronológico; relatório FINAL (com sessao_id) aparece aninhado sob a sessão; relatório avulso (whereNull('sessao_id'), rótulo "· avulso") é evento próprio. render() monta $timeline ordenada por data desc.

2) Catálogo de protocolos — 12 → 62 ativos, verificados

  • Gerado por workflow multi-agente (6 geradores por especialidade + verificação na web). Distribuição: psicopedagogia 9, fono 11, T.O. 12, psicologia 13, ABA 11, gerais 6.
  • Correções clínicas: IAR = "Instrumento de Avaliação do Repertório Básico para Alfabetização" (Leite/EDICON 2015), psicopedagogia/Acadêmico (não ABA); "PROAD" → PROADE. Siglas legadas superadas → ativo=false (idempotente no seeder: PROAD/Portage/VABS/Perfil Sensorial/AHEMD/Aval. de linguagem).
  • Migrations: ..._add_dimensoes_to_protocolos_catalogo (json dimensoes+escala_niveis), ..._widen_avalia_referencia_protocolos (TEXT). Model: ESCALA_PADRAO(ok/parcial/deficit), temDimensoes(), escalaNiveis().
  • Registro estruturado por dimensão: protocolo com dimensões → seletor nível+nota por domínio; resultados_json = {modo:'estruturado', escala(snapshot), dimensoes:[{area,nivel,nota}], texto} (retrocompat: chave texto viva; nível validado server-side). GroqLlmService::montarEntrada renderiza por dimensão, pseudonimiza só as notas. Onde aplicar protocolos = dentro de sessão tipo "Avaliação" (coluna 3 do estúdio), filtrado por especialidade + idade.

3) UI profissional (auditoria multi-agente)

  • Terminologia DSM-5 oficial (Paciente::NIVEIS + sessao + construtor): Exige apoio / substancial / muito substancial (era Leve/Moderado/Severo).
  • Emojis removidos de todo o sistema → ícones SVG line ou texto (landing/painel/perfil/pacientes/paciente-detalhe/construtor/estudio). Mantidos só símbolos tipográficos (✓ ✕ ← → ●).
  • Vazamentos de dev p/ usuário removidos (GROQ_API_KEY/.env/"Fase 5/6/9"/voz "clonada"). Tokens de cor novos (--color-sage-deep/line-strong/sage-line). Views ia/* normalizadas. Psicopedagogia na landing. Login gênero-neutro.

4) Voz / TTS — Piper ativo (áudio funcionando), clonagem "Em breve"

  • Arquitetura trocável por TTS_PROVIDER: piper (ATIVO), elevenlabs (pago, codado/testado), local_xtts (grátis/lento), hf_xtts (off). Interface ganhou clona(): bool.
  • Piper (rhasspy, pt_BR-faber-medium, MIT/comercial) em /opt/relatatea-tts/piper/ — voz de catálogo PT-BR, ~4s por resumo (RTF 0,25). PiperProvider roda via Process (stdin→wav). NÃO clona = voz neutra; o Job pula a exigência de voz cadastrada quando !clona().
  • Clonagem da voz do profissional = "Em breve": Perfil → Minha voz desabilitado + lista de modelos (config('services.tts.modelos')). UI do "Gerar áudio" mostra nota "voz padrão; clonagem em breve".
  • Barra de progresso real (frase a frase) + Cancelamento real já implementados (servidor XTTS async + GeracaoCanceladaException + guardas no Job + resumos_pais.progresso). Usados quando o provider reporta progresso.
  • XTTS local: provado, mas inviável nesta CPU compartilhada (~5min/frase); serviço relatatea-tts parado/disabled. PyAV instalado (decodifica webm/mp4 da gravação).
  • Gravação por microfone no Perfil (MediaRecorder→wire:upload), validação mimetypes ampliada (video/webm etc.) — pronta para quando a clonagem ligar.
  • Para ligar clonagem real: ElevenLabs Starter US$5 (ELEVENLABS_API_KEY + TTS_PROVIDER=elevenlabs + config:clear + restart worker) ou modelo open em GPU (CosyVoice 2 / F5-TTS, Apache/comercial; provider a escrever).

5) Infra (root)

  • Worker da fila: systemd relatatea-worker (queue:work database, user relat3058, enabled, --tries=1 --timeout=7200). Pré-requisito de toda geração de áudio.
  • Cron: * * * * * cd <proj> && /usr/bin/php artisan schedule:run no crontab do relat3058 (dispara relatorios:reset-gerando a cada 15min).

Credenciais (sensível — rotacionar no go-live)

  • DB: relatafacil / goPgDlo4coFBHsDIKkuChQh @ 127.0.0.1; root via socket.
  • Groq gsk_… · HF hf_… · ElevenLabs sk_… (free, API bloqueada). APP_KEY no .env.

Sessão 22-23/06/2026 — Rebrand + migração de domínio + Expansão clínica (Fases 14-17)

1) Rebrand RelataFácil → RelataTEA e domínio → relatatea.clsolucoes.com ✅ no ar

  • Marca trocada em todo o app/PDF/CSS/config + e-mails de marca @relatafacil.com → @relatatea.com.
  • Domínio migrado: relatatea.clsolucoes.com criado como child domain do site existente no CyberPanel (reaproveita diretório/usuário/banco — sem migrar arquivos). SSL Let's Encrypt emitido. .env APP_URL/MAIL_FROM virados. Redirect 301 do domínio antigo via public/.htaccess.
  • DNS é Cloudflare (NS jill/clyde.ns.cloudflare.com): registros do *.clsolucoes.com são criados no painel Cloudflare (o servidor não é autoritativo). O CyberPanel tem integração Cloudflare com token inválido (Invalid request headers) — se quiser automação de DNS, atualizar o token no painel.
  • Login demo agora: [email protected] / RelataDemo2026 (mudou de @relatafacil.com). Diretório /home/relatafacil.clsolucoes.com, usuário relat3058 e banco relatafacil mantêm o nome antigo (internos, invisíveis ao usuário).
  • Script de referência: docs/cutover-relatatea.sh. Backups em /tmp/relatatea-db-*.sql.

2) Expansão clínica — prontuário, sessões, IA por sessão (Fases 14-17 ✅ implementadas e validadas ao vivo)

Plano completo em docs/13-PLANO-EXPANSAO.md (Fases 14→21). Docs temáticos: 07 (prontuário/sessões), 08 (protocolos), 09 (modelos relatório/áudio), 10 (CBO), 11 (processo clínico — voz de psicopedagoga), 12 (LGPD-mídia), 14 (base de conhecimento + modelos de IA).

  • Fase 14 — Fundação de dados: tabelas prontuarios (1:1 paciente, estado do ciclo), sessoes (camada de trabalho), anexos (mídia privada por sessão). relatorios_clinicos ganhou sessao_id+tom. Migração de dados aditiva (relatórios viraram sessões). Paciente auto-cria prontuário. Disco anexos + rota anexos.stream.

  • Fase 15 — Estúdio de sessão (SessaoEstudio): chat com texto, áudio (transcrito sync) e fotos (EXIF removido, pasta pac_{id}/sessao_{id}). Rota sessoes.editar. PacienteDetalhe lista sessões.

  • Fase 16 — Finalizar → IA: finalizarSessao() gera o relatório técnico (vinculado à sessão) + planejamento da próxima (gerarPlanejamentoProxima + prompt planejamento_proxima.txt). Sessão finalizada vira read-only com link "Ver relatório gerado".

  • Fase 17 — Tipos de documento configuráveis: tipos_documento_catalogo (9 tipos do sistema) + TipoDocumentoCatalogo (resolução modelo-do-profissional → sistema). 5 prompts novos (anamnese, devolutiva, acolhedor, orientação parental/educacional) com guardrail de tom. GroqLlmService::gerarDocumento() resolve o prompt no catálogo. Seletor do construtor e mapeamento de tipo de sessão vêm do catálogo.

  • Fase 18 — Protocolos de avaliação: protocolos_catalogo (12 protocolos, só metadados — ver disclaimer em docs/08) + aplicacoes_protocolo. No estúdio de sessão de avaliação: seletor filtrado por especialidade + idade (meses), aplicar → registrar observações/resultados/conclusão → concluir. Os registros entram no prompt do relatório (pseudonimizados). Modelo "executar protocolo X" — o sistema é o caderno de registro, não reproduz o instrumento.

  • Fase 19 — Tipos de áudio configuráveis + CBO por especialidade (✅ no ar, 24/06/2026): catálogo tipos_audio_pais + model TipoAudioPais (mesmo molde de TipoDocumentoCatalogo: resolver() com override por profissional, sistema()) + TiposAudioPaisSeeder (5 tipos: evolucao 480, devolutiva 700, orientacao 300, boas_vindas 250, celebracao 180; registrado no DatabaseSeeder). 4 prompts novos resources/prompts/resumo_pais_{devolutiva,orientacao,boas_vindas,celebracao}.txt (guardrail + pseudonimização). GroqLlmService::gerarResumoPais($rel, $tipo) resolve prompt + limite_palavras do catálogo (saiu o 510/480 hardcoded) via helper promptDoAudio(). Coluna tipo em resumos_pais (default evolucao); ConstrutorRelatorio ganhou $tipoAudio + seletor no card de áudio. CBO: Profissional::CBO_POR_ESPECIALIDADE + cbo()/conselho()/ocupacao()/credenciais(); PDF (cabeçalho+assinatura) usa credenciais() ("Ocupação · CBO 0000-00 · CRFa 2-1234", omite o que falta); Perfil.php validação → Rule::in(array_keys(ESPECIALIDADES)). Revisão adversarial (workflow) corrigiu: contagem de palavras agora multibyte-safe (preg_match_all('/\p{L}+/u') via contarPalavras()str_word_count quebrava em acentos e inflava ~30%); max_tokens derivado do limite (ceil($limite*2)+200, antes 1200 fixo truncava a devolutiva). Testes TipoAudioCboTest (7 casos).

Tudo pseudonimizado (LLM só recebe PAC-XXXX) e multi-tenant isolado (testes). Suíte: 31/31 verde. Validado ao vivo: criar sessão → chat → finalizar → Groq gerou relatório técnico estruturado + planejamento referindo só o código.

Notas operacionais (IMPORTANTE ao retomar)

  • Rodar artisan SEMPRE como o usuário do site, nunca root: sudo -u relat3058 /usr/bin/php artisan … (senão cria caches root-owned que o lsphp não sobrescreve).
  • MariaDB: root via socket → mysql -u root … relatafacil. App conecta por TCP (127.0.0.1, user relatafacil).
  • Rebuild de assets: sudo -u relat3058 bash -lc 'npm run build' (node_modules e public/build já com chown p/ relat3058).
  • Aplicar mudanças de vhost: /usr/local/lsws/bin/lswsctrl restart.
  • O estúdio de sessão é desktop 3-colunas (sobrepõe abaixo de ~900px) — responsividade é melhoria futura.

Fase 20 — hardening de isolamento multi-tenant (✅ 24/06/2026)

Auditoria adversarial multi-agente (workflow) das entidades novas (sessões, anexos, aplicações de protocolo, catálogos com override, resumos): zero vazamentos confirmados — as defesas (abort_unless em mounts/rotas + escopo duplo aplicacaoDaSessao()/resolver()) seguram. Adicionados os testes que faltavam em tests/Feature/IsolamentoFase20Test.php (5): cross-binding paciente+sessão na rota sessoes.editar (sem scopeBindings), injeção de id de AplicacaoProtocolo alheia em concluir/remover/salvar (no-op), e override de TipoDocumentoCatalogo não vaza entre tenants. Sessão/anexo já cobertos em SessaoEstudioTest; override de áudio em TipoAudioCboTest. Suíte: 36/36 verde.

Fase 21a — base de conhecimento + MontadorDeContexto (✅ no ar, 24/06/2026)

Fundação de dados + "cérebro", backward-compatible (com conhecimento_ia vazio e sem persona ativa, a saída do prompt é idêntica à anterior). Migrations aditivas aplicadas na base viva (backup /tmp/relatatea-fase21-sessoes-*.sql): conhecimento_ia (escopo sistema/profissional/prontuario, tipo diretriz/preferencia/correcao/fato_clinico/glossario, peso, ativo), modelos_ia (personas; fábrica=profissional_id NULL read-only, baseado_em_id, padrao), modelos_ia_versoes (histórico p/ desfazer), coluna modelo_id em sessoes. Models: ConhecimentoIa (scope crítico paraMontagem($profId,$prontId) — escopo prontuario exige profissional_id E prontuario_id casados, nada vaza entre pacientes/tenants), ModeloIa (disponiveis/padraoPara/deFabrica), ModeloIaVersao. Serviço App\Services\Groq\MontadorDeContexto (ÚNICO leitor de conhecimento_ia/modelos_ia — auditável): systemComPersona() (camada [2]), blocoConhecimento() (camadas [3]+[4], '' quando vazio), modeloAtivo(), prontuarioId(). GroqLlmService injeta o montador no construtor; gerarDocumento() aplica persona; montarEntrada() anexa o bloco de conhecimento. Seeder ModelosIaSeeder (4 personas de fábrica: Equilibrado=padrão, Enxuto, Detalhado, Caloroso). Testes BaseConhecimentoTest (11). Suíte 47/47. Revisão adversarial (workflow) endureceu 2 pontos latentes: (a) MontadorDeContexto::modeloAtivo() agora escopa por posse (ModeloIa::disponiveis($profId)->firstWhere) — modelo privado de outro tenant nunca vira persona; (b) ConhecimentoIa ganhou hook saving que pseudonimiza o conteudo de prontuário (troca nome real do paciente pelo codigo_anonimo) — a invariante deixa de ser só comentário. Bônus: o teste expôs que modelo_id faltava no $fillable do Sessao (corrigido — senão a UI da 21b não gravaria a persona). v1 NÃO auto-aplica persona (só quando sessao.modelo_id setado) nem semeia diretrizes de sistema — preserva a saída clínica já validada; popular conhecimento/persona é o trabalho da UI (Fase 21b).

Fase 21b — UI personas + base de conhecimento (✅ no ar, 24/06/2026)

As 4 frentes entregues. Decisões de produto aplicadas: psicopedagogia adicionada a Profissional::ESPECIALIDADES; ABA usa CBO de Psicólogo (2515-10/CRP)CBO_POR_ESPECIALIDADE atualizado (só const, sem migration). 1) Seletor de persona no SessaoEstudio ($modeloIdsessao.modelo_id, updatedModeloId valida posse via ModeloIa::disponiveis — id alheio rejeitado). 2) "Corrigir / ensinar a IA" (modal: escopo só-este-paciente=prontuario / sempre=profissional / só-desta-vez=não persiste → ConhecimentoIa, pseudonimizado pelo hook). 3) App\Livewire\Ia\Conhecimento (/ia/conhecimento, "o que a IA aprendeu": ensinar preferência/glossário, revogar/reativar, agrupado por paciente — tudo escopado ao profissional). 4) App\Livewire\Ia\Modelos (/ia/modelos: editar persona, editar fábrica cria cópia, voltarAoPadrao recopia da fábrica + grava modelos_ia_versoes, definirPadrao, excluir — helper meu() confere posse). Links no topbar (IA aprendeu / Personas), rotas sob auth:profissional. Revisão adversarial (workflow): 1 achado (baixo) corrigido — a temperatura da persona agora chega à geração (gerarDocumento passa $modelo?->temperatura ao chat()), antes era um knob morto. Testes Ia21bTest (10, incl. isolamento + Http::fake da temperatura). Suíte 58/58.

Fase 21c — compactação de memória (✅ no ar, 24/06/2026) — FASE 21 COMPLETA

Sem migration (campos já existiam). 2 prompts novos (resumo_sessao.txt ~150 palavras, sintese_prontuario.txt ~300). GroqLlmService::gerarResumoSessao() (resumo clínico compacto da sessão, pseudonimizado) + compactarSinteseProntuario(Prontuario) (consolida síntese anterior + até 20 resumos → prontuarios.sintese_avaliacao). MontadorDeContexto::blocoMemoria(RelatorioClinico) = síntese + 3 resumos recentes (escopado por prontuário E profissional); montarEntrada() usa a memória compactada e cai no fallback do relatório anterior cru quando ainda não há memória (backward-compat). SessaoEstudio::finalizarSessao gera resumo + compacta síntese em try/catch best-effort (não desfaz o relatório). Testes MemoriaProntuarioTest (4, incl. isolamento paciente↔paciente e tenant↔tenant). Suíte 62/62.

Auditoria pré-go-live (workflow, 24/06/2026) — 25 achados confirmados

Varredura multi-agente do app inteiro (Fases 0–21), 6 dimensões + verificação adversarial. Corrigido em código + testado (AuditoriaGoliveTest): pseudonimização do texto livre/transcrição ANTES da LLM (novo App\Services\Pseudonimizador, aplicado em todas as bases/protocolos/anterior do GroqLlmService; ConhecimentoIa refatorado p/ usá-lo) — antes o nome real ditado no áudio chegava à Groq; arquivos órfãos ao excluir paciente (hook deleting no Paciente apaga anexos+áudios antes do cascade do banco); síntese do prontuário deixou de pegar as 20 sessões mais ANTIGAS (congelava) → agora as mais recentes; resposta vazia da LLM lança exceção (não vira doc em branco); filtros profissional_id defensivos nas queries de "anterior"; TipoDocumentoCatalogo::rotulo não memoiza cache vazio. Resta ação do cliente (em docs/15 §8): .env produção (APP_ENV/DEBUG), rotacionar segredos, SESSION_SECURE_COOKIE/LOG_LEVEL, não rodar DemoSeeder em prod, captura de consentimento LGPD (profissional + responsável do menor), aviso de transferência internacional (Groq/EUA), e tuning das 4 chamadas Groq por finalização.

2ª passada — verificação de completude da remediação (workflow, 24/06/2026)

Auditar a própria remediação revelou 11 gaps remanescentes, corrigidos + testados (RemediacaoCompletudeTest): a memória (blocoMemoria/compactarSinteseProntuario) era a única fronteira de envio ao LLM sem pseudonimização → agora mascara (cobre dado legado em sintese_avaliacao/resumo_sessao); correção de escopo profissional pseudonimizada; GerarAudioResumoJob apaga o MP3 anterior ao refazer; Profissional::deleting elimina voz+pacientes; placeholder de transcrição não polui o LLM; badge de status corrigido. Residuais aceitos em docs/15 §9 (pseudonimização best-effort por nome exato; áudio bruto→Whisper é governança; status preso recuperável). Suíte 69/69.

Consentimento LGPD — implementado em código (24/06/2026)

Fecha a pendência H4/M4 da auditoria (mecanismo; o texto legal é do cliente, docs/15 §3). pacientes.consentimento_responsavel_em (migration + backfill COALESCE(consent, created_at, now()) no piloto): checkbox obrigatório no cadastro do paciente (Pacientes, regra accepted na criação). Aceite do profissional em Meu perfil (aceitarTermosconsentimento_lgpd_em). Revisão adversarial fechou um bypass de edição: o gate agora deriva do banco (consentimentoJaRegistrado()), nunca da propriedade pública $jaConsentido (só hint de UI). Corrigido bug pré-existente (Perfil dava 500 com voz_status nulo). ConsentimentoLgpdTest (5). Suíte 74/74.

Robustez de go-live (24/06/2026)

Comando php artisan relatorios:reset-gerando {--minutos=15} (app/Console/Commands/ResetGeracoesPresasCommand) reverte relatórios/resumos presos em "gerando" para estado recuperável (fecha M7/L5). Agendado a cada 15 min em routes/console.phpprecisa de cron de schedule:run (linha pronta em docs/15 §8, junto do bloco .env de produção). Testes ResetGeracoesPresasTest (3). Suíte 77/77.

Estado: todo o trabalho de CÓDIGO está esgotado. Fases 0–21 + 3 auditorias multi-agente (pré-go-live, completude da remediação, consentimento) + remediação verificada + consentimento LGPD + robustez. O que resta é 100% decisão/ação do cliente — ver docs/15 (voz, go-live, billing, texto legal do termo, CBO oficial, assinatura PDF).

TODAS as funcionalidades (Fases 0–21) entregues. O que resta é decisão/ação do cliente.

Ver docs/15-PENDENCIAS-POR-DECISAO.md — consolidado de tudo que depende de você: voz (provider + worker + licença), billing (provider + onboarding/LGPD), go-live (APP_ENV=production + segredos + consentimento + checklist técnico §8), CBO oficial + assinatura no PDF, entrega aos pais. Ordem combinada: Voz → Go-live → Billing. Suíte 66/66.

Decisões em aberto desta expansão

  • CBO do ABA: não tem código próprio → usar o da formação-base (geralmente Psicólogo). Confirmar.
  • numero de sessão sob concorrência: hoje max(numero)+1; sob carga, usar transação/lock.
  • Análise de imagem pela IA: fora de escopo (modelo texto-puro) — fotos são documentação armazenada.
  • Pendências antigas seguem: voz (Fase 9), billing, go-live (ver seções abaixo).

Sessão 19/06/2026 — plano de retomada das frentes finais

  • Decisão de ordem (cliente): 1) Voz (Fase 9) → 2) Go-live → 3) Billing. Provider de pagamento a decidir (planejar agnóstico, interface trocável como IA/voz).
  • Plano executável gravado em 06-PLANO-RETOMADA.md — passo a passo com tags [CLIENTE]/[DEV]/[ROOT] e validação por etapa. Ler ao retomar.
  • Estado verificado nesta sessão (voz):
    • Discos voices/audios definidos ✅ e pastas existem; storage:link ausente mas não bloqueia (áudio vai por rota privada /audios/resumo/{resumo}).
    • Fila database vazia, sem failed jobs. Worker NÃO está rodando — só há o pulse-worker (outro projeto) na VPS → mas Supervisor já em uso = precedente para instalar o nosso.
    • .env: HF_TOKEN presente, HF_XTTS_SPACE_URL vazio (falta o cliente duplicar o Space), TTS_PROVIDER=hf_xtts.
  • Próximo passo imediato: 1.1 — ligar o worker (docs/deploy-queue-worker.ini/etc/supervisord.d/, requer sudo). É pré-requisito de TODA geração de áudio. Depois: decidir provider de voz (XTTS grátis p/ validar vs. pago p/ produção) e calibrar HuggingFaceXttsProvider à API real do Space.

Estado atual (18/06/2026)

  • ✅ Ambiente: VPS com CyberPanel/OpenLiteSpeed, PHP 8.3, Composer 2.9, Node 20, MariaDB 10.11. Root disponível. supervisord+systemctl presentes → worker de fila persistente é possível (melhor que cron).
  • ✅ Stack espelhando o CRM (crm.clsolucoes.com): Laravel 13.16 + Livewire 4.3 + Tailwind 4 + Vite 8.
  • Fase 0 concluída — Laravel scaffoldado em public_html/; .env com MariaDB + chaves de IA (placeholders); fila/sessão/cache em database; design system aplicado em app.css (tokens) + fontes Fraunces/Hanken via <x-fonts>.
  • ✅ Banco MariaDB relatafacil criado (usuário relatafacil, senha no .env e em /tmp/rf_dbpass.txt). Migrations base + profissionais rodadas.
  • Fase 1 concluída e validada no navegador — guard profissional, registro com consentimento LGPD (timestamp gravado), login com rate-limit, logout, painel (dashboard com roadmap) e perfil editável. Layouts components.layouts.{auth,app}.
  • Fase 2 concluída — CRUD de pacientes (Livewire) com codigo_anonimo automático, busca, modal, exclusão; detalhe com timeline. Escopado/autorizado ao profissional.
  • Fases 3-4 concluídas e validadas no domínio — design system aplicado; layout studio (3 zonas); ConstrutorRelatorio com seletores reativos + conversa de coleta, persistindo em relatorios_clinicos. Timeline do paciente lista relatórios.
  • PREVIEW NO AR: https://relatatea.clsolucoes.com (login: [email protected] / senha12345). Paciente de teste: Lucas Martins (PAC-B0IU); rascunho de relatório id 1.
  • ✅ Documentação + protótipo visual (design/relatorio-builder.html).

Reestruturação 18/06 (turno 4) — modelo de acesso

  • Sem auto-cadastro. O fluxo é landing page → compra de assinatura → conta provisionada. Registro público removido (/criar-conta → 404; componente Registrar deletado).
  • Raiz / agora é a landing page (resources/views/landing.blade.php + layouts.site): hero com mockup do áudio, recursos, como funciona, planos (Profissional R$97/mês e Clínica sob consulta). Botões "Assinar" abrem mailto:[email protected]checkout/billing real ainda não existe (fase futura).
  • Conta demo provisionada (seeder DemoSeeder, idempotente): [email protected] / RelataDemo2026 — já vem com paciente Lucas Martins e um rascunho de relatório populado. Reseed: php artisan db:seed --class=DemoSeeder --force.
  • ⚠️ Consentimento LGPD era capturado no registro; sem registro, precisa migrar para o onboarding/primeira sessão ou para os termos da assinatura (TODO). O seeder já preenche consentimento_lgpd_em para o demo.
  • IA ATIVA ✅ (GROQ_API_KEY configurada no .env) — validado ao vivo:
    • Fase 5 — transcrição (GroqWhisperService, mic+upload no composer). Pronta; testar com áudio real.
    • Fase 6 — relatório técnico (GroqLlmService::gerarRelatorioTecnico + prompts/relatorio_tecnico.txt). Gera em ~3,6s, pseudonimizado (PAC-XXXX). Botão "Gerar relatório com IA".
    • Fase 8 — resumo p/ pais (gerarResumoPais + prompts/resumo_pais.txt), salvo em resumos_pais. ~400-480 palavras (limite validado), ~2,7 min, tom acolhedor, sem nome real.
    • ⚠️ A chave foi compartilhada no chat — o cliente pode rotacioná-la em console.groq.com quando quiser (só atualizar o .env). Modelo LLM: llama-3.3-70b-versatile.

Infra do preview (vhost OpenLiteSpeed/CyberPanel)

  • Arquivo: /usr/local/lsws/conf/vhosts/relatafacil.clsolucoes.com/vhost.conf.
  • docRoot ajustado para $VH_ROOT/public_html/public (era public_html → causava o 404).
  • PHP do vhost trocado para lsphp83 (era lsphp82/PHP 8.2; Laravel 13 exige 8.3). CRM usa lsphp85.
  • Aplicar mudanças: /usr/local/lsws/bin/lswsctrl restart (graceful).
  • ⚠️ Se mexer no PHP/site pelo painel do CyberPanel, ele pode reescrever o vhost.conf — reconferir docRoot/lsphp depois.

Gotchas resolvidos (não repetir)

  • Middleware auth precisa de redirect: configurado em bootstrap/app.php (redirectGuestsToentrar, redirectUsersTopainel). Sem isso, rota protegida dá 500 (procura rota login).
  • Rotas Livewire com {paciente} fazem route-model binding automáticomount(Paciente $paciente) (não int), e autorizar com abort_unless($p->profissional_id === auth()->id(), 404).

Notas técnicas

  • APP_ENV=local, APP_DEBUG=true — trocar para production/false no deploy real.
  • Ícones do painel usam emoji (👋📄🔊). Em alguns ambientes sem fonte de emoji aparecem como caixas → trocar por SVG num passe de polish.
  • Tabela users default do Laravel permanece (não usada) — pode remover depois.

Decisões já tomadas (não re-discutir)

  1. Backend: Laravel (não Python). Motivo: Hostinger é PHP-nativo, você já opera um CRM Laravel idêntico, deploy conhecido. IA é só HTTP, Laravel resolve.
  2. Banco: MariaDB/MySQL (não Supabase/Postgres) — já incluso na Hostinger, sem dependência externa.
  3. LLM de texto: Groq (llama-3.3-70b-versatile) na camada gratuita. Fallback pago (OpenAI/Anthropic) só se a qualidade clínica exigir — atrás de uma interface trocável.
  4. Transcrição: Groq Whisper (whisper-large-v3), não Hugging Face. Um fornecedor a menos.
  5. Clonagem de voz: XTTS v2 via Hugging Face Space duplicado na própria conta, atrás de uma interface TextToSpeechProvider para migrar para provider pago (Replicate/Fish/PlayHT) sem reescrever.
  6. Processamento de áudio/LLM = sempre em fila (Queue), nunca na request HTTP. Status via máquina de estados + polling.
  7. Pseudonimização: a LLM recebe codigo_anonimo ("PAC-7F2A"), nunca o nome real da criança.

Riscos conhecidos / a vigiar

  • HF Spaces grátis são instáveis (cold start, fila, somem). OK para validar; planejar provider pago barato para produção. Ver 04-IA-E-PROMPTS.md.
  • Licença XTTS v2 (Coqui CPML) é não-comercial. Para cobrar pelo SaaS, validar licença do modelo/Space ou migrar para provider comercial. ⚠️ pendência jurídica.
  • Voz clonada = dado biométrico (LGPD Art. 11). Exige consentimento explícito do profissional (campo já no schema). Idealmente avisar os pais que o áudio é sintético.
  • Dado clínico de criança = dado sensível de saúde. Base legal + minimização obrigatórias.

Perguntas em aberto para o cliente

  1. O profissional terá assinatura/carimbo digital no PDF? (impacta validade junto a conselhos/convênios)
  2. Entrega aos pais: download, link, WhatsApp ou e-mail? (define integração da Fase 10)
  3. Modelo de cobrança do SaaS: assinatura mensal por profissional? (define Fase 1/billing)
  4. Confirmar se a Hostinger atual é VPS (permite worker de fila persistente via systemd/supervisor) ou plano com cron — muda como rodamos queue:work.

Decisões adicionais (turno 18/06)

  • Voz: começar com XTTS (HF). Se for cobrar, migrar para provider eficiente/barato — camada já trocável.
  • Entrega aos pais: por ora só download (profissional baixa e manda no WhatsApp); link/WhatsApp/e-mail "em breve" (Fase 10).
  • Fila: servidor tem Supervisor → usar worker persistente queue:work (cron fica de plano B).

Próximo passo imediato

Fase 9 (voz) — código completo, validado o upload; falta ATIVAR a geração de áudio:

  1. Cliente: gerar HF_TOKEN e duplicar um Space XTTS v2 na conta HF; pôr HF_TOKEN + HF_XTTS_SPACE_URL no .env. ⚠️ Conferir a API do Space (/?view=api) e ajustar HuggingFaceXttsProvider (ordem do data/endpoints variam por Space). Licença XTTS é não-comercial — validar para cobrança.
  2. Worker da fila: áudio é assíncrono; precisa de queue:work rodando. Config pronta em docs/deploy-queue-worker.inirequer aprovação (serviço de sistema em /etc/supervisord.d/). Alternativa cron no mesmo arquivo.
  3. Já feito e testado: upload de voz + consentimento (Meu perfil, disco voices), TextToSpeechProvider/HuggingFaceXttsProvider, GerarAudioResumoJob, polling + player + download, rota privada /audios/resumo/{resumo}.

Fase 10 (PDF/download) ✅barryvdh/laravel-dompdf, view pdf/relatorio.blade.php, rota /relatorios/{relatorio}/pdf (validada). PDF tem o nome real do paciente (doc oficial) + assinatura; nome do arquivo usa codigo_anonimo.

Fase 11 (dashboards/evolução) ✅ — painel com métricas reais + relatórios recentes (o roadmap estático que estava no painel foi removido); detalhe do paciente com "Metas mais trabalhadas" (barras de frequência).

Fase 12 (diferenciais) ✅ núcleo — justificativa de convênio, PEI e relatório escolar implementados como tipos de documento (seletor no construtor + prompt reforçado). Validados via Groq.

Fase 13 (hardening) 🟡 — feito sem depender de decisão: testes de isolamento multi-tenant (IsolamentoMultiTenantTest, 8 testes, suite 10 ✅ via php artisan test), rate-limit de IA (60/h por profissional), limpeza de código morto. Falta (precisa do cliente): billing/checkout, consentimento LGPD no onboarding, go-live (APP_ENV=production+APP_DEBUG=false), retenção/exclusão LGPD.

Status geral

App funcionalmente completo para piloto (Fases 0-13, exceto voz e lançamento comercial). Fluxo end-to-end validado: login → paciente → construtor (seletores + notas/ditado) → relatório por IA → resumo p/ pais → PDF. Multi-tenant seguro (testado).

Pendências do cliente (decisões/insumos):

  • VOZ (parada por decisão do cliente): retomar depois — grátis (Space XTTS, instável) ou pago (Fish/PlayHT/ElevenLabs, recomendado; licença XTTS é não-comercial). HF_TOKEN já no .env; camada de voz trocável via TTS_PROVIDER. + aprovar worker.
  • Billing + onboarding: provedor de pagamento e como a conta nasce pós-assinatura (+ captura de consentimento LGPD).
  • Go-live: APP_ENV=production, APP_DEBUG=false.

Conta demo: [email protected] / RelataDemo2026. Prompts clínicos em resources/prompts/.

Seeders (reset rápido do ambiente)

php artisan migrate:fresh --seed recria tudo (metas + demo). Ou individuais: db:seed --class=MetasCatalogoSeeder / --class=DemoSeeder.

Comandos úteis

cd /home/relatafacil.clsolucoes.com/public_html
php artisan serve --host=127.0.0.1 --port=8010   # dev
npm run build                                     # assets
php artisan migrate                               # banco