Component · console-api/

console-api

The identity authority. It owns who a caller is — identities, orgs, RBAC membership, and API keys — and hands the control plane a verifiable principal. It never runs workloads and never holds a brokered secret.

Role in the architecture#

Enclave splits identity from enforcement across two services. console-api is the authority for who: it signs users in, issues a user JWT (HS256), and stores orgs, members, roles, and API keys. The control plane trusts it for identity but enforces what a caller may do itself, on every route.

Source
console-api/src/auth.ts (login), orgs.ts / members.ts (orgs + RBAC), apiKeys.ts (key mint), internal.ts (the introspection endpoint), and repo/ (a pluggable memory or dynamo store).

What it owns#

  • Login → user JWT — authenticates a user and mints a short-lived HS256 JWT carrying the principal (user, org, role, scopes).
  • Orgs & membership — creates organizations and manages members with fixed roles: owner · admin · developer · viewer.
  • API keys — mints and revokes ek_<id>_<secret> keys for programmatic access from the SDK/MCP. Only the hash is stored; the secret is shown once.
  • /internal/introspect — the service-to-service endpoint the control plane calls to resolve an API key into a principal. Not exposed to callers.

The who / what split#

When a request reaches the control plane, its auth hook verifies the credential: a user JWT is checked locally (HS256), while an ek_ API key is resolved by calling console-api's /internal/introspect. Either way the result is a Principal{ userId, orgId, role, scopes } — that the control plane then uses to authorize and org-scope every action. console-api decides identity; the control plane decides access.

How it runs#

In production it deploys as an AWS SAM Lambda backed by DynamoDB. For local development and the dev loops it runs as a plain Express server with an in-memory repository — the same code path, no cloud dependencies. It is an external dependency the operator wires up: Enclave ships no manifest for it in deploy/; the control plane reaches it via its introspection endpoint.