Skip to content

PAY-002B2C4C1 — Freeze unbound attempt-2 Checkout Session result evidence policy #246

Description

@daliu

Officer impact: None — this defines an unused server-side safety policy. It changes no page, checkout, officer task, payment, permission, or live service.

Officer documentation: None — no current officer procedure changes because the policy is not connected to an endpoint.

Deployment evidence: None at creation. Closure must distinguish source/tests/merge from website publication, Firebase deployment, Stripe configuration, production data, and live behavior.

Problem

PAY-002B2C4B/#238 ends at a fixed send_permitted retry-safety classification. It makes no Stripe call and records no provider result. The existing initial reconciliation classifier rejects provider attempt 2, and the journal exports no attempt-2 result API.

C4B proves only that pre-send evidence was recorded before its clock limits. No current code observes the Stripe POST boundary, and a Stripe create response does not echo or prove the idempotency key. A pre-send marker, reported response shape, or self-asserted digest must never be treated as proof that Stripe received, accepted, or completed a request.

Non-negotiable invariant

This child may classify only the shape of closed, synthetic, future-adapter evidence. Its sole positive shape is an unbound candidate that still requires trusted dispatch evidence, persistence, and business validation.

It must never claim dispatch, provider acceptance, success, payment, or authority. It must never retry, authorize attempt 3, persist, complete a command, write a registration/order/hold, expose a Session ID or URL, or claim that its future evidence adapter is trusted.

Atomic outcome

Add one unused pure CommonJS API:

classifyAuthorizedStripeCheckoutResultEvidence(input)

It accepts only a primitive, length-bounded, canonical JSON string containing closed enum evidence. Parsing creates the ordinary record inside the module. The string must be deterministic and exact; object provenance is never inferred from mutable JavaScript prototypes. It returns one of two frozen fixed results and never echoes supplied values:

  • { providerResultPolicySchemaVersion: 1, classification: 'unbound_result_candidate', state: 'requires_dispatch_evidence_persistence_and_business_validation' }
  • { providerResultPolicySchemaVersion: 1, classification: 'reconciliation_required', state: 'requires_reconciliation' }

These are exact three-key objects; no extra key is allowed.

Malformed or schema-hostile input throws one fixed frozen error:

  • name: CommerceProviderResultError
  • code: invalid_provider_result_evidence
  • message: Commerce provider result evidence is invalid.

The error name, code, and message descriptors must be non-enumerable, read-only, and non-configurable. Each error instance, the error prototype, and the error constructor must be frozen.

Exact version-1 serialized input: 16 fields only

The primitive string is limited to 1,024 UTF-16 code units. It must equal the module's deterministic JSON.stringify reserialization using the field order below. Whitespace, reordered keys, duplicate/extra/missing keys, alternate escapes or number spellings, non-object JSON roots, and oversized or invalid JSON fail with the fixed error.

  1. providerResultPolicySchemaVersion — exactly 1
  2. provider — exactly stripe
  3. providerAttempt — exactly 2
  4. providerOperation — exactly checkout_session_create
  5. planBindingexact | missing | conflicting
  6. sendEvidenceBindingexact | missing | conflicting
  7. evidenceSourcereported_direct_response | unverified_or_missing | conflicting
  8. evidenceCompletenesscomplete | partial | conflicting
  9. responseEvidencenone | accepted | timeout | connection_lost | conflict | external_dependency_failure | rate_limited | server_failure | other_failure | unknown | conflicting
  10. providerObjectEvidencenone | exact_open | exact_complete | exact_expired | exact_unknown | missing_reference | not_found | conflicting
  11. environmentEvidenceexact | missing | conflicting
  12. parameterEvidenceexact | missing | conflicting
  13. resultReferenceEvidencebounded_opaque | missing | invalid | conflicting
  14. redirectEvidencevalidated_checkout | missing | invalid | conflicting
  15. paymentEvidencenone | unpaid | paid | no_payment_required | processing | unknown | conflicting
  16. expiryEvidencevalid_future | missing | invalid | expired | unknown | conflicting

The input must not contain dispatch binding/evidence, idempotency evidence, result binding, raw IDs, URLs, money, timestamps, status codes, provider bodies, free text, personal data, secrets, or caller authority.

Sole unbound candidate tuple

  • exact plan, C4B pre-send-evidence, environment, and immutable-parameter projections;
  • reported_direct_response;
  • complete evidence;
  • accepted response category;
  • exact open Checkout Session projection;
  • bounded opaque reference;
  • validated Checkout redirect projection;
  • unpaid payment evidence;
  • valid future expiry evidence.

