Skip to content

DATA-001A9 — Redact My Account registration-sort failures #598

Closed

Description

@daliu

Officer impact: None — My Account already discards every registration-list rejection detail and shows the same generic registration-load error.

Officer documentation: None — this is an internal server sort-failure boundary; no officer procedure, screen, navigation, page structure, collected field, data movement, permission, account ownership, approval, or deployment process changes.

Deployment evidence: None at issue creation. Source, tests, review, merge, website publication, runmprc.com verification, Firebase deployment/readback, outside-provider action, production-data action, migration, and live behavior must be recorded separately.

Outcome

After the exact-UID registration query, registration projection, and event work succeed, map every exceptional final registration-created sort outcome to the existing fixed unavailable / Registration data could not be loaded. result without opening the caught value.

Parent: #374. This atomic child follows released DATA-001A8/#579, whose closure explicitly leaves later registration sorting separately claimable. Exact clean main at publication: d462ff6.

Confirmed defect

Current functions/listMyRegistrations.js materializes and sorts retained registration records after all event reads. The comparator reads nested createdAt._seconds values and subtracts them outside every fixed-error boundary. A throwing nested accessor or numeric-coercion hook therefore escapes the application-owned callable boundary and enters Firebase/platform handling instead of the fixed registration-load result.

This defect is higher priority than the queued non-authoritative Strava activity-key precision residual because it is a current raw exception boundary on an authenticated callable. No dependency-ready unowned P0 remains.

Invariant and order

For one authenticated callable request:

  1. Preserve App Check before Auth and unauthenticated denial before Firestore.
  2. Preserve the one exact stored-UID registration query.
  3. Preserve registration projection, runner minimization, event-ID derivation, and A7/A8 event acquisition and projection behavior.
  4. Preserve Promise-all event lookup concurrency and complete the same event work before sorting.
  5. Catch without binding every exceptional final registration array construction, comparator, nested _seconds access, or numeric-coercion outcome.
  6. Return only fixed unavailable / Registration data could not be loaded.
  7. Never inspect, format, coerce, log, attach, or serialize the caught value.
  8. Never return a partial callable response.
  9. Preserve valid descending created-time order, fallback-to-zero behavior, ties, response bytes, successful empty and one-row results, and read-only behavior.
  10. Do not claim that the catch prevents an already-attempted getter or coercion hook; it only redacts an exception the hook throws.

Smallest safe scope

  1. functions/listMyRegistrations.js
    • wrap only the existing final Array.from(results.values()).sort(...) operation in a separate catch without binding;
    • preserve the comparator expression, token sequence, and runtime semantics; only indentation may change inside the new try boundary;
    • change no A3–A8 boundary, query, event work, response, or field.
  2. functions/listMyRegistrations.test.js
    • add one separately named DATA-001A9 block plus minimum synthetic fixture support;
    • use at least two exact-UID registrations so the comparator definitely runs.
  3. SECURITY.md
    • add one separately named DATA-001A9 remediation-ledger row immediately after A8.

Trustworthy test-first proof

Before runtime or documentation edits:

  • use two exact-UID registrations sharing one invented event;
  • independently make retained _seconds access throw a hostile proxy;
  • independently make numeric coercion throw the same hostile proxy;
  • prove the old runtime exposes that exact raw failure after the exact query, both registration projections, one event acquisition, and the complete event snapshot/field projection;
  • prove zero caught-value inspection, formatting, serialization, console logging, or Firebase Functions logging;
  • prove no resolved or partial callable response;
  • retain a positive exact descending numeric sort plus null/missing fallback control.

The fixed runtime must return exactly unavailable / Registration data could not be loaded., with no details or cause, while all earlier ordering and successful behavior remain exact.

Use invented values only. Do not call Firebase, a provider, or production.

Required green proof

  • focused DATA-001A3–A9 tests pass;
  • Functions lint and the full Functions suite pass;
  • frontend, TypeScript, non-mutating lint, SPA, repository safety, diagnostic build, Rules, and real demo-only commerce-emulator gates pass;
  • diff and sensitive-output review pass;
  • three independent exact-head reviews approve privacy/error handling, tests/compatibility, and scope/docs/claims;
  • hosted exact-head and exact-main CI pass before closure;
  • deployment and live states are audited separately.

Explicit exclusions and residuals

