Deployment Procedure
Implements: Change Management Policy Owner: Security Lead Last Updated: 19 June 2026 Next Review: 21 November 2026
Scope
This procedure covers production deployment across both Maelstrom AI platforms — Provii (zero-knowledge age verification) and downpipes (no-custody backup & disaster recovery for the Cloudflare data layer).
Maelstrom builds and maintains the software for both platforms and operates the vendor-side surfaces — the downpipes control-plane (fail-open) and the signature-pinned update channel. The Provii Workers, the downpipes control-plane and the docs gateway are deployed by Maelstrom via the Cloudflare Workers Deployment steps below. The downpipes engine and console run in each customer’s own Cloudflare account, under the customer’s keys (no-custody) — Maelstrom cannot deploy into a customer tenant, so updates reach those customer-operated components through the downpipes Update Channel instead, and the decision to apply an update is a complementary user-entity control (CUEC) of the customer.
Cloudflare Workers Deployment
All Maelstrom-operated Cloudflare Workers (Provii’s verifier, issuer and SDKs, the downpipes vendor-side control-plane, and the docs gateway) deploy via GitHub Actions CI/CD. Manual deployment is only used for emergencies.
Automated (Standard)
- PR merged to
main - CI runs: lint, test, build
- CI deploys to sandbox (if applicable)
- Sandbox deployment verified
- CI deploys to production (for repos with production deployment in CI)
- Post-deploy health checks run automatically
Pre-Deploy Checklist
Before merging to main:
- PR approved by required reviewer(s)
- CI passes (all checks green)
- No unresolved review comments
- If API change: backward compatibility confirmed or migration communicated
- If secret change: secret updated in Cloudflare before deploy
Post-Deploy Verification
After deployment:
- Worker responds to health check endpoint (where available)
- No spike in error rates on Cloudflare dashboard
- Key flows work end-to-end (Provii: challenge → proof → verification; downpipes control-plane: licence-token mint and advisory-beacon ingest, which is fail-open and never gates backup or restore)
- Monitor for 30 minutes (standard) or 2 hours (significant change)
Manual Emergency Deployment
# Deploy directly from local machine
cd /path/to/repo
wrangler deploy --env production
Only used when CI is unavailable and a P1/P2 incident requires an immediate fix.
Mobile App Deployment (Provii mobile wallet client repository, MaelstromAI GitHub enterprise)
iOS
- Merge to
maintriggers CI build - CI builds.ipa and uploads to TestFlight
- Internal testing on TestFlight (minimum 24 hours for significant changes)
- Submit to App Store Connect for review
- Apple review (typically 24-48 hours)
- Release to App Store (phased rollout: 1%, 5%, 10%, 50%, 100%)
Android
- Merge to
maintriggers CI build - CI builds.aab and uploads to Google Play Console
- Internal testing track (minimum 24 hours for significant changes)
- Promote to production track
- Google Play review (typically 2-7 days)
- Staged rollout: 5%, 20%, 50%, 100%
Mobile Rollback
- iOS: Cannot roll back. Must submit a new version with the fix.
- Android: Can halt rollout in Google Play Console. Must submit a new version to fix.
downpipes Update Channel
The downpipes engine and console do not run in Maelstrom’s account — they run in each customer’s own Cloudflare account, under the customer’s keys, with no standing inbound path (“runs dark”). Maelstrom cannot wrangler deploy into a customer tenant, so changes reach these customer-operated components through the signature-pinned update channel rather than the Cloudflare Workers Deployment steps above.
Release Pipeline (vendor side)
- The code change is proposed, reviewed and merged through the Change Management Procedure (Standard / Significant / Emergency)
- CI builds the release artefact and publishes it as a static update to the signature-pinned R2 bucket at
updates.downpipes.io - The artefact is signed with the downpipes Update Signer, a key held offline by the operator and never deployed to any Worker
- The update channel PULLS — updates are never pushed into a tenant. The engine fetches the update on its own schedule and verifies the signature against a pinned public key before applying anything
- Application is canary-gated (safe-apply) with automatic rollback on a failed post-apply canary integrity flight; there is no phone-home
Update Channel Rollback
A bad update that fails its post-apply canary integrity flight is rolled back automatically to the prior version inside the customer’s tenant. Maelstrom’s remediation is to publish a corrected, re-signed artefact to updates.downpipes.io; there is no wrangler rollback path into a customer account.
Customer responsibility (CUEC)
Applying an update to a customer’s engine or console is the customer’s decision and is a complementary user-entity control. Maelstrom’s responsibility is limited to building, signing and publishing the update correctly. See the ISMS Scope Statement shared-responsibility model.
Maelstrom’s own Cloudflare estate is backed up by our own production instance of downpipes, which receives engine and console updates through this same signature-pinned, pull-only channel — so we operate the release process as a customer of our own product. See Cloudflare Backup Evidence.
Deployment Freeze Periods
No non-emergency deployments — including publishing updates to the downpipes update channel — during:
- Active P1/P2 incidents
- Public holidays (Australian national holidays)
- Pre-announced maintenance windows for Cloudflare
During freeze periods, only emergency changes per the Emergency Change Process are permitted.