Skip to content

feat(db): add service fee assessment schema and billing ADR - #5236

Closed
jeanduplessis wants to merge 9 commits into
mainfrom
transaction-service-fee-1-schema
Closed

feat(db): add service fee assessment schema and billing ADR#5236
jeanduplessis wants to merge 9 commits into
mainfrom
transaction-service-fee-1-schema

Conversation

@jeanduplessis

@jeanduplessis jeanduplessis commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Defines the service-fee requirements, technical design, and validation plan, then adds the reduced database schema needed to retain fee decisions and organization exemptions.

Why this change is needed

Adding a 5% Stripe line item covers the charge, but not the cases where no line exists: an exempt organization, a pre-activation purchase, a zero-rounded fee, or a fail-open error. The agreed scope also requires expected-versus-settled reporting, proportional refunds, dispute adjustments, and one commercial event across Checkout, Invoice, PaymentIntent, and Charge objects.

This is the first PR in a stacked series. It makes those requirements and tradeoffs reviewable before any runtime billing path starts charging a fee. Operator procedures belong in kilo-org/on-call, not this repo.

Stack: #5236 (this PR) → #5262#5263#5264#5265#5266.

How this is addressed

  • Add GOAL.md as the product requirements source, SPEC.md as the technical design, and VALIDATION.md as the end-to-end proof contract.
  • Add stripe_service_fee_assessments as one durable row per commercial billing event, with unique Stripe object indexes and outcome/amount constraints.
  • Use assessment_key directly as the assessment primary key and derive eligibility from outcome rather than storing either value twice.
  • Add one append-only organization_service_fee_exemptions log. Its newest row is current state, while assessments retain the exact historical row used for an exemption decision.
  • Record the architectural decisions and invariants in ADR 0004.

Human Verification

  • Reviewed the assessment and exemption schema against the durable-state requirements in .plans/service-fees/GOAL.md.
  • Reduced the design from three tables and 47 columns to two tables and 38 columns.
  • Confirmed migration 0221 is additive: two new tables with no mutations to existing billing tables.
  • Applied migration 0221 successfully to an empty PostgreSQL database with pnpm drizzle:verify-bootstrap.
  • Passed database and web typechecks, web lint, 391 targeted tests, and the repository markdown-table check.

Reviewer Notes

Human Reviewer Flags

  • Please review the product scope in GOAL.md before judging whether the assessment table is necessary. In particular: durable missed-fee records, historical exemptions, settled-only reporting, refunds, and disputes.
  • New billing ledger: one assessment per commercial event, not per Stripe object.
  • Exemptions are internal, exact-organization, append-only, and time-resolved. They are intentionally not written to customer-visible organization_audit_logs.
  • The large 0221_snapshot.json is generated Drizzle metadata. Review 0221_goofy_true_believers.sql and schema.ts, not the snapshot.

Code Reviewer Agent

Code Reviewer Notes
  • Additive only: two new tables, no existing billing table mutations.
  • organization_service_fee_exemptions is the complete log and current state is its newest row; there is no duplicated current-state table.
  • stripe_service_fee_assessments has 32 columns. Its application-owned assessment key is the primary key, and outcome is the only decision-state column.
  • Unique partial indexes on Checkout, Invoice, PaymentIntent, Charge, and fee-line IDs prevent webhook retries from creating duplicate fee revenue.
  • Checks encode row invariants for pending, charged, missed, exempt, refund, and dispute states.
  • outcome = exempt iff exemption_id is set, so an exempt assessment points to the exact log row that justified it.
  • Expected and charged fee remain separate because hosted Checkout discounts can make the settled fee lower than the fee prepared before Checkout.

Comment thread docs/adr/0004-stripe-service-fee-assessment.md Outdated
@kilo-code-bot

kilo-code-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental docs-only follow-up aligns SPEC, VALIDATION, and ADR 0004 with the two-table exemption-log design; previous schema-mismatch findings are resolved.

Files Reviewed (3 files)
  • .plans/service-fees/SPEC.md
  • .plans/service-fees/VALIDATION.md
  • docs/adr/0004-stripe-service-fee-assessment.md
