key-cape/docs/audit-core-sender-package.md
tegwick 9adfb0bf4d KEY-WP-0044: traceparent correlation task and audit-core intake package (NK-WP-0055-T11)
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-27 23:28:54 +01:00

6.6 KiB

KeyCape audit-core intake package

Status: proposed, 2026-10-27. Answers audit-core AUDIT-WP-0017-T04 ("common intake package for every new sender") for KeyCape, and NetKingdom NK-WP-0055-T11. Implementation work: workplans/KEY-WP-0044-audit-correlation-and-intake.md. Unknowns are marked UNKNOWN. Authelia, LLDAP and privacyIDEA get their own packages and source names; this one covers KeyCape only.

1. What KeyCape emits today (from source, 2026-10-27)

All events go through telemetry.Emitter (src/internal/server/telemetry/). In production cmd/keycape/main.go wires a LogEmitter: one zerolog JSON line on stdout per event. There is no webhook, receipt store or audit-core sender.

Fields per line: event_type, client_id, endpoint, result, environment, trace_id, timestamp, and optionally feature, error_type, scopes, uid, assurance, grant_type. Events never carry tokens, codes, email or OTPs (comment in events.go).

event_type Emitted at
auth_start /authorize request accepted
auth_success /authorize completes (with uid, assurance aal1/aal2); also /userinfo
auth_failure /authorize: auth_failed, stale_upstream_authentication, mfa_check_error, mfa_failed
token_issued /token authorization_code/refresh and client_credentials success
unsupported_feature profile enforcement middleware
migration_event migration tools only (not the server)

Gaps against audit needs:

  • trace_id is never set (always empty) — fixed by KEY-WP-0044-T01.
  • No event on /token failures, client authentication failure, revoke or introspection; no explicit event for denied scope/tenant/principal-type preconditions — KEY-WP-0044-T02.
  • token_issued lacks subject and tenant; environment is unset on several emissions; no stable event id — KEY-WP-0044-T02.

2. Source registration

Item Value
source netkingdom.keycape (proposed)
Owning repo key-cape (runtime package owner: UNKNOWN, the Railiance/rapp package that deploys KeyCape)
Namespace / pod selector UNKNOWN — to be taken from the deploying package; KeyCape does not own its manifests
Emitting identity a dedicated KeyCape audit sender credential (section 6); not a KeyCape OIDC client
Tenant policy per-tenant: the event's tenant is the principal's tenant; platform-scoped events (client auth failure before a tenant is known, service clients without a tenant) use a platform tenant value — UNKNOWN, audit-core to name it

3. Envelope mapping (audit-core docs/event-envelope.md)

Envelope field KeyCape value
id (= Idempotency-Key) event_id: UUIDv7 minted once when the event is created and reused on every retry (KEY-WP-0044-T02). Not derived from request content, so two identical logins stay distinct
type keycape.<action> from section 4
source netkingdom.keycape
subject the principal (sub/uid) for user events; client:<client_id> for client-only events
tenant principal tenant, else the platform tenant value
correlation_id W3C trace-id from inbound traceparent, or a generated one (contract AC-1, AC-4)
occurred_at event timestamp, RFC 3339 with offset (UTC Z)
data client_id, endpoint, result, error_type, grant_type, scopes, assurance, principal_type, environment, correlation_origin (propagated/generated), optional parent_event_id

Never in data: access/ID/refresh tokens, authorization codes, client secrets, passwords, OTPs, email. actor is null at ingest per the envelope; the authenticated subject lives in subject/data.

4. Scope rows (action vocabulary)

type Today Meaning
keycape.auth.start yes authorize request accepted
keycape.login.success yes (auth_success) user authenticated, with assurance
keycape.login.failure yes (auth_failure) upstream auth failed or stale
keycape.mfa.success partly (aal2 on auth_success) MFA/step-up satisfied
keycape.mfa.failure yes (mfa_failed, mfa_check_error) MFA challenge failed or errored
keycape.token.issued yes token issued (any grant)
keycape.token.denied no /token refused: invalid_grant, invalid_scope, unauthorized_client
keycape.client.auth_failure no client authentication failed at /token, revoke or introspect
keycape.scope.denied no requested scope, tenant or principal-type precondition refused
keycape.token.revoked no revocation accepted
keycape.token.introspected no introspection served (volume to be judged; may be excluded)
keycape.userinfo.served yes (auth_success on /userinfo) userinfo served
keycape.profile.unsupported_feature yes request used a feature the profile refuses
keycape.heartbeat no liveness, section 5

migration_event is excluded: it comes from offline tools, not the server.

5. Volume, heartbeat, retention

  • Volume: UNKNOWN — no production measurement exists. Estimate for the current one-node estate with a handful of users and six flex-auth consumers: low hundreds to a few thousand events/day, peak under 5/s, dominated by token.issued (client_credentials) and userinfo.served. To be replaced by a measured count from the stdout stream before overlay sizing.
  • emission_cadence: event-driven plus keycape.heartbeat every 5 minutes; proposed silence threshold 15 minutes.
  • Retention: audit-core default 30-day query window plus archive. Proposed archive for login/MFA/token/denial records: 1 year (security-relevant identity evidence). Final class is a NetKingdom/audit-core decision — UNKNOWN.

6. Credential path

The sender secret is minted through the attended OpenBao path that warden route find "audit-core sender credential" points to (railiance-platform OpenBao), delivered to the KeyCape pod as a Kubernetes Secret reference, and never in Git, State Hub, logs or this document. audit-core never holds or prints it; may_read stays false; may_write is limited to source netkingdom.keycape. The exact OpenBao path and delivery mechanism are UNKNOWN until railiance-platform names them.

7. Export mechanism

Open choice, recorded in KEY-WP-0044-T03: (a) a collector tailing KeyCape's stdout JSON lines and posting envelopes, or (b) a KeyCape AuditEmitter posting directly with retry on the stable event_id. Preference: (b), because event_id and correlation_origin are known only inside KeyCape and a log tail cannot guarantee idempotent retry. UNKNOWN until audit-core states its preferred intake for application senders.