Skip to content

PAY-003A13 — Reject impossible Checkout Session/Event chronology #590

Closed

Description

@daliu

Outcome

Reject a newly delivered supported Checkout Event when its already admitted embedded Checkout Session created second is later than the already admitted outer Event created second.

Invariant

After exact processed-Event replay and the existing realm, lifecycle, metadata, outer Event-time, and embedded Session-time structural checks:

Checkout Session.created <= Event.created

Equality is valid because both fields have whole-second resolution. An earlier Session time is valid. A later Session time is contradictory evidence and must produce fixed durable needs_review:invalid_checkout_session_event_chronology before any reference, fallback, target, ownership, provider-binding, money, PaymentIntent, predecessor, or business-state work.

The ledger must retain the valid outer stripeCreatedAt, keep target fields null, and use the existing fixed redacted log. Neither compared raw value may be stored, returned, or logged.

Allowed transitions and failure cases

  • Exact processed-Event replay stays first and read-only.
  • Outer Event realm, embedded Session realm, lifecycle, metadata schema, outer Event-time, and Session-time structural failures keep precedence.
  • Newly delivered later-Session contradictions change from target-capable behavior to target-free durable review.
  • Equal and earlier Session times retain existing Checkout outcomes.
  • A contradictory claimed missing target becomes durable review; a chronologically valid claimed missing target remains retryable.
  • Refund Charge chronology, all Dispute behavior, and unsupported Events remain unchanged.
  • Provider delivery order and the current server clock are not part of this comparison.

Exact implementation scope

  1. functions/stripeWebhook.js
    • One Checkout-only strict-greater-than comparison immediately after Session-created structural admission.
    • One fixed reason: invalid_checkout_session_event_chronology.
  2. functions/stripeWebhook.test.js
    • One separately named PAY-003A13 matrix/helpers.
    • Reconcile only the stale PAY-003A10 later-Session acceptance control.
    • Correct the PAY-003A11 Event epoch/max fixture to supply matching embedded Session time.
    • Correct the weak PAY-003A8 non-Dispute Event-boundary fixture so its embedded time equals the tested outer boundary.
  3. STRIPE_COMMERCE_DESIGN.md
    • One named PAY-003A13 SOURCE ONLY / NOT LIVE section immediately after A12.
    • Only chronology-specific A12 wording needed to mark the former exclusion/residual as superseded by A13.

Everything else is excluded.

Trustworthy RED

Before runtime, compatibility-fixture, or documentation changes, add only a named test helper and a PAY-003A13 registration/order matrix across all four Checkout lifecycles. With structurally valid Session time exactly one second later than the outer Event, current source must be shown reaching its existing target/business outcomes instead of target-free chronology review.

Use synthetic signed fixtures only. No provider, credential, payment, customer/member record, production service, or live mutation.

Acceptance

  • All four supported Checkout lifecycles across registration and order reject a Session time later by one second.
  • Fixed result/log, valid outer ledger time, null targets, exact ledger-only reads, no Timestamp.now, no compared-value disclosure or Session-time conversion.
  • Contradiction wins before metadata/client-reference/legacy fallback, ambiguous target, malformed reference, binding conflict, money, PaymentIntent, and predecessor work.
  • Claimed missing-target contradiction is durable; a valid missing target remains retryable.
  • Earlier precedence is unchanged through invalid Session-created structural evidence.
  • Exact rejected replay is read-only and logs once; richer historical ledgers remain authoritative.
  • Equality and earlier Session time are valid across both domains and all lifecycles.
  • Unix epoch equality and Firestore-maximum equality are valid.
  • PAY-003A11 still projects only admitted outer Event time to missing paidAt; Session time never replaces it.
  • PAY-003A8 through A12, refund chronology, all Dispute lifecycles, and unsupported Events remain compatible.
  • Focused tests, complete webhook/Functions tests, frontend/safety/SPA/Rules/commerce emulator gates, lint, build, diff check, and non-forced audits pass.

