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
8 changes: 6 additions & 2 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 | proposed | core security/payment/data children |
| 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 |
| 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,9 +1202,13 @@ 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:** Proposed
**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
**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.

### Problem

Before this planning pass, Functions had seven tests and about 20% line coverage; webhook tests covered only invalid signature/method. Firestore rule tests cover many paths but intentionally asserted unsafe admin access. There is no test proving the cross-system sagas under concurrency/retry/provider failure.
Expand Down
5 changes: 3 additions & 2 deletions GITHUB_ISSUE_SLICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de
| WEB-001D | owner_action; A–C | Execute controlled DNS cutover/rollback and retire old deploy path without enabling commerce. | Dated owner-approved cutover evidence. |
| 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-001A | ready; CI-001A | Add synthetic factories, signed Stripe helpers, production-project/live-key/network guards, and artifact scrubber. | Deliberate guard and redaction failures. |
| TEST-001B | proposed; A | Add Auth/Firestore/Functions emulator saga, RBAC, Rules, and App Check integration harness. | Repeatable local/CI demo-project run. |
| 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-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. |
| TEST-001E | owner_action; A–D, staging | Add browser/test-mode E2E and exact-commit release traceability report. | Redacted staging report; no live objects. |
Expand Down
1 change: 1 addition & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ 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. |
| 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
5 changes: 5 additions & 0 deletions functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,10 @@
"firebase-functions-test": "^3.1.0",
"jest": "^29.7.0"
},
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/testSupport/jestSafetySetup.js"
]
},
"private": true
}
18 changes: 9 additions & 9 deletions functions/stripeWebhook.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const crypto = require('crypto');
const { createSignedStripePayload } = require('./testSupport/testSafety');

jest.mock('firebase-admin', () => {
const store = new Map();
Expand Down Expand Up @@ -184,7 +184,7 @@ jest.mock('firebase-admin/firestore', () => {

const admin = require('firebase-admin');

const WEBHOOK_SECRET = 'whsec_testsecret';
const WEBHOOK_SECRET = 'stripe_webhook_synthetic_test_material';
process.env.ENVIRONMENT_NAME = 'test';
process.env.SITE_ORIGIN = 'https://runmprc.test';
process.env.STRIPE_SECRET_KEY = 'sk_test_testing';
Expand Down Expand Up @@ -297,16 +297,16 @@ function seedOrder(overrides = {}) {
}

function signedRequest(event, signatureOverride) {
const body = JSON.stringify(event);
const timestamp = Math.floor(Date.now() / 1000);
const signature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${body}`, 'utf8')
.digest('hex');
const header = signatureOverride || `t=${timestamp},v1=${signature}`;
const signedPayload = createSignedStripePayload({
event,
secret: WEBHOOK_SECRET,
timestamp,
});
const header = signatureOverride || signedPayload.signatureHeader;
return {
method: 'POST',
rawBody: Buffer.from(body),
rawBody: signedPayload.rawBody,
get: (name) => (name.toLowerCase() === 'stripe-signature' ? header : undefined),
};
}
Expand Down
15 changes: 15 additions & 0 deletions functions/testSupport/jestSafetySetup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const {
assertSafeTestEnvironment,
installNetworkGuard,
} = require('./testSafety');

assertSafeTestEnvironment(process.env);
installNetworkGuard();

beforeEach(() => {
assertSafeTestEnvironment(process.env);
});

afterEach(() => {
assertSafeTestEnvironment(process.env);
});
Loading
Loading