This returns only the fixed unbound candidate. All 46 single-enum alternate values return the same fixed reconciliation result.

The binding and evidence categories are assertions reported by a later adapter. This classifier creates and trusts no projector. It does not prove dispatch, idempotency, Stripe state, plan authority, money, membership, inventory, capacity, or business state.

Required tests

  • The sole tuple returns the fixed frozen unbound-candidate singleton.
  • All 46 single-enum alternate values remove candidate status and return the same frozen reconciliation singleton.
  • Timeout, connection loss, conflict, dependency failure, rate limit, server failure, other failure, and unknown response reconcile.
  • Paid, no-payment-required, processing, exact_complete, exact_expired, wrong/missing environment, parameters, reference, redirect, and expiry reconcile.
  • Wrong version/provider/attempt/operation and unknown enum values fail with the exact fixed error.
  • Every non-string input—including null, booleans, numbers, arrays, ordinary/class/private-slot objects, dates, wrappers, accessors, proxies, and re-branded native objects—fails before property access or hostile invocation.
  • Empty, oversized, invalid, whitespace-bearing, reordered, duplicate-key, missing/extra-key, alternate-escape/number, non-object-root, wrong-type, Unicode-confusable, and future-enum serialized inputs fail with the exact fixed error.
  • Object.prototype pollution present before module load or introduced later fails closed without invoking hostile accessors.
  • Error/result shapes are frozen, byte-equivalent where applicable, and contain no supplied canary.
  • Outputs expose no send/dispatch/execute/persist boolean, success state, Session ID/URL, amount, key, attempt 3, or business transition.
  • Source has no Firebase, Stripe SDK, network, logger, environment, clock, randomness, filesystem, dynamic import, journal, index, or runtime edge. A literal static regression check must reject dispatchBinding, dispatchEvidence, idempotencyEvidence, resultBinding, execution_started, and active_exact.
  • No production source imports this module.
  • Full Node 20 Functions lint/tests and relevant hosted gates pass.

Exact ownership

  1. New functions/commerceProviderResult.js
  2. New functions/commerceProviderResult.test.js
  3. STRIPE_COMMERCE_DESIGN.md — separately named C4C1 source-only policy section and direct sequence references only.
  4. SYSTEM_DESIGN.md — separately named C4C1 source-only policy/diagram text only; no persisted collection row. The diagram must show reported evidence entering the unbound policy and stopping at a later dispatch-evidence, persistence, and business-validation boundary; it must never draw C4B directly to a trusted Stripe result.
  5. SECURITY.md — PAY-002/C4C1 ledger text only; preserve RISK-014 and RISK-035.
  6. IMPLEMENTATION_PLAN.md — PAY-002 sequence/status text only.
  7. GITHUB_ISSUES.md — PAY-002 boundary/status text only.
  8. GITHUB_ISSUE_SLICES.md — one C4C1 row plus immediate downstream dependency wording only.
  9. OPERATIONS_RUNBOOK.md — separately named synthetic source-only verification section only.

Explicit exclusions

No commerceCommandJournal.js or journal tests; Firestore Rules/emulator; Stripe SDK/network; dispatch observer; result projector implementation; runtime/index/checkout/webhook adoption; persistence; Session ID/URL; money; business/member data; package/lock/workflow/provider/deploy/data change; production access; or officer procedure.

Do not define attempt-2 result persistence, durable response replay, retention, late-result/takeover rules, business-record attachment, hold handling, payment confirmation, or attempt 3. A later runtime-adjacent child must supply trusted dispatch evidence and result persistence before this candidate can advance. PAY-002C/D and PAY-003B retain business and provider validation.

Dependencies and coordination

PAY-002B2C4B/#238 is the direct dependency. PAY-002B2C3A/#184 is the closed-policy vocabulary precedent. Hosted commerce-journal gate #167 is validation context only; this pure child requires no emulator change.

OAUTH-001C1B/#242 is complete and released at main e2e1987f3604422fb78ee76006b1379cd66761d1. A live duplicate audit found no attempt-2 result evidence policy issue.

Claim protocol

Creation is not a claim. Before editing, re-read live comments and open PRs, resolve any exact-hunk overlap, assign the issue, post a UTC timestamped claim with branch and exact base, and move status:ready to status:in-progress.

Metadata

Metadata

Assignees

Labels

area:stripeStripe payments and financial lifecyclepriority:P0Launch blocker or urgent security risksize:MMedium multi-file issuetype:architectureArchitecture and contract designtype:reliabilityReliability and recoverytype:securitySecurity or privacy boundarytype:testingTest infrastructure and quality gates

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions