# Contexto de retomada — Novo Modelo de Negócio

Atualizado em: 02/08/2026 (America/Sao_Paulo)

Este arquivo é o handoff operacional para continuar a implementação iniciada a partir de `NovoModeloNegocio.md`. Em 02/08/2026, os gates locais ficaram verdes e a árvore está pronta para o commit de release e o deploy controlado, mantendo o checkout público desativado. Não descartar nem resetar a árvore atual.

> Atualização de retomada: as pendências locais descritas nas seções 5 e 6 foram fechadas em 02/08/2026. A seção 11 ao fim deste arquivo contém o estado autoritativo atual. Os gates externos Shopify/produção continuam abertos e o checkout não foi ativado.

## 1. Pedido original e objetivo

Implementar integralmente o novo atacado Vida Mansa:

- catálogo público com preços vigentes e estoque;
- carrinho e checkout sem aprovação cadastral prévia;
- pedido mínimo fixo de US$ 150;
- checkout simples com nome, e-mail e endereço;
- pagamentos ACH, Wire e cartão;
- Payment Terms/NET apenas após cadastro, análise e aprovação de crédito;
- conta pós-pagamento, acesso ao status do pedido e troca obrigatória da senha provisória;
- ajuste completo do admin/dashboard;
- remoção de textos “Become a Retail Partner” e equivalentes;
- preservar segurança, criar release e fazer deploy pela `.github/workflows/deploy.yml`.

O plano funcional e os critérios detalhados estão em `NovoModeloNegocio.md`.

## 2. Ponto de rollback e backup

- Branch atual: `main`.
- Estado Git no momento deste handoff: `main...origin/main [ahead 1]`.
- Commit de checkpoint local:
  - SHA: `7a4c68ef25c864f3249ee8b741b14cef12656b4d`
  - Mensagem: `chore: checkpoint antes da mudanca do modelo de negocio`
- Commit anterior: `26c6fa3 Keep campaign hourly chart responsive`.
- Backup integral:
  - arquivo: `FullBackup-AntesMudarModeloNegocio.zip`
  - tamanho: `993973029` bytes;
  - SHA-256: `2E172362769B855D61B224248D816861E7504848943C683CDC445E8FF32EECFA`;
  - criado em 28/07/2026 21:45;
  - está ignorado pelo Git e **não deve ser commitado nem enviado ao GitHub**.
- A escrita em `.git` exige execução escalada neste ambiente. Não usar `git reset --hard`, `git checkout --` ou qualquer limpeza destrutiva.

## 3. Estado geral da implementação

A maior parte do novo modelo já está implementada na árvore de trabalho:

- preços e estoque públicos;
- carrinho anônimo e pedido mínimo de US$ 150;
- checkout guest e autenticado;
- ACH, Wire, cartão hospedado Shopify e Payment Terms aprovado;
- cadastro e análise de crédito, limites e reservas;
- conta pós-pagamento com senha temporária e troca no primeiro acesso;
- signup seguro e verificação de e-mail;
- outbox durável para notificações;
- webhooks, reconciliação, reembolsos e inventário Shopify;
- dashboards, relatórios, analytics e textos da home;
- feature flag/kill switch para checkout;
- migrations, preflight, workflow de deploy e rollback;
- privacidade de logs, RBAC interno, revogação de sessões e hardening de OAuth.

Há muitas alterações rastreadas e arquivos novos legítimos. O último `git diff --stat` mostrava aproximadamente 178 arquivos rastreados alterados, 15.485 inserções e 4.345 remoções, além de novos arquivos. Isso é esperado para esta release. O arquivo legado inseguro `check_2fa.php` e o backup `resources/views/storefront/catalog.blade.php.bak` foram removidos.

## 4. Defesas importantes já concluídas

