-- LFS storage is content-addressed: one R2 copy per oid, shared by every repository that links it. -- Each account is billed once per oid no matter how many of its repositories (forks) link it. -- Dev-only data: the old per-repo tables are recreated rather than migrated. DROP TABLE IF EXISTS lfs_objects; DROP TABLE IF EXISTS lfs_usage; -- Which repositories may serve an oid. owner_id is denormalized so triggers can bill without a join -- (the repo row may already be gone during a cascading delete). CREATE TABLE lfs_objects ( repo_id TEXT NOT NULL REFERENCES repos(id) ON DELETE CASCADE, oid TEXT NOT NULL, owner_id TEXT NOT NULL, size INTEGER NOT NULL, created_at INTEGER NOT NULL, PRIMARY KEY (repo_id, oid) ); CREATE INDEX lfs_objects_oid ON lfs_objects (oid); -- The single stored copy. refs counts lfs_objects rows; at 0 the sweeper deletes it after a grace period. CREATE TABLE lfs_blobs ( oid TEXT PRIMARY KEY, size INTEGER NOT NULL, r2_key TEXT NOT NULL, refs INTEGER NOT NULL DEFAULT 0, orphaned_at INTEGER, created_at INTEGER NOT NULL ); CREATE INDEX lfs_blobs_orphaned ON lfs_blobs (orphaned_at) WHERE orphaned_at IS NOT NULL; -- Per-account billing: refs counts the account's repositories linking the oid; billed while refs > 0. CREATE TABLE lfs_account_objects ( owner_id TEXT NOT NULL, oid TEXT NOT NULL, size INTEGER NOT NULL, refs INTEGER NOT NULL, PRIMARY KEY (owner_id, oid) ); CREATE TABLE lfs_usage (