Implementa o MVP do Adaptador de Planilhas no Elo Pro.
O módulo usa a identidade Supabase, isola cada workspace e registra storage, TTL, runner e biblioteca XLSX como decisões ainda abertas. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
6e23f1533b
144 files changed
+19060
No files matched your search
@@ -0,0 +1,42 @@
|
||||
# Pacote de Prompts — Adaptador de Planilhas Elo Pro
|
||||
|
||||
Este pacote foi preparado para construir o MVP do **Adaptador de Planilhas** dentro do ecossistema **Elo Pro** usando Cursor.
|
||||
|
||||
## Como usar
|
||||
|
||||
1. Coloque esta pasta dentro do repositório (por exemplo, `docs/cursor-prompts/spreadsheet-adapter/`) ou mantenha-a aberta ao lado do projeto.
|
||||
2. Execute os prompts na ordem numérica. Não envie todos de uma vez.
|
||||
3. Em cada etapa, peça ao Cursor para **primeiro inspecionar o repositório e apresentar um plano curto**, e somente então alterar código.
|
||||
4. Após cada pacote, rode lint, typecheck e testes pertinentes, revise o diff e faça um commit antes de seguir.
|
||||
5. Se o repositório Elo Pro já tiver implementações equivalentes (auth, workspace, RLS, design system, audit log, feature flags, Sentry, Supabase clients), **reutilize-as**. Não crie versões paralelas.
|
||||
6. As pendências arquiteturais ainda não decididas (storage, job runner, TTL, biblioteca XLSX, soft delete) devem ser implementadas somente se houver uma decisão existente no repositório; caso contrário, documente a decisão necessária e use uma abstração que permita troca posterior.
|
||||
|
||||
## Ordem recomendada
|
||||
|
||||
- `01-MASTER-CONTEXT.md` — contexto fixo e regras que o agente deve respeitar em todas as etapas.
|
||||
- `02-REPO-AUDIT-PLAN.md` — auditoria do repositório Elo Pro e plano de integração.
|
||||
- `03-FOUNDATION-ROUTES-FEATURE-FLAG.md` — esqueleto do módulo e rotas.
|
||||
- `04-AUTH-WORKSPACE-PERMISSIONS-RLS.md` — identidade única, workspace, autorização e RLS.
|
||||
- `05-DATABASE-MIGRATIONS.md` — schema do módulo.
|
||||
- `06-DESIGN-SYSTEM-APP-SHELL.md` — UI Elo Pro, shell e estados comuns.
|
||||
- `07-MODEL-MANAGEMENT.md` — gestão de modelos e configuração de upload.
|
||||
- `08-SOURCE-UPLOAD-VALIDATION.md` — fontes, validação, abas e cabeçalho.
|
||||
- `09-MAPPING-PREVIEW.md` — mapeamento 1:1 e revisão.
|
||||
- `10-JOBS-PROCESSING-EXPORTS.md` — jobs, processamento sequencial e saídas.
|
||||
- `11-REDIS-PROGRESS-RESILIENCE.md` — lock, progresso, idempotência e falhas.
|
||||
- `12-AUDIT-SENTRY-SECURITY.md` — auditoria, observabilidade e hardening.
|
||||
- `13-TESTING-QA.md` — testes unitários, integração, RLS, E2E e performance.
|
||||
- `14-DEPLOYMENT-OPERATIONS.md` — staging, migrations, feature flag e rollback.
|
||||
- `15-FINAL-GAP-REVIEW.md` — revisão final contra o escopo.
|
||||
|
||||
## Regra de precedência
|
||||
|
||||
Quando houver conflito de informação, siga:
|
||||
|
||||
1. Regra de negócio validada do produto.
|
||||
2. Arquitetura e segurança já existentes do Elo Pro.
|
||||
3. Comportamento útil comprovado pelo primeiro MVP.
|
||||
4. Documento V2 do Adaptador.
|
||||
5. Fluxos/protótipos antigos.
|
||||
|
||||
Não invente regra de negócio para preencher lacunas. Registre a lacuna em `docs/decisions/` ou em uma seção `OPEN DECISIONS` no relatório da etapa.
|
||||
@@ -0,0 +1,185 @@
|
||||
# MASTER CONTEXT — Adaptador de Planilhas Elo Pro
|
||||
|
||||
Use este contexto em **todas** as etapas de implementação.
|
||||
|
||||
## Papel do agente
|
||||
|
||||
Você está implementando um módulo de produção dentro do ecossistema Elo Pro. Trabalhe como engenheiro sênior full-stack. Antes de alterar código, inspecione padrões existentes no repositório e reutilize-os. Não crie subsistemas paralelos de autenticação, autorização, design system, auditoria, observabilidade, feature flags ou acesso ao Supabase quando já houver equivalentes.
|
||||
|
||||
## Objetivo do produto
|
||||
|
||||
O Adaptador recebe planilhas de origens diferentes, valida sua estrutura, mapeia colunas manualmente para um modelo padronizado, mostra uma prévia do resultado e gera um novo arquivo consolidado sem alterar o modelo original.
|
||||
|
||||
Fluxo principal:
|
||||
|
||||
`Elo Pro autenticado -> Adaptador -> selecionar modelo -> carregar fonte(s) -> selecionar aba/cabeçalho quando necessário -> validar -> mapear -> revisar -> processar -> acompanhar progresso -> baixar -> continuar com outra fonte ou encerrar`.
|
||||
|
||||
## Identidade e login — regra inegociável
|
||||
|
||||
- O Adaptador **NÃO possui login próprio**.
|
||||
- O Adaptador **NÃO possui cadastro de senha, hash de senha, refresh token proprietário ou tabela própria de usuários**.
|
||||
- Use o mesmo **Supabase Auth** do Elo Pro.
|
||||
- Use o mesmo `auth.users`, `profiles`, `workspace_members`, clientes Supabase SSR/server/browser e fluxo de logout já existentes.
|
||||
- Ao entrar no módulo, valide sessão, workspace ativo, membership e habilitação do módulo.
|
||||
- Ausência de sessão deve seguir o fluxo central de autenticação Elo Pro.
|
||||
- Logout encerra a sessão Elo Pro.
|
||||
- A meta é uma identidade/uma senha para vários apps do ecossistema. Não copie usuários entre bancos e não crie credenciais duplicadas.
|
||||
|
||||
## Tenant e autorização
|
||||
|
||||
- Tenant técnico: `workspace_id`.
|
||||
- Toda persistência do módulo deve ser isolada por workspace.
|
||||
- RLS é obrigatória quando aplicável.
|
||||
- Não aceite `workspace_id` do cliente como verdade. Derive/valide no servidor conforme padrão Elo Pro.
|
||||
- Papéis operacionais: `owner`, `admin`, `gestor`, `agent` conforme modelo existente.
|
||||
- `owner/admin`: gestão de modelos e configurações.
|
||||
- `gestor/agent`: fluxo operacional. Upload de modelo só se configuração específica permitir.
|
||||
- `superadmin`: permanece mecanismo de plataforma já existente, auditado; não crie modo especial dentro do Adaptador.
|
||||
- Segurança deve existir no servidor/banco. Esconder botão no frontend é apenas UX.
|
||||
|
||||
## Regras de negócio do MVP
|
||||
|
||||
- Até 10 modelos ativos por workspace.
|
||||
- Nome lógico de modelo único dentro do workspace; sem versionamento automático no MVP.
|
||||
- Entradas suportadas: XLSX e CSV.
|
||||
- XLS, ODS e XML ficam fora do MVP.
|
||||
- Fonte: até 10 MB e 50.000 linhas úteis por arquivo.
|
||||
- Até 10 fontes por operação/jornada.
|
||||
- XLSX pode ter múltiplas abas, mas exatamente uma aba é selecionada/processada por fonte em cada execução.
|
||||
- Permitir seleção da linha de cabeçalho quando necessário.
|
||||
- Toda coluna utilizada precisa ter cabeçalho identificável.
|
||||
- Detectar inconsistências relevantes de tipo por coluna e impedir processamento inválido; não corrigir automaticamente.
|
||||
- Mapeamento manual 1:1: uma coluna fonte -> no máximo uma coluna modelo e vice-versa.
|
||||
- Todas as colunas obrigatórias do modelo devem estar mapeadas.
|
||||
- Mapeamento não vira template reutilizável no MVP.
|
||||
- Deve existir etapa de pré-visualização antes do processamento.
|
||||
- Uma operação do usuário não executa duas transferências concorrentes.
|
||||
- Modelo persistido é imutável durante transformação. Saída é sempre novo artefato.
|
||||
- Modelos são persistentes. Fontes e saídas são temporárias, sujeitas a TTL.
|
||||
- Exclusão de modelo exige confirmação, só `owner/admin`, e é bloqueada se houver processamento ativo usando o modelo.
|
||||
- Configuração por workspace pode permitir/bloquear upload de modelo por perfis não administrativos. Isso não concede exclusão/gestão geral.
|
||||
- Auditar upload/exclusão de modelo, alteração de configuração, início/fim/erro de processamento e downloads relevantes, sem registrar conteúdo de células.
|
||||
- Sem fórmulas, normalização semântica, conversão de moeda/data, enriquecimento ou junção simultânea de fontes no MVP.
|
||||
|
||||
## Stack obrigatória
|
||||
|
||||
Frontend:
|
||||
- Next.js 16, App Router
|
||||
- React 19
|
||||
- TypeScript 5
|
||||
- Tailwind CSS v4
|
||||
- Lucide React
|
||||
- `@dnd-kit` para drag and drop acessível
|
||||
- TanStack Query v5 para estado remoto/cache
|
||||
- `@react-pdf/renderer` para PDF
|
||||
|
||||
Backend/infra:
|
||||
- Supabase Auth + PostgreSQL com `@supabase/supabase-js` e `@supabase/ssr`
|
||||
- Redis via `ioredis`
|
||||
- Sentry client/server/edge
|
||||
- `postgres` + `tsx` para migrations/ETL onde esse for o padrão do repositório
|
||||
|
||||
IA:
|
||||
- `@anthropic-ai/sdk` pode existir na stack, mas **não participa do caminho crítico do MVP**.
|
||||
|
||||
Qualidade:
|
||||
- Vitest
|
||||
- ESLint 9
|
||||
- typecheck estrito conforme padrão do monorepo/repo
|
||||
|
||||
## UX/UI — EloPro Design System Global V2.1
|
||||
|
||||
O Adaptador não cria Design System próprio.
|
||||
|
||||
- Interface predominantemente clara.
|
||||
- Cloud White `#FBFBFE`: base.
|
||||
- Midnight Ink `#071B45`: texto/estrutura.
|
||||
- Action/Primary Blue: ações principais conforme token oficial do repo.
|
||||
- Bright Blue `#2F8FFF`: foco/hover/ativos quando previsto.
|
||||
- Aqua Signal `#00C2A8`: sucesso, continuidade e progresso.
|
||||
- Warning `#F39A2D`.
|
||||
- Error `#E63946`, sempre com texto/ícone; nunca cor isolada.
|
||||
- Tipografia operacional: Manrope.
|
||||
- Espaçamento base: 4px.
|
||||
- Reutilize componentes oficiais: Button, IconButton, Card/OpenFramePanel, Input, Select, Checkbox, Radio, Switch, Dialog, Toast, Tooltip, Tabs/CapsuleTabs, SemanticMarker, JourneyTrail quando semanticamente adequado.
|
||||
- Lucide React para ícones.
|
||||
- Drag-and-drop precisa ter alternativa via teclado/select.
|
||||
- Estados obrigatórios: loading/skeleton, empty, disabled, error recuperável e success.
|
||||
- Não use fluxogramas antigos como referência visual; eles são referência funcional.
|
||||
|
||||
## Modelo de dados proposto
|
||||
|
||||
Adapte nomes/convenções ao repo, mantendo semântica:
|
||||
|
||||
- `spreadsheet_adapter_settings`
|
||||
- `workspace_id` PK/FK
|
||||
- `allow_non_admin_model_upload`
|
||||
- timestamps
|
||||
|
||||
- `spreadsheet_models`
|
||||
- `id`, `workspace_id`, `name`, `original_filename`, `format`, `storage_key`
|
||||
- `sheet_name`, `header_row`, `columns_schema jsonb`
|
||||
- `created_by`, `created_at`, `status`
|
||||
|
||||
- `spreadsheet_jobs`
|
||||
- `id`, `workspace_id`, `user_id`, `model_id`, `status`
|
||||
- `source_count`, `current_source`, `output_format`, `progress`
|
||||
- `error_code`, `started_at`, `finished_at`, `created_at`
|
||||
|
||||
- `spreadsheet_job_sources`
|
||||
- `id`, `job_id`, `source_name`, `temp_storage_key`
|
||||
- `selected_sheet`, `header_row`, `row_count`, `size_bytes`, `status`, `expires_at`
|
||||
|
||||
- `spreadsheet_job_mappings`
|
||||
- `id`, `job_source_id`, `source_column`, `model_column`, `is_required`, `position`
|
||||
|
||||
- Reuse `audit_log` existente quando compatível.
|
||||
|
||||
## Rotas sugeridas
|
||||
|
||||
Adapte ao padrão existente do Elo Pro:
|
||||
|
||||
- `GET /api/spreadsheet-adapter/models`
|
||||
- `POST /api/spreadsheet-adapter/models`
|
||||
- `DELETE /api/spreadsheet-adapter/models/:id`
|
||||
- `GET/PATCH /api/spreadsheet-adapter/settings`
|
||||
- `POST /api/spreadsheet-adapter/sources/validate`
|
||||
- `POST /api/spreadsheet-adapter/jobs`
|
||||
- `GET /api/spreadsheet-adapter/jobs/:id`
|
||||
- `POST /api/spreadsheet-adapter/jobs/:id/process`
|
||||
- `GET /api/spreadsheet-adapter/jobs/:id/download?format=xlsx|csv|pdf`
|
||||
|
||||
Server Actions podem substituir rotas quando o padrão Elo Pro indicar, desde que contratos de segurança, teste e idempotência permaneçam claros.
|
||||
|
||||
## Pendências que NÃO devem ser inventadas
|
||||
|
||||
Se o repo não trouxer uma decisão, pare e documente a alternativa recomendada em vez de “decidir silenciosamente”:
|
||||
|
||||
1. Object storage definitivo: Supabase Storage privado ou equivalente S3.
|
||||
2. Topologia de login único entre hosts/domínios.
|
||||
3. Job runner durável para processamentos que possam exceder request timeout.
|
||||
4. TTL exato de fontes/saídas temporárias.
|
||||
5. Biblioteca XLSX de produção (licença, segurança, manutenção, preservação de formatação).
|
||||
6. Exclusão física vs soft delete de modelos.
|
||||
|
||||
## Segurança mínima
|
||||
|
||||
- RLS e checagem server-side contra IDOR.
|
||||
- Validar extensão, MIME e assinatura/estrutura do arquivo.
|
||||
- Proteger contra path traversal e nomes maliciosos.
|
||||
- Tratar CSV injection em exportações quando relevante.
|
||||
- Nunca logar conteúdo de célula no Sentry/audit log.
|
||||
- Não enviar planilha ao Anthropic no MVP.
|
||||
- Storage privado; download somente após autorização.
|
||||
- Sanitizar nomes e metadados exibidos.
|
||||
|
||||
## Definição de pronto geral
|
||||
|
||||
Uma etapa só está concluída quando:
|
||||
- implementação segue padrões existentes do Elo Pro;
|
||||
- lint/typecheck passam;
|
||||
- testes da etapa passam;
|
||||
- segurança de workspace/permissões foi coberta;
|
||||
- estados de UX relevantes existem;
|
||||
- nenhuma nova autenticação paralela foi criada;
|
||||
- mudanças e decisões abertas estão documentadas.
|
||||
@@ -0,0 +1,58 @@
|
||||
# PROMPT 02 — Auditoria do repositório e plano de integração
|
||||
|
||||
Use `01-MASTER-CONTEXT.md` como contexto obrigatório.
|
||||
|
||||
## Tarefa
|
||||
|
||||
Antes de escrever funcionalidades, faça uma auditoria técnica do repositório Elo Pro para descobrir os padrões reais que o Adaptador deve reutilizar.
|
||||
|
||||
### Inspecione especificamente
|
||||
|
||||
1. Estrutura Next.js/App Router e convenções de pastas.
|
||||
2. Implementação atual de Supabase:
|
||||
- browser client;
|
||||
- server client;
|
||||
- SSR/cookies;
|
||||
- middleware;
|
||||
- refresh de sessão;
|
||||
- logout.
|
||||
3. Como o app resolve `workspace_id` ativo e membership.
|
||||
4. Tipos/papéis reais existentes (`owner/admin/gestor/agent` ou equivalentes).
|
||||
5. RLS/migrations existentes e helpers de autorização.
|
||||
6. Sistema de feature flags/planos/módulos.
|
||||
7. Design System Elo Pro: componentes, tokens, Tailwind, fontes, ícones e layouts.
|
||||
8. TanStack Query: QueryClient, providers, query keys e padrão de mutations.
|
||||
9. Sentry: client/server/edge, scrubbing e tags.
|
||||
10. Redis: conexão, helpers, namespaces e fallback.
|
||||
11. Audit log existente.
|
||||
12. Storage existente e políticas de bucket.
|
||||
13. Padrão para Route Handlers/Server Actions.
|
||||
14. Estratégia de testes, fixtures, Vitest e E2E se houver.
|
||||
15. CI/CD, migrations e ambientes.
|
||||
|
||||
## Não faça ainda
|
||||
|
||||
- Não crie tabelas.
|
||||
- Não implemente telas.
|
||||
- Não instale biblioteca XLSX.
|
||||
- Não altere autenticação.
|
||||
|
||||
## Saída esperada
|
||||
|
||||
Crie `docs/spreadsheet-adapter/00-repo-integration-audit.md` contendo:
|
||||
|
||||
- padrões existentes que serão reutilizados;
|
||||
- caminhos/arquivos relevantes;
|
||||
- diferenças entre o MASTER CONTEXT e o estado atual do repo;
|
||||
- decisões já resolvidas pelo repo;
|
||||
- `OPEN DECISIONS` somente para o que realmente não estiver definido;
|
||||
- arquitetura proposta do módulo em 1 diagrama Mermaid;
|
||||
- plano de implementação por fases e dependências.
|
||||
|
||||
No chat do Cursor, finalize com:
|
||||
|
||||
1. resumo de no máximo 15 bullets;
|
||||
2. lista dos arquivos inspecionados mais importantes;
|
||||
3. lista de decisões que exigem confirmação humana.
|
||||
|
||||
Não altere código de produção nesta etapa.
|
||||
@@ -0,0 +1,48 @@
|
||||
# PROMPT 03 — Fundação do módulo, rotas e feature flag
|
||||
|
||||
Use `01-MASTER-CONTEXT.md` e a auditoria produzida no Prompt 02.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Criar o esqueleto do Adaptador dentro do Elo Pro sem duplicar infraestrutura já existente.
|
||||
|
||||
## Implementar
|
||||
|
||||
1. Rota/página principal do Adaptador seguindo a convenção do App Router existente.
|
||||
2. Entrada do módulo pelo mecanismo de navegação do Elo Pro.
|
||||
3. Proteção por feature flag/plano/módulo conforme sistema existente.
|
||||
4. Layout/shell inicial reutilizando navegação, workspace e componentes globais.
|
||||
5. Rotas internas planejadas, por exemplo:
|
||||
- dashboard;
|
||||
- operação nova/atual;
|
||||
- configurações (somente perfis administrativos);
|
||||
Adapte nomes ao padrão do repo.
|
||||
6. Boundary de erro e loading states no padrão Elo Pro.
|
||||
7. Tipos centrais do domínio do Adaptador em local coerente com o repo.
|
||||
8. Estrutura de módulos de domínio para evitar lógica pesada nos componentes React.
|
||||
|
||||
## Regras
|
||||
|
||||
- Não crie login próprio.
|
||||
- Não crie novo seletor de workspace se o Elo Pro já possui um.
|
||||
- Não permita acesso ao módulo sem feature habilitada.
|
||||
- Não implemente lógica de planilha ainda.
|
||||
- Não introduza store global nova se não for necessária.
|
||||
|
||||
## UX mínima
|
||||
|
||||
Dashboard inicial deve explicar o propósito e fornecer um CTA claro para iniciar uma adaptação, mas pode usar dados mockados somente dentro de testes/story fixtures. Em produção, não invente modelos/fonte falsos.
|
||||
|
||||
## Testes
|
||||
|
||||
- acesso com módulo habilitado;
|
||||
- acesso com módulo desabilitado;
|
||||
- estado loading/error;
|
||||
- rota de configurações inacessível a quem não tem permissão administrativa.
|
||||
|
||||
## Entrega
|
||||
|
||||
- código;
|
||||
- testes;
|
||||
- `docs/spreadsheet-adapter/01-foundation.md` com rotas, guardas e decisões.
|
||||
- reporte comandos rodados e resultados.
|
||||
@@ -0,0 +1,52 @@
|
||||
# PROMPT 04 — Autenticação Elo Pro, workspace, permissões e RLS
|
||||
|
||||
Use o MASTER CONTEXT. Este é um pacote de segurança crítica.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Garantir que o Adaptador opere integralmente com a identidade e o workspace existentes do Elo Pro.
|
||||
|
||||
## Implementar/validar
|
||||
|
||||
1. Resolver sessão via mecanismo Supabase SSR já existente.
|
||||
2. Resolver usuário/perfil sem segunda consulta desnecessária quando contexto já estiver disponível.
|
||||
3. Resolver workspace ativo e validar `workspace_members` no servidor.
|
||||
4. Helpers de autorização do módulo reutilizando os helpers Elo Pro quando existirem:
|
||||
- `canUseSpreadsheetAdapter`
|
||||
- `canManageSpreadsheetModels`
|
||||
- `canUploadSpreadsheetModel`
|
||||
Os nomes podem variar; a semântica deve permanecer.
|
||||
5. Preparar políticas RLS para as futuras tabelas do módulo segundo as convenções do repo.
|
||||
6. Garantir que `workspace_id` nunca seja confiado diretamente a payload de cliente.
|
||||
7. Integrar feature flag à autorização.
|
||||
8. Garantir comportamento correto ao trocar workspace.
|
||||
|
||||
## Perfis esperados
|
||||
|
||||
- `owner/admin`: podem gerir modelos/configuração.
|
||||
- `gestor/agent`: podem operar adaptações.
|
||||
- upload de modelo por não-admin somente se setting do workspace permitir.
|
||||
- Superadmin segue mecanismos globais existentes, sem bypass local criado pelo Adaptador.
|
||||
|
||||
## Testes obrigatórios
|
||||
|
||||
- usuário sem sessão;
|
||||
- usuário autenticado sem membership;
|
||||
- workspace A tentando ler/escrever B;
|
||||
- agent tentando ação administrativa;
|
||||
- admin/owner executando ação administrativa;
|
||||
- feature flag desligada;
|
||||
- troca de workspace invalidando cache/dados anteriores.
|
||||
|
||||
## Restrições
|
||||
|
||||
Não altere o modelo central de autenticação para “facilitar” o módulo. O Adaptador deve se adaptar ao Elo Pro.
|
||||
|
||||
## Entrega
|
||||
|
||||
Documente em `docs/spreadsheet-adapter/02-auth-workspace-permissions.md`:
|
||||
- fluxo de autenticação;
|
||||
- fonte do workspace;
|
||||
- matriz de permissões efetiva;
|
||||
- estratégia RLS;
|
||||
- testes executados.
|
||||
@@ -0,0 +1,96 @@
|
||||
# PROMPT 05 — Banco de dados e migrations
|
||||
|
||||
Use o MASTER CONTEXT e as convenções de migrations descobertas no Prompt 02.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Criar o schema persistente mínimo do Adaptador, multi-tenant por `workspace_id`, sem duplicar entidades do Elo Pro.
|
||||
|
||||
## Tabelas alvo
|
||||
|
||||
Adapte nomenclatura/campos às convenções do repo, preservando a semântica:
|
||||
|
||||
### spreadsheet_adapter_settings
|
||||
- `workspace_id` PK/FK
|
||||
- `allow_non_admin_model_upload boolean not null default false`
|
||||
- timestamps
|
||||
|
||||
### spreadsheet_models
|
||||
- id
|
||||
- workspace_id
|
||||
- name lógico
|
||||
- original_filename
|
||||
- format (`xlsx|csv`)
|
||||
- storage_key
|
||||
- selected/default sheet quando aplicável
|
||||
- header_row
|
||||
- `columns_schema jsonb`
|
||||
- created_by
|
||||
- created_at / updated_at
|
||||
- status
|
||||
- constraint de nome único ativo por workspace, se compatível com estratégia de exclusão
|
||||
|
||||
### spreadsheet_jobs
|
||||
- id
|
||||
- workspace_id
|
||||
- user_id
|
||||
- model_id
|
||||
- status com enum/check coerente
|
||||
- source_count
|
||||
- current_source
|
||||
- output_format
|
||||
- progress
|
||||
- error_code / error_metadata sanitizada
|
||||
- timestamps de ciclo
|
||||
|
||||
### spreadsheet_job_sources
|
||||
- id
|
||||
- job_id
|
||||
- source_name
|
||||
- temp_storage_key
|
||||
- selected_sheet
|
||||
- header_row
|
||||
- row_count
|
||||
- size_bytes
|
||||
- status
|
||||
- expires_at
|
||||
|
||||
### spreadsheet_job_mappings
|
||||
- id
|
||||
- job_source_id
|
||||
- source_column
|
||||
- model_column
|
||||
- is_required
|
||||
- position
|
||||
- unicidade suficiente para garantir 1:1
|
||||
|
||||
### audit log
|
||||
Reutilize o audit log Elo Pro se a estrutura suportar os eventos do módulo. Não crie tabela paralela sem necessidade.
|
||||
|
||||
## Regras de banco
|
||||
|
||||
- FKs corretas e cascades cuidadosamente escolhidas.
|
||||
- Índices por `workspace_id`, status e relacionamentos frequentes.
|
||||
- RLS em todas as tabelas tenant-aware.
|
||||
- Constraints para integridade que não dependam só do frontend.
|
||||
- Não persistir conteúdo bruto das planilhas no PostgreSQL.
|
||||
- Não armazenar segredos.
|
||||
|
||||
## Decisões abertas
|
||||
|
||||
Se soft delete vs delete físico ainda estiver aberto, implemente schema que não torne a decisão irreversível e documente a escolha temporária. Não invente política de retenção.
|
||||
|
||||
## Testes
|
||||
|
||||
- migrations sobem do zero;
|
||||
- rollback/estratégia de reversão documentada;
|
||||
- RLS A != B;
|
||||
- constraints de duplicidade;
|
||||
- 1:1 de mapping;
|
||||
- FKs e deleções.
|
||||
|
||||
## Entrega
|
||||
|
||||
- migrations;
|
||||
- tipos gerados/atualizados conforme padrão Supabase do repo;
|
||||
- `docs/spreadsheet-adapter/03-data-model.md` com ERD Mermaid.
|
||||
@@ -0,0 +1,56 @@
|
||||
# PROMPT 06 — Design System Elo Pro e shell de UX
|
||||
|
||||
Use o MASTER CONTEXT e componentes reais do Design System encontrados no repo.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Construir a estrutura visual do Adaptador sem criar um design system paralelo.
|
||||
|
||||
## Criar
|
||||
|
||||
1. Dashboard do módulo.
|
||||
2. Estrutura da jornada:
|
||||
- modelo;
|
||||
- fontes;
|
||||
- mapeamento;
|
||||
- revisão;
|
||||
- processamento;
|
||||
- resultado.
|
||||
3. Área de configurações administrativa.
|
||||
4. Componentes de estado comuns:
|
||||
- loading/skeleton;
|
||||
- empty state;
|
||||
- error recuperável;
|
||||
- warning;
|
||||
- success;
|
||||
- disabled.
|
||||
5. Navegação/journey indicator usando os componentes Elo Pro adequados. Não force `JourneyTrail` como stepper se o componente não tiver essa semântica.
|
||||
|
||||
## Requisitos visuais
|
||||
|
||||
- Manrope.
|
||||
- Cloud White como base predominante.
|
||||
- Midnight Ink para texto/estrutura.
|
||||
- Action/Primary Blue para CTAs conforme token oficial.
|
||||
- Aqua Signal para sucesso/progresso.
|
||||
- Warning/Error conforme tokens.
|
||||
- Não usar cor como único sinal.
|
||||
- Lucide React.
|
||||
- Responsivo para desktop/tablet; mobile não é foco, mas não deve quebrar.
|
||||
- Foco visível, navegação por teclado, labels e ARIA adequados.
|
||||
|
||||
## Componentes
|
||||
|
||||
Reutilize Button, Card/OpenFramePanel, Dialog, Toast, Select, Input, Switch, Tooltip, SemanticMarker e demais oficiais. Se algum não existir exatamente, componha a partir dos primitives já adotados no Elo Pro, mantendo tokens.
|
||||
|
||||
## Não implementar ainda
|
||||
|
||||
Parsing real de planilhas ou jobs.
|
||||
|
||||
## Testes
|
||||
|
||||
Inclua testes de estados e acessibilidade básica dos componentes-chave.
|
||||
|
||||
## Entrega
|
||||
|
||||
`docs/spreadsheet-adapter/04-ux-shell.md` com mapa de páginas e componentes reutilizados.
|
||||
@@ -0,0 +1,64 @@
|
||||
# PROMPT 07 — Gestão de modelos e configuração administrativa
|
||||
|
||||
Use o MASTER CONTEXT.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Implementar o ciclo de vida de modelos do workspace e a configuração que permite upload por perfis não administrativos.
|
||||
|
||||
## Funcionalidades
|
||||
|
||||
### Lista de modelos
|
||||
- listar somente workspace ativo;
|
||||
- ordem alfabética;
|
||||
- nome, data, criador e metadados úteis;
|
||||
- empty state e loading state;
|
||||
- seleção do modelo para operação.
|
||||
|
||||
### Upload de modelo
|
||||
- XLSX e CSV apenas;
|
||||
- drag-and-drop + file picker;
|
||||
- critérios de upload visíveis em Dialog/ajuda contextual;
|
||||
- até 10 modelos ativos por workspace;
|
||||
- impedir nome lógico duplicado;
|
||||
- validar cabeçalho/estrutura mínima;
|
||||
- permitir escolha de aba e linha de cabeçalho quando necessário;
|
||||
- persistir arquivo somente em storage privado aprovado pelo repo;
|
||||
- persistir metadados/`columns_schema` no PostgreSQL.
|
||||
|
||||
### Exclusão
|
||||
- owner/admin apenas;
|
||||
- Dialog de confirmação;
|
||||
- bloquear se houver job ativo usando o modelo;
|
||||
- auditar;
|
||||
- respeitar estratégia delete/soft delete já decidida.
|
||||
|
||||
### Setting de upload por não-admin
|
||||
- Switch oficial;
|
||||
- `owner/admin` alteram;
|
||||
- valor por workspace;
|
||||
- server-side authorization;
|
||||
- `gestor/agent` apenas recebem permissão de upload, não de exclusão/administração.
|
||||
|
||||
## Segurança
|
||||
|
||||
- storage key não deve ser construída de modo vulnerável a path traversal;
|
||||
- MIME/extensão/estrutura devem ser checados;
|
||||
- não confiar em metadata do navegador;
|
||||
- sem bucket público.
|
||||
|
||||
## API/Actions
|
||||
|
||||
Implemente no padrão do repo as operações equivalentes a:
|
||||
- listar;
|
||||
- criar;
|
||||
- excluir;
|
||||
- ler/alterar settings.
|
||||
|
||||
## Testes
|
||||
|
||||
Cubra 10 modelos, 11º bloqueado, duplicidade, papel não autorizado, setting ligado/desligado, RLS, job ativo e arquivo inválido.
|
||||
|
||||
## Entrega
|
||||
|
||||
Atualize documentação técnica e descreva o contrato de upload e erros possíveis.
|
||||
@@ -0,0 +1,49 @@
|
||||
# PROMPT 08 — Upload e validação de planilhas fonte
|
||||
|
||||
Use o MASTER CONTEXT.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Implementar carregamento temporário e validação estrutural das fontes sem persistência permanente.
|
||||
|
||||
## Requisitos
|
||||
|
||||
- Até 10 fontes por operação.
|
||||
- XLSX/CSV apenas.
|
||||
- Até 10 MB por arquivo.
|
||||
- Até 50.000 linhas úteis por arquivo.
|
||||
- Arquivo corrompido/inválido deve falhar individualmente sem destruir as demais fontes válidas.
|
||||
- XLSX multiaba: listar abas e exigir seleção de exatamente uma antes do mapeamento.
|
||||
- Permitir definir linha de cabeçalho quando o sistema não puder assumir a primeira linha.
|
||||
- Detectar cabeçalhos vazios/duplicados/problemáticos e apresentar causa clara.
|
||||
- Inferir tipos estruturais suficientes para alertar inconsistências relevantes; não transformar dados.
|
||||
- Retornar metadados para UI: abas, headers, row count, size, amostra segura e warnings.
|
||||
- Temporários devem receber `expires_at` e storage privado conforme política existente. Se TTL não estiver decidido, não invente número final; use configuração central/documentada.
|
||||
|
||||
## Parsing
|
||||
|
||||
Antes de instalar biblioteca XLSX, verifique se o repo já possui uma. Se não houver decisão aprovada, proponha 2–3 alternativas com licença/manutenção/segurança e pare antes de consolidar dependência de produção.
|
||||
|
||||
## UX
|
||||
|
||||
- lista de fontes com status individual;
|
||||
- progress/validation state;
|
||||
- erro recuperável por arquivo;
|
||||
- opção de remover/recarregar;
|
||||
- critérios acessíveis antes do upload.
|
||||
|
||||
## Segurança
|
||||
|
||||
- MIME spoofing;
|
||||
- arquivo zip bomb / estruturas anômalas quando aplicável ao XLSX;
|
||||
- path traversal;
|
||||
- limite de memória;
|
||||
- não logar conteúdo bruto.
|
||||
|
||||
## Testes
|
||||
|
||||
Arquivos válidos, 11º arquivo, >10MB, >50k, corrompido, CSV inválido, XLSX multiaba, header row alternativo, colunas sem título, tipos inconsistentes.
|
||||
|
||||
## Entrega
|
||||
|
||||
Documente códigos de erro estáveis para a UI e estratégia de temporários.
|
||||
@@ -0,0 +1,57 @@
|
||||
# PROMPT 09 — Mapeamento 1:1 e pré-visualização
|
||||
|
||||
Use o MASTER CONTEXT.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Implementar a etapa central do produto: mapear colunas fonte para colunas modelo e revisar o resultado antes de processar.
|
||||
|
||||
## Interface de mapeamento
|
||||
|
||||
- mostrar metadados da fonte selecionada e do modelo;
|
||||
- apresentar colunas fonte e destino claramente;
|
||||
- permitir `Select` como interação básica obrigatória;
|
||||
- adicionar drag-and-drop com `@dnd-kit` somente como melhoria, mantendo alternativa completa por teclado/select;
|
||||
- marcar colunas obrigatórias do modelo;
|
||||
- impedir mapeamento duplicado em ambos os sentidos;
|
||||
- permitir deixar colunas não obrigatórias sem mapeamento;
|
||||
- botão de continuar desabilitado enquanto obrigatórias faltarem;
|
||||
- mensagem textual indicando exatamente o que falta.
|
||||
|
||||
## Persistência
|
||||
|
||||
- mapping pertence à operação/fonte atual;
|
||||
- salvar de forma suficiente para retomar a jornada da operação, mas não convertê-lo em template reutilizável;
|
||||
- invalidar/recalcular quando fonte/modelo/header/aba mudar.
|
||||
|
||||
## Preview
|
||||
|
||||
Antes do processamento:
|
||||
- gerar amostra da estrutura resultante;
|
||||
- respeitar ordem/colunas do modelo;
|
||||
- não modificar o modelo persistido;
|
||||
- deixar claro que é prévia;
|
||||
- permitir voltar ao mapeamento sem perder estado válido;
|
||||
- permitir confirmar processamento.
|
||||
|
||||
## Acessibilidade
|
||||
|
||||
- drag via teclado ou alternativa equivalente;
|
||||
- labels explícitos;
|
||||
- foco previsível;
|
||||
- estados não dependem só de cor.
|
||||
|
||||
## Testes
|
||||
|
||||
- 1:1;
|
||||
- obrigatórias;
|
||||
- conflito;
|
||||
- desmapear/remapear;
|
||||
- troca de fonte;
|
||||
- troca de aba/header;
|
||||
- preview com ordem do modelo;
|
||||
- navegação por teclado.
|
||||
|
||||
## Entrega
|
||||
|
||||
Documente o algoritmo de validação de mapping e o contrato do preview.
|
||||
@@ -0,0 +1,61 @@
|
||||
# PROMPT 10 — Jobs, processamento e geração de arquivos
|
||||
|
||||
Use o MASTER CONTEXT.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Implementar o processamento real de uma fonte mapeada para um novo arquivo baseado no modelo, preservando o original.
|
||||
|
||||
## Ciclo do job
|
||||
|
||||
Defina estados explícitos e tipados, por exemplo:
|
||||
`draft -> validating -> ready -> processing -> completed | failed | expired | cancelled`
|
||||
Adapte ao padrão do repo sem perder clareza.
|
||||
|
||||
## Regras
|
||||
|
||||
- job sempre pertence a workspace e usuário;
|
||||
- validar novamente autorização e integridade no servidor antes de processar;
|
||||
- uma mesma operação do usuário não executa duas transferências simultâneas;
|
||||
- processamento deve ser idempotente para evitar cliques duplicados;
|
||||
- múltiplas fontes na mesma jornada são processadas sequencialmente;
|
||||
- o modelo original jamais é sobrescrito;
|
||||
- saída é novo arquivo;
|
||||
- mapping 1:1 e obrigatórias devem ser revalidados server-side;
|
||||
- erros não devem expor conteúdo sensível.
|
||||
|
||||
## Saídas
|
||||
|
||||
- XLSX;
|
||||
- CSV;
|
||||
- PDF via `@react-pdf/renderer` quando o formato fizer sentido para o resultado definido no produto.
|
||||
|
||||
Garanta compatibilidade de nomes, encoding, caracteres especiais e download autorizado.
|
||||
|
||||
## Preservação de modelo
|
||||
|
||||
Se o requisito de “manter formatação do modelo” depender da biblioteca XLSX, escreva teste de não regressão e documente limitações reais. Não prometa preservação que a implementação não suporte.
|
||||
|
||||
## Download
|
||||
|
||||
- autorização no momento do download;
|
||||
- URL assinada/stream privado conforme storage;
|
||||
- audit event relevante;
|
||||
- temporário com expiração;
|
||||
- nome de arquivo seguro e previsível.
|
||||
|
||||
## Job runner
|
||||
|
||||
Se o repo já tiver fila/worker, use-o. Se não tiver e o processamento puder exceder timeout do runtime atual, não esconda o problema dentro de uma request longa: crie abstração/ADR e implemente somente solução aprovada.
|
||||
|
||||
## Testes
|
||||
|
||||
- sucesso XLSX/CSV/PDF;
|
||||
- modelo intacto;
|
||||
- mapping inválido barrado;
|
||||
- idempotência;
|
||||
- dupla submissão;
|
||||
- usuário/workspace indevido;
|
||||
- caracteres especiais;
|
||||
- erro de storage;
|
||||
- retry seguro quando aplicável.
|
||||
@@ -0,0 +1,39 @@
|
||||
# PROMPT 11 — Redis, progresso, lock e resiliência
|
||||
|
||||
Use o MASTER CONTEXT e a implementação Redis existente do Elo Pro.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Adicionar coordenação efêmera sem transformar Redis em fonte de verdade.
|
||||
|
||||
## Implementar
|
||||
|
||||
1. Namespace claro para chaves do Adaptador.
|
||||
2. Lock por operação/usuário necessário para impedir processamento concorrente indevido.
|
||||
3. TTL do lock com renovação/cleanup seguro para evitar deadlock.
|
||||
4. Progresso efêmero em Redis quando trouxer benefício, mantendo status durável no PostgreSQL.
|
||||
5. Idempotency key para disparo de processamento, se o padrão do repo suportar.
|
||||
6. Query/polling/subscription da UI conforme arquitetura existente; TanStack Query deve invalidar/refetch adequadamente.
|
||||
7. Fallback claro se Redis estiver indisponível: falha controlada ou degradação segura, nunca execução duplicada silenciosa.
|
||||
|
||||
## UX de progresso
|
||||
|
||||
- percentual somente se for real/estimável; não invente precisão falsa;
|
||||
- estados textuais como “Validando”, “Processando”, “Gerando arquivo”;
|
||||
- sucesso e erro persistentes o suficiente para o usuário agir;
|
||||
- botão de processar desabilitado durante job ativo.
|
||||
|
||||
## Observabilidade
|
||||
|
||||
Tags de job ID e workspace ID técnico, sem dados de planilha.
|
||||
|
||||
## Testes
|
||||
|
||||
- lock adquirido;
|
||||
- lock concorrente;
|
||||
- expiração;
|
||||
- erro de Redis;
|
||||
- retry;
|
||||
- progresso;
|
||||
- refresh de página durante job;
|
||||
- job concluído enquanto UI estava fechada.
|
||||
@@ -0,0 +1,51 @@
|
||||
# PROMPT 12 — Auditoria, Sentry e hardening de segurança
|
||||
|
||||
Use o MASTER CONTEXT. Trate esta etapa como security review.
|
||||
|
||||
## Auditoria
|
||||
|
||||
Reutilize o mecanismo Elo Pro para registrar, no mínimo:
|
||||
- upload de modelo;
|
||||
- exclusão de modelo;
|
||||
- alteração do setting de upload por não-admin;
|
||||
- criação/início de job;
|
||||
- conclusão;
|
||||
- falha;
|
||||
- download relevante.
|
||||
|
||||
Registre IDs técnicos, actor, workspace, timestamps, ação e resultado. Não registre conteúdo de célula, planilha completa, token, segredo ou arquivo bruto.
|
||||
|
||||
## Sentry
|
||||
|
||||
- usar integrações client/server/edge existentes;
|
||||
- definir tags seguras: módulo, job_id, workspace_id técnico, error_code;
|
||||
- scrubbing de request body, headers e breadcrumbs;
|
||||
- não anexar arquivo nem amostra de linhas;
|
||||
- errors esperados de validação não devem gerar ruído como exception crítica.
|
||||
|
||||
## Hardening
|
||||
|
||||
Revisar e testar:
|
||||
- IDOR;
|
||||
- workspace forging;
|
||||
- bypass de papel;
|
||||
- MIME spoofing;
|
||||
- extensão enganosa;
|
||||
- path traversal;
|
||||
- nome de arquivo malicioso;
|
||||
- CSV injection nas exportações;
|
||||
- zip bomb/arquivo excessivamente complexo quando aplicável;
|
||||
- download de artefato de outro workspace;
|
||||
- replay/double-submit;
|
||||
- XSS em nomes de arquivo/headers;
|
||||
- logs contendo PII/dados financeiros.
|
||||
|
||||
## Headers/Runtime
|
||||
|
||||
Siga CSP/security headers já existentes. Não crie política conflitante com o app principal.
|
||||
|
||||
## Entrega
|
||||
|
||||
- testes automatizados onde possível;
|
||||
- `docs/spreadsheet-adapter/05-security-observability.md` com threat model resumido;
|
||||
- lista de riscos residuais e mitigação.
|
||||
@@ -0,0 +1,73 @@
|
||||
# PROMPT 13 — Testes e QA do MVP
|
||||
|
||||
Use o MASTER CONTEXT e todo o código produzido até aqui.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Criar cobertura suficiente para liberar piloto sem depender apenas de teste manual.
|
||||
|
||||
## Matriz mínima
|
||||
|
||||
### Unitário / Vitest
|
||||
- normalização/validação de cabeçalho;
|
||||
- limites de arquivo/linha;
|
||||
- nomes duplicados;
|
||||
- validação de tipo;
|
||||
- mapping 1:1;
|
||||
- obrigatórias;
|
||||
- transformação de linha;
|
||||
- geração de nomes de saída;
|
||||
- state machine do job.
|
||||
|
||||
### Componentes
|
||||
- upload;
|
||||
- Dialog;
|
||||
- Select;
|
||||
- drag-and-drop + alternativa teclado;
|
||||
- preview;
|
||||
- loading/error/disabled;
|
||||
- progress;
|
||||
- settings Switch.
|
||||
|
||||
### Integração
|
||||
- sessão válida/inválida;
|
||||
- workspace membership;
|
||||
- owner/admin/gestor/agent;
|
||||
- feature flag;
|
||||
- Redis indisponível;
|
||||
- storage failure;
|
||||
- job/download.
|
||||
|
||||
### Banco/RLS
|
||||
- workspace A não lê/escreve B;
|
||||
- agent não administra;
|
||||
- owner/admin administram;
|
||||
- setting de upload não-admin;
|
||||
- constraints de mapping/duplicidade.
|
||||
|
||||
### E2E
|
||||
Cenário principal:
|
||||
`login Elo Pro existente -> abrir Adaptador -> selecionar/subir modelo -> upload fonte -> selecionar aba/header -> mapear -> revisar -> processar -> baixar -> continuar`.
|
||||
|
||||
### Performance
|
||||
- fonte 10MB;
|
||||
- 50.000 linhas;
|
||||
- 10 fontes sequenciais;
|
||||
- dois usuários distintos processando em paralelo;
|
||||
- observar memória e timeout.
|
||||
|
||||
### Segurança
|
||||
Inclua os cenários do Prompt 12.
|
||||
|
||||
## Critérios de corte
|
||||
|
||||
- zero acesso cruzado nos testes RLS;
|
||||
- fluxo principal completo;
|
||||
- modelo original intacto;
|
||||
- sem segundo login;
|
||||
- erros inesperados correlacionados no Sentry;
|
||||
- lint/typecheck/test suite verdes.
|
||||
|
||||
## Entrega
|
||||
|
||||
Crie `docs/spreadsheet-adapter/06-test-plan-and-results.md` com matriz de testes, resultados e itens bloqueantes.
|
||||
@@ -0,0 +1,38 @@
|
||||
# PROMPT 14 — Deploy, operação e rollout
|
||||
|
||||
Use o MASTER CONTEXT e padrões CI/CD do Elo Pro.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Preparar o módulo para staging e piloto controlado.
|
||||
|
||||
## Implementar/documentar
|
||||
|
||||
1. Migrations idempotentes e ordem de deploy.
|
||||
2. Feature flag desligada por padrão, se esse for o padrão de rollout.
|
||||
3. Configuração de envs reutilizando naming conventions do Elo Pro.
|
||||
4. Redis em cada ambiente.
|
||||
5. Storage privado e políticas por ambiente.
|
||||
6. Sentry release/environment.
|
||||
7. Limites de runtime e job runner.
|
||||
8. Política de limpeza de temporários.
|
||||
9. Rollback técnico:
|
||||
- app;
|
||||
- migration;
|
||||
- feature flag;
|
||||
- workers/jobs.
|
||||
10. Checklist de smoke test pós-deploy.
|
||||
11. Runbook para job travado, Redis indisponível, storage indisponível e migration parcial.
|
||||
|
||||
## Segurança operacional
|
||||
|
||||
- nenhuma service role exposta ao cliente;
|
||||
- secrets somente no mecanismo padrão do ambiente;
|
||||
- downloads privados;
|
||||
- não criar buckets públicos para simplificar teste.
|
||||
|
||||
## Entrega
|
||||
|
||||
- `docs/spreadsheet-adapter/07-deployment-runbook.md`;
|
||||
- checklist de staging/piloto;
|
||||
- tabela de env vars necessárias sem valores secretos.
|
||||
@@ -0,0 +1,71 @@
|
||||
# PROMPT 15 — Revisão final e fechamento de gaps
|
||||
|
||||
Use `01-MASTER-CONTEXT.md` e todos os documentos/commits produzidos nas etapas anteriores.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Fazer uma revisão final do Adaptador contra o escopo V3 antes de declarar o MVP pronto.
|
||||
|
||||
## Procedimento
|
||||
|
||||
1. Inspecione toda a implementação do módulo.
|
||||
2. Compare requisito por requisito com o MASTER CONTEXT.
|
||||
3. Crie uma matriz:
|
||||
- requisito;
|
||||
- status: `OK`, `PARCIAL`, `FALTA`, `DECISÃO ABERTA`;
|
||||
- evidência (arquivo/teste);
|
||||
- correção necessária.
|
||||
4. Corrija automaticamente apenas gaps claros que não exigem nova decisão de produto/arquitetura.
|
||||
5. Para decisões abertas, não invente. Gere ADR/issue sugerida.
|
||||
|
||||
## Verificações críticas
|
||||
|
||||
- nenhum login próprio;
|
||||
- nenhum armazenamento de senha/token paralelo;
|
||||
- workspace/RLS em todas as entidades;
|
||||
- feature flag;
|
||||
- matriz de permissões;
|
||||
- 10 modelos;
|
||||
- nomes únicos;
|
||||
- XLSX/CSV somente;
|
||||
- 10MB/50k/10 fontes;
|
||||
- multiaba com uma aba selecionada;
|
||||
- header row;
|
||||
- mapping 1:1;
|
||||
- obrigatórias;
|
||||
- preview;
|
||||
- lock/processamento sequencial;
|
||||
- modelo imutável;
|
||||
- temporários;
|
||||
- exclusão protegida;
|
||||
- auditoria;
|
||||
- Sentry sem conteúdo sensível;
|
||||
- XLSX/CSV/PDF;
|
||||
- Design System Elo Pro;
|
||||
- acessibilidade básica;
|
||||
- testes e performance.
|
||||
|
||||
## Rodar
|
||||
|
||||
Use os comandos reais do repo para:
|
||||
- lint;
|
||||
- typecheck;
|
||||
- unit/integration;
|
||||
- RLS;
|
||||
- E2E;
|
||||
- build de produção.
|
||||
|
||||
## Entrega
|
||||
|
||||
Crie `docs/spreadsheet-adapter/08-final-readiness-report.md` com:
|
||||
- scorecard factual por requisito (sem notas subjetivas);
|
||||
- bloqueadores;
|
||||
- riscos residuais;
|
||||
- decisões abertas;
|
||||
- evidências de teste;
|
||||
- checklist final de release.
|
||||
|
||||
No chat, apresente somente:
|
||||
1. o que está pronto;
|
||||
2. o que bloqueia release;
|
||||
3. quais decisões humanas ainda são necessárias.
|
||||
@@ -0,0 +1,25 @@
|
||||
# OPCIONAL — Regra persistente para Cursor
|
||||
|
||||
Se o repositório usa `.cursor/rules/`, transforme o conteúdo abaixo em uma rule apropriada ao padrão da versão instalada do Cursor.
|
||||
|
||||
## spreadsheet-adapter.mdc — intenção
|
||||
|
||||
Ao editar arquivos do Adaptador de Planilhas:
|
||||
|
||||
- Nunca crie autenticação, cadastro, senha, refresh token ou base de usuários própria.
|
||||
- Reutilize Supabase Auth, `profiles`, `workspace_members`, workspace ativo, feature flags, RLS, audit log, Sentry e Design System do Elo Pro.
|
||||
- Tenant é `workspace_id`.
|
||||
- Nunca confie em `workspace_id` fornecido pelo browser sem validação server-side.
|
||||
- Storage deve ser privado.
|
||||
- Não logue conteúdo de células/arquivos.
|
||||
- Suporte somente XLSX/CSV no MVP.
|
||||
- Limites: 10 modelos/workspace; 10 fontes/operação; 10MB e 50k linhas por fonte.
|
||||
- XLSX multiaba processa uma aba selecionada por fonte.
|
||||
- Mapping é 1:1 e obrigatórias devem estar mapeadas.
|
||||
- Preview é obrigatório antes do processamento.
|
||||
- Modelo original é imutável.
|
||||
- Redis é coordenação, PostgreSQL é fonte durável.
|
||||
- Anthropic não faz parte do caminho crítico do MVP.
|
||||
- UI deve consumir EloPro Design System Global V2.1 e Lucide React.
|
||||
- Drag-and-drop precisa ter alternativa acessível.
|
||||
- Não invente decisões para storage, job runner, TTL, XLSX library ou soft delete; siga ADR/padrão existente ou registre decisão aberta.
|
||||
@@ -0,0 +1,27 @@
|
||||
# Checklist de execução no Cursor
|
||||
|
||||
- [ ] 02 Auditoria concluída sem mudanças de produção
|
||||
- [ ] 03 Fundação/feature flag
|
||||
- [ ] 04 Auth/workspace/permissões/RLS
|
||||
- [ ] 05 Banco/migrations
|
||||
- [ ] 06 Design System/shell
|
||||
- [ ] 07 Modelos/settings
|
||||
- [ ] 08 Fontes/validação
|
||||
- [ ] 09 Mapping/preview
|
||||
- [ ] 10 Jobs/exports
|
||||
- [ ] 11 Redis/progresso
|
||||
- [ ] 12 Auditoria/Sentry/security
|
||||
- [ ] 13 Testes/QA
|
||||
- [ ] 14 Deploy/runbook
|
||||
- [ ] 15 Gap review
|
||||
|
||||
## Gates obrigatórios antes do piloto
|
||||
|
||||
- [ ] Uma identidade/senha Elo Pro, sem login paralelo
|
||||
- [ ] Zero acesso cruzado entre workspaces nos testes
|
||||
- [ ] Modelo original permanece intacto
|
||||
- [ ] Fluxo upload -> mapping -> preview -> processo -> download funciona
|
||||
- [ ] Feature flag e permissões funcionando
|
||||
- [ ] Storage privado e temporários com limpeza definida
|
||||
- [ ] Sentry sem dados de planilha
|
||||
- [ ] Lint, typecheck, testes e build verdes
|
||||
@@ -0,0 +1,7 @@
|
||||
# ADR 0001 — Object storage
|
||||
|
||||
Status: aberta, com adaptação provisória.
|
||||
|
||||
Produção exige `SUPABASE_SERVICE_ROLE_KEY` e `SUPABASE_STORAGE_BUCKET`. O cliente só faz upload/download pelo Route Handler, depois da autorização. Sem essas variáveis, produção recusa subir o storage. Desenvolvimento usa `.data/storage`, fora da pasta pública do Next.
|
||||
|
||||
Recomendação: bucket privado no Supabase Storage, ou S3 compatível atrás da mesma interface `ObjectStorage`.
|
||||
@@ -0,0 +1,5 @@
|
||||
# ADR 0002 — Login único entre hosts
|
||||
|
||||
Status: aberta.
|
||||
|
||||
O Adaptador lê a sessão Supabase e o cookie `elo_pro_workspace_id`. Não copia usuários nem cria senha. A topologia de domínio e cookie compartilhado continua com a arquitetura do Elo Pro. `ELO_PRO_LOGIN_URL` é o destino quando não há sessão.
|
||||
@@ -0,0 +1,7 @@
|
||||
# ADR 0003 — Job runner
|
||||
|
||||
Status: aberta, com dois modos explícitos.
|
||||
|
||||
`ADAPTER_JOB_MODE=worker` apenas marca o job como `queued`. O processo `npm run worker` executa com o mesmo `runProcess`, lock e estado no PostgreSQL. `inline` executa na própria chamada e existe para desenvolvimento e teste. Produção sem a variável cai em `worker`.
|
||||
|
||||
Recomendação: manter o worker como processo contínuo no piloto. Não depender do tempo de uma função serverless.
|
||||
@@ -0,0 +1,5 @@
|
||||
# ADR 0004 — TTL de temporários
|
||||
|
||||
Status: aberta.
|
||||
|
||||
`SPREADSHEET_TEMP_TTL_SECONDS` é obrigatório em produção e aceita de 1 segundo a 7 dias para não gravar um número de produto no código. Fora de produção, a omissão usa 3600 segundos só para o ambiente local. A limpeza não apaga chaves que contenham `/models/`.
|
||||
@@ -0,0 +1,11 @@
|
||||
# ADR 0005 — Biblioteca de planilha
|
||||
|
||||
Status: aberta. Implementação provisória: ExcelJS (MIT) atrás de `readSpreadsheet`, `buildXlsx` e CSV próprio.
|
||||
|
||||
Alternativas consideradas:
|
||||
|
||||
- ExcelJS, MIT, leitura e escrita, manutenção ativa, não promete preservar a formatação do modelo.
|
||||
- SheetJS comunitário, leitura muito usada; a licença das versões atuais precisa de revisão jurídica antes de produção.
|
||||
- ExcelJS para grade e geração de arquivo novo, que é o comportamento do MVP: a saída não sobrescreve o modelo.
|
||||
|
||||
O binário do modelo é só lido. O teste de jornada compara os bytes antes e depois. Trocar de biblioteca não deve vazar para os componentes React.
|
||||
@@ -0,0 +1,9 @@
|
||||
# ADR 0006 — Azul de ação e exclusão de modelo
|
||||
|
||||
## Azul de ação
|
||||
|
||||
O escopo fixa Bright Blue `#2F8FFF` e pede o azul primário do token oficial, que não estava no repositório. Uso provisório: `#0B3D91` em `--color-action`, com texto branco. Substituir quando o pacote do Design System Elo Pro for ligado.
|
||||
|
||||
## Exclusão
|
||||
|
||||
Status: aberta. O schema marca `deleted` e preenche `deleted_at`, mantém o arquivo e o histórico. A exclusão física pode ser feita depois sem migração destrutiva. Enquanto houver job em `validating`, `ready`, `queued` ou `processing`, a exclusão é recusada.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Auditoria de integração — Adaptador de Planilhas
|
||||
|
||||
Data da inspeção: 2026-10-02. O diretório de trabalho era um repositório Git vazio, sem aplicação Elo Pro.
|
||||
|
||||
## O que não existia para reutilizar
|
||||
|
||||
- App Router, clientes Supabase, middleware e logout
|
||||
- Resolução de `workspace_id` e `workspace_members`
|
||||
- Papéis, RLS, feature flags, design system, TanStack Query, Sentry, Redis, audit log e storage
|
||||
- Padrão de Route Handlers, Vitest, CI e migrations
|
||||
|
||||
## Diferença em relação ao master context
|
||||
|
||||
O contexto pede para encaixar o módulo no Elo Pro existente. Como não havia código de plataforma, este repositório implementa o Adaptador como aplicação Next.js pronta para compartilhar a mesma identidade, com um shim SQL das tabelas `profiles`, `workspaces`, `workspace_members`, `workspace_module_flags` e `audit_log`. Essas tabelas não têm senha, hash ou refresh token. Em um monorepo Elo Pro real, a migration `0001_platform_shim.sql` não deve recriar o que já existe (`create table if not exists`).
|
||||
|
||||
## Decisões já fechadas pelo escopo V3
|
||||
|
||||
Identidade única via Supabase Auth, tenant `workspace_id`, RLS, limites do MVP, mapeamento manual 1:1, prévia obrigatória, modelo imutável, flag de módulo e papéis owner/admin/gestor/agent.
|
||||
|
||||
## OPEN DECISIONS
|
||||
|
||||
Registradas em `docs/decisions/`:
|
||||
|
||||
1. Object storage definitivo
|
||||
2. Topologia de cookie/login entre hosts
|
||||
3. Job runner durável
|
||||
4. TTL de temporários
|
||||
5. Biblioteca XLSX de produção
|
||||
6. Exclusão física versus soft delete
|
||||
|
||||
## Arquitetura
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
browser[Browser Elo Pro] --> session[Sessão Supabase]
|
||||
session --> app[Next.js Adaptador]
|
||||
app --> domain[Domínio de planilhas]
|
||||
app --> pg[(PostgreSQL + RLS)]
|
||||
app --> redis[(Redis lock e progresso)]
|
||||
app --> storage[Storage privado]
|
||||
app --> sentry[Sentry sem células]
|
||||
```
|
||||
|
||||
## Fases
|
||||
|
||||
Fundação e flag, autorização, schema, shell visual, modelos, fontes, mapeamento, jobs, Redis, auditoria/Sentry, testes, operação e revisão de gaps. A implementação seguiu essa ordem no mesmo repositório.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Fundação, rotas e feature flag
|
||||
|
||||
## Rotas de página
|
||||
|
||||
- `/login` redireciona ao login central (`ELO_PRO_LOGIN_URL`) ou, só fora de produção, oferece identidades locais sem senha
|
||||
- `/adaptador` dashboard
|
||||
- `/adaptador/operacao` jornada
|
||||
- `/adaptador/configuracoes` somente owner/admin
|
||||
|
||||
`loading.tsx` e `error.tsx` cobrem espera e falha recuperável. Sem sessão, o proxy manda para `/login`. Sem a flag `spreadsheet_adapter`, a página informa que o módulo está desligado e as APIs respondem `FEATURE_DISABLED`.
|
||||
|
||||
## APIs
|
||||
|
||||
- `GET/POST /api/spreadsheet-adapter/models`
|
||||
- `DELETE /api/spreadsheet-adapter/models/:id`
|
||||
- `GET/PATCH /api/spreadsheet-adapter/settings`
|
||||
- `POST /api/spreadsheet-adapter/sources/validate`
|
||||
- `POST /api/spreadsheet-adapter/jobs`
|
||||
- `GET /api/spreadsheet-adapter/jobs/:id`
|
||||
- `PUT /api/spreadsheet-adapter/jobs/:id/mappings`
|
||||
- `POST /api/spreadsheet-adapter/jobs/:id/preview`
|
||||
- `POST /api/spreadsheet-adapter/jobs/:id/process`
|
||||
- `PATCH/DELETE /api/spreadsheet-adapter/jobs/:id/sources/:sourceId`
|
||||
- `GET /api/spreadsheet-adapter/jobs/:id/download?format=xlsx|csv|pdf&sourceId=`
|
||||
|
||||
O `workspace_id` do corpo é ignorado como tenant. Se vier diferente da sessão, a chamada é negada e auditada.
|
||||
|
||||
## Códigos de erro estáveis
|
||||
|
||||
`UNAUTHENTICATED`, `WORKSPACE_FORBIDDEN`, `FEATURE_DISABLED`, `FORBIDDEN`, `TOO_MANY_MODELS`, `DUPLICATE_MODEL_NAME`, `TOO_MANY_SOURCES`, `FILE_TOO_LARGE`, `TOO_MANY_ROWS`, `UNSUPPORTED_FORMAT`, `MIME_MISMATCH`, `INVALID_STRUCTURE`, `ZIP_BOMB`, `EMPTY_HEADER`, `DUPLICATE_HEADER`, `HEADER_ROW_INVALID`, `SHEET_REQUIRED`, `TYPE_INCONSISTENT`, `MAPPING_CONFLICT`, `MAPPING_INCOMPLETE`, `MAPPING_UNKNOWN`, `MODEL_IN_USE`, `JOB_LOCKED`, `REDIS_UNAVAILABLE`, `MODEL_TAMPERED`, `NOT_FOUND`.
|
||||
|
||||
## Contratos
|
||||
|
||||
Upload de modelo: `multipart` com `file`, `name`, `sheet` opcional, `headerRow`, `requiredColumns` (JSON). Sem `requiredColumns`, todas as colunas nascem obrigatórias e a tela permite desmarcar.
|
||||
|
||||
Validação de fonte: `file`, `jobId`, `sheet`, `headerRow`. Várias abas devolvem `409 SHEET_REQUIRED` com a fonte já armazenada para troca de aba sem novo upload. Tipo misto devolve `422` e preserva as outras fontes.
|
||||
|
||||
Prévia: `{ preview: true, columns, rows, rowCount, truncated }`. Colunas na ordem do modelo. Não grava saída nem altera o modelo.
|
||||
|
||||
Temporários: `expires_at = agora + SPREADSHEET_TEMP_TTL_SECONDS`. Em produção a variável é obrigatória. Fora de produção, a ausência usa 3600 segundos apenas como apoio de desenvolvimento, não como política de produto.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Autenticação, workspace, permissões e RLS
|
||||
|
||||
## Fluxo
|
||||
|
||||
1. Supabase Auth (`getUser`) quando `NEXT_PUBLIC_SUPABASE_URL` e a anon key existem.
|
||||
2. Workspace ativo no cookie `elo_pro_workspace_id`, validado contra `workspace_members`.
|
||||
3. Fora de produção, `ADAPTER_DEV_AUTH=1` aceita um cookie assinado sem senha, só para identidades já existentes no banco.
|
||||
4. A flag `workspace_module_flags.module_key = spreadsheet_adapter` precisa estar ligada.
|
||||
5. Logout chama `supabase.auth.signOut()` e apaga o cookie local de desenvolvimento.
|
||||
6. `src/proxy.ts` só redireciona quem não tem cookie de sessão. A autorização real continua no servidor.
|
||||
|
||||
Não existe formulário de senha, tabela de credencial ou refresh token do Adaptador. Superadmin (`profiles.is_superadmin`) não ganha bypass dentro do módulo.
|
||||
|
||||
## Fonte do workspace
|
||||
|
||||
O identificador vem do cookie de plataforma ou da sessão de desenvolvimento. Consultas usam o valor já validado no servidor. Payload do browser não escolhe o tenant.
|
||||
|
||||
## Matriz
|
||||
|
||||
| Ação | Owner/Admin | Gestor/Agent |
|
||||
| --- | --- | --- |
|
||||
| Usar módulo habilitado | Sim | Sim |
|
||||
| Operar fonte, mapa, prévia, processo e download | Sim | Sim |
|
||||
| Enviar modelo | Sim | Só se `allow_non_admin_model_upload` |
|
||||
| Excluir modelo e alterar a flag de upload | Sim | Não |
|
||||
|
||||
## RLS
|
||||
|
||||
`migrations/0003_rls.sql` liga e força RLS. O aplicativo faz `set local role app_user` e `app.user_id`. Funções `security definer` resolvem membership, flag, upload e job ativo sem vazamento entre workspaces. A conexão de serviço (worker, seed, flag, limpeza) não passa por `app_user` e permanece só no servidor.
|
||||
|
||||
## Testes
|
||||
|
||||
`tests/integration/rls.test.ts` cobre leitura/escrita cruzada, insert bloqueado por RLS, flag desligada mesmo com contexto mentiroso e agent impedido de gravar settings. `tests/integration/journey.test.ts` cobre agent sem upload, upload após a setting e exclusão negada.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Modelo de dados
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
workspaces ||--o| spreadsheet_adapter_settings : configura
|
||||
workspaces ||--o{ spreadsheet_models : possui
|
||||
workspaces ||--o{ spreadsheet_jobs : isola
|
||||
profiles ||--o{ spreadsheet_jobs : executa
|
||||
spreadsheet_models ||--o{ spreadsheet_jobs : orienta
|
||||
spreadsheet_jobs ||--o{ spreadsheet_job_sources : contem
|
||||
spreadsheet_job_sources ||--o{ spreadsheet_job_mappings : mapeia
|
||||
workspaces ||--o{ audit_log : audita
|
||||
```
|
||||
|
||||
Migrations: `0001_platform_shim.sql`, `0002_spreadsheet_adapter.sql`, `0003_rls.sql`. Rollback do módulo: `migrations/down/0002_spreadsheet_adapter_down.sql`. Não remove tabelas de identidade do Elo Pro.
|
||||
|
||||
## Integridade
|
||||
|
||||
- Nome lógico único entre modelos `active` por workspace
|
||||
- No máximo 10 modelos ativos e 10 fontes por job, também por trigger
|
||||
- Mapeamento único nos dois sentidos (`source_column` e `model_column`)
|
||||
- Job não referencia modelo de outro workspace
|
||||
- Conteúdo da planilha fica no storage, não em JSONB de linhas
|
||||
- `status = deleted` e `deleted_at` deixam a exclusão física reversível até a decisão de produto
|
||||
|
||||
Colunas extras em fontes (`output_csv_key`, `output_xlsx_key`, `columns_schema`, `process_idempotency_key`) guardam metadados da saída temporária. O PDF é gerado na hora do download a partir do CSV privado.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Shell de UX
|
||||
|
||||
Não havia Design System publicado no repositório. Os componentes em `src/components/ui.tsx` seguem os tokens do escopo V3: Cloud White `#FBFBFE`, Midnight Ink `#071B45`, Bright Blue `#2F8FFF`, Aqua Signal `#00C2A8`, Warning `#F39A2D`, Error `#E63946`, Manrope e raio de 10/14/18/24 px. O azul de ação `#0B3D91` está registrado como provisório em `docs/decisions/0006-action-blue.md` porque o token oficial não estava no repo.
|
||||
|
||||
## Páginas
|
||||
|
||||
Dashboard, jornada (modelo, fontes, mapeamento, revisão, processamento, resultado) e configurações. `JourneyTrail` mostra continuidade da jornada, com texto de etapa concluída, não só cor.
|
||||
|
||||
## Componentes
|
||||
|
||||
Button, IconButton, Input, Select, Switch, Dialog, Card, SemanticMarker, estados de loading, vazio e erro. Lucide para ícones. Mapeamento usa `@dnd-kit` e um `select` com o mesmo efeito, utilizável por teclado.
|
||||
|
||||
## O que a interface não faz
|
||||
|
||||
Não inventa modelos de demonstração. Lista vazia é estado vazio. Flag desligada não abre a jornada.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Segurança e observabilidade
|
||||
|
||||
## Auditoria
|
||||
|
||||
`audit_log` recebe upload e exclusão de modelo, mudança da setting, criação, início, conclusão, falha e download. Metadados passam por lista de chaves bloqueadas e só aceitam escalares. O teste de jornada procura o token `=CMD()` no log e não o encontra.
|
||||
|
||||
## Sentry
|
||||
|
||||
`beforeSend` remove body, cookies, breadcrumbs e headers de autorização. Tags previstas: módulo, `job_id`, `workspace_id`, `error_code`. Validação de negócio (`AdapterError` abaixo de 500) não é capturada. Sem DSN, a inicialização não ocorre.
|
||||
|
||||
## Controles
|
||||
|
||||
- RLS e checagem de papel no serviço
|
||||
- Extensão conferida com assinatura ZIP/OLE
|
||||
- Rejeição de XLS, ODS, XML, MIME incompatível e ZIP com expansão acima de 256 MB ou taxa anômala
|
||||
- Chave de storage sem `..` e, no disco local, resolvida dentro do diretório privado
|
||||
- CSV/XLSX de saída neutraliza células que começam com `=`, `+`, `@` ou hífen que não é número
|
||||
- Download exige sessão, workspace, fonte concluída e `expires_at` futuro
|
||||
- Lock Redis (ou falha `REDIS_UNAVAILABLE`) antes de processar; clique repetido com a mesma chave de idempotência devolve o job existente
|
||||
- Nomes exibidos são basename sanitizado
|
||||
|
||||
## Threat model resumido
|
||||
|
||||
| Ameaça | Mitigação | Residual |
|
||||
| --- | --- | --- |
|
||||
| IDOR / workspace forjado | Sessão + RLS + auditoria | Conexão de serviço ignora RLS e só pode existir no servidor |
|
||||
| Bypass de papel | Serviço e policies | — |
|
||||
| Planilha em log | Scrub e auditoria escalar | Erro inesperado ainda pode ir ao Sentry se o `throw` embutir dado; o código de domínio evita isso |
|
||||
| ZIP bomb | Teto de expansão antes do ExcelJS | Estruturas com data descriptor continuam limitadas pelos 10 MB de entrada |
|
||||
| CSV injection | Prefixo `'` | Números negativos permanecem numéricos de propósito |
|
||||
| Job duplicado | Lock + idempotência | Lock em memória vale para um processo; produção exige Redis |
|
||||
|
||||
## Riscos residuais
|
||||
|
||||
PDF limita 200 linhas e 12 colunas e declara a limitação no próprio arquivo. XLSX/CSV levam o resultado completo. A formatação visual do modelo não é copiada: a saída é um arquivo novo e o binário do modelo é conferido por SHA-256 antes e depois.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Plano de testes e resultado
|
||||
|
||||
Comandos: `npm test`, `npm run typecheck`. A suíte abaixo passou na execução local desta entrega, junto com o typecheck.
|
||||
|
||||
| Área | Evidência | Resultado |
|
||||
| --- | --- | --- |
|
||||
| Cabeçalho, tipos, 1:1, permissões, nomes, CSV, cache por workspace | `tests/unit/domain.test.ts` | Passou |
|
||||
| Lock, expiração e scrub do Sentry | mesmo arquivo | Passou |
|
||||
| 50.000 linhas CSV | `tests/performance/rows.test.ts` | Passou |
|
||||
| Path traversal, MIME, XLS, ZIP | `tests/security/files.test.ts` | Passou |
|
||||
| Switch, dialog, select, loading, vazio, erro | `tests/component/ui.test.tsx` | Passou |
|
||||
| Migrations e rollback do módulo | `tests/integration/migrations.test.ts` | Passou |
|
||||
| RLS A/B, agent versus owner | `tests/integration/rls.test.ts` | Passou |
|
||||
| Jornada modelo → mapa → prévia → processo → download, modelo intacto, idempotência, limites, aba, Redis indisponível, TTL, workspace forjado | `tests/integration/journey.test.ts` | Passou |
|
||||
|
||||
## Não executado aqui
|
||||
|
||||
- E2E de browser contra o login real do Elo Pro. Não há host do ecossistema neste repositório. A jornada de API cobre o mesmo fluxo de negócio.
|
||||
- XLSX de 10 MB e 50.000 linhas pelo ExcelJS. O teto de 10 MB é rejeitado antes do parse. As 50.000 linhas foram medidas no caminho CSV/domínio.
|
||||
- Dois processos OS com Redis real. O lock em memória cobre dois usuários no mesmo processo; usuários diferentes usam chaves diferentes.
|
||||
|
||||
Não há bloqueio de teste vermelho na suíte automatizada. Os bloqueios de release estão na revisão final e são decisões de plataforma, não falhas desta suíte.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Deploy e operação
|
||||
|
||||
## Ordem
|
||||
|
||||
1. Conferir envs sem colar segredo no repositório.
|
||||
2. `npm run migrate` na `DATABASE_URL` do ambiente.
|
||||
3. Subir a aplicação com a flag ainda desligada.
|
||||
4. Subir `npm run worker` e o Redis do ambiente.
|
||||
5. Confirmar bucket privado. Não criar bucket público.
|
||||
6. Smoke test no workspace piloto e só então `npm run flag -- <workspace_id> on`.
|
||||
|
||||
## Variáveis
|
||||
|
||||
| Nome | Uso |
|
||||
| --- | --- |
|
||||
| `NEXT_PUBLIC_SUPABASE_URL` | Auth no browser/servidor |
|
||||
| `NEXT_PUBLIC_SUPABASE_ANON_KEY` | Chave pública do Auth |
|
||||
| `SUPABASE_SERVICE_ROLE_KEY` | Storage no servidor. Nunca `NEXT_PUBLIC_` |
|
||||
| `SUPABASE_STORAGE_BUCKET` | Bucket privado |
|
||||
| `DATABASE_URL` | PostgreSQL. Obrigatório em produção |
|
||||
| `REDIS_URL` | Lock. Sem ela o processamento recusa iniciar |
|
||||
| `SENTRY_DSN` / `NEXT_PUBLIC_SENTRY_DSN` | Observabilidade |
|
||||
| `SENTRY_ENVIRONMENT` / `SENTRY_RELEASE` | Ambiente e release |
|
||||
| `ELO_PRO_LOGIN_URL` | Login central |
|
||||
| `SPREADSHEET_TEMP_TTL_SECONDS` | Retenção. Obrigatório em produção; valor de produto ainda aberto |
|
||||
| `ADAPTER_JOB_MODE` | `worker` em produção, `inline` em desenvolvimento |
|
||||
| `ADAPTER_DEV_AUTH` | Só fora de produção |
|
||||
| `ADAPTER_DEV_AUTH_SECRET` | Assina o cookie local. Não é senha de usuário |
|
||||
|
||||
O cookie de workspace lido pela aplicação chama-se `elo_pro_workspace_id`.
|
||||
|
||||
## Rollback
|
||||
|
||||
- Aplicação: voltar o deploy anterior.
|
||||
- Flag: `npm run flag -- <workspace_id> off`.
|
||||
- Schema: `migrations/down/0002_spreadsheet_adapter_down.sql` remove só tabelas do módulo.
|
||||
- Jobs: parar o worker. Jobs `queued` não avançam. Jobs `processing` sem lock viram `INTERRUPTED` na próxima varredura.
|
||||
|
||||
## Smoke
|
||||
|
||||
Login Elo Pro sem segunda senha; workspace piloto com flag ligada; upload de modelo; fonte; aba ou cabeçalho se preciso; mapeamento; prévia; download XLSX, CSV e PDF; workspace sem flag recebe bloqueio; download sem sessão recebe 401.
|
||||
|
||||
## Runbook
|
||||
|
||||
- Job travado em `processing`: confirmar se o lock Redis ainda existe. Se expirou, o worker marca `INTERRUPTED`. O usuário pode tentar de novo.
|
||||
- Redis indisponível: APIs de leitura seguem; processamento responde `REDIS_UNAVAILABLE` e não grava saída.
|
||||
- Storage indisponível: upload falha com `STORAGE_FAILURE` ou 503 e não deixa modelo sem arquivo.
|
||||
- Migration parcial: `schema_migrations` só registra arquivo aplicado por completo. Reexecutar `npm run migrate` continua do próximo arquivo. Não editar migration já aplicada.
|
||||
- Limpeza: `npm run cleanup` apaga blobs em chaves `/tmp/` expiradas e não mexe em `/models/`.
|
||||
@@ -0,0 +1,48 @@
|
||||
# Revisão final contra o escopo V3
|
||||
|
||||
| Requisito | Status | Evidência |
|
||||
| --- | --- | --- |
|
||||
| Sem login, senha ou token próprio | OK | `src/server/auth`, ausência de tabela de senha |
|
||||
| Sessão Supabase e cookie de workspace | OK | `context.ts`, middleware |
|
||||
| Flag de módulo, padrão desligado | OK | `workspace_module_flags`, página de módulo desligado |
|
||||
| RLS e papéis | OK | `0003_rls.sql`, testes de RLS e jornada |
|
||||
| 10 modelos, nome único, soft delete provisório | OK | triggers, unique index, `status` |
|
||||
| XLSX/CSV, 10 MB, 50k, 10 fontes | OK | domínio + testes; 50k no caminho CSV |
|
||||
| Uma aba e linha de cabeçalho | OK | jornada e `updateSource` |
|
||||
| Mapeamento 1:1, obrigatórias, select e drag | OK | domínio, UI e testes |
|
||||
| Prévia antes de processar | OK | `previewSource` e passo da jornada |
|
||||
| Lock, idempotência, Redis obrigatório em produção | OK | coordinator e teste de indisponibilidade |
|
||||
| Modelo imutável | OK | SHA-256 e comparação de bytes na jornada |
|
||||
| Temporários e limpeza | OK | `cleanupExpired`; TTL de produto aberto |
|
||||
| Exclusão só owner/admin e bloqueio com job ativo | OK | jornada |
|
||||
| Auditoria sem células | OK | scrub e teste do token `=CMD()` |
|
||||
| Sentry sem planilha | OK | `beforeSend` e teste de scrub |
|
||||
| Saída XLSX, CSV e PDF | OK | jornada gera os três |
|
||||
| UI com tokens V3, Manrope, Lucide | PARCIAL | Componentes locais no token do escopo; biblioteca oficial do Elo Pro não estava no repo |
|
||||
| Acessibilidade básica | PARCIAL | Select, switch, dialog e foco visível cobertos; não houve auditoria WCAG formal |
|
||||
| E2E no browser do Elo Pro | PARCIAL | Jornada de API completa; browser do ecossistema inexistente aqui |
|
||||
| Performance 10 MB / 50k XLSX / 10 fontes paralelas | PARCIAL | 50k CSV e rejeição de arquivo acima de 10 MB; ExcelJS de 50k linhas não medido |
|
||||
| Job runner de produção | DECISÃO ABERTA | Worker no mesmo código; fila externa não escolhida |
|
||||
| Storage de produção | DECISÃO ABERTA | Interface pronta; local só fora de produção |
|
||||
| TTL, biblioteca XLSX, soft delete, SSO entre hosts | DECISÃO ABERTA | ADRs |
|
||||
|
||||
## Bloqueios de release para o piloto no ecossistema
|
||||
|
||||
1. Apontar `DATABASE_URL` do Postgres Elo Pro e não aplicar o shim de identidade se as tabelas já existirem com outro formato.
|
||||
2. Aprovar bucket privado e preencher as envs de storage.
|
||||
3. Definir TTL numérico em `SPREADSHEET_TEMP_TTL_SECONDS`.
|
||||
4. Rodar `ADAPTER_JOB_MODE=worker` com Redis, não o modo inline, no ambiente de piloto.
|
||||
5. Confirmar a biblioteca ExcelJS (MIT, provisória) ou trocar o codec em `src/infra/spreadsheet/parse.ts`.
|
||||
6. Ligar a flag só no workspace piloto.
|
||||
|
||||
## Riscos residuais
|
||||
|
||||
PDF truncado de propósito. Formatação do modelo não é reaproveitada. Conexão de serviço ignora RLS. Lock em memória não atravessa várias instâncias.
|
||||
|
||||
## Checklist de release
|
||||
|
||||
- [x] Suíte Vitest, typecheck, lint e build de produção locais
|
||||
- [ ] Smoke no staging com Supabase, Redis e bucket reais
|
||||
- [ ] Smoke no staging com Supabase, Redis e bucket reais
|
||||
- [ ] Flag desligada para quem não é piloto
|
||||
- [ ] Sentry com DSN, sem anexo de arquivo
|
||||
Reference in new issue
Block a user