Runbook: eseguire il workflow newsletter via API
Obiettivo
Eseguire in ordine il percorso editoriale della newsletter tramite Admin API:
health → identità → fonti accepted → generazione → quality
→ approvazione esplicita → pubblicazione → readback → rendering email
→ verifica di zero effetti Mailjet
La collection dedicata è
docs/postman/architecture-coffee-newsletter-workflow.postman_collection.json.
L'environment di esempio sanitizzato è
docs/postman/architecture-coffee-newsletter-workflow.postman_environment.example.json.
Inventario API esatto
| Ordine | Metodo e route | Scopo | Permesso applicativo |
|---|---|---|---|
| 1 | GET /health |
Health del Worker | pubblico |
| 2 | GET /db/health |
Health D1 con query minima | pubblico |
| 3 | GET /admin/auth/me |
Identità operatore sicura e permessi effettivi | admin:read |
| 4 | GET /admin/editorial/topics?status=accepted&limit=100 |
Topic accettati | admin:read |
| 5 | GET /admin/editorial/knowledge-assets?status=accepted&limit=100 |
Knowledge Asset accettati | admin:read |
| 6 | POST /admin/issues/generation-jobs |
Richiesta asincrona di generazione | issue:generate |
| 7 | GET /admin/issues/generation-jobs/{jobId} |
Poll bounded del job | admin:read |
| 8 | GET /admin/issues/{slug} |
Readback del draft canonico | admin:read |
| 9 | PUT /admin/issues/{slug}/draft |
Correzione opzionale con expectedRevision |
issue:draft |
| 10 | GET /admin/issues/{slug}/quality |
Quality gate deterministico | admin:read |
| 11 | POST /admin/issues/{slug}/approve |
Approvazione attribuita all'operatore | issue:review |
| 12 | POST /admin/issues/{slug}/publish |
Pubblicazione esplicita | issue:publish |
| 13 | GET /issues/{slug} |
Readback pubblico del JSON canonico | pubblico |
| 14 | GET /admin/issues/{slug}/email/html |
Rendering HTML canonico | campaign:draft |
| 15 | GET /admin/issues/{slug}/email/text |
Rendering plain text canonico | campaign:draft |
| 16 | GET /admin/issues/{slug}/email-campaign |
Stato Campaign Draft e attempt, sola lettura | campaign:draft |
La collection non include send-test, prepare, confirm, content_upload,
schedule, deployment, archive, search, glossario o feedback analytics.
Configurazione rapida
- Importare collection ed environment di esempio.
- Duplicare l'environment in Postman; non modificare il file versionato.
- Selezionare
baseUrl: http://127.0.0.1:8787per il Worker locale;- il valore di
developmentBaseUrlper development remoto; productionBaseUrlsoltanto in una futura Issue operativa autorizzata.- Scegliere
authMode: local-serviceper sviluppo locale;access-serviceper il workflow remoto completo.
Per access-service, conservare cfAccessClientId e
cfAccessClientSecret soltanto nell'environment locale. Non esportare
environment popolati e non estrarre cookie browser.
Esecuzione locale diretta
Preparare D1 locale e avviare il Worker:
npm run db:prepare:local
npm run dev:api
La generazione richiede OPENAI_API_KEY nel secret store locale del Worker.
Allineare localAuthSubject al subject service locale. Lasciare:
authMode = local-service
allowMutations = true
allowProductionMutations = false
runDraftCorrection = false
Avviare la collection con Collection Runner in ordine. Un delay di un secondo
tra le richieste rende leggibile il polling; pollLimit limita comunque il
numero di tentativi e produce un errore esplicito. La collection cattura
automaticamente topicId, generationJobId, issueId, slug, contenuto,
revisione e timestamp: non copiare ID a mano.
Impostare runDraftCorrection = true soltanto dopo avere modificato
canonicalContent nell'environment locale. La write usa la revisione letta dal
server e fallisce con conflitto se il draft è cambiato.
Verifiche decisive
La run è valida soltanto se:
- la richiesta senza autenticazione viene rifiutata;
/admin/auth/merestituisce un'identitàservice, un riferimento hash senza subject raw e i permessi richiesti;- Topic e Knowledge Asset selezionati sono
accepted; - il job termina
completedentropollLimit; - il secondo read del job terminale è identico;
- schema e quality risultano validi;
- la pubblicazione prima dell'approvazione fallisce;
- approvazione e pubblicazione restano due richieste distinte;
- il readback pubblico coincide con il contenuto pubblicato;
- HTML e plain text sono disponibili;
- i conteggi di Campaign Draft e attempt dopo la pubblicazione coincidono con il baseline;
- non esiste alcun nuovo stato
scheduledo di delivery.
Controllo contenuto email
Sulle richieste 18 e 19 della collection verificare direttamente:
- nell'HTML, il
<title>coincide conArchitecture Coffee #<numero>: <titolo>; - il preheader nascosto deriva dal sottotitolo e dal tempo di lettura;
- paragrafi, liste, blocchi tecnici e riferimenti HTTPS restano leggibili a larghezza mobile e desktop;
- i quattro link di feedback sono assoluti, usano
https://api.architecturecoffee.it/f/{token}(o l'origine API dell'ambiente), sono identici per ogni destinatario, non contengono email o id sequenziali e aprono soltanto la pagina di ringraziamento del Worker; - HTML e plain text contengono lo stesso significato, gli stessi riferimenti,
la stessa domanda di feedback e il placeholder Mailjet
[[UNSUB_LINK_EN]]; - il testo non contiene tag HTML, CSS o entità HTML residue.
Questi endpoint sono read-only: non preparano né caricano un Campaign Draft. Il controllo visuale può quindi essere ripetuto senza una nuova conferma.
Confini e stop
allowProductionMutations resta false. Non abilitarlo senza una Issue
Production che descriva esattamente la mutazione e una PR mergiata da Fra.
Questa collection non
chiama Mailjet, non prepara Campaign Draft, non carica contenuto provider, non
schedula, non invia e non esegue deployment.
Fermarsi se identità o permessi non corrispondono, il job fallisce, il polling scade, quality non passa, il readback diverge o cambia il conteggio Campaign Draft/attempt. Conservare soltanto status HTTP, ID applicativi non sensibili, stati, timestamp e diagnostica sanitizzata; mai cookie, credenziali, indirizzi destinatario o payload provider.