Migration and compatibility

No schema, Rule, index, package, workflow, API, provider configuration, migration, backfill, or history-reprocessing change. Already-processed ledgers remain authoritative on replay. Existing business records, provider bindings, payment fields, and historical rows are not inspected or repaired.

Stripe documents Checkout Session and Event created as Unix-second object-creation timestamps, and the installed Stripe 14.25.0 types require both. The supported lifecycle Events concern a previously created Session. This source boundary treats chronology as admitted evidence; it does not claim canonical provider endpoint/version truth or exact payment time.

Dependencies and exclusions

Depends on completed PAY-003A2/A4/A8/A12 admission slices. Excludes current-clock freshness/skew, Session expires_at, endpoint/API-version policy, provider retrieval/history repair, already-paid missing-time repair, paid-after-cancellation policy, other Charge/Dispute decisions, PAY-003B/C, reconciliation, alerts, protected release, provider/data/payment actions, and live verification.

Officer and deployment truth

Officer impact: None — server-only pre-target evidence ordering; no officer screen, task, field, permission, topology, approval path, incident step, or available recovery action changes.

Officer documentation: None — current officer procedures remain factual; engineering truth belongs in STRIPE_COMMERCE_DESIGN.md.

Deployment evidence: Source, tests, merge, website publication, runmprc.com, Firebase deployment/readback, Stripe/provider configuration/action, production data, checkout/payment/refund/dispute activity, and live behavior must be reported separately. Source/tests alone prove none of the later states.

Claim rule

Claim only this atomic child after confirming the exact base and disjoint ownership. Stop on any path/hunk overlap, provider/API-version dependency, need for production data or secrets, or change outside the exact scope.

