Production Readiness Checklist for Synthetic Spatial Pipelines

Shipping a synthetic spatial pipeline to production is not a code review, it is an audit: every claim the pipeline makes — this CRS, this seed, this privacy budget, this topology guarantee — must be backed by evidence a reviewer can inspect without trusting the author. This page is part of Synthetic Spatial Data Architecture & Fundamentals: it consolidates the contracts from scoping rules and data contracts, the budget accounting from privacy-preserving generation frameworks, and the fidelity gates from realism metrics evaluation into a single promotion checklist, and maps each item to the artifact a compliance reviewer will ask for. The failure it prevents is the “works on my machine” release: a generator that produces plausible output in a notebook but has no reproducible seed, no composed budget, and no gate history — nothing a reviewer can sign off.

Mapping of five production-readiness checklist categories to their required audit evidence Two columns joined by arrows. The left column lists five checklist categories from top to bottom: CRS and contract readiness, determinism and seed registry, privacy budget accounting, geometric and statistical gates, and promotion and audit evidence. Each category has an arrow to the right column naming the artifact it must produce. CRS and contract readiness produces a versioned CRS and schema contract. Determinism and seed registry produces a seed registry entry keyed to the generator version hash. Privacy budget accounting produces a composed epsilon-delta ledger. Geometric and statistical gates produce a passing gate report listing every tolerance. Promotion and audit evidence produces an immutable promotion record linking all the others. A reviewer verifies each artifact before sign-off. Checklist category Required audit evidence 1 · CRS & contract readiness extent · projection · schema · units 2 · Determinism & seed registry explicit seeds · version hash · replay 3 · Privacy budget accounting composed (ε, δ) · attack scores 4 · Geometric & statistical gates topology · fidelity · tolerances 5 · Promotion & audit evidence immutable record · sign-off versioned CRS & schema contract checked-in, hashed, machine-validated seed registry entry keyed to generator version hash composed ε/δ ledger + attack report budget spent vs standing limit passing gate report every tolerance listed & met immutable promotion record links all evidence above
Every checklist category owes the reviewer one concrete artifact — readiness is having all five on the shelf before promotion, not asserting them after.

Problem Framing: Readiness Is Evidence, Not Confidence

The failure this checklist prevents is the unauditable release — a pipeline that works but cannot prove why, so a compliance reviewer has nothing to sign. It manifests as four recurring gaps.

  • Untraceable output. A dataset ships without recording which generator version, which seed, and which CRS produced it. When a downstream model behaves oddly, nobody can reproduce the exact artifact to diagnose it, and no reviewer can confirm the release matches its manifest.
  • Undocumented privacy spend. The generator applies noise, but no ledger records the composed (ε,δ)(\varepsilon, \delta) across all releases against a standing budget. The privacy claim is a sentence in a design doc, not a number a reviewer can check.
  • Gates that ran once. Topology and statistical checks passed on a developer laptop months ago, but nothing re-runs them on the actual promoted artifact. The evidence is stale and the reviewer has to take it on faith.
  • No promotion boundary. Data flows from generation to consumption with no explicit gate where evidence is collected and a verdict recorded, so “production” is wherever the file happened to land.

Each gap is invisible while the pipeline runs green and fatal the moment a regulator, a security review, or an incident asks “show me.” The checklist below is organized so that clearing every item leaves behind exactly the evidence trail a reviewer requires, produced automatically as a byproduct of running the pipeline rather than assembled under deadline.

Prerequisites & Toolchain

Readiness assumes the standard synthetic-spatial stack plus the machinery that turns runs into records. Pin majors so the evidence is reproducible across environments:

python >= 3.10
numpy == 1.26.*
scipy == 1.11.*
geopandas == 0.14.*
shapely == 2.*          # GEOS 3.11+; topology validation
pyproj == 3.*           # PROJ 9.x; CRS contract enforcement
pydantic == 2.*         # machine-validated contract + manifest schema
pytest == 7.*           # gates as build-failing tests

Two environment invariants underpin every checklist item. First, run generation inside a pinned container with the PROJ datum grids shipped in-image and PROJ_NETWORK=OFF, so a coordinate transformation resolves identically on CI and on a reviewer’s replay months later. Second, treat the manifest as code: the seed, CRS contract, budget allocation, and gate tolerances live in a version-controlled file that the pipeline reads and the audit record hashes, so there is one source of truth the reviewer and the runner share. The CI/CD integration layer is what executes these gates on every candidate artifact.

Core Concept: The Promotion Gate as an Audit Contract

A production-ready pipeline has exactly one place where an artifact crosses from “generated” to “promoted,” and that gate is a contract with three properties. It is complete — no artifact reaches consumers except through it. It is evidence-producing — passing the gate writes an immutable record of every check, its tolerance, its result, and the inputs that produced it. And it is reproducible — anyone with the manifest and the recorded seeds can regenerate the artifact byte-for-byte and re-run every gate to the same verdict.

