Skip to content

[Bug] OCSF provenance has two homes, and the mapping's enrichment shape fails OCSF validation #260

Open

Description

@rocklambros

What is broken

The OCSF mapping and the Extending OCSF page put provenance in two different places, and the place the mapping requires can't be built as the mapping describes it.

Where

specification/v0.1.0/trace/ocsf-mapping.json (provenance_metadata); docs/spec/trace/extend_ocsf.md (the tool-call example and the Provenance implementation note)

What the specification says, and what happens instead

ocsf-mapping.json, provenance_metadata.description: "the OCSF event MUST carry provenance facts in 'enrichments' (an OCSF-recognized extensibility field). Each enrichment carries name='acs_provenance_*' and value={origin, source_id, ...}." It requires an acs_provenance_origin enrichment.

extend_ocsf.md says the opposite: "Provenance flows onto OCSF events under unmapped.acs.provenance." Its tool-call example does exactly that and carries no enrichments at all. events.md says nothing about provenance on OCSF events, so the two pages are all an implementer has.

The enrichment shape in the mapping also fails OCSF. In 1.9.0, enrichment.value is a string, and data (JSON) is required. I ran the tool-call example through https://schema.ocsf.io/api/v2/validate with an enrichment built the way the mapping describes it, {"name": "acs_provenance_origin", "value": {"origin": ..., "source_id": ...}}. It fails with two errors: enrichments[0].data is missing, and enrichments[0].value has the wrong type. The same event with "value": "user_input" and the provenance object in data passes. I added a device to both tries so the missing-device error from #235 didn't hide the result.

Impact on implementers

An exporter following the mapping writes events OCSF validators reject. An exporter following the docs page fails the mapping's MUST. Two exporters that each follow one source produce provenance a SIEM query can't find in the other's events. ACS-Trace requirement 3 (carry provenance forward onto the Trace event) has no single checkable form on the OCSF side.

Two smaller questions belong in the same fix. When a step carries more than one Provenance object, the mapping doesn't say whether that is one enrichment per object or one per field. It also doesn't say whether provenance_id goes along, which is what lets a reader join cited_provenance_ids on a decision back to its origin.

Proposed direction: pick one home and make the other page match. If it is enrichments, the mapping should say value is the origin string and data holds the Provenance object (provenance_id, origin, source_id), with one enrichment per object. If it is unmapped.acs.provenance, the MUST in the mapping changes to that path. Either way, the example on extend_ocsf.md should validate.

Related: #235 (OCSF required fields), #228 (decision replay facts, including cited_provenance_ids), #234 (OCSF examples on other pages).

Current Priority Scope

Feeds conformance evidence

Activity

  1. rocklambros commented on Oct 12, 2026

    @rocklambros
    CollaboratorAuthor

    More detail from reviewing the Trace PRs (#258, #261, and the #228 branch), so whoever picks this up starts from the same facts.

    The two homes, confirmed.

    • ocsf-mapping.json provenance_metadata says the event "MUST carry provenance facts in 'enrichments'" with name='acs_provenance_*' and value={origin, source_id, ...}.
    • extend_ocsf.md says "Provenance flows onto OCSF events under unmapped.acs.provenance", and its tool-call example does exactly that.
    • events.md says nothing about provenance on OCSF.

    The required form also loses the join key. The normative enrichment form carries origin and source_id but no provenance_id. The example's unmapped.acs.provenance entries do carry it. A decision cites provenance by id (cited_provenance_ids), so only the example form can be joined back to the provenance a decision cited.

    OCSF rejects the enrichment shape as written. Version 1.9.0 types enrichment.value as a string and requires data. I checked against the validator: the mapping's shape fails with two errors, and value set to the origin string with the Provenance object in data passes. Fields under unmapped are never validated, which cuts both ways. They always pass, but nothing checks their shape.

    What the #228 branch does nearby. Every other ACS fact on an OCSF event now rides under unmapped.acs. That covers the decision's replay fields (acs_fields), the join keys (join_fields, request_id and session_id), and request_id/session_id on every step event. Provenance is the one fact still pointed at enrichments.

    Proposed direction (for a Spec lead to decide):

    • Make the mapping match the example. That is the smaller change, and it is consistent with everything else.
    • Replace the provenance_metadata description with: "When Provenance is attached to the originating hook, the OCSF event MUST carry each Provenance object under unmapped.acs.provenance as {provenance_id, origin, source_id when present}. Trust classification is computed by the Guardian against local policy and is not a v0.1 field (see §7.1)."
    • Replace required_enrichments / optional_enrichments with required_fields: ["provenance_id", "origin"] and optional_fields: ["source_id"].
    • If you'd rather keep enrichments, the mapping instead needs one enrichment per Provenance object, value = the origin string and data = the object, and extend_ocsf.md changes to match.

    Decide it together with #262. That issue is the OTel side of the same join: an acs.provenance.ids array so acs.cited_provenance_ids resolves on a span. Both are small once the direction is picked. They touch ocsf-mapping.json, extend_ocsf.md and events.md, so they should land after the #228 PR to avoid conflicts.

  2. added
    scope:in-focusFeeds the ninety-day committed outcome. Maintainers only
    workstream:specOwning workstream. Maintainers only
    status:acceptedIn the backlog. Maintainers only
    and removed
    status:needs-triageNot yet triaged. Applied by the issue forms
    on Oct 12, 2026
  3. moved this from Needs triage to Accepted in ACS Project Trackeron Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:P2Maintainers onlyscope:in-focusFeeds the ninety-day committed outcome. Maintainers onlystatus:acceptedIn the backlog. Maintainers onlytype:bugSomething isn't workingworkstream:specOwning workstream. Maintainers only

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions