Skip to content

implement the CAEP 1.0 event vocabulary#1

Merged
hstern merged 1 commit into
mainfrom
feat/caep-events
Jun 21, 2026
Merged

implement the CAEP 1.0 event vocabulary#1
hstern merged 1 commit into
mainfrom
feat/caep-events

Conversation

@hstern

@hstern hstern commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Brings go-caep from a stub to the full OpenID CAEP 1.0 event vocabulary.

What's here

  • Eight typed event payloadsSessionRevoked, TokenClaimsChange, CredentialChange, AssuranceLevelChange, DeviceComplianceChange, SessionEstablished, SessionPresented, RiskLevelChange — each embedding a common Base envelope (event_timestamp as go-secevent's NumericDate, initiating_entity, reason_admin, reason_user). The subject stays the SET's sub_id.
  • Event-type URI constants + typed-constant sets for the enumerated values.
  • Registration into go-secevent's registry from a single init (one RegisterEventType per URI), so import _ "github.com/hstern/go-caep" wires the whole vocabulary.
  • Lenient decode / strict opt-in: unknown enum values and unrecognized members are preserved (the latter as json.RawMessage, re-emitted byte-stably). Validate checks the CAEP required-field MUSTs and returns errors.Is-matchable sentinels.
  • Put producer helper; Example_* functions; a conformance suite round-tripping a spec-shaped golden fixture per event type.

Notes

  • Adds the one sanctioned runtime dependency, go-secevent v0.1.0 (transitively go-subjectid).
  • risk-level-change (CAEP 1.0 §3.9) is included — the original scaffold brief's expected list omitted it.
  • Statement coverage ~91%; go vet, race tests, and golangci-lint all clean locally.

🤖 Generated with Claude Code

Add typed payloads for all eight OpenID CAEP 1.0 event types and register
their decoders with go-secevent, so a parsed Security Event Token's
events decode to typed Go values and CAEP events can be built back into a
SET. This is the substance of the library; the stub package becomes a
real vocabulary.

Each event embeds a common Base envelope carrying the optional CAEP §3.1
fields (event_timestamp as go-secevent's NumericDate, initiating_entity,
reason_admin, reason_user); the subject stays the SET's sub_id and is not
duplicated on the event. The eight types are SessionRevoked,
TokenClaimsChange, CredentialChange, AssuranceLevelChange,
DeviceComplianceChange, SessionEstablished, SessionPresented, and
RiskLevelChange — the last of which the original scaffold brief's
expected list omitted but CAEP 1.0 §3.9 defines.

Registration follows go-secevent's documented idiom: a single init calls
RegisterEventType once per event-type URI, so a side-effect import wires
the whole vocabulary (the database/sql-driver pattern). A generic decoder
keeps that to one function. Decoding is lenient — unknown enum values and
unrecognized members are preserved, the latter as json.RawMessage that
re-emits byte-stably, so an event from a future CAEP profile survives a
decode/encode cycle. Strictness is opt-in via Validate, which checks the
required-field MUSTs and returns errors.Is-matchable sentinels.

Tests cover registration completeness, typed-field extraction, lenient
enums, open-extension round-tripping, the producer/consumer path through
a real SET (Put then Parse then Typed), malformed-payload errors, and the
required-field MUSTs. A conformance suite round-trips a spec-shaped golden
fixture for every event type (CAEP 1.0 ships no machine-readable
vectors). Statement coverage is ~91%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hstern hstern enabled auto-merge (squash) June 21, 2026 11:41
@hstern hstern merged commit 307d8c8 into main Jun 21, 2026
4 checks passed
@hstern hstern deleted the feat/caep-events branch June 21, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant