Third-Party & Supply Chain Evidence

Evidence of vendor assessments, sub-processor management, dependency security scanning, and supply chain controls

Public

Status: pre-launch. This evidence reflects implemented code and deployed infrastructure. Provii is not yet serving end-user production traffic, so production operational metrics and audit history are not yet available. downpipes is in production for Maelstrom’s own Cloudflare estate (we run our own product), but is not yet serving external customer production traffic.

Two platforms, one ISMS. Maelstrom AI builds two products under one ISMS — Provii (privacy-preserving age verification via zero knowledge proofs) and downpipes (no-custody backup & disaster recovery for the Cloudflare data layer). This document is cross-cutting: it evidences the third-party dependencies, vendor relationships and supply-chain controls of Maelstrom AI as an organisation, across both platforms. Because downpipes is no-custody — the engine and console run in the customer’s own Cloudflare account, under the customer’s own keys, and Maelstrom holds no customer keys, data or Cloudflare tokens — downpipes adds no sub-processor for customer data (see Sub-Processors & Data Processing). The downpipes supply chain adds one Maelstrom-operated surface to this register: the static, signature-pinned update channel (updates.downpipes.io), covered under Supply Chain Security.

Third-Party Dependencies & Vendor Management Evidence

Document Version: 1.1 Date: 2026-06-19 Author: Maelstrom AI Control Scope: UC-070, UC-144 through UC-148 (Vendor/Supply Chain Management)


Executive Summary

This document provides evidence of Maelstrom AI’s third-party dependencies, vendor relationships, and supply chain security controls across both platforms — Provii and downpipes. The evidence demonstrates:

  • Complete vendor inventory (critical cloud providers, development tools, package registries)
  • dependency tracking across Rust, JavaScript/TypeScript, Android, and iOS ecosystems
  • SLSA Level 3 supply chain security implementation, complemented by the downpipes signature-pinned update channel (pull-only, verified against a pinned public key, signed by an offline-held update key)
  • Automated security scanning via Dependabot, cargo audit, and npm audit
  • Licence compliance across open source and source-available dependencies (Provii: AGPL-3.0-only, Apache-2.0, MIT, some proprietary; crates dual MIT OR Apache-2.0. downpipes: engine/console/control-plane source-available under Elastic License v2, with an MIT offline reader)
  • Signed commits and verified builds designed to ensure artefact integrity
  • No additional sub-processor for downpipes customer data: under the no-custody model the engine and console run in the customer’s own Cloudflare account under the customer’s keys, so Maelstrom processes no downpipes customer data and engages no sub-processor for it

Table of Contents

  1. Critical Third-Party Vendors
  2. Rust Dependencies (Cargo)
  3. JavaScript/TypeScript Dependencies (npm)
  4. Mobile Dependencies
  5. Supply Chain Security
  6. Dependency Security Scanning
  7. Licence Compliance
  8. Sub-Processors & Data Processing
  9. Control Mapping

Critical Third-Party Vendors

1. Cloudflare (Critical - Complete Service Dependency)

Services Used:

  • Cloudflare Workers (serverless compute)
  • Cloudflare KV (key-value storage)
  • Cloudflare Durable Objects (stateful compute)
  • Cloudflare Workers Assets (static site serving)
  • Cloudflare Workers Logs (structured console.log JSON shipped to Grafana Loki)
  • Cloudflare DDoS Protection
  • Cloudflare Secrets Store
  • Cloudflare R2 (object storage — Provii backups; downpipes backup destinations; and the static, signature-pinned downpipes update channel updates.downpipes.io)

Criticality: HIGH - Complete infrastructure dependency

downpipes application: Cloudflare is also the substrate for downpipes, but under the no-custody model the responsibility split differs. The downpipes engine and console run in the customer’s own Cloudflare account, under the customer’s own keys — that Cloudflare tenancy is the customer’s own infrastructure, not a Maelstrom vendor relationship or sub-processor. Maelstrom operates only two content-free downpipes surfaces on its own Cloudflare account: the vendor-side control-plane (Cloudflare Workers; mints licence tokens and receives a content-free advisory beacon; holds no customer keys, data or Cloudflare tokens; fail-open — never gates backup or restore) and the static, signature-pinned update channel (updates.downpipes.io, Cloudflare R2; pull-only, no phone-home). The downpipes Licence Signer is held in Cloudflare Secrets Store on the fail-open control-plane (see Cryptographic Key Management).

Security Assessment:

  • ✅ SOC 2 Type II certified
  • ✅ ISO 27001 certified
  • ✅ Enterprise SLA (99.99% uptime)
  • ✅ Regular security audits published
  • ✅ GDPR-compliant data processing

Contract Terms:

  • Data Processing Agreement in place
  • Security and privacy provisions
  • Incident notification requirements
  • Right to audit

Monitoring:

  • status.cloudflare.com for outages
  • Security advisories reviewed
  • Annual contract review

Evidence:

  • provii-verifier/wrangler.toml - Production configuration
  • provii-issuer/worker/wrangler.toml - Issuer service configuration
  • /trust/security/supplier-management.md - Vendor management documentation

Data Flows:

  • Verifier API: Challenge storage (5-minute TTL, enforced by KV expiration_ttl at provii-verifier/src/routes/challenge.rs:854), audit logs (90-day retention, enforced by KV expiration_ttl(7_776_000) at provii-verifier/src/routes/csp_report.rs:293, which comments “TTL: 90 days matching audit log retention”; critical security event logs are retained for up to 365 days)
  • Issuer API: Encrypted credential issuance, officer authentication
  • All services: IP address logging (90-day retention for abuse prevention, hashed via HMAC-SHA-256 keyed by PII_HASH_KEY before persistence; critical security event logs are retained for up to 365 days)
  • downpipes control-plane: licence-token issuance and a content-free advisory beacon only — no customer keys, data or Cloudflare tokens
  • downpipes update channel (updates.downpipes.io, R2): static, signature-pinned engine update artefacts, served read-only and pulled by the engine; carries no customer data

