approval-engine/docs/caller-authentication.md

49 lines
2.5 KiB
Markdown
Raw Normal View History

# Caller authentication
Production accepts only RS256 JWTs verified against KeyCape JWKS with the exact
configured issuer and `approval-engine` audience. `exp`, `iat`, `sub`,
`principal_type`, `tenant`, `roles`, `scope`, and `assurance` are mandatory.
Missing or unverifiable credentials fail closed. The development static-token
mode is explicit, file-backed, and refused with `--production`.
The verified `tenant` must exactly match the service's configured store tenant;
cross-tenant reads and mutations are rejected before object lookup.
| Route | Required scope |
|---|---|
| create approval | `approval:create` |
| get approval or claim | `approval:read` |
| add approval entry | `approval:approve` |
| revoke | `approval:revoke` |
| supersede | `approval:supersede` |
| consume | `approval:consume` and service/agent principal |
| cadence, outbox, storage | `approval:observe` |
| explicit heartbeat | `approval:emit` |
Create additionally requires `binding.actor == sub`. Approval-entry subject,
assurance, evidence reference, and **principal type** are derived from the
verified JWT, never the request body.
`principal_type` is recorded on the entry (schema v4) because `subject_id`
alone cannot answer what kind of principal bound the approval — `user:alice` is
a naming convention, not a verified claim. This engine does not restrict
`/entries` to human principals: whether a service or agent may supply approver
evidence is approval doctrine and belongs to `gate-house`, and the
`approval-engine-operator` registration holds `approval:approve` today. What
this engine owes is that the evidence chain says which it was. Entries written
before v4 stay `null` rather than being back-filled into a claim nobody made. KeyCape owns client registration and scope grants; approval-engine
only verifies and enforces them. Requested registrations are:
- audience/resource server `approval-engine` with the scopes above;
- the secrets-engine PEP service client with `approval:read` and
`approval:consume`;
- separately governed lifecycle/operator clients with only their needed
mutation or observation scopes.
Client credentials belong in OpenBao/operator custody and must not be placed in
manifests, logs, State Hub, or this repository.
KeyCape's OpenBao service-auth contract currently emits `aud` as the OAuth
`clientId`. That pattern must not be reused here. Tokens presented to this API
MUST have resource-server audience `approval-engine`. Requested non-secret
client fragments are in `docs/keycape-service-registrations.md`.