-- v1.1.5: filesystem-backed blob storage. The row holds metadata + -- the SHA-256 checksum; the blob bytes live on disk at -- /files//// -- (never in Postgres). Identity tuple is (app_id, collection, id) per -- docs/sdk-shape.md, matching KV/docs collection scoping. -- -- The checksum is computed in a single pass during the atomic write and -- re-verified on read (FilesError::Corrupted on mismatch). Per-app -- quotas are deferred to v1.2; only the per-file size cap is enforced -- (in the service, not the schema). CREATE TABLE files ( app_id UUID NOT NULL REFERENCES apps(id) ON DELETE CASCADE, collection TEXT NOT NULL, id UUID NOT NULL, name TEXT NOT NULL, content_type TEXT NOT NULL, size_bytes BIGINT NOT NULL, checksum_sha256 TEXT NOT NULL, -- hex, 64 chars, lowercase created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (app_id, collection, id) ); -- List + cursor pagination scans by (app_id, collection). CREATE INDEX idx_files_app_collection ON files (app_id, collection);