# Política de Stacks do Ecossistema PharmData

> Documento normativo. Define qual stack usar em cada app do ecossistema PharmData (Lector, PRISMA, PATOS, Vigília, BrigServer, showcase, documentação, landing pages). Referenciado pelo `CLAUDE.md` global.
>
> **Versão 2 — 2026-04-12.** Revisa a versão 1 do mesmo dia, que previa três trilhos e superestimava a necessidade de reatividade cliente-lado rica. Ver nota histórica ao final.

---

## O princípio

**O ecossistema PharmData tem um trilho default e uma exceção rara.** Não há três alternativas equivalentes — há um caminho que funciona para quase tudo e um escape hatch para o caso raro em que ele comprovadamente não funciona.

O princípio por trás é uma observação empírica sobre os apps do PharmData: *reatividade cliente-lado rica é uma raridade, não um requisito recorrente*. Curadoria, dashboards, formulários, navegação hierárquica, visualização de evidence packs, busca, filtros, edição de registros, paginação, autocomplete, validação ao vivo, drag-and-drop simples, dashboards com atualização periódica — **tudo isso é resolvido por Flask + HTMX sem esforço e sem fragilidade**. O que HTMX não resolve bem é um conjunto pequeno e identificável de casos (editores colaborativos em tempo real, visualizações com interação contínua pesada, offline-first com sincronização), nenhum dos quais descreve app algum do PharmData hoje.

O fundamento mais profundo está documentado em `docs/usando-next.js.md`, seção 10 ("CSS é ativo, React é conveniência"): o ecossistema React/Next escolheu velocidade de iteração sobre estabilidade, e pagar esse preço só faz sentido quando o benefício funcional é demonstrável — nunca por inércia, estética ou expectativa hipotética.

---

## O trilho default — Flask + HTMX + DS como CSS

**Cobre ~100% dos apps do ecossistema hoje. É a resposta padrão.**

| | |
|---|---|
| **Quando usar** | Sempre que não houver demonstração concreta de que HTMX falha no caso específico. Curadoria, dashboards, formulários, CRUD sobre Oracle, busca, filtros, ferramentas internas, apps públicos institucionais, conteúdo estático, showcase do DS, documentação, landing pages — tudo. |
| **Stack concreto** | Python + Flask (ou FastAPI quando a API for central), Jinja para templates, HTMX para interatividade, Tailwind via CDN, DS consumido via `<link href="tokens/index.css">` e preset Tailwind do DS. |
| **Acesso a dados** | Driver Oracle nativo (`oracledb` Python), credenciais via `~/.pharmdata.env`. |
| **Dark mode** | Automático via `html.dark-mode` — o DS cuida. |
| **Conteúdo estático** | Flask+Jinja também renderiza conteúdo estático. Servido por nginx ou gunicorn, igualmente rápido e cacheável. Não há razão para trazer um gerador estático separado. |
| **Prova de campo** | Lector (em produção, funcionando). |
| **Interatividade que HTMX resolve sem drama** | Lista com filtros, formulário com validação ao vivo, modal com detalhes carregados sob demanda, dashboard com números atualizados em intervalo, drag-and-drop simples com SortableJS, autocomplete, paginação infinita com `hx-trigger="revealed"`, upload de arquivo com progresso, tabs, accordions. |

---

## A exceção — Next.js + React + DS como CSS

**Reservada para o caso raro em que a evidência funcional obriga. Nenhum app do ecossistema se enquadra hoje.**

| | |
|---|---|
| **Ônus de prova** | Quem propõe Trilho 2 precisa apontar **uma interação específica e concreta** que HTMX comprovadamente não resolve — não "vai ser complicado", não "o público espera stack moderna", não "parece melhor assim". Exige demonstração, não intuição. |
| **Exemplos do que realmente justifica** | Editor colaborativo em tempo real (Google Docs-like). Visualização com interação contínua pesada (gráfico com zoom/pan ao vivo sobre milhares de pontos, atualizando 30 fps). Jogo ou interface com estado de animação complexo. Offline-first com sincronização ao religar. Interface que precisa continuar operacional após queda de conexão. |
| **O que NÃO justifica** | "Tem dashboard com números atualizados" (HTMX resolve). "Tem drag-and-drop" (HTMX + SortableJS resolve). "É público-facing" (público não exige stack, exige resultado). "Parece mais moderno" (estética não é requisito). "O cliente final pediu React" (pressão social não é justificativa técnica — se for pressão comercial real, vira decisão de negócio registrada, não inércia). "Vai ser mais fácil contratar" (argumento circular do ecossistema). |
| **Stack concreto** | Next.js, React, Tailwind via npm com preset espelhado do DS, DS consumido como CSS (tokens + preset Tailwind), wrappers React copiados localmente a partir do `ds-nextjs` quando necessário. |
| **Acesso a dados** | Via backend Flask/FastAPI atrás (Next só como frontend). Conexão direta Oracle do Next só em último caso. |
| **Dark mode** | `next-themes` com `attribute="class"` e `value={{ light: "light", dark: "dark-mode" }}`. |
| **Custo aceito** | Fragilidade de versões, peer deps, quebras a cada major. Pago deliberadamente, nunca por inércia. |
| **Auditoria obrigatória** | A cada major do Next (17, 18, 19...), o app é reavaliado contra a pergunta-chave. Se em algum momento a interação que justificava a exceção puder ser resolvida no trilho default, **rebaixa-se sem constrangimento**. |

---

## A pergunta-chave

Antes de criar qualquer app novo, o responsável responde honestamente:

> **"Existe alguma interação neste app que HTMX comprovadamente não resolve?"**

