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
31 changes: 30 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ jobs:
- name: Validate protected release workflow
run: |
ruby -e 'require "yaml"; YAML.safe_load(File.read(".github/workflows/deploy.yml"), permitted_classes: [], permitted_symbols: [], aliases: true)'
node --test tests/release-workflow.test.js tests/firebase-release-verification.test.js
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
- run: npm run lint:fix -- --max-warnings=0 || true
- name: Build
env:
Expand Down Expand Up @@ -58,6 +59,34 @@ jobs:
# firebase-admin so no emulator is needed.
- run: npm run test:run

commerce-command-journal:
name: Commerce command journal emulator
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '20'
cache: 'npm'
- uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'
- name: Install committed root dependencies
run: npm ci --legacy-peer-deps --ignore-scripts
- name: Install committed Functions dependencies
run: npm --prefix functions ci --ignore-scripts
- name: Run commerce command journal concurrency tests
env:
REQUIRE_COMMERCE_COMMAND_JOURNAL_EMULATOR: '1'
run: >-
npx --no-install firebase emulators:exec
--project demo-pay002b2-test
--only firestore
"npm --prefix functions run test:run --
--runInBand commerceCommandJournal.emulator.test.js"

firestore-rules:
name: Firestore security-rules tests
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 @@ -112,6 +112,7 @@ jobs:
for required_job in \
"Frontend lint + build" \
"Cloud Functions lint + test" \
"Commerce command journal emulator" \
"Firestore security-rules tests"
do
if ! jq -e --arg name "$required_job" '
Expand Down Expand Up @@ -391,6 +392,7 @@ jobs:
for required_job in \
"Frontend lint + build" \
"Cloud Functions lint + test" \
"Commerce command journal emulator" \
"Firestore security-rules tests"
do
if ! jq -e --arg name "$required_job" '
Expand Down
8 changes: 4 additions & 4 deletions GITHUB_ISSUES.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,12 @@ Do not redesign routing or hosting in this issue; WEB-001 owns that. Optimized p
## 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). [#103](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/103), [#124](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/124), and [#126](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/126) provide the local/hosted frontend and SPA baselines. [#135](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/135) owns the manual exact-commit, backend-first source gate and Git-triggered Netlify production containment. [#133](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/133) owns protected OIDC/environment configuration, and [#136](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/136) owns the actual profile-recovery release. Fail-closed lint, required checks, scanning, staging/live evidence, and protected Netlify publication remain open, so the pipeline is still non-compliant overall.
**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), [#124](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/124), and [#126](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/126) provide the local/hosted frontend and SPA baselines. CI-001B3 [#167](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/167) owns the dedicated hosted command-journal Firestore transaction gate. [#135](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/135) owns the manual exact-commit, backend-first source gate and Git-triggered Netlify production containment. [#133](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/133) owns protected OIDC/environment configuration, and [#136](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/136) owns the actual profile-recovery release. Fail-closed lint, branch-required-check configuration, scanning, staging/live evidence, and protected Netlify publication remain open, so the pipeline is still non-compliant overall.
**Depends on:** SAFETY-001

### Problem

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`. #135 removes the automatic/fail-open release source defects: merge and release are separate, exact CI checks are re-read, release targets are fixed, OIDC replaces JSON-key wiring, lockfile tooling is used, backend precedes Pages, and Git-triggered Netlify production builds stop. The protected identity/environments and actual staged/live release remain outside that source slice.
Before #103, frontend tests failed because the Jest environment lacked `TextEncoder`. That child repaired the local baseline, and #124 adds it to hosted CI. #167 adds a separate named Node 20/Java 17 job for the PAY-002B2A Firestore transaction suite and makes both protected-release CI reads require it. The job uses one explicit demo project, Firestore only, committed lockfiles, and no cloud/provider authority. CI still runs a mutating `lint:fix` command and ignores its failure with `|| true`. #135 removes the automatic/fail-open release source defects: merge and release are separate, exact CI checks are re-read, release targets are fixed, OIDC replaces JSON-key wiring, lockfile tooling is used, backend precedes Pages, and Git-triggered Netlify production builds stop. The protected identity/environments and actual staged/live release remain outside that source slice.

### Scope

Expand Down Expand Up @@ -179,7 +179,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. CI-001A/#103 owns test reliability, CI-001B1/#124 owns hosted frontend Jest, CI-001B1A/#126 owns hosted SPA safety, CI-001B2/#135 owns the protected release source gate, #133 owns cloud/environment authority, and #136 owns staged/target release evidence. Keep fail-closed lint, scanning, required checks, and Netlify hosting work in separately claimed children.
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 hosted frontend Jest, CI-001B1A/#126 owns hosted SPA safety, CI-001B2/#135 owns the protected release source gate, CI-001B3/#167 owns the focused command-journal emulator gate, #133 owns cloud/environment authority, and #136 owns staged/target release evidence. Keep fail-closed lint, scanning, branch-required-check configuration, and Netlify hosting work in separately claimed children.

---

Expand Down Expand Up @@ -633,7 +633,7 @@ PAY-002A1 defines only a dependency-free version-1 target: separate payment, reg

The next boundaries remain separate. A later inventory/migration child must use #113-approved data categories and a dry-run before writes. PAY-002B1 [#163](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/163) owns only pure caller-scoped command keys, payload fingerprints, and deterministic Stripe keys with closed environment/mode pairing. A provider attempt is one logical generation, not an HTTP retry. PAY-002B2A [#165](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/165) owns only the atomic `checkoutRequests/{commandKeyHash}` registered record plus deterministic revision-1 `auditEvents` partner. Exact existing pairs are read-only; same-key command-type/schema/payload conflicts and malformed pairs reject. Environment and caller scope derive different B1 keys; there is no cross-scope UUID query. B2A adds no lease, execute/send permission, result replay, provider plan/attempt, or reconciliation. PAY-002B2B owns leases/fencing, stale-worker rejection, terminal pointers/fixed final failure, and transition audit without provider-send permission. PAY-002B2C owns immutable provider-plan binding, safe-send cutoff, ambiguous outcomes, reconciliation, and safe provider-attempt advancement. PAY-002C/D, PAY-003B, RACE-001B, MERCH-001B, PAY-004, and PAY-005 depend on B2C.

B2A adds no TTL. Deletion could re-enable an old command, so [#110](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/110) must approve retention and a server-only tombstone or equivalent durable duplicate barrier before any journal pair is removed. #165's concurrent proof is dedicated local-emulator evidence; hosted Functions CI does not start its exact demo project or set the explicit suite opt-in, and the standard differently named demo run safely skips it. No #165 endpoint/index export, Firebase deployment, Stripe/provider configuration, production read/write, or officer behavior exists.
B2A adds no TTL. Deletion could re-enable an old command, so [#110](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/110) must approve retention and a server-only tombstone or equivalent durable duplicate barrier before any journal pair is removed. CI-001B3 [#167](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/167) runs #165's exact demo-project/opt-in transaction suite as a separate hosted job and requires it in protected-release CI evidence. That hosted result remains synthetic source proof only. No #165 endpoint/index export, Firebase deployment, Stripe/provider configuration, production read/write, or officer behavior exists.

### Problem

Expand Down
3 changes: 2 additions & 1 deletion GITHUB_ISSUE_SLICES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de
| CI-001B1 | merged/closed 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. | Exact pull-request and post-merge hosted steps passed; Firebase skipped and Netlify exact production commit remained unverified. |
| CI-001B1A | merged/closed as #126; #99 and CI-001B1 | Run the standalone same-origin SPA callback suite as a separate blocking hosted frontend step. | Local deliberate-failure proof plus the named hosted step passing on the exact pull-request and post-merge commits; no provider callback claim. |
| CI-001B2 | published as #135; CI-001B1 | Provide the tested manual exact-commit source gate: fixed Rules/Functions, lockfile CLI, pinned Actions, short-lived-auth wiring, backend-first Pages dependency, missing-config failure, no frontend credential, and Netlify Git-production containment. | Source/static negative tests and exact PR evidence. #133 separately owns protected OIDC/environment configuration; #136 owns staged/target release; WEB-001 owns protected Netlify publication. |
| CI-001B3 | source/tests tracked in live [#167](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/167); PAY-002B2A/#165 | Run the dedicated command-journal Firestore transaction suite as one named blocking Node 20/Java 17 job with exact demo project, explicit opt-in, Firestore-only scope, committed tooling, and no secrets/provider authority; require it at both protected-release CI reads. | Static negative workflow tests plus exact pull-request and post-merge hosted six-test evidence; no Firebase deployment, Stripe, website, or live claim. |
| SUPPLY-001A | published as [#127](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/127); 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. |
Expand Down Expand Up @@ -63,7 +64,7 @@ An agent-ready child has one observable outcome, one trust boundary, explicit de
| PAY-002A1 | source/tests tracked in live [#161](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/161); PAY-001A; no runtime adoption/migration/deploy | Build pure version-1 payment/registration/fulfillment/confirmed-refund/per-dispute reducers, cross-dimension validation, and a synthetic legacy classifier/redacted aggregate report. | Exhaust every state pair, retry/reorder/terminal/composite/legacy/hostile-input case; no Firebase/Stripe/logger call or record patch. |
| PAY-002A2 | proposed; PAY-002A1, #113 owner-approved inventory | Use an owner-approved private read-only inventory for any real legacy/provider references (no mutation/export or copying into tests/issues), define one context-aware compatibility derivation, and use only synthetic emulator fixtures for the dry-run/idempotent migration plan. | Redacted counts/reasons for every approved fixture; repeat synthetic dry-run is identical; no production write until separately approved. |
| PAY-002B1 | source/tests tracked in live [#163](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/163); PAY-002A1; no journal/runtime/deploy | Define the pure caller-scoped command-key, UUID/payload-fingerprint, and deterministic Stripe-key contract. The command key excludes command type so B2 can reject cross-operation ID reuse; environment/mode pairs fail closed; provider attempt means one logical generation and survives lease/HTTP retry. | Canonical UUID, golden length-framed digests, environment/mode and dimension separation, hostile frozen payload, key-length/raw-value absence, immutability, and no-side-effect tests. |
| PAY-002B2A | source/tests tracked in live [#165](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/165); PAY-002B1; unused/no runtime or deploy | Atomically create one immutable `registered` command and deterministic revision-1 audit partner, return a fixed read-only exact-existing classification, and reject same-key type/schema/payload conflicts or malformed pairs. Environment/caller changes derive another B1 key; stored mismatches are corruption. No lease, execute/send permission, result replay, provider, or reconciliation API. | Mocked transaction and dedicated opt-in demo-emulator concurrent pair/conflict/orphan/failure tests; hosted Functions CI does not run that opt-in suite and the standard demo run safely skips it. |
| PAY-002B2A | source/tests tracked in live [#165](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/165); PAY-002B1; unused/no runtime or deploy | Atomically create one immutable `registered` command and deterministic revision-1 audit partner, return a fixed read-only exact-existing classification, and reject same-key type/schema/payload conflicts or malformed pairs. Environment/caller changes derive another B1 key; stored mismatches are corruption. No lease, execute/send permission, result replay, provider, or reconciliation API. | Mocked transaction plus dedicated opt-in demo-emulator concurrent pair/conflict/orphan/failure tests; CI-001B3 [#167](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/167) adds the exact suite as a hosted release prerequisite. |
| PAY-002B2B | proposed; PAY-002B2A | Add leases, monotonic fence epochs, stale-worker rejection, terminal server-only pointers/fixed final failure, and append-oriented transition audit without provider-send permission. | Concurrent lease/takeover/stale fence, terminal replay-pointer, fixed-failure, and transaction-retry emulator tests. |
| PAY-002B2C | proposed; PAY-002B2B | Bind an immutable Stripe account/sandbox/API-version/endpoint/operation/mode/parameters plan, attempt/key, and pre-POST first-send evidence; stop old/unknown automatic POST, record ambiguity, reconcile verified evidence, and advance only a proven-safe logical attempt. | Exact-plan/key reuse, timeout/5xx/unknown-send cutoff, conflicting-plan, old-key, reconciliation, and safe/unsafe attempt-advance emulator/provider-fixture tests. |
| PAY-002C | proposed; PAY-001B, PAY-002B2C, RACE-001B | Convert race checkout to persistence-first record/hold plus deterministic Stripe Session saga. | One record/Session on retry at every failure boundary. |
Expand Down
1 change: 1 addition & 0 deletions OFFICER_START_HERE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,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.
- **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
Loading
Loading