Skip to content

v0.3.2 — signed URLs for private file namespaces

Latest

Choose a tag to compare

@javimosch javimosch released this 06 Sep 23:12
· 23 commits to master since this release

A private namespace with a signing_key can serve its files through time-limited signed URLs — no auth header, no guessing, and an expiry.

bkn files ns create reports --signing-key auto
bkn files sign reports q3.pdf --ttl 24h
# -> /v1/files/reports/q3.pdf?sig=...&exp=...
const url = bkn.files.sign("reports", "q3.pdf", { ttl: "24h" });

The signature is HMAC-SHA256(signing_key, "ns/name|exp") in URL-safe base64, compared in constant time. The key is generated with crypto/rand when you pass auto, and carries json:"-" so it is never serialised into an API response — files ns list does not leak it.

The use case is an email gate. A hook stores the lead, signs a URL and returns it. The recipient downloads without an account; the link expires on its own and cannot be forged.

Credit and review

The feature is Devin's. It is released after review — constant-time compare, expiry checked before the signature, migration present for existing databases — and an end-to-end check on a real build: unsigned request 404, signed 200, tampered signature 404, expired URL 404, key absent from ns list.

Also in this release, for anyone on v0.3.0

v0.3.1's two files fixes:

  • A name claim was a check followed by a write. Two uploads of the same free name both saw it free and the second silently replaced the first — twelve concurrent writers all reported success against the old code. Now exactly one wins.
  • --verify-type makes a namespace decide a file's type from its bytes instead of from what the uploader declared. Off by default.

Upgrading

Two ALTER TABLEs on file_namespaces (verify_type, signing_key), both defaulted, both instant. Existing namespaces behave exactly as before: no signing key means no signed access, and private namespaces still require auth.