# Trust boundary

Email is hostile input. The platform is built so that nothing in a message can act.

- **No model in the pipeline.** Classification and extraction are rules. There is no prompt to inject into. When your own agent reads a message over MCP it sees sanitized text with provenance, and your agent's actions go through the same proposal-and-policy path as anyone else's.
- **Raw MIME is stored, never served.** Tools and routes return sanitized text and document text. The raw message stays in object storage for reprocessing.
- **Hidden text is quarantined, and you are told.** HTML text that a person would not see (display none, zero font size, colour on the same colour, hidden attribute) is rendered separately, reported as `hidden_text`, flagged, and excluded from extraction. The order-confirmation fixture in our tests carries "IGNORE PREVIOUS INSTRUCTIONS" in a hidden div; it never reaches a field. By default policy then holds the message as a `flagged_message` task, a `message.flagged` event is written, and the flags travel in every webhook payload. A bucket that expects such markup (some newsletters do) can accept specific flags with `policy.on_flags`.
- **Sender identity comes from headers, not content.** SPF, DKIM and DMARC results are parsed from Authentication-Results and are available to rules (`{"auth": {"dkim": "pass"}}`). The receiving address is the envelope recipient.
- **Attachments are allowlisted.** Documents, images, plain data. Executables, macro-enabled office formats and archives are refused, their bytes dropped, and the refusal recorded. PDFs are parsed under size and page caps with document JavaScript disabled; a parse failure is a flag, not an error.
- **`requires_human` is absolute.** Fields marked that way always create a task. No confidence, no policy, no key scope auto-applies them.
- **Extraction cannot cause side effects.** Only a capture that policy applied, or a person or approve-scoped key approved, reaches a destination.
- **Every write has an actor** and every change is an event. Keys are hashed at rest; the plaintext is shown once.
- **Rate limits and per-address disable** come with real addresses. Addresses leak; abuse is expected.