- Logs de atividade usam allowlist, redaction e retenção.
- Contas staff/customer inativas têm sessões e remember tokens revogados.
- Rotas administrativas customizadas exigem conta staff ativa e autorização real.
- Provisionamento de conta ocorre somente com evidência de pagamento integral.
- Onboarding staff usa outbox durável e expiração.
- Registrar webhooks não repete mutation POST de resultado ambíguo.
- OAuth Shopify valida token/webhooks antes de substituir a conexão ativa.
- Deploy faz preflight dos scopes antes de backup/manutenção.
- Rollback executa comandos pela release imutável, inclusive com código antigo.
- Push normal preserva o kill switch; checkout só pode ser explicitamente ligado por `workflow_dispatch` com `checkout_state=enable`.
- Preços zero, subcent, descontos de 100% ou fracionários inválidos falham de forma fechada.
- Comparação de SKU no preflight é byte-exata e consistente entre SQLite/MariaDB.
- Admin só aceita variantes do catálogo Shopify canônico.
- Pedido pago não pode ir para `Cancelled`; deve passar pelo fluxo de `Refund`.

## 5. Trabalho crítico mais recente — ainda em validação

Uma auditoria adversarial encontrou condições de corrida financeiras no serviço Shopify. Alterações já aplicadas, mas que ainda precisam de testes adversariais completos:

### 5.1 ShopifyDraftOrderCheckout

Arquivo principal: `app/Services/Shopify/ShopifyDraftOrderCheckout.php`.

Já alterado para:

- rejeitar criação/retomada de checkout para pedido cancelado ou reembolsado;
- exigir estado e método de pagamento esperados sob lock;
- revalidar Customer ativo antes de criar/completar um checkout remoto;
- revalidar aprovação de Payment Terms;
- cercar `draft`, `completion` e `mark-paid` com leases;
- impedir `orderMarkAsPaid` em pedido terminal;
- persistir marcação de pago sob lock e validar o Shopify Order ID;
- recalcular `outstanding_total` usando o total canônico com imposto retornado pela Shopify;
- validar total positivo e moeda coerente;
- expor um fence de cancelamento e impedir cancelamento concorrente com criação/completion/mark-paid;
- excluir draft sob fence;
- não permitir cancelamento de status com fundos pagos.

Foi criada a migration:

`database/migrations/2026_07_30_000000_add_shopify_cancellation_fence_to_orders.php`

Ela adiciona:

- `shopify_cancellation_operation_token`;
- `shopify_cancellation_operation_started_at`;
- índice do timestamp.

Também foram atualizados `Order`, `ReleasePreflight`, pruning, automação de cancelamento e ação admin.

Pendente neste domínio:

- adicionar testes explícitos para:
  - ação forjada em pedido cancelado/refunded;
  - cancelamento tentando entrar durante `draft`, `completion` e `mark-paid`;
  - suspensão do Customer entre falha remota e retry, para cartão e offline;
  - valores `grand_total`, `tax_total` e `outstanding_total` em Card, ACH/Wire e NET;
  - cancelamento pago sendo rejeitado;
- revisar cleanup fail-closed se o Customer ficar inelegível exatamente entre a chamada remota e a persistência local;
- rodar novamente toda a matriz Shopify/checkout depois desses testes.

### 5.2 Retomada de checkout local

`app/Services/Checkout/CheckoutService.php` agora valida pedidos idempotentes/claimed antes de devolvê-los:

- mesmo método de pagamento;
- pedido não terminal;
- estado retomável;
- Customer ainda ativo;
- Payment Terms ainda permitido.

Isto fecha retry de cartão para pedido cancelado e retry de cliente suspenso antes da aceitação remota. Ainda requer testes específicos.

### 5.3 Cancelamento automático/admin

- `PaymentPendingOrderAutomation` adquire fence antes de cancelar Shopify/local.
- A action `cancel` do `OrderResource` adquire o mesmo fence, revalida sob lock e o libera em falha.
- `OrderStateMachine` não permite mais `PaidAwaitingFulfillment -> Cancelled`; pedido pago deve ser reembolsado.

