This release is a pre-release and may not be stable for production use.
ocsf-toolkit
Version-pinned OCSF semantics for Python. Each OCSF release is compiled
from upstream ocsf/ocsf-schema at a pinned commit into a schema you can query as data. On top of
that schema, the library builds events and derives everything the schema computes, checks events and
reports every deviation it finds, extracts observables, and diffs two versions. Typed
msgspec models are generated from the same schema.
Status: alpha. The API may change before 0.1.0.
Install
pip install --pre ocsf-toolkit # core: every OCSF release from 1.0.0 to 1.9.0, as data
pip install --pre ocsf-toolkit-v1-9-0 # optional: typed models for OCSF 1.9.0 (also -v1-8-0, -v1-7-0)
ocsf-toolkit generate builds a model package for any other version or extension set (see
Command line).
Python 3.12 or newer. The only runtime dependency is msgspec.
Build and emit one event
Pick an OCSF version and a class, give the fields you know, and build fills in what the schema
derives: class and category identity, type_uid, the label beside every _id enum, and
metadata.version.
>>> import json
>>> from ocsf_toolkit import build, load
>>> schema = load("1.9.0")
>>> event = build(
... (schema, "detection_finding"),
... activity_id=1,
... severity_id=4,
... time=1_700_000_000_000,
... metadata={"product": {"name": "Sensor", "vendor_name": "Acme"}},
... finding_info={"uid": "f-1", "title": "Suspicious login"},
... )
>>> print(json.dumps(event, indent=2, sort_keys=True))
{
"activity_id": 1,
"activity_name": "Create",
"category_name": "Findings",
"category_uid": 2,
"class_name": "Detection Finding",
"class_uid": 2004,
"finding_info": {
"title": "Suspicious login",
"uid": "f-1"
},
"metadata": {
"product": {
"name": "Sensor",
"vendor_name": "Acme"
},
"version": "1.9.0"
},
"severity": "High",
"severity_id": 4,
"time": 1700000000000,
"type_name": "Detection Finding: Create",
"type_uid": 200401
}
build raises ConformanceError if the event can't conform, and the error carries every problem
it found:
>>> from ocsf_toolkit import ConformanceError
>>> try:
... build((schema, "detection_finding"), severity_id=4, time=1)
... except ConformanceError as error:
... for finding in error.report.errors():
... print(finding.message)
activity_id is required and absent
finding_info is required and absent
metadata is required and absent
Check an event you received
parse returns the event with a report of findings, each with a kind, an indexed path and a
severity. You decide which findings are fatal.
>>> from ocsf_toolkit import parse
>>> received = dict(event, severity_id=9, status_id="x")
>>> _, report = parse(received)
>>> report.ok()
False
>>> for finding in report.errors():
... print(finding.kind.value, finding.path, finding.message)
enum_out_of_range ('severity_id',) severity_id is 9, not one of ['0', '1', '2', '3', '4', '5', '6', '99']
type_mismatch ('status_id',) status_id is str 'x'; expected integer_t
The version and profiles come from the event's own metadata. repair returns a normalized copy
and records every change it made. The same check runs from the shell over JSON Lines files:
ocsf-toolkit check --version 1.9.0 events.jsonl.
Typed models
With ocsf-toolkit-v1-9-0 installed, every class and object is a msgspec Struct, every enum is
referenceable by its caption, and build and parse accept and return the typed classes:
import msgspec
from ocsf_toolkit import build, parse
from ocsf_toolkit_v1_9_0 import DetectionFinding
from ocsf_toolkit_v1_9_0.classes.detection_finding import DetectionFindingActivityId
from ocsf_toolkit_v1_9_0.enums import SeverityId
from ocsf_toolkit_v1_9_0.objects import FindingInfo, Metadata, Product
finding = build(
DetectionFinding,
activity_id=DetectionFindingActivityId.CREATE,
severity_id=SeverityId.HIGH,
time=1_700_000_000_000,
metadata=Metadata(product=Product(name="Sensor", vendor_name="Acme")),
finding_info=FindingInfo(uid="f-1", title="Suspicious login"),
)
assert finding.type_uid == 200401
wire = msgspec.json.encode(finding) # the event as JSON bytes
same, report = parse(msgspec.json.decode(wire), as_=DetectionFinding)
assert same == finding and report.ok()
The models pass pyright in strict mode, and importing one class loads only that class's module.
More
- Schema as data: required attributes, enums and captions, siblings, profiles, class identity, all without building an event.
- Building and checking events:
build,parse,repair, policies and reports. - Observables: extracting and merging the observables an event carries.
- Schema diff: what changed between two OCSF versions, renames included.
- Typed models: the model packages, and generating your own (custom extensions and exact profile sets).
- Command line:
check,diff,generateand the schema pipeline.
How versions work
Every OCSF release is pinned by upstream commit in ocsf.lock and compiled with the
official ocsf-schema-compiler. CI recompiles each one and checks it byte for byte against the
lockfile. Core ships the schema of every release, so you can check, repair and diff events of any of
them and extract their observables. Typed models ship for the newest three releases, one package
each, so you install only the versions you produce.
The library's own version follows SemVer on its API. Support for a new OCSF release ships as a minor release of the library.
Why not an existing library?
We installed and ran each Python OCSF package we could find. These results are from 2026-11-02, against the versions named:
- pydantic-ocsf (3.0.0) is the closest relative and the one we learned the most from: multiple
OCSF versions side by side, sibling-label checks and computed
type_uid. It builds its models from the schema's source files, which leave profiles unresolved, so profile attributes such asactororaction_idare missing or untyped. Against the official compiler's output for OCSF 1.7.0, about a third of its integer enums differ; for example,device.type_id=2("Desktop") is rejected. - py-ocsf-models (0.10.0, Prowler) is a hand-written model set for three finding classes at OCSF 1.5.0. It silently drops attributes it doesn't model.
- ocsf-lib (0.10.4) is useful schema tooling (compile, diff, compatibility checks), but it has
no event models or validation. It can't read the official
ocsf-schema-compileroutput, and its own compiler disagrees with upstream on profile gating.
This library exists for four things those packages lack: OCSF knowledge as data you can query without building a model, a conformance report that lists every problem in an event, observables derived from the schema, and profiles treated as part of an event's identity.
License
Apache-2.0.
Metadata
Release files for ocsf-toolkit 0.1.0a2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ocsf_toolkit-0.1.0a2.tar.gz | 1.0 MB | With provenance | Details for ocsf_toolkit-0.1.0a2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ocsf_toolkit-0.1.0a2-py3-none-any.whl | Python 3 | none | any | Details for ocsf_toolkit-0.1.0a2-py3-none-any.whl |
Total release size: 2.0 MB
Release files / ocsf_toolkit-0.1.0a2.tar.gz
| Download URL | ocsf_toolkit-0.1.0a2.tar.gz |
|---|---|
| Size | 1.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3abeb6a6e2fed960037f29d3e5ee9ea8ab4628fa0fb67455882943598cf1976a
|
|
BLAKE2b-256 checksum How to use checksums |
8cff2b7b72878582307cfe02260a8293f7492b957403ca04a9215bd8ec8a9f14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logRelease files / ocsf_toolkit-0.1.0a2-py3-none-any.whl
| Download URL | ocsf_toolkit-0.1.0a2-py3-none-any.whl |
|---|---|
| Size | 955.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a41201a68acfab273826eb8dbb37b2fd57446b009faf27671f3c064a94137107
|
|
BLAKE2b-256 checksum How to use checksums |
a7d3c9f4821055c559e7693a35df068af6ba5591bcfdacde72bd25b7d32463fc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logSecurity for ocsf-toolkit 0.1.0a2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for ocsf_toolkit-0.1.0a2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.