Run the business

File storage

Tenant-scoped uploads with the receipts in your own database and the bytes behind an adapter you own — files your product can reason about, not a bucket nobody can.

PreviewA miniature of the file library — the shape the real /admin/files page renders.

The problem

A file whose only record is the storage vendor's dashboard is a file your product can't list, authorize, bill, or delete by.

How it works

Every stored file is a row in your own database — the receipt your product lists, scopes to a tenant, and deletes by. The bytes live behind a two-method adapter you own: Vercel Blob, S3, or a directory on disk in tests, swapped without re-auditing a single caller.

Reads and deletes are tenant-scoped in the query itself, so a guessed id belonging to another tenant touches nothing. The upload is a plain route handler, because a file has no business being serialized through a typed RPC layer.

  • A database row per file; tenant-scoped list, get, and delete
  • Vendor-neutral adapter — no storage SDK baked into the package
  • A blob with a row is a file; a blob without one is a leak — so the bytes go down first, the receipt second, and the bytes are reclaimed if the receipt fails
  • Deleting a file removes the bytes by their storage handle, which the row keeps separately from the public URL — conflating the two is how 'deleted' files keep serving
npm install @adminigloo/storageBook a callAll features