"""M7: the imported knowledge library's HTTP surface. Every route here is scoped to one campaign, twice. `current_adventure` resolves `{adventure_id}` to an adventure the caller owns or 404s; `_source_or_404` then requires the source to belong to *that* adventure. A source id from another campaign is a 404 whichever campaign asks, so guessing ids gets nowhere and nothing depends on the browser filtering anything (`IMPORTED-KNOWLEDGE-DESIGN.md` §66). ## The upload takes a file, never a path `POST .../knowledge` accepts `multipart/form-data` and reads `UploadFile`. There is no endpoint anywhere that takes a server-side pathname, so H08's traversal has nothing to traverse: no path is resolved, no root is compared against, no symlink is followed, because none of those operations exists on this surface. The filename that arrives is metadata and is cleaned before it is stored. ## Imported text is inert on the way out as well as on the way in Every response here is JSON, served by FastAPI with `application/json`, and the browser puts source text into a `
` as a text node. Nothing renders imported
Markdown as HTML, so a `