feat(web): record sales-demo spend before a reset discards it - #5496
Merged
Conversation
The sales-demo reset deletes the org's usage and credit rows, so demo cost left no trace after the daily cron ran. Add the `sales_demo_spend_ledger` table and write one row per reset, taken from the org's `microdollars_used` counter, which the LLM, Exa, and compute charge paths all increment. A reset that discards no spend writes no row. A check constraint keeps a zero or negative row out of the table.
Contributor
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (6 files)
Reviewed by grok-4.6 · Input: 123.7K · Output: 12.5K · Cached: 692.7K Review guidance: REVIEW.md from base branch |
iscekic
enabled auto-merge (squash)
August 25, 2026 19:46
pandemicsyn
approved these changes
Aug 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A sales-demo reset (#5459) deletes the org's
microdollar_usage,exa_usage_log,compute_usage_charge, andcredit_transactionsrows, then zeroes the org balance columns. The daily cron runs that reset for every live demo, so demo cost disappeared within 24 hours and finance had no way to account for it.This adds a separate ledger table,
sales_demo_spend_ledger, and writes one row inside the reset transaction before the deletes:microdollars_usedcomes from the org counter at reset time. The LLM path (mutateOrganizationUsage), the Exa path, and the container compute settlement all increment that counter, so one value covers all three spend sources.period_startis the previoussales_demo_last_reset_at, or the org'screated_atfor the first reset.period_enddefaults to the reset time, so each row is a closed window.sales_demo_spend_ledger_spend_positivecheck constraint enforces that at the database level.organization_idandowner_kilo_user_idonly. It stores no name or email, so it adds no PII andsoftDeleteUserneeds no change; the org row survives a reset and holds the name.ON DELETE restrict, matchingcompute_usage_charge, so a demo org cannot be hard-deleted out from under its spend history.Monthly demo cost is then one query:
Out of scope, worth a separate look: the reset leaves orphan
microdollar_usage_metadatarows (that table has no FK tomicrodollar_usage), and it never resetsexa_monthly_usage, so a demo keeps its Exa free-allowance consumption across resets within a month.Verification
pnpm --filter web jest src/routers/admin/sales-demo-router.test.ts— 10 passed, including the two new cases: a dirty reset writes one row of 1,000,000 microdollars with the owner and window, and a clean reset writes none.pnpm --filter web jest packages/db/src/schema.test.ts src/app/api/cron/sales-demo-reset src/lib/organizations/sales-demo— 12 passed; the schema test proves the generated migration matches the schema.pnpm lint,pnpm typecheck,pnpm format— clean.pnpm drizzle migrateapplied0227_exotic_scarecrow.sqlto a local database.No manual UI test. The change has no UI.
Visual Changes
N/A
Reviewer Notes
restoreSalesDemoOrganization, inside the same transaction that holdsFOR UPDATEon the org row, so a failed reset writes no ledger row.Note for finance
Nothing is lost yet if this lands before 2026-08-26 05:00 UTC. Sales-demo orgs first existed on 2026-08-25 18:40 UTC (#5459), and the reset cron runs at
0 5 * * *, so the first spend-destroying reset has not run.microdollar_usage,exa_usage_log,compute_usage_charge, andcredit_transactionsfor the org, then zeroes its balance columns. No archive, no analytics sink, no per-request export holds a copy.owner_kilo_user_idtokilocode_users.id. Each row is one closed window,period_starttoperiod_end, so no window double counts.