Key points
JWT_SIGNING_KEYsigns user, personal-access, service-account, browser, CLI, automation, and hosted MCP tokens.SERVICE_JWT_SIGNING_KEYsigns internal REST and dispatcher service tokens and must be a different secret.- Personal access tokens are created and revoked by the owning user under
/v1/auth/personal-tokens. - Service account tokens are administrator-managed under
/v1/admin/service-accounts/{id}/tokens. - Token values are returned once at creation and cannot be read back.
- A service account is a first-class caller for AAA, so it can be named in external trigger
allowed_callers.
Examples
# a personal token, for a human automating their own access
curl -sX POST "$NOPSAI_URL/v1/auth/personal-tokens" \
-H "Authorization: Bearer $NOPSAI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"laptop-cli"}' | jq
# a service account token, for a system
curl -sX POST "$NOPSAI_URL/v1/admin/service-accounts/$SERVICE_ACCOUNT_ID/tokens" \
-H "Authorization: Bearer $NOPSAI_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"release-bot"}' | jqHow it works
Use a service account for machine-to-machine automation rather than a human personal access token. It survives staff changes and carries its own roles and grants.
Internal service tokens are not part of the public surface. Routes under /v1/internal/ and the git-bot event ingress require them and should never be exposed as public endpoints.
Implementation evidence
doc/jwt-authentication.mdToken types, signing keys, and refresh behavior.
services/nopsai/routes.goPersonal token and service account token routes.