## 6. Auditorias paralelas congeladas no momento deste arquivo

No instante da primeira gravação havia três agentes ativos. Logo após salvar este handoff, os três foram interrompidos para congelar o workspace sem descartar nenhuma alteração já aplicada. Na retomada, tratar os diffs de webhook e RBAC como trabalho possivelmente incompleto, revisar os arquivos e repetir as matrizes antes de aceitar o resultado.

### 6.1 Binding canônico de webhooks

Agente: `/root/corrigir_webhook_binding`.

Escopo:

- `app/Http/Controllers/Shopify/ShopifyWebhookController.php`;
- testes de binding canônico Shopify.

P1 encontrado: fallback de webhook aceitava somente `wholesale_order_id` ou somente `wholesale_order_number`, permitindo que um payload válido da mesma loja associasse IDs remotos ao pedido local errado.

Correção exigida:

- fallback apenas quando **ID local e número local** estão presentes e coincidem com o mesmo pedido e a mesma loja;
- rejeitar conflito com Shopify order/draft ID já vinculado;
- testes same-shop para id-only, number-only, par divergente e conflito de IDs em create/update/paid/cancelled/draft update.

### 6.2 RBAC de compradores no storefront

Agentes: `/root/revisao_release_final` e filho `/root/revisao_release_final/review_storefront_checkout_security`.

Arquivos de produção anunciados:

- `app/Http/Middleware/EnsureStorefrontBuyerCapability.php`;
- `bootstrap/app.php`;
- `routes/web.php`;
- `tests/Feature/StorefrontBuyerRbacTest.php`.

Modelo decidido:

- guest mantém cart/checkout públicos;
- `buyer_viewer`: somente leitura de dashboard/pedidos/status;
- `buyer_purchaser`: leitura + cart/checkout/shipping/pay/reorder;
- `buyer_admin`: inclui CRUD de endereços e solicitação/resubmissão de crédito;
- usuário autenticado sem buyer role ou com identidade buyer+staff: 403 fail-closed.

O teste novo isolado havia passado com `9 testes / 101 asserções`. A matriz ampliada mais recente informada pelo agente passou com `109 testes / 1.111 asserções`. Fixtures antigas estavam sendo atualizadas para papéis explícitos nos seguintes testes:

- `CartTest.php`;
- `CheckoutTest.php`;
- `CustomerCreditApplicationFlowTest.php`;
- `CreditApplicationResubmissionTest.php`;
- `ReorderAndExportTest.php`;
- `FinancialMetricsAndDocumentsTest.php`;
- `PostPaymentAccountTest.php`.

Depois dessa matriz, restavam ajustes mínimos de fixture em:

- `OrderFinancialAccountingTest.php` (papel `buyer_viewer` para listagem read-only);
- `ShopifyInventoryFreshnessTest.php` (papel `buyer_purchaser` para checkout).

Decisão funcional/UX ainda pendente: `buyer_purchaser` pode abrir checkout, mas o fluxo autenticado atual envia “Add address” para uma rota reservada a `buyer_admin`. Isso é seguro (403), porém incoerente se o purchaser precisar informar um novo endereço de entrega durante a compra. Na retomada, decidir entre:

- purchaser compra somente com endereços previamente administrados pelo buyer_admin e as views ocultam CTAs sem permissão; ou
- criar uma capacidade/rota restrita para o purchaser informar o endereço daquele checkout sem receber administração ampla do cadastro.

P0 operacional pendente: o deploy não deve depender de executar manualmente `RolePermissionSeeder`. O workflow roda `migrate --force`, mas não o seeder; uma base antiga pode não ter `buyer_admin`, `buyer_purchaser` e `buyer_viewer`. Hoje `AccessRequestController` e `AccountProvisioner` procuram `buyer_admin` e, se a role não existir, não a atribuem. Isso faria contas storefront existentes e novas receberem 403 após o deploy.

Correção exigida antes da release:

