Principles
- A single production environment, never an unobserved bundle. Every change passes through a replica (staging) or a zero-traffic preview of production itself, before a user ever sees it.
- The gate is human and tracked. No production release
without the maintainer's explicit approval, recorded on GitHub
(a
productionenvironment with a required reviewer). - Rollback in seconds, without a rebuild. Cloudflare Workers
keeps previous versions:
wrangler rollbackreverts immediately. - Staging never holds real data. Staging databases are born from the schemas versioned in the repo plus synthetic data: copying production data would be a GDPR-relevant processing with no purpose.
- Production secrets never leave their perimeter. Staging has its own secrets, generated for the purpose. In particular the secret that signs attestations — never rotated for this project — exists only in production and in the escrow vault.
- Config cannot drift. Production and staging live in the
same configuration file (
wrangler.toml, an[env.staging]block): every configuration change touches both in the same commit, drift is structurally impossible.
The same process — replicated staging, CI, human gate, rollback in seconds — is also adopted for the organization's other services.
The parts: production and replica
Detailed map
| Component | Production | Staging |
|---|---|---|
| imgauth (engine) | Worker imgauth · imgauth.spaziogenesi.org | imgauth-staging · workers.dev only |
| Database / archive | imgauth-health · imgauth-pdf-archive (EU) | -staging twins, no real data |
| PDF signing (authart) | Azure, TSA timestamp | not replicated in v1: unsigned PDF |
| Anti-bot / notifications | real Turnstile · Telegram | test keys · silent |
| authweb (interface) | GitHub Pages · attestazione.spaziogenesi.org | copy generated from the same source, pointed at staging |
Release flow
Runbook
Ordinary release
- PR with the change → checks must be green.
- Merge to
main→ staging updates itself; check the smoke test. - Manual test on staging if the change is UI/flow-related.
- Approve the
productionjob on GitHub → 0% preview → promotion. - Production smoke:
/ping(expected version),/api/statusall green. - Tag
vX.Y.Zif there's a version bump; documentation per convention.
Urgent hotfix
Identical to an ordinary release — the chain IS the fast path (automatic staging + one approval click). Skipping staging is not supported: if production is already broken, rollback is faster than any fix written in a hurry.
Rollback
npx wrangler rollback # choose the previous version
Then: production smoke, a note on what went wrong, a calm fix through the normal chain.
Adding staging to a new module
- Create the module's
-stagingD1/R2 (EU where relevant). - An
[env.staging]block inwrangler.toml: redeclare all bindings (wrangler envs don't inherit from the top level). - Schemas applied to the staging D1, new secrets with
--env staging. - Smoke test, then CI following the reference model (imgauth's workflow).
Declared limits
Honesty about the process: what the replica doesn't cover, by documented choice.
- PDF signing has no replica in v1: staging issues unsigned PDFs, identical in content. Replicating the signer is deferred to that component's next substantial change.
- The self-service OAuth flow isn't active in staging: the providers would require dedicated redirect URIs; the buttons stay absent by fail-closed design.
- v1 promotion is 0% → 100% after approval; gradual percentage rollout is a later refinement.
Implementation status
| Phase | Content | Status |
|---|---|---|
| 0 | Inventory and prerequisites | ✅ 2026-07-11 |
| 1 | Engine code ready for multi-environment | ✅ 2026-07-11 |
| 2 | Attestation engine staging | ✅ 2026-07-11 |
| 3 | CI (PR checks, automatic staging + smoke) | ✅ 2026-07-11 |
| 4 | Production gate (approval, 0% preview, rollback tested) | ✅ 2026-07-11 |
| 7 | Staging web interface | ✅ 2026-07-11 |
| 8 | Documentation publication + registration in the GTF | ✅ 2026-07-11 |
The table is updated when each phase closes (date + outcome). The
process is registered in the GTF registry as a decision, process and
control (ADR-P24 CTL-cicd-pipeline,
status: active since 2026-07-11) with verifiable evidence:
CI runs are public on the GitHub repos — anyone can check that the
declared process is the one actually practiced. Phases 5 and 6 of the
P24 plan concern a different project and are not part of this path.