nearmiss is designed so an advocacy group with no budget can still run it. The intake can run as a stateless, scale-to-zero serverless function, and the published site is static-friendly, so there is no always-on component to keep paid.
What lives here (the analysis still runs entirely offline without any of it):
-
aws-static-site.ymlprovisions the canonical nearmiss.chelseakr.com origin: a private, versioned S3 bucket, CloudFront with OAC and TLS, Route 53 A/AAAA aliases, directory-route rewriting, security headers, and a narrowly scoped GitHub OIDC deployment role. TheproductionGitHub environment can publish only the exact artifact assembled by the dependency-gatedbuild-pagesjob; no static AWS key is stored. The legacynearmiss.reportGitHub Pages origin stays live during migration. First deployment usesPublishDns=false; after the reviewed artifact is present at the private origin, update the same stack withPublishDns=trueto expose the Route 53 A and AAAA aliases. Deploy this stack inus-east-1: CloudFront accepts ACM certificates only from that region. Theproductionenvironment is configured with an exactmainbranch policy, and administrators cannot bypass that deployment restriction. The OIDC subjectrepo:ChelseaKR/nearmiss:environment:productionis therefore a main-only deployment identity. The deploy job downloads the reviewed artifact, checks out the exact source into a separate directory, rebuilds withpython -S, and byte-compares both trees before requesting its OIDC token. The Pages-only.nojekyllandCNAMEcontrols are excluded and deleted from the canonical origin. A failed transfer or non-deterministic build therefore cannot mutate the origin. -
Pull requests exercise the exact
build-pagesassembly and both artifact-upload paths. Onmain, dependency-gated deploy jobs publish that one reviewed artifact to GitHub Pages and the canonical CloudFront origin only after the full CI is green.tools/build_site.pyallowlistsweb/anddata/published/, rejects symlinks and path-resolution escapes, and excludes private/raw and repository-internal files. The artifact exposes/deployment.jsonand/site-manifest.json; the manifest hashes every payload file (the manifest envelope itself is the sole exception), and the workflow verifies the deployed commit and critical data/UI paths before reporting success. The least-privilege job boundary is recorded in ADR 0005. -
A serverless intake deploy (validate against the report schema, rate-limit to resist spam and poisoning, write to the private raw store).
-
A scheduled rebuild that re-runs the pipeline and republishes the open dataset, keeping it current (timeliness), with rebuild latency budgeted in CI.
-
A container image and one-command deploy for self-hosting.
Cost target: near zero, with a budget alarm. Secrets are provided via the environment and never
committed — see SECURITY.md.
Re-run the deploy workflow for a known-good commit after reverting main to that content through a
normal reviewed PR. Do not rewrite published data in place: the deployment stamp and manifest must
continue to identify the exact commit that produced the live artifact.
The CloudFront bucket is versioned. An emergency rollback still rebuilds a known-good reviewed commit, syncs that exact artifact, invalidates the distribution, and reruns the live verifier; do not restore a loose subset of old S3 object versions because that would break the manifest envelope. The workflow intentionally reports a failed post-publication verification rather than automatically rolling back on a possibly transient edge failure, so the bounded verifier and this exact-artifact rollback procedure are both part of the operator response.