Composer local attachment paths

When a user drops or selects a local file, image, or folder in the Electron desktop app, the outgoing message must identify the original absolute path. The existing attachment tiles and byte-upload behavior remain unchanged.

Verified gap

BoundaryCurrent behaviorRequired behavior
Electron preloadExposes window and web-tab APIs but no approved file-path accessor.Expose webUtils.getPathForFile through the existing bridge.
Composer pending stateStores only the basename from File.name.Store an optional immutable sourcePath for images and documents.
SubmitDocuments receive a path only after the backend saves a copy; images receive no original path; unreadable folders are described as unsent.Emit the attachment marker with a JSON-encoded original absolute path whenever sourcePath exists.

Data flow

User drop or picker
File
Preload
getPathForFile(file)
Pending state and message marker
[attachment: … @json "/abs/path"]

Behavior contract

Boundaries and rejected changes

Included files are the Electron preload bridge, bridge TypeScript contract, composer attachment state, submit marker construction, and the existing backend marker rewrite. Excluded are attachment tile styling, directory traversal, recursive browser uploads, arbitrary filesystem scanning, new IPC handlers, upload-size changes, Programs UI changes, and dependencies.

Rejected: using the non-standard legacy File.path; requesting Node integration in the renderer; replacing uploads with path-only messages for readable files; inventing a relative path in a normal browser; recursively enumerating a dropped directory.

Acceptance and verification

Focused checks must prove: preload returns the exact native path for the same File object; path capture handles an absent bridge, empty result, and exception; document, image, and unreadable-folder markers contain the full path; filenames with parentheses are display-safe; paths containing ], quotes, and trailing spaces round-trip through both parsers; path-less browser attachments retain their current marker; same-name browser and mixed-source attachments remain distinct; backend persistence does not duplicate a pre-path-marked attachment; TypeScript, desktop checks, web checks, backend attachment tests, build, documentation links, and diff whitespace checks pass.

Implementation status

Implemented and reviewed. The focused RED established the missing preload path boundary, absent composer provenance, and duplicate backend marker behavior. The final implementation preserves Electron paths for files, images, and folders; keeps plain-browser uploads unchanged; distinguishes same-name attachment sources; and uses a JSON-encoded path marker that round-trips legal delimiters and trailing spaces while reading historical markers. Focused Web and Python checks, TypeScript, full Web and Desktop checks, production build, documentation build/link check, Ruff, and diff whitespace checks pass. Independent specification and quality reviews pass. The preload boundary is exercised in a VM with the same File object; real-window manual dragging was not part of this verification.