Commit graph

40 commits

Author SHA1 Message Date
Francisco Solla
8387a477db fix(media): repara rota do Garage no deploy 2026-09-25 12:11:21 -03:00
Francisco Solla
1cfeff0250 docs(C220-FOLLOWUP): registra o efeito colateral do ufw (Garage) e a correcao no post-mortem/runbook 2026-09-25 10:47:23 -03:00
Francisco Solla
cba4a9d56c fix(C220-FOLLOWUP): retry no download do CDN do Instagram (rede instavel)
Causa-raiz do sintoma residual: o container e IPv4-only e a rota IPv4 ate o
CDN do Instagram e instavel nesta rede (IPv6 e o caminho confiavel); o resolver
baixava com uma tentativa e virava 'indisponivel'. O dono do download ganha
teto de conexao por tentativa e ate 6 tentativas; resposta nao-2xx nao repete.
Rede IPv6 ja corrigida no stack (fora do repo) e documentada no runbook.
2026-09-25 10:20:27 -03:00
Francisco Solla
0fa618d0af fix(ia-egress): estabiliza a rota ate o deepseek com proxy na tailnet + probe no deploy 2026-09-25 01:43:37 -03:00
Francisco Solla
4e7b844419 fix(C192/S28/C219): busca por tema indisponivel — thinking do deepseek-flash truncava o JSON 2026-09-24 23:09:49 -03:00
Francisco Solla
c0760f4234 docs(OPS128): remove verificação pós-deploy em staging do fechamento do work-issue (Closes #1188) 2026-09-19 00:29:23 -03:00
Francisco Solla
5afa16c33b feat(C195): ingestão do pacote do reel na biblioteca privada (Closes #1154) 2026-09-18 21:47:48 -03:00
Francisco Solla
10b58afe4c chore(OPS125): conta de teste dos agentes no staging (Closes #1126)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-17 02:08:57 -03:00
Francisco Solla
1ebae91428 fix(OPS126): auto-unblock honra o proxy do homeserver e resolve o opencode fora do PATH
Duas causas independentes mantinham o agente de desbloqueio (OPS106) sem
entregar:

1. `fetch failed` no launcher: o homeserver só alcança o GitHub pelo proxy
   CONNECT local (github-tunnel + http-proxy-socks) e o `fetch` global do Node
   ignora HTTP(S)_PROXY sem `NODE_USE_ENV_PROXY` (Node >= 24). O launcher
   morria lendo os jobs do run (run 35171293357) e nenhum token era criado.
   `scripts/auto-unblock.sh` passa a exportar `NODE_USE_ENV_PROXY=1` quando há
   proxy no env; o agente destacado herda.

2. exit 127 do agente: o serviço do runner não carrega o profile interativo,
   então `~/.opencode/bin` fica fora do PATH e o `timeout ... opencode` morria
   com *No such file or directory* (log unblock-35101121310.log), deixando o
   token `blocked` sem PR. Novo `resolveOpenCodeBinary` (OPENCODE_BIN → argv0
   com path → `$HOME/.opencode/bin` → PATH) usado pelo wrapper, pelo `--check`
   e por um gate fail-closed no launcher (token blocked, sem provisionar
   worktree).

Runbook + changelog OPS126; unit tests do resolver. Token órfão #1089 fechado
no replay. Flakiness de e2e full segue na #1124.
2026-09-17 02:07:18 -03:00
Francisco Solla
a164961344 docs(ops): ajusta wrapping do prettier 2026-09-15 15:46:01 -03:00
Francisco Solla
b9052f37bb docs(ops): staging.jorgesolla1313.com.br vivo no túnel Cloudflare (ingress zero; runbook atualizado) 2026-09-15 15:46:01 -03:00
Francisco Solla
e579406b1f feat(C163): relatório de cidade pré-viagem (agente + skill → PDF A4) (Closes #1007) 2026-09-15 07:10:45 -03:00
Francisco Solla
119b8980fb fix(OPS107): aprovação de produção não ocupa a lane do staging (Closes #1002)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-14 08:18:21 -03:00
Francisco Solla
37b338a700 feat(OPS106): falha do verify dispara agente autônomo de desbloqueio (single-flight)
Workflow separado auto-unblock.yml (workflow_run no Deploy, push/main + job verify vermelho pela jobs API), launcher com flock próprio + Issue token auto-unblock como single-flight, e wrapper destacado que provisiona worktree fix/* via worktree.mjs fix --headless, aplica guard de banco local teqo_wt* fail-closed e roda opencode run --command bug-fix (cap 4h). deploy.yml/verify intocados; sem auto-retry e produção segue com approval humano.
2026-09-14 05:51:39 -03:00
Francisco Solla
346f33c1ce docs(C160): runbook §C160 e changelog da prova viva em produção (965 falas, 0 legadas) (#988) 2026-09-14 05:00:18 -03:00
Francisco Solla
03d1b79629 fix(C160): normaliza coleções obsoletas (J/vazia) do link legado para D
A varredura de produção (2026-09-14) achou 33 falas em selCodColecaoCsv=J e 1
com o parâmetro vazio: o endpoint devolve 'Documento não encontrado' e a mesma
data/página resolve na coleção D que a busca atual da Câmara gera. Aliases
J/vazio → D, puros e unit-testados; DCN e demais códigos ficam como estão.
2026-09-14 05:00:18 -03:00
Francisco Solla
f58a712ad9 feat(OPS104): inicia o deploy no merge, com staging automático e produção com review
- deploy.yml: trigger push em main + preflight guard (pula se há run queued/in_progress; waiting não conta) e job hosted requeue após deploy-staging (fora do grupo deploy-homeserver)
- scripts/lib/deploy-trigger.mjs (decidePreflight/decideRequeue) + CLIs deploy-preflight/deploy-requeue; github-api ganha listWorkflowRuns/getBranchHead
- pins: ciSkipInvariants reescrito (push + guard + dispatch + requeue fora do grupo), deployTrigger/githubApi novos; deployScript intocado
- docs realinhados (AGENTS*, AGENT-OPS, README, runbook, rules/skills) + changelog

Closes #980
2026-09-14 03:07:59 -03:00
Francisco Solla
90718bc669 docs(C155): resultado da prova viva em produção (997 discursos) no changelog, runbook e plano 2026-09-14 01:54:55 -03:00
Francisco Solla
a41ee0d11d docs(C155): runbook do backfill em produção, changelog e ajustes do plano 2026-09-14 01:54:55 -03:00
Francisco Solla
b03b7bd969 feat(OPS103): staging no homeserver com verify único e aprovações separadas (Closes #968) 2026-09-12 22:48:22 -03:00
Francisco Solla
907b9ba96b refactor(OPS102): fixes do /simplify — comentários vivos alinhados, pin do exit 0 com mais dentes, runbook/changelog precisos 2026-09-12 21:32:28 -03:00
Francisco Solla
c9bd627de4 fix(OPS102): deploy manual roda até o fim mesmo com main à frente (remove guards de stale run) (Closes #962) 2026-09-12 21:32:28 -03:00
Francisco Solla
d9b778b269 feat(campaign): C149 — botão Conectar com o Google (OAuth) substitui a configuração manual da service account (Closes #934) 2026-09-12 19:49:24 -03:00
Francisco Solla
2aa445dd1d impl(OPS84): verificar valores (não só entidades) da migração — 13 tabelas, 0 diffs (Closes #828) 2026-08-24 15:03:31 -03:00
Francisco Solla
c69376f3c2 docs(deploy): caveat de rollback para backups pré-INF13 (tags bare) — review
O primeiro deploy pós-fix faz backup do compose ainda bare e o cleanup novo
remove os aliases bare em seguida: um rollback manual restaurando esse backup
legado precisaria recriar o alias (docker tag) após o pull. Documenta a
janela de transição na seção de rollback e na linha INF13 da tabela de
falhas.
2026-08-24 14:33:07 -03:00
Francisco Solla
ddd58a01d1 fix(deploy): compose referencia a tag qualificada do registry; F2 preserva por image ID (INF13)
O compose do stack referenciava a tag local bare teqo-1313:<sha>, que é uma
segunda ref que nada recria se perdida (achado INF8 24/08: só restava a ref
do registry e o 'compose up -d' falhou com No such image). Agora:

- swap escreve sempre localhost:5000/teqo-1313(-migrator):<sha> (sed
  idempotente aceita ambas as formas); os docker tag bare somem (sem
  consumidor);
- rollback do runbook simplifica (docker pull basta, sem dance de tag);
- limpeza pós-deploy (INF3/F2) preserva TODAS as tags da imagem em uso pelo
  IMAGE ID do container, imune a drift de label do compose.

Runbook docs/ops/teqo-1313-deploy.md atualizado (fluxo, rollback, tabela de
falhas com o achado). Issue de referência (tracker infra-solla):
git.solla.dev/fsolla/infra-solla#24
2026-08-24 14:17:43 -03:00
Francisco Solla
bddbd5c085 ops(OPS79): última migração de dados em produção — reconciliação da vertical campanha (Neon→teqo_1313) + migração do residual público (Closes #797)
- scripts/reconcile-campaign-vertical.mjs: verificação read-only repetível (contagens + junta de IDs das 13 coleções da vertical + conteúdo semântico das rels); absorve os 3 links de edição de portfolio pós-OPS51; nunca imprime PII
- scripts/migrate-signature-orphan.mjs: migração one-off com guard OPS79_MIGRATE_CONFIRM=1, dry-run/apply, transação única, PII mascarada
- Execução 100% no homeserver: aplicado contact 2225 + signature 1486 preservada + subscription 1492; sequences ajustadas; pós-verificação signature 1485=1485 e reconcile 19/19
- Runbook (docs/ops/teqo-1313-deploy.md §OPS79): execução + rollback (DELETE 3 linhas + setval)
- docs: plano de intenção restaurado (deletado acidentalmente em C140) + impl plan + changelog
2026-08-23 22:45:43 -03:00
Francisco Solla
28e1e4540c docs(OPS76-FOLLOWUP): runbook do backup passivo GitHub→Forgejo (pull mirror teqo-backup) 2026-08-21 09:23:43 -03:00
Francisco Solla
c723d6accf
merge(OPS75): convergência Forgejo→GitHub — GitHub como fonte única
* deploy: limpeza pós-deploy do build cache e tags locais antigas (INF3/F2)

O deploy compila no homeserver e acumulava build cache + tags locais
antigas no disco raiz (incidente 19/08: 45G de cache). Após o smoke:
docker builder prune -f + remoção das tags locais teqo-1313 exceto o
SHA em uso (best-effort, registry preserva o rollback).

* feat(S9): captura de novidades da campanha na home pública (form + CTA do hero)

Seção 'Receba as novidades da campanha' acima do rodapé: nome + WhatsApp
obrigatórios, e-mail/estado/cidade/comentário opcionais, toggle pré-selecionado
'Quero fazer parte do time' gravado como subscription.campaignLevel
(time|esporadico). CTA secundário do hero vira o atalho (#novidades, scroll
suave). Contact + Subscription em withPayloadTransaction com consentimento
novo fail-closed por chave estável 'campanha-novidades' — nada é gravado sem o
texto aprovado no admin. Migration 20260819_192605 (state de contact nullable
+ coluna campaign_level). Impl plan, changelog, int + e2e.

* plans(C141,C143,C142): permissões granulares por assessor + responsáveis de demanda + UI por perfil

* plans(C141,C143,C142): permissões granulares por assessor + responsáveis de demanda + UI por perfil

* feat(S8): seção 'Nossa história' na home — vídeo da trajetória embutido do YouTube (Closes #91)

* docs(S8): resolução do conflito com S9 (história → newsletter) + nota do guard e2e dev-only

* feat(S10): pixel do Meta na página pública de campanha (campo admin em SiteSettings + PageView na home + Lead no sucesso da captura)

Campo tracking.facebookPixelId no global SiteSettings (mesma validação/normalização do precedente Petition, regra centralizada em facebookPixel.ts); home (grupo (home)) injeta o base code + PageView quando o ID está configurado (fail-closed) e o CampaignNewsletterForm dispara exatamente um Lead no sucesso do S9. Migration 20260819_213947_add_site_settings_facebook_pixel_id. Closes #94

* refactor(S10): simplify pass — Lead wiring unit-tested e raças de estado compartilhado do e2e resolvidas

e2e: stub hermético de connect.facebook.net no guard compartilhado (specs paralelos renderizam a home com o pixel); advisory lock no Postgres serializando o login do usuário de teste (Payload perde sessão em login concorrente read-modify-write — classe documentada no webauthn); seedTestUser vira create-if-missing (sem janela de usuário ausente nem reset de senha); Lead do form protegido do catch de erro (tracking nunca falha uma captura commitada); descrição do campo compartilhada; unidade nova campaignNewsletterLead cobre exatamente um Lead no sucesso.

* feat(C141): perfis de permissão por assessor — Visão × Edição configuráveis, enforcement fail-closed (Closes #105)

* chore(C141): regenera changelog agregado após rebase com S10

* plans(C144): options write-scoped para formulários de escrita pós-C141

---------

Co-authored-by: Francisco Solla <admin@solla.dev>
2026-08-21 01:41:18 -03:00
Francisco Solla
3ce5a69555 feat(S11): feed do Instagram configurado não aparece na home — painel de status da sincronização no admin
O fail-closed silencioso da S3 deixava a assessoria cega: token errado não deixava
rastro além do picker vazio. Fim da caixa-preta:

- `instagramSyncStatus` (jsonb hidden) na global `social-feed-settings`, escrito pelo
  render, pelo afterChange (sync awaited quando a credencial IG muda) e pela rota
  `POST /api/social-feed/sync` (botão, auth admin + same-origin).
- `InstagramApiError` + `describeInstagramError`: o fetch parseia o body de erro da
  Graph API e o mapeia para copy pt-BR com a correção (OAuthException/expired →
  "token inválido/expirado ou emitido via Facebook Login — gere pelo Instagram Login";
  "Invalid user id" → confira o ID; 5xx → indisponível; TypeError → rede; AbortError →
  demorou demais). O ID só casa com "user" E "id" juntos (token rejections real falam
  "the user must be logged in" — não podem virar a branch de ID).
- `InstagramSyncStatusPanel` (campo ui irmão do picker): 5 estados fiéis ao rascunho;
  gate respeita o master `enabled`; `outcome` transiente limpo ao editar credencial;
  aria-live nos boxes interativos. Home inalterada (fail-closed intacto).
- Bug real: `afterChange` roda dentro da transação do save (row lock até os hooks
  retornarem); persistir o status via pool numa 2ª conexão deadlockava no lock da
  própria linha (~80-230s/save). Fix: persists do sync-hook na MESMA transação via
  `getPostgresTransactionDatabase` (C6); render/rota sem transação seguem no pool.
  Diagrama: UPDATE transactionid Lock vs idle in transaction; fix verificado 45ms vs 232s.
- Stub IG ganha estado `invalid-token`; runbook docs/ops/instagram-feed-token-runbook.md;
  migration add_instagram_sync_status (jsonb nullable).
- Débitos registrados: #124 (janela de lock) e #125 (polish P3).
- Gates: unit 2463 + int 791; lint/format/tsc/cycles; build; e2e admin 5/5 + frontend serial 19/19.
2026-08-20 00:54:58 -03:00
Francisco Solla
6cf5ea5885 docs(OPS71-INFRA): runner do GitHub instalado no homeserver — runbook + changelog (Issue #113) 2026-08-20 00:58:40 +00:00
Francisco Solla
02c1e4f36b feat(OPS71): Fase 2 — remover arquivos do fluxo Forgejo (workflows/scripts/specs) pós-validação do GitHub Actions
14 arquivos removidos: .forgejo/workflows/* (6), forgejo-pr-automerge.mjs,
forgejo-dispatch.mjs, ci-classify-production.mjs, lib/dockerignore.mjs,
lib/branch-protection.mjs + 3 specs órfãs. Consumidores ajustados:
test-affected-core (HIGH_RISK_EXACT), ciSkipInvariants (re-ancorado no
deploy.yml dispatch-only — deploy nunca automático), comentários com
referência morta (gate-ci, github-pr-automerge, agent-pr-ready-automerge).
Docs: AGENTS.md, runbook (rollback via git history), README (era GitHub).
Tracker intocado (forgejo-api/agent-*/issue-transition ficam).
2026-08-20 00:20:10 +00:00
Francisco Solla
0901d60d72 fix(OPS71): literal do required check = nome do check-run (checks) + docs (pin PR #742) 2026-08-19 23:07:34 +00:00
Francisco Solla
24a867dfc3 feat(OPS71): CI/PR/deploy no GitHub Actions — tracker de Issues permanece no Forgejo (Closes #97) 2026-08-19 19:17:19 -03:00
Francisco Solla
8d33e89102 style: prettier — runbook/impl plan/unit test (OPS66) 2026-08-19 10:07:14 -03:00
Francisco Solla
228f2217c7 ops(OPS66): deploy — migrate antes do build do runner (deadlock de migrations em caminho estático) 2026-08-19 10:06:00 -03:00
Francisco Solla
9504c7ccf6 ops(OPS65): CI do main em janela de 30 min (gate .dockerignore fail-open) + matar agent-pool
- ci.yml: on push removido → schedule */30 + workflow_dispatch (fundido com a
  estrutura de job único sequencial do OPS62 X1)
- job gate (host, main-only, sem pnpm): revision do container rodando no
  homeserver (label org.opencontainers.image.revision — o compose pode mentir
  após rollback falho) + diff + classificador .dockerignore
- fail-open: revision desconhecida → suite roda (verde); incapaz de classificar
  → run vermelho (nunca blackout silencioso); deploy duplo-gated
  (needs: [checks, gate] + if explícito)
- deploy-homeserver.sh: guard 'already deployed' idempotente (mesma revision)
- agent-pool.yml removido; pool dormente (144 pnpm install/dia no tick */10)
- specs: dockerignoreMatch, ciClassifyProduction (incl. git-diff com repo
  scratch e exit codes), pins ciSkipInvariants/deployScript; HIGH_RISK_EXACT
- docs: runbook (janela/gate/verificação ao vivo/falhas), AGENTS.md,
  AGENT-OPS.md (tabela X1 fundida), skills pool dormente, changelog OPS65
- impl plan aprovado; intenção marcada entregue
2026-08-18 21:08:12 -03: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
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