Repository navigation
test(uploads): pin the browser's copies of the document list to ALLOWED_DOCUMENT_EXTS - #653
Conversation
…ED_DOCUMENT_EXTS The browser cannot import the server's document allowlist, so the classifier, the three pickers' accept lists and the two file-path link patterns each carry a hand-kept copy. A missed copy fails silently: a file greyed out in the picker, an upload dropped client-side, or a pasted path that is no longer a link. Hoist the set to module scope so the test reads the shipped list.
|
Thank you @JDProfresh, this is exactly the parity test I asked for in #621: it imports Two gaps turned up while doing that, plus one typing nit. I will apply these on top at merge time, so there is nothing you need to push:
Thanks also for the note on #644: once this lands, that PR will need |
The reverse classifier check read only the one includes(ext) list, so a second branch such as `if (ext === 'rtf') return 'document';` passed every test; the method may now return 'document' from exactly one place. The accept= checks kept only .ext tokens, so adding text/* to a picker passed; the non-extension tokens must be exactly image/* and video/*. Both verified by mutation (each fails the suite). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Now that the set is exported for the parity test, type it read-only like VIDEO_ATTACHMENT_EXTENSIONS, so an importer cannot add to the live upload allowlist. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…he document list to ALLOWED_DOCUMENT_EXTS Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> # Conflicts: # CLAUDE.md
|
Merged and shipped in 1.43.0. Thanks @JDProfresh! The three edits from my review are on top: |
The browser can't import the server's document allowlist from #621, so it keeps four hand copies of it, and the two file-path link patterns have to cover it too. Nothing checked any of them against
ALLOWED_DOCUMENT_EXTS. This is the parity test you asked for in the #621 merge comment.Problem
ALLOWED_DOCUMENT_EXTS(session-routes.ts) decides which documents the paste-image route accepts. The browser keeps its own copies:_promptAttachKind()inimage-input.js, the classifier every pick, drop and paste goes throughaccept=on the toolbar Attach input (#attachFileInput,index.html)accept=on the two.paste-file-inputpickers (Compose and the paste dialog,keyboard-accessory.js)FILE_PATH_LINK_PATTERNandRELATIVE_FILE_PATH_LINK_PATTERNinconstants.js, which make the uploaded path clickable when the agent prints it backIf one copy is missed, nothing errors. Depending on which one, the file is greyed out in the picker, dropped client-side as "Unsupported file type", or sent and then refused with a 400, or its path comes back as plain text. In #621 I had to add tsv and zip to the link patterns by hand. #644 (still open) rewrites both patterns from a base older than #621, without tsv and zip.
Cause
The lists are copies with nothing tying them together, and
ALLOWED_DOCUMENT_EXTSwas a local insideregisterSessionRoutes(), so a test could not read it.Fix
ALLOWED_DOCUMENT_EXTSmoves to module scope besideTEXT_UPLOAD_EXTSand is exported. Same set and same comment, plus one line pointing at the test. The route body is unchanged.test/upload-document-list-parity.test.tsimports the shipped set and checks every copy against it:_promptAttachKind()is loaded fromimage-input.jsin avmcontext, the waytoolbar-attach.test.tsloads it, and called withreport.<ext>and no MIME for every server extension. For the reverse direction, the test reads the document list from the live method's own text (comments stripped, exactly one list required), checks that each entry really returnsdocument, and requires the list to equal the server set.accept=values are read from the real files (index.html through JSDOM, the two picker templates fromkeyboard-accessory.js, exactly two required) and must list exactly the server's extensions.constants.jsand run on a sample path per extension. Each must match the whole path. This direction is one-way, since the patterns link many non-document types too.Tests
For each copy I dropped one extension and ran the test. Every time it failed and named both the file and the extension:
image-input.jswithouttsv:does not classify as document: tsv, and the list check shows- "tsv"image-input.jswith an extrartf: the list check shows+ "rtf"index.htmlwithout.zip:index.html #attachFileInput accept=with- "zip"; with an extra.rtf:+ "rtf"keyboard-accessory.jsfirst picker without.md, and the second picker without.xml:.paste-file-input #1/#2with the missing extensionconstants.jsFILE_PATH_LINK_PATTERNwithoutzip:does not link: zip;RELATIVE_FILE_PATH_LINK_PATTERNwithouttsv:does not link: tsv.zip: the classifier list and all threeaccept=checks fail on+ "zip"rtfin the live one: fails onrtfVerified
Test-only change, so there is no runtime behaviour to show. Upstream master 1.42.0 (
ce809eac), Node 26.2.0, vitest 4.1.8: typecheck, lint, format:check, check:frontend-syntax, check:browser-excludes and the fullnpm testall pass (583 files, 11589 tests).Invariant touched: none changed. The test pins the document list described in CLAUDE.md "Prompt uploads" and architecture-invariants#buffers-uploads-and-terminal-history.