- migration aditiva e idempotente que crie as três buyer roles no guard `web`;
- atribuir `buyer_admin` às contas customer-linked válidas que ainda não tenham papel comprador;
- falhar/registrar casos staff ou identidades mistas, sem convertê-los silenciosamente;
- preflight exigir as roles e nenhuma conta storefront ativa sem identidade buyer-only;
- não resolver executando indiscriminadamente `RolePermissionSeeder`, pois ele também sincroniza permissões staff.

## 7. Validações executadas

Resultados anteriores à última rodada de P1:

- suíte integral paralela: `516 testes / 4320 asserções`, verde;
- Pint integral, PHPStan integral, build e audits estavam verdes naquele ponto.

Resultados mais recentes:

- preço positivo: `71 testes / 302 asserções`, verde;
- RBAC storefront: teste isolado `9/101`; matriz ampliada mais recente `109 testes / 1.111 asserções`, verde antes dos dois últimos ajustes mínimos de fixture citados acima;
- `ShopifyDraftOrderPipelineTest`: 11 testes verdes após os primeiros fences;
- `PaymentPendingOrderAutomationTest`: 12 testes verdes;
- PHPStan focado nos arquivos recentes (`ShopifyDraftOrderCheckout`, `CheckoutService`, automação, `OrderResource`, `Order`, pruning): verde;
- `composer audit --locked --no-dev`: sem advisories;
- `npm audit --omit=dev --audit-level=high`: 0 vulnerabilidades;
- Pint informado verde pela revisão;
- `git diff --check` estava verde, salvo avisos normais de CRLF.

Última execução combinada:

```text
ShopifyDraftOrderPipelineTest: PASS
PaymentPendingOrderAutomationTest: PASS
CheckoutTest: interrompido no primeiro 403
```

O 403 ocorreu porque o novo RBAC exige buyer role e a fixture legada ainda não tinha papel explícito. O agente de RBAC estava corrigindo as fixtures; não tratar esse resultado isolado como bug definitivo de produção.

Depois das alterações mais recentes **a suíte integral ainda não foi repetida**. Os números 516/4320 não são evidência final da árvore atual.

## 8. Gates externos Shopify/produção

Não ativar o checkout público por suposição.

Gates ainda reais e não reproduzíveis apenas localmente:

- confirmar no Shopify Partner Dashboard se o app é custom/merchant-created ou public;
- se for app público criado a partir de 01/04/2026, implementar/validar refresh de offline access token expirável antes de reautorizar;
- aprovação e reautorização dos scopes `read_all_orders` e `read_payment_terms`;
- teste controlado real de cartão;
- teste controlado real de ACH;
- teste controlado real de Wire;
- teste de Payment Terms aprovado/reprovado;
- reconciliação/webhook real, fulfillment e refund;
- restore drill do backup do banco;
- observação pós-release por 48 horas.

O deploy por push deve publicar código/migrations mantendo o estado anterior do kill switch. Espera-se que o checkout permaneça OFF nesta primeira publicação. Só executar dispatch manual com `checkout_state=enable` depois dos gates reais.

## 9. Sequência exata recomendada para retomar

1. Ler este arquivo e `NovoModeloNegocio.md`.
2. Rodar `git status --short --branch`; preservar todas as alterações.
3. Verificar se os agentes de webhook/RBAC terminaram e revisar seus diffs.
4. Finalizar os testes do fence Shopify e retry de Customer suspenso/cancelado.
5. Fechar o risco de roles/permissions de buyer em deploy com migration/preflight idempotente.
6. Rodar matrizes focadas:

```powershell
php artisan test tests/Feature/ShopifyDraftOrderPipelineTest.php
php artisan test tests/Feature/PaymentPendingOrderAutomationTest.php
php artisan test tests/Feature/CheckoutTest.php
php artisan test tests/Feature/StorefrontBuyerRbacTest.php
php artisan test tests/Feature/ShopifyWebhookCanonicalBindingTest.php tests/Feature/ShopifyWebhookTest.php
php artisan test tests/Feature/PositiveWholesalePricingTest.php tests/Feature/CatalogTest.php tests/Feature/CartTest.php tests/Feature/ReleaseSafetyTest.php
```

