The authorization decision class nobody had written.
OCSF can describe who signed in and that a request happened. It has no class for whether this actor could act on this record, under which grant, and why not. B5 wrote one, and published it before writing any marketing about it.
The gap, stated precisely
This is checkable in ten minutes against the published schema, which is why it is worth stating rather than asserting.
OCSF’s Identity & Access Management category contains Account Change, Authentication, Authorize Session, Entity Management, User Access Management and Group Management. Authorize Session is session-level: authority is settled once, at the door, and the session lives for minutes. API Activity and Web Resources Access Activity are request-shaped: they record that a call happened and how it ended.
Neither shape fits a data-element decision. A record decision happens on every operation, and it is the unit an auditor examines. Expect the obvious objection — why is this not Authorize Session with extra attributes? The answer is cardinality and lifetime.
The asymmetry that makes the case. Every vendor schema can carry who acted and whether it was allowed. Not one can carry the authority under which it was allowed. That is not four integration problems. It is one missing schema.
The class
Eleven activity values; six attributes required, because an authorization event missing any of them cannot be audited.
The six
activity_id · actor · resource · is_permitted · reason_code · enforcement_point
Five, plus a dictionary
delegation_grant, enforcement_point, decision_evidence, authority_limit, and nine new dictionary attributes.
{
"uid": 1,
"name": "authorization_decision",
"caption": "Authorization Decision",
"description": "A decision about whether a specific actor may perform a specific action on a specific record, made at the point the action would execute. Distinct from Authorize Session (3003), which describes privileges assigned at session establishment, and from API Activity (6003), which describes a request rather than the authority under which it was permitted or refused.",
"extends": "base_event",
"profiles": [
"authority",
"host",
"cloud"
]
}The profile is the adoption vector
The most important design decision in the extension, and the least obvious.
An extension with one event class is a vendor’s private mapping. The authority profile is a mixin — five optional attributes that any vendor’s Authentication, API Activity, Datastore Activity or HTTP Activity event can carry without adopting B5’s class at all.
That distinction decides whether this gets used. An identity vendor will never adopt a competitor’s event class. It might well adopt five optional attributes that make its own events more useful.
{
"caption": "Authority",
"name": "authority",
"meta": "profile",
"description": "Adds authority context to any event class: the delegation in force, the enforcement point, the reason code, the declared purpose and whether the decision was simulated. Applying this profile to Authentication, API Activity, Datastore Activity or HTTP Activity lets a producer carry authority without adopting the Authorization Decision class.",
"attributes": {
"delegation": {
"requirement": "optional"
},
"enforcement_point": {
"requirement": "recommended"
},
"reason_code": {
"requirement": "recommended"
},
"purpose": {
"requirement": "optional"
},
"is_shadow": {
"requirement": "recommended"
}
}
}Four attributes nobody writes unless they have built this
Was the decision enforced?
A simulated decision must be distinguishable from a real one, or shadow traffic silently poisons every detection and metric downstream.
How fresh was the state?
A permit against three-second-old state is not the same permit as one against three-hour-old state. Identical outcome, different assurance.
Which aggregate was consulted?
Without it a threshold denial is indistinguishable from a scope denial — and the remedies are opposite.
What happens to work already moving?
fail or allow_completion, decided when the grant was written rather than during the incident.
Where it maps, and where it does not
Four destinations, honestly assessed. Every inferred field name is marked unconfirmed.
No authorization schema
Nearest fit is Audit Event, lossy twice: EventResult collapses a denial’s reason to pass or fail, and there is nowhere for the grant in force.
Mapped to the wrong model
The published OCSF-to-CIM add-on routes class 3003 into Authentication. For a data-element decision Change is the better target. CIM has no concept of delegated authority.
Emit OCSF, let their parser work
They publish an OCSF parser, so the fastest route is emitting OCSF rather than hand-mapping to UDM.
Needs no mapping at all
Custom sources must conform to OCSF and Parquet. That destination does not need a mapping — it needs the extension.
Every row in the mapping table that was inferred from a schema’s shape rather than read from its documentation is marked unconfirmed. A mapping table that looks authoritative and is half-guessed is worse than one that says which half.
It is not registered, and it says so in the data
OCSF assigns each extension a reserved identifier range so two organisations cannot ship colliding extensions. The identifier is therefore a reservation, not a choice. Until the range is issued, extension.json carries “uid”: “PENDING-OCSF-REGISTRATION” — a string where an integer is required, so it is invalid on purpose and cannot be mistaken for a registered schema by anyone, including us.
Read the schema before the marketing
The tree, the profile, the objects and the mapping notes are in the download. Nothing in it depends on B5 software.
Talk to a human.
Get architecture guidance, Test Mode access, integration review, or help choosing the right B5 identity and authorization pattern.