fix(approvals+storage): decision attachments — name, open, correct download filename (#3504)#3505
Open
baozhoutao wants to merge 2 commits into
Open
fix(approvals+storage): decision attachments — name, open, correct download filename (#3504)#3505baozhoutao wants to merge 2 commits into
baozhoutao wants to merge 2 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 106 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
… and correct download filename (#3504) The approval inbox timeline showed a nameless "附件" chip that did nothing on click, and even the downloaded file was named after the opaque URL token. Two root causes, both in the framework: approvals — `sys_approval_action.attachments` (a `Field.file`) stores rich descriptors `{ id, name, url, mimeType, size }`, but `rowFromAction` mapped them with `.map(String)`, collapsing each to "[object Object]". `ApprovalActionRow. attachments` is now `ApprovalActionAttachment[]`; the descriptor carries name + url, so consumers label/open attachments without reading the system `sys_file`. storage — presigned downloads served `application/octet-stream` with no `Content-Disposition`. `getSignedUrl`/`getPresignedDownload` now take `PresignedDownloadOptions { filename, contentType, disposition }`; the REST download routes pass the `sys_file` name+mime; the local adapter carries them in the token and `_local/raw` emits an RFC 5987 Content-Disposition; S3 bakes the same into the signed URL. Default `inline` preserves in-browser preview. Verified end-to-end in app-showcase. Refs objectui #2820. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…aces Additive only (0 breaking): ApprovalActionAttachment + PresignedDownloadOptions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #3504. Frontend companion: objectstack-ai/objectui#2820.
Problem
A decision attachment in the approval inbox timeline (审批动态) showed a nameless "附件" chip that did nothing when clicked — and even when the file did download, it was named after the opaque signed-URL token (
eyJrIjoiYXR0YWNo…) asapplication/octet-stream.Root cause 1 — approvals read path stringified descriptors
sys_approval_action.attachmentsis aField.file, which stores rich descriptors{ id, name, url, mimeType, size }(a fileId is resolved to a full descriptor on write) — not fileId strings.rowFromActionmapped the column with.map(String), collapsing each descriptor to the literal"[object Object]". EverylistActionsconsumer received garbage.Root cause 2 — storage download had no filename/type
Presigned downloads served
application/octet-streamwith noContent-Disposition, and the signed token carried no filename, so browsers saved files under the URL token.Changes
approvals (
@objectstack/spec,@objectstack/plugin-approvals)ApprovalActionAttachment;ApprovalActionRow.attachmentsis nowApprovalActionAttachment[].rowFromActionpasses descriptors through (tolerating a bare-string fileId). Decision input staysstring[]. Consumers no longer need read access to the systemsys_fileobject.storage (
@objectstack/spec,@objectstack/service-storage)getSignedUrl/getPresignedDownloadtake optionalPresignedDownloadOptions { filename, contentType, disposition }.GET /storage/files/:id/url,/:id) pass thesys_filename+mime_type._local/rawemitsContent-Type+ RFC 5987Content-Disposition(ASCII fallback +filename*=UTF-8''…). S3 adapter usesResponseContentType/ResponseContentDisposition. Defaultinlinepreserves in-browser preview.Testing
@objectstack/plugin-approvals: 165/165 (incl. new descriptor-passthrough cases).@objectstack/service-storage: 104/104 (incl. new token-metadata + Content-Disposition helper cases).app-showcase(approvals + storage): chip showssigned-contract.pdf, click opens the real PDF, and the download respondscontent-type: application/pdf+content-disposition: inline; filename="signed-contract.pdf".🤖 Generated with Claude Code