7. Rodar gates integrais:

```powershell
vendor\bin\pint --test
vendor\bin\phpstan analyse --memory-limit=2G --no-progress
composer test
npm run build
composer validate --strict
composer check-platform-reqs
composer audit --locked --no-dev
npm audit --omit=dev --audit-level=high
```

8. Validar YAML e shell:

```powershell
bash -n scripts/production-release-guard.sh
php artisan route:list
php artisan schedule:list
git diff --check
```

9. Atualizar a seção de evidências de `NovoModeloNegocio.md` com os números finais e deixar gates externos desmarcados.
10. Fazer secret scan e confirmar que ZIP, `.env`, chaves, dumps e artefatos temporários não entram no index.
11. Somente então, com escrita Git escalada:

```powershell
git add -A
git diff --cached --name-only
git diff --cached --check
git commit -m "feat: implement open wholesale checkout model"
git push origin main
```

12. Monitorar `.github/workflows/deploy.yml` até estado terminal.
13. Se o preflight falhar por scopes, **não contornar**; obter aprovação/reautorização.
14. Se deploy passar, fazer smoke GET em `/up`, `/`, `/products`, `/how-to-order`, `/cart` e confirmar que checkout continua no estado preservado/OFF.
15. Não gerar pedido/pagamento real sem autorização e ambiente controlado.

## 10. Cuidados para não perder trabalho

- Não executar reset/clean/checkout destrutivo.
- Não sobrescrever alterações concorrentes.
- Todas as edições locais devem usar patch.
- O ZIP é material de recuperação local, não artefato de release.
- O commit `7a4c68e` é o rollback exato anterior à mudança e está preservado no histórico publicado.
- O estado inicial sem commit/deploy foi superado; consultar a seção 12 para o histórico operacional atual.
- Antes de declarar conclusão, usar os resultados atuais da suíte integral, não os números antigos.

## 11. Atualização da retomada — 02/08/2026

### 11.1 Pendências locais fechadas

- O binding canônico de webhook foi revisado e validado. O fallback exige o par exato `wholesale_order_id` + `wholesale_order_number`, mesma loja e IDs remotos sem conflito.
- Foi criada a migration aditiva/idempotente `2026_07_30_010000_provision_storefront_buyer_roles.php`:
  - cria `buyer_admin`, `buyer_purchaser` e `buyer_viewer` no guard `web`;
  - atribui `buyer_admin` somente a contas ativas customer-linked sem qualquer papel;
  - não converte identidades staff/mistas e registra esses casos para revisão;
  - preserva atribuições no `down` para não revogar contas criadas depois da migration.
- `ReleasePreflight` agora exige as três buyer roles e falha se qualquer conta storefront ativa não tiver identidade buyer-only.
- Signup e `AccountProvisioner` não ignoram mais buyer role ausente; falham fechados antes de deixar conta sem autorização.
- A suíte Shopify cobre ação forjada em pedido cancelado/refunded, fences de draft/completion/mark-paid, cancelamento pago, retry após suspensão e totais Card/ACH/Wire/NET.
- Se o Customer perder elegibilidade após a criação remota e antes da persistência:
  - draft provisório é excluído com prova de lease;
  - exclusão ambígua preserva vínculo sem invoice URL e marca reconciliação;
  - Shopify Order já comprometida é persistida e marcada para reconciliação, mas o checkout retorna falha e não libera instruções ao comprador.
- Retomada local de checkout possui testes explícitos para pedido claimed cancelado e Customer suspenso.
- A decisão de UX/RBAC foi fechada: `buyer_purchaser` pode criar somente endereço de entrega via rota restrita de checkout; continua sem listagem, edição, exclusão ou administração ampla de endereços e crédito. A ação de exclusão não aparece para esse papel.
- A fixture de política de senha administrativa recebeu papel staff explícito, compatível com o hardening fail-closed.

