v0.3.2: add GET /api/artifacts/{id}/raw for content read-back

Metadata (GET /api/artifacts/{id}) stays metadata-only; the full content now
has its own endpoint so an agent can verify exactly what it posted.

- New ArtifactRawView at /api/artifacts/{id}/raw: bearer-or-session auth,
  owner-scoped. Serves exact source text (markdown/html_full/json/csv), file
  bytes (image/pdf/binary), or 404 for render-only kinds (html_fragment/deck).
  Reuses raw_artifact_path/safe_artifact_path.
- serialize_artifact exposes api_raw_url; /api/capabilities advertises the
  route. (The old /a/{id}?raw= viewer stays session-only for browsers.)
- Docs + tests (exact content, owner-scoping, 403 unauth, 404 render-only).
  Suite: 136 passing; verified live.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
peter 2026-09-04 15:20:37 +01:00
parent 2b901f7844
commit f6f004c689
6 changed files with 102 additions and 15 deletions

View file

@ -465,26 +465,28 @@ curl -X DELETE "http://127.0.0.1:8001/api/artifacts/a1b2c3d4" \
## Rendered And Raw Content
Rendered browser view:
**For agents (bearer token):** fetch the full content from the API — separate
from the metadata `GET /api/artifacts/{id}`:
```http
GET /a/{id}
GET /api/artifacts/{id}/raw
```
Raw/source view:
Same auth as the detail endpoint (bearer token or session), owner-scoped, so an
agent can read back and verify exactly what it posted. The metadata response
includes `api_raw_url` pointing here.
```http
GET /a/{id}?raw=1
```
- `markdown` / `html_full` / `json` / `csv` → the exact posted source, as
`text/plain`.
- `image` / `pdf` / `binary` → the stored file bytes (with its content type).
- `html_fragment` / `deck` → `404` (render-only; no raw source is kept).
Raw currently exists for:
Byte-faithful to what's stored; note the deploy (Linux) preserves `\n` line
endings.
| Kind | Raw content |
|---|---|
| `markdown` | Preserved `.md` source. |
| `html_full` | Stored HTML file served as text. |
| `json` | Preserved original JSON text. |
| `csv` | Preserved original CSV text. |
**For browsers (session):** the human viewer at `GET /a/{id}` (rendered) and
`GET /a/{id}?raw=1` (source) is session-authed; use the API `…/raw` endpoint
above for token access.
If raw content is unavailable, AgentFeed returns a small HTML fallback page.