API Key Authentication
Key Format
API keys follow the format: ely_sk_<64-character-hex-string>
Keys are generated using cryptographically secure random bytes. The first 8 characters are stored as a prefix for identification in logs and admin interfaces.
Storage
Keys are stored as SHA-256 hashes. The raw key is never persisted. Lookup is performed by hashing the presented key and matching against stored hashes.
Scope-Based Access Control
API keys can be assigned specific scopes that restrict their access:
| Scope | Grants Access To |
|---|---|
execute:agent |
Agent task creation and execution |
audit:read |
Read audit logs |
admin:audit |
Manage audit policies |
admin:keys |
Manage API key rotation |
admin:tenant |
Tenant-level administration |
A key with null scopes has unrestricted access (legacy admin keys).
Scope validation is performed via hasScope(), hasAnyScope(), and hasAllScopes() helper functions on the authenticated request object.
Key Expiry
Keys have an optional expiration date. The remaining time-to-expiry is communicated to clients via the X-API-Key-Expires-In response header, allowing clients to rotate keys before expiry.
Key Provisioning
Keys are provisioned via:
- Admin API: POST
/api/v1/admin/tenants(creates tenant + key) - Admin Jobs service:
create-api-keyCLI tool (Cloud Run Job) - Service bootstrap:
ensure-api-keysfor development/production defaults
Implemented in packages/auth/src/middleware.ts and services/admin-jobs/ at commit 4b572c2.