|
| 1 | +--- |
| 2 | +description: How stored content (workspace files, run files, knowledge, table rows) reaches Chat's model, and the per-path policy. Read before changing a use case, route or Chat surface that returns such content. |
| 3 | +paths: |
| 4 | + - "apps/sim/lib/core/application/content-delivery.ts" |
| 5 | + - "apps/sim/lib/mothership/content-delivery/**" |
| 6 | + - "apps/sim/lib/**/application/admit-*.ts" |
| 7 | + - "apps/sim/lib/**/application/operations.ts" |
| 8 | + - "apps/sim/lib/mothership/agent-cli/**" |
| 9 | + - "apps/sim/lib/mothership/tools/sandbox-resource-transport.ts" |
| 10 | +--- |
| 11 | + |
| 12 | +# Sim Content Delivery to Chat |
| 13 | + |
| 14 | +Content derived from a provenance-bearing store reaches Chat's model only after **each item** it |
| 15 | +came from is admitted by the gate of the surface it leaves through. The stores are workspace files |
| 16 | +(and their versions), run files, knowledge documents and chunks, and table rows. "Derived" covers |
| 17 | +bytes, text, excerpts, chunks, cells, previews, base64, archives, rendered or compiled output, |
| 18 | +error text that quotes content, public links, and match results. |
| 19 | + |
| 20 | +Only Copilot principals (`delegated` / `organization_delegated` with `serviceId: 'copilot'`) are |
| 21 | +classified. Every other caller is admitted without a provenance read, so the UI, API keys, MCP and |
| 22 | +the workflow executor see byte-identical results. |
| 23 | + |
| 24 | +## The pieces |
| 25 | + |
| 26 | +- `lib/core/application/content-delivery.ts`: the primitive. |
| 27 | + - `admitContent(principal, sources)` returns per-item verdicts. `requireAdmittedContent` is the |
| 28 | + single-item form and throws `ContentRefusedError` (403). |
| 29 | + - `admitWrittenContent` is for a committed write that returns content. A refusal or gate failure |
| 30 | + does not undo the write: audit and effects run, then the operation answers with the refusal. |
| 31 | + - A source is `{ kind, id, provenance, view }`. `view` is `'complete'` (text whose every entry |
| 32 | + may appear), `{ derived: value }` (only entries occurring in `value`), or `'opaque'` (bytes no |
| 33 | + redaction reaches: binary, base64, archives, images, public links). |
| 34 | +- Gates, installed by the surface: the **registry gate** (Chat tools, CLI, mounts) imports entries |
| 35 | + into the registry egress projects with; the **session gate** (run_code sandbox proxy) records |
| 36 | + them into the workbench history. Neither ever admits `unknown`, and one refused item never |
| 37 | + latches the shared registry. |
| 38 | +- `observeContentOutsideModel` reads for Chat without classifying, for content that never reaches |
| 39 | + the model (the user's own edit preview; a derived file that carries its sources' provenance). |
| 40 | + Name why at each use. |
| 41 | + |
| 42 | +## Rules |
| 43 | + |
| 44 | +1. **Every operation that admits Copilot declares `contentDelivery`**: `'sourced'` when its result |
| 45 | + can carry content from a store (including a match oracle), `'none'` otherwise. Definition throws |
| 46 | + without it, and `copilot-route-inventory.test.ts` lists every Chat-reachable route without one. |
| 47 | +2. **A `sourced` use case accounts for what it returns**, before it loads content: call |
| 48 | + `admitContent` (with `[]` when this call returns none). Otherwise Chat gets |
| 49 | + `ContentDeliveryUnaccountedError`, and the transports turn the response into a 403. |
| 50 | +3. **Classify before loading bytes**, and exclude refused items per item. Withhold a whole result |
| 51 | + only when its items cannot be separated (one file, one render, one compile). |
| 52 | +4. **A new `sourced` route needs a case in `lib/mothership/__integration__/content-delivery.integration.ts`.** |
| 53 | + `copilot-content-routes.json` lists them; the suite fails for a listed route it does not drive. |
| 54 | + Refresh the list with `vitest run -u lib/api/server/routes/copilot-route-inventory.test.ts`. |
| 55 | +5. **Do not reach a store's bytes around a use case for Chat.** A helper that reads content for |
| 56 | + Chat goes through the gated use case, or names `observeContentOutsideModel` and why. |
| 57 | + |
| 58 | +## Policy |
| 59 | + |
| 60 | +U = `unknown`, E = exact with secret entries, R/C = unrecorded or clean. Each item is decided on its |
| 61 | +own unless noted. |
| 62 | + |
| 63 | +| Path | U | E | R / C | |
| 64 | +|---|---|---|---| |
| 65 | +| File download (CLI `files get`) | Delivered once; invocation withheld from the model; workbench copy stays unknown | Redacted | Delivered | |
| 66 | +| File download (run_code proxy) and mounts | Refused, not recorded, listed in `excludedInputs` | Recorded in workbench history | Delivered | |
| 67 | +| File text, version text, `files read`, grep | 403 | Redacted (grep redacts before clipping) | Delivered | |
| 68 | +| Bulk download zip | Left out | Left out (opaque) | Included | |
| 69 | +| `files search` | Results dropped | Results dropped (a match is an oracle) | Returned | |
| 70 | +| File edit (`PATCH` content) | 403 before reading | Diagnostics redacted | Unchanged | |
| 71 | +| Chat public share activation | 403 | 403 (a link is opaque) | Shares | |
| 72 | +| Rendered view, streamed image, inline attachments | Refused | Refused (opaque) | Delivered | |
| 73 | +| Doc compile | Compile refused | Error text redacted | Compiles | |
| 74 | +| Run file download | 403 | Redacted | Delivered | |
| 75 | +| Run read / execute / resume `base64` | `base64` removed, descriptor kept | Same | Inlined (sync runs only) | |
| 76 | +| KB chunks, search, documents, tags | Item dropped (single read: 403) | Redacted | Delivered | |
| 77 | +| KB export, table export download | Not available to Chat | | | |
| 78 | +| Table rows, query, read, `table_selection` | Row dropped (single read: 403) | Redacted | Delivered | |
| 79 | +| Row search | Match dropped | Match in a secret column dropped | Returned | |
| 80 | +| Table import from a file | Rows stored unknown | Per-cell entries | Exact-empty, as before | |
| 81 | +| `tools execute` for file, knowledge, table, memory, function, custom, MCP tools | Not available to Chat | | | |
0 commit comments