diff --git a/brain/PENDING_UPDATES.md b/brain/PENDING_UPDATES.md index 9b1c0cb..4fd0747 100644 --- a/brain/PENDING_UPDATES.md +++ b/brain/PENDING_UPDATES.md @@ -6,10 +6,7 @@ Fila FIFO de lacunas que precisam ser confirmadas para manter o Brain fiel ao pr - [ ] Confirmar o nome do owner a ser usado no front-matter dos documentos canonicos. Valor inicial usado: `LuanTrindade95`. - [ ] Decidir se o pacote operacional de prompts deve ser versionado dentro do repositorio ou continuar como referencia externa em `Downloads`. -- [ ] Definir backlog tecnico inicial pos-Fase 8. +- [ ] Definir backlog tecnico inicial pos-Fase 9. - [ ] Confirmar como Obsidian sera usado na pratica: apenas templates dentro do repositorio ou tambem vault/configuracao local fora do Git. -- [ ] Decidir se vulnerabilidades dev-only apontadas por `npm audit` completo devem ser tratadas em hardening futuro ou aceitas enquanto `npm audit --omit=dev` estiver limpo. -- [ ] Aprovar explicitamente, por plataforma, qualquer criacao externa em Netlify, Render, Aiven ou equivalente. -- [ ] Definir politica de reset do banco demo para staging futuro. -- [ ] Confirmar Git remoto e workspace antes de qualquer deploy externo. -- [ ] Validar template Render com CLI/Dashboard apenas apos Gate PO. +- [ ] Planejar o upgrade major do Angular que encerra as advisories aceitas em `ADR-020` e devolve `npm run fitness` ao verde. +- [ ] Decidir como tratar a hibernacao do plano free na primeira visita antes de divulgar a URL para avaliadores. diff --git a/brain/canonico/CURRENT_STATE.md b/brain/canonico/CURRENT_STATE.md index 61ea8e8..2e2f94e 100644 --- a/brain/canonico/CURRENT_STATE.md +++ b/brain/canonico/CURRENT_STATE.md @@ -1,5 +1,5 @@ --- -updated: 2026-09-18 +updated: 2026-09-20 owner: LuanTrindade95 status: canonico --- @@ -131,13 +131,16 @@ Existe no repositorio: - Render Blueprint real `render.yaml` foi materializado e validado - Aiven criou `flowcore-valkey` em free tier - Aiven bloqueou segundo MySQL free por limite da organizacao; FlowCore usa banco `flowcore_staging` e usuario `flowcore_app` isolados no servico MySQL existente `portfolio` - - Netlify permanece pendente ate existirem URLs publicas de API/Reverb + - Blueprint aplicado no Render: `flowcore-api` em `https://flowcore-api-urkx.onrender.com` e `flowcore-reverb` em `https://flowcore-reverb.onrender.com`, ambos web services free com `autoDeploy: false` + - Netlify no ar em `https://flowcore-luantrindade.netlify.app`, servindo `/config.json` com as URLs publicas de API e Reverb + - Smoke externo completo executado contra as URLs publicas: `/health`, `/config.json`, login, catalogo, criacao de solicitacao, inbox, decisao e evento realtime no canal privado + - `render.yaml` define `LOG_CHANNEL=stderr` e `LOG_LEVEL=error` para que excecoes apareçam nos Logs do Render Ainda nao existe: - Fluxos completos do produto fora do roadmap faseado. - Backlog tecnico. -- Deploy publico/staging real aplicado no Render/Netlify. +- Escalonamento de SLA em staging, que depende de scheduler ausente no plano free. ## Contexto Confirmado @@ -181,12 +184,15 @@ Ainda nao existe: - A Fase 8 definiu que templates Render/Aiven permanecem documentais ate Gate PO especifico. - A Fase 9 definiu que o limite gratuito da Aiven impede segundo MySQL; o banco demo FlowCore deve ficar isolado em `flowcore_staging`, sem operar sobre `defaultdb`. - A Fase 9 definiu `flowcore-valkey` como Redis-compatible gerenciado para cache, sessoes, filas e Horizon/Reverb no staging. +- A Fase 9 definiu que o staging free roda sem Horizon e sem scheduler, com `QUEUE_CONNECTION=sync`, o que desliga o escalonamento de SLA fora do ambiente local. +- A Fase 9 definiu `LOG_CHANNEL=stderr` como requisito do staging: sem ele a excecao fica em arquivo dentro do container e o diagnostico externo se torna cego. +- A Fase 9 aceitou as advisories de `@angular/*` 19.2.25 para a demo de staging, conforme `ADR-020`, mantendo `npm run fitness` vermelho no passo `audit`. ## Em Progresso -Fase 9 em andamento em `main`. +Nenhuma fase em andamento. A Fase 9 foi concluida em 2026-09-19/20 na branch `feature/phase-9-external-smoke`, com smoke externo reproduzido e aprovado em auditoria adversarial. -Proxima etapa recomendada: aplicar o Blueprint no Render Dashboard, preencher segredos `sync: false`, capturar URLs publicas de API/Reverb e entao criar/configurar o site Netlify. +Proxima etapa recomendada: definir o backlog tecnico pos-Fase 9, com o upgrade major do Angular como candidato prioritario por causa das advisories aceitas em `ADR-020`. ## Bloqueios diff --git a/brain/canonico/DECISIONS.md b/brain/canonico/DECISIONS.md index cdb41cc..e9bf63c 100644 --- a/brain/canonico/DECISIONS.md +++ b/brain/canonico/DECISIONS.md @@ -1,5 +1,5 @@ --- -updated: 2026-06-12 +updated: 2026-09-19 owner: LuanTrindade95 status: canonico --- @@ -265,3 +265,9 @@ Por que: Netlify config nao provisiona recurso por si so; Render Blueprint e Aiv Decisao: adicionar `/health` com resposta JSON simples para checks de plataforma. Por que: Render e outras plataformas precisam de liveness HTTP sem autenticar, sem tocar banco e sem acoplar health check ao dominio runtime. + +## 2026-09-19 - Aceite das advisories do Angular 19 no staging + +Decisao: aceitar as 7 advisories de `@angular/*` 19.2.25 para a demo de staging; `npm run fitness` fica vermelho no passo `audit` enquanto elas existirem, sem bloquear a Fase 9. O upgrade major do Angular e tarefa propria. + +Por que: nao existe correcao dentro da linha 19, a superficie e demo de portfolio sem dado real de usuario e sem SSR, e puxar migracao de framework para dentro do smoke externo trocaria um risco conhecido por um risco maior. Detalhes em `brain/decisions/ADR-020-angular-19-advisory-acceptance.md`. diff --git a/brain/canonico/KNOWN_ISSUES.md b/brain/canonico/KNOWN_ISSUES.md index a5ec896..50c00b7 100644 --- a/brain/canonico/KNOWN_ISSUES.md +++ b/brain/canonico/KNOWN_ISSUES.md @@ -1,21 +1,26 @@ --- -updated: 2026-09-18 +updated: 2026-09-19 owner: LuanTrindade95 status: canonico --- # Known Issues -Nenhum bug funcional aberto registrado nas fases concluidas ate a Fase 8. +Nenhum bug funcional aberto registrado. ## Limitacoes Atuais - Fluxos completos do produto ainda nao foram especificados. - Backlog tecnico ainda nao foi criado. -- Deploy publico/staging real ainda nao foi provisionado por decisao do PO. +- Staging externo esta no ar: frontend Netlify `https://flowcore-luantrindade.netlify.app`, API Render `https://flowcore-api-urkx.onrender.com`, Reverb Render `https://flowcore-reverb.onrender.com`, MySQL/Valkey Aiven no projeto `portfolio-01`. +- Os web services Render em plano free hibernam por inatividade; a primeira resposta apos hibernacao ja foi medida em 24,6 s e 84,5 s. Qualquer divulgacao do link precisa avisar sobre essa espera. +- O servico MySQL Aiven `portfolio` desliga sozinho (`Powered off`) e, enquanto desligado, seu hostname deixa de resolver em DNS. A API continua respondendo `/health` 200, mas toda rota que toca o banco retorna 500. Religar o servico no console Aiven restaura o acesso. +- O staging Render roda `QUEUE_CONNECTION=sync` sem Horizon e sem scheduler: o escalonamento de SLA (`workflow:escalate-overdue`) nao executa em staging, so em ambiente local. +- Logo apos religar o MySQL Aiven, chamadas isoladas a API podem falhar com 500 ou 520 de borda antes de estabilizar; repetir a chamada resolve. Um 500 nessa janela nao caracteriza bug de aplicacao. +- A API em staging roda `php artisan serve`, servidor de desenvolvimento de processo unico, adequado apenas para demo. - O host Windows possui PHP 8.2.26; a referencia de runtime para PHP 8.3 e Docker/CI. - O token frontend permanece somente em memoria por decisao de seguranca do MVP; recarregar a SPA exige novo login. -- `npm audit --omit=dev` esta limpo; auditoria completa do npm ainda pode apontar vulnerabilidades em dependencias dev do toolchain Angular/Jest. +- `npm audit --omit=dev` acusa 7 vulnerabilidades (3 high) em `@angular/*` 19.2.25, ultima versao da linha 19; a correcao exige upgrade major. Enquanto nao houver decisao, `npm run fitness` termina vermelho nesse passo. - Se `backend/.env` local existir com `DB_CONNECTION=sqlite`, o servidor HTTP Docker pode autenticar contra banco errado. Alinhar `.env` local ao `.env.example` antes de smoke HTTP. - O versionamento imutavel da Fase 3B usa endpoint explicito `/draft`; update direto em publicado e recusado com 422. - A tabela `instance_steps` possui apenas `assigned_to`; para steps por role/multiplos aprovadores, a Fase 3C deixa `assigned_to=null` e resolve os aprovadores dinamicamente a partir de `step_approvers` no momento da decisao. @@ -26,6 +31,8 @@ Nenhum bug funcional aberto registrado nas fases concluidas ate a Fase 8. - O CI exibe annotations de deprecacao: actions em runtime Node 20 (`actions/checkout@v4`, cache) e migracao de `ubuntu-latest` para Ubuntu 26 a partir de 2026-10-19. - Em Docker local, `backend/.env` ignorado precisa estar alinhado ao `.env.example` para `BROADCAST_CONNECTION`, `REVERB_APP_ID`, `REVERB_APP_KEY`, `REVERB_APP_SECRET` e `REVERB_BROADCAST_HOST`; caso contrario, o servidor `artisan serve` pode divergir dos processos CLI. - O deploy externo ainda depende de plataforma, workspace, Git remoto, secrets e URLs reais aprovados pelo PO. -- `deploy/render/render.yaml.example` nao foi validado por Render CLI nem aplicado em Blueprint, por decisao de nao criar/provisionar recursos externos. -- A politica de reset do banco demo para staging externo ainda precisa de aprovacao explicita por plataforma. +- `deploy/render/render.yaml.example` permanece documental; o Blueprint real aplicado e `render.yaml`. +- `render.yaml` define `LOG_CHANNEL=stderr` e `LOG_LEVEL=error` para que excecoes aparecam nos Logs do Render; sem elas o Laravel grava em arquivo dentro do container e o erro fica invisivel. O valor so vale apos novo deploy do Blueprint. +- Os testes backend via `docker compose exec` rodam contra o MySQL do compose em vez do sqlite de `phpunit.xml`, porque o `env_file` do compose precede os `` do PHPUnit; rodar a suite apaga os dados demo locais. +- O banco demo resetavel e exclusivamente `flowcore_staging` no servico MySQL Aiven `portfolio`; `defaultdb` e qualquer outro banco estao fora da politica de reset. - O runner local do `godmode-plus` foi ajustado fora do repositorio para resolver `npx` no Windows via `cmd.exe`; uma atualizacao futura da skill pode sobrescrever esse ajuste. diff --git a/brain/canonico/NEXT_ACTIONS.md b/brain/canonico/NEXT_ACTIONS.md index c85bd06..cb22c50 100644 --- a/brain/canonico/NEXT_ACTIONS.md +++ b/brain/canonico/NEXT_ACTIONS.md @@ -1,5 +1,5 @@ --- -updated: 2026-06-12 +updated: 2026-09-20 owner: LuanTrindade95 status: canonico --- @@ -8,35 +8,28 @@ status: canonico ## Ordem Recomendada -1. Aplicar o Blueprint Render publicado em `main`: - - repo: `https://github.com/LuanTrindade95/FlowCore`; - - arquivo: `render.yaml`; - - Dashboard: `https://dashboard.render.com/blueprint/new?repo=https://github.com/LuanTrindade95/FlowCore`. -2. Preencher no Render os segredos `sync: false` fora do Git: - - `APP_KEY`; - - credenciais Aiven MySQL do usuario `flowcore_app`; - - credenciais Aiven Valkey do usuario `default`; - - `REVERB_APP_ID`, `REVERB_APP_KEY`, `REVERB_APP_SECRET`; - - `APP_URL`, `FRONTEND_URL`, `FRONTEND_URLS`, `REVERB_HOST`, `REVERB_BROADCAST_HOST`. -3. Depois que `flowcore-api` e `flowcore-reverb` estiverem `live`, criar/configurar Netlify com as variaveis `FLOWCORE_*`. -4. Rodar migracoes/seed apenas no banco Aiven `flowcore_staging`; nunca rodar reset em `defaultdb`. -5. Executar smoke externo: `/health`, login, dashboard, runtime inbox/detalhe e realtime basico. +1. Definir o backlog tecnico pos-Fase 9, usando `brain/canonico/KNOWN_ISSUES.md` como entrada. +2. Planejar o upgrade major do Angular para encerrar as advisories aceitas em `ADR-020` e devolver `npm run fitness` ao verde. +3. Corrigir o isolamento da suite backend: `docker compose exec` roda os testes contra o MySQL do compose em vez do sqlite de `phpunit.xml`, apagando os dados demo locais. +4. Antes de divulgar a URL publica, confirmar que o MySQL Aiven `portfolio` esta `Running` e aquecer `flowcore-api` e `flowcore-reverb` com um `GET /health`. +5. Avaliar como reduzir o impacto da hibernacao do plano free na primeira visita: aviso na tela de login, aquecimento agendado ou mudanca de plano. 6. Manter seed demo idempotente como base obrigatoria de qualquer E2E local ou staging. 7. Atualizar `docs/DECISIONS.md`, `docs/PROGRESS.md` e o Brain no fechamento de cada fase. ## Estado Atual -Fase 9 esta em andamento e foi promovida para `main`. +Fase 9 concluida. Staging externo no ar e validado de fora. + +Superficies publicas: + +- Frontend Netlify: `https://flowcore-luantrindade.netlify.app` +- API Render: `https://flowcore-api-urkx.onrender.com` +- Reverb Render: `https://flowcore-reverb.onrender.com` +- Dados: MySQL Aiven `flowcore_staging` e Valkey Aiven `flowcore-valkey`, no projeto `portfolio-01` Evidencias registradas: -- Commit funcional: `466f0f7 feat(deploy): prepare staging runtime configuration` -- Blueprint Render: `14cdb59 feat(deploy): add staging blueprint` -- Ajuste validado do Blueprint free-tier: `beb74e8 fix(deploy): validate render free-tier blueprint` -- Root gate `npm run fitness` verde -- `npm run guard:migrations` verde -- `npm run check:enforcement` verde -- `npm --prefix frontend run build:staging` verde -- Browser local validou `/config.json`, login e dashboard sem erros de console -- Docker seed `php artisan db:seed --force` usado para restaurar dados demo antes do smoke autenticado -- veredicto `APROVADO` do verificador local +- Smoke externo completo em 2026-09-19 e reproduzido por auditoria independente em 2026-09-20: login 200, criacao de solicitacao 201, payload fora do schema 422, inbox 200, decisao 200 com avanco de step, evento `runtime.workflow.updated` recebido em canal privado sem refresh +- Veredito `APROVADO` da auditoria adversarial, com ressalvas de divulgacao registradas em `brain/canonico/KNOWN_ISSUES.md` +- `npm run guard:migrations` e `npm run check:enforcement` verdes; `npm --prefix frontend run build:staging` verde +- `npm run fitness` vermelho apenas no passo `audit`, conforme `ADR-020` diff --git a/brain/decisions/ADR-020-angular-19-advisory-acceptance.md b/brain/decisions/ADR-020-angular-19-advisory-acceptance.md new file mode 100644 index 0000000..833ef51 --- /dev/null +++ b/brain/decisions/ADR-020-angular-19-advisory-acceptance.md @@ -0,0 +1,30 @@ +# ADR-020 - Angular 19 advisory acceptance in staging demo + +## Status + +Accepted on 2026-09-19. + +## Context + +`npm audit --omit=dev` reports 7 advisories (3 high, 4 moderate) against `@angular/common`, `@angular/compiler`, `@angular/core`, `@angular/forms`, `@angular/platform-browser*` and `@angular/router` at `19.2.25`, which is the last release of the 19 line. The advisories cover `HttpTransferCache` cache-key ambiguity and information leak, a `formatDate` denial of service and a two-way binding sanitization bypass. No patch exists inside the 19 line, so the only remediation is a major upgrade. + +The FlowCore staging surface is a portfolio demo: a single Angular SPA on Netlify talking to one Laravel API, with demo accounts, seeded data and no real user data. The SPA is client-rendered and does not run server-side rendering, which is the delivery mode the `HttpTransferCache` advisories target. + +`npm run fitness` chains `audit` as its last step, so the gate stays red while the advisories are open. + +## Options considered + +- Upgrade Angular to a supported major line before closing phase 9. Clears the advisories, but pulls a breaking framework migration into a phase whose scope is external smoke, and risks the builder surface built on `@foblex/flow`. +- Drop `audit` from `npm run fitness`. Rejected: it hides the signal instead of deciding on it, and weakens a gate for every future task. +- Accept the risk for the staging demo and keep the gate red until a dedicated upgrade task. Chosen. + +## Decision + +Accept the advisories for the staging demo. `npm run fitness` is expected to fail on its `audit` step while they are open, and that failure does not block phase 9. The Angular major upgrade is a separate task, not part of external smoke work. + +## Consequences + +- Any task that runs `npm run fitness` must read the audit step failure against this ADR before treating it as a regression, and must confirm the failing advisories are still only these Angular ones. +- The acceptance covers the staging demo only. Real user data, authentication against a real identity provider or server-side rendering would each void it and require the upgrade first. +- `brain/canonico/KNOWN_ISSUES.md` carries the open limitation while it lasts. +- The upgrade task must revisit this ADR and supersede it once the advisories clear. diff --git a/docs/DEMO_E2E_SCRIPT.md b/docs/DEMO_E2E_SCRIPT.md index 9c25110..27d8a8f 100644 --- a/docs/DEMO_E2E_SCRIPT.md +++ b/docs/DEMO_E2E_SCRIPT.md @@ -79,6 +79,80 @@ Parar a demo se ocorrer qualquer item: - realtime exige refresh manual no roteiro de SLA; - seed duplicar usuarios, workflows ou instancias demo. +## Roteiro Externo (Staging) + +Este roteiro executa o mesmo fluxo de ponta a ponta contra as URLs publicas de staging, sem depender de `docker compose`. + +URLs: + +| Servico | URL | +|---|---| +| Frontend (Netlify) | `https://flowcore-luantrindade.netlify.app` | +| API (Render) | `https://flowcore-api-urkx.onrender.com` | +| Reverb (Render) | `wss://flowcore-reverb.onrender.com:443` | + +O roteiro de escalonamento de SLA (`workflow:escalate-overdue`) **nao se aplica** a este ambiente: o Render free tier roda `QUEUE_CONNECTION=sync` e nao provisiona worker/scheduler dedicado, entao nao ha execucao periódica do comando de escalonamento em staging. + +Passos: + +1. `GET https://flowcore-api-urkx.onrender.com/health`. + - Esperado: `200` com `{"status":"ok","service":"flowcore-api"}`. + - Atencao: o primeiro acesso apos um periodo ocioso pode levar de ~25 s a mais de 1 min por spin-down do plano free do Render; repetir a chamada apos o primeiro sucesso deve responder em menos de 1 s. + +2. `GET https://flowcore-luantrindade.netlify.app/config.json`. + - Esperado: `200` com `apiBaseUrl` apontando para `https://flowcore-api-urkx.onrender.com/api/v1` e `realtime.wsHost` apontando para `flowcore-reverb.onrender.com` (porta `443`, `forceTls: true`). + +3. Login como `requester@demo.com` (senha `password`): + + ```bash + curl -s -X POST https://flowcore-api-urkx.onrender.com/api/v1/auth/login \ + -H "Content-Type: application/json" -H "Accept: application/json" \ + -d '{"email":"requester@demo.com","password":"password"}' + ``` + + - Esperado: `200` com `access_token`. + +4. Buscar o schema do workflow `Aprovacao de Compra` publicado e criar uma solicitacao de compra com valor acima de `1000`: + + ```bash + curl -s https://flowcore-api-urkx.onrender.com/api/v1/runtime/workflows/ \ + -H "Authorization: Bearer " -H "Accept: application/json" + + curl -s -X POST https://flowcore-api-urkx.onrender.com/api/v1/requests \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" -H "Accept: application/json" \ + -d '{"workflow_definition_id": , "data": {"amount": 1500, "supplier": "Fornecedor Demo", "cost_center": "Tecnologia"}}' + ``` + + - O schema do formulario publicado (`GET /api/v1/runtime/workflows/`) define exatamente os campos `amount` (number), `supplier` (text) e `cost_center` (select: `Tecnologia`, `Operacoes` ou `Financeiro`), todos obrigatorios. Enviar qualquer campo fora dessa lista retorna `422` com `{"errors":{"data":["O formulario contem campos que nao pertencem a definicao publicada."]}}`. + - Esperado com o payload correto: `201` (o Laravel atribui automaticamente o status `201` a um `JsonResource` retornado por uma rota `POST`) com a instancia criada, `status: running` e o primeiro step (`manager_approval`, `assignee_type: dynamic` / `assignee_ref: requester_manager`) pendente e resolvido para o aprovador demo. + +5. Login como `approver@demo.com` (senha `password`) e conferir `GET /api/v1/inbox`. + - Esperado: `200` com a pendencia da solicitacao criada no passo 4 na lista (o aprovador dinamico do primeiro step e resolvido automaticamente para um usuario com role `approver`). + +6. Aprovar a pendencia pelo endpoint real de decisao: + + ```bash + curl -s -X POST "https://flowcore-api-urkx.onrender.com/api/v1/requests//steps//decide" \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" -H "Accept: application/json" \ + -d '{"decision":"approve"}' + ``` + + - Esperado: `200` com a instancia avancando de step. + +7. Inbox atualizando em realtime sem refresh: um cliente do aprovador se inscreve no canal privado `private-users.{id}.runtime` via Reverb (`wss://flowcore-reverb.onrender.com:443`), autenticando em `POST https://flowcore-api-urkx.onrender.com/api/broadcasting/auth` com `Authorization: Bearer `. + - Esperado: ao repetir o passo 4 (nova solicitacao do requester), o cliente inscrito recebe o evento `runtime.workflow.updated` (classe `App\Events\RuntimeWorkflowUpdated`) no canal do aprovador, sem reload manual. + +## Stop Criteria (Roteiro Externo) + +Parar o roteiro externo se ocorrer qualquer item: + +- qualquer resposta `5xx`; +- `401`/`403` inesperado (fora do esperado em `GET /api/v1/runtime/workflows` sem token); +- CORS bloqueado a partir da origem do Netlify; +- evento realtime nao recebido pelo cliente inscrito no canal privado. + ## Evidencias Versionadas Screenshots selecionados vivem em `docs/assets/screenshots/`: diff --git a/docs/DEPLOYMENT_READINESS.md b/docs/DEPLOYMENT_READINESS.md index 2c7631a..f591219 100644 --- a/docs/DEPLOYMENT_READINESS.md +++ b/docs/DEPLOYMENT_READINESS.md @@ -4,9 +4,9 @@ Este documento registra a prontidao de deploy do FlowCore e o estado de staging ## Status -- Netlify: configurado como candidato para SPA Angular estatica via `netlify.toml`; site ainda nao criado porque depende das URLs publicas do Render. -- Render: Blueprint real em `render.yaml` e template de referencia em `deploy/render/render.yaml.example`. -- Aiven: Valkey free-tier criado para FlowCore; MySQL free-tier ja estava ocupado, entao FlowCore usa banco e usuario isolados no servico MySQL existente. +- Netlify: site no ar em `https://flowcore-luantrindade.netlify.app` (`200`), servindo `/config.json` com as URLs publicas corretas de API e Reverb. +- Render: Blueprint real em `render.yaml` aplicado; `flowcore-api` (`https://flowcore-api-urkx.onrender.com`) e `flowcore-reverb` (`wss://flowcore-reverb.onrender.com:443`) no ar e respondendo `/health` com `200`. Smoke externo de login (`POST /api/v1/auth/login`) esta bloqueado com `500 Server Error`; a rota de validacao (sem tocar banco) responde `422` normalmente, entao a falha esta isolada ao acesso a banco/Redis. Diagnostico levado ao humano; nao investigar/alterar credenciais aqui. +- Aiven: Valkey free-tier criado para FlowCore; MySQL free-tier ja estava ocupado, entao FlowCore usa banco e usuario isolados no servico MySQL existente. Migracao/seed do banco `flowcore_staging` ainda nao confirmados dado o bloqueio acima. - Frontend: configuracao runtime carregada de `/config.json`. - Backend: `/health` disponivel para health checks de plataforma. @@ -52,32 +52,25 @@ FLOWCORE_REALTIME_FORCE_TLS ```text base: frontend command: npm ci && npm run build:staging -publish: dist/frontend/browser +publish: frontend/dist/frontend/browser ``` O arquivo tambem define rewrite SPA para `index.html` e `Cache-Control: no-store` para `/config.json`. -Antes de criar site no Netlify, o PO precisa aprovar: - -- conta/workspace; -- dominio ou subdominio; -- URL publica da API; -- variaveis `FLOWCORE_*` no escopo de build; -- smoke externo. +O site ja foi criado em `https://flowcore-luantrindade.netlify.app` com as variaveis `FLOWCORE_*` de staging aplicadas no escopo de build. ## Render O Blueprint `render.yaml` modela: -- API Laravel como web service Docker; -- Horizon como worker; -- scheduler como worker free-tier executando `schedule:run` em loop; -- Reverb como web service separado; +- `flowcore-api`: API Laravel como web service Docker (`plan: free`), rodando `php artisan serve`; +- `flowcore-reverb`: Reverb como web service Docker separado (`plan: free`), rodando `php artisan reverb:start`; +- `QUEUE_CONNECTION=sync`: o free tier nao provisiona Horizon nem worker/scheduler dedicado, entao filas rodam de forma sincrona e o escalonamento de SLA (`workflow:escalate-overdue`) nao executa periodicamente em staging; - segredos com `sync: false`; - `autoDeploy: false`; - banco e Valkey/Redis externos via Aiven. -O deploy Render ainda exige aplicar o Blueprint no Dashboard e preencher os segredos `sync: false` fora do Git. +O Blueprint ja foi aplicado no Dashboard com os segredos `sync: false` preenchidos fora do Git. ## Aiven diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 4dc33e9..523abbe 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -15,4 +15,4 @@ | Fase 6 - Polish & Vitrine | DONE | Branch `feature/portfolio-polish`; seed demo idempotente, README/arquitetura de vitrine, polish de login, 39 testes backend, 25 testes frontend, build, auditorias, seed real repetida e E2E browser login/dashboard/workflows/mobile validados. | | Fase 7 - Staging Documentado + Evidencias | DONE | Branch `feature/deploy-staging-evidence`; plano Netlify/Render/Aiven sem provisionamento externo, roteiro E2E, screenshots versionados, dashboard copy polish, `npm run fitness`, `guard:migrations`, `check:enforcement` e E2E visual local validados. | | Fase 8 - Deployment Readiness | DONE | Branch `feature/deployment-readiness`; runtime config do frontend, health endpoint, `netlify.toml`, exemplos de env, template Render e checklist Aiven, `npm run fitness`, `guard:migrations`, `check:enforcement`, `build:staging` e smoke Browser local validados. | -| Fase 9 - Platform Approval + External Smoke | IN_PROGRESS | PO aprovou seguir; Aiven Valkey `flowcore-valkey` criado, MySQL isolado em `flowcore_staging`/`flowcore_app`, `render.yaml` validado e publicado em `main`; pendente aplicar Blueprint Render, configurar Netlify e executar smoke externo. | +| Fase 9 - Platform Approval + External Smoke | DONE | Branch `feature/phase-9-external-smoke`; frontend `https://flowcore-luantrindade.netlify.app` e API `https://flowcore-api-urkx.onrender.com` no ar; smoke externo (2026-09-19) validou `GET /health` (`200`), `GET /config.json` (`200`), login `requester@demo.com` e `approver@demo.com` (`200`/`200`), schema publicado de `Aprovacao de Compra` via `GET /api/v1/runtime/workflows/1` (`200`), `POST /api/v1/requests` com o payload real (`amount`/`supplier`/`cost_center`) criando as instancias `#17` e `#18` no workflow de compra (`201`, primeiro step `assignee_type: dynamic` resolvido para o aprovador), `422` para payload com campo fora do schema publicado, `GET /api/v1/inbox` do aprovador listando as pendencias (`200`), `POST /api/v1/requests/17/steps/18/decide` avancando a instancia `#17` de `manager_approval` para `finance_approval` (`200`) e o pipeline de realtime completo disparado pela criacao da instancia `#18` (auth de canal privado `200`, subscribe confirmado em `private-users.2.runtime`, evento `runtime.workflow.updated` recebido sem refresh). `render.yaml` ganhou `LOG_CHANNEL=stderr`/`LOG_LEVEL=error` para manter futuras excecoes visiveis nos Logs do Render. | diff --git a/docs/STAGING_PLAN.md b/docs/STAGING_PLAN.md index 2782570..86212b2 100644 --- a/docs/STAGING_PLAN.md +++ b/docs/STAGING_PLAN.md @@ -28,9 +28,9 @@ Para a execucao operacional, a estrategia mais coerente e: - Exige backend publico configurado antes de virar demo funcional. 3. **Render como candidato para backend full stack** - - Melhor encaixe entre as opcoes para API Laravel, workers, scheduler e servicos web. + - Melhor encaixe entre as opcoes para API Laravel e servicos web. - O free tier e bom para prova de conceito, mas tem spin down em web services ociosos. - - No free tier, o template validado modela o scheduler como worker; cron dedicado fica como opcao futura paga/aprovada. + - `render.yaml` real modela apenas dois web services (`flowcore-api` e `flowcore-reverb`, ambos `plan: free`); nao ha worker de Horizon nem scheduler dedicado. Filas rodam com `QUEUE_CONNECTION=sync`, e o escalonamento de SLA (`workflow:escalate-overdue`) nao executa periodicamente neste ambiente. - Deploy real deve ser aprovado separadamente porque exige conta, Git remoto e variaveis sensiveis. 4. **Aiven como candidato para dados gerenciados** @@ -72,17 +72,15 @@ Ainda nao deve haver smoke externo completo sem aplicar Render e configurar Netl Netlify Angular SPA build: npm ci && npm run build:staging - publish: dist/frontend/browser + publish: frontend/dist/frontend/browser Render - Laravel API web service - Horizon worker - Scheduler worker no free tier - Reverb web service + flowcore-api: Laravel API web service (QUEUE_CONNECTION=sync, sem worker/scheduler) + flowcore-reverb: Reverb web service Aiven MySQL service portfolio / database flowcore_staging / user flowcore_app - Valkey service flowcore-valkey for Redis-compatible cache/queue/session + Valkey service flowcore-valkey for Redis-compatible cache/session ``` ## Variaveis De Ambiente Para Staging @@ -110,7 +108,7 @@ REDIS_PASSWORD= REDIS_PORT= SESSION_DRIVER=redis -QUEUE_CONNECTION=redis +QUEUE_CONNECTION=sync CACHE_STORE=redis BROADCAST_CONNECTION=reverb diff --git a/docs/env/staging.backend.env.example b/docs/env/staging.backend.env.example index 2651c2f..6309b53 100644 --- a/docs/env/staging.backend.env.example +++ b/docs/env/staging.backend.env.example @@ -30,7 +30,7 @@ REDIS_SCHEME=tls SESSION_DRIVER=redis CACHE_STORE=redis -QUEUE_CONNECTION=redis +QUEUE_CONNECTION=sync BROADCAST_CONNECTION=reverb FILESYSTEM_DISK=local diff --git a/render.yaml b/render.yaml index 1a84411..078f6a6 100644 --- a/render.yaml +++ b/render.yaml @@ -29,6 +29,10 @@ services: value: https://flowcore-luantrindade.netlify.app - key: FRONTEND_URLS value: https://flowcore-luantrindade.netlify.app + - key: LOG_CHANNEL + value: stderr + - key: LOG_LEVEL + value: error - key: APP_KEY sync: false - key: DB_CONNECTION @@ -101,6 +105,10 @@ envVarGroups: value: staging - key: APP_DEBUG value: "false" + - key: LOG_CHANNEL + value: stderr + - key: LOG_LEVEL + value: error - key: APP_KEY sync: false - key: DB_CONNECTION