Skip to main content
Pre-release

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. Minor releases before 1.0 may change the API, and the changelog lists every change.

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, what each one changes, 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, generate and 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 its canonical sha256 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; before 1.0, a minor release may change it. Support for a new OCSF release ships as a minor release of the library. A model package requires the core minor it was generated with, so patch releases of the core install under it unchanged.

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 as actor or action_id are 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-compiler output, 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. The bundled schema data is compiled from the OCSF schema, © OCSF a Series of LF Projects, LLC, also under Apache-2.0; NOTICE carries its notice. ocsf-toolkit is an independent project with no affiliation to OCSF.

Metadata

Release files for ocsf-toolkit 0.1.0a3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ocsf-toolkit 0.1.0a3
File Size Uploaded Provenance Actions
ocsf_toolkit-0.1.0a3.tar.gz 1.0 MB With provenance Details for ocsf_toolkit-0.1.0a3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for ocsf-toolkit 0.1.0a3
File Interpreter ABI Platform Actions
ocsf_toolkit-0.1.0a3-py3-none-any.whl Python 3 none any Details for ocsf_toolkit-0.1.0a3-py3-none-any.whl

Total release size: 2.0 MB

Release files / ocsf_toolkit-0.1.0a3.tar.gz

Download URL ocsf_toolkit-0.1.0a3.tar.gz
Size 1.0 MB
Tags Source
SHA-256 checksum
How to use checksums
3fbf51753643abb9d9a4a5c5b05c504cb7c9d7ec6a2d929bf8f933cf1bdac8c5
BLAKE2b-256 checksum
How to use checksums
e1b8736579f5325fe10a6de043db771b44fd9bc0aaab03c01e921aa2a50e51dc
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 8, 2026.

Transparency log

Release files / ocsf_toolkit-0.1.0a3-py3-none-any.whl

Download URL ocsf_toolkit-0.1.0a3-py3-none-any.whl
Size 963.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d4cb1d053188eb1253df3a8b427e2160d785adcc6ec6c57aced7f54be7c5b0df
BLAKE2b-256 checksum
How to use checksums
729a0de0ac615868aecb6a2b79d7f59fb0111fefe4eb77c10d52992c4f39393f
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 8, 2026.

Transparency log

Security for ocsf-toolkit 0.1.0a3

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.

Select from 2 files

Attestation for ocsf_toolkit-0.1.0a3.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 8, 2026.

Transparency log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page