diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7e4fcdf9..867698ae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,6 +17,10 @@ jobs: node-version: '20' cache: 'npm' - run: npm ci --legacy-peer-deps + - name: Run frontend Jest tests + env: + CI: 'true' + run: npm test -- --watchAll=false --runInBand - run: npm run lint:fix -- --max-warnings=0 || true - name: Build env: diff --git a/AGENTS.md b/AGENTS.md index 3a08c6ef..5ad406c7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -105,7 +105,7 @@ The following are **NOT AVAILABLE YET** on `main`: - `npm run emulators` and fail-closed Auth/Firestore/Functions isolation — owned by #99. - `npm run test:spa-navigation` — owned by #99. -The deterministic frontend Jest baseline is available through the command above. It is not yet a required CI quality gate; workflow enforcement remains **NOT AVAILABLE YET** under #105. +The deterministic frontend Jest baseline is available through the command above. Hosted CI runs that command as the blocking `Run frontend Jest tests` step under #124. This proves the suite ran for that commit; it does not prove branch protection, website publication, Firebase deployment, provider configuration, or production behavior. The remaining fail-closed lint and deployment work stays open under #105. Do not run Firebase-backed local development against the current production-configured client. Do not describe queued working-tree commands as merged or available. diff --git a/GITHUB_ISSUES.md b/GITHUB_ISSUES.md index b5e3b44c..00c747b2 100644 --- a/GITHUB_ISSUES.md +++ b/GITHUB_ISSUES.md @@ -14,6 +14,7 @@ Published foundation mapping: - PAY-003A → [#101](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/101) - PROMO-001 → [#102](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/102) - CI-001A → [#103](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/103) +- CI-001B1 → [#124](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/124) - ARCH-001 documentation → [#104](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/104) - CI-001 tracker → [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105) - PAY-003 tracker → [#106](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/106) @@ -49,7 +50,7 @@ Every issue inherits `AGENTS.md` and the definition of done in `IMPLEMENTATION_P | Order | ID | Title | Priority | Size | Status | Depends on | | ---: | --- | --- | --- | --- | --- | --- | | 1 | SAFETY-001 | Preserve commerce/OAuth callbacks and isolate local Firebase Functions | P0 | S | implemented_locally | — | -| 2 | CI-001 | Repair test gates and secure the deployment pipeline | P0 | L | ready | SAFETY-001 | +| 2 | CI-001 | Repair test gates and secure the deployment pipeline | P0 | L | partial: #103 baseline + #124 hosted Jest; remaining gates open | SAFETY-001 | | 3 | SUPPLY-001 | Remove vulnerable dependency chains and stage SDK/build upgrades | P0 | L | ready | CI-001 baseline | | 4 | SEC-001 | Replace the Firestore admin catch-all with resource-specific rules | P0 | M | implemented_locally | — | | 5 | CONFIG-001 | Fail closed on server environment and commerce configuration | P0 | M | ready | CI-001A recommended | @@ -121,12 +122,12 @@ Do not redesign routing or hosting in this issue; WEB-001 owns that. Do not incl ## CI-001 — Repair test gates and secure the deployment pipeline **Labels:** `priority:P0`, `type:security`, `type:testing`, `area:ci`, `size:L`, `needs-external-config` -**Status:** Published as tracker [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105); focused child [#103](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/103) owns the deterministic local frontend Jest baseline. The live issue records its merge state. Required workflow gating and protected deployment remain open under #105, so the current workflow is still non-compliant. +**Status:** Published as tracker [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105). [#103](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/103) merged the deterministic local frontend Jest baseline, and [#124](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/124) owns its named blocking hosted-CI step. Fail-closed lint, required branch protection, dependency/secret checks, and protected backend-first deployment remain open, so the delivery pipeline is still non-compliant overall. **Depends on:** SAFETY-001 ### Problem -Before #103, frontend tests failed because the Jest environment lacked `TextEncoder`. The focused child repairs that local baseline, but CI still runs a mutating `lint:fix` command, ignores failure with `|| true`, and does not require frontend Jest. Deployment runs independently of CI, gives a full Firebase service-account JSON to the frontend build, installs `firebase-tools@latest`, deploys frontend before backend, and can succeed while silently skipping Firebase deployment. +Before #103, frontend tests failed because the Jest environment lacked `TextEncoder`. That child repaired the local baseline, and #124 adds it to hosted CI. CI still runs a mutating `lint:fix` command and ignores its failure with `|| true`. Deployment still runs independently of CI, gives a full Firebase service-account JSON to the frontend build, installs `firebase-tools@latest`, deploys frontend before backend, and can skip or fail before proving Firebase deployment. ### Scope @@ -163,7 +164,7 @@ Before #103, frontend tests failed because the Jest environment lacked `TextEnco ### Agent handoff -Repository changes can implement tests/workflow shape, but OIDC/IAM/environment protection requires an authorized owner. Split into `CI-001A` (test reliability) and `CI-001B` (deployment identity) if one PR would be too broad. +Repository changes can implement tests/workflow shape, but OIDC/IAM/environment protection requires an authorized owner. CI-001A/#103 owns test reliability, CI-001B1/#124 owns the hosted frontend-Jest step, and the remaining CI-001B2 deployment-identity/protection work must stay in separately claimed children. --- diff --git a/GITHUB_ISSUE_SLICES.md b/GITHUB_ISSUE_SLICES.md index 68afe276..ab765464 100644 --- a/GITHUB_ISSUE_SLICES.md +++ b/GITHUB_ISSUE_SLICES.md @@ -16,14 +16,15 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de | ID | Status/dependency | Bounded deliverable | Close evidence | | --- | --- | --- | --- | -| CI-001A | published as #103; local baseline slice | Repair Jest browser globals and replace the stale starter test with a deterministic, no-provider-network MPRC app smoke test. Required workflow gating remains under #105. | Node 20 focused/full frontend tests, changed-file lint, clean diff, and diagnostic build pass; do not claim a required CI gate. | -| CI-001B | owner_action; CI-001A | Protect backend-first staging/production deployment; pin tools/Actions; remove frontend service-account JSON; configure OIDC/WIF, approvals, missing-config failure, smoke and roll-forward. | PR gate and negative credential run; private two-owner IAM review; staging deployment evidence. | +| CI-001A | merged/closed as #103 | Repair Jest browser globals and replace the stale starter test with a deterministic, no-provider-network MPRC app smoke test. | Node 20 focused/full frontend tests, changed-file lint, clean diff, and diagnostic build pass. | +| CI-001B1 | published as #124; CI-001A | Run the complete committed frontend Jest suite as a named blocking step in the hosted frontend CI job; update exact officer/engineering truth. | Local Node 20 suite/build plus exact pull-request and post-merge hosted step evidence; no production/provider claim. | +| CI-001B2 | owner_action; CI-001B1 | Protect backend-first staging/production deployment; make lint/remaining checks fail closed; pin tools/Actions; remove frontend service-account JSON; configure OIDC/WIF, approvals, missing-config failure, smoke and roll-forward. | Required PR gate and negative credential run; private two-owner IAM review; staging deployment evidence. | | SUPPLY-001A | ready; CI-001A | Prove `gpxparser` unused and remove its obsolete transitive chain. | `rg`/tree proof, before/after audits, root lockfile diff, full frontend checks. | | SUPPLY-001B | ready; CI-001A | Patch React Router within compatible 6.x and resolve/test future flags without route redesign. | Navigation/callback tests, audit delta, build. | | SUPPLY-001C | proposed; CI-001A | Upgrade Firebase web SDK within one compatibility boundary. | Auth/Firestore/Functions/App Check/emulator tests and bundle/audit diff. | | SUPPLY-001D | proposed; CI-001A | Upgrade Firebase Admin/Functions in one supported set. | Node 20 lint/unit/emulator/trigger tests and deploy compatibility notes. | | SUPPLY-001E | proposed; PAY-003C | Upgrade Stripe SDK and deliberately select/test an API version. | Signed fixture/test-mode diff and rollback notes; no live endpoint change. | -| SUPPLY-001F | proposed; CI-001B, A–C | Replace CRA while preserving env handling, SPA callbacks, sitemap/SEO, code splitting, and deploy output. | Full CI, bundle/SEO comparison, staging dry run. | +| SUPPLY-001F | proposed; CI-001B2, A–C | Replace CRA while preserving env handling, SPA callbacks, sitemap/SEO, code splitting, and deploy output. | Full CI, bundle/SEO comparison, staging dry run. | | SUPPLY-001G | proposed; CI-001A | Add dependency updates, audit exceptions, secret scan, SBOM, and lockfile review policy. | Safe sample update; deliberate secret detection; sanitized SBOM. | ## Identity, OAuth, and abuse controls @@ -101,7 +102,7 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de | MERCH-002B | proposed; A, MERCH-001B | Apply server shipping/tax config and actual total snapshots/reconciliation. | Test-mode taxable/pickup/shipping/mismatch fixtures. | | MERCH-002C | proposed; A/B, ADMIN-001C | Add fulfillment/return/restock state and audited operator actions. | Forbidden transitions and stock adjustment tests. | | MERCH-002D | proposed; A–C, MAIL-001B | Add minimum customer communications/UI and address minimization. | Lifecycle/email/PII projection tests. | -| WEB-001A | owner_action; CI-001B | Provision isolated staging hosting, rewrites, canonical/sitemap behavior, deploy and rollback. | ADR and deep-route staging evidence. | +| WEB-001A | owner_action; CI-001B2 | Provision isolated staging hosting, rewrites, canonical/sitemap behavior, deploy and rollback. | ADR and deep-route staging evidence. | | WEB-001B | proposed; A | Add CSP/HSTS/frame/referrer/permissions/MIME/cache policy. | Automated header/CSP and browser flow smoke. | | WEB-001C | proposed; A/B, PAY-001A | Sanitize/validate stored HTML/URLs and migrate unsafe content. | XSS/protocol/legacy content fixtures. | | WEB-001D | owner_action; A–C | Execute controlled DNS cutover/rollback and retire old deploy path without enabling commerce. | Dated owner-approved cutover evidence. | diff --git a/OFFICER_START_HERE.md b/OFFICER_START_HERE.md index 10e4b03e..b6b4c79b 100644 --- a/OFFICER_START_HERE.md +++ b/OFFICER_START_HERE.md @@ -35,12 +35,13 @@ Use the club's approved password manager for access. Share only a public link or ## A change is complete only when each line is answered - **Code changed:** What changed? -- **Tests passed:** What was checked? +- **Hosted frontend tests passed:** Did the `Frontend lint + build` job show a green `Run frontend Jest tests` step? Jest is the automated frontend behavior test. +- **Other tests passed:** What else was checked for this change? - **Code merged:** Which pull request was approved? - **Website live:** Was the exact change seen on [runmprc.com](https://runmprc.com)? - **Backend live:** If Firebase changed, did the log show a real Firebase deployment rather than “skipping” it? - **Outside service verified:** If Stripe, Netlify, DNS, Google, or email changed, was that service checked separately? -As of **2026-07-12**, GitHub Pages builds and the live Netlify site are separate. A green GitHub check does **not** by itself prove that `runmprc.com` or Firebase changed. +As of **2026-07-13**, hosted CI runs the frontend Jest suite, but GitHub Pages and the live Netlify site are still separate. A green test or workflow does **not** by itself prove that `runmprc.com` or Firebase changed. For the concise handbook, see [OFFICER_HANDBOOK.md](./OFFICER_HANDBOOK.md). The expanded task index is [docs/officers/README.md](./docs/officers/README.md). diff --git a/OPERATIONS_RUNBOOK.md b/OPERATIONS_RUNBOOK.md index 6e45193d..144377d4 100644 --- a/OPERATIONS_RUNBOOK.md +++ b/OPERATIONS_RUNBOOK.md @@ -177,7 +177,7 @@ npm --prefix functions run test:run -- --runInBand CI=true npm test -- --watchAll=false --runInBand ``` -The SPA navigation command is **NOT AVAILABLE YET** and belongs to #99. The frontend Jest command is a dependable local baseline, but a required CI quality gate is **NOT AVAILABLE YET** and remains under [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105). +The SPA navigation command is **NOT AVAILABLE YET** and belongs to #99. The frontend Jest command is a dependable local baseline and hosted CI runs it as the blocking `Run frontend Jest tests` step under [#124](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/124). Required branch protection, fail-closed lint, and protected deployment remain **NOT AVAILABLE YET** under [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105). ### Firestore Rules @@ -465,4 +465,6 @@ On the isolated #104 branch based at `ce22c110`, Functions lint and 17/17 Functi On the isolated #103 branch based at `0e03ac1`, Node 20 focused App tests pass 1/1 and the complete frontend suite on the branch passes 16/16. Changed-file lint, diff checks, and the diagnostic production build also pass. Service initialization and provider-network paths are prevented by test mocks; this was not a socket-monitored provider test, and the separately owned #99 Firebase/Sentry tests are not present on the branch. A separate read-only Node 20 compatibility run against the preserved #99 working tree passed those two suites 6/6, but that is not #103 branch or merge coverage. This proves a deterministic local baseline only. It does not prove a required CI gate, website publication, Firebase deployment, provider configuration, or production behavior. +Issue #124 adds that complete committed frontend suite to the hosted frontend job as the named, blocking `Run frontend Jest tests` step. Its pull-request and post-merge runs are the proof that the exact commits executed Jest. Even a green step does not prove branch protection, website publication, Firebase deployment, provider configuration, or production behavior. + Provider configuration, production secrets, Netlify publication, Firebase deployment, and live behavior always require separate dated evidence. Local tests and a green GitHub summary do not prove them. diff --git a/README.md b/README.md index 04527206..eee7556b 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ npm run test:rules CI=true DISABLE_ESLINT_PLUGIN=true npx --no-install react-scripts build ``` -Rules tests require Java 17. The direct `react-scripts build` command is useful for a diagnostic compile because the normal `npm run build` runs the sitemap generator and may intentionally update `public/sitemap.xml`. The SPA navigation command remains queued under #99. The frontend Jest command now provides a deterministic local baseline, but current CI does not run it as a required gate; [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105) owns that remaining workflow work. +Rules tests require Java 17. The direct `react-scripts build` command is useful for a diagnostic compile because the normal `npm run build` runs the sitemap generator and may intentionally update `public/sitemap.xml`. The SPA navigation command remains queued under #99. The frontend Jest command provides the deterministic local baseline and runs as the blocking `Run frontend Jest tests` step in hosted CI under [#124](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/124). [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105) still owns non-mutating lint, branch/deployment protection, credentials, staging, and the other incomplete delivery gates. ## Working on the platform diff --git a/SECURITY.md b/SECURITY.md index 42fc03d1..f26a2836 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -82,7 +82,7 @@ The findings below describe the repository at the start of the 2026-07-12 assess | RISK-032 | `auditLog` arrays grow within primary documents and are editable by broad admins. | Move to append-oriented, immutable-by-client audit records with retention/export rules. | | RISK-033 | CSV export mitigates formula injection, but roster export has no explicit re-auth, download audit, row limit/streaming limit, or data-minimization profiles. | Add scoped exports, reason/re-auth, audit, minimum columns, safe filename IDs, and large-export controls. | | RISK-034 | Webhook error response includes the Stripe library's signature error detail. | Return generic client errors; keep sanitized structured diagnostics server-side. | -| RISK-035 | The local frontend Jest baseline is deterministic, but CI does not run it as a required gate; CI's frontend lint step is still allowed to fail with `|| true`, and broader domain/integration coverage remains incomplete. | Make non-mutating lint/test gates mandatory and add domain/integration coverage. | +| RISK-035 | The deterministic frontend Jest suite runs as a blocking hosted CI step, but CI's frontend lint step still mutates files and is allowed to fail with `|| true`; branch protection and broader domain/integration coverage remain incomplete. | Make lint non-mutating and mandatory, prove required branch checks, and add domain/integration coverage. | | RISK-036 | Production and staging deployment topology is inconsistent in docs/workflows; backend deploy follows frontend and can silently skip when a secret is absent. | Define environment-protected deployments, deploy compatible backend first, fail required production stages closed, and add rollback evidence. | | RISK-037 | Account/registration deletion, export, retention, backup, and restore procedures are incomplete. | Approve retention matrix, automate minimization, support access/deletion requests, and test backup restoration. | | RISK-038 | Source-controlled secret scan is ad hoc; no continuous secret scanner, dependency update bot, SBOM, provenance, or branch protection is documented. | Add secret/dependency/code scanning, reviewed lockfile updates, protected environments/branches, and artifact provenance appropriate to project scale. | @@ -101,7 +101,7 @@ These entries are implementation evidence, not a production risk-acceptance deci | RISK-013 | PROMO-001 sets both current Checkout creators to `allow_promotion_codes: false`; the webhook quarantines nonzero discounts plus unconfigured tax/shipping totals. | Add exact creator-payload tests, inventory pre-change Sessions/provider promotion configuration, keep the guard through staging/deploy, and implement an authoritative discount/tax/shipping contract before ever enabling it. | | Part of RISK-024 | SEC-001 protects token documents from every browser client. | OAUTH-001 must still add transactional refresh/versioning, scope/account binding, disconnect/revocation, IAM/encryption decision, and redacted lifecycle audit. | | Part of RISK-027 | Firebase Analytics and Sentry do not initialize in local/test runtime in the working tree, even if production-looking public config is present. | Approve hosted consent/redaction/retention/replay policy, environment-specific configuration, payload inspection, and deploy evidence under OBS/DATA work. | -| Part of RISK-035 | The Jest environment is repaired, the stale frontend smoke test is replaced, and webhook lifecycle tests materially increase Functions coverage. | CI still needs fail-closed lint/test/rules gates and the broader TEST-001 suite. | +| Part of RISK-035 | The Jest environment is repaired, the stale frontend smoke test is replaced, and #124 adds the complete frontend suite as a named blocking step in the hosted frontend CI job. | Keep exact hosted evidence on #124; make lint non-mutating/fail-closed, prove required branch checks, and add the broader TEST-001 suite. | ## 5. Threat model diff --git a/docs/officers/GLOSSARY.md b/docs/officers/GLOSSARY.md index 0cf9def6..d37f9919 100644 --- a/docs/officers/GLOSSARY.md +++ b/docs/officers/GLOSSARY.md @@ -32,3 +32,4 @@ | Rollback or revert | A reviewed change that restores the last known-good version. | | DNS | The settings that direct `runmprc.com` to a website host. DNS changes can take the whole site offline. | | CI or workflow | Automated checks and build jobs in GitHub. Green means those jobs passed, not necessarily that production changed. | +| Jest | The automated test tool used to check frontend behavior before the website build. | diff --git a/docs/officers/PUBLISH_AND_CHECK.md b/docs/officers/PUBLISH_AND_CHECK.md index 3399eff9..fbde1c6a 100644 --- a/docs/officers/PUBLISH_AND_CHECK.md +++ b/docs/officers/PUBLISH_AND_CHECK.md @@ -1,15 +1,19 @@ # Review, Merge, and Check a Change -**Use this when:** a preview is approved and someone asks whether the change is live. +**Purpose:** Review one approved change, merge it safely, and record what did or did not become live. **Approver:** content owner for ordinary content; specialist owners listed in [Events, shop, members, and money](./EVENTS_SHOP_MEMBERS.md) for higher-risk work. +**Prerequisites:** an approved pull request aimed at `main`, its rollback note, access to its GitHub job details, and a platform maintainer available for merge and live verification. **Independent officer publication status:** **NOT AVAILABLE YET.** A platform maintainer must own the merge and live verification until the Netlify repository, branch, owner, build, preview, and rollback path are recorded and tested. ## Current deployment truth -As of **2026-07-12**: +As of **2026-07-13**: - Merging to `main` starts GitHub workflows. +- The `Frontend lint + build` job includes a job-failing step named `Run frontend Jest tests`. A failed step fails that job. +- Required branch protection is not proven. The Jest step does not by itself prevent someone with merge access from merging a failed change. +- The same job still has a lint command that can rewrite files and ignore failure. A green job is not proof that lint passed. - Merging therefore also authorizes an automatic GitHub Pages publication; there is no separate Pages approval today. - The GitHub repository currently opens stale, unprotected `dev` by default; use the explicit `main` branch and do not merge `dev` into `main` as a shortcut. - GitHub Pages builds a copy of the website. @@ -22,12 +26,15 @@ As of **2026-07-12**: 1. Open the pull request and confirm its destination says `main`. 2. Confirm it names one issue and one outcome. 3. Confirm another person or review agent approved it. -4. Confirm required tests are green without “ignored” failures. -5. Confirm the officer guide was updated when needed. -6. Read the rollback note. -7. Confirm you understand that a merge automatically publishes the GitHub Pages copy. -8. Ask the platform maintainer whether any outside automation may also publish from the merge. -9. Do not merge if either automatic publication is unacceptable or unknown. +4. Open the `Frontend lint + build` job. +5. Confirm `Run frontend Jest tests` is present and green. Stop if it is missing, skipped, or failed. +6. Confirm the other required test steps are green. +7. Ask the platform maintainer for separate non-mutating lint evidence when lint applies. Do not use the green job as lint proof. +8. Confirm the officer guide was updated when needed. +9. Read the rollback note. +10. Confirm you understand that a merge automatically publishes the GitHub Pages copy. +11. Ask the platform maintainer whether any outside automation may also publish from the merge. +12. Do not merge if either automatic publication is unacceptable or unknown. ## Netlify publication — NOT AVAILABLE YET @@ -49,15 +56,28 @@ Before a backup officer can publish independently, a claimed hosting issue must 1. Record the pull request number and merged commit. 2. Wait for the GitHub workflow to finish. 3. Read the job details, not only the green summary. -4. Look for “skipping Firebase deploy.” If present, mark the backend **not deployed**. -5. Ask the platform maintainer which commit Netlify says it deployed. -6. Open [runmprc.com](https://runmprc.com) in a private/incognito window. -7. Visit the exact changed page directly. -8. Check the requested text, link, image, or behavior. -9. Check one phone-sized view. -10. Check one normal computer view. -11. If Firebase or an outside service changed, ask its owner for separate dated proof. -12. Record the result using the checklist below. +4. Confirm the merged commit's `Run frontend Jest tests` step is green. Stop and escalate if it is missing, skipped, or failed. +5. Look for “skipping Firebase deploy.” If present, mark the backend **not deployed**. +6. Ask the platform maintainer which commit Netlify says it deployed. +7. Open [runmprc.com](https://runmprc.com) in a private/incognito window. +8. Visit the exact changed page directly. +9. Check the requested text, link, image, or behavior. +10. Check one phone-sized view. +11. Check one normal computer view. +12. If Firebase or an outside service changed, ask its owner for separate dated proof. +13. Record the result using the checklist below. + +## Expected result + +The named Jest step is green for both the pull-request commit and the merged commit. The delivery record separately says whether GitHub Pages, Netlify, `runmprc.com`, Firebase, and any outside provider were verified. + +## Stop conditions + +Stop and ask the platform maintainer if the pull request does not target `main`; approval or the rollback note is missing; the named Jest step is missing, skipped, or failed; publication is unexpected; the deployed commit is unknown; or any live surface disagrees with the merged change. + +## Success proof + +Keep the completed delivery record with links to the pull request, merged commit, and exact GitHub job details. Add dated, separately obtained proof for each live website, Firebase, or outside-provider surface that the change affected. ## Delivery record @@ -65,7 +85,8 @@ Before a backup officer can publish independently, a claimed hosting issue must Issue: Pull request: Merged commit: -Tests passed: +Hosted frontend Jest step: pass / fail / missing +Other tests passed: GitHub Pages published: yes / no / not relevant Netlify intended commit verified: yes / no / unknown runmprc.com verified: yes / no