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:
2026-03-15 00:39:41 -07:00
parent d87b4b4042
commit b1b52000c4
3 changed files with 164 additions and 9 deletions

View File

@@ -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