Commit graph

995 commits

Author SHA1 Message Date
54058da059 OPS52 — Migrar a media de produção do Vercel Blob para o Garage S3
Merge pull request #27 from fsolla/OPS52-migrar-a-media-de-producao-do-vercel-blob-para-o-garag

OPS52 — Migrar a media de produção do Vercel Blob para o Garage S3 (Closes #3)
2026-08-18 02:45:52 +00:00
Francisco Solla
a34cd9b68a fix(ops OPS53): deploy — compose run consome o stdin do bash -s (migrate com </dev/null); build via --network host + proxy socat (BuildKit recusa rede bridge custom) 2026-08-18 01:59:17 +00:00
Francisco Solla
dabc00f46c ops(OPS52): migra a media de produção do Vercel Blob para o Garage S3
- payload.config.ts: vercelBlobStorage -> s3Storage (@payloadcms/storage-s3)
  com endpoint Garage (forcePathStyle, region garage); bucket privado — o
  staticHandler do plugin streama os objetos em /api/media/file/<filename>,
  mantendo o contrato de URL relativa das 40 rows pré-existentes
- src/utilities/mediaStorage.ts: resolveS3StorageEnv fail-closed (S3_* parcial
  -> throw no boot com a lista exata; nenhuma -> storage local dev/test)
- seed-posts: remove pre-delete do @vercel/blob (S3 sobrescreve nativamente)
- worktree-env.mjs: s3EnvCopiedLines all-or-nothing (unit-testada)
- envs S3_BUCKET/S3_ENDPOINT/S3_REGION/S3_ACCESS_KEY_ID/S3_SECRET_ACCESS_KEY
  no .env.example/.env.test; cloud-setup.sh sem o sed morto do blob
- deps: -storage-vercel-blob -@vercel/blob +storage-s3; importMap regenerado
- docs: impl plan (revisão A->B: Garage v2 sem acesso anônimo na API S3),
  AGENTS.md, changelog 2026-08-18-ops52
2026-08-17 22:36:34 -03:00
Francisco Solla
0aec0d5040 feat(PUB5): slogan 'Mais saúde mais futuro' no hero e rodapé 2026-08-18 01:31:28 +00:00
Francisco Solla
8854fcb85b style(plans S1-S4): prettier nos planos e no rascunho UI (format pós-commit do lote) 2026-08-17 22:02:14 -03:00
Francisco Solla
02c922eac8 docs(ops OPS53): falha conhecida do runner — PATH dos containers quebra com runner.envs.PATH só de host 2026-08-18 00:50:41 +00:00
Francisco Solla
6a3f61f968 ops(OPS53): etapa de deploy no CI para o homeserver (teqo-1313)
Job deploy em ci.yml (runs-on host na workstation) streama
scripts/deploy-homeserver.sh para o homeserver via SSH: build dos stages
runner+migrator com secrets do teqo-1313.env, push no registry local,
migrate pelo serviço de maintenance antes do rollout, up + smoke. Zero
secrets novos no Forgejo; HEAD guard + flock; rollback automático com
backup do compose; runbook docs/ops/teqo-1313-deploy.md; invariantes
unit do script (bash -n + estrutura).
2026-08-18 00:50:41 +00:00
Francisco Solla
87410ccc63 plan(S1-S4): seção de conteúdos na home de campanha — artigos, YouTube, Instagram + compartilhar WhatsApp 2026-08-18 00:47:52 +00:00
Francisco Solla
346da3896e style(plan): prettier no rascunho UI do PUB5 2026-08-17 21:34:27 -03:00
Francisco Solla
220142cc75 plan(PUB5): slogan da campanha 'Mais saúde mais futuro' no hero e rodapé 2026-08-17 21:33:12 -03:00
Francisco Solla
dfd57344e3 plan(OPS54): silencia o warning do pnpm sobre pnpm.onlyBuiltDependencies ignorado 2026-08-17 21:03:43 -03:00
Francisco Solla
e03ba1f83b ops(OPS51): migra o banco de produção do Neon para o Postgres do homeserver (teqo_1313)
Dump pg_dump -Fc do Neon no homeserver (/srv/hdd/backups/teqo-neon-pre-migracao/),
restore como a role teqo_1313 (o container já lia o banco preparado — sem mudança
de config). Neon intacto como rollback. Divergência da intenção (A/B validada como
B): destino = teqo_1313, não teqo_prod. Débito de media registrado (#10 → OPS52).
2026-08-17 22:41:18 +00:00
Francisco Solla
5afb54b692 chore(OPS53): prettier no plano 2026-08-17 16:06:05 -03:00
Francisco Solla
8cc4900cf0 plan(OPS53): etapa de deploy no CI para o homeserver (container teqo-1313) 2026-08-17 16:01:21 -03:00
Francisco Solla
f151376641 ops(OPS50): remove deploy Vercel do pipeline — produção é self-hosted no homeserver (jorgesolla1313.com.br); ci.yml vira verificador puro (sem deploy/requeue), apaga vercel-promote.yml, scripts/tests/vercel.json e secrets VERCEL_* 2026-08-17 13:17:17 -03:00
Francisco Solla
2f538e396b OPS50: ajusta changelog ao formato prettier 2026-08-16 23:34:28 -03:00
Francisco Solla
f20305759a OPS50: port CI e scripts de agentes do GitHub para o Forgejo
Workflows nativos em .forgejo/workflows/ (ci, ci-pr, agent-pool,
automerge, issue-transition, plan-issue, vercel-promote, archive),
removendo .github/workflows e .github/actions. Runner Forgejo v13 com
services Postgres por porta + DB_HOST via gateway do bridge. Libs de
agente sobre o novo cliente forgejo-api.mjs (zero dependências,
GITHUB_SERVER_URL/FORGEJO_API_URL), helpers de workflow plain-Node.
pnpm issue corrigido (await em função sync) e validado ao vivo. Testes:
forgejoApi.unit.spec.ts novo, pin do matrix do ci.yml atualizado.

Closes #1 (parte 1 — docs/issues/pool seguem na parte 2)
2026-08-16 23:32:20 -03:00
Francisco Solla
8d16b8a0cb plan(OPS50-52): planos de intenção — CI Forgejo, DB Neon→homeserver, Blob→Garage
Related #1 #2 #3
2026-08-16 21:54:25 -03:00
Francisco Solla
665157a0c0 feat(site): hero da campanha responsivo aos boards do Penpot
A primeira dobra da home pública agora acompanha as referências do Penpot
em 393, 768, 1024, 1280, 1366 e 1920 px. No desktop, a escala e a posição
horizontal das fotos dependem somente da largura: Solla, Lula e Wagner
ficam ancorados ao rodapé real do hero mesmo quando o conteúdo aumenta a
seção, e um palco centralizado de 1920 px preserva a proximidade entre
retrato e texto em monitores ultrawide. E2E fixa a geometria das seis
referências, transições de proporção, desktops baixos, ultrawide e os
overrides da WCAG 1.4.12; o caso de regressão também roda no Firefox.
2026-08-16 20:33:00 -03:00
Francisco Solla
98b1f5c089 style(site): formata artefatos da campanha 2026-08-16 00:50:07 -03:00
Francisco Solla
7ddc281f22 feat(site): publica home da campanha Jorge Solla 1313 2026-08-16 00:49:24 -03:00
Francisco Solla
d6df8c6360
Merge pull request #741 from fsolla/C139-contatos-pagina-da-entidade-contact-lista-desktop-cards
C139 — Contatos — página da entidade Contact (lista desktop + cards mobile)
2026-08-13 19:27:17 +00:00
Francisco Solla
d4342a96d7 docs(C139): plano C140 — form reset do React 19 em formulários de campanha
Débito colhido no simplify do C139: ~21 forms com action={submitAction}
apagam o digitado em erro (provado na sessão). Registrado como #740 com
depends em #728.
2026-08-13 15:20:39 -03:00
Francisco Solla
a06f810a40
Merge pull request #739 from fsolla/C134-e2e-agenda-dia-hardcoded-17-de-agosto-de-2026-no-teste-
test(C134): e2e agenda deriva o dia do picker de término de hoje + 1 (sem data hardcoded)
2026-08-13 18:17:27 +00:00
Francisco Solla
fe0a7999a9 test(C134): e2e agenda deriva o dia do picker de término de hoje + 1 (sem data hardcoded)
O teste C104 clicava em '17 de agosto de 2026' fixo no picker de término;
quebrava deterministicamente ~2026-09, quando o dia sairia do grid visível.
Agora o alvo é civilDatePlusDays(formatBahiaCivilDate(new Date()), 1) —
sempre dentro do grid (dia do mês ou day 1 do mês seguinte como outside day).
Absorve também o flake pré-existente do redirect canônico ?tab=overview nos
3 sítios de toHaveURL do detalhe (mesmo regex da linha 219, C123).
2026-08-13 15:01:23 -03:00
Francisco Solla
b420598328
Merge pull request #734 from fsolla/OPS45-e2e-campaigne2efixtures-deixa-lixo-no-banco-de-teste-c
OPS45: e2e fixtures — purge de resíduo no claim + robustez dos int specs
2026-08-13 17:56:11 +00:00
Francisco Solla
9471c8f0aa OPS44: changelog por entrega + guards de docs + merge por rebase 2026-08-13 17:55:22 +00:00
Francisco Solla
bf25100ed5 chore(OPS45): e2e fixtures — purge de resíduo no claim de município + robustez dos int specs (Closes #723)
O cleanup do campaignE2EFixtures estava completo em runs normais (proxy auto-own
cobre contact/stateDeputy); o lixo vinha de runs crashados, cujo cleanup nunca
roda. O claim e2e agora purga resíduo como o int já fazia, e a purga ganhou a
classe dobradinha (stateDeputy vinculados via municipality.stateDeputies + fichas
órfãs com ref-check incluindo stateDeputy — FK ON DELETE RESTRICT).

peopleList.int.spec.ts passa a varrer todas as páginas (lista global de 25/pág)
com dedupe; personDelete/peopleList usam personName() nos nomes fixos, imunes ao
invariante global de nome de dobradinha.
2026-08-13 14:18:54 -03:00
Francisco Solla
1daaaf9f4e feat(C139): domínio de contatos — URL state, loader com vínculos e invariante de nome
Fase 2 do plano aprovado. Três módulos em src/utilities/contacts/:
- contactListUrl: contrato de params (q|gender|state|city|ausencia|vinculo|sort|dir|page),
  canonicalize, hrefs de sort e where de fonte com 'phones.value' like (ILIKE verificado
  no Postgres local).
- contactListData: loader com UM find em contact (user threadado, overrideAccess false),
  vínculos (liderancas/dobradinhas/assessores/equipe) como facets sobre o conjunto
  legível, filtro/sort/paginação em memória, nulos no fim (precedente B15).
- contactNameInvariant: lock contact-name:{normalized} + prefilter ILIKE + veredito
  exato em memória; mensagem de conflito pt-BR.

38 testes unit novos; format + tsc limpos.
2026-08-13 14:05:24 -03:00
Francisco Solla
69044a04bc plan(C139): nome obrigatório e único na criação, com aviso de conflito 2026-08-13 13:10:01 -03:00
Francisco Solla
9583bb16e8 plan(C139): revisão do rascunho UI — coluna CEP, Apagar no mobile, inputs sem moldura 2026-08-13 13:05:03 -03:00
Francisco Solla
dca6ccdc88 plan(C139): remove rascunho do C135 (cancelado no lote 2026-08-13) 2026-08-13 12:57:24 -03:00
Francisco Solla
977dab044e
Merge pull request #729 from fsolla/plans/plan-issue-43
plan(C139): Contatos - pagina da entidade Contact + cancelamento dos planos abertos de Pessoas
2026-08-13 15:56:35 +00:00
Francisco Solla
72d189cfd7 style(plan): prettier no rascunho UI do C139 + re-render PNGs 2026-08-13 12:55:24 -03:00
Francisco Solla
65a5881b2d plan(C139): Contatos — página da entidade Contact; cancela planos abertos de Pessoas (C121/C130+/C132/C135-C138) 2026-08-13 12:53:12 -03:00
Francisco Solla
c2296701e2 style(plans): C135 — formata HTML do rascunho UI (prettier) 2026-08-13 12:05:24 -03:00
Francisco Solla
8ed3da8982 docs(plans): C135 — pessoas mobile feed/cards edge-to-edge com drawer de edição e faixa de status 2026-08-13 12:05:24 -03:00
Francisco Solla
98b03d8e91
Merge pull request #718 from fsolla/C130-pessoas-ajustes-da-tabela-desktop-contato-completo-base
C130 — Pessoas: ajustes da tabela desktop (contato completo, base sob o nome, caret, tooltips, Dobra em, filtro/ordenação por partido)
2026-08-12 16:20:44 -03:00
Francisco Solla
ef41e0c6a3
Merge pull request #726 from fsolla/B200-municipios-mobile-encaixes-dos-cards-densidade-alinhame
B200 — Municípios mobile: encaixes dos cards — densidade, alinhamento de labels e avatares (pós-B196)
2026-08-12 16:01:40 -03:00
Francisco Solla
65659bac2f C130: ajustes da tabela desktop de pessoas (contato completo, base sob o nome, caret, tooltips, Dobra em, filtro/ordenação por partido) 2026-08-12 16:01:25 -03:00
Francisco Solla
98f8ec9b9b
Merge pull request #710 from fsolla/C128-pessoas-qualquer-pessoa-pode-assessorar-liderar-e-ou-do
C128 — Pessoas: qualquer pessoa pode assessorar, liderar e/ou dobrar — ciclo de vida nas tabelas pela lista
2026-08-12 15:45:55 -03:00
Francisco Solla
3ee2d83350 feat(B200): encaixes dos cards mobile de municípios — densidade, alinhamento de labels e pilha de avatares (pós-B196) 2026-08-12 15:40:02 -03:00
Francisco Solla
6f89a8ff59 fix(C128): separadores entre entradas do changelog pós-rebase (C123) 2026-08-12 15:31:01 -03:00
Francisco Solla
c0645067f1 feat(C128): ciclo de vida das capacidades pelas células de /campanha/pessoas (Closes #695)
Qualquer pessoa visível ganha/perde Assessora, Lidera e Aliada em pela
lista: a primeira cidade cria a entidade (conta staff sem credenciais
utilizáveis / liderança / dobradinha), a última remove da tabela com
confirmação destrutiva (manifest: votos+convites da liderança, conta+
autorias+assessorado da assessora; dobradinha sem diálogo). Saída
destrutiva por escopo: assessor encerra Lidera/Aliada com a capacidade
inteira na carteira; Assessora segue coordenação/candidato. Escritas
person-centric por contactId com extração dos deltas B34/B37 e da
cascata de conta (deleteCampaignUserAccount, nextFreeStubCampaignEmail,
matchers de conflito) — sem twin. commitGuard/commitWithNullOwner/
extraFormFields como opt-ins no RelationChipCell. Corrige bug latente
C116 (célula Assessora nunca salvava — contactId faltava no FormData).
Sem migration. Int: 28, unit: 6, e2e: +2.
2026-08-12 15:29:56 -03:00
Francisco Solla
4202462e17 docs(plans): OPS43 — migration-lock bloqueia PRs sem schema por colateral (#721) 2026-08-12 15:03:20 -03:00
Francisco Solla
99a3a5f590 test(OPS42): e2e dev — quiescência do router antes de interagir (login + chat Sollinha) (Closes #691) 2026-08-12 15:03:20 -03:00
Francisco Solla
db8102b47e feat(C123): agenda — overlay modal central como única superfície de criação/edição de atividade (Closes #667) 2026-08-12 14:16:20 -03:00
Francisco Solla
508350fcf1 chore(plan-issue): formata o rascunho do OPS44 (prettier) 2026-08-12 14:12:52 -03:00
Francisco Solla
057eebfbb1 plans(OPS44): redesenhar fluxo de registros/compartilhados para menos conflitos (Related #713) 2026-08-12 14:12:52 -03:00
Francisco Solla
7e05dc925d feat(C131): Salvador como opção agregada no dropdown de municípios das células de capacidade
O dropdown de adição de municípios (pessoas ×3, assessores, lideranças,
dobradinhas) oferece 'Salvador — Todas as zonas' como primeiro hit da busca:
um toque adiciona as 19 ZEs num lote, via máquina existente do RelationChipCell
(delta otimista, cap/floor, undo, colapso 'Salvador (19)' B178, exact-match C116).

- searchMunicipalityPortfolio ganha kind 'city' (NORMALIZED_ZONE_CITIES,
  derivado do catálogo) com gate de escopo por contagem: o agregado só aparece
  quando a cidade inteira está no escopo addableIds do ator — a label 'Todas as
  zonas' nunca mente para assessor com carteira parcial.
- hitDescription ganha o branch 'Todas as zonas'; sem migration/access/schema.
- Testes: unit busca pura (19 ids, soma, escopo parcial, tudo atribuído,
  posição), cell render, e2e em campaignPeople (agregado → chip → 19 zonas no
  DB).
2026-08-12 14:02:34 -03:00