---
title: "The trust model"
description: "What the mbag.ai server enforces regardless of what your agent does — inbound screening, outbound blocklists, operating modes, send caps, and a tamper-evident audit log."
order: 3
---

Your agent runs code you wrote (or an LLM generated). The server does not
trust that code. Every mail-moving action on mbag.ai passes through
server-side checks your agent cannot see around, configure away, or talk its
way past. This page describes what those checks are.

## What the server enforces

**Inbound policy screening, before your agent sees the mail.** Every message
arriving at a mailbox is evaluated against that mailbox's policy — sender
allowlist, DKIM/SPF verification, content guards — before a single token
reaches your agent's code. The evaluator walks the policy's sender rules top
to bottom; the first match wins. No matching rule means the message never
reaches the agent at all.
<!-- source: src/content/docs/policy.md:9-11 -->
<!-- source: backend/src/policy_eval.rs:1-9 -->

**Outbound blocklist.** A mailbox owner can set recipient addresses or
domains the mailbox may never send to, "regardless of capability" — this is
enforced independently of anything the agent's policy grants it.
<!-- source: backend/src/policies.rs:35-40 -->

**Operating modes.** Every mailbox has a mode that gates how far an
agent-generated send is allowed to travel, independent of what the agent
believes it's doing:
- **Live** — sends leave immediately. The default for every mailbox.
- **Supervised** — every send is parked for one-click human approval before
  it leaves.
- **Shadow** — nothing ever leaves; the agent's draft and the fact that it
  would have sent are recorded, and that's all.
<!-- source: backend/src/policies.rs:41-66 -->

**Send caps.** The free tier is capped at 1,000 emails/month per account and
100 sends/day per mailbox (a tenth of the monthly quota, as a burst brake).
Only mail that actually left counts against the quota — a held or blocked
send costs nothing.
<!-- source: backend/src/send_caps.rs:1-28 -->

**Tamper-evident audit log.** Every MCP tool call is logged, including
denials — a blocked send or a refused read is recorded as signal, not
discarded as noise. Each row is hash-chained to the previous row for the
same customer (`entry_hash = SHA256(prev_hash || canonical_fields)`),
so deleting or editing any row breaks the chain from that point forward
and is detectable.
<!-- source: backend/src/mcp/audit.rs:1-15 -->

## What your agent cannot do

Your agent can *propose* — a new allowed sender, a request to widen its own
capabilities, a promotion from sandbox to production — but proposing changes
nothing on its own. Every one of those creates a row that sits inert until a
named human approves it out-of-band. Only that approval, done by a human,
makes the change take effect. Your agent cannot promote itself, cannot widen
its own scope, and cannot approve its own drafts.
<!-- source (propose-never-grant; promotion + scope-widening): backend/src/mcp/approvals.rs:1-6 -->
<!-- source (draft release is human-only): backend/src/agents/jmap_send.rs:453-458 — the ungated send may only be called by the gated send_reply and the human release path core_approve_draft (backend/src/mcp/rest.rs:1431) -->

## Fail-closed default

New mailboxes are seeded with `defaultAction: bounce` — a sender who matches
no rule in the policy is bounced, not silently allowed through on the
assumption that "no rule" means "no restriction." A malformed or missing
sender address falls back to the same default: an empty sender list and
`bounce` for everyone.
<!-- source: backend/src/policies.rs:434-460 -->
<!-- source: backend/src/policy_eval.rs:350-367 (scenario_b_unknown_sender_bounces) -->

None of this depends on your agent behaving well. It is what happens when it
doesn't.
