# Security model

Ozma is designed so agents can call third-party APIs **without ever seeing upstream provider secrets**. Security spans credential storage, key hashing, session hygiene, and abuse prevention.

## Upstream credentials

Provider secrets are encrypted with **AES-256-GCM** before storage. Only the gateway decrypts at proxy time and injects them into outbound requests — never into API responses, MCP tool output, or usage logs.

## Ozma API keys

- Format: `ozma_live_<24 chars>` (plaintext shown once at creation)
- Storage: SHA-256 hash (+ optional pepper) — not reversible
- Scoped: least privilege per key; anonymous register keys omit billing/provider scopes
- Revocation: soft-delete; immediate effect on next request

## Sessions

Session tokens (`sess_…`) are 30-day control-plane credentials created on signup or OTP login. They grant full scopes for dashboard operations but are **rejected on the gateway** — proxy calls require API keys.

Passwordless login uses rate-limited 6-digit codes with constant-time verification. Logout deletes the server-side session row.

## Network hygiene

- CORS allowlists production and local web origins
- Stripe webhooks verified with signing secret
- Secrets live in Wrangler / environment — never in git

## Abuse controls

- Turnstile on human signup (not on agent register)
- Per-IP and per-email signup rate limits
- Gateway rate limits (~300/min per key)
- Self-dealing proxy blocked (same consumer + provider org)

## Provider terms gate

When providers require acceptance, the gateway fails closed with **428** before charging or calling upstream. Anonymous agent orgs must attach a verified human owner before acceptance.

## Reporting issues

Report vulnerabilities via the contact addresses on [https://ozma.app/contact](https://ozma.app/contact).

## Learn more

- [Authentication](/docs/getting-started/authentication)
- [Keys & budgets](/docs/guides/keys-and-budgets)
