Changes touching this path

  • tenant_blob counts what a tenant references, and the account tier it belongs to stays unwritten on purpose #612 asked what `tenant_blob.bytes` counts before anything counts it, and said the dedup question decides whether the producer belongs at the blob `put` "where dedup is visible" or at `ingest` "where tenancy is". Both halves resolve, and neither the way the ticket framed them. `bytes` is REFERENCED FOOTPRINT. What settles it is #482's own accepted cost -- deleting a tenant is "refcount-decrement-and-delete-if-zero, because a fork legitimately holds the same object". A decrement presupposes many tenants holding a row for one oid, which is the reference reading; under the origination reading there is one row per oid forever and nothing to decrement. The shorter argument -- that the primary key forces it -- is tempting and does not work, so the comment says so rather than leaving the next reader to try it. `(tenant_id, object_oid)` does settle the ticket's other half, running total vs append-only ledger, because a set whose `bytes` is a property of the oid cannot accumulate. It does not separate reference from origination: "one row per oid, for the tenant that introduced it" is equally a set with that key. Origination is already recorded and is not this table's: `object.introduced_by` (#501) is first-write-wins on the address, keyed by PUBKEY, not tenant_id. What it lacks is a byte count, so billing on origination is a column on `object`. The put-vs-ingest question dissolves rather than being answered by the dedup verdict. Dedup is not visible at `put` at all -- `BlobStore::put` returns no novelty bit, and an `exists`-then-`put` is a race between concurrent pushes -- and a set-membership upsert never needs to know. So: ingest, where tenancy is. The reason nothing counted anything is bigger than this table, and is the find worth keeping: `tenant` HAS NO PRODUCER EITHER. #504 resolved "first push auto-creates the `tenant` and `repo` rows"; only `repo` was built, correctly, because `repo` is keyed by owner_pubkey and has no tenant_id at all. `tenant`, `account_key`, `repo_member` and `tenant_blob` are one unbuilt ACCOUNT TIER -- #487 decided its shape and is closed, #753 is the build. So tenant_blob was never a missing producer; it is a member of a tier held whole, flagged alone because #482 named it by table. Its consumer is behind the same door: quotas arrive with #504's open multi-tenant push. No producer is built, and no migration is added. The record goes in the schema comment, which is legitimate because migration 0001 IS docs/sql/forge-schema.sql and comment-only edits are the #720-enforced exception to append-only -- `released_migration_statements_are_pinned_by_checksum` proves no statement token moved. Per-tenant export, the third consumer, is recorded as deferred rather than answered: it needs #493's reachability walk, which a byte count is not. tests/account_tier.rs is the tripwire that keeps the absence from re-opening silently, and it is written to be deletable when #753 arrives. Its own first cut failed open twice -- on a `\` line continuation (the house SQL style) and a quoted identifier (`INSERT INTO "ref"` is real) -- so the scan now normalises both, plus schema qualifiers and Rust escapes, and covers the migrations directory rather than only src/. Every spelling it claims to catch is pinned by a positive control, because a scan that has quietly stopped matching reproduces the exact silence #612 was filed about, inside its own guard. Two claims in the first draft were corrected by review before landing: the primary-key argument above, and pointing the reader at #487 (closed) rather than #753. #690's allowlist is also named as what it is -- a deployment setting, not a code closure, since an empty list means open and the binary only warns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> a0106e52 · dbf3dbe6…

Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.