feat(OPS52-media): recupera os objetos de media de produção (pnpm media:recover) #38

Merged
fsolla merged 1 commit from OPS52-media-ops52-media-recuperar-os-arquivos-de-media-de-pr into main 2026-08-18 11:39:29 +00:00
Owner

OPS52-media — Recuperar os arquivos de media de produção

Closes #10

O que entrega

Ferramenta commitada para restaurar os objetos de media de produção (as ~40 capas dos posts) do WordPress de origem para o bucket S3 (Garage) — sem tocar no banco (rows e URLs relativas /api/media/file/<filename> intocadas; o staticHandler do Payload passa a servir).

  • pnpm media:recover (scripts/recover-media.mjs) — 3 modos:
    • reconcile (padrão): plano → baixa a capa do WP → PutObject com key = filename da row (idempotente por overwrite); DB apenas lido
    • --dry-run: plano + headObject por key (pre-flight; exit 1 se qualquer checagem falhar)
    • --verify: HEAD da URL pública por filename — o aceite da Issue, sem credencial de bucket
  • scripts/lib/wpArticles.mjs — fetch ao vivo do WordPress extraído do seed (sem twin; o seed importa de lá com comportamento idêntico) + helpers puros unit-testados (resolveCoverSource, resolveMediaCoverSources, resolveCoverDownloadUrl, slugFromFilename); processContent agora usa a resolução compartilhada
  • Fail-closed: S3_* completas obrigatórias (reconcile/dry-run), ALLOW_REMOTE_DB=true explícito + echo do alvo (DB/bucket/endpoint/origin), timeouts curtos (SDK 5s/15s, fetches 30s/60s) — endpoint inalcançável falha em segundos; covers constrangidas a http(s) no host do WP com só image/* armazenado
  • Runbook de execução no homeserver (docs/plans/ops52-media-recuperar-arquivos-impl.md), nota no AGENTS.md, changelog OPS44

Evidências coletadas no planejamento (probes read-only)

  • Só 7/43 posts do WP têm featuredmedia — a maioria das capas vem do fallback de 1ª imagem inline; todas as 42 capas resolvidas estão no host jorgesolla.com.br
  • A rota pública de media de prod hoje pendura (>25s, não 404) — o runbook inclui pre-flight container→Garage para separar "arquivo faltando" desta Issue de "infra de rede" (sucessor OPS se confirmado)

Dívida registrada

  • #37 (P3, depends #10): guard de intenção explícita para escrita em bucket de produção

Verificação

  • pnpm gate:fast, pnpm format:check, pnpm check:cycles, pnpm test (2312 unit + 791 int), pnpm build, pnpm push (gate:ci completo incl. e2e) — tudo verde (knip: erro conhecido P3 de payload.config, exit 0)
  • Execução em prod: pós-merge, no homeserver, seguindo o runbook do impl plan
## OPS52-media — Recuperar os arquivos de media de produção Closes #10 ### O que entrega Ferramenta commitada para restaurar os objetos de media de produção (as ~40 capas dos posts) do WordPress de origem para o bucket S3 (Garage) — **sem tocar no banco** (rows e URLs relativas `/api/media/file/<filename>` intocadas; o staticHandler do Payload passa a servir). - **`pnpm media:recover`** (`scripts/recover-media.mjs`) — 3 modos: - `reconcile` (padrão): plano → baixa a capa do WP → `PutObject` com key = `filename` da row (idempotente por overwrite); DB apenas lido - `--dry-run`: plano + `headObject` por key (pre-flight; exit 1 se qualquer checagem falhar) - `--verify`: HEAD da URL pública por filename — o aceite da Issue, sem credencial de bucket - **`scripts/lib/wpArticles.mjs`** — fetch ao vivo do WordPress extraído do seed (sem twin; o seed importa de lá com comportamento idêntico) + helpers puros unit-testados (`resolveCoverSource`, `resolveMediaCoverSources`, `resolveCoverDownloadUrl`, `slugFromFilename`); `processContent` agora usa a resolução compartilhada - **Fail-closed**: S3_* completas obrigatórias (reconcile/dry-run), `ALLOW_REMOTE_DB=true` explícito + echo do alvo (DB/bucket/endpoint/origin), timeouts curtos (SDK 5s/15s, fetches 30s/60s) — endpoint inalcançável falha em segundos; covers constrangidas a http(s) no host do WP com só `image/*` armazenado - **Runbook de execução no homeserver** (`docs/plans/ops52-media-recuperar-arquivos-impl.md`), nota no AGENTS.md, changelog OPS44 ### Evidências coletadas no planejamento (probes read-only) - Só 7/43 posts do WP têm `featuredmedia` — a maioria das capas vem do fallback de 1ª imagem inline; todas as 42 capas resolvidas estão no host `jorgesolla.com.br` - A rota pública de media de prod hoje **pendura** (>25s, não 404) — o runbook inclui pre-flight container→Garage para separar "arquivo faltando" desta Issue de "infra de rede" (sucessor OPS se confirmado) ### Dívida registrada - #37 (P3, depends #10): guard de intenção explícita para escrita em bucket de produção ### Verificação - `pnpm gate:fast`, `pnpm format:check`, `pnpm check:cycles`, `pnpm test` (2312 unit + 791 int), `pnpm build`, `pnpm push` (gate:ci completo incl. e2e) — tudo verde (knip: erro conhecido P3 de payload.config, exit 0) - Execução em prod: pós-merge, no homeserver, seguindo o runbook do impl plan
fsolla added 1 commit 2026-08-18 11:28:25 +00:00
feat(OPS52-media): recupera os objetos de media de produção do WordPress para o bucket (pnpm media:recover)
All checks were successful
Agent PR Ready + auto-merge / ready-automerge (pull_request) Has been skipped
CI (PR) / docs-guards (pull_request) Successful in 7s
CI (PR) / plans-only-closes (pull_request) Successful in 8s
CI (PR) / scope (pull_request) Successful in 51s
CI (PR) / lint (pull_request) Successful in 1m4s
CI (PR) / format (pull_request) Successful in 1m14s
CI (PR) / typecheck (pull_request) Successful in 39s
CI (PR) / knip (pull_request) Successful in 40s
CI (PR) / cycles (pull_request) Successful in 39s
CI (PR) / unit (pull_request) Successful in 1m0s
CI (PR) / int (pull_request) Successful in 2m39s
CI (PR) / build (pull_request) Successful in 4m2s
CI (PR) / e2e (2) (pull_request) Successful in 6m2s
CI / e2e (1) (push) Successful in 6m39s
CI (PR) / e2e (1) (pull_request) Successful in 7m26s
CI (PR) / checks (pull_request) Successful in 7s
Promote plan-issue Related on main merge / plan-issue-ready (pull_request) Has been skipped
Main merge flips claimed issues to done + in-prod / issue-done (pull_request) Successful in 19s
Agent pool supervisor / tick (pull_request) Successful in 42s
CI / int (push) Successful in 2m52s
CI / static (push) Successful in 2m57s
CI / build (push) Successful in 3m52s
CI / e2e (2) (push) Successful in 5m34s
CI / checks (push) Successful in 2s
CI / deploy homeserver (teqo-1313) (push) Successful in 8m27s
45e29a7785
- scripts/recover-media.mjs: CLI de reconciliação (reconcile/--dry-run/--verify)
  — lê rows de media + posts.coverImage, resolve a capa com a mesma lógica do
  seed (featured media, senão 1ª imagem inline), PutObject com key = filename;
  DB nunca escrito; fail-closed (S3_* completas, ALLOW_REMOTE_DB, echo do alvo,
  timeouts curtos, covers só do origin WP e image/*)
- scripts/lib/wpArticles.mjs: fetch ao vivo do WordPress extraído do seed
  (sem twin), helpers puros de resolução + row→cover mapping (unit-testados)
- seed-posts.mjs: importa o fetch da lib (comportamento idêntico) e usa
  resolveCoverSource em processContent
- runbook de execução no homeserver (impl plan), nota no AGENTS.md, changelog
Closes #10
fsolla merged commit 45e29a7785 into main 2026-08-18 11:39:29 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: fsolla/teqo#38
No description provided.