Previous Review Summaries (4 snapshots, latest commit 2e27cdb)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 2e27cdb)

Status: 4 Issues Found | Recommendation: Address before merge

Executive Summary

The schema reduction is consistent, but SPEC/VALIDATION still describe the removed two-table exemption write, a third assessment table/id PK, and SQL that selects the dropped id column.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 4
Issue Details (click to expand)

SUGGESTION

File Line Issue
.plans/service-fees/SPEC.md 719 Admin set still describes lock/insert-history/upsert-current instead of appending one exemption-log row
.plans/service-fees/SPEC.md 966 Phase 1 still says three tables and idPrimaryKeyColumn; assessments now use assessment_key as PK
.plans/service-fees/VALIDATION.md 489 Helper 3.2 still filters WHERE a.id = ...; id was removed
.plans/service-fees/VALIDATION.md 565 Helper 3.7 still selects id from assessments
Files Reviewed (7 files)
  • .plans/service-fees/SPEC.md - 2 issues (previous Phase 6 numbering and refunded_gross_minor findings resolved)
  • .plans/service-fees/VALIDATION.md - 2 issues
  • packages/db/src/migrations/0213_service_fee_assessments.sql
  • packages/db/src/migrations/meta/0213_snapshot.json
  • packages/db/src/migrations/meta/_journal.json
  • packages/db/src/schema.test.ts
  • packages/db/src/schema.ts

Fix these issues in Kilo Cloud

Previous review (commit 88b4136)

Status: 2 Issues Found | Recommendation: Address before merge

Executive Summary

The latest commit fixed the ADR invariant cross-reference and started fixing the Phase 6 numbering, but the renumbering is incomplete (6. now appears twice), and the SPEC schema table still omits refunded_gross_minor.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
.plans/service-fees/SPEC.md 1045 Incomplete renumbering: after the previous line changed 5. to 6., this line is still 6. (duplicate), and the following line should become 8. — list should run 1–8
.plans/service-fees/SPEC.md 262 stripe_service_fee_assessments column table omits refunded_gross_minor, which the spec's refund section (line 781) requires as a typed column — carried forward, still unresolved
Files Reviewed (2 files)
  • .plans/service-fees/SPEC.md - 2 issues (1 new in this increment, 1 carried forward)
  • docs/adr/0004-stripe-service-fee-assessment.md - 0 issues (previous Invariant 10 cross-reference finding resolved: now correctly cites Invariant 11)

Notes: Incremental review of commit 88b4136 (two one-line documentation fixes). The ADR fix was verified against the Invariants section — Invariant 11 is indeed the Stripe test-mode coupon-allocation proof. The previous duplicate 5. finding in the Phase 6 list was addressed but the fix stopped short, creating a new duplicate 6.. No memory-leak-relevant code was introduced (documentation only); markdown-image-format rule not triggered (no images).

Fix these issues in Kilo Cloud

Previous review (commit 97a395c)

Status: 3 Issues Found | Recommendation: Address before merge

Executive Summary

The new service-fee GOAL/SPEC/VALIDATION plan documents are internally consistent and arithmetically correct; the findings are minor documentation issues: a duplicated Phase 6 step number, a missing refunded_gross_minor row in the SPEC's schema table, and the previously reported wrong invariant cross-reference in ADR 0004.

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 3
Issue Details (click to expand)

SUGGESTION

