Sync docs and fix flaky renewal e2e test
- ARCHITECTURE.md: add Vault Endpoints section, /unseal UI page,
vault_sealed/vault_unsealed audit events, sealed interceptor in
gRPC chain
- openapi.yaml: add /v1/vault/{status,unseal,seal} endpoints, update
/v1/health sealed-state docs, add VaultSealed response component,
add vault audit event types and Admin — Vault tag
- web/static/openapi.yaml: kept in sync with root
- test/e2e: increase renewal test token lifetime from 2s to 10s
(sleep 6s) to eliminate race between token expiry and HTTP round-trip
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -431,11 +431,23 @@ All endpoints use JSON request/response bodies. All responses include a
|
||||
|---|---|---|---|
|
||||
| GET | `/v1/audit` | admin JWT | List audit log events |
|
||||
|
||||
### Vault Endpoints
|
||||
|
||||
| Method | Path | Auth required | Description |
|
||||
|---|---|---|---|
|
||||
| GET | `/v1/vault/status` | none | Returns `{"sealed": bool}`; always accessible |
|
||||
| POST | `/v1/vault/unseal` | none | Accept passphrase, derive key, unseal (rate-limited 3/s burst 5) |
|
||||
| POST | `/v1/vault/seal` | admin JWT | Zero key material and seal the vault; invalidates all JWTs |
|
||||
|
||||
When the vault is sealed, all endpoints except health, vault status, and unseal
|
||||
return 503 with `{"error":"vault is sealed","code":"vault_sealed"}`. The UI
|
||||
redirects non-exempt paths to `/unseal`.
|
||||
|
||||
### Admin / Server Endpoints
|
||||
|
||||
| Method | Path | Auth required | Description |
|
||||
|---|---|---|---|
|
||||
| GET | `/v1/health` | none | Health check |
|
||||
| GET | `/v1/health` | none | Health check — returns `{"status":"ok"}` or `{"status":"sealed"}` |
|
||||
| GET | `/v1/keys/public` | none | Ed25519 public key (JWK format) |
|
||||
|
||||
### Web Management UI
|
||||
@@ -458,6 +470,7 @@ cookie pattern (`mcias_csrf`).
|
||||
|
||||
| Path | Description |
|
||||
|---|---|
|
||||
| `/unseal` | Passphrase form to unseal the vault; shown for all paths when sealed |
|
||||
| `/login` | Username/password login with optional TOTP step |
|
||||
| `/` | Dashboard (account summary) |
|
||||
| `/accounts` | Account list |
|
||||
@@ -797,6 +810,8 @@ The `cmd/` packages are thin wrappers that wire dependencies and call into
|
||||
| `policy_rule_updated` | Policy rule updated (priority, enabled, description) |
|
||||
| `policy_rule_deleted` | Policy rule deleted |
|
||||
| `policy_deny` | Policy engine denied a request (logged for every explicit deny) |
|
||||
| `vault_unsealed` | Vault unsealed via REST API or web UI; details include `source` (api\|ui) and `ip` |
|
||||
| `vault_sealed` | Vault sealed via REST API; details include actor ID, `source`, and `ip` |
|
||||
|
||||
---
|
||||
|
||||
@@ -1010,9 +1025,12 @@ details.
|
||||
### Interceptor Chain
|
||||
|
||||
```
|
||||
[Request Logger] → [Auth Interceptor] → [Rate Limiter] → [Handler]
|
||||
[Sealed Interceptor] → [Request Logger] → [Auth Interceptor] → [Rate Limiter] → [Handler]
|
||||
```
|
||||
|
||||
- **Sealed Interceptor**: first in chain; blocks all RPCs with
|
||||
`codes.Unavailable` ("vault sealed") when the vault is sealed, except
|
||||
`AdminService/Health` which returns the sealed status.
|
||||
- **Request Logger**: logs method, peer IP, status code, duration; never logs
|
||||
the `authorization` metadata value.
|
||||
- **Auth Interceptor**: validates Bearer JWT, injects claims. Public RPCs
|
||||
|
||||
Reference in New Issue
Block a user