feat(blob): allow client uploads to set access (private client uploads)#1080
feat(blob): allow client uploads to set access (private client uploads)#1080kars85 wants to merge 1 commit into
access (private client uploads)#1080Conversation
`handleUpload`'s `onBeforeGenerateToken` callback could not return `access`, so every client-uploaded blob was forced to public even after private Blob shipped (vercel#816). Add optional `access` to the client-token options and to the `onBeforeGenerateToken` return `Pick`; it is serialized into the signed client token by the existing generic token path, so no runtime-logic change is needed. When omitted, behavior is unchanged (public). Fixes vercel#1079 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014yndSRPZ2WRRFJajNWX1F1
|
@kars85 is attempting to deploy a commit to the Curated Tests - Permanent E2E Team on Vercel. A member of the Team first needs to authorize it. |
🦋 Changeset detectedLatest commit: e963c2a The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Answering my own open question after tracing the SDK — and it changes how this PR should be read. Today the control-plane gets a client upload's // access is always required, so always add it to headers
headers[putOptionHeaderMap.access] = options.access; // x-vercel-blob-accessSo on a client upload: Implication: this PR makes I've therefore converted this to a draft. It's the SDK-side half of a two-part change; happy to keep it warm until (or adjust it to match) whatever the backend does. The security motivation is that a server-pinned, tamper-proof access (token) is stronger than a client-settable header — but that's a backend decision. Flagging so this doesn't merge as if the SDK change alone were sufficient. |
What
Lets client uploads choose their access level.
handleUpload'sonBeforeGenerateTokencallback can now returnaccess: 'public' | 'private', bringing client uploads to parity with the server-sideput({ access })API.Fixes #1079.
Why
Private Blob shipped in #816, but only for server-side operations. The client-upload path (
upload()→handleUpload()→generateClientTokenFromReadWriteToken()) was never given anaccessknob, so every client-uploaded blob is forced topublic.onBeforeGenerateToken's return type is aPick<GenerateClientTokenOptions, …>that omitsaccess, andGenerateClientTokenOptionshas noaccessmember to pick from — so returning{ access: 'private' }is a TypeScript error with no runtime channel to carry the intent.Motivating use case: uploading receipts/documents containing PII/PHI directly from the browser — these should be private, but client uploads can currently only be public.
Change
Minimal and additive (
packages/blob/src/client.ts):access?: BlobAccessTypetoGenerateClientTokenOptions.'access'to thePickinonBeforeGenerateToken's return type.No runtime-logic change:
generateClientTokenFromReadWriteTokenalready serializes all of its non-tokenargs into the signed client-token payload, andhandleUploadalready spreads theonBeforeGenerateTokenresult into it — soaccessnow flows end-to-end into the token payload automatically. When omitted, behavior is unchanged (public), so this is non-breaking.Tests
Added to
packages/blob/src/client.node.test.ts:generateClientTokenFromReadWriteTokenbakesaccessinto the decoded token payload.accesswhen it isn't provided (unchanged default).handleUploadthreadsaccessfromonBeforeGenerateTokeninto the minted client token.Locally:
pnpm --filter @vercel/blob test:node→ 160 passedpnpm --filter @vercel/blob test:edge→ passedpnpm --filter @vercel/blob type-check(tsc --noEmit) → cleanChangeset included (
minor).Open question for maintainers 🔎
I could only verify the SDK side. Does the control-plane / api-storage already honor an
accessfield embedded in avercel_blob_client_*token payload, or is backend work needed for it to take effect? If the backend currently ignores token-levelaccess, this type change would let developers express private client uploads without them actually being private — so I'm flagging it rather than assuming. Happy to gate it, wire it differently, or hold the SDK change until the backend consumes the token — whatever matches how you'd like this to land.🤖 Generated with Claude Code
https://claude.ai/code/session_014yndSRPZ2WRRFJajNWX1F1