A pergunta é formulada assim de propósito. Ela coloca o ônus da prova no lado correto: é preciso apontar algo específico que HTMX não faz, não apenas intuir que "vai precisar de mais". A inversão é deliberada — a versão 1 desta política usava "este app precisa de reatividade cliente-lado rica?" e esse enquadramento convidava ao viés da empolgação com stack novo.

Se a resposta for *não*, ou *não tenho certeza*, ou *talvez no futuro*, o trilho é o default. Sempre. A certeza de que a exceção é necessária deve ser tão forte quanto a certeza de que o fogão está ligado — não uma intuição, não uma projeção, não uma expectativa. Uma interação concreta, nomeada, com demonstração de que HTMX falha nela.

---

## Registro de decisão obrigatório

Todo app novo recebe um registro em `/decisions/YYYY-MM-DD-stack-<app>.md`:

```markdown
## Decisão: Stack para <nome do app>

## Contexto: <o que o app faz em uma frase>

## Trilho escolhido: <default (Flask+HTMX) | exceção (Next+React)>

## Pergunta-chave: Existe alguma interação neste app que HTMX comprovadamente não resolve?
Resposta: <não | sim, especificamente: X>

## Se exceção, qual interação específica obriga:
<descrição concreta e verificável — ex.: "editor colaborativo em tempo real com cursores múltiplos sincronizados via WebSocket">

## Alternativas consideradas: <o que se tentou antes de aceitar a exceção>

## Trade-offs aceitos: <o que ficou mais difícil por causa dessa escolha>
```

Apps no trilho default também recebem registro, mas curto — serve para marcar que a pergunta foi feita, não para justificar o óbvio.

---

## Classificação do ecossistema atual

| App | Trilho | Observação |
|---|---|---|
| **Lector** | Default | Prova de campo. Flask+HTMX em produção. |
| **PRISMA (backend)** | Default | API Python com Oracle. |
| **PATOS** | Default | Curadoria documental. |
| **Vigília** | Default | Migração para Next foi tentada e revertida em 2026-04-12 — ver `/decisions/2026-04-12-stack-vigilia-revisao.md`. Retorna ao Flask+HTMX com DS como CSS. |
| **BrigServer PE (ANVISA)** | Default | Frontend administrativo e portal público. |
| **BrigServer EE (comercial)** | Default | Decisão revisada — a exceção "cliente final exige stack moderna" foi reconhecida como fraca. Avaliar caso a caso na hora de construir; até lá, default. |
| **Showcase do DS** | Default | HTML estático servido via Flask. |
| **Documentação do DS** | Default | Mesmo. |
| **Landing pages BRIG** | Default | Mesmo. |

**Nenhum app do ecossistema está na exceção hoje.** Essa linha é importante — é a medida honesta de quanto o trilho default cobre.

---

## O pacote `ds-nextjs`

O pacote `design-system/ds-nextjs/` continua existindo como **prova de conceito e reserva estratégica**. Não é mais uma das formas oficiais de consumir o DS — a forma oficial é CSS + preset Tailwind via `<link>`. O `ds-nextjs` serve para:

1. Provar que o DS é consumível em Next quando e se a exceção for acionada.
2. Fornecer wrappers React prontos para copiar quando um app real precisar.
3. Manter a porta aberta sem que o custo de manutenção seja recorrente.

Não há obrigação de mantê-lo atualizado ao ritmo do Next. Quando um app real precisar, a atualização é feita no momento.

---

## Como a política é enforçada

1. **`CLAUDE.md` global** referencia este documento. Todo agente que abre sessão no ecossistema vê.
2. **Registro de decisão obrigatório** em `/decisions/` antes de qualquer app novo começar.
3. **Revisão periódica** — o documento é revisitado a cada seis meses ou quando um app real propuser acionar a exceção, o que vier primeiro.
4. **Lições aprendidas** registradas em `pharmdata/lessons.md` sempre que um desvio da política gerar dor — como a migração revertida do Vigília em 2026-04-12.

---

## Nota histórica — por que a versão 1 foi revisada no mesmo dia

A versão 1 desta política, escrita horas antes da versão 2 em 2026-04-12, previa **três trilhos**: Flask+HTMX como default (~80%), Astro para conteúdo (~15%), e Next+React como exceção (~5%). A classificação inicial colocava o Vigília em Next+React sob duas condições — "interatividade rica genuína" e "público externo que exige stack moderna".

Poucas horas depois, durante a migração real do Vigília, o viés ficou evidente. A migração gerou fricção imediata com fragilidade de versões (Next 14 do `ds-nextjs` contra Next 16 do Vigília), peer deps, e o custo operacional cotidiano que o ecossistema React impõe. A reversão foi pedida no mesmo dia.

A revisão consolidou três aprendizados:

1. **Reatividade rica é raridade, não recorrência.** A maioria esmagadora dos apps do PharmData é bem servida por HTMX. A política anterior previa ~80% no trilho default; o número real é mais próximo de ~100%.
2. **Astro era inércia, não necessidade.** Flask+Jinja renderiza conteúdo estático igualmente bem. Trazer um gerador estático separado só adiciona uma ferramenta para manter.
3. **A pergunta-chave anterior estava enquadrada errado.** "Precisa de reatividade rica?" convida à resposta "sim" sempre que há empolgação com stack novo. "Existe interação específica que HTMX não resolve?" força o ônus da prova para o lado certo.

A versão 1 está preservada no histórico git caso seja útil comparar. Esta versão 2 é a que vale.

---

*Política reescrita em 2026-04-12 a partir do aprendizado concreto da migração revertida do Vigília. Ver `docs/usando-next.js.md` seção 10 para o raciocínio de fundo sobre durabilidade do CSS vs. fragilidade do React.*
