You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
SAFETY-001 — Preserve callbacks and fail closed on local Firebase isolation #99
The GitHub Pages SPA bridge dropped Stripe/Strava query and hash state. Local Auth and Firestore used emulators while Functions could still target the deployed project; emulator setup errors and non-emulated analytics/monitoring could silently reach external services.
Outcome
Preserve safe same-origin callback state and make development/test use a matching demo-mprc-local Firebase namespace with fail-closed Auth, Firestore, Functions, Analytics, and Sentry behavior.
src/services/firebase/FirebaseResources.ts and its focused test
src/services/monitoring/sentry.ts and its focused test
Emulator/script hunks in root and Functions package.json
Safe local environment examples owned by the architecture handoff
Acceptance criteria
Path, query, and hash survive the SPA bridge; malformed/cross-origin targets are discarded.
Development and test select demo-mprc-local and connect Auth, Firestore, and Functions to localhost.
Emulator configuration failure stops startup.
Production does not connect emulators.
Analytics and Sentry do not initialize in local/test.
Focused frontend/SPA tests and production compile pass.
Dependencies
None. This is a prerequisite for CI-001A and safe provider testing.
Coordination
A verified local working-tree implementation predates publication of this issue. This issue records the exact ownership boundary before any further editing or PR work. The existing diff must be isolated onto the claimed branch before review; unrelated changes and the pre-existing public/sitemap.xml modification are excluded.
Do not edit the listed paths or duplicate this outcome while the issue is assigned and has a valid timestamped CLAIMED marker.
CLAIMED by Codex agent /root at 2026-07-12T20:49:58Z; branch codex/issue-99-safety-callback-emulators.
Existing shared working-tree implementation predates issue publication. I will isolate this outcome onto the named branch serially before opening a PR; no unrelated dirty path is included.
CLAIM RETAINED / EXTRACTION QUEUED at 2026-07-12T21:53:37.334Z. Assignment and the original timestamped CLAIMED marker remain authoritative. No issue-specific extraction has begun. Dependency: #104. #104 exclusively owns .env.example, functions/.env.example, functions/.secret.local.example, and all .gitignore hunks; #99 owns no environment-example or ignore-file hunk. After #104 merges, transplant only #99 runtime/emulator/callback/monitoring/package/test work onto refreshed main containing #98. Do not duplicate this outcome.
EXTRACTION STARTED by Codex agent /root at 2026-07-13T07:16:39Z; branch codex/issue-99-safety-callback-emulators; base a7fc301.\n\nThe clean worktree preserves merged #98, #103, and #100. Extraction remains limited to #99 callback/emulator/monitoring/scripts/tests plus the minimum current-truth documentation required by AGENTS.md. It excludes all environment examples, ignore files, sitemap output, Firebase deployment, provider configuration, #118 profile behavior, and #124 hosted-CI files/document statements while #124 is active.\n\nNo production account, data, email, Functions endpoint, monitoring provider, or Firebase deployment will be used.
SCOPE AMENDMENT by Codex agent /root at 2026-07-13T07:19:08Z: add only src/pages/admin/events/AdminEventRegistrations.tsx to the runtime boundary.\n\nReason: this is the sole direct browser construction of a cloudfunctions.net URL. Connecting the shared Firebase Functions SDK to the emulator does not protect that fetch. The minimal change routes the existing export endpoint through FirebaseResources.getHttpFunctionUrl so local/test uses 127.0.0.1:5001 with demo-mprc-local and production retains its current us-central1 URL.\n\nNo export behavior, authorization, CSV data, production call, or #116 roster design is changed. Focused FirebaseResources tests will prove the local and production URL split.
SENTRY BOUNDARY CLARIFICATION at 2026-07-13T07:23:07Z: #99 retains one minimal production safety guard in its already-owned sentry.ts/test paths.\n\nThe new Pages bridge preserves OAuth/checkout capability query and fragment state. Because spa-navigation.js restores that state before src/index.js initializes Sentry, landing the bridge without a guard could newly send the callback URL into hosted monitoring/replay. #99 therefore does not initialize Sentry when the page initially loads one of the three current capability routes with query/fragment state.\n\nThis is not general telemetry redaction. #111 still owns URL/event scrubbing, replay policy, already-initialized SPA navigation, PII/log review, consent/retention, and staged provider evidence. #99 uses no provider call or live callback.
DOCUMENTATION SCOPE AMENDMENT at 2026-07-13T07:27:03Z: add the minimum current-truth updates required by AGENTS.md to SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, AGENTS.md, README.md, SECURITY.md, OPERATIONS_RUNBOOK.md, GITHUB_ISSUES.md, GITHUB_ISSUE_SLICES.md, and docs/officers/PUBLISH_AND_CHECK.md.\n\n#124 currently owns hunks in every overlapping file except SYSTEM_DESIGN.md and IMPLEMENTATION_PLAN.md. #99 will not edit the overlapping documents until #124 merges and releases them; it will then refresh/rebase and preserve the hosted-Jest truth.\n\nThe #99 updates will:\n- show simple callback and local-emulator diagrams;\n- replace only the stale #99 NOT AVAILABLE / implemented_locally statements;\n- give the exact two-terminal localhost procedure and stop conditions;\n- state that endpoint configuration is not readiness until the CLI reports all three emulators;\n- forbid provider, email, payment, refund, Strava, and production-data flows;\n- warn that optimized/preview builds still target production Firebase and are unsafe for sign-in/private workflows until #105/CONFIG provides staging;\n- distinguish source/tests/merge/website/Firebase/provider/live states.\n\nNo officer is asked to use a terminal. The officer guide changes only the preview stop condition and escalation path.
REVIEW CORRECTION at 2026-07-13T07:41:44Z on exact commit f97c2f4.
Two independent reviews correctly blocked the earlier draft because preserving the full callback route could expose capability-bearing query/fragment state before application verification:
Firebase Analytics could initialize after restoration and observe the callback URL.
The external bridge script could receive the callback URL through a same-origin Referer header before JavaScript ran.
The corrected #99 boundary adds only src/services/monitoring/capabilityCallback.ts and related existing #99 test/document hunks. Analytics and Sentry now share the same narrow initial-callback guard. Both Pages documents declare strict-origin before any subresource. Tests prove the guard on all three current capability routes, preserve ordinary production startup behavior, and prove policy order.
Updated local proof: 20/20 focused Firebase/monitoring tests, 4 suites / 36 frontend tests, 10/10 standalone callback/referrer tests, diagnostic build clean, and changed runtime lint has 0 errors. Broader telemetry redaction, replay, consent, retention, and already-initialized SPA navigation remain #111. No live callback, account, provider, Firebase deploy, or production data was used. PR #128 remains draft pending exact-commit re-review and hosted checks.
EXTRACTION FINISHED / IN REVIEW at 2026-07-13T07:58:25Z.
PR: #128
Exact head: f7b63d4
Base: f04b89a
Changed paths: 21, all within #99 and its timestamped scope amendments.
Final source behavior:
same-origin callback path/query/fragment restoration with strict-origin before subresources;
rejection of malformed, outside-origin, normalized protocol-relative, case/trailing/encoded-path bypasses;
App Check, Analytics, and Sentry suppressed on the initial capability URL;
browser development/test uses fully synthetic demo-mprc-local and loopback Auth/Firestore/Functions;
connector setup fails closed; direct CSV export uses the environment-aware Functions resolver;
ABUSE-001A must defer three callback callables until DATA-001A/OAUTH-001C handoffs.
Verification:
Node 20 frontend 4 suites / 47 tests;
focused Firebase/monitoring 31/31;
standalone callback/referrer 10/10;
Functions lint and 17/17 tests;
Java 17 Rules 295/295;
diagnostic build passed;
changed runtime lint 0 errors; only pre-existing legacy admin warnings;
34 relative Markdown links resolve;
two independent exact-head reviews: no P0/P1/P2 findings;
exact-head hosted run 29233727821: frontend, Functions, and Rules jobs passed;
exact-head Netlify preview checks passed, but no sign-in/private/Firebase/provider behavior was exercised.
No production account, data, callback, provider, Firebase deployment, or live profile repair was used or claimed. Merge remains the separate publication authorization.
POST-MERGE DOCUMENTATION CORRECTION STARTED at 2026-07-13T07:59:13Z on branch codex/issue-99-oauth-ticket-map, base a237e1a.
A coordination message arrived immediately after PR #128 merged: live issue #88 already owns the complete Strava callback/state/code/server-exchange hardening outcome. The new local OAUTH-001C slice is therefore not a new issue to publish. This follow-up changes documentation only to map OAUTH-001 and OAUTH-001C to #88 and prevent duplicate work. It will not change runtime, tests, providers, or production data. #99 remains open and claimed until this correction and deployment evidence complete.
Runtime deploy run 29233830301 pushed gh-pages commit 68b823a for a237e1a.
The published GitHub Pages spa-navigation.js SHA-256 exactly matches reviewed source: d5c14bc1e0e010bb93c240b753500ebb9db57061695a2def618ce519c00f31b5.
Final docs-only deploy run 29234173825 correctly found the Pages artifact unchanged.
Netlify public deployment evidence reports production state ready for exact final-main commit f6e86be.
runmprc.com serves the exact reviewed spa-navigation.js hash, strict-origin before subresources, and the final guarded production bundle. Public/read-only verification only; no sign-in or private action was used.
Separate surfaces:
Firebase was NOT deployed. Final deploy log explicitly says: No FIREBASE_SERVICE_ACCOUNT secret; skipping Firebase deploy.
No Stripe, Strava, email, monitoring-provider, account, or production-data flow was exercised.
Provider callback behavior remains unproven until the named test-provider gates.
Because the repository default branch is stale dev, this issue is being closed manually after the two controlled merges and exact deployment evidence. #99 package.json and SECURITY/GITHUB documentation ownership is now released at final main f6e86be.
#335 merged through PR #336 as exact main f9a3f3cac92ae1a38d4a02041cf7301355470f36 and preserves #99 byte-for-byte. The Pages handoff still safely carries the inbound same-origin callback, and #335 adds only the later Strava component's current native/Router cleanup boundary. #99 Sentry/Analytics/App Check guards were not changed.
Exact-main CI 29555712712 passed all five jobs; deployments are empty.
Activity
daliu commentedon Jul 12, 2026
CLAIMED by Codex agent /root at 2026-07-12T20:49:58Z; branch codex/issue-99-safety-callback-emulators.
Existing shared working-tree implementation predates issue publication. I will isolate this outcome onto the named branch serially before opening a PR; no unrelated dirty path is included.
daliu commentedon Jul 12, 2026
CLAIM RETAINED / EXTRACTION QUEUED at 2026-07-12T21:53:37.334Z. Assignment and the original timestamped CLAIMED marker remain authoritative. No issue-specific extraction has begun. Dependency: #104. #104 exclusively owns .env.example, functions/.env.example, functions/.secret.local.example, and all .gitignore hunks; #99 owns no environment-example or ignore-file hunk. After #104 merges, transplant only #99 runtime/emulator/callback/monitoring/package/test work onto refreshed main containing #98. Do not duplicate this outcome.
daliu commentedon Jul 13, 2026
EXTRACTION STARTED by Codex agent /root at 2026-07-13T07:16:39Z; branch codex/issue-99-safety-callback-emulators; base a7fc301.\n\nThe clean worktree preserves merged #98, #103, and #100. Extraction remains limited to #99 callback/emulator/monitoring/scripts/tests plus the minimum current-truth documentation required by AGENTS.md. It excludes all environment examples, ignore files, sitemap output, Firebase deployment, provider configuration, #118 profile behavior, and #124 hosted-CI files/document statements while #124 is active.\n\nNo production account, data, email, Functions endpoint, monitoring provider, or Firebase deployment will be used.
daliu commentedon Jul 13, 2026
SCOPE AMENDMENT by Codex agent /root at 2026-07-13T07:19:08Z: add only src/pages/admin/events/AdminEventRegistrations.tsx to the runtime boundary.\n\nReason: this is the sole direct browser construction of a cloudfunctions.net URL. Connecting the shared Firebase Functions SDK to the emulator does not protect that fetch. The minimal change routes the existing export endpoint through FirebaseResources.getHttpFunctionUrl so local/test uses 127.0.0.1:5001 with demo-mprc-local and production retains its current us-central1 URL.\n\nNo export behavior, authorization, CSV data, production call, or #116 roster design is changed. Focused FirebaseResources tests will prove the local and production URL split.
daliu commentedon Jul 13, 2026
SENTRY BOUNDARY CLARIFICATION at 2026-07-13T07:23:07Z: #99 retains one minimal production safety guard in its already-owned sentry.ts/test paths.\n\nThe new Pages bridge preserves OAuth/checkout capability query and fragment state. Because spa-navigation.js restores that state before src/index.js initializes Sentry, landing the bridge without a guard could newly send the callback URL into hosted monitoring/replay. #99 therefore does not initialize Sentry when the page initially loads one of the three current capability routes with query/fragment state.\n\nThis is not general telemetry redaction. #111 still owns URL/event scrubbing, replay policy, already-initialized SPA navigation, PII/log review, consent/retention, and staged provider evidence. #99 uses no provider call or live callback.
daliu commentedon Jul 13, 2026
DOCUMENTATION SCOPE AMENDMENT at 2026-07-13T07:27:03Z: add the minimum current-truth updates required by AGENTS.md to SYSTEM_DESIGN.md, IMPLEMENTATION_PLAN.md, AGENTS.md, README.md, SECURITY.md, OPERATIONS_RUNBOOK.md, GITHUB_ISSUES.md, GITHUB_ISSUE_SLICES.md, and docs/officers/PUBLISH_AND_CHECK.md.\n\n#124 currently owns hunks in every overlapping file except SYSTEM_DESIGN.md and IMPLEMENTATION_PLAN.md. #99 will not edit the overlapping documents until #124 merges and releases them; it will then refresh/rebase and preserve the hosted-Jest truth.\n\nThe #99 updates will:\n- show simple callback and local-emulator diagrams;\n- replace only the stale #99 NOT AVAILABLE / implemented_locally statements;\n- give the exact two-terminal localhost procedure and stop conditions;\n- state that endpoint configuration is not readiness until the CLI reports all three emulators;\n- forbid provider, email, payment, refund, Strava, and production-data flows;\n- warn that optimized/preview builds still target production Firebase and are unsafe for sign-in/private workflows until #105/CONFIG provides staging;\n- distinguish source/tests/merge/website/Firebase/provider/live states.\n\nNo officer is asked to use a terminal. The officer guide changes only the preview stop condition and escalation path.
daliu commentedon Jul 13, 2026
REVIEW CORRECTION at 2026-07-13T07:41:44Z on exact commit f97c2f4.
Two independent reviews correctly blocked the earlier draft because preserving the full callback route could expose capability-bearing query/fragment state before application verification:
The corrected #99 boundary adds only src/services/monitoring/capabilityCallback.ts and related existing #99 test/document hunks. Analytics and Sentry now share the same narrow initial-callback guard. Both Pages documents declare strict-origin before any subresource. Tests prove the guard on all three current capability routes, preserve ordinary production startup behavior, and prove policy order.
Updated local proof: 20/20 focused Firebase/monitoring tests, 4 suites / 36 frontend tests, 10/10 standalone callback/referrer tests, diagnostic build clean, and changed runtime lint has 0 errors. Broader telemetry redaction, replay, consent, retention, and already-initialized SPA navigation remain #111. No live callback, account, provider, Firebase deploy, or production data was used. PR #128 remains draft pending exact-commit re-review and hosted checks.
daliu commentedon Jul 13, 2026
EXTRACTION FINISHED / IN REVIEW at 2026-07-13T07:58:25Z.
PR: #128
Exact head: f7b63d4
Base: f04b89a
Changed paths: 21, all within #99 and its timestamped scope amendments.
Final source behavior:
Verification:
No production account, data, callback, provider, Firebase deployment, or live profile repair was used or claimed. Merge remains the separate publication authorization.
daliu commentedon Jul 13, 2026
POST-MERGE DOCUMENTATION CORRECTION STARTED at 2026-07-13T07:59:13Z on branch codex/issue-99-oauth-ticket-map, base a237e1a.
A coordination message arrived immediately after PR #128 merged: live issue #88 already owns the complete Strava callback/state/code/server-exchange hardening outcome. The new local OAUTH-001C slice is therefore not a new issue to publish. This follow-up changes documentation only to map OAUTH-001 and OAUTH-001C to #88 and prevent duplicate work. It will not change runtime, tests, providers, or production data. #99 remains open and claimed until this correction and deployment evidence complete.
daliu commentedon Jul 13, 2026
COMPLETED / DEPLOYMENT EVIDENCE at 2026-07-13T08:07:18Z.
Source and merge:
Review and checks:
Website deployment:
Separate surfaces:
Because the repository default branch is stale dev, this issue is being closed manually after the two controlled merges and exact deployment evidence. #99 package.json and SECURITY/GITHUB documentation ownership is now released at final main f6e86be.
daliu commentedon Jul 17, 2026
#335 merged through PR #336 as exact main
f9a3f3cac92ae1a38d4a02041cf7301355470f36and preserves #99 byte-for-byte. The Pages handoff still safely carries the inbound same-origin callback, and #335 adds only the later Strava component's current native/Router cleanup boundary. #99 Sentry/Analytics/App Check guards were not changed.Exact-main CI 29555712712 passed all five jobs; deployments are empty.