Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,108 changes: 1,108 additions & 0 deletions .github/scripts/scan-test-artifacts.mjs

Large diffs are not rendered by default.

18 changes: 17 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
ruby -e 'require "yaml"; YAML.safe_load(File.read(".github/workflows/deploy.yml"), permitted_classes: [], permitted_symbols: [], aliases: true)'
ruby -e 'require "yaml"; YAML.safe_load(File.read(".github/workflows/ci.yml"), permitted_classes: [], permitted_symbols: [], aliases: true)'
node --test tests/ci-workflow.test.js tests/release-workflow.test.js tests/firebase-release-verification.test.js
node --test tests/ci-workflow.test.js tests/release-workflow.test.js tests/firebase-release-verification.test.js tests/test-artifact-safety.test.js
- run: npm run lint:fix -- --max-warnings=0 || true
- name: Build
env:
Expand All @@ -39,6 +39,22 @@ jobs:
REACT_APP_SENTRY_DSN: ${{ secrets.REACT_APP_SENTRY_DSN }}
run: npm run build

test-artifact-scrubber:
name: Test artifact scrubber
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: actions/setup-node@v6
with:
node-version: '20'
- name: Run emitted test artifact safety tests
run: node --test tests/test-artifact-safety.test.js

functions:
name: Cloud Functions lint + test
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ jobs:
"Frontend lint + build" \
"Cloud Functions lint + test" \
"Commerce command journal emulator" \
"Test artifact scrubber" \
"Firestore security-rules tests"
do
if ! jq -e --arg name "$required_job" '
Expand Down Expand Up @@ -393,6 +394,7 @@ jobs:
"Frontend lint + build" \
"Cloud Functions lint + test" \
"Commerce command journal emulator" \
"Test artifact scrubber" \
"Firestore security-rules tests"
do
if ! jq -e --arg name "$required_job" '
Expand Down
6 changes: 3 additions & 3 deletions GITHUB_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Every issue inherits `AGENTS.md` and the definition of done in `IMPLEMENTATION_P
| 24 | WEB-001 | Move to controlled hosting and add browser security policy | P1 | L | proposed | SAFETY-001, CI-001 |
| 25 | OBS-001 | Add payment observability, alerts, SLOs, and redaction | P1 | M | proposed | PAY-003, PAY-005 |
| 26 | RESILIENCE-001 | Establish backup, restore, retention, and audited repair | P1 | L | proposed | DATA-001, PAY-005 |
| 27 | TEST-001 | Build the Stripe/Firebase security integration and E2E suite | P0 | L | in progress through #175; most children proposed | core security/payment/data children |
| 27 | TEST-001 | Build the Stripe/Firebase security integration and E2E suite | P0 | L | in progress through #177; most children proposed | core security/payment/data children |
| 28 | LEGAL-001 | Approve legal, tax, insurance, privacy, refund, and fulfillment policy | P0 | M | blocked_owner_decision | — |
| 29 | OPS-001 | Configure production systems and run a controlled live pilot | P0 | L | blocked by all launch gates | CI-001, TEST-001, LEGAL-001, OBS-001, RESILIENCE-001 |

Expand Down Expand Up @@ -1202,12 +1202,12 @@ Cloud backup configuration changes external state and needs an authorized owner.
## TEST-001 — Build the Stripe/Firebase security integration and E2E suite

**Labels:** `priority:P0`, `type:testing`, `type:security`, `area:stripe`, `area:firebase`, `size:L`
**Status:** In progress through focused child [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175); the wider integration/E2E program remains proposed
**Status:** In progress through focused children [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175) and [#177](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/177); the wider integration/E2E program remains proposed
**Depends on:** Core SEC/AUTH/ABUSE/PAY/RACE/MERCH/MAIL/DATA work

### Current child status

TEST-001A is split so a small safety foundation can be reviewed before any CI artifact or end-to-end expansion. TEST-001A1 is tracked in [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175): Functions tests receive deterministic reserved fixtures, one shared synthetic Stripe signer, fail-closed checks for supplied production/live configuration, and a Node transport guard that permits only loopback emulator targets. TEST-001A2 remains proposed for bounded emitted-artifact scanning and named CI/release wiring. Neither child authorizes provider calls, production data, Firebase deployment, or live payment testing.
TEST-001A is split so a small safety foundation can be reviewed before any end-to-end expansion. TEST-001A1 merged through [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175) as `e6d8929698b95ddcda78b00108cc7665bf9f5e01`: Functions tests receive deterministic reserved fixtures, one shared synthetic Stripe signer, fail-closed checks for supplied production/live configuration, and a Node transport guard that permits only loopback emulator targets. TEST-001A2 is tracked in [#177](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/177) for a bounded emitted-artifact scanner, its deliberate synthetic test suite, one exact named CI job, and both protected-release job lists. It uploads no artifact. Neither child authorizes provider calls, production data, Firebase deployment, or live payment testing.

### Problem

Expand Down
2 changes: 1 addition & 1 deletion GITHUB_ISSUE_SLICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de
| RESILIENCE-001A | owner_action; DATA-001B, LEGAL-001 | Inventory RPO/RTO and configure least-privilege monitored backup/export retention. | Private access review and scheduled backup success. |
| RESILIENCE-001B | proposed; A, staging | Restore into isolated no-live-Stripe/email/DNS project and validate rules/indexes/counts/references/reconciliation. | Dated timed restore drill and no-external-side-effect proof. |
| TEST-001A1 | delivery tracked in [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175); CI-001A | Add the Functions-only deterministic synthetic factories, shared Stripe signer, supplied-environment rejection, and loopback-only Node test-network guard. | Deliberate unsafe environment/transport failures, fixed redacted errors, existing webhook adoption, full Functions suite, and loopback emulator proof; no runtime/provider claim. |
| TEST-001A2 | proposed; A1 | Add the bounded emitted-artifact scrubber and make its deliberate allow/deny suite a named CI and protected-release gate. | Synthetic artifact fixtures, exact workflow checks, and no source/canary false-positive proof. |
| TEST-001A2 | source/tests tracked in live [#177](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/177); A1 | Add the bounded emitted-artifact scrubber and make its deliberate allow/deny suite the exact `Test artifact scrubber` CI and protected-release gate; upload nothing. | Synthetic artifact fixtures, fixed redacted failures, exact workflow mutation checks, and no source/canary false-positive proof. |
| TEST-001B | proposed; A1–A2 | Add Auth/Firestore/Functions emulator saga, RBAC, Rules, and App Check integration harness. | Repeatable local/CI demo-project run. |
| TEST-001C | proposed; B, race/merch reducers | Add deterministic capacity/inventory concurrency and every local/Stripe failure-boundary test. | Repeated no-flake invariant matrix. |
| TEST-001D | proposed; B, PAY-003/PAY-005 | Add signed Stripe lifecycle, duplicate/reorder, async, refund/dispute/reconcile fixtures. | Risk/invariant traceability and coverage thresholds. |
Expand Down
1 change: 1 addition & 0 deletions OFFICER_START_HERE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Use the club's approved password manager for access. Share only a public link or
- **Code changed:** What changed?
- **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.
- **Hosted payment-safety test passed:** Did the `Commerce command journal emulator` job finish green? This check uses made-up records in a closed test database.
- **Hosted test-output safety check passed:** Did the `Test artifact scrubber` job finish green? It proves the deliberate made-up output scan ran. It does not prove that a report was uploaded or that a live service changed.
- **Other tests passed:** What else was checked for this change?
- **Code merged:** Which pull request was approved?
- **Release approved:** Which environment, exact commit, and named approver were recorded?
Expand Down
3 changes: 2 additions & 1 deletion OPERATIONS_RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,10 @@ npm --prefix functions run lint
npm --prefix functions run test:run -- --runInBand
CI=true npm test -- --watchAll=false --runInBand
npm run test:spa-navigation
node --test tests/test-artifact-safety.test.js
```

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). Hosted CI also runs the separate Node SPA suite as `Run SPA callback safety tests` under [#126](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/126). CI-001B3 [#167](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/167) adds the blocking `Commerce command journal emulator` job. That job uses exact demo project `demo-pay002b2-test`, Firestore only, an explicit opt-in, and the focused transaction suite. The protected release source gate requires that named job both before artifact work and after approval. Its green result proves synthetic transaction behavior, not Firebase deployment or Stripe behavior. The manual-release source invariants remain under [#135](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/135). Protected environment/OIDC configuration, actual staged/live deployment, fail-closed lint, branch-required-check configuration, and controlled Netlify publication remain **NOT AVAILABLE YET** under [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105), [#133](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/133), [#136](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/136), and WEB-001.
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). Hosted CI also runs the separate Node SPA suite as `Run SPA callback safety tests` under [#126](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/126). CI-001B3 [#167](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/167) adds the blocking `Commerce command journal emulator` job. That job uses exact demo project `demo-pay002b2-test`, Firestore only, an explicit opt-in, and the focused transaction suite. TEST-001A2 [#177](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/177) adds the exact `Test artifact scrubber` job. It deliberately creates bounded synthetic output and proves that the dependency-free scanner accepts reserved examples, rejects the documented recognizable sensitive patterns with fixed messages, ignores source outside an explicit output root, and protects both release job lists. Current CI uploads no test report. Later report-producing work must scan its explicit output before upload. A green scrubber proves only that this deliberate source test ran. It is not a general data-loss-prevention guarantee and does not prove that an unknown or newly obfuscated sensitive value is absent, that an artifact was uploaded, that all runtime logs are safe, or that Firebase, Stripe, the website, or another provider changed. The manual-release source invariants remain under [#135](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/135). Protected environment/OIDC configuration, actual staged/live deployment, fail-closed lint, branch-required-check configuration, and controlled Netlify publication remain **NOT AVAILABLE YET** under [#105](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/105), [#133](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/133), [#136](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/136), and WEB-001.

### Firestore Rules

Expand Down
3 changes: 2 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ These entries are implementation evidence, not a production risk-acceptance deci
| RISK-006, part of RISK-024/RISK-032 | #100 merged at `a7fc301e85b0aeabe396e771faea21d3fc8e7b2b`. OAuth secrets and server-owned financial/operational collections are denied; current catalog writes are restricted to inert drafts/display fields. | Firebase deployment skipped. Stage/deploy the exact Rules revision under #105, verify synthetic deny behavior, then move remaining catalog mutation to scoped APIs under ADMIN-001. |
| RISK-009 | #99 preserves same-origin path, query, and fragment state through the Pages fallback, clears temporary state, rejects unsafe targets, and suppresses monitoring startup on initial capability callbacks. #126 adds the standalone suite as the named blocking `Run SPA callback safety tests` hosted step. | Keep exact hosted evidence on #126; verify exact website publication and later run approved test-mode Stripe/Strava callbacks; WEB-001 still owns controlled hosting. |
| RISK-010 | #99 uses a fully synthetic `demo-mprc-local` configuration, connects Functions/Auth/Firestore to loopback in development/test, routes the direct CSV Function URL locally, fails startup on connector errors, and completed a demo-only three-port CLI smoke. | Current optimized previews still target production; provider calls are not isolated by Firebase. Add protected staging/config and test-provider/sink evidence before end-to-end flows. |
| Test-only foundation for RISK-010 and RISK-035 | TEST-001A1 is tracked in live [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175). The Functions Jest setup installs a fixed-error, loopback-only guard around supported Node outbound transports and rejects any supplied production-like project/origin/emulator host or live Stripe mode/key. Shared deterministic deeply frozen fixtures use reserved values, and the existing webhook suite adopts one synthetic signed-payload helper. | This is a test-process boundary, not a runtime sandbox. It does not intercept every possible native/add-on transport, isolate an emulated Function process, configure a test provider, scan emitted artifacts, deploy Firebase, or prove live behavior. TEST-001A2 must add the bounded artifact scrubber and named CI/release gate; later TEST-001 children must add emulator sagas and isolated staging evidence. |
| Test-only foundation for RISK-010 and RISK-035 | TEST-001A1 is tracked in live [#175](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/175). The Functions Jest setup installs a fixed-error, loopback-only guard around supported Node outbound transports and rejects any supplied production-like project/origin/emulator host or live Stripe mode/key. Shared deterministic deeply frozen fixtures use reserved values, and the existing webhook suite adopts one synthetic signed-payload helper. | This is a test-process boundary, not a runtime sandbox. It does not intercept every possible native/add-on transport, isolate an emulated Function process, configure a test provider, scan emitted artifacts, deploy Firebase, or prove live behavior. TEST-001A2 [#177](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/177) separately adds the bounded artifact scrubber and named CI/release gate; later TEST-001 children must add emulator sagas and isolated staging evidence. |
| Emitted-test-output part of RISK-035 | TEST-001A2 is tracked in live [#177](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/177). Its source adds a dependency-free read-only scanner for explicit narrow artifact roots, bounded deterministic traversal, fixed redacted failures, deliberate synthetic allow/deny tests, the exact `Test artifact scrubber` CI job, and that job in both protected-release CI rechecks. Current CI still uploads no test artifact. | This scanner covers a documented bounded set of recognizable patterns; green is not a general data-loss-prevention guarantee or proof that every unknown/obfuscated value is absent. It does not inspect source, runtime logs, website builds, provider responses, production data, or an operating-system sandbox, and it does not sanitize a rejected file. Every later report producer must invoke the scanner before upload, and exact hosted evidence remains separate from source and local-test evidence. |
| Configuration part of RISK-001/RISK-010 | CONFIG-001A [#149](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/149) merged through PR #150 as `2c62b8dd`, requiring an exact environment/origin/expected Stripe mode, key-mode compatibility on the four key-bound Functions, no production-origin fallback, and no Stripe API key on webhook/mail. CONFIG-001B1 [#151](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/151) adds exact `COMMERCE_ENABLED` parsing. A false ceiling denies new commerce before Firestore; otherwise new-commerce commands and every refund perform a fresh strict server-only global/domain/resource admission read. Missing controls/resource flags mean disabled; fixed errors expose no supplied value; Rules tests deny browser control; webhook/mail remain independent. | Neither source result configures or deploys Firebase/Stripe. B1 cannot stop already-admitted commands or existing Sessions/Payment Links and has no safe operator writer. CONFIG-001B2, PAY-002/PAY-004/PAY-005, and #105/#133/#136 retain protected control, expiry/reconciliation, staging, deployment, provider readback, and drill. No live payment or email is authorized. |
| Part of RISK-007 | AUTH-001A [#98](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/98) was merged through [PR #107](https://github.com/Run-MPRC/Run-MPRC.github.io/pull/107) as `ce22c110f2132b157bd8a0d43b065585e0b43cb5`. Source and focused tests reject unverified targets at the two existing role-grant endpoints. | The workflow skipped Firebase because `FIREBASE_SERVICE_ACCOUNT` was absent, so backend-live behavior is unproven. Remaining AUTH-001 guards, Rules, verification mirror/refresh, demotion propagation, audit, and authoritative membership work stay open. |
| RISK-013 | PROMO-001 [#102](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/102) sets both current Checkout creators to promotion entry off and automatic tax off. Exact payload and signed event tests require an explicit all-zero breakdown; malformed or nonzero discount, tax, or shipping data creates durable review evidence while definitive failed/expired Sessions still cancel. | Privately inventory pre-change Sessions/provider promotion settings, keep the guard through protected staging/deploy, verify provider and live state separately, and implement an approved authoritative discount/tax/shipping contract before ever enabling it. |
Expand Down
Loading
Loading