Repository navigation
OAUTH-001C1J — Require exact Strava exchange client confirmation #612
Description
Outcome
The browser must navigate away from the Strava callback only after the callable returns the exact documented success confirmation. Any other fulfilled result must use the existing fixed callback-failure screen.
Parent: #88
Problem
src/services/strava/stravaService.ts currently returns arbitrary fulfilled stravaExchangeCode data. StravaCallback treats every fulfillment as success. A fulfilled null, { ok: false }, malformed athlete ID, accessor, or hostile reflection result can therefore produce a false-success navigation even though the client has no valid confirmation.
Invariant and allowed transitions
- Admit only a value presenting exactly two own enumerable data fields: primitive
ok: trueand a primitive positive safe-integerathleteId. - Return a fresh frozen canonical confirmation; never retain or return the received object.
- Malformed fulfillment or exceptional result/data/structure inspection throws only
Invalid Strava exchange response. - A callable transport rejection remains uninspected and identity-preserving.
- The existing callback rejection path keeps the cleaned callback page on its fixed failure screen and must not navigate.
- An exact client confirmation is acknowledgement admission only. It does not independently prove provider exchange, paired Firestore persistence, provider origin, deployment, or live behavior.
Scope
src/services/strava/stravaService.ts: exact response reader and narrowed return type forstravaExchangeCodeonly.src/pages/account/Account.test.tsx: focused service matrix plus one real-service/callback composition proof.SECURITY.md: RISK-009 current-source and residual boundary only.docs/officers/EVENTS_SHOP_MEMBERS.md: existing Strava callback-failure procedure only.
No StravaCallback.tsx, Function, Rules, workflow, package, schema, migration, Firebase, provider, production-data, or live change is included.
Required RED and coverage
On exact base 63d29bedf379a857421501a5c0938c2901618095, fulfill the mocked callable with { data: { ok: false, athleteId: 608 } } and require the real service to reject with the fixed response error. The old source must fulfill. The callback composition test must prove the same malformed fulfillment stays on the fixed failure screen and does not navigate.
Cover exact valid bounds; fresh/frozen projection; missing, extra, inherited, symbol, non-enumerable, accessor, primitive, array, custom-prototype, malformed ok, malformed/non-safe/non-positive athleteId, throwing/revoked/transparent Proxy behavior; exceptional outer-result/data access where representable; and transport-rejection identity. Preserve existing callback cleanup, lifecycle, App Check handoff, rejection, and exact success behavior.
Dependencies
- OAUTH-001C1E — Validate Strava authorization-exchange success before writes #281: validated server result
{ ok: true, athleteId }. - OAUTH-001C1B — Redact browser-rendered Strava callback failures #242: fixed callback failure containment.
- OAUTH-001C1G — Scrub Strava callback capabilities from current browser history before use #335, OAUTH-001C1H — Replace browser-local Strava OAuth state with a one-use server challenge #441, and OAUTH-001C1I — Initialize App Check only after the Strava callback is clean #443: callback cleanup, one-use state, and App Check handoff.
All source dependencies are merged. Provider configuration, IAM/encryption, deployment, and live proof remain separate #88 gates.
Acceptance criteria
- The trustworthy RED fails on the exact base and passes with the fix.
- Exact confirmation is the only fulfilled value that can reach callback success.
- Invalid fulfillment cannot navigate, log, display, retain, coerce, or serialize supplied details.
- Transport rejection behavior and all existing callback behavior remain compatible.
- Focused checks and the relevant full suites pass.
- Exact-head security, lifecycle, privacy, test-quality, and backup-officer reviews find no STOP.
Officer impact: A member will no longer see a false successful Strava callback transition when the website receives an invalid fulfilled confirmation. The fixed retry instruction remains visible.
Officer documentation: docs/officers/EVENTS_SHOP_MEMBERS.md existing Strava callback-failure procedure.
Deployment evidence: At claim time, no source change, test result, merge, website publication, runmprc.com verification, Firebase deployment, Strava/provider action, production-data action, or live-behavior verification is claimed. Final evidence must record each surface separately.
Activity
daliu commentedon Aug 2, 2026
CLAIMED by /root at 2026-08-02T07:34:49Z on branch
codex/issue-612-strava-exchange-confirmation, exact base63d29bedf379a857421501a5c0938c2901618095.This atomic OAUTH-001C1J child owns only the four paths and exact client fulfilled-confirmation outcome listed in the issue. It excludes Functions/server behavior, scope policy, response-byte bounds, athlete ownership, provider/local reconciliation, audit, IAM/encryption, deployment, production data, provider configuration, live behavior, and completion of #88.
daliu commentedon Aug 2, 2026
Trustworthy RED recorded before runtime or documentation edits.
63d29bedf379a857421501a5c0938c29016180951d897e7868e04aa27cfcbc94dd6244f0f2f22c7baf7fb8c7a5e04f7e0c216014CI=true npm test -- --runInBand src/pages/account/Account.test.tsx --testNamePattern='OAUTH-001C1J'{ data: { ok: false, athleteId: 612 } }reachedAccount destinationwith replacement navigation; the new composition assertion required the existing fixed callback alert and no navigation.The RED used only made-up values and mocked Firebase/callable boundaries. No provider, Firebase project, production data, deployment, or live surface was contacted or changed.
daliu commentedon Aug 2, 2026
Corrected exact-base RED evidence — this supersedes the earlier test-only hash after five legacy successful mocks were corrected from the impossible
athleteId: nullshape to positive athlete IDs.63d29bedf379a857421501a5c0938c2901618095ddcdfb68ec47f40c9d8a38c30d463ac7bf8ed2b51d130a338ce6a65b9cc53875{ data: { ok: false, athleteId: 612 } }, so the real callback composition navigated to Account instead of staying on the cleaned fixed-failure page.No production, provider, persistence, scope, deployment, or live behavior was exercised by this evidence.
daliu commentedon Aug 2, 2026
COMPLETE / CLOSED / CLAIM RELEASED
#612 is complete as a source-only client acknowledgement boundary.
07237d570ccba266dd48a265fd22b7d9ddb10365; tree031b49e53a5b728944c2abeac18d58ffcd6f1a6d; full binary diff SHA-256b5b08f101adb6f8712ea8bc4f03847fdab99f8759d5c1c185d4f1262127d769f.644d9f1fe3e6c06427412fd3ae37973dbbfeca20; the main tree exactly matches the reviewed head tree.30738759163: all five jobs passed. Exact-main CI30738868932: all five jobs passed.6a6ef803662161000886623a: ready at the reviewed head, deploy-preview context, unpublished.6a6ef8d14154fc0008c2aabb: error,published_at: null. GitHub deployments for exact main:[].6a6dc9ea588b0c0008036312at control commit9ad6837756cdd409d296009fde5082eeeae5c059. The OAUTH-001C1J — Require exact Strava exchange client confirmation #612 website change was not published, sorunmprc.comwas not verified for it.The browser now admits only the exact two-field confirmation and uses the existing fixed callback failure for malformed fulfillment. This does not prove provider exchange, paired persistence, athlete ownership, approved scopes, deployment, or live behavior. Remaining #88 work includes provider response bounds/timeouts, scope/account policy, reconciliation, audit, IAM/encryption, native enforcement, release, and provider/live evidence.
CLAIM RELEASED at exact main
644d9f1fe3e6c06427412fd3ae37973dbbfeca20. No #612 path or outcome ownership remains.