Skip to content

SAFETY-001 — Preserve callbacks and fail closed on local Firebase isolation #99

Closed

Description

@daliu

Problem

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.

Scope

  • public/404.html, public/index.html, public/spa-navigation.js, tests/spa-navigation.test.js
  • 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.

Activity

  1. added
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    area:firebaseFirebase services and data
    area:webWeb application and hosting
    size:SSmall focused issue
    status:readyDependencies complete and ready to claim
    on Jul 12, 2026
  2. self-assigned this
    on Jul 12, 2026
  3. daliu commented on Jul 12, 2026

    @daliu
    ContributorAuthor

    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.

  4. added
    status:in-progressClaimed and actively being implemented
    status:proposedDesigned but dependencies or decisions remain
    and removed
    status:readyDependencies complete and ready to claim
    status:in-progressClaimed and actively being implemented
    on Jul 12, 2026
  5. daliu commented on Jul 12, 2026

    @daliu
    ContributorAuthor

    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.

  6. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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.

  7. added
    status:in-progressClaimed and actively being implemented
    and removed
    status:proposedDesigned but dependencies or decisions remain
    on Jul 13, 2026
  8. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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.

  9. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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.

  10. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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.

  11. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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:

    1. Firebase Analytics could initialize after restoration and observe the callback URL.
    2. 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.

  12. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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.

  13. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    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.

  14. daliu commented on Jul 13, 2026

    @daliu
    ContributorAuthor

    COMPLETED / DEPLOYMENT EVIDENCE at 2026-07-13T08:07:18Z.

    Source and merge:

    Review and checks:

    • Two independent exact-head reviews approved with no P0/P1/P2 findings.
    • Final main CI run 29234173865 passed frontend, Functions, and Rules jobs.
    • Hosted frontend Jest ran 4 suites / 47 tests.
    • Local exact runtime evidence remains: focused Firebase/monitoring 31/31; standalone callback/referrer 10/10; Functions 17/17; Rules 295/295; diagnostic build and changed-file lint passed.

    Website deployment:

    • 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:

    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.

  15. daliu commented on Jul 17, 2026

    @daliu
    ContributorAuthor

    #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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:firebaseFirebase services and dataarea:webWeb application and hostingpriority:P0Launch blocker or urgent security risksize:SSmall focused issuetype:reliabilityReliability and recoverytype:securitySecurity or privacy boundary

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions