adr 0026 chat attachment workspace saves - Alshival-Ai/neural-labs GitHub Wiki

ADR 0026: Explicitly save chat attachments into the shared workspace

Design history: for current instructions, see Files desktop app. See the decision index for amendments and related records.

  • Status: Accepted
  • Date: 2026-09-06

Context

Private Alshival attachments use the scoped media capabilities described in ADR 0018. Users also need to save an attachment into Files, where approved workspace users share access. This is an explicit transfer from a private conversation into shared storage.

Decision

Offer Download to Workspace only as a user action with a destination and filename chooser. Explain the shared destination in the chooser. Previewing an attachment or downloading it to the browser does not persist a workspace copy. Ask on name conflicts; replacement uses the existing Files recovery behavior.

For private ticketed media, an authenticated, same-origin POST to /workspace/api/files/import-neura accepts an existing outgoing-media route, destination, filename, and optional conflict choice. It validates the same strict route and ticket as the media relay and streams from the fixed configured Gateway origin into the confined Files upload pipeline. It does not accept arbitrary origins, follow redirects, forward browser credentials upstream, mint media tickets, or read arbitrary Gateway paths. Disconnection aborts the import; failed and oversized transfers remove staging files before replacement.

Existing workspace files use Files copy operations. Already-resolved inline attachments use the existing upload endpoint. Each source retains its existing authorization checks. Media tickets and temporary preview URLs are not persisted in desktop preferences. Expired tickets may be refreshed once through the owning user's authenticated Gateway session.

The GET/HEAD media relay additionally accepts download=1 and an optional filename to return attachment disposition. These display parameters are not forwarded upstream. Downloads can carry any ticket-authorized file type; inline responses retain their existing media-type restrictions.

Consequences

  • A successful explicit save creates a normal shared workspace file. Expiry of the source ticket does not revoke that user-requested copy.
  • There is no new public ingress route or general-purpose URL fetch service.
  • The import reuses Files limits, conflict checks, recovery, and notifications.
  • Team attachment-only messages require migration 10 to permit empty text when attachments exist. Existing message text is preserved, including ambiguous filename captions; fully empty messages remain rejected.