# mailbox.bot — Security Overview

mailbox.bot sends real physical mail and charges real money, so the platform is built around scoped credentials, pre-charge spend controls, and human approval checkpoints. This page summarizes the security model for operators and agents evaluating the service. Vulnerability reports: security@mailbox.bot (machine-readable contact at https://mailbox.bot/.well-known/security.txt).

## Credential model

Four key types, each scoped to the minimum surface it needs:

- `sk_live_` (member): full account access for setup and administration.
- `sk_agent_` (agent): scoped to a single agent's resources. Agent keys cannot read or act on other agents — cross-agent access returns 403 `cross_agent_denied`.
- `sk_agent_test_` (sandbox): identical request shapes on production endpoints with no billing and no facility fulfillment. Responses carry `test_mode: true` and an `X-Test-Mode` header so test traffic is always distinguishable.
- `sk_facility_` (facility): scoped to one facility for scanner/intake applications.

Keys carry explicit scopes (for example `mail.send`, `mailbox.read`, `inbound.read`) and are checked per endpoint. Humans create, scope, and revoke keys in the dashboard; 401/403 responses include structured reason codes (`token_missing`, `key_revoked`, `insufficient_scope`, `cross_agent_denied`, and others) so clients can fail safely.

Agent self-registration (`/agent/auth`) never issues live spending credentials. It verifies that a human saw and approved the request by email one-time code; the human still completes onboarding, adds payment, and creates or approves the agent key.

## Spend and approval controls

Live mail submission is rejected before any upload or charge when a control fails:

- `dry_run=true` — full validation and exact cost breakdown with no record and no charge.
- `X-Max-Cost-Cents` — hard per-request cost cap, rejected with 422 before any charge.
- `requires_approval=true` — routes the piece to a human approval queue before fulfillment.
- `force_approval` (key policy) — every send from that key requires human approval, regardless of request parameters.
- `max_daily_pieces` (key policy) — per-key daily piece limit.
- Account-level daily spend caps, re-checked at approval time.

## Webhooks

Outbound webhooks are signed with HMAC-SHA256 (`whsk_` key prefix, `t=<timestamp>,v1=<hmac>` signature format) so receivers can verify origin and reject replays. Signing keys can be rotated via `POST /v1/webhooks/signing-keys/rotate`. Bearer-token and custom-header auth modes are also supported. Every delivery and retry is logged and inspectable via `GET /v1/webhooks/events`.

## Request integrity

- `Idempotency-Key` support on mutating endpoints prevents duplicate submissions; payment calls also carry idempotency keys to the payment processor so retries cannot double-charge.
- Mutating mail and action endpoints require the `X-Mailbox-MD-Version` header to match the agent's current standing instructions, preventing agents from acting on stale instructions.
- Rate limiting applies to public endpoints (per IP and per target email on registration/signup) and authenticated endpoints.

## Data handling

- Payments are processed by Stripe; mailbox.bot does not store card numbers.
- Uploaded documents are stored in access-controlled storage scoped by facility, member, and agent; database access is governed by row-level security.
- Admin and system mutations are audit-logged.

## Human oversight

Identity verification, payment, plan selection, and credential approval are human-only steps. Approval gates can hold any outbound piece for dashboard review before it is printed or mailed. Receiving mail at a mailbox.bot address (issuing begins August 31, 2026) additionally requires the human owner to complete a notarized USPS Form 1583, the standard postal authorization for commercial mail receiving agencies.

## Reporting a vulnerability

Email security@mailbox.bot. Please include reproduction steps and affected endpoints. Do not test against other customers' data or live mail fulfillment.
