Implement approval engine production readiness

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a05e2e-805b-7042-a750-71f473bceea2
This commit is contained in:
tegwick 2026-09-02 00:52:04 +02:00
parent ebce5abb27
commit 2bd2d19a98
30 changed files with 1679 additions and 53 deletions

View file

@ -41,9 +41,12 @@ emitted class. The validity window is already on the object.
| `event_id` | UUID | Stable. Drain retries reuse it. |
| `class` | enum above | |
| `approval_id` | UUID or null | Null only for heartbeat. |
| `payload` | object | The `audit-core.event.v1alpha1` record, ready to POST. |
| `payload` | object | The source record adapted to audit-core's HTTP envelope at drain time. |
| `created_at` | RFC 3339 UTC | |
| `drained_at` | RFC 3339 UTC or null | Set after a successful audit-core ack. |
| `attempts` | integer | Delivery attempts, including the successful attempt. |
| `last_attempt_at` | RFC 3339 UTC or null | Most recent delivery attempt. |
| `last_error` | class name or null | Bounded failure category; never exception text. |
## Payload (audit-core v1alpha1)
@ -76,9 +79,13 @@ approval-validity query; this payload does not invite one.
## Drain
1. Select undrained rows, oldest first.
2. POST each payload to `audit-core`.
3. On success, set `drained_at`.
4. On failure, leave the row; retry later. **Do not** roll back the object
2. Adapt it to audit-core's `{id,type,source,subject,tenant,correlation_id,
occurred_at,data}` envelope, using `event_id` as both `id` and the
`Idempotency-Key` header.
3. POST with the mounted sender credential, reread on every attempt.
4. On `202 accepted` or `200 duplicate`, set `drained_at`.
5. On failure, leave the row and record only a bounded failure class; retry
later. **Do not** roll back the object
mutation — it already committed with the row.
An `audit-core` outage therefore cannot block a revocation. This engine's