Skip to content

feat(billing): export bounded reconciliation evidence - #582

Draft
seonghobae wants to merge 37 commits into
feat/stripe-reconciliation-scheduler-488from
feat/stripe-reconciliation-evidence-export-488
Draft

feat(billing): export bounded reconciliation evidence#582
seonghobae wants to merge 37 commits into
feat/stripe-reconciliation-scheduler-488from
feat/stripe-reconciliation-evidence-export-488

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Buyer/audit objective

Refs #488. This Draft child of #579 adds a tenant-scoped, bounded export of durable Stripe reconciliation evidence for incident review, diligence, and customer/auditor evidence without exposing raw webhook payloads, provider credentials, active lease-token hashes, or plaintext operator recovery references.

Exact current stack

  • protected develop: 2c328875e00e86537df3e965170be80532571cad;
  • exact live parent/base feat(billing): schedule Stripe reconciliation continuously #579: feat/stripe-reconciliation-scheduler-488@673fde2c10108783ddcc698cbe4c233d118c3ae9;
  • exact contributor head: 08d89b004c66e0f0bc57c40d2fcd77965a865213;
  • branch: feat/stripe-reconciliation-evidence-export-488;
  • state: Draft and mechanically mergeable at the latest fresh refetch;
  • current submitted formal reviews: none; current inline review threads: none.

Any parent, contributor-head, protected-base, review, or check movement invalidates ancestry- and revision-sensitive evidence until freshly revalidated.

Evidence export contract

  • Tenant authority derives only through persisted billing_stripe_subscriptions -> billing_stripe_customers -> organization_id; URL tenant input never substitutes persisted provider/tenant authority.
  • Authentication plus owner/admin membership is required. Unknown/non-member workspace authority remains hidden behind the existing not-found boundary; ordinary members receive forbidden.
  • Event selection defaults to 50 and is capped at 100 before nested history is read; combined selected attempt/recovery history is capped at 1,000 rows before materialization, with stable fail-closed 413 behavior.
  • The export contains decision-relevant provenance: Stripe Event/Subscription identity, provider creation time, immutable payload SHA-256, receipt/queue/completion time, processing state, attempt/recovery history, stable error codes, and claim-decision linkage where present.
  • Durable attempt_count must match a complete contiguous append-only attempt history; job lifecycle, latest attempt lifecycle, active-lease state, and recovery/attempt outcome/error linkage must agree. Contradictory restored state fails closed rather than becoming authoritative evidence.
  • Selected Events and their nested attempt/recovery histories are read under one SQLite snapshot, so concurrent worker progress cannot create a mixed-time evidence artifact.
  • Raw webhook payloads, Stripe/provider credentials, active lease-token hashes, and plaintext recovery references are not exported. Recovery references are portable only as SHA-256 correlation values.
  • The response uses Cache-Control: no-store, X-Content-Type-Options: nosniff, an explicit JSON content type, and a fixed attachment filename.
  • Successful disclosure is fail-closed on durable access logging. The report is serialized once; the audit metadata records schemaVersion, eventCount, and evidenceDocumentSha256; and those exact serialized bytes are then returned. The audit event is therefore bound to the specific exported artifact without copying its private contents into the audit stream.
  • docs/doctoring/stripe-reconciliation-evidence-export.md records active-PR versus protected-shipped truth, operator next actions, privacy/boundedness rationale, and current evidence limitations.

TDD and review-driven hardening

The slice was built and hardened through realistic contract-first boundaries on the existing #488 stack. Historical RED/GREEN pairs cover the absent repository module, absent authenticated route, orphaned recovery links, incomplete append-only attempt history, job/attempt lifecycle contradictions, recovery/attempt contradiction, lease consistency, and nested-history bounds. The current tree also contains a file-backed WAL concurrency regression proving the export observes one consistent snapshot while a second connection advances worker state.

A fresh current-source audit found that successful evidence disclosures were access-logged only with schema version and Event count. Two distinct exports with the same count/schema were therefore not cryptographically distinguishable in the audit stream even though the route already had the exact portable artifact before disclosure.

  • Test-first commit 49d9010108fd63b757395bc10af4bd6367630d81 changed the existing authenticated API acceptance path to hash the exact response body and require that digest in the durable audit metadata. Its hosted workflow generation was cancelled by the immediate production repair and is retained as test-first lineage, not as passing or failed merge evidence.
  • Production commit ab8692718dd1c40c1fd2c4c4551eff66a2fa8390 serializes the report once, computes SHA-256 over those exact bytes, writes evidenceDocumentSha256 before disclosure, and returns the same bytes. Audit-sink failure still returns stripe_reconciliation_evidence_export_audit_failed without disclosing the report.
  • Current head 08d89b004c66e0f0bc57c40d2fcd77965a865213 updates code-current doctoring for the digest-binding and one-snapshot contracts.

No security gate, threshold, production file, or review requirement was weakened to obtain the repair.

Current evidence boundary

Fresh workflow runs for exact contributor head 08d89b004c66e0f0bc57c40d2fcd77965a865213 exist but are currently queued and therefore non-passing:

  • Server Tests 32762464997 — queued;
  • Dependency Review 32762465045 — queued;
  • OSV Scanner 32762465461 — queued.

Other applicable exact-head gates are absent from this stacked-head enumeration and are non-passing, not implicitly successful. The repository-wide Server Tests exact-contributor checkout repair remains owned by #523 and has not reached protected develop; the centrally reusable SAST/Security exact-head defect remains on its existing .github owner path. Synthetic merge, predecessor, cancelled, absent, skipped-required, model-only, status-only, queued, or stale evidence does not transfer. There is no qualifying independent exact-current-head approval.

Remain Draft. Do not integrate independently of #579/#575 and the preceding #488 stack. Before integration, refetch the then-live prerequisite stack and require every applicable exact-head deterministic/browser/owned statement-branch-function-line coverage/docstring/CodeQL/SAST/security/dependency/supply-chain/package/SBOM/provenance/recovery/review gate under live governance.

Primary implementation basis

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant