Authentication Reference

Bearer authentication, API key behavior, permissions, and common authorization errors.

Alfred authenticates API requests with bearer API keys and authorizes each route through principal permissions.

Request Header

Authorization: Bearer <alfred-api-key>

Missing, malformed, expired, revoked, or unknown keys return:

{
  "error": "unauthorized",
  "message": "Missing or invalid bearer token"
}

with HTTP 401.

An authenticated principal without the required permission receives HTTP 403:

{
  "error": "forbidden",
  "message": "Missing required permission: workflows:add-domain"
}

Workflow permissions

PermissionAllows
workflows:onboard-domainInteract with onboard-domain.
workflows:add-certificateInteract with add-certificate.
workflows:add-domainInteract with add-domain.
workflows:add-subdomainInteract with add-subdomain.
workflows:update-lambda-versionInteract with update-lambda-version.

A workflow permission grants every supported client interaction for that workflow: submission, readback, cancellation, retry, recovery, and rollback. It also grants access to that workflow's execution events, stream records, and add-subdomain plan operations where applicable. Alfred exposes no manual pause operation; approval-driven waiting remains part of workflow orchestration.

Execution lists and SSE streams include only workflows the principal can currently access. Supplying a workflow filter never expands that access.

Non-workflow permissions

PermissionAllows
subscriptions:manageCreate and manage the principal's webhook subscriptions.
principals:manageManage another principal's API keys and revoke keys.
audit:readQuery authorization decisions.
admin:readInspect event-version usage and the configured Workflow Admin proxy.
admin:writeArchive an eligible deprecated event version after confirmation.

Operators grant workflow permissions by assigning roles in Alfred's persisted RBAC store. API clients and Slack users cannot grant themselves roles or permissions. The client API intentionally has no RBAC administration routes.

Slack uses the same permission names against the immutable slack:<workspace-id>:<user-id> principal. Membership in the configured workflow-operator group can supplement these permissions for Slack interactions only; it does not change bearer API permissions.

API Key Lifecycle

API key creation returns plaintext exactly once:

curl --fail-with-body --silent --show-error \
  -X POST "$ALFRED_API_URL/v1/principals/$PRINCIPAL_ID/api-keys" \
  -H "Authorization: Bearer $ADMIN_API_KEY" | jq

Store apiKey.plaintextToken in a secret manager. List responses expose only metadata and a display prefix. A principal may list or mint its own keys; principals:manage is required for another principal.

Revoke a key by ID:

curl --fail-with-body --silent --show-error \
  -X DELETE "$ALFRED_API_URL/v1/api-keys/$API_KEY_ID" \
  -H "Authorization: Bearer $ADMIN_API_KEY"

Revocation requires principals:manage and is immediate for subsequent authentication.

Stream Tokens

Stream tokens are not general API credentials. They:

  • require at least one workflow permission to mint;
  • expire after 300 seconds;
  • are single-use;
  • authenticate only the SSE stream route;
  • contain the minting principal identity, whose workflow permissions are resolved again when the stream connects.