AEP-0005: Bridge Annexes (CloudEvents, OTLP, and OCSF)

Defines the lossless, mechanical, reversible mapping between AEP Events and CloudEvents 1.0 (JSON format, structured mode), the export of AEP Events to OpenTelemetry as OTLP LogRecords, and the projection of AEP's security-relevant event families onto OCSF (Open Cybersecurity Schema Framework) class

Draft: the AEP suite is pre-v0.1; each document's status lives in its header table. This page is rendered from the canonical spec/AEP-0005-bridges.md, which is the normative text.

Field Value
AEP 0005
Title Bridge Annexes: CloudEvents Mapping, OTLP Export, and OCSF Projection
Type Standards Track — Annex (normative)
Status Draft
Sponsor AEP maintainers
Created 2026-07-03
Requires AEP-0001, AEP-0002
Supersedes / Superseded-by n/a

Provenance (non-normative): the bridges are normative, day-one deliverables: the mapping tables are specification text, the reference implementations are conformance-tested, and both are versioned and released with the specification; this is the standing answer to "adopters would rather ingest CE/OTLP".

Abstract

Defines the lossless, mechanical, reversible mapping between AEP Events and CloudEvents 1.0 (JSON format, structured mode), the export of AEP Events to OpenTelemetry as OTLP LogRecords, and the projection of AEP's security-relevant event families onto OCSF (Open Cybersecurity Schema Framework) classes for security-analytics consumers.

Losslessness is a design property (the AEP envelope is deliberately CE-isomorphic), so the CE mapping is five rules and one table, and round-trip identity is a conformance requirement, not an aspiration. The OCSF projection is deliberately partial by scope, not by loss: it carries the security signal (sessions, tool activity, human-attention outcomes), and every record embeds the complete source envelope.

1. CloudEvents mapping: forward (AEP → CE)

Output: a valid CloudEvents 1.0 event, JSON format, structured mode.

