Browser
AES-GCM encrypts bytes locally
Zero-knowledge encrypted uploads.
Define upload routes against customer-owned S3 while keeping files encrypted before they leave the browser. Your app keeps the keys; DorsalUpload coordinates ciphertext uploads.
Encrypted in browser before direct upload
7f3a9c1d8b2e4c91a8f0d3e9c2... RSA-OAEP-256 + A256GCM Compatibility target
DorsalUpload keeps the developer-facing API familiar: route config, middleware, input parsing, `onUploadComplete`, React components, and `DorsalUploadApi`.
import { createDorsalUpload, type FileRouter } from "dorsalupload/server";
const f = createDorsalUpload();
export const uploadRouter = {
pdfUploader: f({ pdf: { maxFileSize: "16MB", maxFileCount: 1 } })
.middleware(async ({ input }) => ({ userId: input.userId }))
.onUploadComplete(async ({ file, metadata }) => {
await saveEncryptedObject({
userId: metadata.userId,
objectKey: file.key,
envelope: file.dorsal.key_envelope
});
}),
} satisfies FileRouter; Zero-knowledge flow
AES-GCM encrypts bytes locally
Signs a direct upload URL for ciphertext only
Persists encrypted objects under org/app routes
onUploadComplete receives safe metadata
Developer docs
Pricing
Local setup, mock presigns, and 1,000 monthly encrypted uploads.
Production apps, API keys, usage tracking, and larger encrypted uploads.
Higher limits, operational review, and launch support for regulated data flows.
Security model
The SDK encrypts, the API validates envelope v1 and signs short-lived S3 URLs, and your app keeps private keys. Developers still own plaintext before encryption and after local decryption.