No validation or normalization of createdAt or _seconds; no change to malformed-but-nonthrowing values, NaN/Infinity ordering, fallback-to-zero, ties, or sort stability; no event-ID validation/derivation change; no sibling cancellation or reordering; no response/platform serialization or platform-log proof; no retry; no schema, Rules, indexes, packages, Account UI/service/types, officer guide, provider, migration, production data, deployment, or live action.

This child is the final in-function sort-stage boundary, not final overall failure containment. Event-ID derivation and response/platform serialization remain explicit residuals. A protected Firebase deployment/readback and a made-up staged account check remain required before describing the behavior as live.

Dependencies and coordination

Claim protocol

Creation is not a claim. Before edits: re-fetch exact main; create and push a unique codex branch; assign this issue; add status:in-progress; and post an exact UTC claim naming branch, base, paths, invariants, exclusions, and active competing claims. The claim remains active through trustworthy RED, implementation, independent exact-head review, hosted CI, merge, exact-main verification, closure, and explicit release.

Activity

  1. added
    bugSomething isn't working
    priority:P1High-priority follow-up
    type:securitySecurity or privacy boundary
    area:firebaseFirebase services and data
    area:webWeb application and hosting
    size:XSOwner decision or very narrow change
    type:testingTest infrastructure and quality gates
    area:privacyPersonal data, consent, minimization, retention, and privacy operations
    status:in-progressClaimed and actively being implemented
    on Aug 2, 2026
  2. self-assigned this
    on Aug 2, 2026
  3. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    CLAIMED by /root at 2026-08-02T04:19:20Z on branch codex/issue-598-registration-sort, exact released base d462ff6.

    Exact ownership:

    1. functions/listMyRegistrations.js
      • only a separate catch-without-binding around the existing final Array.from(results.values()).sort(...) operation;
      • the comparator expression, token sequence, and runtime semantics remain unchanged; only indentation changes inside the new try boundary;
      • all A3–A8 query, projection, event, response, and ordering behavior remains immutable.
    2. functions/listMyRegistrations.test.js
      • one separately named DATA-001A9 block plus minimum synthetic fixture support;
      • every A3–A8 test/mock contract remains immutable except minimum additive support.
    3. SECURITY.md
      • one separately named DATA-001A9 row immediately after A8.

    Invariant: after App Check/Auth, the exact UID query, registration projection, event-ID derivation, and A7/A8 event work, any exceptional final registration-array construction, comparator, nested _seconds access, or numeric-coercion outcome returns only fixed unavailable / Registration data could not be loaded. through a catch with no binding. The caught value is never inspected, formatted, coerced, logged, attached, or serialized, and no partial callable response returns. Valid descending created-time order, fallback-to-zero behavior, ties, successful/empty/one-row bytes, lookup concurrency, runner minimization, and read-only behavior remain exact.

    Immutable exclusions: timestamp validation/normalization; malformed nonthrowing values; NaN/Infinity behavior; event-ID validation/derivation; sibling cancellation/order; response/platform serialization or platform logs; retries; schema/Rules/indexes/packages; Account UI/service/types/tests; officer docs; provider/deployment/data/migration/live behavior; all released A3–A8 hunks; active #571 paths/hunks; coordinating #504; draft #462; queued unclaimed Strava activity-ID precision child.

    The unique empty remote branch was pushed from exact current main before this marker. Live issues, PRs, remote branches, dependencies, and path claims were re-read; no competing registration-sort issue or claim exists. No source, test, documentation, package, or generated-file edit preceded this claim. This claim remains active through trustworthy RED, implementation, independent exact-head review, hosted CI, merge, exact-main/deployment truth audit, closure, and explicit release.

    Officer impact: None — My Account already discards every registration-list rejection detail and shows the same generic registration-load error.

    Officer documentation: None — this is an internal server sort-failure boundary; no officer procedure, screen, navigation, page structure, collected field, data movement, permission, account ownership, approval, or deployment process changes.

    Deployment evidence: none at claim time; source/tests/merge will not be described as website publication, Firebase deployment, outside-provider action, production-data change, migration, or live behavior.

  4. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    TRUSTWORTHY RED recorded before runtime or documentation edits.

    • Exact base: d462ff6.
    • Test-only binary diff SHA-256: dcd30a79fb071d5cc2f7cd7201266d843dad61ccb027e2eb8b62f47588de00f2.
    • Pinned Node 20 focused result: 31 cases total; 29 existing/control cases passed and exactly 2 new DATA-001A9 cases failed.
    • Intended failures: a retained createdAt._seconds getter and the later numeric-coercion hook each threw the exact hostile value after the exact UID query, both registration projections, and the complete single-event acquisition/snapshot/field projection. The old source returned that raw value instead of fixed unavailable / Registration data could not be loaded.
    • Each RED matched the exact earlier query/event stages, two data calls per registration, expected one/two nested seconds reads, expected zero/one coercion attempt, zero hostile-value inspection, zero console/Functions logging, and no resolved or partial callable response.
    • The new positive descending-sort and missing-time fallback control passed on old source.
    • Only functions/listMyRegistrations.test.js changed. Runtime, SECURITY, packages, Account/officer docs, Rules, providers, deployment, production data, and live behavior were untouched.

    This is the claimed final sort-stage boundary, not an unrelated pre-existing failure or a response/platform serialization claim.

  5. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    IMPLEMENTATION CANDIDATE — exact reviewed-head request

    • Exact base: d462ff6.
    • Candidate head: 3bb8fd5.
    • Candidate tree: fb78356422c4754e1c0b95db804d0bc03c22988a.
    • Exact three-file binary diff SHA-256: 0249c70b5658a9b76df360ec545dcd523f997341568c158183bffee5ba9d2d75.
    • Scope: exactly SECURITY.md, functions/listMyRegistrations.js, and the separately named DATA-001A9 block in functions/listMyRegistrations.test.js.
    • Worktree is clean; diff and syntax checks pass.

    Outcome: the existing final Array.from-and-sort operation now runs inside a separate catch without a binding. A nested _seconds access failure or numeric-coercion failure maps only to fixed unavailable / Registration data could not be loaded. The comparator expression, token sequence, and runtime semantics remain unchanged; only indentation changes inside the new try boundary. All A3–A8 boundaries, event work, successful responses, descending order, fallback-to-zero behavior, and read-only behavior remain unchanged.

    Trustworthy RED on untouched source: exactly 2 intended raw-escape failures after 29 existing/control passes. Both old-runtime cases exposed the exact hostile value only after the exact UID query, two registration projections, one complete event acquisition/projection, and the intended accessor/coercion prefix. The positive descending-order and missing-time fallback control passed before the runtime change.

    Pinned local verification:

    • DATA-001A3–A9 focused: 31/31.
    • Functions lint: passed.
    • Full Functions: 69 suites passed / 2 intentionally skipped; 7,490 passed / 64 intentionally skipped.
    • Frontend: 951/951.
    • TypeScript: passed.
    • Frontend lint: 118 files / 113 reviewed legacy errors / 6 reviewed warnings.
    • SPA: 11/11.
    • Workflow/release/artifact/dependency safety: 93/93.
    • Diagnostic build: passed.
    • Rules emulator: 418/418.
    • Real demo-only commerce emulator: 63/63.
    • Dependency audit snapshot: root 59 total with zero critical; root production 4; Functions 8. No dependency file changed and no forced update was applied.

    Three independent exact-head reviews are in progress.

    Officer impact: None — My Account already discards every registration-list rejection detail and shows the same generic registration-load error.

    Officer documentation: None — this internal server sort-failure boundary changes no officer procedure, screen, navigation, page structure, collected field, data movement, permission, ownership, approval, or deployment process.

    Deployment evidence: source, tests, local review, commit, and push only. The change is not merged. The website and runmprc.com were not published or verified; Firebase was not deployed/read back; no outside provider was configured or contacted; production data, migration, and live behavior were not accessed, changed, or verified.

  6. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    WORDING CORRECTION — supersedes every earlier byte-equivalent comparator phrase.

    The comparator expression, token sequence, and runtime semantics remain unchanged; only indentation changes inside the new try boundary. The issue body, claim marker, implementation-candidate marker, and PR #599 body have been edited to use that exact factual boundary.

    This wording correction changes no tracked file, commit, tree, patch, test result, claim scope, or delivery state. Exact head remains 3bb8fd5; tree fb78356422c4754e1c0b95db804d0bc03c22988a; patch SHA-256 0249c70b5658a9b76df360ec545dcd523f997341568c158183bffee5ba9d2d75.

  7. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    PR PREVIEW EVIDENCE

    PR #599 hosted CI run 30732412289 passed all five required jobs for exact head 3bb8fd5.

    Netlify deploy preview 6a6ec73fd569250008c8d477 is exact-head, deploy-preview context, state ready, HTTP 200, x-robots-tag noindex, and published_at null. It is not production website publication, runmprc.com verification, Firebase deployment/readback, outside-provider configuration, production-data action, migration, or live-behavior proof.

  8. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    COMPLETE / CLOSED / CLAIM RELEASED

    PR #599 was admin-squash-merged only after the maintainer's explicit instruction to self-review and merge, three independent exact-head final GO reviews, both reviewer-requested delivery-record corrections, and all five required hosted checks. Ordinary merge was blocked only by the external-review rule.

    Exact identities:

    • Reviewed head: 3bb8fd5
    • Exact main: 57ac85b
    • Exact parent: d462ff6
    • Identical reviewed/merge tree: fb78356422c4754e1c0b95db804d0bc03c22988a
    • Parent-to-main binary patch SHA-256: 0249c70b5658a9b76df360ec545dcd523f997341568c158183bffee5ba9d2d75
    • Exact scope: SECURITY.md, functions/listMyRegistrations.js, and functions/listMyRegistrations.test.js

    Verification:

    • Trustworthy RED: exactly 2 intended raw application-boundary failures after 29 existing/control passes on untouched runtime.
    • Focused final: 31/31.
    • Functions lint: passed.
    • Full Functions: 69 suites passed / 2 intentionally skipped; 7,490 passed / 64 intentionally skipped.
    • Frontend: 951/951.
    • TypeScript: passed.
    • Frontend lint: 118 files / 113 reviewed legacy errors / 6 reviewed warnings.
    • SPA: 11/11.
    • Workflow/release/artifact/dependency safety: 93/93.
    • Diagnostic build: passed.
    • Rules emulator: 418/418.
    • Real demo-only commerce emulator: 63/63.
    • PR CI 30732412289: all five required jobs passed on exact reviewed head.
    • Exact-main CI 30732611095: all five required jobs passed.
    • Three independent exact-head reviewers returned final GO for security/privacy, tests/compatibility, and docs/scope/backup-officer review.
    • Dependency snapshot remains root 59 total with zero critical, root production 4, and Functions 8; no dependency file changed.

    Delivery truth:

    • Source changed: yes.
    • Synthetic/local and hosted tests passed: yes.
    • Code merged: yes.
    • Netlify PR preview 6a6ec73fd569250008c8d477: exact reviewed head, deploy-preview, ready, HTTP 200, noindex, published_at null.
    • GitHub deployments for exact main: [].
    • Netlify exact-main production attempt 6a6ec8d87569330008962c25: production context, state error, published_at null.
    • Published runmprc.com release marker remains bounded WEB-002A — Publish bounded Shop and Events permissions containment #473 control/source 9ad6837 / 39ab864; DATA-001A9 — Redact My Account registration-sort failures #598 is not published.
    • Firebase deployed/read back: no.
    • Outside-provider configuration changed: no.
    • Production data, migration, or live behavior: not accessed, changed, or verified.

    Officer impact: None — My Account already discards every registration-list rejection detail and shows the same generic registration-load error.

    Officer documentation: None — no officer procedure, screen, navigation, page structure, collected field, data movement, permission, ownership, approval, or deployment process changed.

    The status label and assignee are being cleared. The remote work branch was deleted by the merge, the local worktree is detached at exact main, and all three #598 path/hunk claims are RELEASED. Malformed-but-nonthrowing timestamp semantics, event-ID derivation/validation, sibling cancellation/order, response/platform serialization/logging, retries, deployment/readback, and live proof remain separately claimable residuals.

  9. removed their assignment
    on Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:firebaseFirebase services and dataarea:privacyPersonal data, consent, minimization, retention, and privacy operationsarea:webWeb application and hostingbugSomething isn't workingpriority:P1High-priority follow-upsize:XSOwner decision or very narrow changetype:reliabilityReliability and recoverytype:securitySecurity or privacy boundarytype:testingTest infrastructure and quality gates

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions