First 50 seats always free: Paddle carries paid seats, key carries total cap (#25) #26
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/free-tier-stacking"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #25.
One conversion boundary: Paddle prices/quantities carry PAID seats; everything else (API, signed key, dashboard, Cairn enforcement) talks TOTAL seats.
paddle.go:const freeSeats = 50;paddleTransactionCompletedaddsfreeSeatsto the derived paid quantity (line-item sum or absolute subscription lookup) before refresh/issue. The zero-seat "keep existing" fallback is untouched.seats.go:resolveSeatChangefloors atfreeSeats+1(400 "seats must be above the free tier (minimum 51)");subItemsBodysendsseats − freeSeatsto Paddle for both preview and the billing PATCH.TestPaddleQuantityIsPaidSeats(quantity 1 → 51-seat key); floor-rejection test.go vet+ full suite green on the runner.Requires the Paddle price quantity minimum to drop 51 → 1 (max 10000 → 9950) — done in the sandbox alongside this merge; repeat on the live price at launch (#26 swap).
Migration note: keys minted before this change were billed for their full seat count; their next renewal/seat-change re-signs them at quantity+50. Sandbox-only, no live customers.