
# Security overview

Ethen handles API keys, provider credentials, and request metadata across several surfaces. This page summarises the security boundaries you should be aware of before integrating.

## Release honesty (M9)

- Platform security controls (auth fail-closed, tenancy matrix, vault patterns) are documented and partially certification-proven in SOL-43.
- The **Security (Sentinel) workspace** is **deferred / private-alpha enrollment**, not a public-beta launch product.
- **Launch Gate K** (independent security review) is **BLOCKED** until an external reviewer attests — see [Certification status and known limits](/docs/resources/certification-and-limits).
- **Payment collection is implemented in code but is not live-certified or production-ready** in this release.


## API key storage and verification

Ethen Gateway API keys are **never stored in plain text**. When a key is created:

1. A random 16-byte salt is generated.
2. The raw key is combined with the salt and hashed with SHA-256.
3. Only the `algorithm:salt:digest` triplet is stored.

When a key is used for authentication, the raw submitted key is hashed with the stored salt and compared using constant-time comparison (`crypto.timingSafeEqual`). A key that was never created or has been revoked cannot be verified.

Keys are scoped per project and per environment (`live` or `test`). The key prefix and suffix are stored in plain text for identification in dashboards and logs; the full key is never persisted after creation.

See the [Gateway authentication guide](/docs/gateway/authentication) for key creation and usage.

## Credential management

Provider credentials (third-party API keys for OpenAI, Anthropic, DeepSeek, etc.) are managed through a **credential store abstraction** that keeps raw secrets off the renderer process and out of plain-text configuration files:

- **Desktop (Electron) mode** — uses `safeStorage.encryptString`/`decryptString` via IPC. Encrypted blobs are stored in a scoped file. Only credential references (provider ID + label) are exposed to the renderer.
- **Web mode** — delegates to existing `process.env` resolution (`getProviderApiKey`). Setting and deleting are no-ops; environment variables are read-only at runtime.
- **Gateway BYOK** — provider keys stored for a project are encrypted at rest with AES-256-GCM and stored in the `gateway_provider_credentials` table.

## Managed vault and approvals

Connected Apps credentials live in the **managed vault**, the only interface that may hold secret values:

- Production adapters are backed by a managed KMS/vault. Database rows hold an opaque `externalRef` — never the secret value.
- Flow grant secrets resolve to a sealed credential handle reachable only through `reveal()`; every implicit serialization path (logs, errors, caches, telemetry) is redacted.
- Every vault touch emits an audit event — created, read, rotated, revoked — with actor, purpose, reference, and version.
- Secret lifecycle is explicit: `staged` → `active` → `superseded` or `revoked`.

Sensitive actions on connected accounts pause for **approval** at `/api/platform/approvals` before running. Approvals name the exact action, account, and scopes; they expire; changed actions need fresh approvals. See [Connected Apps overview](/docs/connected-apps/overview) and the [approval governance guide](/docs/security/approval-governance).

## Secrets redaction

Before content is stored, displayed, or exported, a centralised redaction layer scans for common secret patterns and masks them:

- OpenAI-style keys (`sk-...`)
- Anthropic-style keys (`sk-ant-...`)
- AWS access keys (`AKIA...`)
- SendGrid keys, Firebase tokens, and generic `sk_`/`pk_` prefixed keys
- Sensitive metadata fields (secrets, tokens, keys, passwords, credentials, cookies, headers, bodies) are stripped from audit exports.

## Safe error handling

API error responses are constructed through a centralised `jsonError` utility that:

- Clamps HTTP status codes to the 400–599 range.
- Redacts error messages to a maximum length (default 500 characters).
- Returns structured `{ ok: false, code, error }` objects without leaking secrets.

Gateway-specific errors produce codes like `SETUP_REQUIRED`, `PROVIDER_UNAVAILABLE`, `INVALID_REQUEST`, and `INTERNAL_ERROR` that are safe to surface in client responses.

## Audit export

All audit entries pass through a `stripSensitiveMetadata` filter before export. Fields matching secret, token, key, credential, authorization, cookie, body, header, or session patterns are removed from the exported record. Metadata that survives the filter includes event type, timestamp, actor ID, and high-level outcome.

## Data handling

Gateway request logs contain **metadata only** — model, provider, tokens, cost, and timestamps. Request and response content is never stored in the Gateway logging pipeline unless separately configured. See the [data handling guide](/docs/security/data-handling) for configuration options.

## Review-required statements

The following claims in this guide have not been independently verified by a security review and should be reviewed before publication:

- Credential store patterns on Desktop rely on Electron `safeStorage` availability and have not undergone external penetration testing.
- Data retention commitments depend on the project's configured `contentRetentionDays` and `loggingMode` settings — no default retention SLA is guaranteed.
