docs(plan): showcase covers realistic upload formats — two-stage extract→guard, dev-scoped parsers, honest binary-layer limits

This commit is contained in:
Kjell Tore Guttormsen 2026-07-06 10:18:43 +02:00
commit 896ab4034a

View file

@ -244,6 +244,53 @@ prove intent, not to coincidentally pass.
— semantic/factual poisoning stays out (README honest-limits), consistent with
the core showcase.
#### Realistic upload formats — the two-stage inbox (extract → materialize → guard)
A human inbox does not receive tidy `{path: text}` dicts; it receives the files
people actually drop: `.txt`, `.md`, Word `.docx`, Excel `.xlsx`, PowerPoint
`.pptx`, `.pdf`, `.csv`, whole **folders**, and **`.zip`** archives. The showcase
therefore has two stages, honouring the locked text-extraction boundary (§
"Text-extraction boundary"): the guard core never grows a file parser.
1. **Extract & materialize (the inbox front-end).** Reads each dropped file, walks
folders, and *safely* unpacks archives; extracts text via format libraries
(`python-docx`, `openpyxl`, `python-pptx`; stdlib `zipfile`/`csv`); materializes
the result into an OKF bundle `{concept_path: text}` with provenance
(`origin=EXTERNAL`, source filename + type). **This stage owns the container and
format threats.** These libraries are **showcase/dev-scoped only** — never core
`dependencies` (which stays `[]`). Promotion to an optional `[extract]` extra is
a documented future option if a consumer wants turnkey extraction, not v1.
2. **Guard (`import_bundle`).** Scans every extracted concept + the OKF structural
gates → aggregate disposition. **This stage owns the text/structural threats.**
**One representative planted vector per format** (the point is where the payload
hides — the place a human does not look):
| Input | Hidden vector planted | Caught at |
|---|---|---|
| `.txt` | raw injection + carrier (zero-width / homoglyph / rot13 / base64) | guard scan |
| `.md` | OKF frontmatter attack (T2) + body injection (T1) | guard |
| `.docx` | injection in a **comment / hidden (vanish) run / core metadata property** | guard scan of extracted text |
| `.xlsx` | **formula injection** (`=cmd\|'…'`, `=HYPERLINK(…)`) + **hidden sheet / cell comment** | front-end + guard |
| `.pptx` | injection in **speaker notes / off-slide text box / image alt-text** | guard scan |
| `.pdf` | injection in extracted / **white-on-white** text | guard scan |
| `.csv` | formula injection (`=`, `+`, `-`, `@` lead) | front-end + guard |
| **folder** | the OKF bundle-directory shape directly; one member path trips the path gate (T4) | guard |
| **`.zip`** | **zip-slip** entry `../../x.md` (maps straight onto OKFPathError, T4) + **zip-bomb** (bounded by the size cap / a safe-extract limit, LLM10) + symlink entry | front-end + guard |
**Assertions:** each planted vector is caught at the correct stage; the front-end
refuses zip-slip / zip-bomb / oversize fail-fast; the guard rejects
injection/carrier/frontmatter/resource/link/path; a **clean** file of every format
admits (WARN). Detach-proof at **both** stages.
**Honest scope for uploads (must be conceded — README honest-limits).** What
survives text extraction is **out of scope**: VBA/macros (`.docm`/`.xlsm`/`.pptm`),
OLE / embedded objects, image-embedded instructions that need OCR, font/render
steganography, and encrypted/password-protected files. The guard scans *extracted
text*; binary-layer carriers need a separate scanner. A high-untrust, unattended
inbox is exactly where assuming uncovered-coverage is most dangerous (§4.7), so the
concession is itself a control.
**Deferred, unchanged:** T5b/B (the persisted cross-run link graph) waits for a
consumer that owns corpus storage; §7.2 dormant cross-run links remain a
documented residual until then.