### 11.2 Evidências atuais

- matrizes críticas focadas: `216 testes / 1.579 assertions`, verdes;
- suíte integral paralela: `602 testes / 4.944 assertions`, verde em 8 processos;
- Pint integral: verde;
- PHPStan/Larastan integral: verde, sem erros;
- build Vite de produção: verde;
- `composer validate --strict`: verde;
- `composer check-platform-reqs`: verde;
- `composer audit --locked --no-dev`: nenhuma vulnerabilidade;
- `npm audit --omit=dev --audit-level=high`: zero vulnerabilidades;
- `bash -n scripts/production-release-guard.sh`: verde;
- workflows CI/deploy: YAML válido via Symfony YAML;
- rotas: `120` carregadas;
- scheduler: `9` tarefas carregadas com cache local em memória porque o MySQL local não estava ativo;
- `git diff --check`: verde, apenas avisos normais de CRLF;
- secret scan de alta confiança: zero arquivos com credencial detectada;
- `.env`, `.secrets`, `FullBackup-AntesMudarModeloNegocio.zip` e `known_hosts_deploy.txt`: confirmados como ignorados.

### 11.3 Estado operacional

- Os commits de release `42acb6e` e de correção `739c2d7` estão publicados na `main`.
- O CI de `739c2d7` passou; a promoção em produção foi bloqueada pelo preflight Shopify e restaurada com segurança.
- O kill switch não foi alterado nem ativado.
- Os gates externos da seção 8 continuam obrigatórios e não podem ser simulados localmente.
- Próxima etapa segura: corrigir a instalação e os scopes Shopify, fazer novo push mantendo checkout OFF e monitorar o workflow; não contornar falha de scopes/preflight.

## 12. Estado após as primeiras tentativas de produção — 02/08/2026

- O release foi publicado na `main` pelo commit `42acb6e`.
- A primeira execução revelou uma falha real no ensaio do stream criptografado de backup; a correção e sua regressão foram publicadas no commit `739c2d7`.
- O CI de `739c2d7` passou integralmente, inclusive o ensaio de backup/restauração com MariaDB.
- O job de produção enviou o candidato imutável ao servidor, mas falhou fechado no preflight anterior à manutenção porque:
  - a instalação Shopify ativa não corresponde a `SHOPIFY_SHOP_DOMAIN`;
  - faltam os scopes `read_products`, `read_inventory`, `read_orders`, `read_customers`, `read_draft_orders`, `read_all_orders` e `read_payment_terms` na instalação canônica reconhecida pelo servidor.
- Nenhum backup, migration ou promoção dessa tentativa ocorreu. O guard restaurou o código anterior e o checkout permaneceu desligado.
- Smoke tests após a restauração confirmaram `/up`, `/` e `/products` com HTTP 200; `/cart` e `/checkout` continuam redirecionando para login na versão antiga. `/how-to-order` continua ausente até a nova release ser promovida.
- A auditoria local posterior reforçou a verificação do candidato no servidor para exigir aplicação, dependências, migrations, rotas, views, release guard e `public/build/manifest.json` antes do preflight.
- A loja canônica real foi confirmada como `tgujns-ep.myshopify.com`, configurada no ambiente `production` do GitHub e usada como fallback durável no workflow.
- A instalação Shopify foi refeita com `read_all_orders` e os scopes de escrita equivalentes. O preflight passou a reconhecer corretamente que `write_*` inclui a leitura correspondente, mantendo `read_all_orders` explicitamente obrigatório.
- A suíte atual passou com `602 testes / 4.944 assertions`, além de Pint, PHPStan, Composer, build Vite, audits online, YAML, Bash, 120 rotas e 9 tarefas agendadas.
- Próxima ação: publicar o hotfix e repetir o deploy sem alterar o kill switch do checkout.
