Skip to content
Wow your usersDeveloper platform

Private file storage

Your users' files stay private, verified, and off your server.

Users upload files straight to storage, so a big file never ties up your server. Every file is checked against its declared fingerprint before anyone can download it. And deletes that fail show up for a human instead of leaving stray files behind.

0public file linksSHA-256fingerprint checked before a file goes live10 minbefore an upload link expires

Product example

See it working

This is the same visual component used by the authenticated app, rendered with deterministic sample data.

Scenario
viewport
surface theme
mode

Private object available

Inspect tenant-scoped metadata, classification, download, and durable deletion controls.

Inert sample data · no network access

Upload a file

Editors can upload files up to 5 GiB. Files stay private, and each upload is checked before it becomes available.

Drag and drop a file here, or choose a fileMax size 5 GB · One file
Data classification
Choose how sensitive the file is. This label stays with the file.

Stored objects

1 object

Files stored in this workspace right now. Downloads use a short-lived signed link.

security-review.pdfAvailable
2.7 MiBConfidentialAdded

Retention and deletion

Check which files are waiting for deletion and when stored files expire.

Deletion is queued, not immediate
Deletion runs in the background. We retry until the storage provider confirms removal and keep a record of the result.
0
Deletions that ran out of retries
These files stay in the list so an editor can retry deleting them.
0
Files with an expiry date
An object with an expiry date is removed automatically once it passes.
0

Preview ready

Highlights

Why it matters

Private by default

Every file lives under its owner's organization, and all access goes through short-lived, permission-checked links.

Verified before visible

After upload, the server compares the stored file's size and fingerprint to what was declared. Mismatches get quarantined.

Cleanup you can see

Deleting runs as a retried background job. If the provider keeps refusing, the file is flagged as failed instead of quietly lingering.

The problem this solves

Without a shared foundation, every team rebuilds these edge cases — differently.

The upload that melts your server

Streaming big files through your app server burns memory until requests time out. But letting browsers write straight to a bucket usually skips your permission checks. Here you get both: direct upload, server-approved first.

The file that isn't what it claims

An upload gets cut off halfway, or someone swaps the bytes after declaring them. Without a settlement step, that broken file goes live. Here a mismatch means quarantine, never availability.

Ghost files on your bill

A fire-and-forget delete fails silently. Months later you're paying to store files nobody can see. Worse: files marked deleted still exist, which is a compliance problem. Failed deletes here surface for an operator.

How it works

The mechanism end to end, as implemented in the repository.

  1. 1

    Ask for an upload link

    The server checks the user's role plus the file's name, type, size, and fingerprint, then returns a signed link that works for 10 minutes.

  2. 2

    The browser uploads directly

    The file goes straight from the browser to the storage provider, with progress reporting. Your server never touches the bytes.

  3. 3

    The server double-checks

    After upload, the server asks the provider for the file's real size and fingerprint. A match makes it available; a mismatch gets quarantined.

  4. 4

    Deletes are jobs, not wishes

    Delete hides the file immediately, then a background job removes the bytes with retries. Stubborn failures get flagged so an operator can act.

Engineering guarantees

What this does and does not promise

Safety boundary

The included certification proof runs against a disposable local storage provider, not a hosted one. This feature stays switched off behind a gate until you certify it against the storage you'll actually run in production.

Implementation evidence

The boundary above is code, not a claim. These files carry the contract:

  • src/features/storage/server.ts
  • src/features/storage/jobs.ts
  • src/features/storage/browser-upload.ts
  • .resource-certifications/storage.json
Questions

Frequently asked questions

Build on the private file storage foundation

The docs describe the same contracts this page demonstrates.