# Generic Workspace Attachments Plan

## Current Design

- Workspace uploads already use `POST /api/workspace/{id}/image-attachments`,
  store metadata in the attachment table, and enter Chat through
  `attachment_ids`.
- The route accepts only PNG/JPEG/WEBP/GIF. Depending on server configuration,
  images may be parsed into a summary before the Agent sees them.
- A separate writable `/files` route would duplicate storage and bypass the
  existing attachment/Chat contract.

## Risks

- Existing image clients must retain their configured parser behavior.
- Arbitrary file types must not be decoded or treated as images.
- Filename/path handling, size limits, and raw-content logging must remain
  fail-closed.

## Target Contract

- Add `/api/workspace/{workspace_id}/attachments` as the canonical alias; retain
  `/image-attachments` as a compatibility alias to the same handler.
- Accept any non-empty file type within the configured size bound.
- Add multipart `parse: bool | null`. For images, omitted means current server
  default and `false` means passthrough. Non-images always bypass parsing.
- Store every file under its attachment-owned directory with sanitized filename
  metadata and unchanged bytes.
- Set passthrough items ready immediately. Kind is `image` for supported image
  formats and `file` otherwise.
- Chat includes attachment ID, filename, MIME type, and workspace-relative path
  for non-images so the Agent reads the file directly. It does not inline,
  extract, OCR, or summarize it.

## Invariants

- Canonical and legacy routes share one function and one persistence model.
- Existing image upload behavior remains compatible when `parse` is omitted.
- `parse=false` and non-image files never call the vision parser.
- Raw file bodies and tokens never appear in logs or API errors.

## Not Doing

- No writable generic `/files` endpoint.
- No Jira/AO-specific field or workflow.
- No frontend route migration in this slice.

## Implementation Steps

1. Generalize validation and attachment kind handling.
2. Add route alias and request-level parser control.
3. Teach Chat to reference raw non-image files by workspace path.
4. Add focused compatibility, passthrough, arbitrary-file, and Chat tests.

## Verification Checklist

- [x] Existing image tests pass unchanged.
- [x] Raw image passthrough and arbitrary binary round-trip pass.
- [x] Text/PDF/Office/archive files are ready and Agent-readable without parsing.
- [x] Both route names return the same response contract.
- [x] Focused pytest (19 tests), ruff, compileall, and diff checks pass.
