You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(config): purchase_delay_hours defaults to 0 in the DB but is documented as 48 #1934
The documented default for purchase_delay_hours is 48, but a freshly migrated database stores 0. A fresh install therefore executes approved purchases immediately, with no free-cancel window.
internal/database/postgres/migrations/000070_purchase_history_revocation.up.sql:72 says "default 48", but line 77 adds purchase_delay_hours INT NOT NULL DEFAULT 0.
000001_initial_schema.up.sql:273 seeds the global_config row (id=1), so the row always exists and the column default of 0 applies.
The 48 fallback (DefaultPurchaseDelayHours, internal/config/store_postgres.go around line 162) only runs on sql.ErrNoRows, which a migrated database never returns.
Steps to verify
Create a new database and run all migrations.
SELECT purchase_delay_hours FROM global_config WHERE id = 1; returns 0.
GET /api/config returns purchase_delay_hours: 0; approving a purchase executes immediately.
Expected behaviour
Either the shipped default is 48 as documented (free-cancel window on by default), or the docs and constants say 0 consistently.
Proposed fix
Needs a product decision:
A: new migration ALTER TABLE global_config ALTER COLUMN purchase_delay_hours SET DEFAULT 48 plus an UPDATE for rows still at 0 only if existing installs should change (they may have chosen 0 deliberately; probably leave them).
B: keep 0 and fix the comments and constants: types.go:61-66, 000070...up.sql:72, and the DefaultPurchaseDelayHours fallback in store_postgres.go.
Deploy hazard: migrations run under auto-migrate at deploy, so option A changes behaviour for new databases at rollout time; stage it first and note it in the release notes.
Claiming (claude-cc-libs), with findings that change the proposed fix. Verified on main 51e9242:
Option A as written (ALTER COLUMN ... SET DEFAULT 48) does not fix a fresh install. 000001 seeds the global_config row (id=1) before 000070 adds the column, so ADD COLUMN ... NOT NULL DEFAULT 0 fills that existing row with 0. A later SET DEFAULT only affects rows inserted afterwards. Changing the seeded row needs an UPDATE, and a new migration cannot tell a fresh install from an existing one that never touched the setting, so that UPDATE is exactly the backfill the issue warns about.
The only no-backfill way to give fresh installs 48 is to change 000070's ADD COLUMN default to 48 in place (existing DBs have already applied it and are untouched; fresh DBs get 48 on the seeded row). Old migrations have been edited in place before (000059, 000027), so there is precedent.
New hazard the issue does not mention: on a deployment with FireSweepOff (no fire_scheduled_purchases sweep), a stored delay above 0 makes every approval return 409 (handler_purchases.go:1199-1205, fix(purchase): reject a purchase delay where no fire sweep is scheduled #1588) and PUT /api/config refuses a write above 0 (handler_config.go:221). A fresh install on such a deployment would get 409 on every approval until an admin sets the delay to 0. Fail-closed, but a visible behaviour change.
The OpenAPI text was already corrected (934dbca): "A fresh install stores 0 ... 48 is only the fallback used when the configuration row is missing". Remaining stale text: internal/config/types.go:61-66 ("Default: 48") and the 000070 up.sql comment (line 72 "default 48").
Two coherent options, owner decision: (A') 000070 in place -> 48, test that a fresh migrate yields 48, plus accept the FireSweepOff 409 on fresh installs; or (B) keep 0 and fix types.go, the 000070 comment and the DefaultPurchaseDelayHours fallback to say 0 consistently. No existing row is changed by either. Recommended default: A'. Holding implementation for the decision.
Activity
cristim commentedon Nov 10, 2026
Claiming (claude-cc-libs), with findings that change the proposed fix. Verified on main 51e9242:
ALTER COLUMN ... SET DEFAULT 48) does not fix a fresh install. 000001 seeds the global_config row (id=1) before 000070 adds the column, soADD COLUMN ... NOT NULL DEFAULT 0fills that existing row with 0. A later SET DEFAULT only affects rows inserted afterwards. Changing the seeded row needs an UPDATE, and a new migration cannot tell a fresh install from an existing one that never touched the setting, so that UPDATE is exactly the backfill the issue warns about.ADD COLUMNdefault to 48 in place (existing DBs have already applied it and are untouched; fresh DBs get 48 on the seeded row). Old migrations have been edited in place before (000059, 000027), so there is precedent.FireSweepOff(no fire_scheduled_purchases sweep), a stored delay above 0 makes every approval return 409 (handler_purchases.go:1199-1205, fix(purchase): reject a purchase delay where no fire sweep is scheduled #1588) and PUT /api/config refuses a write above 0 (handler_config.go:221). A fresh install on such a deployment would get 409 on every approval until an admin sets the delay to 0. Fail-closed, but a visible behaviour change.Two coherent options, owner decision: (A') 000070 in place -> 48, test that a fresh migrate yields 48, plus accept the FireSweepOff 409 on fresh installs; or (B) keep 0 and fix types.go, the 000070 comment and the DefaultPurchaseDelayHours fallback to say 0 consistently. No existing row is changed by either. Recommended default: A'. Holding implementation for the decision.