Skip to content

OAUTH-001C1I — Initialize App Check only after the Strava callback is clean#444

Merged
daliu merged 1 commit into
mainfrom
codex/issue-443-strava-app-check-handoff
Jul 22, 2026
Merged

OAUTH-001C1I — Initialize App Check only after the Strava callback is clean#444
daliu merged 1 commit into
mainfrom
codex/issue-443-strava-app-check-handoff

Conversation

@daliu

@daliu daliu commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Members keep the same Strava connection screen, while the client now waits for a clean callback page and one Firebase App Check readiness result before admitting the existing exchange.

Officer impact: Members still see the same Strava connection screen. A cleanup, App Check, saved-history, or current-attempt failure before exchange uses the existing plain retry result and sends no exchange; an unmounted completion is inert.

Officer documentation: docs/officers/EVENTS_SHOP_MEMBERS.md, SYSTEM_DESIGN.md, and SECURITY.md now describe the source-only flow, exact Router-history boundary, proof states, stop conditions, undo path, and escalation.

Deployment evidence: Source commit 65608e5e5118399d5bccb6a32576ff08e2ecf780 and local synthetic checks only. Website publication: not performed. runmprc.com verification: not performed. Firebase deployment/readback: not performed. Enterprise provider/key/domain/token evidence: not performed. Strava/provider configuration: not performed. Production data: not accessed or changed. Live behavior: not verified.

Closes #443
Parent: #88 remains open.

Invariant and transitions

  • Initial capability callback: App Check stays suppressed while URL or saved Router detail is current.
  • Eligible Strava callback: suppressed -> exact native/Router cleanup -> one App Check initialization/token-readiness flight -> one existing exchange.
  • Only null or the pinned BrowserRouter's exact plain {idx,key,usr:null} native history record is clean. Extra fields, accessors, non-plain values, invalid keys, or mismatched effective keys stop. The pinned empty native key correctly matches Router's default fallback.
  • The callback rechecks exact native/Router path, Router entry key, UID, services, Firebase resources/app, attempt, and lifecycle before exchange and before applying its result.
  • Dirty, wrong, failed, stale, or reinjected mounted work before exchange uses one fixed result. Unmounted work is inert. Work already admitted to the server/provider cannot be canceled and may require separate reconciliation.
  • Auth, registration, and shop callbacks cannot use this Strava-only restart. Ordinary production startup stays eager; local/test App Check remains off.

Failure, privacy, and authority review

  • The delayed method accepts no callback data and discards the App Check result without returning, inspecting, logging, or storing it.
  • Module scope retains only booleans, not pathname/query/fragment objects or callback values.
  • Missing key, provider construction/initialization, synchronous/asynchronous token failure, hostile rejection, dirty boundaries, and microtask reentry use fixed value-free results.
  • Provider/init/token boundaries and the final promise microtask recheck sticky invalidation; concurrent callers share one cached flight.
  • Exact native/Router path equality remains fail-closed after outbound-only trailing-slash canonicalization.
  • No membership, discount, payment, member, or admin authority changes.
  • No Function, Rule, package, lockfile, workflow, environment, schema, migration, or backfill change.

Verification

  • RED on exact base a6b40d5e6042d6b5a26fe56a01165c1b4894029f: the old source called exchange first instead of prepare (recorded on OAUTH-001C1I — Initialize App Check only after the Strava callback is clean #443).
  • Focused FirebaseResources + Account: 198/198 passed.
  • Full frontend: 14 suites, 727/727 passed.
  • SPA callback suite: 11/11 passed.
  • TypeScript no-emit and changed-file ESLint: passed with no output.
  • Reviewed frontend lint baseline: 111 files; 117 legacy errors and 6 legacy warnings exactly preserved.
  • Diagnostic production build: compiled successfully; only the pre-existing stale Browserslist-data advisory appeared.
  • Workflow/release/Firebase-readback/artifact/dependency safety: 54/54 passed.
  • Functions lint: passed. Functions unit: 63 suites passed, 2 skipped; 6,057 tests passed, 64 skipped.
  • Firestore Rules: 378/378 passed on Node 20/Java 17. An initial outer-npx --yes wrapper leaked npm configuration and failed before tests; the direct pinned-PATH rerun passed.
  • Commerce command-journal Firestore emulator: 63/63 passed on demo project demo-pay002b2-test.
  • git diff --check: passed.

Review and residual risk

Self-review covered authorization, initial/delayed App Check ordering, exact Router/native identity, input shape, privacy, fixed diagnostics, single-flight behavior, lifecycle races, production fallback, and documentation claims. Three independent review tracks found and verified fixes for raw initial-location retention, provider/token and promise-microtask races, normalized-versus-exact path divergence, saved-history extra fields, Router-entry key binding, and pinned short/empty key compatibility. Their final re-reviews reported no remaining findings.

App Check initialization and any exchange already admitted to the server/provider are irreversible. This source does not prove configured provider behavior, native enforceAppCheck, deployment, or live protection. Those remain under #88, ABUSE-001A2, and the protected release gates.

@netlify

netlify Bot commented Jul 22, 2026

Copy link
Copy Markdown

Deploy Preview for luminous-fox-7c393f ready!

Name Link
🔨 Latest commit 65608e5
🔍 Latest deploy log https://app.netlify.com/projects/luminous-fox-7c393f/deploys/6a609126b1b0d20008e49f58
😎 Deploy Preview https://deploy-preview-444--luminous-fox-7c393f.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@daliu

daliu commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

SELF-REVIEWED by /root at exact head 65608e5e5118399d5bccb6a32576ff08e2ecf780 against exact base a6b40d5e6042d6b5a26fe56a01165c1b4894029f.

No actionable findings remain after independent security/privacy, race/lifecycle, and tests/documentation reviews. All identified findings were fixed and re-reviewed.

Verification at this exact head:

  • GitHub Actions run 29909212081: all five jobs passed (frontend, Functions, Firestore Rules, commerce emulator, artifact scrubber).
  • Netlify deploy preview passed; redirect rules passed; header/pages checks were intentionally neutral/skipped because those surfaces did not change.
  • Local focused tests: 198/198.
  • Local full frontend tests: 727/727.
  • Functions: 6,057 passed / 64 skipped.
  • Firestore Rules: 378/378.
  • Commerce emulator: 63/63 against the demo project.
  • TypeScript, changed-file ESLint, full lint review, SPA navigation, diagnostic production build, release/readback/artifact/dependency checks, and git diff --check passed.

Security/privacy review: callback inputs remain untrusted; raw capability values, App Check tokens, URLs, and user data are not retained or logged. App Check initializes only after a recognized Strava callback has been cleaned and the native/Router path and history key still match. A stale lifecycle, UID, app, route, history, or reinjection context fails closed.

Deployment evidence: source and preview only. No Firebase, production Netlify, Strava provider, DNS, or other production action was performed or claimed.

The branch rule still reports REVIEW_REQUIRED because GitHub does not count an author's self-review as an independent approval. The user explicitly requested self-review and merge when no issues remain, so this exact-head review is the basis for the maintainer merge bypass.

@daliu
daliu merged commit 3cbfb9e into main Jul 22, 2026
9 checks passed
@daliu
daliu deleted the codex/issue-443-strava-app-check-handoff branch July 22, 2026 09:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAUTH-001C1I — Initialize App Check only after the Strava callback is clean

1 participant