key-cape/workplans/KEY-WP-0044-audit-correlation-and-intake.md
tegwick 1af86580e3 KEY-WP-0044: record hub ids
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 4515@bnt-lap001
Assistant-Session: 0bf96127-6e04-41be-bfda-d11717c3f354
2026-10-28 01:13:57 +01:00

83 lines
3.3 KiB
Markdown

---
id: KEY-WP-0044
type: workplan
title: "Audit correlation (traceparent) and audit-core intake for KeyCape"
domain: infotech
repo: key-cape
status: proposed
owner: claude-code
topic_slug: custodian
created: "2026-10-27"
updated: "2026-10-27"
flavor: extension
depends_on: []
state_hub_workstream_id: "7d8c5e7a-0291-58eb-a1cb-284d663468aa"
---
Accepted from net-kingdom NK-WP-0055-T11 under the NetKingdom Audit Correlation
Contract (`net-kingdom/canon/standards/audit-correlation_v0.1.md`, AC-1 to AC-7).
KeyCape's intake package for audit-core AUDIT-WP-0017-T04 is
`docs/audit-core-sender-package.md`. Nothing here registers a sender, mints a
credential or changes a live deployment; activation stays owner-run.
## Read inbound traceparent and record correlation_id
```task
id: KEY-WP-0044-T01
status: todo
priority: high
state_hub_task_id: "f059548e-f6eb-57a9-8ad2-9c7bcf2da2dc"
```
On `/authorize` (including the login, MFA and handoff legs of the same flow)
and `/token` (all grants), parse the inbound W3C `traceparent` header. If it is
valid (version 00, 32 lowercase hex trace-id, not all zeros, valid parent-id),
record its trace-id as `correlation_id` with `correlation_origin: propagated`;
otherwise generate a fresh random trace-id and record `correlation_origin:
generated`. Carry the value through the request context into every
`telemetry.Event` (today `TraceID` is always empty) and add a
`CorrelationOrigin` field. For the authorize flow, keep the id from the first
`/authorize` request on the login session so the success/failure record for
that flow carries it; `/token` uses its own inbound header.
Rules (AC-3, AC-5): the id is never placed in an access token, ID token,
refresh token, authorization code or userinfo response; it never influences an
authentication, authorization or token decision; a malformed header is ignored,
never an error. Outbound calls KeyCape makes while serving the request
(Authelia, LLDAP, privacyIDEA) send a `traceparent` with the same trace-id.
Tests: propagated, absent, malformed and all-zero headers; a decoded token from
each grant carries no trace id; the token/authorize response is identical with
and without the header.
## Emit audit-grade records for every issuance and refusal
```task
id: KEY-WP-0044-T02
status: todo
priority: high
state_hub_task_id: "b126f10a-d301-5512-8447-d1131608e4b5"
```
Close the gaps the intake package lists: emit on `/token` failures
(`invalid_client`, `invalid_grant`, `unauthorized_client`, `invalid_scope`),
on revoke and introspection, and on denied scope/tenant/principal-type
preconditions; add `sub`/`uid`, `tenant` and `principal_type` to
`token_issued`; add a stable `event_id` (UUIDv7 minted once per event, reused on
retry); set `environment` on every event. No secret, token, code, password,
OTP or email on any event.
## Forward to audit-core (after admission)
```task
id: KEY-WP-0044-T03
status: wait
priority: medium
state_hub_task_id: "721254d8-6b50-575c-9715-feaf2ef7e414"
```
Waits on audit-core admitting `netkingdom.keycape` (AUDIT-WP-0017-T04) and on
AUDIT-WP-0017-T05 confirming `correlation_origin`. Implement the envelope
mapping from the intake package (log-tail collector or direct POST, owner's
choice), heartbeat, and fixture tests against audit-core's receiver. Sender
credential is read from an OpenBao-delivered Secret; activation is owner-run.