Repository navigation
1.30 backend: block allowance — 10 included + one-time packs - #38
Merged
Merged
Conversation
…r cap)
Owner, 2026-10-15: "everything free, pay only for extra blocks" (+10 $7,
+100 $49, +1000 $149, one-time, permanent, never expire). Adds append-only
block_entitlements (migration 017, same no-UPDATE/DELETE trigger as
admin_audit_log) and enforces settings.included_block_allowance (10) + sum
of grants on POST /businesses/{id}/blocks only — 402 with a machine-readable
{used, allowance, next_pack} body, never a bare 403. PATCH/DELETE/reorder
untouched. GET /businesses/{id} gains owner-only blocks_used/blocks_allowance
(None elsewhere) — every public/preview/proof/by-slug payload already uses a
separate schema, so there's no leak path to close there.
Admin comp path: POST /admin/entities/{id}/grant-blocks (require_admin),
writes the entitlement + the mandatory admin_audit_log row. No payment code
here — Stripe is session 1.31.
Prod measured before shipping (tetapi-psql): 36 entities, 21 blocks total,
max 4 on any single entity, zero above 10 — ships with no grandfathering
needed, ahead of the 455-entity GTM batch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CI caught it: the two "allowed" quota tests hit add_block's real db.refresh(block, ["media"]) call after flush, which _StubSession didn't implement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
block_entitlementstable (migration 017, same no-UPDATE/DELETE trigger pattern asadmin_audit_log) records every grant; a correction is a new compensating row, never an edit.settings.included_block_allowance(10, named constant) + sum of grants, computed on read (routes/blocks.py::block_allowance/block_usage), never stored onbusinesses.POST /businesses/{id}/blocks: over allowance →402with a machine-readable{message, used, allowance, next_pack}body, never a bare 403. PATCH/DELETE/reorder are untouched.GET /businesses/{id}gains owner-onlyblocks_used/blocks_allowance(Nonefor every other caller) —/preview,/proof,by-slug/publicuse separate response shapes that never carry these fields, so there's no leak path to close there.POST /admin/entities/{id}/grant-blocks(require_admin), writes the entitlement + the mandatoryadmin_audit_logrow. No payment code here — Stripe is session 1.31.tetapi-psql): 36 entities, 21 blocks total, max 4 blocks on any single entity, zero above 10 — ships with no grandfathering needed, ahead of the 455-entity GTM batch.Note on numbering: boot called this 1.30 (branch kept as given), but that number was already taken on
mainby thebitcoin_confirmedfix (PR #36/#37) — same collision pattern as roadmap rows 1.24→1.25/1.25→1.26. The infra roadmap/changelog entry for this work is 1.32.Test plan
tests/test_block_quota.py(16 unit tests, stub-session style matchingtest_device_revoke.py): 10th block OK / 11th → 402;pack_100grant unblocks the 111th, blocks the 112th-equivalent; PATCH/DELETE/reorder ignore quota;BusinessOutquota fields defaultNone; admin grant writes both rows; unknownsource→ 422.tests/test_blocks_is_public.pyupdated to stub the new quota check (unrelated to that suite's ownis_publicassertions).pytest -q, full dependency install) — this sandbox's local dependency install didn't complete in a reasonable time (native builds); relying on the GitHub Actions runner, which installs.[dev]fresh per.github/workflows/tests.yml.block_entitlements(can only be proven against real Postgres).🤖 Generated with Claude Code