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
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/laravelempublic_html/(Laravel 13.16, espelha o CRM). - Instalar Livewire 4, Tailwind 4 (
@tailwindcss/vite),@tailwindcss/typography. -
.env: conexão MariaDB (banco+usuáriorelatafacilcriados),APP_*pt-BR, chavesGROQ_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,
migrateroda em MariaDB, assets buildam.
Fase 1 — Identidade, multi-tenant & LGPD ✅ (revisada)
- Autenticação de
profissionais(guardprofissional, modelProfissionalcomsenha_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(LivewirePacientes) com geração automática decodigo_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 viaabort_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(corespetro/clay/sage/paper) + fontes Fraunces/Hanken via<x-fonts>. -
layouts.app(topbar extraído p/x-app.topbar) elayouts.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 ✅
-
ConstrutorRelatoriocom 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 promptresources/prompts/relatorio_tecnico.txt. - Geração do
relatorio_tecnicocruzando seletores + notas + relatório anterior (continuidade). Pseudonimizado (enviacodigo_anonimo, nunca o nome). - Botão "Gerar relatório com IA" + regenerar; status
gerando→pronto; 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+ modelMetaCatalogo+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).DatabaseSeederchama metas + demo. - Saída: ✅ validado no domínio (filtro por especialidade + persistência).
Fase 8 — Resumo para os pais & roteirização ✅
-
GroqLlmService::gerarResumoPais()+ promptresources/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+ modelResumoPais; 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. Statuspendente/ativa/revogada. Validado ao vivo (voz ativa). -
interface TextToSpeechProvider+HuggingFaceXttsProvider(Gradio), binding trocável viaTTS_PROVIDER. -
GerarAudioResumoJob(fila, timeout 600s): texto + amostra → provider → salva.mp3no discoaudios;failed()trata erro. - Card de áudio: botão dispara o job,
wire:polldurantegerando_audio, player + download quandoconcluido. 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 usacodigo_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_VBMAPPremovido — 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=falseno 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).
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/systemdrodandophp artisan queue:work. Se plano com cron,queue:work --stop-when-emptyvia cron a cada minuto (degradação aceitável). Confirmar com o cliente (ver HANDOFF). - Assets:
npm run buildno 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. .envfora do controle de versão; chaves de IA só no servidor.
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_jsonguarda o estado da tela (nível, metas marcadas, tipo) — é o que cruzamos com a transcrição no prompt.- Versionamento de
resumos_paispermite regenerar o áudio sem perder o histórico (campoversao). - Para "evolução comparativa" (Fase 11), busca-se o
resumos_pais/relatorios_clinicosanterior do mesmopaciente_id.
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=apido 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_texto → GroqResumoService →
gerando_audio → TextToSpeechProvider->clonarFala() → salva .mp3 no disco audios →
status='concluido'. failed() grava erro_detalhe. Controller despacha o job e retorna HTTP 202 + poll_url.
Design system
Fonte da verdade visual: design/relatorio-builder.html. Estes tokens viram o theme do Tailwind 4 na Fase 3.
Princípios
- 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.
- Alta legibilidade — serif quente (Fraunces) para conteúdo humano (relatório/resumo); sans humanista (Hanken Grotesk) para a UI.
- 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/gridcommin-width:0emin-height:0nos 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 |
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.inijá roda na VPS). - Validar:
dispatchde um job de teste e conferir consumo emstorage/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ôrHF_XTTS_SPACE_URLno.env(hoje vazio). - [CLIENTE+DEV] Abrir
…/?view=apido Space e conferir endpoints/ordem dodata(/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.phpimplementandoTextToSpeechProvider(configurado/clonarFala/nome). - [DEV] Registrar binding por
TTS_PROVIDERno 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+backoffjá no job; conferir mensagem amigável no player quandostatus=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) + conferirvhost.conf(docRootpublic_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_empara 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ãoTextToSpeechProvider. - 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 worker (destrava qualquer áudio) → 1.2 decisão → 1.3/1.4 voz validada.
- 2.1 + 2.2 (produção + LGPD mínimo) — pode rodar piloto com contas provisionadas à mão.
- Frente 3 billing quando o modelo comercial estiver fechado.
Atualizar
HANDOFF.mdao fim de cada etapa concluída.
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:
- A conversa consolidada vira relatório(s) (
relatorios_clinicoscomsessao_id), no tom escolhido (técnico e/ou acolhedor). - A IA produz o planejamento da próxima sessão (
planejamento_proxima). - 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_clinicoexistente vira umasessaoespelhada, comsessao_idligando de volta — a conta demo continua "viva". relatorios_clinicossegue 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.
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:
- Metadados do protocolo (nome, sigla, o que avalia, faixa etária, área, referência) — informação factual, pública.
- 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
- Numa sessão de
tipo = avaliacao, a profissional abre o painel "Aplicar protocolo". - A lista é filtrada por especialidade do profissional e faixa etária do paciente (a avaliação depende da idade).
- 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.
- Resultados (
- 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, Portage→IPO, VABS→Vineland-3, Perfil Sensorial→SP-2, AHEMD→AHEMD-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.
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 paragerarDocumento(relatorio, tipo), carregando o prompt do catálogo.montarEntrada()→ lookup no catálogo (em vez deRelatorioClinico::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.
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.phpe cabeçalho dos relatórios: exibirNome — 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.
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:
- transforma a conversa em um relatório de evolução daquele dia, e
- 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
- O paciente é uma pasta (prontuário) que acompanha o ciclo inteiro, na ordem acima.
- A sessão é o lugar do trabalho — conversa, áudio transcrito, fotos —, e finalizá-la gera documento + planejamento.
- A avaliação depende da idade e se faz em várias sessões, com protocolos que o profissional aplica e registra.
- Dois tons de relatório: técnico e acolhedor.
- 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.
- A devolutiva responde à queixa registrada lá no início.
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
- 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.
- Binário só no disco privado, nunca no banco. No banco vai apenas o
path. Discoanexos(storage/app/anexos, driver local, sem URL pública). - Acesso só por rota autorizada.
/anexos/{anexo}fazabort_unless($anexo->profissional_id === auth('profissional')->id(), 404). Sem link público, semstorage:linkpara esse disco. - EXIF removido das fotos no upload (geolocalização/dispositivo). Re-encode da imagem ao salvar.
- 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 porcodigo_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 deupdatedAudio), até ~25 MB.
Checklist de verificação (Fase 20)
- Anexo só acessível pelo dono (intruso → 404). Estender
IsolamentoMultiTenantTest. - Disco
anexossem 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).
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)
- Prontuário por paciente: pasta organizada por data. Ver
07-PRONTUARIO-E-SESSOES.md. - Sessão é camada própria (não refatorar
relatorios_clinicos; adicionarsessoespor cima). - 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.
- Fotos nunca vão à IA — o LLM é texto-puro; foto é documentação clínica armazenada (reforça LGPD). Ver
12-LGPD-MIDIA.md. - 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. - Tipos de documento e tipos de áudio configuráveis (catálogo em banco + modelos por profissional). Ver
09-MODELOS-RELATORIO-E-AUDIO.md. - 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.
- CBO por especialidade, não por profissional. Ver
10-CBO-E-CONSELHOS.md. - Tudo documentado em
docs/(este conjunto 07→13).
Princípios herdados (preservar)
- Pseudonimização no limite da IA —
GroqLlmService::montarEntrada()só enviacodigo_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
pathno banco. Padrãovoices/audiosemconfig/filesystems.php. - Catálogo DB filtrado por especialidade —
metas_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-tenant —
abort_unless($x->profissional_id === auth('profissional')->id(), 404)em toda nova entidade; estenderIsolamentoMultiTenantTest.
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; adicionarsessao_id/tomarelatorios_clinicos. - Models
Prontuario,Sessao,Anexo(relações;Anexoapaga o arquivo nodeleting). - Auto-criar
ProntuarionocreateddePaciente(espelha o auto-codigo_anonimo). - Disco
anexosemconfig/filesystems.php(privado) + rota autorizada/anexos/{anexo}(anexos.stream). - Migração de dados (uma vez): cada paciente → prontuário; cada
relatorio_clinico→ umasessaoespelhada comsessao_idapontando 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 --forceok; 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(clonaConstrutorRelatorio, layoutstudio), rota/pacientes/{paciente}/sessoes/{sessao}(sessoes.editar; semscopeBindings—mount()valida sessão⊂paciente⊂profissional).PacienteDetalheganhounovaSessao()+ listagem de sessões. - Mensagens de texto persistem em
mensagens_json(formato comtipo/anexo_id). - Áudio: grava → upload → salva no disco
anexos(anexotipo=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}/), criaanexo(tipo=foto), renderiza viaanexos.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 → criarelatorios_clinicoscomsessao_id(tom=tecnico) →gerarRelatorioTecnico()(statuspronto) →gerarPlanejamentoProxima()gravasessao.planejamento_proxima→status=finalizada. Erro de IA/sem chave: sessão finaliza mesmo assim, relatório ficarascunho+ aviso amigável. - Novo prompt
resources/prompts/planejamento_proxima.txt(pseudonimizado, guardrail de tom) + métodoGroqLlmService::gerarPlanejamentoProxima()(reusachat()). - 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 referindoPAC-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+ modelTipoDocumentoCatalogo(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_texto→prompt_arquivo→ fallback técnico);montarEntrada()usa o rótulo do catálogo.gerarRelatorioTecnico()virou wrapper. -
ConstrutorRelatoriomonta o seletor pelo catálogo + derivatom;SessaoEstudiomapeiatipo_sessao → tipo_documento+ tom na finalização;RelatorioClinico::rotuloTipo()resolve pelo catálogo. - Coluna
profissional_id+prompt_textosuportam 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 → docdevolutiva/tomacolhedor); ✅ 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+ modelProtocoloCatalogo(scopesparaEspecialidade/paraIdade,faixaLegivel) +ProtocolosCatalogoSeeder(12 protocolos, só metadados; registrado no DatabaseSeeder). -
aplicacoes_protocolo+ modelAplicacaoProtocolo; 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; adicionarpsicopedagogiaà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.mde este conjunto de docs. - Checklist LGPD de mídia (
12-LGPD-MIDIA.md): retenção, exclusão, EXIF, rota autorizada. - Estender
IsolamentoMultiTenantTestpara 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. Colunamodelo_idnasessao. - 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)
- CBO para ABA — ABA não é ocupação CBO própria; usar o CBO da formação-base (geralmente Psicólogo). Confirmar.
numerode sessão sob concorrência — usar transação/lock ou tratar como rótulo derivado decreated_at.- 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 doSessaoEstudio(chat,updatedAudio, seletores, autosave, rate-limit).app/Services/Groq/GroqLlmService.php—montarEntrada()(pseudonimização); generalizargerarDocumento/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).
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_clinicosó existe no escopoprontuario. Conhecimento sobre a criança fica preso ao prontuário dela.profissionalguarda só estilo/persona:preferencia,glossario, e correções marcadas como "sempre".sistemasã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_iaativo do prontuário. Tudo pseudonimizado.
Isolamento (o ponto crítico)
- Toda linha carrega
profissional_ide, 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/correcaode 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(referecodigo_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.
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: ouHF_XTTS_SPACE_URL(XTTS, hoje vazio) ouELEVENLABS_API_KEY+TTS_PROVIDER=elevenlabs(requer plano ElevenLabs com Instant Voice Cloning). - [INFRA] Ligar o worker da fila (
docs/deploy-queue-worker.ini→ Supervisor, requersudo). É 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=productioneAPP_DEBUG=falseno.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]
numerode sessão sob concorrência: hojemax(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]
.envde produção (hojeAPP_ENV=local,APP_DEBUG=true): virar paraAPP_ENV=production+APP_DEBUG=false(com debug ligado, uma exceção expõe stack trace + segredos). Depoisphp artisan config:cache. - [INFRA] Rotacionar segredos que circularam em texto puro:
GROQ_API_KEY(console.groq.com), senha do MariaDB (DB_PASSWORD), e avaliarAPP_KEY(trocar invalida sessões/dados cifrados — planejar).HF_TOKENidem. - [INFRA]
SESSION_SECURE_COOKIE=true(app é HTTPS-only) eLOG_LEVEL=warning(hojedebug— reduz superfície de vazamento em log). - [INFRA] Conta demo: NÃO rodar
DemoSeederem produção (cria login conhecidodemo@... / 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).
- ✅ Responsável pelo MENOR (Art. 11/14): checkbox obrigatório no cadastro do
paciente grava
- [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-gerandoreverte relatórios/resumos travados em "gerando" (> 15 min) para estado recuperável. Já agendado a cada 15 min emroutes/console.php— basta cron deschedule:runno 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 docodigo_anonimonos 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 |
Fluxo de testes
Roteiro para validar as funcionalidades principais ponta a ponta. Atualizado em 26/06/2026.
Acesso
- URL: https://relatatea.clsolucoes.com
- Conta demo:
[email protected]/RelataDemo2026 - Não há auto-cadastro (modelo: landing → assinatura → conta provisionada).
1. Login e painel
- Acesse a URL → Entrar → use as credenciais demo.
- No Painel, confira as métricas (Pacientes, Relatórios, Resumos p/ pais).
- 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
- Pacientes → Novo paciente (botão com ícone +).
- Preencha nome, nascimento, nível de suporte (terminologia DSM-5: Exige apoio / substancial / muito substancial), CID, responsável.
- Marque o consentimento do responsável (obrigatório) e salve.
- 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
- No prontuário → + Nova sessão (abre o estúdio).
- Coluna esquerda → Tipo de sessão → escolha Avaliação.
- 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.
- 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.
- Conduza a sessão pelo chat: texto, áudio (gravar/anexar → transcrição) e foto (anexo).
- 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
- No prontuário, abra um relatório (final de sessão ou avulso).
- Ajuste seletores/observações → Gerar relatório com IA (Groq).
- Confira o texto técnico gerado (pseudonimizado).
- 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):
- Gerar resumo para os pais → a IA escreve o roteiro acolhedor (segundos).
- 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 .env → TTS_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 comorelat3058). - Cron:
schedule:runno crontab dorelat3058(destrava itens presos viarelatorios: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 ....
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.
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\SincronizarStripeListener → App\Services\Pagamento\SincronizadorAssinatura).
O que foi construído
- Cashier: billable =
Profissional(Cashier::useCustomerModel), traitBillable, colunasstripe_id/pm_type/pm_last_four/trial_ends_at+ tabelassubscriptions/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 (Assinaturasuspensa, origemstripe) + 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 viacheckoutCharge). - Webhook em
POST /stripe/webhook(rotacashier.webhook). Sincroniza assinatura, reseta cota mensal de voz na troca/renovação e credita pacotes avulsos (idempotente poridda sessão de checkout). - Termos LGPD:
/termos(renderizadocs/17-TERMOS-LGPD.md); links nos pontos de consentimento.
Configuração na Stripe (uma vez)
- Conta Stripe → modo Teste primeiro.
- 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). - Webhook: Developers → Webhooks → endpoint
https://relatatea.clsolucoes.com/stripe/webhook. Eventos mínimos:customer.subscription.createdcustomer.subscription.updatedcustomer.subscription.deletedcheckout.session.completedCopie o Signing secret (whsec_…) paraSTRIPE_WEBHOOK_SECRET.
.env:STRIPE_KEY(pk_…),STRIPE_SECRET(sk_…),STRIPE_WEBHOOK_SECRET(whsec_…). Já existemCASHIER_CURRENCY=brleCASHIER_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./assinaturae/conta-suspensaficam FORA do gate para permitir regularizar. - Idempotência: crédito de pacote avulso usa o
idda sessão de checkout comojob_uuidno 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 emContaDetalhe::aplicarPlano.
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".PacienteDetalhevirou TIMELINE ÚNICA "Prontuário": funde sessões + relatórios num feed cronológico; relatório FINAL (comsessao_id) aparece aninhado sob a sessão; relatório avulso (whereNull('sessao_id'), rótulo "· avulso") é evento próprio.render()monta$timelineordenada 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(jsondimensoes+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: chavetextoviva; nível validado server-side).GroqLlmService::montarEntradarenderiza 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). Viewsia/*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 ganhouclona(): 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).PiperProviderroda viaProcess(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-ttsparado/disabled. PyAV instalado (decodifica webm/mp4 da gravação). - Gravação por microfone no Perfil (MediaRecorder→wire:upload), validação
mimetypesampliada (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:runno crontab dorelat3058(dispararelatorios:reset-gerandoa cada 15min).
Credenciais (sensível — rotacionar no go-live)
- DB:
relatafacil/goPgDlo4coFBHsDIKkuChQh@ 127.0.0.1; root via socket. - Groq
gsk_…· HFhf_…· ElevenLabssk_…(free, API bloqueada).APP_KEYno.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.comcriado como child domain do site existente no CyberPanel (reaproveita diretório/usuário/banco — sem migrar arquivos). SSL Let's Encrypt emitido..envAPP_URL/MAIL_FROMvirados. Redirect 301 do domínio antigo viapublic/.htaccess. - DNS é Cloudflare (NS jill/clyde.ns.cloudflare.com): registros do
*.clsolucoes.comsã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áriorelat3058e bancorelatafacilmantê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_clinicosganhousessao_id+tom. Migração de dados aditiva (relatórios viraram sessões).Pacienteauto-cria prontuário. Discoanexos+ rotaanexos.stream.Fase 15 — Estúdio de sessão (
SessaoEstudio): chat com texto, áudio (transcrito sync) e fotos (EXIF removido, pastapac_{id}/sessao_{id}). Rotasessoes.editar.PacienteDetalhelista sessões.Fase 16 — Finalizar → IA:
finalizarSessao()gera o relatório técnico (vinculado à sessão) + planejamento da próxima (gerarPlanejamentoProxima+ promptplanejamento_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 emdocs/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+ modelTipoAudioPais(mesmo molde deTipoDocumentoCatalogo: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 novosresources/prompts/resumo_pais_{devolutiva,orientacao,boas_vindas,celebracao}.txt(guardrail + pseudonimização).GroqLlmService::gerarResumoPais($rel, $tipo)resolve prompt +limite_palavrasdo catálogo (saiu o 510/480 hardcoded) via helperpromptDoAudio(). Colunatipoemresumos_pais(defaultevolucao);ConstrutorRelatorioganhou$tipoAudio+ seletor no card de áudio. CBO:Profissional::CBO_POR_ESPECIALIDADE+cbo()/conselho()/ocupacao()/credenciais(); PDF (cabeçalho+assinatura) usacredenciais()("Ocupação · CBO 0000-00 · CRFa 2-1234", omite o que falta);Perfil.phpvalidação →Rule::in(array_keys(ESPECIALIDADES)). Revisão adversarial (workflow) corrigiu: contagem de palavras agora multibyte-safe (preg_match_all('/\p{L}+/u')viacontarPalavras()—str_word_countquebrava em acentos e inflava ~30%);max_tokensderivado do limite (ceil($limite*2)+200, antes 1200 fixo truncava a devolutiva). TestesTipoAudioCboTest(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, userrelatafacil). - 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 ($modeloId→sessao.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 (aceitarTermos→consentimento_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.php — precisa 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.
numerode sessão sob concorrência: hojemax(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/audiosdefinidos ✅ e pastas existem;storage:linkausente mas não bloqueia (áudio vai por rota privada/audios/resumo/{resumo}). - Fila
databasevazia, sem failed jobs. Worker NÃO está rodando — só há opulse-worker(outro projeto) na VPS → mas Supervisor já em uso = precedente para instalar o nosso. .env:HF_TOKENpresente,HF_XTTS_SPACE_URLvazio (falta o cliente duplicar o Space),TTS_PROVIDER=hf_xtts.
- Discos
- Próximo passo imediato: 1.1 — ligar o worker (
docs/deploy-queue-worker.ini→/etc/supervisord.d/, requersudo). É pré-requisito de TODA geração de áudio. Depois: decidir provider de voz (XTTS grátis p/ validar vs. pago p/ produção) e calibrarHuggingFaceXttsProviderà 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+systemctlpresentes → 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/;.envcom MariaDB + chaves de IA (placeholders); fila/sessão/cache emdatabase; design system aplicado emapp.css(tokens) + fontes Fraunces/Hanken via<x-fonts>. - ✅ Banco MariaDB
relatafacilcriado (usuáriorelatafacil, senha no.enve em/tmp/rf_dbpass.txt). Migrations base +profissionaisrodadas. - ✅ 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. Layoutscomponents.layouts.{auth,app}. - ✅ Fase 2 concluída — CRUD de
pacientes(Livewire) comcodigo_anonimoautomá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);ConstrutorRelatoriocom seletores reativos + conversa de coleta, persistindo emrelatorios_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; componenteRegistrardeletado). - 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" abremmailto:[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_empara o demo. - IA ATIVA ✅ (
GROQ_API_KEYconfigurada 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 emresumos_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.
- Fase 5 — transcrição (
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(erapublic_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
authprecisa de redirect: configurado embootstrap/app.php(redirectGuestsTo→entrar,redirectUsersTo→painel). Sem isso, rota protegida dá 500 (procura rotalogin). - Rotas Livewire com
{paciente}fazem route-model binding automático →mount(Paciente $paciente)(nãoint), e autorizar comabort_unless($p->profissional_id === auth()->id(), 404).
Notas técnicas
APP_ENV=local,APP_DEBUG=true— trocar paraproduction/falseno 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
usersdefault do Laravel permanece (não usada) — pode remover depois.
Decisões já tomadas (não re-discutir)
- Backend: Laravel (não Python). Motivo: Hostinger é PHP-nativo, você já opera um CRM Laravel idêntico, deploy conhecido. IA é só HTTP, Laravel resolve.
- Banco: MariaDB/MySQL (não Supabase/Postgres) — já incluso na Hostinger, sem dependência externa.
- 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. - Transcrição: Groq Whisper (
whisper-large-v3), não Hugging Face. Um fornecedor a menos. - Clonagem de voz: XTTS v2 via Hugging Face Space duplicado na própria conta, atrás de uma
interface TextToSpeechProviderpara migrar para provider pago (Replicate/Fish/PlayHT) sem reescrever. - Processamento de áudio/LLM = sempre em fila (Queue), nunca na request HTTP. Status via máquina de estados + polling.
- 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
- O profissional terá assinatura/carimbo digital no PDF? (impacta validade junto a conselhos/convênios)
- Entrega aos pais: download, link, WhatsApp ou e-mail? (define integração da Fase 10)
- Modelo de cobrança do SaaS: assinatura mensal por profissional? (define Fase 1/billing)
- 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:
- Cliente: gerar
HF_TOKENe duplicar um Space XTTS v2 na conta HF; pôrHF_TOKEN+HF_XTTS_SPACE_URLno.env. ⚠️ Conferir a API do Space (/?view=api) e ajustarHuggingFaceXttsProvider(ordem dodata/endpoints variam por Space). Licença XTTS é não-comercial — validar para cobrança. - Worker da fila: áudio é assíncrono; precisa de
queue:workrodando. Config pronta emdocs/deploy-queue-worker.ini— requer aprovação (serviço de sistema em/etc/supervisord.d/). Alternativa cron no mesmo arquivo. - 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_TOKENjá no.env; camada de voz trocável viaTTS_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