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
36 changes: 36 additions & 0 deletions SYSTEM_DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,42 @@ This contract invents no policy and duplicates no sibling. It owns the *member-f

The module is imported by no runtime or Functions index and makes nothing officer- or member-observable. It requires only `node:util` and `./membershipAuthority` (itself `node:util`-only), reads no clock or environment, calls no Firebase/Stripe/provider service, stores nothing, logs nothing, and changes no current profile/role/claim. Source tests and a merge are not Firebase deployment or live behavior proof.

### 8.0i Provider-link lifecycle reconciliation — SOURCE ONLY, UNUSED

MEMBERS-IDENTITY-001F [#445](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/445) defines one unused, pure, versioned snapshot contract and optimistic-concurrency reducer for the provider-neutral account link in §8.0e. It composes §8.0e's reviewed classifier for consent gating, collision, and desired-versus-observed drift instead of reproducing those decisions. The caller supplies the effective consent disposition already derived by §8.0d: only `active` maps to granted consent, `withdrawn` maps to withdrawn consent, and `reaffirmation_required` or `not_consented` maps to unknown consent. Changing that disposition does not silently request a provider action.

```mermaid
flowchart LR
I["Current lifecycle snapshot + exact command"] --> V{"Current revision and stable command?"}
V -- "Malformed, stale, or conflicting" --> X["One fixed error; no input echo"]
V -- "Exact latest retry" --> R["Same frozen snapshot"]
V -- "Valid new command" --> C{"Command type?"}
C -- "Consent or desired state" --> D["Update safe local intent"]
C -- "Reconciliation evidence" --> O{"Next ordered outcome?"}
C -- "Replace provider account" --> A{"Desired and observed unlinked?"}
O -- "Success" --> S["Advance the known observation"]
O -- "Definitive failure" --> F["Keep the last known observation"]
O -- "Outcome unknown" --> U["Keep desired state; mark observation unknown"]
A -- "Only confirmed unlinked" --> N["Reset observation for the new opaque account"]
A -- "Linked or unknown" --> X
D --> P["§8.0e classifies consent, collision, and drift"]
S --> P
F --> P
U --> P
N --> P
R --> Z["grantsAuthority: false"]
P --> Z
X --> Z
```

Text alternative: a well-formed current command either returns the same frozen snapshot for an exact latest retry or advances one revision; ordered success records a known observation, definitive failure preserves the last known observation, an unknown outcome invalidates the observation without changing intent, and a provider account can change only after confirmed unlink, while every result grants no authority.

The exact snapshot contains bounded typed membership and provider-account references, one existing provider enum, the effective consent disposition, desired and observed link state, optional collision evidence, a safe-integer revision, the last reconciliation sequence/outcome/typed attempt reference/fixed error code, and the latest stable command ID, payload hash, and expected revision. Creation requests `unlinked` but records provider observation as `unknown`; source never fabricates an external fact. Commands can change consent, request link or unlink, record the exact next reconciliation result, or replace the account after desired and observed state are both unlinked. A reconciliation command pins the current provider-account reference, desired state, record revision, and next per-account sequence, so a delayed link result cannot satisfy a later unlink or relink. Reversing an unresolved link or unlink intent invalidates the prior observation, preventing an in-flight action from making the record look aligned or replaceable. Success must report the requested known state; a foreign bound-membership reference remains collision evidence for §8.0e. Definitive failure keeps the prior observation, while outcome-unknown clears it. Account replacement resets observation and reconciliation to unknown/not-attempted for the new reference.

Inputs and every nested value are exact plain data objects: missing, extra, symbol, non-enumerable, inherited, accessor, proxy, malformed, out-of-range, stale, skipped, and conflicting shapes fail through one fixed non-echoing error. Purpose-specific prefixes reject raw phone, token, error, URL, and name values from reference fields; a payload hash must be the exact lowercase SHA-256 digest that the reducer recomputes over the canonical command type and safe payload fields. Outputs and nested records are frozen, and records and verdicts hard-code `grantsAuthority: false`. Exact latest retry is read-only. Reusing an ID with a changed type or payload produces another digest and fails; a changed expected revision fails the separate revision comparison. Durable all-history replay protection, cross-record uniqueness, storage transactions, and command authorization remain future trusted-runtime work.

This contract does not capture consent events or choose a policy-version order, retention rule, deletion service level, provider behavior, relink policy, or officer approval. It makes no provider call and adds no persistence, migration, Firestore schema or Rules, Auth claim, endpoint, route, interface, package, workflow, or deployment. It is imported by no runtime or Functions index, requires only deterministic `node:util`/`node:crypto` operations and the pure §8.0e classifier, and reads no clock, environment, randomness, network, service SDK, or logger. Parent [#81](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/81) remains open for those boundaries. Source changed, tests passed, code merged, website published, `runmprc.com` verified, Firebase deployed, outside provider configured, production data migrated, and production behavior verified are separate states; this source contract proves only the first two before merge.

### 8.1 Paid race registration

PAY-001B1 [#219](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/219) adds only the browser projection and first two server validation steps below. The website sends the active field set and omits volunteer tier. The callable preserves the opaque event ID, accepts an exact bounded envelope before Firestore, matches answers against the admitted selected server fields, and encodes callback values. It does not add the target request ID, snapshot, transaction, reservation, idempotent Session saga, safe confirmation capability, deployment, or live proof.
Expand Down
67 changes: 67 additions & 0 deletions docs/officers/EVENTS_SHOP_MEMBERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,73 @@ Officer review steps after the source merge:

**Escalation:** membership lead plus treasurer and privacy/security owner. Add the platform owner for source/deployment evidence and use the private incident path if real data or unintended access is involved.

## Provider-link lifecycle reconciliation — SOURCE ONLY, UNUSED

**Status: NOT AVAILABLE YET**

**Purpose:** define how a future provider-account record can distinguish a requested link or unlink from what the provider has confirmed, without treating email, Google, WhatsApp, Strava, or that record as proof of membership, discounts, payment, a website role, or officer access.

**Approver:** membership lead plus privacy/security and platform owners.

**Prerequisites:** issue [#445](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/445), its reviewed pull request, and its exact merge commit are required for source review. The pure classifier from [#367](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/367) and current-consent contract from [#370](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/370) are its source dependencies. Use only made-up references that contain no member or provider information. Approved data purpose and retention under #110, legacy migration under #113, authorization, cross-account uniqueness, storage, provider wiring, protected deployment, readback, and live verification remain future prerequisites.

```mermaid
flowchart TD
Start["Made-up current snapshot + command"] --> Check{"Exact and current?"}
Check -- "No" --> Stop["Fixed rejection; no private detail"]
Check -- "Exact latest retry" --> Same["Same frozen snapshot"]
Check -- "Valid new command" --> Kind{"Command type?"}
Kind -- "Consent or requested state" --> Local["Update safe local intent"]
Kind -- "Reconciliation evidence" --> Result{"Provider result"}
Kind -- "Change provider account" --> Replace{"Requested and confirmed unlinked?"}
Result -- "Success" --> Known["Record the requested known state"]
Result -- "Definitive failure" --> Keep["Keep the last known state"]
Result -- "Outcome unknown" --> Unknown["Keep the request; mark provider state unknown"]
Replace -- "Confirmed unlinked" --> Reset["Start the new account with unknown provider state"]
Replace -- "Linked or unknown" --> Stop
Same --> NoAuthority["Never grants authority"]
Local --> NoAuthority
Known --> NoAuthority
Keep --> NoAuthority
Unknown --> NoAuthority
Reset --> NoAuthority
Stop --> NoAuthority
```

Text alternative: the future source rejects malformed or stale input, treats an exact latest retry as read-only, handles local intent, provider evidence, and account replacement as separate commands, preserves uncertainty instead of guessing success, permits replacement only after confirmed unlink, and never grants membership or any other authority.

Backup-officer source-review steps:

1. Keep this procedure marked **NOT AVAILABLE YET**.
2. Obtain the exact #445 issue, reviewed pull request, merge commit, and synthetic test report.
3. Confirm the report uses only made-up references and labels that contain no name, email, phone, provider identifier, URL, error, or token.
4. Confirm the made-up test matrix applies the same provider-neutral contract to email/password, Google, WhatsApp, and Strava values; no live provider uses it yet.
5. Confirm a new snapshot requests unlinked state but marks the provider observation unknown.
6. Confirm the existing classifier blocks link action unless the current consent result is active; ordered provider evidence may still be recorded without granting authority.
7. Confirm a consent change does not silently make a provider call or create an unlink request.
8. Confirm an exact latest command retry returns the same frozen record. The source recomputes a SHA-256 fingerprint, which is a fixed-length one-way summary of the command type and safe payload fields; it checks the expected record version separately.
9. Confirm a changed command with the same ID, stale version, skipped result number, wrong account, reversed in-flight request, or delayed link/unlink result is rejected or marked unknown with one fixed safe boundary.
10. Confirm success records only the requested known state.
11. Confirm a definitive failure keeps the last known state and stores only a fixed error code.
12. Confirm an unknown outcome keeps the requested state but marks provider observation unknown.
13. Confirm a different provider account is accepted only after unlink is both requested and confirmed.
14. Confirm the replacement starts with unknown provider state and cannot accept a delayed result for the old account.
15. Confirm collision, consent, and drift decisions come from the already reviewed #367 classifier.
16. Confirm every record and verdict says it grants no authority.
17. Confirm the module has no runtime import, provider call, database action, claim or role change, route, interface, migration, deployment, log, or production record.

**Expected result:** the unused synthetic contract can represent ordered link, unlink, relink, failure, uncertainty, collision, and safe account replacement without granting authority. Current signup, membership, discounts, email/password, Google, WhatsApp, Strava, officer screens, provider accounts, and website behavior remain unchanged.

**Stop conditions:** any real member or provider data; a raw provider error, response, URL, token, email, phone, name, or screenshot; a production inspection; a manual database or provider action; a request to choose consent, retention, relink, or migration policy; missing prerequisite evidence; or a claim that source, tests, a pull request, merge, or green workflow makes this live.

**Success proof:** exact #445 issue, pull request, reviewed merge commit, focused and full test/lint reports, and the source-isolation scan. Record website publication, `runmprc.com` verification, Firebase deployment, outside-provider configuration, production-data changes, migration, and live behavior separately as **not performed** for this source-only issue.

**Undo:** before runtime adoption, use one reviewed revert or safe roll-forward for the two unused module/test files and these named documentation sections. No production record repair exists. Any future runtime child must provide its own data-safe rollback.

**Escalation:** membership lead plus privacy/security and platform owners. Use the private incident route if real data, unintended authority, or a provider action appears.

No system-topology map changes are required because this unused contract changes no data movement, permissions, account ownership, or deployment topology.

## My Account membership truth — SOURCE ONLY, NOT LIVE

**Status: NOT AVAILABLE YET**
Expand Down
Loading