The five checklist categories are the five kinds of evidence that gate collects, and they are not independent. The CRS contract fixes the units that make the privacy budget’s metres meaningful; the seed registry is what makes the gate results reproducible rather than a one-time observation; the privacy ledger and the adversarial privacy testing scores together substantiate the privacy claim, one formally and one empirically; and the statistical gates confirm the output is still useful after all the protection is applied. The promotion record binds them: it is a single manifest that references the CRS contract hash, the seed registry entry, the composed budget, the gate report, and the sign-off, so a reviewer follows one link and finds everything. Readiness is the state in which that record can be produced automatically, on demand, for any release.

Step-by-Step Implementation

Work the checklist category by category. Each item names the check and the artifact it leaves behind; a manifest ties them together at the end.

Group 1 — CRS & contract readiness. The generator must declare and enforce its spatial contract before emitting a single feature.

python
from pydantic import BaseModel

class CRSContract(BaseModel):
    target_crs: str          # e.g. "EPSG:6933"
    extent: tuple[float, float, float, float]   # minx, miny, maxx, maxy (metres)
    geometry_types: list[str]
    attribute_schema: dict[str, str]

    def validate_output(self, gdf) -> None:
        assert str(gdf.crs) == self.target_crs, "CRS drifted from contract"
        minx, miny, maxx, maxy = gdf.total_bounds
        ex = self.extent
        assert minx >= ex[0] and miny >= ex[1] and maxx <= ex[2] and maxy <= ex[3], \
            "geometry escaped declared extent"

The detailed enforcement of this contract is worked through in enforcing CRS contracts in a generation pipeline; the checklist only requires that the contract exists, is hashed, and is machine-validated on every run.

Group 2 — Determinism & seed registry. Every stochastic step must be replayable from a recorded seed.

python
def registry_entry(seed: int, version_hash: str, lockfile_hash: str) -> dict:
    return {"seed": seed, "generator_version": version_hash,
            "lockfile": lockfile_hash}

def test_replay_is_byte_identical(build_fn, entry):
    a = build_fn(entry["seed"]).geometry.apply(lambda g: g.wkb).tolist()
    b = build_fn(entry["seed"]).geometry.apply(lambda g: g.wkb).tolist()
    assert a == b, "artifact is not reproducible from its seed registry entry"

Group 3 — Privacy budget accounting. The privacy claim must be a composed number, backed by an attack result.

εrelease=C({(εi,δi)})εstanding,advantagemeasuredeεrelease1.\varepsilon_{\text{release}} = \mathcal{C}\big(\{(\varepsilon_i, \delta_i)\}\big) \le \varepsilon_{\text{standing}}, \qquad \text{advantage}_{\text{measured}} \le e^{\varepsilon_{\text{release}}} - 1.

The mechanism-specific composition — summing for pure ε\varepsilon, Rényi accounting for Gaussian — follows the guidance in differential privacy mechanisms compared, and the failure mode of an under-tracked budget is detailed in diagnosing epsilon budget exhaustion across releases.

Group 4 — Geometric & statistical gates. The artifact must be both valid and useful, each with a listed tolerance.

python
def gate_report(gdf, contract, tolerances) -> dict:
    report = {}
    report["valid_geometry"] = bool(gdf.geometry.is_valid.all())
    report["in_extent"] = _within_extent(gdf, contract.extent)
    report["fidelity_ok"] = _fidelity_within(gdf, tolerances["fidelity"])
    report["passed"] = all(v is True for v in report.values())
    return report

Tie the statistical side back to realism metrics evaluation so the tolerances are principled rather than arbitrary.

Group 5 — Promotion & audit evidence. Bind everything into one immutable record and require sign-off.

The full manifest that drives all five groups lives in version control and is read by the pipeline on every run:

yaml
# release-manifest.yaml — the single source of truth the gate hashes
release:
  id: "synth-2026-04-22"
  generator_version: "g1a2b3c"
  lockfile_hash: "sha256:…"
crs_contract:
  target_crs: "EPSG:6933"
  extent: [-17367530.0, -7314540.0, 17367530.0, 7314540.0]
determinism:
  seed: 20260422
privacy:
  standing_epsilon: 8.0
  per_stage:
    - {stage: perturbation, epsilon: 1.0, delta: 1.0e-6, mechanism: gaussian}
    - {stage: attributes,   epsilon: 0.5, delta: 1.0e-6, mechanism: exponential}
  attack_thresholds:
    membership_advantage_max: 0.10
    nn_reid_ratio_min: 0.50
gates:
  fidelity:
    wasserstein_max_m: 250.0
  topology:
    area_tol: 1.0e-3
