osyra_ome.types
Private pre-release / network boundary: The currently usable customer surface is offline verification of an existing signed artifact against an out-of-band trust anchor. Memory/network RPC APIs and host snippets on this page describe protocol and interface shape; the public Edge bridge, package publication, and release acceptance remain pending. Do not treat
api.osyra.ai:443examples as a released customer route.
Public-surface Pydantic v2 typed models for the Osyra OME SDK.
Cross-language parity (per ADR-045): every type here has a structurally identical TypeScript counterpart at ``@osyra/ome`` (AP00014). Field names use Python snake_case here and camelCase in TS; the JSON representation goes through Pydantic's alias generators if/when needed (deferred to v0.2).
Authoritative source for the wire types is ``osyra-ai/ome-proto:proto/ome/v1/ome_service.proto`` (the T14 single source of truth). These Pydantic models project the proto messages into ergonomic Python objects for the public SDK surface, while the gRPC stubs at ``osyra_ome._pb`` carry the raw protobuf classes used internally by the transport layer.
Design doc §3.4 (Phase 3 impl reference) — public type contract. ADR-044 stability — every class + field here is a v0.1.0 public API commitment; future schema evolutions are additive only.
v1.0.0 scope: Claim + SignedClaim + JMTProof + CompletenessWitness + BundleManifest + TombstoneReceipt + ClaimKind enum. Wire-level message classes are exposed lazily through ``osyra_ome._pb`` for callers that need to drop down to the raw protobuf form.
Classes
class BundleManifest
Bases: _OmeBaseModel
`.ome` ZIP bundle manifest (mirrors ome.v1 export bundle manifest).
The first chunk of an ``ExportBundle`` stream is this manifest; subsequent chunks are raw ZIP bytes. Signature uses dsTag "osyra-ome-bundle-v1".
v1.0.0 surface: just enough fields for ``client.verify.bundle_manifest(path)`` to validate the manifest signature against the workspace key.
Attributes
| Name | Type | Default |
| --- | --- | --- |
| claim_count | int | Field(default=0, ge=0) |
| created_ms | int | Field(ge=0) |
| encoded_cbor | bytes | Field(min_length=1) |
| sig | _Ed25519Sig | |
| signer_pub | _Ed25519PubOptional | b'' |
| spec_version | str | Field(min_length=1) |
| workspace_id | str | Field(min_length=1) |
class Claim
Bases: _OmeBaseModel
A signed-or-unsigned memory record (mirrors ome.v1.Claim proto).
Fields map 1:1 to the canonical .proto message (see proto comments for OAP-MEM v0.1 §4.1 wire-key mapping). Names use snake_case per Python convention; canonical CBOR encoding goes through the osyra-claims-common artifact (NOT this class directly) so the Python+TS public surface need not be the wire-format authority.
Hashing fields (``content_hash``, ``embedding_hash``) are 32-byte SHA-256 digests; ``id`` is 16-byte UUID v7. Length constraints are enforced by Pydantic at construction time — invalid bytes raise ``ValidationError`` (Pydantic v2's structured exception) BEFORE the object is exposed to the user. This is a hard fail-closed gate.
Note: the v1.0.0 SDK does NOT enforce the per-field W3C DID NFC normalization rules described in the proto comment — Python's default ``str`` is NFC on most platforms (CPython on Linux/macOS), which is correct, but Windows behaviour is platform-dependent. Customers running on Windows MUST call ``unicodedata.normalize("NFC", s)`` on issuer_did / subject_id strings before constructing Claims. Codified in ADR-044 v0.2 platform compatibility table.
Attributes
| Name | Type | Default |
| --- | --- | --- |
| body | bytes | Field(default=b'', max_length=16 * 1024 * 1024) |
| content_hash | _Sha256 | |
| embedding_hash | _Sha256 | |
| id | _UuidV7Bytes | |
| issuer_did | str | Field(min_length=1) |
| kind | ClaimKind | |
| parents | tuple[_UuidV7Bytes, ...] | Field(default=()) |
| subject_id | str | Field(min_length=1) |
| ts | int | Field(ge=0) |
| workspace_id | str | Field(min_length=1) |
class ClaimKind
Bases: IntEnum
OAP-MEM v0.1 ClaimKind discriminator (mirrors ome.v1.ClaimKind enum).
Wire encoding: int32 with the enum value. Cross-language parity: Python's ``IntEnum`` accepts both name and value at deserialization; Pydantic v2 serializes by value on JSON output. The TS sibling declares this as a `const enum` with the same numeric values, so over-the-wire compatibility is preserved.
Values match the proto exactly to avoid translation bugs: UNSPECIFIED = 0 # reserved sentinel ASSERTION = 1 DERIVATION = 2 TOMBSTONE = 3 CONSOLIDATION = 4 # OME extension above OAP-MEM v0.1
Higher values (5..15) are RESERVED for V1.5+ extensions per the proto convention.
class CompletenessWitness
Bases: _OmeBaseModel
Top-K signed completeness witness over a workspace JMT.
Signature uses dsTag "osyra-ome-cw-v1". The verify-side mini-kernel re-runs signature verification BEFORE root comparison (M2 from the /osyra-security review — avoids the root-equality oracle side-channel).
Note: the v1.0.0 surface exposes only the fields needed for ``client.verify.witness(bytes)``. Full witness structure including gap proofs lands in v0.2 via the ``WitnessTopResponse`` proto.
Attributes
| Name | Type | Default |
| --- | --- | --- |
| encoded_cbor | bytes | Field(min_length=1) |
| sig | _Ed25519Sig | |
| signer_pub | _Ed25519PubOptional | b'' |
| snapshot_at_unix_ms | int | Field(ge=0) |
| workspace_jmt_root | _Sha256 | |
class JMTProof
Bases: _OmeBaseModel
JMT inclusion or non-membership proof (mirrors ome.v1.JMTProof).
Layout matches OAP-MEM v0.1 §4.4 (``JMTProof`` CDDL). The verify-side mini-kernel implements the verification algorithm; this model is just the data container. ``depth`` MUST equal ``len(levels)``.
``absent_kind`` discriminates non-membership proofs: 0 = UNSPECIFIED (rejected by server with OSY-MEM-5152) 1 = ABSENT_EMPTY_SLOT (path terminates at a nil child) 2 = ABSENT_DIFFERENT_LEAF (path terminates at a leaf with different key)
``other_key`` + ``other_value`` are populated ONLY when ``absent_kind == 2``; empty otherwise.
Attributes
| Name | Type | Default |
| --- | --- | --- |
| absent_kind | int | Field(default=0, ge=0, le=2) |
| depth | int | Field(ge=0, le=64) |
| levels | tuple[tuple[bytes, ...], ...] | Field(default=()) |
| other_key | bytes | Field(default=b'', max_length=16) |
| other_value | bytes | Field(default=b'', max_length=32) |
class SignedClaim
Bases: _OmeBaseModel
A Claim with a DETACHED Ed25519 signature (mirrors ome.v1.SignedClaim).
**Wire-truth invariant (C1 / CRYPTO-2 re-model, ENG-2228).** The signature is a DETACHED bare-Ed25519 signature over the wire signing-PREIMAGE bytes (``encoded_cbor``) VERBATIM — the Form-B 2-tuple ``canonical_cbor([tstr("osyra-ome-claim-v1"), claimMap])`` (the claim 2-tuple wire shape per ADR-157 + ADR-008; canonical-CBOR strict-decode per ``AP00011-OME-FILE-FORMAT-V1.md`` §4.2). The ``claim`` field is a DECODED VIEW for ergonomics; it is **NOT** what the signature attests — verification runs over ``encoded_cbor`` and the signature is never re-derived by re-encoding ``claim``. To verify, pass ``signed.encoded_cbor`` + ``signed.sig`` + a caller-trusted public key to :func:`osyra_ome.verify_receipt`. Mirror of TS ``SignedClaim`` (``{ claim, signature, signerPub?, encodedCbor }``).
Attributes
| Name | Type | Default |
| --- | --- | --- |
| claim | Claim | |
| encoded_cbor | bytes | Field(default=b'') |
| sig | _Ed25519Sig | |
| sig_alg | str | Field(default='Ed25519', min_length=1) |
| signer_pub | _Ed25519PubOptional | b'' |
class TombstoneReasonCode
Bases: IntEnum
Reason a claim was tombstoned (mirrors ome.v1.TombstoneReasonCode).
ENG-583: enumerated reason codes keep free-text PII out of the audit-pipeline boundary. ``UNSPECIFIED`` is a reserved sentinel that the server rejects (OSY-MEM-5184) and the SDK refuses client-side before the wire — pass one of the concrete reasons instead. Values match the proto exactly; the TS sibling (AP00014) declares the same set (ADR-296 D2).
UNSPECIFIED = 0 # reserved sentinel — never a valid input GDPR_ART17_DSAR = 1 LEGAL_HOLD_EXPIRY = 2 CUSTOMER_OFFBOARDING = 3 OPERATOR_REDACTION = 4 REGULATORY_OTHER = 5
class TombstoneReceipt
Bases: _OmeBaseModel
Receipt returned by ``client.memory.tombstone(...)``.
Mirrors ome.v1.TombstoneResponse. Distinguishes the post-redaction root + era-binding + audit-correlation tuple from the original pre-tombstone state. The salt is NEVER on the wire (preimage- confirmation defense per ADR-016).
Attributes
| Name | Type | Default |
| --- | --- | --- |
| audit_correlation_id | str | Field(min_length=1) |
| era_index | int | Field(ge=0) |
| new_root | _Sha256 | |
| redacted_at_unix_ms | int | Field(ge=0) |
| tombstoned_at_sequence | int | Field(ge=0, default=0) |
class WrittenClaim
Bases: _OmeBaseModel
The outcome of ``client.memory.write_claim_signed`` (wire: SignAndInsert).
Carries the persisted ``claim_id`` AND the SERVER-MINTED :class:`SignedClaim` whose ``encoded_cbor`` is the signing preimage the server's Ed25519 signature attests. This is the v0.1-wire source of the attested preimage a body-bearing read path needs to bind a returned body to the SIGNATURE (ENG-2413): ``GetClaimBody`` returns only ``{body, content_hash}`` (the ``content_hash`` is unsigned/forgeable), so a caller who wants signature-bound verify-on-read MUST hold the ``SignedClaim`` from the write and pass it to ``get_claim_body(..., signed_claim=...)``.
Mirror of the AP00014 TS store pattern, where the adapter caches the ``SignedClaim`` it wrote and re-binds the read body to its ``encodedCbor``.
Attributes
| Name | Type | Default |
| --- | --- | --- |
| claim_id | str | Field(min_length=1) |
| signed_claim | SignedClaim | |