docs: record the Cloudflare user-agent trap (AGENTS.md #18)

Every Gitea API call from Python 403s with "error code: 1010" unless a
User-Agent is set, including endpoints that need no auth — and it looks like a
token/scope problem, which is where this went wrong once. Registered next to
the other environment traps, with the two-command check that tells them apart.
This commit is contained in:
2026-07-25 15:28:29 +02:00
parent 91ea90348c
commit 30fd3120a6
+2
View File
@@ -285,3 +285,5 @@ Configurazione in `PSScriptAnalyzerSettings.psd1`. Regole principali:
16. **Delta di snapshot orfani dopo `--force`** — `deploy-*` cancella `<vm>.vmsd` (il database snapshot) per evitare l'errore di resize sulla catena, ma **non** cancella i file delta `<disk>-00000N.vmdk`. Restano su disco con un `parentCID` che non corrisponde più al base ricreato: innocui (fuori dal percorso di boot, la VMX punta al base con `parentCID=ffffffff`) ma confondono la diagnosi e vanno rimossi a mano. Verifica della catena: `head -c 2000 <disk>.vmdk | strings | grep -E '^CID|parentCID'`.
17. **`vmrun list` è per-utente e mente se lo lanci con l'utente sbagliato** — le VM della CI le avvia `ci-runner`; `vmrun -T ws list` eseguito come `simone` (o come root) risponde `Total running VMs: 0` **anche mentre un clone sta girando**, perché vede solo l'istanza VMware dell'utente corrente. Occorso il 2026-07-22 durante la validazione della cache cargo: `vmrun list` diceva 0 e `ps` mostrava un `vmware-vmx` vivo da 19 minuti. Conseguenza pratica: il check "0 VM accese" prima di un `deploy --force` (vedi #14) **non è affidabile** se non lo si esegue come `ci-runner`. Usare `sudo -u ci-runner vmrun -T ws list`, oppure — meglio, perché indipendente dall'utente — `ps -eo pid,lstart,etime,args | grep '[v]mware-vmx'`, che è anche la diagnosi già raccomandata in #14 e #15.
18. **Gitea è dietro Cloudflare: `Python-urllib` riceve 403 prima di arrivare a Gitea** — qualunque chiamata a `https://gitea.emulab.it/api/v1/...` fatta con `urllib.request` senza `User-Agent` esplicito torna `403` con body `error code: 1010` (Cloudflare "browser banned"), **su ogni endpoint**, incluso `/api/v1/version` che non richiede autenticazione. Sembra identico a un problema di token/scope e manda la diagnosi fuori strada. Verifica in due mosse: `curl -s https://gitea.emulab.it/api/v1/version` risponde 200 (curl manda il suo UA) mentre la stessa chiamata in Python risponde 403; gli header di risposta mostrano `server: cloudflare` + `cf-ray`. Fix: header `User-Agent` esplicito — qualunque stringa normale passa (vedi `operations/executions.py::_USER_AGENT`). Corollario generale: quando un endpoint HTTP risponde 4xx, **leggere il body** prima di ipotizzare la causa — Gitea scrive il permesso mancante (`required=[read:user], token scope=read:admin,read:repository`), Cloudflare scrive il suo codice.