2. GitHub (Critical - Development Dependency)

Services Used:

  • GitHub source control (Git hosting)
  • GitHub Actions (CI/CD pipelines)
  • GitHub Packages (artefact hosting)
  • GitHub Advanced Security (Dependabot, CodeQL, secret scanning)
  • GitHub Container Registry

Criticality: HIGH - Development and deployment dependency (both platforms)

GitHub hosts the source repositories and CI/CD for both platforms — Provii (provii-verifier, provii-issuer, provii-crypto, the mobile wallet, SDKs, agegate-rust, etc.) and downpipes (downpipes-engine, downpipes-console, downpipes-control-plane and the MIT offline reader). It is a development tool, not a production sub-processor of end-user personal data, and is tracked under UC-070 and UC-144 rather than UC-147.

Security Assessment:

  • ✅ SOC 2 Type II certified
  • ✅ GitHub Advanced Security features enabled
  • ✅ Bug bounty program
  • ✅ Regular security updates
  • ✅ SLSA Level 3 build infrastructure

Contract Terms:

  • GitHub Enterprise Cloud agreement
  • Data Protection Addendum
  • Security features included

Monitoring:

  • GitHub status page
  • Security advisories
  • Dependabot alerts

Evidence:

  • provii-verifier/.github/workflows/ci.yml - CI pipeline
  • provii-agegate/.github/workflows/secure-build.yml - SLSA Level 3 build
  • provii-mobile-sdk/.github/workflows/secure-build.yml - Secure build pipeline
  • provii-agegate/.github/dependabot.yml - Dependency scanning
  • provii-issuer/.github/dependabot.yml - Dependabot config

3. npm Registry (Medium - JavaScript Build Tooling)

Services Used:

  • npm package registry (build-time development dependencies for TypeScript repos)
  • npm provenance (SLSA attestations for internal build artefacts)

Criticality: MEDIUM - Build-time dependency resolution for TypeScript services and tooling

provii-agegate ships via CDN only (cdn.provii.app). There is no npm package for provii-agegate. npm is used as a build-time dependency manager for the TypeScript projects (admin-portal, provii-management, provii-docs, provii-agegate build toolchain) but not as a distribution channel for the browser SDK.

Security Assessment:

  • SRI hashes on CDN-served provii-agegate bundles
  • npm audit integration for build-time dependencies
  • Hermetic builds with package-lock.json
  • 2FA required for npm publishing (internal tooling only)

Supply Chain Controls:

  • Hermetic builds with package-lock.json
  • SLSA Level 3 provenance generation
  • Sigstore keyless signing for CDN bundles
  • SRI hash generation for browser bundles

Evidence:

  • provii-agegate/.github/workflows/secure-build.yml - CDN publish and SRI hash generation

4. Crates.io (Medium - Rust Package Registry)

Services Used:

  • Rust crate registry (dependency resolution)

Criticality: MEDIUM - Build-time dependency only

Security Assessment:

  • ✅ cargo audit integration
  • ✅ Cargo.lock hermetic builds
  • ✅ Crate verification

Supply Chain Controls:

  • All Rust projects use Cargo.lock for deterministic builds
  • cargo audit runs in CI/CD (deny warnings)
  • cargo deny for licence compliance

Evidence:

  • provii-verifier/.github/workflows/ci.yml - Lines 74-85 (cargo audit)
  • provii-issuer/.github/workflows/security-audit.yml - security scanning

5. CocoaPods / Swift Package Manager (Low - iOS Dependency Management)

Services Used:

  • CocoaPods registry (YubiKit dependency)

Dependencies:

  • YubiKit (YubiKey hardware authentication)

Criticality: LOW - Single optional hardware authentication dependency

Evidence:

  • provii/ios/Podfile - iOS dependency specification

6. Maven Central / Google Maven (Low - Android Dependency Management)

Services Used:

  • Maven Central (Android libraries)
  • Google Maven (AndroidX, Compose)

Criticality: LOW - Standard Android development dependencies

Evidence:

  • provii/android/app/build.gradle.kts - Android dependency specification

Rust Dependencies (Cargo)

Core Cryptographic Dependencies

Critical Zero knowledge Proof Libraries:

File: provii-crypto/Cargo.toml

# Core cryptography dependencies
bellman = { version = "0.14", default-features = false, features = ["groth16"] }
bls12_381 = "0.8"
jubjub = "0.10"
redjubjub = "0.8"
blake2 = "0.10"
blake2s_simd = "1.0"
sha2 = "0.10"
secp256k1 = "0.31.1"
blstrs = "0.7"

# Zero-knowledge proof utilities
ff = "0.13"
group = "0.13"
rand_core = "0.6"
rand = "0.8"
subtle = "2.6"
zcash_proofs = { version = "0.24", default-features = false }
zcash_primitives = { version = "0.24", default-features = false }
sapling-crypto = { version = "0.5", default-features = false, features = ["circuit"] }

Security Properties:

  • All cryptographic libraries are widely-audited open source projects
  • bellman: Groth16 zk-SNARK implementation (used by Zcash, extensively audited)
  • bls12_381: BLS12-381 elliptic curve (IETF standard)
  • jubjub: Twisted Edwards curve (Zcash Sapling protocol)
  • redjubjub: Schnorr signatures on Jubjub curve

Licence: All MIT OR Apache-2.0 (permissive, no copyleft)

Verifier API Dependencies

File: provii-verifier/Cargo.toml

Core Runtime:

worker = "=0.6.1"  # Cloudflare Workers runtime
worker-kv = "=0.9.0"  # KV storage client
getrandom = { version = "0.2", features = ["js"] }  # WASM-compatible RNG

Cryptography:

sha2 = "0.10"
blake2 = "0.10"
blake3 = "1.5"
base64 = "0.22"
hmac = "0.12"
zeroize = { version = "1.7", features = ["derive"] }
argon2 = { version = "0.5", features = ["std"] }

Serialization:

serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
prost = "0.12"  # Protocol Buffers

