Implementação MVP
This commit is contained in:
commit
807b3d72cd
54 files changed
+5241
No files matched your search
@@ -0,0 +1,23 @@
|
||||
# ADR-000 — Aplicação standalone neste repositório
|
||||
|
||||
- Status: Accepted
|
||||
- Data: 2026-10-02
|
||||
- Decisor: produto / engenharia, nesta sessão
|
||||
|
||||
## Contexto
|
||||
|
||||
O discovery da fase 00 encontrou um repositório vazio. A premissa inicial do pacote era reutilizar auth, workspace, RLS e design system de outro checkout EloPro.
|
||||
|
||||
## Decisão
|
||||
|
||||
`gerador-proposta` é um produto standalone novo. O repositório vazio é o baseline oficial.
|
||||
|
||||
Auth, workspace, usuários, papéis e RLS serão implementados aqui, nas fases 02 e 03. O design system nasce aqui no prompt 04, com os tokens EloPro V2.1, pronto para convergir depois sem acoplar código agora.
|
||||
|
||||
A integração com outros componentes EloPro ocorre por ports. Este módulo não assume banco, sessão, componentes ou código compartilhado.
|
||||
|
||||
## Consequências
|
||||
|
||||
- Não há etapa de importar um repositório legado antes do prompt 02.
|
||||
- Contratos externos ficam em `src/integrations/`. O CRO standalone devolve `no-context` ou `pending-source` (P-002), e a geração não depende dele.
|
||||
- Stack alvo: Next.js 16, React 19, TypeScript 5, Tailwind CSS v4, Supabase, Redis, Sentry, Claude e Vitest. Nesta fase só entram TypeScript, ESLint e Vitest, porque ainda não há app, banco, fila nem chamada de modelo.
|
||||
@@ -0,0 +1,49 @@
|
||||
# ADR-001 — Escopo da sequência PROP
|
||||
|
||||
- Status: Proposed
|
||||
- Data: 2026-10-02
|
||||
- Pendência: P-009
|
||||
- Decisão: nenhuma
|
||||
|
||||
## Contexto
|
||||
|
||||
A primeira geração bem-sucedida cria um número comercial no formato `PROP-######` e a versão `V1`. Falha de geração não pode consumir número nem versão. O que permanece aberto é o escopo do contador: o que faz duas propostas receberem números diferentes, e onde a unicidade vale.
|
||||
|
||||
A source of truth registra uma recomendação técnica de escopo por workspace. Esta recomendação não foi aprovada. Este ADR não a converte em regra.
|
||||
|
||||
## Alternativas
|
||||
|
||||
1. Sequência por `workspace_id`. É a recomendação técnica citada na especificação. Continua não adotada.
|
||||
2. Sequência global da plataforma, única entre workspaces.
|
||||
3. Sequência por documento comercial (CNPJ ou equivalente). CNPJ não é chave de tenant; esta alternativa entra só para ficar visível.
|
||||
4. Sequência por usuário criador.
|
||||
|
||||
## Critérios para sair de Proposed
|
||||
|
||||
- Unicidade definida: quem pode ver o mesmo número e quem não pode.
|
||||
- Comportamento em falha: a reserva volta ao contador. Pular número em rollback não atende RN-017.
|
||||
- Concorrência: duas gerações simultâneas no mesmo escopo não recebem o mesmo número.
|
||||
- Efeito em workspace novo, arquivado e reativado.
|
||||
|
||||
## Impacto no código desta fase
|
||||
|
||||
`CommercialNumberAllocator` só pode ser chamado de dentro do commit formal, depois do artefato válido, e só quando a proposta ainda não tem número. O duplo em memória usa o prefixo `TEST-` de propósito. Ele não é a sequência de produção e não escolhe a alternativa 1, 2, 3 ou 4.
|
||||
|
||||
O formato `PROP-######` já está na source of truth. O regex em `src/domain/generation/types.ts` descreve esse formato. Ele não aloca números.
|
||||
|
||||
## Impacto no prompt 02
|
||||
|
||||
A migration pode criar `proposals.commercial_number` como texto anulável.
|
||||
|
||||
Ainda não criar:
|
||||
|
||||
- `CREATE SEQUENCE` ou equivalente
|
||||
- `UNIQUE (commercial_number)` global
|
||||
- `UNIQUE (workspace_id, commercial_number)`
|
||||
- trigger que preencha o número na inserção da proposta
|
||||
|
||||
Qualquer um desses objetos escolheria o escopo antes da aprovação deste ADR.
|
||||
|
||||
## O que aprovar este ADR não muda
|
||||
|
||||
Versão formal continua imutável. Retry com a mesma chave não cria outra versão. A segunda versão reutiliza o número já commitado; não pede outro.
|
||||
@@ -0,0 +1,40 @@
|
||||
# ADR-002 — Motor de ingestão de PDF, PPTX e DOCX
|
||||
|
||||
- Status: Proposed
|
||||
- Data: 2026-10-02
|
||||
- Pendência: P-010
|
||||
- Decisão: nenhuma
|
||||
|
||||
## Contexto
|
||||
|
||||
Admin ou Gestor importa um modelo PDF, PPTX ou DOCX. O campo dinâmico nasce só de um marcador `[campo]` escrito no arquivo. O sistema não infere trecho variável. IA não substitui essa validação.
|
||||
|
||||
O motor que lê o arquivo e devolve texto ou estrutura ainda não foi escolhido. Sem essa escolha, não há parser real nesta fase.
|
||||
|
||||
## Alternativas
|
||||
|
||||
1. Bibliotecas locais por formato, com uma etapa posterior e determinística que só aceita `[campo]`.
|
||||
2. Conversão por processo externo (por exemplo LibreOffice) para um formato intermediário, seguida da mesma detecção determinística.
|
||||
3. Serviço externo de extração de documento, seguido da mesma detecção determinística.
|
||||
4. Modelo de linguagem lendo o arquivo para achar campos. Esta alternativa conflita com a regra de marcador explícito e com a proibição de a IA substituir a validação. Está listada para não reaparecer como atalho. Não é candidata aceitável para descobrir campos.
|
||||
|
||||
As alternativas 1, 2 e 3 continuam abertas. Nenhuma foi escolhida. Claude permanece na stack para capacidades de IA que venham a ser aprovadas; não é o motor de marcadores.
|
||||
|
||||
## Critérios para sair de Proposed
|
||||
|
||||
- Fidelidade dos marcadores em PDF, PPTX e DOCX reais, inclusive repetidos e partidos por formatação.
|
||||
- O que acontece com arquivo sem marcador, arquivo protegido e extração incompleta. O último ponto também depende de P-006.
|
||||
- Isolamento do processo que abre o arquivo, tempo máximo e falha sem criar rascunho de modelo. O limite numérico continua em P-006 e P-012.
|
||||
- O workspace só lê o próprio arquivo.
|
||||
|
||||
## Impacto no código desta fase
|
||||
|
||||
`TemplateIngestionService` devolve `blocked / P-006` enquanto a política de arquivo não existir, e `blocked / P-010` mesmo que um teste marque a política como aprovada. Não há adapter que leia bytes.
|
||||
|
||||
## Impacto no prompt 02
|
||||
|
||||
Pode existir coluna ou objeto para `source_file_ref`, `normalized_template` e `analysis_json`. O conteúdo desses JSON não fica preso a um motor. Não há worker de conversão nesta fase nem na migration.
|
||||
|
||||
## O que este ADR não decide
|
||||
|
||||
Tamanho máximo, antivírus, sandbox e extração parcial continuam no ADR-004.
|
||||
@@ -0,0 +1,41 @@
|
||||
# ADR-003 — Provider de e-mail
|
||||
|
||||
- Status: Proposed
|
||||
- Data: 2026-10-02
|
||||
- Pendência: P-011
|
||||
- Relacionada: P-001
|
||||
- Decisão: nenhuma
|
||||
|
||||
## Contexto
|
||||
|
||||
Download e e-mail usam o PDF da versão formal exibida. O envio não muda o status `Gerada`. A documentação de ecossistema cita Resend em outros contextos. Isso não formaliza o provider deste módulo.
|
||||
|
||||
P-001 também segue aberto: o que fazer quando o workspace não tem e-mail comercial para Reply-To.
|
||||
|
||||
## Alternativas
|
||||
|
||||
1. Resend. Citado fora deste módulo. Não adotado aqui.
|
||||
2. Outro provider HTTP transacional.
|
||||
3. SMTP operado por este produto.
|
||||
4. Não enviar até haver provider e regra de Reply-To. É o comportamento do port hoje, não uma escolha de produto para o MVP.
|
||||
|
||||
## Critérios para sair de Proposed
|
||||
|
||||
- Provider nomeado, conta e ambiente definidos.
|
||||
- O anexo é o `pdfRef` da versão exibida, não uma nova renderização.
|
||||
- Falha de envio não altera status, número nem versão.
|
||||
- Reply-To: ou o e-mail comercial do workspace, ou a regra explícita de P-001. O provider não inventa remetente.
|
||||
- Evento em `proposal_email_events` com resultado e id do provider quando houver.
|
||||
- Corpo, assunto e destinatário não vão para o Sentry.
|
||||
|
||||
## Impacto no código desta fase
|
||||
|
||||
`ProposalEmailProvider` devolve `blocked / P-001` sem Reply-To resolvido e `blocked / P-011` quando o Reply-To existe mas não há provider. Não há cliente HTTP.
|
||||
|
||||
## Impacto no prompt 02
|
||||
|
||||
A tabela `proposal_email_events` pode ser criada com `provider_message_id` anulável e `result` textual. Não gravar um check constraint com o nome de um provider.
|
||||
|
||||
## O que aprovar o provider não decide
|
||||
|
||||
P-001 continua uma pendência separada. Aprovar Resend, ou outro nome, não define o fallback de Reply-To.
|
||||
@@ -0,0 +1,39 @@
|
||||
# ADR-004 — Limites e segurança de arquivo
|
||||
|
||||
- Status: Proposed
|
||||
- Data: 2026-10-02
|
||||
- Pendência: P-006
|
||||
- Decisão: nenhuma
|
||||
|
||||
## Contexto
|
||||
|
||||
O upload do modelo aceita PDF, PPTX e DOCX. A especificação deixa abertos tamanho máximo, antivírus, sandbox e o que fazer com extração parcial. P-012 também deixa abertas as metas numéricas de tempo e tamanho. Este ADR não preenche nenhum desses números.
|
||||
|
||||
## Alternativas
|
||||
|
||||
1. Allowlist de MIME e extensão, com teto de tamanho, sem antivírus no MVP.
|
||||
2. Antivírus síncrono antes de persistir o arquivo.
|
||||
3. Abertura do arquivo só em sandbox, com timeout.
|
||||
4. Rejeitar qualquer extração parcial. A alternativa simétrica, aceitar documento parcial, também fica registrada e não foi escolhida.
|
||||
|
||||
Nenhuma combinação foi aprovada. Não há valor padrão de megabytes, timeout ou lista de assinaturas.
|
||||
|
||||
## Critérios para sair de Proposed
|
||||
|
||||
- Tamanho máximo por arquivo e por workspace, ou a decisão explícita de não ter teto.
|
||||
- Varredura: obrigatória, adiada ou dispensada no MVP, com o risco aceito.
|
||||
- Onde o arquivo é aberto e o que acontece se o conversor não terminar.
|
||||
- Extração parcial: rejeita o upload ou segue com o que foi lido. Isso altera o rascunho de modelo e precisa estar explícito.
|
||||
- Falha de política não cria rascunho de modelo nem dispara o motor do ADR-002.
|
||||
|
||||
## Impacto no código desta fase
|
||||
|
||||
`FileSecurityPolicy` só tem `unapproved` ou `approved` com uma referência de decisão. Não há campos `maxBytes` nem `timeoutMs`. A ingestão bloqueia em P-006 enquanto a política estiver `unapproved`.
|
||||
|
||||
## Impacto no prompt 02
|
||||
|
||||
Pode existir referência de storage privado para o arquivo de origem. Não criar check de tamanho, coluna de status de antivírus com fornecedor escolhido, nem job de varredura. Signed URL e bucket entram quando o fluxo de upload existir, com isolamento por workspace.
|
||||
|
||||
## Relação com os outros ADRs
|
||||
|
||||
P-010 escolhe como ler o arquivo. P-006 escolhe se ele pode ser aceito. Os dois precisam estar Approved antes do upload real do prompt 06. O checklist humano pede essa revisão antes do Pacote B.
|
||||
Reference in new issue
Block a user