yaml
# promotion gate step in CI — halts unless every artifact is green
promote:
  needs: [crs_contract, seed_registry, privacy_ledger, gate_report]
  rules:
    - if: crs_contract.valid && seed_registry.reproducible
        && privacy_ledger.epsilon <= privacy.standing_epsilon
        && gate_report.passed && attack_report.passed
      then: write_promotion_record
    - else: halt

Validation & Testing

The checklist is only real if a test proves each artifact exists and is consistent before promotion. The meta-gate asserts completeness of the evidence, not just of the data.

python
REQUIRED = ["crs_contract", "seed_registry", "privacy_ledger",
            "attack_report", "gate_report"]

def test_promotion_requires_complete_evidence(record: dict):
    for artifact in REQUIRED:
        assert artifact in record, f"missing audit evidence: {artifact}"
        assert record[artifact]["hash"], f"unhashed evidence: {artifact}"

def test_budget_within_standing_limit(record, standing_epsilon):
    assert record["privacy_ledger"]["composed_epsilon"] <= standing_epsilon, \
        "release would exceed the standing privacy budget"

def test_manifest_hash_matches_artifact(record, artifact_bytes_hash):
    assert record["artifact_hash"] == artifact_bytes_hash, \
        "promoted artifact does not match its manifest"

Run these as build-failing checks in the same CI/CD integration pipeline that runs the generator, so an incomplete evidence trail blocks promotion exactly like a failing topology check. The reviewer’s job then reduces to reading the promotion record, because the CI system has already enforced that every claim it contains is backed by a hashed, reproducible artifact.

Performance & Scale Considerations

Making a pipeline auditable adds bookkeeping, and at scale the bookkeeping must not dominate.

  • Hash incrementally, not at the end. Compute content hashes for the contract, seeds, and manifest as they are produced, so the promotion record assembles in constant time rather than re-reading gigabytes of output at the gate.
  • Sample the statistical gates, validate topology in full. Topology validity is cheap and must cover every geometry; distance-based fidelity metrics are expensive and a seeded, stratified sample gives a stable estimate at a fraction of the cost on continental extents.
  • Keep the evidence small and the data large. The audit record references artifacts by hash rather than embedding them, so the promotion record stays kilobytes even when the release is terabytes, and append-only storage growth tracks releases, not data volume.
  • Parallelize gates, serialize the verdict. Run topology, fidelity, and attack gates concurrently across shards, then collect their reports into a single verdict — the same reproducible per-shard seeding the scoping rules and data contracts layer enforces keeps concurrent gate runs replayable.

Failure Modes & Troubleshooting

Frequently Asked Questions

What is the single most common reason a synthetic pipeline fails an audit?
Untraceable output: a dataset that cannot be regenerated because the seed, generator version, and CRS were never recorded together. A reviewer cannot verify a release they cannot reproduce, so the fix is a seed registry entry keyed to the generator version hash and the library lockfile hash, plus a determinism test that regenerates the artifact and asserts byte-identical output. Reproducibility is the precondition for every other piece of evidence, which is why it sits so early on the checklist.
Do I need adversarial privacy tests if I already track a formal epsilon budget?
Yes. The composed epsilon-delta budget bounds the worst case assuming the mechanism is implemented correctly, while an attack measures what the specific release actually leaks. A reviewer wants both: the formal number substantiates the design, and the attack scores substantiate the implementation. Record the composed budget and the membership, attribute, and re-identification scores together, and tie each attack threshold to the stated epsilon so the two lines of evidence are consistent rather than independent.
Where exactly is the boundary between "generated" and "production"?
At the promotion gate, which must be the only path from generation to consumers. Passing the gate writes an immutable promotion record that references the CRS contract, seed registry, privacy ledger, attack report, and gate report by content hash, and no artifact reaches a consumer without one. Making the boundary explicit is what lets you answer "show me" instantly: there is one record per release, it links all the evidence, and append-only storage means it cannot be quietly edited after the fact.
How do I keep tolerances from being arbitrary numbers in a config file?
Derive each tolerance from the stage that owns it and record the observed value against it, not just a pass or fail bit. Fidelity tolerances come from the realism metrics evaluation stage, area-conservation tolerances from the topology requirements of a gap-free partition, and privacy thresholds from the stated budget. Putting them in the version-controlled manifest with a comment on their provenance means a reviewer can trace every number to a rationale, and a change to a tolerance shows up as a reviewable diff.
Can I add this checklist to an existing pipeline, or must I rebuild?
You can retrofit it incrementally, and the order on the checklist is a sensible sequence. Start by pinning the CRS contract and adding the seed registry, because reproducibility unblocks everything else. Then add the privacy ledger and attack suite, then wire the topology and fidelity gates, and finally introduce the promotion record that binds them. Each group produces standalone evidence, so partial adoption still improves auditability, and the manifest gives you one place to grow the contract without touching generator code.