Reveal a credential
Show a stored secret to a named operator — and meet every guard the reveal path puts in the way.
The most sensitive read in the service, exercised guard by guard: Reveal returns plaintext exactly once per deliberate, named, audited request.
Goal
Reveal one credential's plaintext with a reveal-scoped token, and observe each refusal: wrong scope, anonymous call, deleted record.
Prerequisites
- A service token with the
provider-credentials.revealscope:export REVEAL_TOKEN=...; an admin-scoped token for contrast (Service Plane Tokens). - A stored credential's
id(scenario 07).
Steps
1. The admin scope is not enough
Call POST /internal/v1/admin/credentials/{id}/reveal with the admin token and an actor label. Expected 403 FORBIDDEN — edit rights do not imply seeing secrets; the scopes are granted separately.
2. Anonymity is refused
Same call with the reveal token but no X-Admin-Actor. Expected 400 INVALID_REQUEST — a reveal without a named operator would leave a meaningless audit trace, so it is rejected by construction.
3. The reveal itself
curl -s -X POST "$CREDS_BASE/internal/v1/admin/credentials/$CRED_ID/reveal" \
-H "Authorization: Bearer $REVEAL_TOKEN" \
-H "X-Admin-Actor: panel:olha"
Expected 200: plaintext credentials, open configuration, owner coordinates, revealed_at. This works even on a disabled record — a suspected-broken key is inspected exactly when it is off (Defaults and Lifecycle).
revealed = r.json()
assert revealed["credentials"]["api_key"].startswith("sk-") # the actual secret
4. The trace outlives the response
Query the audit trail for event_type=credential.revealed. Expected: an event with actor_id = "service:<client_id>!panel:olha", metadata naming the revealed field names (never values) — committed before the response was sent, and exempt from retention purge.
5. Deleted means gone
Soft-delete the credential, reveal again. Expected 404 CREDENTIAL_NOT_FOUND — the recovery window keeps ciphertext for operators of the purge job, not for reveals.
Verified by the test test_s08_reveal_a_credential.