Activity

  1. added
    priority:P0Launch blocker or urgent security risk
    type:securitySecurity or privacy boundary
    area:firebaseFirebase services and data
    size:SSmall focused issue
    area:stripeStripe payments and financial lifecycle
    type:testingTest infrastructure and quality gates
    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-02T01:49:31Z on codex/issue-590-checkout-chronology, exact base 56332507f394f419616acfa6320f1bfbb16c60b5, tree dd970cd2994ffeafa52b603ea3094ca8224552cf.

    Exact ownership:

    • functions/stripeWebhook.js: one Checkout-only strict chronology comparison and fixed reason after Session-created structural admission.
    • functions/stripeWebhook.test.js: one separately named PAY-003A13 matrix/helpers; only the stale A10 later-Session control, A11 epoch/max Session construction, and weak A8 embedded-time boundary fixture corrections required for truthful compatibility.
    • STRIPE_COMMERCE_DESIGN.md: one separately named PAY-003A13 SOURCE ONLY / NOT LIVE section after A12 plus only chronology-specific A12 wording that must identify the former exclusion as superseded.

    Invariant: after exact replay and existing realm/lifecycle/metadata/outer-time/Session-time admission, Session.created <= Event.created. Equality and an earlier Session remain valid. A later Session becomes target-free durable needs_review:invalid_checkout_session_event_chronology with valid outer ledger time, null targets, fixed redacted logging, and no reference/fallback/binding/money/PaymentIntent/predecessor/state work.

    Excluded: current-clock freshness/skew, expires_at, endpoint/API-version/provider proof, receipt order, other Event-family runtime, schema/Rules/index/packages/workflows/migration/history, PAY-003B/C, deployment/provider/data/payment/live work, active #571/#504 paths, and draft #462. Any exact overlap or provider/version dependency is STOP-and-coordinate. No edit preceded this claim.

  4. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    TEST-ONLY RED — exact claimed base 56332507f394f419616acfa6320f1bfbb16c60b5

    • Test-only diff: functions/stripeWebhook.test.js (+67 lines)
    • Diff SHA-256: 027964b02b0151a1adb6c061dee22c94c231c0cd121a8f6a30cdb61cb31a1f51
    • Command (Node 20): npm --prefix functions run test:run -- --runInBand stripeWebhook.test.js -t 'PAY-003A13 Checkout Session/Event chronology'
    • Result: FAIL as expected — 8 failed, 760 skipped, 1 suite failed.
    • Demonstrated defect: all four supported Checkout lifecycles, across registration and order targets, accept Session.created = Event.created + 1, mutate the business target/create provider bindings, and record payment_confirmed, payment_failed, or payment_expired instead of the fixed target-free needs_review:invalid_checkout_session_event_chronology result.
    • Production/provider/live data: not touched. Fixtures and in-memory doubles only.

    The runtime and documentation remain unchanged at this marker.

  5. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    CANDIDATE READY on unchanged exact base 56332507f394f419616acfa6320f1bfbb16c60b5. Exact three-file diff SHA-256: 172f0cbac9e1d461e3e34e41bf158dbbbed54152a9b4ed1470b3076eff8f0f80; git diff --check passes.

    Outcome: after the existing Checkout realm, lifecycle, metadata, outer Event-time, and Session-time structure checks, one Checkout-only strict comparison now requires Session.created <= Event.created. A later Session second receives fixed durable target-free needs_review:invalid_checkout_session_event_chronology; equality and earlier chronology keep existing behavior. Exact replay remains authoritative. The valid outer Event time remains the ledger timestamp and the only Checkout evidence projected to missing paidAt.

    Evidence on exact Node 20.20.2 / Java 21, demo emulators only:

    • Trustworthy test-only RED: 8 expected failures across four lifecycles x two domains; test-only diff SHA 027964b02b0151a1adb6c061dee22c94c231c0cd121a8f6a30cdb61cb31a1f51.
    • PAY-003A13: 62/62.
    • Complete webhook: 822/822.
    • Functions lint: pass; Functions full: 7,284 passed / 64 intended skips.
    • Frontend: 951/951; workflow/artifact/supply safety: 86/86; SPA: 11/11.
    • Firestore Rules demo emulator: 418/418.
    • Commerce command-journal demo emulator: 63/63.
    • Frontend lint baseline: 118 files / 113 reviewed legacy errors / 6 reviewed legacy warnings.
    • Diagnostic build: pass; workflow YAML and diff checks: pass.
    • Dependency audits, unchanged by this no-package patch: root full 59, root production 4, Functions 8; no forced upgrade.
    • One discarded diagnostic invocation inherited shell-default Node 22 and reproduced the known Error-own-surface mismatch in an unrelated projection suite; the isolated suite passed 25/25 and the full suite passed under the required Node 20 runtime above.

    Independent exact-diff reviews:

    • Runtime/security: GO — correct precedence, safe-integer comparison, target/binding/business/money/state isolation, durable replay-safe result, outer Event time, fixed redacted logging, and no non-Checkout spillover.
    • Tests/compatibility: GO — trustworthy RED; complete later/equal/earlier, precedence, isolation, replay, boundaries, paidAt, compatibility, and mutant-resistance coverage; only the three claimed compatibility fixtures changed.
    • Design/backup officer: GO — official provider basis and source-only contract are factual; purpose, approvers, prerequisites, order, result, stop/proof/undo/escalation, Mermaid/text alternative, migration/residuals, and separate delivery truths are complete; officer guides remain factual.

    Officer impact: None — server-only pre-target evidence comparison.

    Officer documentation: None — no officer screen, task, field, permission, topology, approval path, incident step, or available recovery action changed; engineering truth is in STRIPE_COMMERCE_DESIGN.md.

    Deployment evidence: Source/tests only. No code is merged yet. No website publication, runmprc.com verification, Firebase deployment/readback, Stripe/outside-provider action or configuration, production-data change, checkout/payment/refund/dispute, or live verification occurred. Claim remains held pending commit, hosted CI, merge, exact-main verification, and explicit release.

  6. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    PR #591 is ready at exact reviewed head 8929be85a8276a02a2222c5b64e53d3723799ec4, tree 8a000d30283e1b6e876b703dbf25a27182cd11bf, patch SHA-256 172f0cbac9e1d461e3e34e41bf158dbbbed54152a9b4ed1470b3076eff8f0f80.

    Hosted self-review confirms one commit, the exact claimed base 56332507f394f419616acfa6320f1bfbb16c60b5, and only the three claimed files (47/3 design, 8/0 runtime, 601/3 tests). The hosted diff hash matches the independently reviewed local candidate exactly. No actionable review findings remain.

    All three independent reviews are GO. Hosted CI and the nonproduction preview checks are running. No merge, deploy, provider, data, payment, or live action is claimed. Claim remains held.

  7. removed their assignment
    on Aug 2, 2026
  8. daliu commented on Aug 2, 2026

    @daliu
    ContributorAuthor

    COMPLETE / CLOSED / CLAIM RELEASED — PAY-003A13.

    PR #591 squash-merged exact reviewed head 8929be85a8276a02a2222c5b64e53d3723799ec4 as exact main 38600a13aeaf57fa1c4d5571efa72af09ea983a1. Reviewed and merged tree 8a000d30283e1b6e876b703dbf25a27182cd11bf is identical. Patch SHA-256 remained 172f0cbac9e1d461e3e34e41bf158dbbbed54152a9b4ed1470b3076eff8f0f80.

    Ordinary squash merge was refused only by the repository approval rule after every hosted check and all three independent reviews were GO. The administrator merge did not bypass a failing code, preview, or deployment check. The CLI then reported only a local worktree checkout collision after the remote merge had succeeded; remote state, exact tree identity, and branch deletion were verified directly.

    Final evidence:

    • Source changed: yes, exact main above.
    • Synthetic tests passed: yes — A13 62/62; webhook 822/822; Functions 7,284 plus 64 intended skips; frontend 951/951; safety 86/86; SPA 11/11; Rules demo emulator 418/418; commerce demo emulator 63/63; lint/build/YAML/diff green.
    • Code merged: yes, PR PAY-003A13: reject impossible Checkout chronology #591.
    • Exact-main CI: run 30728441536 passed all five jobs for exact main.
    • GitHub deployments for exact main: [].
    • Netlify PR preview: deploy 6a6ea6c1ad8a810008fd922f, ready, deploy-preview context, nonproduction, published_at: null; HTTP 200 with x-robots-tag: noindex.
    • Netlify exact-main attempt: deploy 6a6ea778f36a7e00075f7cad, production context, state error, published_at: null.
    • Website published from this issue: no.
    • runmprc.com: HTTP 200 checked 2026-08-02 UTC, but the published deploy remains bounded WEB-002A — Publish bounded Shop and Events permissions containment #473 deploy 6a6dc9ea588b0c0008036312, source 9ad6837756cdd409d296009fde5082eeeae5c059; PAY-003A13 — Reject impossible Checkout Session/Event chronology #590 is not published there.
    • Firebase deployed/read back: no.
    • Stripe or outside provider configured/contacted: no.
    • Production data changed: no.
    • Checkout/payment/refund/dispute performed: no.
    • Production behavior verified: no.

    Officer impact: None — server-only pre-target evidence comparison.

    Officer documentation: None — no officer screen, task, field, permission, topology, approval path, incident step, or available recovery action changed; STRIPE_COMMERCE_DESIGN.md contains the source-only engineering contract.

    Issue is closed, assignee and in-progress label removed, remote branch deleted, and all #590 path/outcome claims are released at exact main 38600a13aeaf57fa1c4d5571efa72af09ea983a1.

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:stripeStripe payments and financial lifecyclepriority:P0Launch blocker or urgent security risksize:SSmall focused issuetype: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