Lints Configuration (Lines 111-133):

[lints.rust]
unsafe_code = "forbid"  # No unsafe Rust allowed
missing_docs = "warn"

[lints.clippy]
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"

This demonstrates secure coding practices enforcement at the compiler level.

Issuer API Dependencies

File: provii-issuer/worker/Cargo.toml

WebAuthn Support:

p256 = { version = "0.13", features = ["ecdsa"] }  # P-256 ECDSA
ecdsa = { version = "0.16", features = ["verifying", "der"] }

Key Derivation:

hkdf = "0.12"  # HMAC-based Key Derivation Function
aes-gcm = "0.10"  # Envelope encryption for signing keys
argon2 = { version = "0.5", features = ["std"] }  # API key hashing

Compression:

flate2 = { version = "1", default-features = false, features = ["rust_backend"] }

Wallet SDK Dependencies

File: provii-mobile-sdk/Cargo.toml

Cross-Platform FFI:

uniffi = { version = "0.29", features = ["cli"] }  # Foreign Function Interface
uniffi_build = { version = "0.29", features = ["build"] }

Networking (HTTP/3):

quinn = "=0.11.7"  # QUIC implementation
h3 = "=0.0.8"  # HTTP/3
h3-quinn = "=0.0.10"  # HTTP/3 over QUIC
rustls = { version = "0.23", default-features = false, features = ["ring"] }
webpki-roots = "0.26"  # Root CA certificates

Parallel Proving:

rayon = "1.11"  # Thread pool for parallel proof generation

JavaScript/TypeScript Dependencies (npm)

provii-agegate Browser SDK

File: provii-agegate/package.json

Production Dependencies:

{
  "dependencies": {
    "qrcode": "^1.5.4",  // QR code generation
    "zod": "^3.25.64"    // Runtime type validation
  }
}

Development Dependencies (Lines 45-78):

Security Tools:

"eslint-plugin-security": "^3.0.1",      // Security linting
"eslint-plugin-sonarjs": "^3.0.2",       // Code quality
"@stryker-mutator/core": "^9.0.1",       // Mutation testing
"@playwright/test": "^1.53.0"            // E2E testing

Build Tools:

"esbuild": "^0.25.5",                    // Fast bundler
"typescript": "^5.8.3",                  // Type safety
"terser": "^5.42.0"                      // Minification

Testing:

"jest": "^29.7.0",                       // Unit testing
"fast-check": "^4.3.0"                   // Property-based testing

OpenAPI:

"openapi-typescript": "^7.8.0",          // Type generation from OpenAPI spec
"openapi-typescript-fetch": "^2.2.0"     // Type-safe API client

Total Dependencies: 79 (2 production, 77 development)


Mobile Dependencies

Android Dependencies

File: provii/android/app/build.gradle.kts

Core Android Libraries (Lines 135-151):

// Core Android
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.7.0")
implementation("androidx.activity:activity-compose:1.8.2")