Rules:

  • B1 (constants). Set specversion: "1.0"; set datacontenttype: "application/json" when data is present.
  • B2 (pass-through). id, source, subject, time, data copy verbatim.
  • B3 (type). type := "dev.aep." + type (reverse-DNS root; placeholder frozen at the naming decision). Vendor types map under the same root: x.acme.foo.bar → dev.aep.x.acme.foo.bar.
  • B4 (attributes). Each remaining envelope attribute maps to its prefixed CE extension attribute per the table below. AEP envelope values are CE-legal extension scalars (string/integer/boolean) by design; there is no encoding step. AEP extension attributes (AEP-0001 §5.4) pass through verbatim (their naming rule is CE's).
  • B5 (trace context). traceparent maps to the CE Distributed Tracing extension attribute traceparent, unprefixed (CE already standardizes it).
AEP attribute CE attribute
aep aepversion
agent aepagentid
session aepsessionid
run aeprunid
step aepstep
seq aepsequence
epoch aepepoch
cause aepcausationid
severity aepseverity
capture aepcapture
traceparent traceparent

Absent OPTIONAL AEP attributes produce no CE attribute (defaults are not materialized).

2. CloudEvents mapping: inverse (CE → AEP), and scope

  1. For CE events whose type begins with the frozen root: drop the B1 constants, strip the B3 prefix, reverse the B4/B5 table, pass B2 through. The result MUST be the original AEP Event, bit-for-bit modulo JSON member order.

  2. Unknown aep*-prefixed extension attributes on inbound events MUST be preserved when their names are legal AEP extension names (AEP-0001 §5.4). They may be from a newer minor version, and any attribute a conformant newer-minor bridge mints satisfies the grammar by construction, since the extension grammar is version-stable. A name violating the shared grammar cannot ride the envelope (the envelope schema rejects it) and is dropped with a diagnostic like any other illegal name.

    Other unknown CE extension attributes SHOULD be preserved as AEP extension attributes when their names are legal (AEP-0001 §5.4), otherwise dropped with a diagnostic.

  3. Foreign CE events (any other type) are out of scope: the bridge is an AEP-to-CE profile carrier, not a universal CE ingester. Lifting foreign CE traffic into AEP is an adapter's job (custom/x.*), like any other source.

3. OTLP export (AEP → OpenTelemetry)

3.1 Signal

AEP Events export as OTLP LogRecords (the OTel Events model: LogRecord + event_name), not synthesized spans. Span synthesis (session/run/step spans from start/finish pairs via cause) is a possible future exporter mode: additive, deferred (an open question for a future revision).

3.2 Field mapping

AEP OTLP LogRecord Note
time time_unix_nano RFC 3339 → epoch nanos
type event_name = "dev.aep." + type same string as the CE bridge: one exported identity everywhere
severity severity_text + severity_number table §3.4
traceparent trace_id, span_id, flags parsed W3C fields; Events land on existing traces
agent resource attribute service.name (default) + attribute aep.agent_id resource = the emitting agent process; override for shared relays
session / run / step attributes aep.session_id, aep.run_id, aep.step
id / seq / epoch / cause / capture attributes aep.event_id, aep.sequence, aep.epoch, aep.causation_id, aep.capture
subject / source attributes aep.subject, aep.source
data members named gen_ai.* top-level LogRecord attributes, verbatim the OTel-mirror rule's payoff: token counts, model names light up in backends with zero mapping code
remaining data body (AnyValue map) preserved wholesale

3.3 Capture enforcement at the exporter

The exporter takes a max_capture setting (default metadata). Events above it are down-leveled per AEP-0001 §8.2 / AEP-0002 §5.1 before export; capture: none Events export envelope-derived attributes only (no body). Backends never see what the operator did not opt into.

3.4 Severity mapping

AEP severity_text severity_number
debug DEBUG 5
info INFO 9
notice INFO2 10
warning WARN 13
error ERROR 17
critical FATAL 21

The inverse buckets OTLP ranges back to the six AEP levels (1-8 to debug, 9 to info, 10-12 to notice, 13-16 to warning, 17-20 to error, 21-24 to critical).

3.5 Exporter shape

aep-bridge-otlp is an ordinary AEP consumer: it subscribes with attr-match filters (operator-scoped), batches, and emits OTLP/HTTP. It is an ecosystem consumer, never normative infrastructure.

4. OCSF projection (AEP → OCSF)

4.1 Signal and scope

AEP's security-relevant event families project onto OCSF (Open Cybersecurity Schema Framework) event classes, so security-analytics backends that ingest OCSF natively (SIEM and security-lake deployments) can consume AEP fleets with zero mapping code. The projection targets OCSF version 1.8.0 (pinned; re-checked per AEP release, §5).

Three AEP families project; every other event (the control plane, progress, presence, messages, vendor x.* traffic) deliberately produces no OCSF record. This is a scope decision, not a loss: the OTLP export (§3) is the full-fidelity telemetry channel, the OCSF projection is the security-signal channel, and flooding a security pipeline with non-security agent chatter under classes that do not mean it would be a mis-mapping.

Like the OTLP exporter (§3.5), an OCSF forwarder is an ordinary AEP consumer; the mapping below is normative independent of any runtime.

4.2 Class mapping

AEP event OCSF class activity_id status_id disposition_id
session.started Authentication (3002) 1 Logon 1 Success n/a
session.ended Authentication (3002) 2 Logoff 1 Success n/a
tool.requested Process Activity (1007) 1 Launch n/a n/a
tool.completed Process Activity (1007) 2 Terminate 1 Success n/a
tool.failed Process Activity (1007) 2 Terminate 2 Failure n/a
tool.denied Process Activity (1007) 1 Launch 2 Failure 2 Blocked
attention.requested Detection Finding (2004) 1 Create 1 New n/a
attention.answered Detection Finding (2004) 2 Update 2 In Progress n/a
attention.resolved Detection Finding (2004) 3 Close 4 Resolved see §4.5
attention.timeout Detection Finding (2004) 3 Close n/a 16 No Action

category_uid is the class's OCSF category (3 IAM, 1 System Activity, 2 Findings); type_uid := class_uid * 100 + activity_id. All Detection Finding records of one attention lifecycle share one finding identity: finding_info.uid is the attention.requested Event's id, its own id on the request, the subject on every later lifecycle Event (the stable correlation AEP-0002 §5 guarantees).

4.3 Record construction

Every projected record is derived from the envelope plus the capture-surviving payload, and nothing else:

  • time := time as epoch milliseconds; metadata := {version: the pinned OCSF version, uid: id, original_time: time, product: {name: agent}}, plus correlation_uid := cause when present. When the record asserts a disposition_id it declares metadata.profiles: ["security_control"] (the disposition attribute rides that OCSF profile).
  • severity_id per the §4.4 table; message := type.
  • Authentication: user := {name: agent}, session := {uid: session}.
  • Process Activity: actor := {app_name: agent}; process := {name: subject} plus uid := the tool call id when the surviving payload carries it; device := {type_id: 0} plus hostname := the source URI authority when it has one, else name := source verbatim.
  • Detection Finding: finding_info := {uid: the request id (§4.2), title: type}.
  • Fidelity carrier: unmapped.aep := the complete envelope verbatim (every attribute except data, extension attributes included); unmapped.data := the capture-surviving payload verbatim (omitted when empty). A consumer can always recover the full AEP identity from the record.

Records satisfy the base-class required attributes of the pinned OCSF version by construction. One documented edge: when a tool Event's payload does not survive the ceiling (capture: none, or a level above max_capture), the process object carries only the tool name and cannot satisfy OCSF's at-least-one-of pid/uid/cpid object constraint; the record still ships, and the projection never invents an identifier to green a constraint.

4.4 Severity mapping

AEP OCSF severity_id
debug 1 Informational
info 1 Informational
notice 2 Low
warning 3 Medium
error 4 High
critical 5 Critical

Monotone, and lossy only at debug/info (OCSF has no debug severity); the original severity string always rides unmapped.aep.severity. The mapping is one-way: there is no OCSF-inbound direction.

4.5 Dispositions assert only what the wire asserts

A disposition is claimed exactly where an AEP Event itself asserts the outcome: tool.denied → 2 Blocked, attention.resolved with resolution: dismissed → 16 No Action, attention.timeout → 16 No Action (the request expired unanswered; AEP-0002 §5 makes it terminal). An attention.resolved with resolution: answered closes its finding with no disposition_id: the decision content lives in the answer payload and its interpretation is vendor-scoped (AEP-0008); a projection claiming Allowed or Blocked there would assert knowledge the wire does not carry.

4.6 Capture enforcement

The §3.3 rule applies unchanged: a max_capture setting (default metadata) down-levels Events before projection, and unmapped.data carries only what survives. Because attention.requested defaults to capture: redacted, at the default ceiling a finding is created from the envelope alone: prompt text, options, and form fields never reach a security backend the operator did not opt into.

5. Conformance

  1. Round-trip identity: for every golden fixture Event e, ce_inverse(ce_forward(e)) ≡ e (canonical-JSON comparison). This fixture class MUST stay green in CI for any release.
  2. Validity: ce_forward(e) MUST validate as CloudEvents 1.0 JSON format (attribute-name/type legality included).
  3. OTLP mapping: golden Events have pinned expected LogRecord projections (JSON encoding of the OTLP data model); severity and gen_ai.* hoisting are asserted exactly; max_capture down-leveling is asserted.
  4. Bridge mappings and fixtures MUST ship with v0.1 (implementations may be labelled beta; the mappings and fixtures may not). The bridge annexes are versioned with the specification; the external pins, namely OTel severity/name and the OCSF class subset (conformance/fixtures/ocsf/ocsf-classes.json: attribute-name sets and the activity/status/disposition/severity value sets at the pinned OCSF version), are re-checked per AEP release.
  5. Inbound preserve-path: hand-authored inbound CE events pin §2 rule 2 directly: a grammar-legal aep*-prefixed extension attribute is preserved, a plain legal extension name is preserved, and a name violating AEP-0001 §5.4's grammar is dropped while the rest maps (conformance/fixtures/ce-roundtrip/inbound-cases.json; both runners feed their inverse implementation directly: the golden-derived round-trip fixtures cannot exercise an attribute the golden corpus does not carry).
  6. OCSF projection: golden Events in the §4.2 families have pinned expected records (conformance/fixtures/ocsf/ocsf-expected.json); the severity table, the §4.5 disposition rules (including the answered-carries-no-disposition rule), and capture enforcement are asserted exactly, and every pinned record is checked against the pinned OCSF class subset: only class attributes, enum-legal ids, derived type_uid.

6. Security considerations

This section is informative; every rule it mentions is defined where cited.

  • Bridges are the egress boundary of the capture model. Everything exported lands in systems with their own retention, indexing, and access-control regimes that AEP's capture semantics no longer govern. For OTLP and OCSF the control point is normative: the exporter's max_capture (default metadata) down-levels before export, so backends never see what the operator did not opt into (§3.3, §4.6).

    A CloudEvents forwarder has no section of its own here because it needs none. It is an ordinary re-emitting hop, and the down-level rule of AEP-0001 §8.2 applies to it like any hop; a deployment configures a ceiling there with the same care as at the OTLP exporter.

  • Envelope metadata travels as broker-visible attributes. The B4 mapping puts session identifiers, agent identity, sequence positions, and causation links into CE extension attributes (§1): exactly the part of a message that broker ecosystems most freely log, index, route on, and hand to middleware. The same holds for the OTLP attribute projection (§3.2).

    Operators for whom activity structure is sensitive (who ran what, when, how much; visible even at capture: metadata, AEP-0001 §12) treat aep* attributes as data when configuring broker ACLs and telemetry pipelines, not as mere routing surface.

  • Severity crosses the bridge with emitter trust attached. The §3.4 mapping is monotone and adds no interpretation: downstream alerting fires on the severity the emitter asserted (AEP-0002 §8). The inverse direction buckets OTLP's 24 levels into six (order-preserving but lossy within a bucket), so round-tripped severity is a coarser claim than the original.

  • Payload members surface as top-level attributes. The gen_ai.* hoisting rule (§3.2) deliberately promotes those payload fields to LogRecord attributes so backends index them without mapping code. They are metadata-level by schema (AEP-0002 §5.2): token counts and model names, not free text. But they are payload-derived and producer-controlled, and inherit the untrusted-input posture of AEP-0001 §12 wherever attributes feed queries or dashboards.

  • OCSF records feed detection pipelines: dispositions are claims. A disposition in a security backend reads as an enforcement fact, which is why §4.5 claims one only where the AEP wire itself asserts the outcome and never interprets an answered decision. The projection carries the emitter's severity and outcome assertions with the emitter's trust attached, exactly like the OTLP direction; unmapped.aep preserves the evidence trail back to the source Event.

References

  • AEP-0001, AEP-0002.
  • CloudEvents 1.0 core + JSON format + Distributed Tracing extension.
  • OTLP logs/v1 protobuf (LogRecord).
  • OTel Logs Data Model severity ranges.
  • W3C Trace Context.
  • OTel GenAI semantic conventions (mirrored names).
  • OCSF 1.8.0 (Authentication 3002, Process Activity 1007, Detection Finding 2004, the security_control profile).
On this page