feat(admin): GET /api/v1/admin/jwt/secrets — metadata-only introspection (#51)
Some checks failed
CI/CD Pipeline / Build Docker Cache (push) Successful in 57s
CI/CD Pipeline / Trigger Docker Push (push) Has been cancelled
CI/CD Pipeline / CI Pipeline (push) Has been cancelled

Co-authored-by: Gabriel Radureau <arcodange@gmail.com>
Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
This commit was merged in pull request #51.
This commit is contained in:
2026-05-05 09:51:54 +02:00
committed by arcodange
parent 46df1f6170
commit f71495b6fc
5 changed files with 118 additions and 1 deletions

View File

@@ -82,7 +82,27 @@ JWT secret rotation policies: cf. ADR-0021 + JWT secrets endpoints under `/api/v
### Admin under v1 (`/api/v1/admin/...`)
JWT secret management endpoints. Cf. swag annotations in handlers + features/jwt/ BDD scenarios for the exact contract.
JWT secret management endpoints.
| Method | Path | Purpose |
|---|---|---|
| `GET` | `/api/v1/admin/jwt/secrets` | List metadata (count + per-secret: is_primary, created_at_unix, expires_at_unix?, age_seconds, is_expired, sha256 fingerprint). **Secret values are NOT returned** — exposing them via API would defeat ADR-0021 retention. |
| `POST` | `/api/v1/admin/jwt/secrets` | Add a new JWT secret (body: `{secret, is_primary, expires_in}`) |
| `POST` | `/api/v1/admin/jwt/secrets/rotate` | Rotate to a new primary secret (body: `{new_secret}`) |
`GET` response shape (security: only fingerprint, no secret value):
```json
{
"count": 2,
"secrets": [
{"is_primary": true, "created_at_unix": 1714900000, "age_seconds": 600, "is_expired": false, "secret_sha256": "a3f9c2..."},
{"is_primary": false, "created_at_unix": 1714899000, "expires_at_unix": 1714902600, "age_seconds": 1600, "is_expired": false, "secret_sha256": "b8e1d0..."}
]
}
```
Cf. ADR-0021 + features/jwt/ BDD scenarios for the broader contract.
## v2 API