Commits
The migrator learns to talk to Payload
API key authentication, import CLI with idempotency and retries, and
The missing piece: how the migrator will talk to Payload
Yesterday's sketch (the first blueprint of the migrator, The 404 with style, the 500 caught and the first sketch of the migrator) could read WordPress, but couldn't get into Payload. Today we put in the three missing pieces.
First, authentication (proving to the system who you are). The Users collection already had an apiKey field, but Payload didn't show it in the UI (the graphical interface). With useAPIKey: *** the "API Keys" tab appears on the admin profile. And to avoid having to click anything, a one-shot script (a program that runs once and deletes itself, generate-api-key.ts) generates the key via Local API and self-deletes.
Second, the CLI (the command line). import.py with --wave=pilot|1|2|3: pilot = a single county, then waves by post_type. What interests me about the pipeline (the data-passing chain):
- Idempotency: before creating, it searches by slug (
find_by_wpslug). If the content is already there, it updates instead of duplicating. If the import is cut in half, I rerun it and nothing is duplicated. - Retries: 3 attempts with backoff 2s/4s/8s per request.
- The WordPress table prefix is auto-detected (
8WfsTsX_in production is notwp_). - created/updated/skipped/failed counters and log to disk (the execution journal).
Third, the tests. test_import_smoke.py: 23 checks. All green.
Credentials don't leave the server
This phase moves credentials: WordPress MySQL access, Payload keys, FTP (the channel for uploading files to a server). BEFORE generating new code that uses them, we closed the door: .gitignore now explicitly excludes /test_ftp*.sh (had credentials inside), /BBDD_WP/, /WP-Media-Upload/, and /informes/, and there's a reserved place (scripts/migrate-wp/_local/) for helper scripts that only live on the server. No secrets in the repo, even by accident.
The import plan
The waves aren't a whim: first a pilot of one county, thorough review, and only then waves 1-3 by content type. If the pilot uncovers a mapping problem (how each field translates from one system to the other), it's fixed with 300 entries in the database, not 6,000.
Tomorrow it's the pilot's turn to run.