// Compose (UI framework)
implementation(platform("androidx.compose:compose-bom:2024.02.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("com.google.android.material:material:1.11.0")

Security (Lines 161-163):

implementation("androidx.security:security-crypto:1.1.0-alpha06")  // EncryptedSharedPreferences
implementation("androidx.biometric:biometric:1.1.0")  // Biometric authentication

Camera & QR (Lines 165-172):

implementation("androidx.camera:camera-camera2:1.3.1")
implementation("androidx.camera:camera-lifecycle:1.3.1")
implementation("androidx.camera:camera-view:1.3.1")
implementation("com.google.mlkit:barcode-scanning:17.2.0")  // Google ML Kit
implementation("com.google.zxing:core:3.5.3")  // QR code generation

YubiKey Support (Lines 174-177):

implementation("com.yubico.yubikit:android:2.8.0")  // Core Android module
implementation("com.yubico.yubikit:yubiotp:2.8.0")  // OTP module

Dependency Injection (Lines 156-159):

implementation("com.google.dagger:hilt-android:2.48")
ksp("com.google.dagger:hilt-compiler:2.48")

Networking (Lines 179-181):

implementation("com.squareup.okhttp3:okhttp:4.12.0")
implementation("com.squareup.retrofit2:retrofit:2.9.0")

Image Loading (Lines 186-188):

implementation("io.coil-kt:coil-compose:2.5.0")  // Image loading
implementation("io.coil-kt:coil-svg:2.5.0")  // SVG support

Total Android Dependencies: ~40 libraries

iOS Dependencies

File: provii/ios/Podfile

CocoaPods Dependencies:

platform :ios, '17.0'

pod 'YubiKit'  # YubiKey hardware authentication (Lightning + NFC)

Build Configuration (Lines 34-60):

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '17.0'
      config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
      config.build_settings['ENABLE_BITCODE'] = 'NO'
    end
  end
end

Total iOS Dependencies: 1 CocoaPod (YubiKit), rest are Apple frameworks


Supply Chain Security

SLSA Level 3 Implementation

Evidence:

  • /trust/developers/supply-chain-security.mdx
  • provii-agegate/.github/workflows/secure-build.yml
  • provii-mobile-sdk/.github/workflows/secure-build.yml

SLSA Requirements Implementation:

RequirementStatusEvidence
Build as CodeAll workflows in .github/workflows/
Ephemeral EnvironmentGitHub-hosted runners (fresh per build)
Isolated BuildsNo privileged access, minimal permissions
Hermetic BuildsCargo.lock, package-lock.json enforced
Signed ProvenanceSLSA provenance via slsa-github-generator
Non-falsifiableSigned with GitHub OIDC tokens
Two-person Review⚠️Not applicable for sole-operator; signed provenance and hermetic builds provide compensating controls

Hermetic Build Verification

provii-agegate (Lines 48-54 in secure-build.yml):

- name: Verify package-lock.json exists (hermetic build requirement)
  run: |
    if [[ ! -f package-lock.json ]]; then
      echo "❌ package-lock.json missing - required for reproducible builds"
      exit 1
    fi
    echo "✅ package-lock.json present"

provii-mobile-sdk (Lines 50-56 in secure-build.yml):

- name: Verify Cargo.lock exists (hermetic build requirement)
  run: |
    if [[ ! -f Cargo.lock ]]; then
      echo "❌ Cargo.lock missing - required for reproducible builds"
      exit 1
    fi
    echo "✅ Cargo.lock present"

Cryptographic Signing (Sigstore)

provii-agegate (Lines 196-236 in secure-build.yml):

- name: Install Cosign
  uses: sigstore/cosign-installer@v3
  with:
    cosign-release: v2.4.1

- name: Sign npm tarball
  env:
    COSIGN_EXPERIMENTAL: "true"
  run: |
    TARBALL=$(ls provii-agegate-*.tgz)
    cosign sign-blob \
      --bundle "${TARBALL}.cosign-bundle" \
      "${TARBALL}"

- name: Sign browser bundle
  env:
    COSIGN_EXPERIMENTAL: "true"
  run: |
    cosign sign-blob \
      --bundle dist/agegate.browser.js.cosign-bundle \
      dist/agegate.browser.js

Properties:

  • Keyless signing (no long-lived keys to leak)
  • OIDC-based authentication via GitHub
  • Signatures logged in Rekor transparency log
  • Non-repudiable cryptographic proof of origin

SLSA Provenance Generation

provii-agegate (Lines 254-267 in secure-build.yml):

provenance:
  name: Generate SLSA Provenance
  uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
  with:
    base64-subjects: "${{ needs.sign-artifacts.outputs.hashes }}"
    provenance-name: "provii-agegate.intoto.jsonl"
    upload-assets: true
    private-repository: true

provii-mobile-sdk (Lines 480-492 in secure-build.yml):

provenance:
  uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
  with:
    base64-subjects: "${{ needs.sign-artifacts.outputs.hashes }}"
    provenance-name: "provii-mobile-sdk.intoto.jsonl"
    upload-assets: true

Provenance Includes:

  • Build command and environment variables
  • Source repository and commit SHA
  • Builder identity (GitHub Actions)
  • All input materials (dependencies with hashes)
  • Output artefact hashes

SRI Hash Generation (Browser Bundles)

provii-agegate (Lines 132-145 in secure-build.yml):

- name: Generate SRI hash for browser bundle
  run: |
    # Generate SHA-384 SRI hash (standard for CDN integrity)
    SRI_HASH=$(openssl dgst -sha384 -binary dist/agegate.browser.js | openssl base64 -A)
    echo "sha384-${SRI_HASH}" > dist/agegate.browser.js.sri
    
    echo "✅ SRI hash generated:"
    cat dist/agegate.browser.js.sri

- name: Generate checksums for all artifacts
  run: |
    cd dist
    sha256sum *.js *.cjs *.d.ts > CHECKSUMS.txt
    cat CHECKSUMS.txt

This allows browsers to verify integrity:

<script 
  src="https://cdn.provii.app/sdk/provii-agegate/v0.1.1/agegate.browser.js"
  integrity="sha384-..." 
  crossorigin="anonymous"></script>

downpipes Update Channel (signature-pinned delivery)

downpipes extends the supply-chain story with its own delivery mechanism for the in-tenant engine, designed so that a Maelstrom-side compromise cannot silently push code into a customer’s Cloudflare account:

  • Pull, never push. The engine pulls verified updates from a static, signature-pinned Cloudflare R2 bucket (updates.downpipes.io); there is no phone-home and no standing inbound path from Maelstrom into the customer tenant (“runs dark”).
  • Signature verification before apply. The engine verifies each update’s signature against a pinned public key before applying it. Update artefacts are signed by the downpipes Update Signer, which is held offline by the operator and is never deployed to any Worker (see Cryptographic Key Management and the Asset Register, CRYPTO-009).
  • Canary-gated safe-apply with automatic rollback. Updates are canary-gated; a bad update is automatically rolled back, limiting blast radius in customer deployments.
  • Vendor surfaces are content-free. Neither the update channel nor the control-plane carries customer keys, data or Cloudflare tokens.

This is the downpipes analogue of SLSA provenance and Sigstore signing for Provii artefacts: cryptographically verified, non-pushed delivery with a key held outside the runtime.


Dependency Security Scanning

Dependabot Configuration

provii-agegate (provii-agegate/.github/dependabot.yml):

version: 2
updates:
  - package-ecosystem: npm
    directory: "/"
    schedule: { interval: weekly }
    open-pull-requests-limit: 10
    commit-message: { prefix: "build:" }

provii-issuer (provii-issuer/.github/dependabot.yml):

Rust Dependencies (Lines 3-43):

- package-ecosystem: "cargo"
  directory: "/worker"
  schedule:
    interval: "weekly"
    day: "monday"
    time: "02:00"
  open-pull-requests-limit: 10
  reviewers:
    - "provii-security-team"
  commit-message:
    prefix: "deps"
    prefix-development: "deps-dev"
  labels:
    - "dependencies"
    - "rust"
    - "security"
  ignore:
    # Ignore major version updates for critical deps
    - dependency-name: "worker"
      update-types: ["version-update:semver-major"]
    - dependency-name: "wasm-bindgen"
      update-types: ["version-update:semver-major"]
  groups:
    crypto:
      patterns:
        - "sha*"
        - "blake2"
        - "hmac"
        - "aes-gcm"
        - "bls12_381"
        - "jubjub"

GitHub Actions (Lines 88-98):

- package-ecosystem: "github-actions"
  directory: "/"
  schedule:
    interval: "weekly"
    day: "monday"
  open-pull-requests-limit: 5
  labels:
    - "dependencies"
    - "github-actions"
    - "ci-cd"

cargo audit Integration

provii-verifier CI (provii-verifier/.github/workflows/ci.yml, Lines 74-85):

security:
  name: Security Audit
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v4
    
    - name: Install cargo-audit
      run: cargo install cargo-audit
    
    - name: Run security audit
      run: cargo audit

provii-issuer Security Audit (provii-issuer/.github/workflows/security-audit.yml):

Daily Scheduled Scans (Lines 9-11):

schedule:
  # Run daily at 2 AM UTC
  - cron: '0 2 * * *'

Scanning (Lines 18-47):

cargo-audit:
  name: Cargo Audit - Dependency Vulnerabilities
  steps:
    - name: Install cargo-audit
      run: cargo install cargo-audit --locked
    
    - name: Run cargo audit
      run: |
        cd worker
        cargo audit --deny warnings --deny unmaintained --deny unsound --deny yanked
      continue-on-error: false

Licence Compliance (Lines 49-62):

cargo-deny:
  name: Cargo Deny - License & Security Compliance
  steps:
    - name: Install cargo-deny
      uses: taiki-e/install-action@cargo-deny
    
    - name: Run cargo deny
      run: |
        cd worker
        cargo deny check --hide-inclusion-graph

Dependency Review (Lines 64-76):

dependency-review:
  name: Dependency Review
  if: github.event_name == 'pull_request'
  steps:
    - name: Dependency Review
      uses: actions/dependency-review-action@v4
      with:
        fail-on-severity: high
        deny-licenses: GPL-3.0, AGPL-3.0

Trivy Vulnerability Scanner (Lines 78-98):

rust-security-scan:
  steps:
    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        scan-type: 'fs'
        scan-ref: 'worker'
        format: 'sarif'
        output: 'trivy-results.sarif'
        severity: 'CRITICAL,HIGH'
    
    - name: Upload Trivy results to GitHub Security
      uses: github/codeql-action/upload-sarif@v3
      with:
        sarif_file: 'trivy-results.sarif'

CodeQL Analysis (Lines 100-117):

codeql-analysis:
  steps:
    - name: Initialize CodeQL
      uses: github/codeql-action/init@v3
      with:
        languages: 'rust'
    
    - name: Perform CodeQL Analysis
      uses: github/codeql-action/analyze@v3

npm audit Integration

provii-agegate secure-build (Lines 59-60):

- name: Run security audit
  run: npm audit --audit-level high

Fails the build if any high-severity vulnerabilities are found.


Licence Compliance

Rust Crates Licence Policy

File: provii-crypto/Cargo.toml (Line 25)

license = "MIT OR Apache-2.0"

All Maelstrom AI Rust crates use dual licensing:

  • MIT License (permissive, allows commercial use)
  • Apache License 2.0 (permissive, includes patent grant)

Third-party Rust dependencies are predominantly:

  • MIT OR Apache-2.0 (bellman, bls12_381, jubjub, etc.)
  • MIT (serde, tokio, anyhow, thiserror)
  • Apache-2.0 (some cryptographic libraries)

Enforcement: cargo deny checks for GPL-3.0, AGPL-3.0 violations (Lines 74-76 in security-audit.yml):

with:
  fail-on-severity: high
  deny-licenses: GPL-3.0, AGPL-3.0

JavaScript Licence Policy

provii-agegate uses the MIT licence for production dependencies:

  • qrcode: MIT
  • zod: MIT

Development dependencies are not distributed, so licensing is more permissive.

Mobile Licence Compliance

Android:

  • AndroidX: Apache 2.0
  • Jetpack Compose: Apache 2.0
  • YubiKit: Apache 2.0
  • All Google libraries: Apache 2.0

iOS:

  • YubiKit: Apache 2.0
  • Apple frameworks: Proprietary (included with Xcode)

No GPL/AGPL dependencies in production builds.

Platform Outbound Licensing (first-party code)

The cargo-deny policy above governs the inbound third-party dependency licences for the Provii Rust crate set. The outbound licences under which Maelstrom AI distributes its own first-party code differ per platform and per repository:

PlatformComponentLicenceType
ProviiRepositories (per-repo mix)AGPL-3.0-only, Apache-2.0, MIT, with some proprietaryOpen source / proprietary mix
ProviiRust crates (e.g. provii-crypto)MIT OR Apache-2.0 (dual)Open source (permissive)
downpipesengine, console, control-planeElastic License v2Source-available (not open source, not AGPL)
downpipesoffline reader (downpipe, Go + TypeScript)MITOpen source (permissive)

downpipes licensing note. The downpipes engine, console and control-plane are source-available under the Elastic License v2 — source is published, and customers are free to self-host and to back up and restore, but the software may not be resold as a managed service (a third party running it would take custody, defeating the no-custody design). The offline reader is MIT open source, and is built from a frozen public format specification so that archives can be restored from archive bytes plus the customer’s offline key with no vendor and no network in the loop. ELv2 is a source-available, not an open source, licence; the cargo-deny GPL/AGPL denial above applies to the Provii crate build and does not bear on the downpipes outbound licences.


Sub-Processors & Data Processing

The canonical sub-processor roster, complete with per-processor data-flow tables, DPA references, audit rights, and transfer mechanisms, is maintained at /trust/legal/sub-processors (version 1.1, effective 14 April 2026). This section summarises the production sub-processors engaged for the age verification platform and the docs interactive sandbox. It is reconciled against the canonical list on every management review.

downpipes adds no sub-processor for customer data. Maelstrom AI’s second platform, downpipes (no-custody backup & disaster recovery for the Cloudflare data layer), runs in the customer’s own Cloudflare account, under the customer’s own keys. The engine and console are deployed in the customer’s tenancy; archives are sealed under customer-held keys (break-glass, operational and archive-signer keys, generated by the customer) and written via a 3-2-1 fan-out to customer-controlled destinations. Maelstrom holds no customer keys, data or Cloudflare tokens at any time. Because no customer personal data is received or processed by, or on behalf of, Maelstrom for downpipes, Maelstrom is not a processor of downpipes customer data and engages no sub-processor for it. The two Maelstrom-operated downpipes surfaces — the vendor-side control-plane (mints licence tokens, receives a content-free advisory beacon; fail-open) and the static, signature-pinned update channel (updates.downpipes.io) — run on the Cloudflare infrastructure already listed below and carry no customer keys or data, so they introduce no additional sub-processor and no international transfer of customer personal data. The sub-processors enumerated in this section are therefore those of the Provii platform and the administrator plane that supports it. See the Sub-Processors List for the canonical roster.

Infrastructure sub-processors

Cloudflare, Inc. operates as a data processor and handles hashed source IP addresses (HMAC-SHA-256 keyed by PII_HASH_KEY), challenge nonces (ephemeral), pseudonymous session identifiers, sandbox credential identifiers with docs-sbx-* and mwallet-sbx-* prefixes, request and response bodies traversing the Workers runtime, and audit and security telemetry events.

FieldDetail
Data locationCloudflare global edge network; traffic served from the data centre nearest the requester
GDPR complianceCloudflare master Data Processing Addendum, EU SCCs (Decision 2021/914, Module 2), UK IDTA for UK transfers
Security certificationsSOC 2 Type II, ISO 27001, ISO 27018, PCI DSS Level 1 for relevant services
EncryptionTLS 1.3 in transit, AES-256-GCM at rest

Mobile attestation sub-processors

Apple Inc. operates the App Attest service as a data processor for the attestation result returned to Provii. It handles Apple-issued attestation public key, attestation receipt, app bundle identifier, and key identifier. It does not receive an Apple ID, device serial number, IDFA, or email address. Its purpose is to mitigate credential cloning and emulator abuse on the iOS Provii wallet at issuance.

FieldDetail
Data locationApple-operated infrastructure
GDPR complianceApple Developer Program Licence Agreement with Schedule 2 (DPA)
PurposeHardware-backed attestation for iOS wallet at issuance

Google LLC operates the Play Integrity API as a data processor for the attestation verdict returned to Provii. It handles the Play Integrity verdict (app integrity, device integrity, licence verdict, Play Protect verdict), nonce supplied by provii-issuer, package name, and certificate hash. It does not receive a Google account identifier, advertising identifier, or precise location. Its purpose is to mitigate credential cloning, repackaging attacks, and emulator abuse on the Android Provii wallet at issuance.

FieldDetail
Data locationGoogle global infrastructure
GDPR complianceGoogle Play Developer Distribution Agreement with Data Processing and Security Terms
PurposeDevice-integrity attestation for Android wallet at issuance

Transactional email sub-processors

Resend, Inc. operates as a data processor for transactional email. It handles the recipient email address, recipient display name where present, email body (HTML and plain text), and sender address. It does not receive age verification data, wallet identifiers, attestations, or children’s data. It is used for low-volume transactional email tied to administrator and verifier onboarding; it is not used for marketing.

FieldDetail
Data locationPrimarily US-based infrastructure
GDPR complianceResend DPA with EU SCCs for transfers out of the EEA
Security certificationsSOC 2 Type II

Authentication sub-processors

Silverhand Inc., operator of Logto, acts as a data processor for administrator authentication. It handles the administrator email address, Logto user identifier, organisation membership, role assignments, MFA factor metadata (TOTP seed reference, WebAuthn credential identifier, phone number for SMS OTP where enabled), session and refresh tokens, and sign-in events. It does not receive wallet data, age verification data, or children’s data. It provides OAuth 2.0 and OpenID Connect for the Provii administrator surface (admin-portal) and officer authentication in provii-issuer; end-user wallet flows do not interact with Logto.

FieldDetail
Data locationLogto hosted tenant at auth.provii.app
GDPR complianceLogto DPA with EU SCCs
PurposeAdministrator and officer identity provider

Development tools (not production sub-processors of end-user personal data)

GitHub acts as a development tool rather than a production sub-processor of end-user personal data. It handles source code, CI/CD logs, build artefacts, and administrator sign-in events for the GitHub organisation. It does not receive age verification data, wallet identifiers, attestations, or children’s data. It is tracked under UC-070 and UC-144 (vendor and supply-chain management) rather than UC-147 (sub-processor management).

FieldDetail
Data locationUnited States (GitHub.com)
GDPR complianceGitHub Enterprise Cloud Data Protection Addendum with Standard Contractual Clauses
Security certificationsSOC 2 Type II
Data retentionIndefinite (version control)

Package Registry Sub-Processors

npm Registry:

  • Data Processed. Published packages (public)
  • Data Location. United States
  • Purpose. Public package distribution only
  • No PII. Only package metadata and code

Crates.io:

  • Data Processed. Published crates (public)
  • Data Location. United States
  • Purpose. Public package distribution only
  • No PII. Only package metadata and code

Maven Central / Google Maven:

  • Data Processed. Build-time dependencies only
  • No Runtime Data. Used during development only

Cryptographic Key Management

Cloudflare Secrets Store:

  • Data Stored. Master Encryption Keys (MEK), API keys, HMAC keys
  • Encryption. Hardware Security Modules (HSMs)
  • Access Control. Service bindings only (no human access)
  • Rotation. Automated key rotation with versioning

Evidence: provii-verifier/wrangler.toml (Lines 126-164):

[[secrets_store_secrets]]
binding = "VERIFIER_MEK"
store_id = "<redacted: internal Cloudflare Secrets Store resource ID>"
secret_name = "VERIFIER_MEK"

[[secrets_store_secrets]]
binding = "VERIFIER_MEK_V1"
store_id = "<redacted: internal Cloudflare Secrets Store resource ID>"
secret_name = "VERIFIER_MEK_V1"

# Supports key rotation with multiple versions active

The Secrets Store entries above are Provii vendor-side keys. downpipes introduces exactly two vendor-side signing keys, neither of which protects customer data:

  • downpipes Licence Signer — held in Cloudflare Secrets Store on the vendor-operated, fail-open control-plane; signs licence tokens, never gates backup or restore (Asset Register: CRYPTO-008).
  • downpipes Update Signer — held offline by the operator and never deployed to any Worker; signs engine update artefacts for the signature-pinned updates.downpipes.io channel (Asset Register: CRYPTO-009).

No-custody key boundary (downpipes). The keys that protect downpipes backup contents — the customer’s break-glass, operational and archive-signer keys — are generated and held by the customer (guided in-browser key ceremony, printed recovery sheet, offline storage). They are not Maelstrom assets, never reach Cloudflare Secrets Store as a Maelstrom secret, and Maelstrom cannot decrypt, recover or rotate them — by design. Safeguarding them is a complementary user-entity control (CUEC) borne by the customer.


Control Mapping

UC-070: Vendor Management

Control Requirement: Maintain inventory of third-party vendors and assess their security posture.

Evidence:

  1. Vendor Inventory: Complete inventory documented above (Cloudflare, GitHub, npm, crates.io, etc.), spanning both platforms; the downpipes update channel runs on Cloudflare R2, already inventoried
  2. Security Assessment: SOC 2 / ISO 27001 certifications verified for critical vendors
  3. Contract Review: DPAs and security clauses documented in supplier-management.md
  4. Monitoring: Status pages monitored, security advisories reviewed

downpipes application: downpipes adds no new critical vendor. Its in-tenant engine and console run in the customer’s own Cloudflare account (the customer’s own infrastructure, not a Maelstrom vendor relationship); the only Maelstrom-operated downpipes surfaces — the control-plane and the signature-pinned update channel — run on Cloudflare, already inventoried above.

Reference: /trust/security/supplier-management.md

UC-144: Supply Chain Security Policy

Control Requirement: Implement supply chain security measures to prevent unauthorised modifications.

Evidence:

  1. SLSA Level 3: Hermetic builds, signed provenance, ephemeral environments
  2. Signed Commits: Sigstore keyless signing on all releases
  3. Provenance: in-toto attestations for all artefacts
  4. Transparency: Rekor transparency log entries
  5. downpipes update channel: signature-pinned, pull-only delivery (updates.downpipes.io); the engine verifies each update against a pinned public key before applying, artefacts are signed by an offline-held Update Signer never deployed to any Worker, and a bad update is canary-rolled-back — preventing unauthorised modification of the in-tenant engine

Reference: /trust/developers/supply-chain-security.mdx

UC-145: Dependency Vulnerability Scanning

Control Requirement: Regularly scan dependencies for known vulnerabilities.

Evidence:

  1. Automated Scanning: Dependabot (weekly), cargo audit (CI/CD), npm audit (CI/CD)
  2. Daily Scans: Security-audit.yml runs daily at 2 AM UTC
  3. Trivy: Filesystem vulnerability scanning
  4. CodeQL: Static analysis for security issues
  5. Fail on High: Builds fail if high-severity vulnerabilities detected

Files:

  • provii-issuer/.github/workflows/security-audit.yml
  • provii-agegate/.github/workflows/secure-build.yml (Lines 59-60)
  • provii-verifier/.github/workflows/ci.yml (Lines 74-85)

UC-146: Licence Compliance

Control Requirement: Ensure third-party dependencies comply with licensing requirements.

Evidence:

  1. Licence Policy: Provii crates dual-licensed MIT OR Apache-2.0; Provii repositories under a per-repo mix (AGPL-3.0-only, Apache-2.0, MIT, some proprietary); downpipes engine/console/control-plane source-available under Elastic License v2, offline reader MIT (see Platform Outbound Licensing)
  2. Dependency Licences: Predominantly MIT/Apache-2.0 (permissive)
  3. GPL Denial: cargo deny explicitly rejects GPL-3.0, AGPL-3.0 in the Provii crate build
  4. Dependency Review: GitHub dependency review action checks licences on PRs

Files:

  • provii-crypto/Cargo.toml (Line 25)
  • provii-issuer/.github/workflows/security-audit.yml (Lines 49-62, 74-76)

UC-147: Sub-Processor Management

Control Requirement: Maintain list of sub-processors and ensure GDPR compliance.

Evidence:

The canonical sub-processor roster is maintained at /trust/legal/sub-processors (version 1.1, effective 14 April 2026), which carries a completeness attestation and names the source-code sweep that backs it. As of that attestation, five sub-processors are engaged in production:

#Sub-processorPurpose
1Cloudflare, Inc.Edge compute, KV, Durable Objects, R2, Workers Logs, Cloudflare managed challenge, Super Bot Fight Mode, WAF, Secrets Store, DNS
2Apple Inc. (App Attest service)Hardware-backed attestation for the iOS Provii wallet at issuance
3Google LLC (Play Integrity API)Device-integrity attestation for the Android Provii wallet at issuance
4Resend, Inc.Transactional email delivery for administrator and verifier onboarding
5Silverhand Inc. (Logto)OAuth 2.0 and OpenID Connect identity provider for the administrator surface and officer authentication in provii-issuer

GitHub is a development tool rather than a production sub-processor for end-user personal data; it is covered separately under UC-070 and UC-144 as a supply chain vendor.

downpipes adds no entry to this roster. Under the no-custody model the engine and console run in the customer’s own Cloudflare account, under the customer’s own keys, so Maelstrom processes no downpipes customer data and engages no sub-processor for it. The two Maelstrom-operated downpipes surfaces — the fail-open control-plane and the signature-pinned update channel (updates.downpipes.io) — run on the Cloudflare infrastructure already listed at #1 and carry no customer keys or data, introducing no additional sub-processor and no international transfer of customer personal data. See Sub-Processors & Data Processing above and the Sub-Processors List downpipes scope note (canonical).

Stripe remains a planned payment processor, not live in production. It will be added to the canonical list when the billing integration lands, with 30 days’ advance notice to controllers as required under SCC Module 2 Clause 9(a) Option 2.

Supporting artefacts:

ArtefactLocation
Canonical sub-processor list/trust/legal/sub-processors version 1.1
Data Processing AddendaCloudflare master DPA with EU SCCs and UK IDTA, Apple Developer Program Schedule 2 DPA, Google Play Developer Data Processing and Security Terms, Resend DPA, Logto DPA
Data flows and retentionROPA and per-sub-processor tables at /trust/legal/sub-processors
Transparency disclosuresPrivacy Policy and DPIA
Change notification30 days’ advance notice mechanism documented at /trust/legal/sub-processors#notification-of-changes

Reference: “Sub-Processors & Data Processing” section above (this document) and /trust/legal/sub-processors (canonical).

UC-148: Artefact Verification

Control Requirement: Provide mechanisms for users to verify integrity of distributed artefacts.

Evidence:

  1. Checksums: SHA256 checksums for all artefacts
  2. Signatures: Sigstore signatures with keyless signing
  3. SRI Hashes: Subresource Integrity hashes for browser bundles
  4. Provenance: SLSA provenance attestations (in-toto format)
  5. Verification Guide: Complete documentation for end users
  6. downpipes update artefacts: signature-verified against a pinned public key before the engine applies them (signed by the offline-held Update Signer); the MIT offline reader is built from a frozen public format specification, so customers can independently verify and restore archives from archive bytes plus their own key with no vendor in the loop

Files:

  • /trust/developers/artifact-verification.mdx
  • provii-agegate/.github/workflows/secure-build.yml (Lines 132-161, 196-236)

Gap Analysis

Current State: Strong

Strengths:

  1. SLSA Level 3 supply chain security implemented
  2. Automated dependency scanning (Dependabot, cargo audit, npm audit)
  3. Keyless cryptographic signing with Sigstore
  4. Hermetic builds with locked dependencies
  5. provenance generation
  6. Licence compliance enforcement
  7. Vendor security assessment documented
  8. Sub-processor DPAs in place
  9. downpipes: signature-pinned, pull-only update channel with an offline-held Update Signer, canary-gated safe-apply and automatic rollback; no-custody architecture adds no sub-processor for customer data

⚠️ Areas for Enhancement:

  1. Branch Protection: Two-person review is not feasible for a sole operator and is accepted as a structural limitation; signed provenance and hermetic builds are in place as compensating controls
  2. SBOM Generation: Software Bill of Materials not yet automated
  3. VEX Documents: Vulnerability Exploitability eXchange not implemented
  4. Bit-for-bit Reproducibility: Not yet achieved (SOURCE_DATE_EPOCH not set)
  5. Dependency Review Policy: No formal policy document (relies on automated tools)

Recommendations

Short-term (1-3 months):

  1. Generate SBOMs during build process (CycloneDX or SPDX format)
  2. Document formal dependency review policy

Medium-term (3-6 months):

  1. Implement VEX documents for vulnerability disclosure
  2. Achieve bit-for-bit reproducible builds
  3. Automate licence compliance reporting
  4. Implement runtime attestation verification

Long-term (6-12 months):

  1. Migrate to hermetic container-based builds
  2. Implement automated vulnerability patching
  3. Establish vendor security reassessment schedule
  4. Create public transparency report for dependencies

Conclusion

Maelstrom AI has implemented third-party dependency management and supply chain security controls — across both platforms, Provii and downpipes — that meet or exceed industry best practices:

  1. Complete Vendor Inventory: All critical vendors documented with security assessments; downpipes adds no new critical vendor (its in-tenant engine and console run in the customer’s own Cloudflare account; the control-plane and update channel run on Cloudflare, already inventoried)
  2. Dependency Tracking: tracking across 4 ecosystems (Rust, JavaScript, Android, iOS)
  3. Supply Chain Security: SLSA Level 3 implementation (two-person review accepted as sole-operator limitation; compensating controls in place), complemented by the downpipes signature-pinned, pull-only update channel with an offline-held Update Signer
  4. Automated Scanning: Daily vulnerability scans, weekly dependency updates
  5. Cryptographic Signing: Keyless signing with Sigstore, non-falsifiable provenance
  6. Licence Compliance: Enforced via automated tools (cargo deny, dependency review); downpipes engine/console/control-plane source-available under Elastic License v2, offline reader MIT
  7. Sub-Processor Management: DPAs in place, data flows documented; downpipes is no-custody and adds no sub-processor for customer data

Controls UC-070, UC-144, UC-145, UC-146, UC-147, UC-148 are substantially addressed, with the enhancement opportunities noted above.


Document metadata:

FieldValue
Document version1.1 (2026-06-19)
Platforms in scopeProvii (zero knowledge age verification) and downpipes (no-custody Cloudflare backup & disaster recovery)
Critical third-party vendors documented in this file6 (Cloudflare, GitHub, npm, Crates.io, CocoaPods, Maven Central / Google Maven); downpipes adds no new critical vendor (its control-plane and update channel run on Cloudflare, already inventoried)
Production sub-processors per canonical list5 (Cloudflare, Apple App Attest, Google Play Integrity, Resend, Logto/Silverhand), see /trust/legal/sub-processors v1.1; downpipes adds no sub-processor for customer data (no-custody)
Rust dependenciesApproximately 100 crates across provii-crypto, provii-verifier, provii-issuer, provii-mobile-sdk
JavaScript dependencies79 packages (provii-agegate)
Android dependenciesApproximately 40 libraries
iOS dependencies1 CocoaPod (YubiKit)
Evidence files analysedMore than 15 configuration files, 6 CI/CD workflows, 3 documentation files
Lines of evidence reviewedMore than 2,000 lines of configuration and workflow code
Next review date2026-11-21 (quarterly review schedule)

Change history:

VersionDateChange
1.02025-11-08Initial third-party & supply-chain evidence (Provii).
1.12026-06-19downpipes added as second in-scope platform; the legacy backup worker retired in favour of self-hosted downpipes. Made the document cross-cutting across both platforms: added the downpipes signature-pinned update channel and offline-held Update Signer to supply-chain controls, the source-available (Elastic License v2) / MIT offline-reader outbound licensing, the downpipes vendor-side signing keys, and the no-custody position that Maelstrom adds no sub-processor for downpipes customer data. Australian/British spelling corrections applied (licence noun, artefact, unauthorised).

End of Document