A drop on the holocron, for moving files between machines
Drop a file on one machine, pick it up on another. Two columns, a private store of its own, and no polling.
Full-width, below the tiles. Left half takes what you drop on it, right half lists what is in there with a download and a delete. It replaces wanting an FTP account somewhere: no third party, no server to patch, and it is already behind the gate.
Its own store, and that is not a preference
Public and private is a property of the store, not of a file in it. Podcast
audio has to be public — a podcast client fetching an <enclosure> has no
cookie to send — and a file drop has to be private. They cannot be the same
store. Vercel's own guidance says the same thing under store limits: use
separate stores to isolate public and private content.
So the store SC-20 created is left alone, and this gets a private one. It also means the delete button here cannot reach the audio, whatever anyone clicks.
Why nothing refreshes by itself
list() is an Advanced Operation and Hobby includes 2,000 a month. Polling the
listing every five seconds is 720 an hour, so a page left open for three hours
would spend the month and lock the store for thirty days. The listing moves on
page load, after an upload, after a delete, and when you press refresh.
The first listing is rendered by the page rather than fetched on mount, so arriving costs one operation rather than two.
The file never touches the site
Uploads go straight from the browser to the store, with /api/drop/upload
handing out a one-shot token. Through a Function instead, a file would be
capped at 4.5 MB — the body limit — and the transfer would be paid for twice.
Downloads have to come back through /api/drop/file, because a private blob's
URL answers to nobody without a token. That route streams it with
Cache-Control: private, no-store.
Ceiling of 100 MB a file, because Vercel recommends against serving anything larger through a private store, and because 1 GB of storage does not survive many mistakes.
The gate is now carrying more than it was sized for
lib/holocron.ts says of itself:
This keeps a casual wanderer out and nothing more, which is the right size for a page with nothing in it.
The page no longer has nothing in it. The attempt counter lives in a cookie, so a private window resets it and two tries an hour is really unlimited guessing. Every route here checks the session server-side next to the call it guards, and a closed session gets a 404 that says nothing — but that is the door, not the lock. Real rate limiting needs server-side state keyed to something the visitor does not control.
Until that exists, the password is the whole of the security, and it should be long enough that unlimited guessing does not matter.
Not done until
- The private store exists and
DROP_BLOB_READ_WRITE_TOKENis set on Vercel and pulled locally. Without it every route answers 503 and the tile says so. - A file has actually made the trip between two machines. Nothing here has touched a real store yet — the gate, the listing route, the path checks and the tile were tested against a running server, the uploads were not.