# 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`, digital-context `inbound.read`, and physical-custody `inbound.item.read`, `inbound.item.action`, or `inbound.item.scan.read`) and are checked per endpoint. `mailbox.read`/`mailbox.write` cover logical outbound endpoints and never issue a receiving PMB. 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.
- Outbound mail requires `X-Mailbox-MD-Version`. Canonical physical Open & Scan requires the current item `expected_version` plus `Idempotency-Key`; no other physical action is publicly callable.
- 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.
- Identity documents submitted for USPS Form 1583 (photo ID and proof of address) are encrypted before storage with keys held in Google Cloud KMS; the storage bucket holds only ciphertext, and no signed or shareable links to these files exist.
- Those documents can be decrypted only for authenticated facility staff, only from approved networks, and only to verify the application; every access is recorded in the audit log.
- Retention follows the stricter of the two rules that apply to a California CMRA: the completed Form 1583 is kept as USPS and California law require, and the two identification copies are kept encrypted for two years after service ends, as California Business and Professions Code §17538.5 requires, then deleted.
- 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 is limited to approved, assigned accounts and 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.