File Line Issue
.plans/service-fees/SPEC.md 1044 Phase 6 list has a duplicated step number 5. (lines 1043–1044), followed by 6./7.; renumber sequentially
.plans/service-fees/SPEC.md 262 stripe_service_fee_assessments column table omits refunded_gross_minor, which the spec's refund section requires as a typed column and the committed migration already includes
docs/adr/0004-stripe-service-fee-assessment.md 200 Alternatives section cites "Invariant 10" for the coupon-allocation proof; the proof is Invariant 11 (Invariant 10 is tax treatment) — carried forward, still unresolved
Files Reviewed (9 files)
  • .plans/service-fees/GOAL.md - 0 issues (fee math, examples, and eligibility rules verified against SPEC/VALIDATION)
  • .plans/service-fees/SPEC.md - 2 issues
  • .plans/service-fees/VALIDATION.md - 0 issues (journey amounts, coupon expectations, and SQL helpers verified against SPEC and schema)
  • docs/adr/0004-stripe-service-fee-assessment.md - 1 issue (carried forward; file unchanged in this increment)
  • packages/db/src/migrations/0213_careful_mastermind.sql - re-verified: additive DDL, includes refunded_gross_minor
  • packages/db/src/migrations/meta/0213_snapshot.json - generated metadata, consistent
  • packages/db/src/migrations/meta/_journal.json - generated journal entry, consistent
  • packages/db/src/schema.test.ts - enum expectations match schema
  • packages/db/src/schema.ts - re-verified: includes refunded_gross_minor at line 10541

Notes: Incremental review of commit 97a395c (three new .plans/service-fees/ documents). Activation constant 1_788_220_800 verified as 2026-09-01T00:00:00Z; rounding formula and all worked examples (20% promo → $1.96/$41.16, restricted coupon → 6.25% effective rate, $0.10 half-cent boundary) are consistent across all three documents. No HTML <img> tags in the new markdown, so the markdown-image-format rule is not triggered. No memory-leak-relevant code was introduced (documentation only).

Fix these issues in Kilo Cloud

Previous review (commit 8d5603a)

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The new service-fee assessment schema, exemption tables, constraints, and migration are consistent and additive; the only finding is a wrong invariant cross-reference in ADR 0004 (Invariant 10 cited instead of Invariant 11).

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

SUGGESTION

File Line Issue
docs/adr/0004-stripe-service-fee-assessment.md 200 Alternatives section cites "Invariant 10" for the coupon-allocation proof; the proof is Invariant 11 (Invariant 10 is tax treatment)
Files Reviewed (6 files)
  • docs/adr/0004-stripe-service-fee-assessment.md - 1 issue
  • packages/db/src/migrations/0213_careful_mastermind.sql - additive DDL for three new tables; indexes/constraints on empty new tables, no locking or data-loss concerns
  • packages/db/src/migrations/meta/0213_snapshot.json - generated Drizzle metadata, consistent with schema
  • packages/db/src/migrations/meta/_journal.json - generated journal entry, consistent
  • packages/db/src/schema.test.ts - enum registry expectations match new schema enums
  • packages/db/src/schema.ts - three new tables with checks/FKs matching the migration and ADR invariants

Notes: docs/operations/service-fees.md was added and then deleted within this PR (net zero), so it was out of scope. The ADR contains no images, so the markdown-image-format rule is not triggered. No memory-leak-relevant code was introduced (schema and docs only).

Fix these issues in Kilo Cloud


Reviewed by grok-4.6 · Input: 61.2K · Output: 6.8K · Cached: 235.6K

Review guidance: REVIEW.md from base branch main

Comment thread packages/db/src/schema.ts Outdated
Comment thread .plans/service-fees/SPEC.md Outdated
Comment thread .plans/service-fees/SPEC.md Outdated
Comment thread .plans/service-fees/SPEC.md Outdated
Comment thread .plans/service-fees/SPEC.md Outdated
Comment thread .plans/service-fees/SPEC.md Outdated
Comment thread .plans/service-fees/VALIDATION.md Outdated
Comment thread .plans/service-fees/VALIDATION.md Outdated
jeanduplessis and others added 9 commits August 19, 2026 15:55
Introduce the assessment and exemption tables, plus the operator
runbook and ADR that define one assessment per commercial event.
No runtime billing behavior changes yet.
On-call runbooks live in kilo-org/on-call. Leave the ADR here as the
engineering record.
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
Co-authored-by: kilo-code-bot[bot] <240665456+kilo-code-bot[bot]@users.noreply.github.com>
@jeanduplessis

Copy link
Copy Markdown
Contributor Author

Superseded by #5383, which consolidates the complete service-fee implementation into one PR against main.

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.

2 participants