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
26 changes: 26 additions & 0 deletions OPERATIONS_RUNBOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,30 @@ Required release order:

If the website arrives before `ensureMemberProfile` or the matching Rules, the intended safe result is a temporary-unavailable message with Edit hidden. Roll back the website or safely roll forward the reviewed backend. Never release the callable while the old signup trigger remains: that trigger can overwrite a recovered profile or replace claims. Deploy the two revised Functions together, or stop and roll back the partial backend release. Do not create, delete, overwrite, or re-role a production account in Firebase Console.

### Registration email outcome — SOURCE ONLY, NOT LIVE

AUTH-MAIL-002A [#145](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/145) separates three transitions:

1. Account creation fails: reject the operation and show one generic create-account error.
2. Account creation succeeds and Firebase accepts the verification request: preserve the signed-in account and report `accepted`; do not claim delivery.
3. Account creation succeeds and Firebase rejects the verification request: preserve the signed-in account, report `unavailable`, emit only the fixed `email_verification_failed` diagnostic, and offer My Account as an inspection path. If My Account is unavailable, stop and keep the account. Do not advertise the existing resend action as proven.

The source and tests do not change Firebase Auth, email templates, DNS, sender branding, or mailbox/provider settings. They do not send a network request in tests. Do not test this flow with a production mailbox or a real member.

Release and evidence order:

1. Review the exact source and synthetic mocked tests.
2. Merge the exact reviewed commit.
3. Publish that frontend revision only through the approved website release path.
4. Verify the hosting record and the exact `runmprc.com` revision separately.
5. Before calling the linked recovery usable, verify the exact [#118](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/118) Rules, Functions, and profile page plus #120's truthful resend result/cooldown child. An unavailable My Account page is a stop result.
6. Use an isolated staging Firebase project and approved safe email sink before any end-to-end test.
7. Record request acceptance separately from message delivery, Spam placement, and sender configuration.
8. Keep provider/DNS/template work under [#119](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/119).
9. Keep profile-independent resend/cooldown/session recovery and password/action-code recovery under parent [#120](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/120). The current Resend success message is not delivery proof.

Rollback is a reviewed frontend revert or safe roll-forward. Do not delete or recreate an Auth account because the verification request failed.

## 17. Verification evidence boundaries

The earlier combined pre-extraction working tree reported 7 frontend tests, 4 SPA callback tests, 45 Functions tests, and 185 Firestore Rules tests. Those numbers combine queued #99, #100, #101, and #103 work. They are historical planning evidence only and are **not reproducible proof for #104 or current `main`**.
Expand All @@ -556,4 +580,6 @@ For OBS-001A2 [#139](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/139),

For OBS-001A3 [#142](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/142), **source/tests** means application and public runtime source has no direct console path outside the closed five-outcome helper and synthetic console canaries pass; **merge** means the resulting `main` SHA; **website publication** and **`runmprc.com` verification** remain separate later evidence; **Firebase deployment** and **outside-provider configuration** are unchanged by this frontend-only source issue; **live behavior** and deletion of any earlier local browser-console history remain unverified. Never reproduce a member error or paste a browser console into an issue to prove this boundary.

For AUTH-MAIL-002A [#145](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/145), **source/tests** means mocked account-create and email-request outcomes plus fixed-output canary checks; **merge** means the resulting `main` SHA; **website publication** and **`runmprc.com` revision verification** are separate; **Firebase/provider configuration** is unchanged; and **live delivery** remains unverified. An `accepted` result proves only that Firebase accepted the request. It does not prove Inbox delivery, sender reputation, or Spam placement.

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.
2 changes: 2 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ The findings below describe the repository at the start of the 2026-07-12 assess
| 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. |
| RISK-039 | Some authenticated accounts can lack `members/{uid}` after the Firebase cutover; the account screen hid the read failure and exposed an update that could only fail. Manual database/account repair could corrupt roles or private data. | Use an authenticated create-once server bootstrap, keep browser creation denied, fail the UI closed, and prove backend-first deployment with synthetic accounts. |
| RISK-040 | Registration currently treats account creation and the later verification-email request as one success. A rejected request can still produce “check your inbox,” while sender delivery and Spam placement are unverified. | Return two explicit outcomes, preserve the signed-in account on email-request failure, show only generic recovery text, and verify source, website revision, and provider delivery separately. |

### Source remediation ledger

Expand All @@ -106,6 +107,7 @@ These entries are implementation evidence, not a production risk-acceptance deci
| Part of RISK-035 | The Jest environment is repaired, the stale frontend smoke test is replaced, #124 adds the complete frontend suite as a named blocking hosted step, and #126 adds the standalone SPA callback suite as its own named blocking step. | Keep exact hosted evidence on #124/#126; make lint non-mutating/fail-closed, prove required branch checks, and add the broader TEST-001 suite. |
| RISK-026, RISK-036 | #135 merged through PR #138 as `9eafab1217aff7058c42240aaba72d7b93f8ed24`, replacing automatic frontend-first/fail-open GitHub deployment with a tested manual exact-current-commit gate. Post-merge staging and synthetic production probes failed closed before authentication or mutation, and published neither Firebase nor Pages. | #133 must configure protected environments and least-privilege OIDC/WIF; #136 must prove staged/target deployment and clearing/readback of the existing Pages `runmprc.com` claim; a protected WEB-001 child must establish Netlify publication and rollback. No Firebase, Pages, live-host, or provider-setting change is proven by source/static tests alone. |
| RISK-039 | The #118 source slice uses an empty authenticated callable request, bounded Firebase Auth identity fields, one transactional create-only helper shared with signup, constant responses, generic failures, and a UI that hides Edit until setup and the Rules-protected read succeed. Signup and recovery never change custom claims; browser profile creation remains denied. | Source review/merge is not deployment. Under #105, deploy the exact #100 Rules plus both `createMemberOnSignUp` and `ensureMemberProfile` before the website, prove App Check policy, use a synthetic staged account, verify rollback, then record website, Function, Rules, and live behavior separately. Never repair a real profile manually. |
| RISK-040 | AUTH-MAIL-002A [#145](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/145) source returns `accepted` or `unavailable` after account creation, keeps the signed-in credential on request failure, and shows a focused generic status with one My Account inspection/stop path. Synthetic tests use mocked Firebase calls and canary values only. | Merge and publish the exact frontend revision, verify `runmprc.com` separately, and keep provider delivery/Spam/DNS/template evidence under #119. A source result or accepted request does not prove delivery. Do not call My Account recovery usable until #118 is live and #120's resend result/cooldown child is complete; password/action-code recovery also remains open under #120. |

## 5. Threat model

Expand Down
30 changes: 30 additions & 0 deletions docs/officers/EMERGENCY_AND_RECOVERY.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,43 @@
| Wrong public text, image, or link | Ask the platform owner for one reviewed revert pull request. |
| Site unavailable or old after a merge | Ask the platform owner to check Netlify and GitHub Pages separately; do not change DNS. |
| Login or member access is wrong | Stop role requests and contact the identity/platform owners. |
| Account exists but verification email request failed | Ask the member to stop resending. Record only the time, public `/login` URL, and plain status. Do not ask for the email address, password, code, action link, mailbox access, or screenshot. |
| Profile Save says permission is missing | Ask the member to stop, sign out, and wait. Open a new redacted incident through [Request a change](./REQUEST_A_CHANGE.md). Do not edit the database, delete the login, recreate the account, or grant a role. |
| Private member information is visible | Contact platform and privacy owners immediately; they choose containment through an approved service procedure. Do not change permissions yourself. |
| Unexpected payment, refund, order, or signup | Contact treasurer and platform owners. There is no proven no-code payment kill switch. Do not test with real money. |
| Password, secret, or recovery code exposed | Contact the owning service's two approved owners. They revoke/rotate through the service-specific procedure and record evidence. Do not rotate it from this generic guide. |

Live commerce is not approved as of 2026-07-12. If the public site appears to accept a real payment, do not test it with a real card.

### Account created but verification request failed

**Status:** the truthful two-result screen in [#145](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/145) is **SOURCE ONLY, NOT LIVE** until its exact website revision is published and verified.

**Purpose:** preserve the new account and prevent repeated email requests or unsafe account repair.

**Approver:** membership lead plus identity/platform owner.

**Prerequisites:** the time, the public `/login` address, and the exact plain status with all private details omitted. My Account recovery is not proven until [#118](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/118) records the exact Rules, Functions, and profile page, and [#120](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/120) records a truthful resend result plus cooldown. Without both proofs, use only these stop-and-escalate steps.

1. Ask the member to stop clicking Create account or Resend.
2. Do not ask for their email address, password, code, action link, mailbox access, or screenshot.
3. Record only `account created; verification request did not finish`, the time, and the public `/login` URL.
4. Ask the member to keep the account. Do not delete or recreate it.
5. Open a redacted incident through [Request a change](./REQUEST_A_CHANGE.md).
6. Contact the identity/platform owner.
7. Add the communications owner if accepted messages land in Spam or never arrive.
8. Wait for separate website and provider evidence before saying the problem is fixed.

**Expected result:** no private data is copied, no duplicate account is created, and the owner can separate a website request failure from a provider-delivery problem.

**Stop conditions:** repeated resend attempts, real mailbox tests, direct Firebase Console changes, account deletion/recreation, role changes, or a request for private details.

**Success proof:** the exact website revision displays the correct generic status in an approved synthetic check. Sender branding, delivery, and Spam placement need separate private evidence under [#119](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/119).

**Undo:** ask for one reviewed frontend revert or safe roll-forward. Never undo this problem by deleting the login account.

**Escalation:** membership lead plus identity/platform owner; communications owner for delivery or Spam.

### Missing profile or profile permission error

**Status:** automatic repair is **NOT AVAILABLE YET**. These are current stop-and-escalate steps only.
Expand Down
43 changes: 43 additions & 0 deletions docs/officers/EVENTS_SHOP_MEMBERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,49 @@ There is currently no proven no-code switch that safely stops all new Stripe pay

If any proof is missing, report the change as **not live**.

## New-account verification message — SOURCE ONLY, NOT LIVE

**Purpose:** tell a member whether the account exists and whether the email service accepted the verification request.

**Approver:** membership lead plus identity/platform owner.

**Prerequisites:** issue [#145](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/145) is merged; the exact website revision is published and verified; and the identity owner confirms the plain status text. Before calling My Account a working recovery path, also verify the profile Rules, Functions, and page from [#118](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/118) plus the resend truth/cooldown child under [#120](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/120). Email sender and Spam-folder improvements remain separate owner work in [#119](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/119).

```mermaid
flowchart TD
A["Member chooses Create account"] --> B{"Was the account created?"}
B -- "No" --> C["Show one generic try-again message"]
B -- "Yes" --> D["Show Account created"]
D --> E{"Did the email service accept the request?"}
E -- "Yes" --> F["Say accepted; check Inbox and Spam"]
E -- "No" --> G["Keep account; check My Account; stop if unavailable"]
```

In words: account creation and the later email request are two separate results. Neither result proves that an email reached the Inbox.

Until the prerequisites are proven, the current website message may still be wrong. Do not treat it as delivery evidence.

Officer steps after live proof:

1. Ask the member which plain status they see.
2. Do not ask for their email address, password, code, action link, or screenshot.
3. If the status says the request was accepted, ask them to check Inbox and Spam once.
4. If the message is in Spam, ask them to mark it **Not spam**.
5. If the status says the request did not finish, ask them to choose **Check My Account**.
6. If My Account is unavailable, stop. Keep the account and open a redacted incident through [Request a change](./REQUEST_A_CHANGE.md).
7. Do not ask the member to use the existing Resend button yet. A truthful resend result, cooldown, and session recovery are **NOT AVAILABLE YET** under parent issue [#120](https://github.com/Run-MPRC/Run-MPRC.github.io/issues/120).
8. Stop repeated create-account or resend attempts.

**Expected result:** the page says `Account created` only after creation succeeds. It separately says the email request was accepted or did not finish. It never displays the member's address or the provider's error. An unavailable My Account page is a stop-and-escalate result, not proof that the account failed.

**Stop conditions:** a request for private account details, repeated resends, a production email test, a claim that accepted means delivered, or a website revision that cannot be identified.

**Success proof:** exact pull request and merge commit, green synthetic tests, website publication record, separate `runmprc.com` revision check, and dated plain-text review. Claim My Account recovery only after #118's exact backend/profile page and #120's truthful resend/cooldown child are verified together. Provider delivery, sender branding, Spam placement, and a real mailbox remain unproven unless #119 records owner-approved private evidence.

**Undo:** publish and verify one reviewed frontend revert or safe roll-forward. Do not delete or recreate the Firebase account.

**Escalation:** membership lead plus identity/platform owner; add the communications owner for Spam or delivery problems.

## Checkout adjustment guard — SOURCE ONLY, NOT LIVE

**Purpose:** prevent an unknown discount, tax, or shipping charge from being treated as a valid payment.
Expand Down
62 changes: 62 additions & 0 deletions src/pages/login/LoginForm.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
.registration-outcome {
margin-bottom: 1rem;
padding: 1rem;
border: 2px solid;
border-radius: 0.5rem;
font-size: 0.95rem;
line-height: 1.55;
}

.registration-outcome:focus {
outline: 3px solid #1d4ed8;
outline-offset: 3px;
box-shadow: 0 0 0 3px #1d4ed8;
}

.registration-outcome--accepted {
color: #14532d;
background: #f0fdf4;
border-color: #86efac;
}

.registration-outcome--unavailable {
color: #713f12;
background: #fefce8;
border-color: #facc15;
}

.registration-outcome__title {
color: inherit;
font-size: 1.05rem;
font-weight: 700;
}

.registration-outcome__message {
margin-top: 0.5rem;
}

.registration-outcome__action {
display: flex;
min-height: 3rem;
margin-top: 1rem;
padding: 0.7rem 1rem;
align-items: center;
justify-content: center;
color: #fff;
background: #005bd8;
border-radius: 0.375rem;
font-weight: 700;
text-align: center;
}

.registration-outcome__action:hover,
.registration-outcome__action:focus-visible {
color: #1f2937;
background: var(--color-secondary);
}

.registration-outcome__action:focus-visible {
outline: 3px solid #fff;
outline-offset: 2px;
box-shadow: 0 0 0 3px #111827;
}
Loading
Loading