Messages and enums
Decoded-view proto message and enum reference. For signed envelopes the canonical wire artifact is the encoded_cbor (or equivalent) bytes; the proto fields are decoded views. Field numbers are the frozen wire contract.
Messages
ome.v1.AdminAttestation
AdminAttestation — single signer's signature on a destructive admin request.
SIGNED-FIELDS: signature (field 2) covers the canonical-CBOR Form B preimage
over the (dsTag, request-fields) tuple, where:
dsTag = "osyra-ome-admin-attestation-v1"
request-fields = the destructive-RPC's structured fields EXCLUDING the
attestations field itself (which would create a circular
self-signing dependency). The exact field set per RPC:
EraseEra → {era_index, reason, idempotency_key, audit_attestation_ref}
EmergencyEraseWorkspace → {reason, kms_cmk_arn, idempotency_key, audit_attestation_ref}
RefreshOrgRoot → {org_id, idempotency_key, audit_attestation_ref}
IssueGrant → {source_workspace_id, target_workspace_id, scope,
expires_at_unix_millis, idempotency_key,
audit_attestation_ref}
The expires_at_unix_millis canonicalization rule from the file header applies.
CBOR map keys are SHORT (matching the OAP-MEM/Form-B convention): "era", "ws", "src_ws", "tgt_ws", "scope", "expiry", "idem", "audit", "kms", "org", "reason". The canonical CBOR preimage is: canonical_cbor([ tstr("osyra-ome-admin-attestation-v1"), { /* short-key map of the destructive request's field set */ } ])
Anti-replay: signed_at (Unix-ms; ±5 min vs server clock) binds the
signature to a wall-clock moment so a stolen valid attestation can't be
replayed beyond the 5-min window. signer_did is the canonical W3C DID of
the admin (audit-trail attribution); the server cross-checks it against the
workspace's admin signer set before counting toward the 2-of-3 threshold.
Wire-freeze: this message's field numbers + tag values are part of the destructive-admin contract. Field additions go in the reserved range.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | signer_did | string | — | Canonical W3C DID of the signer. The server cross-checks this against the workspace's admin signer set (a per-workspace allow-list curated out-of-band by the customer org). Distinct signer_did values are required across the 2-of-3 multi-sig set — duplicate DIDs collapse to 1 signature and fail the threshold check. ENG-786: DID URI pattern + ≤512-byte cap (matches Claim.issuer_did). |
| 2 | signature | bytes | — | 64-byte Ed25519 signature over the canonical-CBOR preimage described in the message-level docstring above. The server re-encodes the destructive RPC's field set (using the short-key map per its RPC), prepends the dsTag, hashes, and verifies under signer_did's resolved pubkey (via IAM ResolveDid or a workspace-pinned signer-pub allowlist). Signature failure → OSY-MEM-5127. ENG-786: exact 64-byte length (Ed25519 raw signature). |
| 3 | signed_at_unix_ms | uint64 | — | When the signer produced the signature, in Unix milliseconds. The server enforces |now() - signed_at| ≤ 5 min freshness. Outside that window → OSY-MEM-5127 (ATTESTATION_EXPIRED). Distinct from the audit-event wall-clock (which is server-stamped at row insert; this is signer-stamped). The signed_at value IS included in the signed preimage (it's the only field the signer self-attests other than the request itself), so a tamperer cannot rewrite signed_at without invalidating the signature. ENG-786: must be set (server rejects 0 as missing). |
ome.v1.AmgateDecisionProjection
AmgateDecisionProjection - the ONLY fields surfaced to the edge gateway + dashboard. Sanitized: NO crypto inputs (DCap / SignedMemoryRoot / OsyidxJmtProof). Maps to ai.osyra.ome.amgate.AmGateDecision. HONEST-SCOPE (ADR-177 D5): a CHANNEL-ENFORCEMENT record of the memory I/O channel, NOT cognition-control / memory-correctness.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | decision_id | string | — | |
| 2 | decided_at_unix_ms | int64 | — | |
| 3 | op | string | — | "READ" or "WRITE". |
| 4 | key | string | — | |
| 5 | allowed | bool | — | true = admitted/committed, false = denied/rejected. |
| 6 | stage | string | — | Decision stage name (CAPABILITY..COMMIT). |
| 7 | code | string | — | OSY-AMGATE-85xx code. |
| 8 | reason | string | — | Human-readable rationale (sanitized; MUST NOT leak secrets). |
ome.v1.AppendOutcomeRequest
AppendOutcomeRequest carries the osyra-trace-outcome-v1 producer-supplied body. The parent trace is resolved UNDER RLS by trace_id; trace_hash is content-bound to it.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | outcome_id | bytes | — | 16-byte UUIDv7 outcome id (CDDL key 2). Append-only. Empty → server mints one. |
| 2 | trace_id | bytes | — | 16-byte trace_id of the osyra-trace-v1 this amends (CDDL key 4, the LINK key). |
| 3 | trace_hash | bytes | — | 32-byte Form-B hash of the amended trace (CDDL key 5). MUST equal the resolved parent's committed trace_hash (TRACE_OUTCOME_LINK_MISMATCH otherwise). |
| 4 | outcome_label | string | — | The deferred outcome label; non-empty; CAPTURED-not-adjudicated (CDDL key 6). |
| 5 | outcome_evidence | bytes | — | Opaque consumer-supplied evidence blob (CDDL key 7). MAY be empty. MUST-NOT carry raw PII (producer contract; signed + un-erasable in V1). |
| 6 | ts | uint64 | — | Attested outcome timestamp, Unix milliseconds, unsigned (CDDL key 8). |
| 7 | epoch | uint64 | — | Store-currency stamp, unsigned (CDDL key 9). |
ome.v1.AppendOutcomeResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | outcome_id | bytes | — | 16-byte UUIDv7 of the committed outcome amendment. |
ome.v1.AuditBundleManifestProto
Server-side echo of the .ome-audit bundle's signed manifest, surfaced in the first stream chunk so the client can validate workspace identity + content type + SHA anchors BEFORE consuming the raw ZIP payload chunks.
All fields are populated from AuditBundleExportResult (server side). The client SHOULD verify:
- content_type == "application/vnd.osyra.ome.audit-bundle.v1+zip"
- bundle_sha256 over the reassembled ZIP bytes matches this field
- manifest_sha256 over the extracted manifest.cbor matches this field
- signer_pub is the workspace's published Ed25519 pub key (out-of-band)
These are the same wire-freeze quantities the ome-audit-spec-freeze-gate
CI workflow byte-checks across platforms (spec §10).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bundle_sha256 | bytes | — | SHA-256 of the complete .ome-audit.zip bytes. 32 bytes raw. |
| 2 | manifest_sha256 | bytes | — | SHA-256 of the manifest.cbor ZIP entry bytes. 32 bytes raw. |
| 3 | signature_sha256 | bytes | — | SHA-256 of the 64-byte Ed25519 signature in bundler.sig. 32 bytes raw. |
| 4 | bundle_bytes | uint64 | — | Total size of the .ome-audit.zip bundle in bytes (echo for client sanity). |
| 5 | n_receipts | uint64 | — | Number of receipt envelopes embedded in the bundle. |
| 6 | signer_pub | bytes | — | Raw 32-byte Ed25519 public key the manifest was signed under (workspace VM-4 active signing key per ADR-040). |
| 7 | content_type | string | — | Bundle's content_type label (spec §3.1). Always "application/vnd.osyra.ome.audit-bundle.v1+zip" for v1.0. |
| 8 | edge_leaf_certs | bytes | repeated | ENG-803 (S7/P5, wire spec §6.2) — every distinct Edge Key Birth Certificate (COSE_Sign1-ES256, dsTag "osyra-edge-leaf-cert-v1") referenced by the bundle's edge-signed claims, deduplicated by EKBC serial. Lets an offline auditor re-verify the edge-leaf→platform-root chain forever from the bundle + a bounded root set, without Osyra-side state. Empty for bundles with no edge-signed claims. Additive; populated by the OME export path (S8). |
ome.v1.BatchInsertRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | signed_claim_cbors | bytes | repeated | Each entry is a canonical-CBOR SignedClaim (Form B). ENG-784 protovalidate: ≤256 entries per batch + ≤1 MiB per entry (matches PR #2 H8 spec). Server-side enforcement remains; the proto-layer bound is defense-in-depth and gives SDKs a uniform local check before the gRPC round-trip. |
| 2 | workspace_id | string | — | MUST match every claim's workspace_id (defense-in-depth; the per-claim workspace_id remains the source of truth and is checked individually). ENG-784 protovalidate: UUID string form. |
| 3 | org_id | string | — | ENG-811 / ADR-113 — OPTIONAL org-level audit-attestation fields. Populated ONLY for an org-level synthetic-workspace claim: when the edge derives workspace_id = OrgWorkspaceUUID(org_id) for an org-level token that carries org_id but no workspace_id (behind OSYMEM_ENABLE_ORG_LEVEL_SYNTHESIS). EMPTY for every normal workspace-scoped claim. No proto-level UUID constraint here — an empty value MUST be allowed — so validation is application-side: the edge rejects a non-UUID org_id BEFORE synthesis, and OME re-derives UUIDv5(org_id) == workspace_id (Check-1) before accepting. org_id: the principal's server-derived organization UUID (the UUIDv5 derivation input). |
| 4 | org_audit_authorized | string | — | org_audit_authorized: the IAM-issued org_audit_authorized claim (= the principal's org_id iff it holds the audit:emit_org permission; empty otherwise). OME checks org_audit_authorized == org_id (Check-2). NOTE: an edge-set field is an integrity/authz assertion*, NOT a cryptographic defense against a compromised edge — the signer-DID↔org binding (ADR-113 §81-87) remains the prod-enable flip-gate. |
| 5 | edge_leaf_certificate | bytes | optional | ENG-803 (S7/P5) — EKBC carriage. The pod's CURRENT Edge Key Birth Certificate (a COSE_Sign1-ES256 envelope, dsTag "osyra-edge-leaf-cert-v1", wire spec docs/architecture/AP00001-EDGE-KEY-BIRTH-CERTIFICATE-V1.md) vouching for the ephemeral leaf key that signed EVERY claim in this batch. Additive (proto3 optional); empty for pre-ENG-803 / non-edge direct callers. The edge enforces the ONE-LEAF-PER-BATCH invariant (it flushes the open batch before activating a new leaf), so all signed_claim_cbors share the single leaf this EKBC certifies. OME verifies the chain at ingest (S8, OMEErrorCodes 5340-5345); structural validation is server-side (the frozen 4-element COSE_Sign1 form), so no protovalidate bound here. |
ome.v1.BatchInsertResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | new_roots | bytes | repeated | Root after each successful insert (ordered to match input). Failed inserts do NOT produce a root entry; consult the failures array for those indices. RETRY CONTRACT (per /osyra-qa M6 PR #2 review): - On retry: claim_id already present with the SAME value_hash → server returns the unchanged root (idempotent no-op; the original value_hash's root, NOT a new one). - On retry: claim_id present with a DIFFERENT value_hash → server rejects that index with OSY-MEM-5153 (TREE_INCONSISTENT_ROOT) in the failures array, leaving the existing tombstoned/non-tombstoned state untouched. - Edge consumers (per design §5.3.2) SHOULD treat "new_roots[i] equals previous-attempt's new_roots[i]" as idempotent success, not a new insert. |
| 2 | n_inserted | uint32 | — | |
| 3 | n_failed | uint32 | — | |
| 4 | failures | FailureDetail | repeated | |
ome.v1.BundleManifest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | version | uint32 | — | SIGNED-FIELDS: bundler_sig (field 9) covers a COSE_Sign1 envelope wrapping the canonical-CBOR Form B preimage with dsTag "osyra-ome-bundle-v1" over fields 1-8: [tstr("osyra-ome-bundle-v1"), {version, content_type, root_hex, n_claims, n_tombstones, created_ms, issuer_pub_keys, epoch}] bundler_sig (field 9) and encoded_cbor (field 10) are EXCLUDED from the preimage (sig cannot self-sign; encoded_cbor IS the preimage echo). issuer_pub_keys MUST be lex-sorted before encoding to lock canonical form. |
| 2 | content_type | string | — | 2 (v2) |
| 3 | root_hex | bytes | — | "application/vnd.osyra.ome.bundle.v1+zip" |
| 4 | n_claims | uint64 | — | hex-encoded JMT root at export time |
| 5 | n_tombstones | uint64 | — | |
| 6 | created_ms | int64 | — | |
| 7 | issuer_pub_keys | bytes | repeated | |
| 8 | epoch | uint64 | — | dedup'd, lex-sorted |
| 9 | bundler_sig | bytes | — | monotonic per-workspace (G-ARCH-3 schema-v2) |
| 10 | encoded_cbor | bytes | — | COSE_Sign1 over Form B preimage with dsTag "osyra-ome-bundle-v1" Form B canonical-CBOR preimage echo (the bytes the bundler_sig was computed over, BEFORE the COSE_Sign1 wrapper). Verifier compares re-encoded fields to this and uses it as the verify input. Eliminates the cross-SDK reconstruction burden where every encoder must produce byte-identical CBOR to verify. |
ome.v1.CaptureTraceRequest
CaptureTraceRequest carries the osyra-trace-v1 producer-supplied body. The workspace is server-authoritative (GUC), NOT carried here — the body's ws is the WBW cross-bind, stamped server-side from the GUC identity so it cannot be forged.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | trace_id | bytes | — | 16-byte UUIDv7 trace id (CDDL key 2). Client-minted; append-only (a re-used id is rejected). Empty → server mints a UUIDv7. |
| 2 | prompt_hash | bytes | — | 32-byte commitment to the request prompt (CDDL key 4). Producer-computed. |
| 3 | model_id | string | — | Resolved model id; non-empty (CDDL key 5). |
| 4 | provider | string | — | Resolved provider; bound-not-validated (CDDL key 6). |
| 5 | params_digest | bytes | — | 32-byte boundary-computed sampling-params commitment (CDDL key 7). Producer-computed. |
| 6 | retrieved_memory | bytes | repeated | Ordered list of 32-byte OME claim content-hashes actually fed in (CDDL key 8; reference-by-hash, no claim bytes embedded). MAY be empty. |
| 7 | output_hash | bytes | — | 32-byte commitment to the generated output (CDDL key 9). Producer-computed. |
| 8 | tool_calls | bytes | repeated | Ordered list of 32-byte producer-opaque tool-call commitments (CDDL key 10). MAY be empty. |
| 9 | human_judgment | bytes | — | Opaque consumer-supplied judgment blob (CDDL key 11). MAY be empty. MUST-NOT carry raw PII (producer contract; signed + un-erasable in V1). |
| 10 | ts | uint64 | — | Attested capture timestamp, Unix milliseconds, unsigned (CDDL key 12). |
| 11 | epoch | uint64 | — | Store-currency stamp, unsigned (CDDL key 13). |
| 12 | broker_request_id | string | — | Model-broker request identity (CDDL key 14; CompleteChatResponse.id / WorkspaceContext.request_id). BOUND, not validated. Non-empty. |
| 13 | idempotency_key | string | — | §12.7 / MUST-fix-7 dedup token. Empty → non-idempotent. <=128 chars when present. |
ome.v1.CaptureTraceResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | trace_id | bytes | — | 16-byte UUIDv7 of the committed (or replayed) trace. |
| 2 | trace_hash | bytes | — | SHA-256(canonical_cbor(["osyra-trace-v1", body])) — the Form-B link identity an outcome amendment binds to (distinct from value_hash). |
| 3 | replayed | bool | — | true iff this was an idempotent replay of an already-committed trace (no 2nd leaf). |
ome.v1.CheckPolicyRequest
ENG-2569: CheckPolicy query input. Workspace is server-authoritative (NEVER carried
here). action is required; resource + context optional.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | action | string | — | The decision verb being pre-flighted (e.g. "memory.put" / "memory.get"). Mapped to the enforcer's memory:read/memory:write axis server-side. ≤256 bytes (DoS guard). |
| 2 | resource | string | — | Optional target key / ORN / handle the action would touch (the OPA resource.key). ≤512 bytes (DoS guard; mirrors ListClaims string-filter caps). |
| 3 | context | map<string, string> | — | Optional bounded, NON-PII decision context (key→value). The MCP layer MUST NOT put plaintext bodies here. Each value ≤512 bytes; map kept small. |
ome.v1.CheckPolicyResponse
ENG-2569: CheckPolicy decision verdict (ADR-291 D2/D3). The query mirrors what the GatedMemory* gates would decide, WITHOUT performing the action.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | decision | PolicyDecision | — | The would-be admission verdict. FAIL-CLOSED to IMPLICIT_DENY on any unreachable/indeterminate/no-bundle path (ADR-291 D3). |
| 2 | policy_version | string | — | The enforcer's SINGLE combined cascade content-address (OpaCascadeDecider.digest()), lowercase-hex SHA-256. Replayable pass-through pin (MCP-C-38) — NOT a per-layer array. Empty iff no decider/digest was resolvable (which itself forces decision=IMPLICIT_DENY). |
| 3 | decision_id | string | — | Server-minted decision correlation id (UUID) for the audit trail. Always present. |
| 4 | violations | string | repeated | The responsible cascade layer name for the verdict (allow-layer on ALLOW; deny-layer / fail-static reason on DENY/IMPLICIT_DENY). Diagnostic, not load-bearing. |
ome.v1.Claim
A single memory record. Wire layout matches the design doc; the canonical-CBOR Form B preimage uses OAP-MEM v0.1 §4.1 short field names — translation between the two layers happens in the Java/Go encoders, not in this proto.
OAP-MEM v0.1 §4.1 wire-key mapping. The encoded_cbor uses SHORT keys per the public spec; the proto uses LONG names for caller ergonomics. Encoders in osyra-claims-common translate at the wire boundary. Drift would silently break signatures; the §12.6 cross-language contract test enforces this.
Canonical mapping artifact (source of truth for cross-language encoders): Repository: github.com/osyra-ai/osyra-claims-common (per ADR-027) File: spec/CLAIM_FIELD_MAPPING.md Owner: ENG-715 (WBW Wave 1a; first consumer)
Proto field → OAP-MEM CBOR key ───────────────────────────────────────── id → "id" workspace_id → "ws" subject_id → "subj" parents → "parents" issuer_did → "issuer" content_hash → "content_hash" embedding_hash → "emb_hash" kind → "kind" ts → "ts" body → "body"
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | id | bytes | — | 16-byte UUIDv7 (RFC 9562); time-ordered, monotonic-within-process. ENG-784 protovalidate: exact 16-byte length (UUIDv7 raw bytes). |
| 2 | workspace_id | string | — | Workspace identifier (UUIDv7 from IAM); enforces tenancy via the OS-Workspace-ID header → ome.workspace_id Postgres GUC. ENG-784 protovalidate: UUID string format (any of v1/v4/v7 — checks structural form only). The server-side WBW gate further binds it. |
| 3 | subject_id | string | — | Subject identifier — the entity the claim is ABOUT. Typically a DID URI string (e.g., "did:web:agent.example.com"). Same canonical-form rules as issuer_did (W3C DID Core §3.2 NFC, case-sensitive, percent-preserved). OPTIONAL in practice — some claims (e.g. self-referential ASSERTION) omit subject_id and the value is the proto3 empty-string default. ENG-784 protovalidate: DID URI pattern + ≤512-byte cap; empty string (proto3 default) skips the pattern check via IGNORE_IF_ZERO_VALUE. The field is NOT proto3 optional-keyword-tagged because doing so would change wire encoding (adds a presence bit) and break the WIRE_JSON byte-equality contract. |
| 4 | parents | bytes | repeated | Parent claim IDs (DAG edges): - Empty for KindAssertion; - Non-empty for KindDerivation; - Exactly one entry for KindTombstone (the redacted claim's id). Encoding contract: the SERVICE performs server-side length-then-lex sort (RFC 8949 §4.2.2 / CTAP2) of parents BEFORE signing/inserting. Client- side order is irrelevant — cross-language SDK output is always canonical regardless of client. Rationale (per /osyra-qa M3 PR #2 review): the alternative (client-sorts-strict) would force every SDK to implement length-then-lex; server-side normalisation moves the burden to one place. |
| 5 | issuer_did | string | — | Issuer DID URI in canonical form per W3C DID Core 1.0 §3.2: - Case-sensitive (do NOT lowercase the method-specific identifier) - NFC-normalized UTF-8 (Unicode Normalization Form C) - Percent-encoding preserved as-is (do NOT decode/re-encode) Signature verification depends on byte-equality of this string in the canonical-CBOR preimage. Cross-language SDKs MUST normalize identically on both encode and decode paths — Python str default is NFC on most platforms; Go string is byte-sequence (no normalization); Java String is UTF-16 internally and NFC at IO boundaries. NFC mismatch produces silent signature failures across languages. Examples: "did:web:agent.example.com", "did:osyra:org-foo:agent-alpha". ENG-784 protovalidate: DID URI pattern per W3C DID Core §3.2 + ≤512 UTF-8 cap. |
| 6 | content_hash | bytes | — | SHA-256 of the claim body (32 bytes). Body itself is stored out-of-band (S3 / Postgres LOB) per design §3.4; this hash binds the body to the signed preimage transitively. ENG-784 protovalidate: exact 32-byte length (SHA-256 digest). |
| 7 | embedding_hash | bytes | — | SHA-256 of the embedding vector (32 bytes); all-zero 32 bytes is the canonical sentinel for "no embedding exists" (per design §1.6 / OAP-MEM §4.1). Encoding of the embedding bytes themselves is implementation- defined per OAP-MEM §9 Open Question 1 (deferred to v0.2). ENG-784 protovalidate: exact 32-byte length (SHA-256 digest or zero-sentinel). |
| 8 | kind | ClaimKind | — | ClaimKind discriminator. CONSOLIDATION (kind=4) is an OME extension above the OAP-MEM v0.1 baseline (ASSERTION/DERIVATION/TOMBSTONE). |
| 9 | ts | int64 | — | Unix milliseconds. Phase-2+: replaced by an RFC 3161 TSA-signed timestamp (OAP-MEM §9 Open Question 6; deferred). |
| 10 | body | bytes | — | Opaque CBOR-canonical payload. NOT included in the signed preimage — covered transitively via content_hash. Bound size: ≤16 MiB per service-level limit (FormBCanonicalCborEncoder.MAX_PAYLOAD_BYTES on the byte[] decode path). ENG-784 protovalidate: max 16 MiB (16 * 1024 * 1024 = 16777216 bytes). |
ome.v1.ClaimProjection
Sanitized projection of a single OAP-MEM Claim envelope. AC2-aligned:
the raw {@code body} bytes, {@code signature} bytes, and
{@code signer_pub} bytes are EXCLUDED structurally (no field number
to carry them). The Edge GraphQL OsymemClaim type maps 1:1 to this
message.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | 16-byte UUIDv7 claim id. |
| 2 | workspace_id | string | — | Workspace UUID — server-stamped from the GUC-bound identity. Echoed for client convenience; always equals the caller's workspace. |
| 3 | subject_id | string | — | Subject DID URI (entity the claim is ABOUT). Empty string when absent (proto3 default — distinguished server-side via repository NULL-on-DB column for index efficiency). |
| 4 | issuer_did | string | — | Issuer DID URI (signing agent). |
| 5 | content_hash | bytes | — | 32-byte SHA-256 of the canonical-CBOR body (content commitment). |
| 6 | embedding_hash | bytes | — | 32-byte SHA-256 of the embedding vector. Zero-32 sentinel for "no embedding" per OAP-MEM §4.1. |
| 7 | kind | ClaimKind | — | ClaimKind discriminator (1=ASSERTION, 2=DERIVATION, 3=TOMBSTONE, 4=CONSOLIDATION). |
| 8 | ts | int64 | — | Unix milliseconds (matches Claim.ts wire field). |
| 9 | parents | bytes | repeated | Parent claim IDs (DAG edges; length-then-lex sorted per RFC 8949). Empty for ASSERTION; non-empty for DERIVATION; exactly one for TOMBSTONE (the redacted claim's id). |
| 10 | tombstoned | bool | — | True when this claim has been tombstoned (a {@code tombstone} row exists for the (workspace_id, claim_id) tuple). The valueHash is then the redacted digest, not the original body's hash. |
| 11 | created_at_unix_ms | int64 | — | Creation time as Unix milliseconds (from claim.created_at column). |
ome.v1.CompletenessWitness
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | root | bytes | — | SIGNED-FIELDS: sig (field 11) covers a canonical-CBOR Form B preimage with dsTag "osyra-ome-cw-v1" over fields 1-10: [tstr("osyra-ome-cw-v1"), {root, epoch, iss, k, sort_key, boundaries, top_values, gap_digest, num_gap_items, gap_proofs}] sig (field 11) is EXCLUDED from the preimage (cannot self-sign). gap_proofs MUST be encoded in length-then-lex order of (claim_id) to match the Go reference impl in osyra-labs/prototypes/osymem/ (archived). |
| 2 | epoch | uint64 | — | 32 bytes |
| 3 | iss | string | — | ADR-008 replay-protection epoch (per-workspace monotonic) |
| 4 | k | uint64 | — | issuer DID — short-form OAP-MEM key for "issuer" |
| 5 | sort_key | string | — | |
| 6 | boundaries | bytes | repeated | "uuid-v7" |
| 7 | top_values | bytes | repeated | K claim IDs, sorted ascending |
| 8 | gap_digest | bytes | — | K value hashes SHA-256 over the concatenation of GapAttestation entries, where each entry's CBOR encoding is canonical Form B and entries are concatenated in length-then-lex order of (claim_id) per RFC 8949 §4.2.2 BEFORE the SHA-256 step. This ordering is part of the signed contract. |
| 9 | num_gap_items | uint64 | — | |
| 10 | gap_proofs | GapAttestation | repeated | |
| 11 | sig | bytes | — | |
ome.v1.CryptoEraseWorkspaceRequest
ENG-1951 — gated crypto-erasure. The target workspace comes from the edge OS-Workspace-ID header (not a field), like EraseEra. For a dry-run, the sign-off fields are unset. For a live run, jws_approval_bundle + nonce + the approval window are required (verified against (workspace, inventory_sha256, nonce)).
WIRE-PARITY (ENG-2354): copied byte-equivalent from the AP00011 Java mirror — field numbers / names / types match exactly. Intentionally NOT protovalidate- annotated (unlike the sibling EmergencyEraseWorkspaceRequest): the Java mirror carries no annotations here, and the field validity is conditional on the run mode (dry-run vs jws-live vs brokered), which the OME service enforces at runtime; static protovalidate annotation is a separate ENG-784 follow-on.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | dry_run | bool | — | |
| 2 | jws_approval_bundle | bytes | — | |
| 3 | nonce | string | — | 2-of-3 JWS bundle (live runs) |
| 4 | approval_issued_at | google.protobuf.Timestamp | — | UUID, single-use (live runs) |
| 5 | approval_expires_at | google.protobuf.Timestamp | — | |
| 6 | idempotency_key | string | — | |
| 7 | legal_basis | string | — | Documented lawful basis: dpa_customer_instructed | offboarding_termination | art17_substantiated | regulatory_order. An exploit finding ALONE is rejected. |
| 8 | operator_user_id | string | — | |
| 9 | reason | string | — | UUID |
| 10 | brokered_approval_grant | bytes | — | ENG-2042 (EPIC ENG-2034) — AP00009-brokered WORKSPACE_CRYPTO_ERASE grant: an ALTERNATIVE live-run authorization to the 2-of-3 jws_approval_bundle. Carries the AP00009 admin.v1.ApprovalRecord.encoded_cbor (the COSE_Sign1/EdDSA WIRE TRUTH over the osyra-admin-approval-v1 Form B preimage); OME decodes + re-derives + verifies every binding against a PRE-PINNED platform admin-approval key (never the in-message signer_pub trusted blindly). Carried as raw bytes (not a typed admin.v1 message) to keep this proto decoupled from the AP00009 proto — the bytes are decoded inside the OME service. EXACTLY ONE of {jws_approval_bundle, brokered_approval_grant} may be set on a live run; both set is rejected (OSY-MEM-5395). For a brokered run, nonce + the approval window are NOT used (the grant carries its own time_window_s duration). |
| 11 | brokered_signer_pub | bytes | — | Optional in-message signer_pub (raw 32-byte Ed25519); if present it MUST equal the pinned platform key (additional tamper signal). The verify key is ALWAYS the pinned key, never this. |
ome.v1.CryptoEraseWorkspaceResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | evidence_id | string | — | |
| 2 | correlation_id | string | — | |
| 3 | inventory_sha256 | string | — | |
| 4 | claim_count | uint32 | — | |
| 5 | era_boundary_from | uint32 | — | |
| 6 | era_boundary_to | uint32 | — | |
| 7 | executed | bool | — | |
| 8 | status | string | — | false for dry-run/aborted |
| 9 | eras_revoked | uint32 | — | DRY_RUN_COMPLETE | COMPLETED | ... |
ome.v1.DerivationChainNode
A single claim in the derivation chain. Field semantics: step — 0-indexed BFS position (0 = root) claim_id — 16-byte UUIDv7 of the OME Claim row kind — ClaimKind enum (typically CLAIM_KIND_DERIVATION = 2) input_hash — 32-byte SHA-256 of the model input model_id — UTF-8 model identifier (e.g. "gpt-4o-mini") output_hash — 32-byte SHA-256 of the model output (matches content_hash) signer_did — RAW issuer DID URI (Edge hashes on public mode) ts_unix_ms — unix-ms timestamp encoded_cbor — canonical-CBOR Form B preimage (ADR-008 dsTag) signature — 64-byte Ed25519 signature over encoded_cbor tombstoned — TRUE if this claim is tombstoned (witness present, body redacted) tombstone_witness — present iff tombstoned=true; carries reason_code + actor_did_hash
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | step | int32 | — | |
| 2 | claim_id | bytes | — | |
| 3 | kind | ClaimKind | — | 16 bytes UUIDv7 |
| 4 | input_hash | bytes | — | |
| 5 | model_id | string | — | 32 bytes SHA-256 |
| 6 | output_hash | bytes | — | |
| 7 | signer_did | string | — | 32 bytes SHA-256 |
| 8 | ts_unix_ms | int64 | — | RAW; Edge hashes on public mode |
| 9 | encoded_cbor | bytes | — | |
| 10 | signature | bytes | — | canonical-CBOR preimage |
| 11 | tombstoned | bool | — | 64 bytes Ed25519 |
| 12 | tombstone_witness | TombstoneWitness | — | |
ome.v1.DispatchKindRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | Canonical-CBOR Form B signed claim (dsTag: "osyra-ome-claim-v1"). Field renamed from encoded_claim → encoded_cbor for cross-SDK naming consistency per /osyra-security PR #2 H1 review. ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB. |
| 2 | mode | DispatchMode | — | Mode: STRICT (reject unknown), PERMISSIVE (wrap in opaque.v1), POLICY (callback). ENG-784 protovalidate: reject UNSPECIFIED at proto layer (server-side rejects with OSY-MEM-5453; proto-layer enforcement spares the gRPC round-trip). |
ome.v1.DispatchKindResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | resolved_kind_uri | string | — | Resolved kind URI, e.g., "osyra.claim.assertion.v1". |
| 2 | is_known | bool | — | |
| 3 | handler_result | string | — | Opaque to the caller; semantics are kind-specific. |
ome.v1.EmergencyEraseWorkspaceRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | reason | string | — | ENG-784 protovalidate: ≤2048-byte cap (defense against giant reason strings sent to flood audit logs); server further hashes the reason at audit-emit time so the cleartext never lands in SIEM. |
| 2 | kms_cmk_arn | string | — | Customer KMS CMK ARN. Customer MUST have already revoked the Decrypt grant out-of-band (via the customer's KMS console) before calling this RPC. SECURITY CONTRACT (per /osyra-security M6 PR #2 review): the server MUST call kms.GetKeyPolicy(kms_cmk_arn) and verify the service's IAM role lacks Decrypt permissions BEFORE proceeding. If the grant is still active, the server returns OSY-MEM-5353 (KMS_DECRYPT_FAILED) and refuses to retire eras. Otherwise "cryptographic erasure" loses its meaning — the era_secret remains decryptable via the active grant and a future code path could recover the data. ENG-784 protovalidate: AWS KMS ARN pattern + ≤2048 char cap (per AWS docs). Example: arn:aws:kms:us-east-1:123456789012:key/abcd-ef01-2345-6789-abcdef012345 |
| 3 | idempotency_key | string | — | ENG-786 [FU-567 M5] destructive-admin pattern (see V1 Admin Messages header). EmergencyEraseWorkspace is the HIGHEST-criticality destructive path — it cryptographically erases EVERY era on the workspace. The multi-sig is paired with the docstring's KMS-grant-revocation contract: both the (a) out-of-band Decrypt-grant revocation in KMS AND (b) the 2-of-3 multi-sig on the gRPC payload must hold before the erase proceeds. |
| 4 | audit_attestation_ref | string | — | |
| 5 | attestations | AdminAttestation | repeated | |
ome.v1.EmergencyEraseWorkspaceResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | erased | bool | — | |
| 2 | confirmed_at | google.protobuf.Timestamp | — | |
| 3 | eras_erased | uint32 | — | |
| 4 | idempotency_replayed | bool | — | ENG-786 [FU-567 M5]: TRUE on idempotent-replay. The (erased, confirmed_at, eras_erased) tuple is the original first-call response, replayed byte-identically. |
ome.v1.EmitInferenceAttestationRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | capability | GatedCapabilityGrant | repeated | |
| 2 | context_keys | string | repeated | capability over the disclosed context keys |
| 3 | prompt | bytes | — | the attested-claim-ref keys forming the declared context |
| 4 | output | bytes | — | |
| 5 | agent_did | string | — | |
| 6 | gateway_did | string | — | OIR subj |
| 7 | model_id | string | — | OIR signer |
| 8 | params_digest | bytes | — | OIR model_id (countersigning model) |
| 9 | cap_spec_digest | bytes | — | 32-byte inference-params digest |
| 10 | nonce | bytes | — | 32-byte capability-spec digest |
| 11 | id | bytes | — | receipt nonce (non-empty) |
| 12 | ts | int64 | — | 16-byte UUIDv7 receipt id |
ome.v1.EmitInferenceAttestationResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | oir_receipt | bytes | — | |
| 2 | context_count | int64 | — | the on-wire OIR COSE_Sign1 receipt |
| 3 | decision | AmgateDecisionProjection | — | the declared-context cardinality (post-dedup) |
ome.v1.EraseEraRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | era_index | uint32 | — | ENG-784 protovalidate: era_index must be ≥ 0 (proto3 default; uint32 is unsigned so this is structural — no explicit constraint needed; but the server-side era_index < 0 check is on the cast-to-int boundary). |
| 2 | reason | string | — | Audit reason, e.g., "gdpr_art_17", "customer_offboarding". ENG-784 protovalidate: ≤2048-byte cap (mirrors EmergencyEraseWorkspace.reason). |
| 3 | idempotency_key | string | — | ENG-786 [FU-567 M5] destructive-admin pattern (see V1 Admin Messages header). EraseEra retires the era's encryption key — cryptographic-erasure semantic. De-duplication on (workspace_id, idempotency_key) within 24h prevents accidental double-erase on retry; multi-sig prevents a single compromised operator from triggering an erasure unilaterally. |
| 4 | audit_attestation_ref | string | — | |
| 5 | attestations | AdminAttestation | repeated | |
ome.v1.EraseEraResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | erased | bool | — | |
| 2 | confirmed_at | google.protobuf.Timestamp | — | |
| 3 | idempotency_replayed | bool | — | ENG-786 [FU-567 M5]: TRUE on idempotent-replay. The (erased, confirmed_at) pair is the original first-call response, replayed byte-identically. |
ome.v1.ExportArchiveRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | vendor | string | — | The archive-header provenance the exporter stamps (the SOURCE vendor/model the memory is exported AS). The workspace identity + signing key are server-authoritative (OS-Workspace-ID header → workspace KMS key); callers do NOT supply them. |
| 2 | model_family | string | — | |
| 3 | retention_policy_did | string | — | The retention policy DID stamped into the archive header (governance binding). |
ome.v1.ExportArchiveResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | The signed OMP archive — Form B canonical-CBOR, dsTag osyra-omp-archive-v1. THE signing surface: verify the Ed25519 archive signature over THESE bytes. |
| 2 | archive_id | bytes | — | Decoded views (caller convenience; NOT signed). |
| 3 | item_count | uint64 | — | 32-byte SHA-256 archive id |
ome.v1.ExportAuditBundleChunk
First chunk of a streaming audit-bundle export.
Three legs (mutually exclusive per oneof semantics):
manifest=1 — sent FIRST when transport=inline; followed by data chunks
data=2 — raw .ome-audit.zip bytes, chunked by chunk_bytes (inline only)
presigned_url=3— ENG-1551 Phase B.3 / ADR-057: server uploaded the bundle to S3
and returns a TTL-bounded GET URL. The ENTIRE response is a
SINGLE chunk carrying this message — no manifest or data legs
follow. The bundle is downloadable from the URL until the TTL
expires (typically 300 s); the embedded url_sha256 field is
the audit-trail anchor (spec §11.2: log records URL emission
HASH, never the raw URL).
Transport selection is server-decided via audit.bundle.transport config
(values: inline | s3 | local_filesystem). Clients MUST handle all 3 payload
cases — switch-default = treat unknown as INTERNAL gRPC error and abort the
stream (defense against silent-payload drift).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | manifest | AuditBundleManifestProto | — | |
| 2 | data | bytes | — | |
| 3 | presigned_url | PublishedBundleProto | — | |
ome.v1.ExportAuditBundleRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | since_unix_ms | int64 | optional | Lower bound (inclusive) on emitted_at_unix_ms. Unset → no lower bound. |
| 2 | until_unix_ms | int64 | optional | Upper bound (exclusive) on emitted_at_unix_ms. Unset → no upper bound. MUST be >= since_unix_ms when both set, else OSY-MEM-5271. |
| 3 | purpose_did | string | optional | Filter by purpose DID. ≤512 bytes DoS guard (mirrors ListReceipts). ENG-784 protovalidate: ≤512-byte cap (DoS guard). |
| 4 | retriever_did | string | optional | Filter by retriever DID. ≤512 bytes DoS guard. ENG-784 protovalidate: ≤512-byte cap (DoS guard). |
| 5 | quarantine_class | uint32 | optional | 0=CLEAN, 1=SHADOW, 2=BLOCK (matches QuarantineClass wireValue()). ENG-784 protovalidate: enum-bound 0..3 (informational; server-side switch is authoritative because the proto-uint32 is the wire-level discriminator). |
| 6 | verdict | uint32 | optional | 0=PASS, 1=WARN, 2=QUARANTINE, 3=FAIL (matches Verdict.ordinal()). |
| 7 | chunk_bytes | uint32 | optional | Optional caller-supplied chunk size in bytes. MUST be in [1024, 16777216] (1 KiB to 16 MiB) when set. Field unset → server uses 1 MiB default. Out-of-range → server rejects with OSY-MEM-5271 (INVALID_ARGUMENT). ENG-784 protovalidate: bound only when explicitly set (the optional keyword makes protovalidate auto-skip the zero/unset path). |
| 8 | workspace_did | string | optional | workspace_did is OPTIONAL on the wire — when unset, server constructs the canonical form did:osyra:ws:{workspace_id} from the MDC-bound workspace UUID. Caller MAY override (e.g., for tenant-supplied alternate DID forms not yet canonicalised in the placement-service registry). ≤512 bytes. ENG-784 protovalidate: ≤512-byte cap (DoS guard). |
| 9 | include_bar_trajectory | bool | — | ENG-1689 FOLD-2 — when true, the exported .ome-audit bundle is enriched with the AP00012 osyrastream BAR drift trajectory covering each acting agent's receipt-timestamp window (.ome-audit v1.0.2; ADR-085 D1). The workspace MUST have osyrastream enabled (workspace_features. osyrastream_enabled); otherwise the server returns OSY-MEM-5440 (OME_AUDIT_BAR_NOT_AVAILABLE). Default false preserves v1.0.1 byte-identity for non-AP00012 workspaces (AC-7). Additive field — pre-FOLD-2 callers and v1.0.1 readers are unaffected. |
ome.v1.ExportBundleChunk
First chunk of a streaming export is the BundleManifest (oneof.manifest); subsequent chunks are raw ZIP bytes (oneof.data).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | manifest | BundleManifest | — | |
| 2 | data | bytes | — | |
ome.v1.ExportBundleRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tombstone_salts | map<string, bytes> | — | Optional caller-supplied tombstone-salt map (claim_id hex → 16-byte salt). Used by audit consumers who want to verify a specific historical bundle against known salts. The salts feed into the BundleManifest's signed preimage (dsTag "osyra-ome-bundle-v1") so an offline verifier treats them as cryptographically authoritative. SECURITY CONTRACT (ENG-782 / ADR-036): same per-mode semantics as WitnessTopRequest.tombstone_salts — UNSPECIFIED / ENFORCE → map MUST be empty (5212 on non-empty); server derives all salts from era_secret. AUDIT → map MAY be populated; each entry VERIFIED against era_secret before bundle stamping (5213 on mismatch, 5351 on era_secret unavailable). Edge Gateway interceptor MUST require the audit:read OPA scope. |
| 2 | chunk_bytes | uint32 | optional | Optional caller-supplied chunk size in bytes. MUST be in [1024, 16777216] (1 KiB to 16 MiB) when set. Field unset (proto3 default — distinguished via optional) → server uses 4 MiB default. chunk_bytes < 1024 OR > 16777216 → server rejects with OSY-MEM-5101 (INVALID_ARGUMENT). The optional keyword is essential so SDKs can distinguish "unset (use default)" from "explicitly out-of-range (server-must-reject)". ENG-784 protovalidate: bound enforced ONLY when set (the optional keyword makes protovalidate auto-skip the zero/unset path). |
| 3 | audit_mode | AuditMode | — | ENG-782 / ADR-036 — Audit-mode discriminator for tombstone_salts (above). Default (UNSPECIFIED) is treated as ENFORCE for wire-compat with pre-ENG-782 callers; standard callers never populated tombstone_salts in practice, so default-deny is safe. |
ome.v1.ExportForSubjectChunk
First chunk of a streaming subject-bundle export is the SubjectBundleManifestProto (oneof.manifest); subsequent chunks are raw .ome-subject.zip bytes (oneof.data).
Future versions MAY ADD a presigned_url leg to the oneof for large-bundle S3 transport per the ADR-057 precedent. v1.0 is gRPC-stream-only.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | manifest | SubjectBundleManifestProto | — | |
| 2 | data | bytes | — | |
ome.v1.ExportForSubjectRequest
Subject-bundle export request. The Edge gateway enforces EdgeIdentityKey
(mTLS service identity) + OPA scope before the call reaches the OME service.
Workspace identity is server-authoritative via workspaceIdFromMdc() +
ome.workspace_id GUC binding.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | subject_did | string | — | The data subject's DID URI to filter on. REQUIRED; non-empty; ≤ 512 UTF-8 bytes (DoS guard matching .ome-audit purpose_did cap). Canonicalised per W3C DID Core §3.2 (NFC UTF-8; percent-encoding preserved; case-sensitive method-specific identifier). The Manifest's subject_did_filter (field 6) carries this verbatim. The bundle filename uses ONLY a SHA-256 hash of this DID (spec §7.1; raw DID NEVER on the wire's transport-layer surfaces). ENG-784 protovalidate: DID URI pattern + 1B ≤ subject_did ≤ 512 bytes (REQUIRED). |
| 2 | workspace_did | string | optional | OPTIONAL workspace DID override — when unset, server constructs the canonical form did:osyra:ws:{workspace_id} from the MDC-bound workspace UUID. ≤ 512 UTF-8 bytes. ENG-784 protovalidate: ≤512-byte cap (DoS guard). |
| 3 | chunk_bytes | uint32 | optional | Optional caller-supplied chunk size in bytes. MUST be in [1024, 16777216] (1 KiB to 16 MiB) when set. Unset → server uses 1 MiB default. Out-of-range → OSY-MEM-5281. ENG-784 protovalidate: bound only when explicitly set. |
| 4 | max_transitive_parents | uint32 | optional | Optional cap on transitive-parent BFS — clamped server-side to the hard ceiling MAX_TRANSITIVE_PARENTS=10_000 (spec §8). Unset → server uses 10_000 default. Callers MAY set a lower value to bound output size for partial-lineage inspection (auditor tooling). ENG-784 protovalidate: bound only when explicitly set; 1..10000. |
ome.v1.ExportTraceBundleRequest
ExportTraceBundleRequest — the server-workspace-scoped filter (NO float fields). All set fields combine with AND. An empty filter exports the whole workspace (capped).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | since_unix_ms | uint64 | — | Lower bound (inclusive) on trace ts (Unix ms). 0 → no lower bound. |
| 2 | until_unix_ms | uint64 | — | Upper bound (exclusive) on trace ts (Unix ms). 0 → no upper bound. MUST be >= since_unix_ms when both set, else TRACE_SCHEMA (OSY-TRACE-7506) in V1. |
| 3 | model_id | string | — | Filter by resolved model id. Empty → no model filter. <=256 bytes. |
| 4 | broker_request_id | string | — | Filter by model-broker request id. Empty → no broker filter. <=512 bytes. |
| 5 | max_traces | uint32 | — | Optional caller-supplied result cap (max traces). 0 → server default. Server enforces a hard ceiling; over-cap → TRACE_SCHEMA (OSY-TRACE-7506) in V1. |
ome.v1.ExportTraceBundleResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bundle | bytes | — | The complete deterministic .ome trace-bundle bytes (application/vnd.osyra.ome.trace-bundle.v1+zip) — signed traces + outcomes + referenced claims + per-leaf JMT inclusion proofs + a workspace-signed root attestation, all at one consistent (root, sequence_no) snapshot. Verifiable OFFLINE by the shipped TraceBundleVerifier (no OME, no DB). |
| 2 | trace_count | uint32 | — | The number of trace leaves carried (>= 1; a degenerate trace-less bundle is never emitted — the verifier rejects it as BUNDLE_SHAPE). |
| 3 | attested_root | bytes | — | The attested workspace JMT root the bundle pins (32 bytes) + its sequence_no — the Stage-4 single-snapshot witness every carried proof recomputes to. |
| 4 | sequence_no | uint64 | — | |
ome.v1.FailureDetail
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | index | uint32 | — | |
| 2 | error_code | string | — | index into BatchInsertRequest.signed_claim_cbors |
| 3 | reason | string | — | OSY-MEM-NNNN |
ome.v1.GapAttestation
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | |
| 2 | salt | bytes | — | |
| 3 | proof | JMTProof | — | 16 bytes (tombstoned) |
ome.v1.GatedCapabilityGrant
One delegated-capability grant: the agent may perform {action} on {key} (the §3 L1 cap leg). In V1 the capability is the request-asserted agent capability; the workspace policy (S4 WASM) + attestation
- the server-authoritative workspace RLS are the binding enforcement (an IAM-signed capability token is a follow-up hardening, flagged to /osyra-security).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | action | string | — | |
| 2 | key | string | — | "read" | "write" |
ome.v1.GatedMemoryReadRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | key | string | — | |
| 2 | capability | GatedCapabilityGrant | repeated | the ATTESTED_CLAIM_REF memory key to read |
| 3 | request_supplied_key | bytes | optional | the agent's delegated capability (L1) Confused-deputy probe — MUST be absent. If set, the read DENIES (AMGATE_ANCHOR_REQUEST_SUPPLIED, 8507): the verification key/epoch resolve SOLELY from the workspace binding. |
| 4 | request_supplied_epoch | int64 | optional | |
| 5 | source_kind | string | optional | Source kind — default ATTESTED_CLAIM_REF; a non-attested kind (RAW_PATH/INLINE_BLOB/URL) DENIES at source-admissibility (8506, §3.2b). |
ome.v1.GatedMemoryReadResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | admitted | bool | — | |
| 2 | value | bytes | — | |
| 3 | decision | AmgateDecisionProjection | — | present iff admitted |
ome.v1.GatedMemoryWriteRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | key | string | — | |
| 2 | value | bytes | — | |
| 3 | capability | GatedCapabilityGrant | repeated | |
| 4 | write_capability_did | string | — | ENG-3221 — OMP provenance captured at write time and folded into the signed MemoryClaimBody. Empty fields preserve the pre-ENG-3221 raw-value write path byte-for-byte; supplied values are never fabricated. |
| 5 | write_purpose_did | string | — | |
| 6 | access_policy | string | — | |
| 7 | memory_subject | string | — | Supply both merge keys to project an OMP assertion item. |
| 8 | memory_predicate | string | — | |
| 9 | valid_time | uint64 | — | |
ome.v1.GatedMemoryWriteResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | committed | bool | — | |
| 2 | epoch | int64 | — | |
| 3 | decision | AmgateDecisionProjection | — | the post-commit durable sequence_no (§D2 emit-after-commit) |
ome.v1.GetActiveDeploymentRequest
ENG-2806: request the latest live deployment pointer for (slug, environment). Workspace identity is server-authoritative (never on the wire).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | slug | string | — | The template family slug (same grammar as ListPromptVersionsRequest.slug). |
| 3 | environment | string | — | The labeled rollout target: a FROZEN reserved label (prod/staging/canary) or a tenant x- lane (^x-[a-z0-9][a-z0-9-]{0,62}$). Unknown labels fail closed with 5561 (CDDL deploy-env). |
ome.v1.GetActiveDeploymentResponse
ENG-2806: the latest live deployment pointer. Every field is decoded from the SIGNED prompt.deployment.v1 claim body (the index only routes) and cross-checked against the index row (divergence → 5566, fail-closed).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | 16-byte UUIDv7 claim id of the deployment pointer claim. |
| 2 | active_template_cid | bytes | — | 32-byte render-preimage CID of the now-ACTIVE template (the pointer's target_cid) — resolve the full version via GetClaimByCid. |
| 3 | environment | string | — | The environment label echoed from the signed body. |
| 4 | deployment_at_unix_ms | int64 | — | Unix ms the pointer became authoritative (the signed body's effective_ts — NOT the claim insert time). |
| 5 | content_hash | bytes | — | 32-byte pointer-decision CID (sha256(canonical_cbor( prompt-deployment-pointer-preimage)), dsTag osyra-prompt-deployment-v1), recomputed server-side from the signed body. |
ome.v1.GetClaimBodyRequest
ENG-2225 [D3]: request the raw canonical-CBOR body of a single claim.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | 16-byte UUIDv7 claim id. The workspace is server-authoritative (OS-Workspace-ID header → ome.workspace_id GUC), not carried here. ENG-784 protovalidate: exactly 16 bytes. |
ome.v1.GetClaimBodyResponse
ENG-2225 [D3]: the raw claim body. The AC2 read-sanitization is consciously reversed for this RPC (see the GetClaimBody rpc doc) — but only the body PAYLOAD is returned; the signature and signer_pub bytes are still NEVER on the wire.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | body | bytes | — | Raw canonical-CBOR body bytes (≤16 MiB per the service body cap). |
| 2 | content_hash | bytes | — | 32-byte SHA-256 content commitment (Claim.content_hash) so the caller can verify SHA-256(body) == content_hash before trusting the bytes. |
ome.v1.GetClaimByCidRequest
ENG-2806: resolve a 32-byte CID to its committed claim. Workspace identity is server-authoritative (never on the wire).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | content_hash | bytes | — | The 32-byte CID: a prompt-family CID (render-preimage / pointer-decision hash, resolved via the prompt index) OR a generic body CID (claim.content_hash = SHA-256(body), the fallback path). Earliest claim wins on ambiguity (mirrors the ClaimRepository.findClaimByContentHash contract). |
ome.v1.GetClaimByCidResponse
ENG-2806: the resolved claim. The body-out read inherits the GetClaimBody posture (AC2 reversal for the body PAYLOAD only — signature and signer_pub are still NEVER on the wire) + the ADR-157 §4 read-path integrity check.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | projection | ClaimProjection | — | Sanitized projection (same shape ListClaims serves; no body/sig/signer_pub fields exist on it structurally). |
| 2 | body | bytes | — | Raw canonical-CBOR claim body bytes (≤16 MiB service body cap). |
| 3 | content_hash | bytes | — | 32-byte signed content commitment (Claim.content_hash = SHA-256(body)) so the caller can self-check the returned bytes. NOTE: for a prompt-CID resolution this is the BODY hash, which differs from the requested prompt-family CID (the render-preimage / pointer-decision hash carried in-body); the server has already verified the requested CID re-derives from the decoded body. |
| 4 | inclusion_proof | InclusionProof | — | The JMT inclusion witness (offline-verifiable; see InclusionProof). |
ome.v1.GetDerivationChainMetadataRequest
Request for cheap metadata probe (cf. GetDerivationChain rationale comment above).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | request_id | string | — | ENG-784 protovalidate: request_id is an opaque UUID-or-token; ≤128 bytes. |
ome.v1.GetDerivationChainMetadataResponse
Response: workspace_id only (raw UUIDv4 string), chain_exists bool, era_index for Edge caching. The metadata probe MUST perform the same DB lookup regardless of workspace opt-in state to avoid timing oracles.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | workspace_id | string | — | RAW workspace_id of the owning workspace, OR empty string if chain does not exist. Edge MAPS empty to UNIFIED-NOT-FOUND with constant-time 404 cushion. |
| 2 | chain_exists | bool | — | |
| 3 | era_index | int32 | — | The era_index of the root claim; informational for Edge cache TTL hints. |
ome.v1.GetDerivationChainRequest
Request for GetDerivationChain. Edge populates workspace_id_for_lookup from its own per-request resolution (NOT from caller JWT — Edge resolves opt-in / private mode + workspace binding BEFORE invoking this RPC). request_id is the UUIDv7 string assigned by ModelBroker (ENG-571) when emitting the original DERIVATION claim.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | request_id | string | — | The UUIDv7 request_id (path parameter from Edge). Edge MUST validate UUIDv7 shape client-side; OME re-validates server-side and returns OSY-TRANS-6101 on parse failure. ENG-784 protovalidate: request_id is an opaque UUID-or-token; ≤128 bytes. |
| 2 | workspace_id_for_lookup | string | — | The workspace_id Edge resolved for this request_id. OME server-side enforces (workspace_id, request_id) match against the partial index idx_claim_workspace_request_id; mismatch → OSY-TRANS-6104 (chain not found). ENG-784 protovalidate: UUID form. |
| 3 | max_chain_length | int32 | — | Optional: maximum number of transitive parents to include in the chain. Server clamps to [1, 1000] (MAX_DERIVATION_CHAIN_LENGTH). 0 / unset = use server default (100). Edge typically sets this to balance response size vs latency budget. ENG-784 protovalidate: 0..1000 (0 = "use default"). |
ome.v1.GetDerivationChainResponse
Response carries the chain (root + transitive parents) plus a JMT witness anchor. signer_did + workspace_id fields are RAW UUIDs / DID URIs; Edge hashes them on public-mode responses per ENG-585 plan §6.2.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | chain | DerivationChainNode | repeated | The chain claims, ordered root-first. Element [0] is the root DERIVATION claim for the requested request_id; subsequent elements are transitive parents in BFS order. Maximum size = MAX_DERIVATION_CHAIN_LENGTH (1000). |
| 2 | witness | TransparencyWitness | — | JMT witness for the workspace at the chain's bound era. Edge embeds this in response.witness for downstream verifier consumption. |
| 3 | workspace_id | string | — | RAW workspace_id of the chain's owning workspace. Edge SHA-256-hashes this (workspace-binding domain-separated) on public-mode responses; passes through on private (JWT-scoped) mode. |
| 4 | chain_partial_tombstone | bool | — | TRUE if the chain contains one or more tombstoned claims. Edge sets HTTP 410 GONE + OSY-TRANS-6106 on this branch instead of 200 OK. |
| 5 | chain_truncated | bool | — | TRUE if BFS hit MAX_DERIVATION_CHAIN_LENGTH before exhausting parents. Edge collapses this to UNIFIED-NOT-FOUND on public mode per plan §6.3; surfaces a private-mode 200 OK with chain_truncated=true on WORKSPACE_SCOPED mode. |
| 6 | chain_length | int32 | — | Server-clamped chain_length (= chain.size()) for forensic-audit metadata. |
ome.v1.GetReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | receipt_id | string | — | Lowercase-hex SHA-256 of the outer envelope bytes (exactly 64 chars). Server validates server-side with a strict ^[0-9a-f]{64}$ regex; any deviation raises OSY-MEM-5121. Capped at 64 bytes server-side as a DoS guard, in line with ListReceipts's DID-length caps. ENG-784 protovalidate: exact ^[0-9a-f]{64}$ pattern (lowercase hex SHA-256). |
ome.v1.GetReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | node | VerifiedMemoryReceiptProjection | optional | The matching receipt's sanitized projection, or absent (not-set) when no row in the caller's workspace matches the id. RLS-scoped — server never reveals cross-workspace existence; not-found is indistinguishable from cross-tenant-id. |
ome.v1.GetServerSpecRequest
ENG-2568: GetServerSpec is a workspace-agnostic, side-effect-free probe. No fields today (reserved 1..999 range stays open for future scoping); the server returns its statically-pinned spec identity regardless of request content.
No scalar fields (empty message or wrapper).
ome.v1.GetServerSpecResponse
ENG-2568: the server's pinned spec identity + residency region (ADR-292 D1). The
MCP client validates spec_id against its pinned osyra.spec_id at startup and
aborts on mismatch (fail-closed); region feeds the MCP-C-31 region binding.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | spec_id | string | — | Stable, frozen wire-format spec identity for the .ome v1 family (ADR-046 RATIFIED). The value a client pins and binds at startup. e.g. "urn:osyra:ome:v1". |
| 2 | spec_version | string | — | Informational point release of the spec the backend was built against (AP00011-OME-FILE-FORMAT-V1.md frontmatter, e.g. "1.0.9"). NOT the binding key — binding is on the stable spec_id; spec_version advances within a frozen family. |
| 3 | region | string | — | Backend residency region (ome.region, e.g. "us-east-1"). Feeds the MCP-C-31 / ADR-297 region-binding startup check so an erasure / read cannot be misrouted cross-region. May be empty if the backend does not advertise a region. |
ome.v1.GetTraceRequest
GetTraceRequest — read one trace projection by id (workspace server-authoritative).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | trace_id | bytes | — | 16-byte UUIDv7 trace id. |
ome.v1.GetTraceResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | trace | TraceProjection | — | The indexed projection (the signed CBOR is the source of truth; this is the queryable projection — design §4). |
ome.v1.HistogramBucket
Single histogram bucket. le is the inclusive right edge of the bucket.
Buckets are half-open: (prevLe, le]. Counts are non-negative; the sum
across buckets equals HistogramReceiptsResponse.total_count.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | le | double | — | |
| 2 | count | uint64 | — | |
ome.v1.HistogramReceiptsRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | since_unix_ms | int64 | optional | Same filter shape as ListReceiptsRequest. All combined with AND. No pagination — the aggregate is bounded. workspace identity is server-authoritative (extracted from OS-Workspace-ID gRPC header / ome.workspace_id GUC), never request-side. String filters MUST NOT exceed 512 bytes; the server rejects with OSY-MEM-5121 otherwise (matches ListReceipts DoS guard). |
| 2 | until_unix_ms | int64 | optional | |
| 3 | purpose_did | string | optional | ENG-784 protovalidate: ≤512-byte cap on filter strings (DoS guard). |
| 4 | retriever_did | string | optional | |
| 5 | quarantine_class | VerifiedMemoryQuarantineClass | optional | |
| 6 | verdict | VerifiedMemoryVerdict | optional | |
ome.v1.HistogramReceiptsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | buckets | HistogramBucket | repeated | Right-edge-inclusive bucket counts. Server emits one entry per bucket boundary in the canonical ticket-spec order; clients MUST iterate by index, not by le numeric comparison (floats), to preserve order. |
| 2 | total_count | int64 | — | Sum across all buckets — equals the total number of facts (NOT receipts) aggregated. Cardinality differs from receipt-count because each receipt contains >= 1 RetrievedFact. |
| 3 | budget_p50 | double | — | P50 of the per-fact imitation_budget values across the filtered set. The FE renders this as a guideline line under the imitation-distance histogram (the budget threshold below which a request would have passed). |
| 4 | budget_p99 | double | — | P99 of the per-fact imitation_budget. The FE renders 2 × budget_p99 as the block-zone threshold guideline (distance > 2x budget → BLOCK). |
| 5 | truncated | bool | — | True when the aggregate represents the most-recent MAX_DECODED_RECEIPTS (10,000) rows because concurrent emits pushed real cardinality past the cap BETWEEN the pre-decode countAll() gate and the streaming SELECT. The OSY-MEM-5123 MEM_RECEIPT_HISTOGRAM_FILTER_TOO_WIDE error fires when countAll already exceeds the cap; this flag covers the TOCTOU race where rows arrived after countAll but before the streaming SQL LIMIT clamped at MAX_DECODED_RECEIPTS. Clients SHOULD render an "aggregated over last 10K events" note when truncated=true. |
ome.v1.ImportArchiveRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | The signed OMP archive to verify-admit (Form B canonical-CBOR). ENG-784 protovalidate: 1 B ≤ encoded_cbor ≤ 16 MiB (DoS guard; matches grant/claim caps). |
ome.v1.ImportArchiveResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | admitted | bool | — | |
| 2 | reason | string | — | |
| 3 | archive_id | bytes | — | OSY-OMP-65xx / OSY-MEM-5254 on a non-empty target |
| 4 | item_count | uint64 | — | |
ome.v1.ImportBundleChunk
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | data | bytes | — | |
ome.v1.ImportBundleResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | recovered_root | bytes | — | |
| 2 | n_claims_imported | uint64 | — | |
| 3 | n_tombstones_imported | uint64 | — | |
| 4 | root_match | bool | — | |
ome.v1.InclusionProof
ENG-2806: a self-contained JMT inclusion witness for one claim leaf. REUSES the existing JMTProof wire message for the sibling structure (no duplicate proof encoding) and adds the (root, key, value) context so the proof is offline-re-verifiable with no service call:
leaf_blob = 0x00 || leaf_key || leaf_value_hash (production framing) fold(leaf_blob, proof siblings, radix-16) == jmt_root (lib/osyidx recompute)
leaf_key = SHA-256 domain-separated derivation over (workspace_id, claim_id) (JmtKeyDeriver — the SAME key the Prove RPC family uses); leaf_value_hash = SHA-256(signed_claim_cbor) (the committed JMT leaf value; V4 claim.value_hash). The server verifies this exact recompute BEFORE responding — a served proof that does not fold to jmt_root is a 5153 server fault, never returned.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | jmt_root | bytes | — | 32-byte committed workspace JMT root the proof folds to (the root read from workspace_jmt_root at proof time; internally consistent with proof). |
| 2 | leaf_key | bytes | — | 32-byte JMT leaf key for (workspace_id, claim_id). |
| 3 | leaf_value_hash | bytes | — | 32-byte committed JMT leaf value (SHA-256 of the canonical SignedClaim CBOR). |
| 4 | proof | JMTProof | — | The sibling path — the EXISTING Prove-RPC proof message, reused verbatim. |
| 5 | inclusion | bool | — | Always true on GetClaimByCid (only live, committed claims are served); carried explicitly so the message is self-describing if reused. |
ome.v1.InsertRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | Frozen wire name; semantically an RFC 9562 UUIDv8 raw 16-byte typed JMT anchor_id. Deterministic producers MUST use a domain-separated mapping; AP00012 freezes SHA-256(UTF8("osyra-jmt-anchor-id-v1") || 0x00 || UTF8(canonical_path)), truncated to 16 bytes with the UUIDv8 version and RFC variant bits stamped. Callers MUST NOT reuse a signed Claim/tombstone/orphan identifier: the server hard-rejects any anchor_id whose JMT slot is already occupied. ENG-784 protovalidate: exact 16-byte typed anchor identifier. |
| 2 | value_hash | bytes | — | Exact 32-byte commitment supplied by the caller. The server does not infer or claim that it is SHA-256(canonical-CBOR(SignedClaim)); no SignedClaim is present in this request. ENG-784 protovalidate: exact 32-byte SHA-256 digest. |
ome.v1.InsertResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | new_root | bytes | — | Root committed by the first successful anchor write. An identical replay returns this original root without a new JMT sequence advance. |
ome.v1.IssueGrantRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | source_workspace_id | string | — | ENG-784 protovalidate: source workspace MUST be UUID. |
| 2 | target_workspace_id | string | — | ENG-784 protovalidate: target workspace MUST be UUID. |
| 3 | scope | string | — | Scope string, e.g., "read:claims:assertion". ENG-784 protovalidate: ≤256-byte cap (scope strings are short by convention; 256 is defense-in-depth — prevents megabyte scope strings inflating signed preimages). |
| 4 | expires_at | google.protobuf.Timestamp | — | |
| 5 | idempotency_key | string | — | ENG-786 [FU-567 M5] destructive-admin pattern (see V1 Admin Messages header). UUIDv7 idempotency key. Server de-duplicates on (source_workspace_id, idempotency_key) within 24 hours; replay returns the cached IssueGrantResponse. REQUIRED — empty string → OSY-MEM-5126 (IDEMPOTENCY_KEY_MISSING). |
| 6 | audit_attestation_ref | string | — | UUIDv7 of the audit-event row recording the human approval. Server resolves this row, asserts (workspace_id, audit_attestation_ref) matches, and asserts the event has not been previously consumed by a destructive RPC. REQUIRED — empty string → OSY-MEM-5311 (WBW_BINDING_MISMATCH). |
| 7 | attestations | AdminAttestation | repeated | 2-of-3 multi-sig attestations per CLAUDE.md. Server enforces: 2 ≤ count ≤ 3 distinct signer_did across the set each signature verifies under the signer_did's resolved pubkey each signed_at within ±5 min of server clock ≥ 2 signer_did values in the workspace's admin signer set ENG-786 protovalidate: 2..3 entries (defense-in-depth ahead of server check). |
ome.v1.IssueGrantResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | grant_id | string | — | |
| 2 | encoded_cbor | bytes | — | Form B canonical-CBOR signed grant (dsTag: "osyra-ome-grant-v1"). SIGNED-FIELDS: the Ed25519 signature inside encoded_cbor covers the canonical-CBOR Form B preimage: [tstr("osyra-ome-grant-v1"), {grant_id, source_workspace_id, target_workspace_id, scope, expires_at_unix_millis}] (fields drawn from the originating IssueGrantRequest plus the server- assigned grant_id). Per the file-header SIGNED-PREIMAGE CANONICALIZATION rule, IssueGrantRequest.expires_at (google.protobuf.Timestamp on the wire) MUST be canonicalized to int64 Unix-ms (expires_at_unix_millis) BEFORE inclusion in the preimage. The wire-level expires_at field stays as Timestamp for caller ergonomics; the int64 millis form is signed- preimage-only and never appears as a separate wire field. Direct Timestamp-to-CBOR encoding in the preimage is FORBIDDEN — would produce cross-SDK signature drift. Encoding contract: same long-name → short-key mapping policy as Claim/SignedClaim; cross-language encoders go through the canonical osyra-claims-common artifact (ENG-715). |
| 3 | idempotency_replayed | bool | — | ENG-786 [FU-567 M5]: TRUE when this response was served from the idempotency dedup cache (the original first-call response is replayed byte-identically). FALSE on the first call. Informational; callers may log this to differentiate first emit vs idempotent retry. |
ome.v1.JMTProof
Inclusion or non-membership proof for a JMT key. Layout matches OAP-MEM v0.1
§4.4 (JMTProof CDDL); see that document for the verification algorithm.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | levels | SiblingLevel | repeated | Per-level sibling-hash array. levels.length == proof depth ≤ 64; each SiblingLevel.slots is 16 entries × 32-byte hashes (empty slots are zero). |
| 2 | depth | int32 | — | Depth of the proof (0..64); equal to levels.length. |
| 3 | absent_kind | AbsentKind | — | Discriminator for non-membership proofs. |
| 4 | other_key | bytes | — | Used only when absent_kind == ABSENT_DIFFERENT_LEAF: the key/value of the colliding leaf at the proof's terminal slot. |
| 5 | other_value | bytes | — | |
ome.v1.LMeetProjection
L_meet operator witness, sanitized (AC2). The raw monotonicity_proof bytes are NEVER on the wire; only their SHA-256 digest is exposed.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | operator | string | — | |
| 2 | monotonicity_proof_sha256 | bytes | — | SHA-256 of the raw monotonicity proof bytes. 32 bytes. The digest commits to the proof; auditors with the raw proof (in a separate audit-only path) can verify byte-equality. The raw bytes are NOT exposed via this wire. |
| 3 | composition_path | string | repeated | Upstream receipt IDs (lowercase hex SHA-256) composed by ⊓_imitation. |
ome.v1.ListAmgateDecisionsRequest
ListAmgateDecisionsRequest - filters over the attested-memory-gate decision log (ARC-31 / ADR-281).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | since_unix_ms | int64 | optional | Optional filters (AND-combined). Caps server-enforced (DoS guard). |
| 3 | until_unix_ms | int64 | optional | |
| 4 | stage | string | optional | Decision stage name {CAPABILITY, POLICY, SOURCE_ADMISSIBILITY, ATTESTATION, TRUST_ANCHOR, COMMIT}. |
| 5 | allowed | bool | optional | Filter by outcome: true = admitted, false = denied; absent = both. |
| 6 | limit | int32 | — | limit: server-clamped to [1,200]; 0 -> default 50. |
| 7 | cursor | string | — | cursor: opaque base64url(<decided_at_unix_ms>:<decision_id>); empty for page 1; <=256 bytes. |
ome.v1.ListAmgateDecisionsResponse
ListAmgateDecisionsResponse - one page of sanitized amgate decisions.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | nodes | AmgateDecisionProjection | repeated | |
| 2 | has_more | bool | — | |
| 3 | next_cursor | string | — | |
| 4 | total_count | int64 | — | |
ome.v1.ListClaimsRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | since_unix_ms | int64 | optional | Optional filters. All combined with AND. String filters MUST NOT exceed 512 bytes; cursor MUST NOT exceed 256 bytes (DoS guards mirror ListReceipts). |
| 3 | until_unix_ms | int64 | optional | lower bound (inclusive) on created_at |
| 4 | issuer_did | string | optional | upper bound (exclusive) on created_at ENG-784 protovalidate: ≤512-byte cap on DID/string filters. |
| 5 | subject_id | string | optional | |
| 6 | kind | ClaimKind | optional | Reserved in the V1 request shape but rejected explicitly by the current server because the claim index does not yet persist/backfill kind. It is never silently ignored. Callers must omit it until the indexed filter lands. |
| 7 | include_tombstoned | bool | optional | |
| 8 | limit | int32 | — | Pagination. limit: server-clamped to [1, 200]; 0 → default 50. cursor: opaque base64url(v2:<epoch_second>:<nano>:<claim_id_hex>); legacy epoch-millisecond cursors remain decode-only compatible; empty for page 1. Capped at 256 bytes server-side. A server-enforced aggregate byte budget applies to the persisted envelopes read for projection integrity. RESOURCE_EXHAUSTED is returned before blob materialization when the requested logical page exceeds that budget; clients should retry the same cursor with a smaller limit. ENG-784 protovalidate: 0 ≤ limit ≤ 200 (0 = "use default 50"). |
| 9 | cursor | string | — | ENG-784 protovalidate: ≤256-byte cap on cursor (matches server enforcement). |
ome.v1.ListClaimsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | nodes | ClaimProjection | repeated | |
| 2 | has_more | bool | — | |
| 3 | next_cursor | string | — | |
| 4 | total_count | int64 | — | Total count over the filter set (workspace-scoped). V1: uncached COUNT(*) per request — same trade-off as ListReceipts (caching tracked as future tuning if SLO requires). |
ome.v1.ListMemoryEventsRequest
ENG-3214: memory-events feed request. Workspace identity is server- authoritative (OS-Workspace-ID header → ome.workspace_id GUC / claim-table RLS) — clients DO NOT carry workspace_id (mirrors ListWitnessEventsRequest).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | since_unix_ms | int64 | optional | Optional filters, AND-combined. Lifecycle kinds not persisted in the claim write-log return an empty page; the service never fabricates event rows. |
| 3 | kind | string | optional | |
| 4 | actor | string | optional | |
| 5 | claim_key_prefix | string | optional | |
| 6 | limit | int32 | — | Server clamps limit to [1, 200]; 0 selects the default. Cursor is opaque. |
| 7 | cursor | string | — | |
ome.v1.ListMemoryEventsResponse
ENG-3214: page of memory events. Mirrors the Edge GraphQL page shape.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | nodes | MemoryEventNode | repeated | |
| 2 | has_more | bool | — | |
| 3 | next_cursor | string | — | |
ome.v1.ListPromptVersionsRequest
ENG-2806: request the template version list for a slug. Workspace identity is server-authoritative (OS-Workspace-ID gRPC header → ome.workspace_id GUC → RLS); clients DO NOT carry workspace_id (mirrors ListClaimsRequest HIGH-1).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | slug | string | — | The template family slug. 1..128 chars, charset [a-z0-9._-]+ (CDDL slug, the SAME grammar the mint-side PromptTemplatePayloadValidator enforces). |
| 3 | limit | int32 | — | Pagination. limit: server-clamped to [1, 200]; 0 → default 50. |
| 4 | cursor | string | — | Opaque cursor base64url(<created_at_unix_ms>:<claim_id_hex>); empty for page 1. Capped at 256 bytes server-side (the ListClaims cursor codec). |
ome.v1.ListPromptVersionsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | versions | PromptVersionNode | repeated | Newest first: (created_at_unix_ms DESC, claim_id DESC). |
| 2 | has_more | bool | — | |
| 3 | next_cursor | string | — | |
| 4 | total_count | int64 | — | Total template-version count for the slug (workspace-scoped; uncached COUNT — same trade-off as ListClaims). |
ome.v1.ListReceiptsRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | since_unix_ms | int64 | optional | Optional filters. All combined with AND. String filters MUST NOT exceed 512 bytes; cursor MUST NOT exceed 256 bytes (server-enforced DoS guard). |
| 3 | until_unix_ms | int64 | optional | |
| 4 | purpose_did | string | optional | ENG-784 protovalidate: ≤512-byte cap on filter strings (DoS guard). |
| 5 | retriever_did | string | optional | |
| 6 | quarantine_class | VerifiedMemoryQuarantineClass | optional | |
| 7 | verdict | VerifiedMemoryVerdict | optional | |
| 8 | limit | int32 | — | Pagination. limit: server-clamped to [1, 200]; 0 → default 50. cursor: opaque base64url(<emitted_at_unix_ms>:<receipt_id>); empty for page 1. Capped at 256 bytes server-side. ENG-784 protovalidate: 0 ≤ limit ≤ 200 (0 = "use default 50"). |
| 9 | cursor | string | — | ENG-784 protovalidate: ≤256-byte cap (matches server-enforced cursor cap). |
ome.v1.ListReceiptsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | nodes | VerifiedMemoryReceiptProjection | repeated | |
| 2 | has_more | bool | — | True if more pages exist beyond nodes. |
| 3 | next_cursor | string | — | Opaque cursor for next page; empty when has_more=false. |
| 4 | total_count | int64 | — | Total count over the filter set (workspace-scoped). V1: uncached COUNT(*) per request. Server-side caching is tracked as ENG-1071-followup (Redis cache keyed on workspace+filter_hash). |
ome.v1.ListSignerPubsRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | workspace_did | string | — | The workspace DID whose allowlist is being queried. Per the DID scheme, typically "did:osyra:workspace:<uuid>" but the cache treats it as an opaque string and delegates resolution to WorkspaceDidResolver. Unresolvable DIDs do NOT produce an error — they produce an empty signer_pubs set (fail-closed semantics per ADR-040 v0.2 §3). This avoids workspace-existence leakage via distinguishable status codes. |
ome.v1.ListSignerPubsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | signer_pubs | bytes | repeated | Raw 32-byte Ed25519 public keys; active + retired entries from workspace_mguard_signing_key, dedup'd into the set the verifier consults. Empty set if workspace_did doesn't resolve OR if the workspace has no registered signing keys (callers MUST fail-closed). Returned in DB-row order, NOT sorted by content — callers that need sorted-deduped sets should impose their own ordering. The set is typically 1-3 entries (one active + zero-to-two retired during rotation window per ADR-040 v0.2 §3). |
| 2 | valid_until_unix_ms | int64 | — | Informational: server-clock-derived deadline beyond which the calling verifier SHOULD refresh its cache. Computed as now() + cache TTL (default 60 seconds per ADR-040 v0.2 §3). Clients SHOULD NOT use this for cache TTL — use a fixed 60-second window from the moment of the call instead. Using valid_until creates a thundering-herd at rotation boundaries (every cached client refreshes within the same millisecond window). |
ome.v1.ListTracesRequest
ListTracesRequest — filtered list within the caller's workspace (NO float fields).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | since_unix_ms | uint64 | — | Lower bound (inclusive) on trace ts (Unix ms). 0 → no lower bound. |
| 2 | until_unix_ms | uint64 | — | Upper bound (exclusive) on trace ts (Unix ms). 0 → no upper bound. |
| 3 | model_id | string | — | Filter by model id. Empty → no filter. <=256 bytes. |
| 4 | broker_request_id | string | — | Filter by broker request id. Empty → no filter. <=512 bytes. |
| 5 | page_size | uint32 | — | Page size. 0 → server default. Server enforces a hard ceiling. |
| 6 | page_token | string | — | Opaque page token from a prior response (the last trace_id, hex). Empty → first page. |
ome.v1.ListTracesResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | traces | TraceProjection | repeated | The page of trace projections, ts-descending then trace_id-descending. |
| 2 | next_page_token | string | — | The page token to pass for the next page; empty when the page is the last. |
ome.v1.ListWitnessEventsRequest
ENG-2073: request for the paginated witness-events feed. Mirrors ListClaimsRequest discipline — workspace is server-authoritative (NOT on the wire), all filters optional + AND-combined, DoS caps on string/cursor length.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 2 | since_unix_ms | int64 | optional | Optional filters, AND-combined. Enum-like values (operator, claim_kind, verdict) that do not resolve to a known value are silently IGNORED (forward-compat, matching the Edge SDL contract) — they do not filter to empty. String filters MUST NOT exceed 512 bytes; cursor ≤256 bytes. |
| 3 | operator | string | optional | exclusive lower bound on occurred_at Lattice operator label (derived server-side from ClaimKind). ≤512 bytes. |
| 4 | signer | string | optional | Signer DID / KMS key alias — exact match on the claim signer. ≤512 bytes. |
| 5 | claim_kind | string | optional | ClaimKind namespace (derived server-side from ClaimKind). ≤512 bytes. |
| 6 | verdict | string | optional | Verdict filter ∈ {valid, invalid, pending, sealed}. ≤32 bytes. |
| 7 | limit | int32 | — | Pagination. limit: server-clamped to [1, 200]; 0 → default 50. cursor: opaque base64url(<occurred_at_unix_ms>:<claim_id_hex>); empty for page 1. Capped at 256 bytes server-side. |
| 8 | cursor | string | — | |
ome.v1.ListWitnessEventsResponse
ENG-2073: page of witness events. Mirrors WitnessEventsPage in the Edge SDL
(nodes / hasMore / nextCursor — no total_count).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | nodes | WitnessEventNode | repeated | |
| 2 | has_more | bool | — | |
| 3 | next_cursor | string | — | Opaque cursor for the next page; empty when has_more is false. |
ome.v1.MemoryEventNode
ENG-3214: one persisted signed claim projected for the Memory Inspector.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | id | string | — | |
| 2 | occurred_at_unix_ms | int64 | — | |
| 3 | kind | string | — | OPEN lowercase set; new event kinds remain forward-compatible. |
| 4 | actor | string | — | |
| 5 | claim_key | string | — | |
| 6 | claim_kind | string | — | |
| 7 | summary | string | optional | |
| 8 | bytes | int64 | optional | |
ome.v1.MergeArchivesRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | input_archives | bytes | repeated | ≥2 signed OMP archives to merge (each Form B canonical-CBOR). Order-tolerant — the merge is confluent (cellLt strict-total ConflictRule). ≤64 inputs (DoS guard). |
| 2 | merger_vendor | string | — | The merger's archive-header provenance for the merged OMP output. |
| 3 | merger_model_family | string | — | |
ome.v1.MergeArchivesResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | merged_archive | bytes | — | The merged OMP archive (live winners) — Form B canonical-CBOR, the signing surface. |
| 2 | merge_receipt | bytes | — | The EAT-hosted Merge Receipt (COSE_Sign1, receipt_kind OMMP-2/OMMP-N) — the offline-re-decidable proof. Signing surface: the EAT envelope bytes. |
| 3 | merge_root | bytes | — | Decoded views (NOT signed). |
| 4 | contradictions | SurfacedContradiction | repeated | the anchored merge root (== merged archive id) |
ome.v1.OmlcLogWitness
One entry of the supplied authorized-write log (the detached omlc-log-witnesses
re-decider input; ADR-330 §4.3 / cddl omlc-log-entry). The relying party supplies the
COMPLETE ordered log; the verifier re-binds it to the signed body via LOG_BOUND
(log_root + the max_seq conjunct) and re-derives CANONICITY over it. subject_did is
bound, NOT vouched (PROVENANCE ≠ TRUTH, ADR-330 §1).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | seq | uint64 | — | |
| 2 | key | string | — | strictly-increasing append-only across the log (BAD_LOG) |
| 3 | value | bytes | — | |
| 4 | subject_did | string | — | the written value bytes (LWW-replayed into state_root) |
ome.v1.PromptVersionNode
ENG-2806: one committed template version of the slug's family.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | 16-byte UUIDv7 claim id of the prompt.template.v1 claim. |
| 2 | content_hash | bytes | — | 32-byte version identity CID — the render-preimage content_hash (sha256(canonical_cbor(prompt-template-render-preimage)), dsTag osyra-prompt-template-v1). This is the CID currency a deployment pointer's active_template_cid references, and the CID GetClaimByCid resolves. |
| 3 | created_at_unix_ms | int64 | — | Claim-row insert time (Unix milliseconds; the keyset-pagination axis). |
| 4 | issuer_did | string | — | Issuer DID of the signing author (claim.signer_did). |
| 5 | tombstoned | bool | — | True only in the transient tombstoned-with-claim-row state; erased versions are REMOVED from the list entirely (GDPR Art-17 — the index row cascades with the claim-row hard-delete). |
ome.v1.ProveRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | ENG-784 protovalidate: exact 16-byte UUIDv7. |
ome.v1.ProveResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | value_hash | bytes | — | |
| 2 | proof | JMTProof | — | 32 bytes; zero-filled if absent |
| 3 | is_present | bool | — | |
| 4 | osyra_retrieval_receipt | bytes | — | VM-4 (ENG-1042) — populated for PRO/ENTERPRISE-tier workspaces with the canonical-CBOR-encoded osyra-receipt-envelope-v1 wrapper proving the negative-set (non-membership) result. The Prove path is the core $50K ACV value-prop per ADR-038 v0.2 §"Performance budget" — the receipt attests that the retrieval mathematically excluded everything outside the proven set. FREE/STARTER-tier workspaces and any request without the os-workspace-tier header set to a receipt-enabled tier receive proto3 default (empty bytes). Wire authority: ADR-039 v0.2 envelope format with inner_ds_tag = "osyra-ome-mguard-v1". Decode via osyra-mguard-common OsyraReceiptEnvelopeCodec. ENG-2279 Task 5: renamed mguard_retrieval_receipt → osyra_retrieval_receipt (Tier-1 trade-secret-vocabulary rename per docs/RENAME-PLAN-v1.0.md). Field NUMBER 4 is PRESERVED — this is a name-only change, binary-wire-compatible (protobuf wire uses field numbers, not names). The inner_ds_tag string "osyra-ome-mguard-v1" is an unchanged wire-format crypto constant, not the field name. |
| 5 | is_tombstoned | bool | — | ENG-1055 — distinguishes redacted-but-present from absent. When the (workspace_id, claim_id) tuple resolves to a JMT leaf whose valueHash is SHA-256("TOMBSTONE\0" || salt16) (per the tombstone redaction protocol from JellyfishMerkleTree.tombstone()), is_present remains true (the leaf structurally exists in the tree) but is_tombstoned becomes true to signal the leaf has been redacted. The returned value_hash is the redacted digest, not the original; callers wishing to confirm tombstoning derive the expected redacted digest from the workspace's era_secret_n + claim_id via HKDF and compare. For pure inclusion proofs of non-tombstoned leaves: is_present=true, is_tombstoned=false. For non-membership proofs: is_present=false, is_tombstoned=false (the redaction protocol does not apply to absent keys). proto3 default (false) is preserved for FREE-tier responses to maintain ENG-1042 AC8 byte-equality (FreeTierByteEqualityTest). |
ome.v1.ProveTombstonedRequest
ENG-583: evidence-of-erasure proof. Caller obtains JMT inclusion proof
against new_root_at_redaction showing the leaf at JmtKey(claim_id) has
valueHash = tombstone_digest. Caller does NOT receive the salt — the
digest is server-attested; verifiers may either trust the server-attested
digest or correlate via the audit chain (audit_correlation_id resolves to
the MEMORY_TOMBSTONED event in the SIEM).
For PRO/ENTERPRISE-tier customers, V1.5 will wrap this in a signed canonical-CBOR Form B envelope with dsTag "osyra-ome-tombstone-proof-v1" (ENG-583-FU-2 follow-up).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | ENG-784 protovalidate: exact 16-byte UUIDv7. |
ome.v1.ProveTombstonedResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | proof | JMTProof | — | |
| 2 | tombstone_digest | bytes | — | inclusion proof at jmt_key(claim_id) |
| 4 | era_index | uint32 | — | 32B = SHA-256("TOMBSTONE\0" || salt16) — redacted leaf valueHash FIELD 3 INTENTIONALLY RESERVED — was contemplated for bytes salt; rejected by ENG-583 B-1/sec (salt exposure defeats Art-17 erasure during active era). |
| 5 | redacted_at | google.protobuf.Timestamp | — | |
| 6 | audit_correlation_id | string | — | |
| 7 | new_root_at_redaction | bytes | — | |
| 8 | tombstoned_at_sequence | uint64 | — | workspace_jmt_root at tombstone time (32B); offline replay |
ome.v1.PublishedBundleProto
Server-side carriage of a published bundle's metadata for transport=s3 (or
transport=local_filesystem in dev/test). Emitted by
OMEServiceGrpcAdapter.exportAuditBundle after the
{@code AuditBundlePublisher} returns. Single chunk; no data chunks follow.
Per spec §11.2 the audit log records url_sha256 (hex) — NEVER the raw URL.
The on-wire url field is for the client to download from; url_sha256
is the auditable anchor a downstream verifier uses to confirm "this URL
was issued by this server-call without revealing the URL itself".
Wire-freeze: this message's field numbering is part of the .ome-audit transport contract. Field additions go in the reserved range; existing fields MUST NOT be renumbered.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | url | string | — | Presigned GET URL (HTTPS only in prod profile; file:// in local_filesystem). TTL-bounded — see ttl_seconds. |
| 2 | url_sha256 | bytes | — | 32-byte SHA-256 of the UTF-8 url bytes. Audit-trail anchor per spec §11.2. |
| 3 | ttl_seconds | uint32 | — | Time-to-live in seconds. Production cap = 300 (5 min) per ADR-057 §Dec 4. Non-prod allowed range: (0, 3600]. |
| 4 | bucket | string | — | S3 bucket name (e.g., osyra-ome-audit-bundles-prod). For local_filesystem transport, this is the filesystem root path. |
| 5 | s3_object_key | string | — | Object key: {workspace_id}/{bundle_sha256_hex}.ome-audit.zip per ADR-057 §Dec 3. Content-addressed: re-export of same filter + same data = same key. |
ome.v1.RefreshOrgRootRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | org_id | string | — | Server MUST verify the calling identity has org-admin scope for the requested org_id before computing the forest-of-merkles root. Returns OSY-MEM-5310 (WBW_BINDING_MISMATCH) on authz failure. Per /osyra-security M10 PR #2 review. ENG-784 protovalidate: org_id is a UUID string (IAM org-id form). |
| 2 | idempotency_key | string | — | ENG-786 [FU-567 M5] destructive-admin pattern. RefreshOrgRoot is a destructive admin operation because it mints the canonical org-level attestation root that downstream verifiers trust — a forged root would silently quarantine or accept the wrong workspace set across the org. (See V1 Admin Messages section header for the full pattern docstring.) |
| 3 | audit_attestation_ref | string | — | |
| 4 | attestations | AdminAttestation | repeated | |
ome.v1.RefreshOrgRootResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | org_root | bytes | — | |
| 2 | n_workspaces_aggregated | uint64 | — | 32 bytes; nightly forest-of-merkles aggregate |
| 3 | computed_at | google.protobuf.Timestamp | — | |
| 4 | idempotency_replayed | bool | — | ENG-786 [FU-567 M5]: TRUE on idempotent-replay (cache hit). See IssueGrantResponse.idempotency_replayed for full semantics. |
ome.v1.RegisterClaimKindRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | kind_uri | string | — | Kind URI, e.g., "osyra.claim.workspace.boundary.cross-org-bridge.v1". ENG-784 protovalidate: reverse-DNS pattern ending in .vN (matches the PR #2 spec). Examples: osyra.claim.assertion.v1 osyra.claim.workspace.boundary.cross-org-bridge.v1 Disallows leading dot, capital letters, and unversioned URIs. |
| 2 | version | uint32 | — | |
| 3 | struct_schema_cbor | bytes | — | CDDL or canonical-CBOR schema for V1.5+ pluggable handlers. ENG-784 protovalidate: ≤1 MiB cap (1048576 bytes) per PR #2 spec. |
ome.v1.RegisterClaimKindResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | kind_id | string | — | |
| 2 | registered | bool | — | |
ome.v1.RegisterWorkspaceKEKRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | workspace_id | string | — | Target workspace UUIDv7. The Edge Gateway also passes OS-Workspace-ID; the server validates that header workspace_id == this field's workspace_id before any DB write (defense-in-depth, mirrors BatchInsertRequest workspace_id pattern). ENG-784 protovalidate: UUID string form. |
| 2 | kek_arn | string | — | AWS KMS multi-region key ARN, e.g. arn:aws:kms:us-east-1:123456789012:key/abcd-ef01-2345-6789-abcdef012345 The server stores this verbatim in workspace_kek.kek_arn and asserts byte-equality against the KMS Decrypt response's keyId field on every era unwrap (cache-poisoning defense per ADR-016 §Security Q1+Q2). ENG-784 protovalidate: AWS KMS ARN pattern + ≤2048-byte cap. |
| 3 | kek_region | string | — | Primary KMS region (e.g., "us-east-1"). For multi-region keys (MRK), the wrapped era_secret is decryptable in any partition region; this field records the workspace's primary region for audit + compliance. ENG-784 protovalidate: AWS region designator pattern + ≤64-byte cap. |
| 4 | kek_grant_id | string | — | Optional grant ID for managed CMKs. Empty for customer-account CMKs (where the grant lives in the customer's KMS account out-of-band). ENG-784 protovalidate: ≤256-byte cap (KMS grant IDs ≤128 in practice; 256 = defense-in-depth bound). |
| 5 | kek_managed_by | string | — | Tier discriminator (M-arch-1): "customer" = ENT BYOK; "osyra" = FREE/PRO managed. Must be exactly one of these two literal strings; the schema CHECK constraint enforces. Server returns OSY-MEM-5101 on invalid values. ENG-784 protovalidate: enumerated allowlist. |
ome.v1.RegisterWorkspaceKEKResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | registered | bool | — | |
| 2 | bootstrap_era_index | uint32 | — | The bootstrap era_index that was inserted into workspace_era. Always 0 for first-time registration; on idempotent retry, this echoes the existing row's era_index (typically 0 unless the caller has already triggered a rotation). |
| 3 | registered_at | google.protobuf.Timestamp | — | |
ome.v1.ResumeCursor
ResumeCursor — per-(source_region, workspace_did) resume anchor for stream restarts. ENG-1233 §3 / ADR-040 v0.4 §3.4.2.
Server-side semantics: events with sequence_number ≤ last_sequence_number for the matching (source_region, workspace_did) tuple are SUPPRESSED; the next event the subscriber sees has sequence_number ≥ last_sequence_number + 1 (within retention; otherwise STREAM_GAP).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | source_region | string | — | AWS region designator (e.g., "us-east-1"). Must match SignerPubChangeEvent.source_region exactly. Length cap: 64 bytes UTF-8 (matches AWS region designator max). ENG-784 protovalidate: AWS region pattern + ≤64-byte cap. |
| 2 | workspace_did | string | — | Workspace DID; same form/normalization as WorkspaceFilter.workspace_dids. ENG-784 protovalidate: ≤256-byte cap (matches WorkspaceFilter per-entry cap). |
| 3 | last_sequence_number | uint64 | — | Highest sequence_number the Edge has already processed for this tuple. Server resumes emission from this number + 1. |
ome.v1.RetrievedFactProjection
Per-fact sanitized projection (AC2). Excludes write_scope_biscuit and write_jmt_inclusion_proof — these are AC2 secrets and have no field on this message.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | fact_id | bytes | — | SHA-256 of the source ClaimKind preimage. 32 bytes. |
| 2 | write_capability_did | string | — | |
| 3 | age_seconds | uint64 | — | |
| 4 | imitation_distance | double | — | |
| 5 | imitation_budget | double | — | |
| 6 | quarantine_class | VerifiedMemoryQuarantineClass | — | |
| 7 | similarity_score | double | — | |
| 8 | tombstone_absent | bool | — | |
ome.v1.RevokeSignerPubRequest
RevokeSignerPubRequest — input to OMEService.RevokeSignerPub per ADR-040 v0.4 §3.20.3.
Validation order:
- Edge mTLS identity (interceptor; bypasses if missing).
- workspace_id non-blank UUID; equals MDC ome.workspace_id (anti-spoof).
- signer_pub exactly 32 bytes.
- reason ∈ {COMPROMISE, POLICY_CHANGE, OPERATOR_PUSHED}; UNSPECIFIED + KEK_CASCADE rejected with INVALID_ARGUMENT.
- actor_user_did non-blank.
- mfa_challenge_id non-blank.
- Rate-limit check (10/hour/workspace) — RESOURCE_EXHAUSTED → 5137.
- OPA gate (owner/security-admin + ≤15min MFA) — PERMISSION_DENIED → 5127 / UNAUTHENTICATED → 5128.
- Row lookup — NOT_FOUND → 5129; already-revoked → 5126.
- UPDATE + audit emit + sequence-number allocation + event queue (atomic).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | workspace_id | string | — | Target workspace UUID (string form). Must equal MDC ome.workspace_id. ENG-784 protovalidate: UUID form. |
| 2 | signer_pub | bytes | — | 32-byte raw Ed25519 pubkey (RFC 8032). Must match a row in workspace_mguard_signing_key for the workspace. ENG-784 protovalidate: exact 32 bytes. |
| 3 | reason | RevocationReason | — | Mandatory. UNSPECIFIED rejected with INVALID_ARGUMENT. KEK_CASCADE rejected from external callers with INVALID_ARGUMENT (reserved for ADR-016 internal cascade). ENG-784 protovalidate: reject UNSPECIFIED (=0) and KEK_CASCADE (=4) at proto layer. |
| 4 | actor_user_did | string | — | Owner-or-security-admin DID (validated by OPA gate). Carried into the audit-event payload as actor_user_did_hash. ENG-784 protovalidate: DID URI + ≤512-byte cap. |
| 5 | mfa_challenge_id | string | — | Recent MFA challenge ID (≤ 15 min freshness; validated by OPA gate). Carried into the audit-event payload as mfa_challenge_id_hash. ENG-784 protovalidate: ≤256-byte cap (challenge IDs are short opaque tokens). |
| 6 | operator_note | string | — | Free-text note for incident-response forensics. Raw value persists ONLY in the workspace-scoped LISTEN/NOTIFY channel ome.security.lawviolation (NOT emitted to central SIEM per ADR-040 v0.4 §3.20.6 PII-redaction). SIEM payload carries only operator_note_redacted=true. ENG-784 protovalidate: ≤2048-byte cap on operator_note (matches reason caps). |
ome.v1.RevokeSignerPubResponse
RevokeSignerPubResponse — output from OMEService.RevokeSignerPub per ADR-040 v0.4 §3.20.3.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | succeeded | bool | — | True on successful state transition; false on idempotent (already-revoked) ack path (paired with OSY-MEM-5126 in the failure case). |
| 2 | revoked_at | google.protobuf.Timestamp | — | Server-side wall-clock at the UPDATE commit. Distinct from the request's OPA-gate timestamp. |
| 3 | last_active_key_warning | bool | — | True iff this revocation transitioned the workspace's ONLY active key. The workspace is now offline for Verified Memory tier until a new key is provisioned via RotateMGuardSigningKey. The CRITICAL audit event provides post-hoc accountability (no 2-person approval required per ADR-040 v0.4 §3.20.10 orchestrator-locked decision Q4). |
| 4 | event_sequence_number | string | — | SignerPubChangeEvent sequence_number assigned for cross-region propagation tracking. Allocated atomically from signer_pub_change_event_sequence (per ADR-040 v0.4 §3.20.9 / V13 migration). Encoded as string (NOT uint64) to dodge JSON-number-precision issues at JSON-bridging consumers (frontend admin UI). Edge subscribers parse to uint64. |
ome.v1.RootAttestation
ENG-2157 — root trust attestation for VerifyWitness (ADR-152 / ADR-153). Server-stamped; carries the re-derivation receipt so a third party holding the workspace's signed root history recomputes the same SERVER_ANCHORED verdict (WIRE-TRUTH / GV-6 — a claim with evidence, never a trusted boolean).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | level | RootAnchorLevel | — | |
| 2 | anchored_sequence_no | uint64 | — | Re-derivation receipt — populated iff level == ROOT_ANCHOR_LEVEL_SERVER_ANCHORED. anchored_sequence_no is the workspace_jmt_root_history.sequence_no of the matched root (NOT the witness's unrelated ADR-008 epoch field). |
| 3 | anchored_era_index | uint32 | — | era_index of the matched root — a freshness signal for the caller's policy, NOT a reject gate (membership in ANY era refutes a fabricated root). |
| 4 | anchored_committed_at_unix_ms | int64 | — | committed_at of the matched root (Unix milliseconds). |
ome.v1.SetTransparencyPublicReadRequest
Request for admin RPC to toggle workspace opt-in.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | workspace_id | string | — | The workspace to mutate. UUIDv4 string. ENG-784 protovalidate: UUID form. |
| 2 | enabled | bool | — | Desired new value of workspace_settings.transparency_public_read. |
| 3 | actor_did | string | — | The admin actor's DID URI. Captured RAW in the audit event (admin trail). ENG-784 protovalidate: DID URI pattern + ≤512-byte cap. |
| 4 | justification | string | — | Free-form justification (required by CEO directive 2026-05-24). Capped server- side at 2048 UTF-8 bytes; stored as SHA-256 on the settings row; verbatim in the audit event. ENG-784 protovalidate: ≤2048-byte cap (matches server-side cap). |
ome.v1.SetTransparencyPublicReadResponse
Response confirms the mutation and carries the Edge cache-invalidation moment.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | updated | bool | — | TRUE if the row was actually updated (FALSE if the value was already at the requested state — idempotent no-op). |
| 2 | effective_at_unix_ms | int64 | — | The wall-clock moment of the row update (or now() if updated=false). Edge LRU cache invalidates on workspace_settings_version bump; this is informational. |
ome.v1.SiblingLevel
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | slots | bytes | repeated | Exactly 16 entries; each 32 bytes (zero for empty slot). |
ome.v1.SignAndInsertRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim | Claim | — | The unsigned Claim envelope. Server computes content_hash transitively via SHA-256(canonical body) per OAP-MEM §4.1. The request-supplied Claim.workspace_id MUST equal the per-connection GUC-bound workspace (5310 WBW binding mismatch on disagreement); other fields are signed verbatim. ENG-784 protovalidate: claim is required. |
| 2 | signer_key_ref | string | — | DEPRECATED (ENG-783 / ADR-035). Use the structured key_source oneof at tags 4-5 instead — same semantics as SignRequest.key_source. See the SignRequest message above for the full deprecation contract, the regex format guarantees, and the V1.5 hsm_key_handle reservation. The dual-form rejection (both signer_key_ref and key_source populated → OSY-MEM-5310) applies here identically; the server treats both messages through a shared resolver per AP00011-ome-service §4.7. ENG-784 protovalidate: ≤512-byte cap (same DoS guard as the legacy form on SignRequest.signer_key_ref). |
| 3 | signer_pub_hint | bytes | optional | Optional caller-pre-resolved signer pubkey hint (performance only; server cross-checks against the canonical pubkey resolved from the issuer DID + signer_key_ref before populating SignedClaim.signer_pub). Same SECURITY CONTRACT as SignRequest.signer_pub_hint. ENG-784 protovalidate: when set, MUST be 32 bytes (Ed25519 raw pubkey). optional keyword auto-tracks presence → unset path skips validation. |
| 4 | kms_key_id | string | — | |
| 5 | secrets_manager_secret_arn | string | — | DEPRECATED + UNSUPPORTED for claim signing (ENG-3373 / ADR-374). Same contract as SignRequest.secrets_manager_secret_arn: production custody is KMS-only (ADR-040); the server REJECTS this arm with OSY-MEM-5149 and never maps the ARN onto the KMS key. Populate kms_key_id. Removed at v1.0 freeze. |
| 7 | idempotency_key | string | optional | ENG-2256 / D2 (idempotency, CEO-ratified 2026-06-13): optional caller-supplied idempotency token. When set, the server de-duplicates on the composite key (workspace_id, idempotency_key) via a PERMANENT unique constraint — mirroring the live WorkspaceCryptoErasure uq_cee_idem precedent, NOT a TTL window. A replay with the same {workspace_id, idempotency_key} returns the originally-inserted SignedClaim + sets idempotency_replayed=true, and does NOT re-sign or double-insert into the claim table / JMT. This covers retry-with-a-FRESH-claim_id, which the existing ON CONFLICT(workspace_id, claim_id) UPSERT does not cover. The token is an OPAQUE client-chosen string: SDKs SHOULD derive a STABLE per-record key (e.g. SHA-256(workspace_id||source||source_id|| content_hash)) so logical retries dedup; a random UUIDv7 also works for at-least-once callers. The field is deliberately NOT constrained to UUID so the content-derived form is accepted. ENG-784 protovalidate: 1..128 bytes when present. |
ome.v1.SignAndInsertResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | signed_claim | SignedClaim | — | The signed claim envelope (post-sign, pre-projection sanitization — surfaced to the caller for return-value parity with the legacy two-call flow). Carries the full SignedClaim shape (sig + signer_pub included) because the caller will see them returned by the legacy Sign RPC; preserving the same shape on the fused RPC keeps the SDK migration path simple. |
| 2 | encoded_cbor | bytes | — | Form B canonical-CBOR encoding of the signed claim (mirror of SignResponse.encoded_cbor). |
| 3 | new_root | bytes | — | 32-byte JMT root AFTER the insert (mirror of InsertResponse.new_root). Callers use this to chain a subsequent Prove or to track JMT root history client-side. |
| 4 | projection | ClaimProjection | — | Sanitized projection of the now-persisted claim. This is what the Edge GraphQL writeClaim mutation surfaces to the FE — it has exactly the field shape of {@code OsymemClaim} in osymem.graphql. |
| 5 | idempotency_replayed | bool | — | ENG-2256 / D2: true iff this response was served from an idempotent replay — i.e. the request's idempotency_key matched a prior insert and the server returned the ORIGINAL SignedClaim WITHOUT re-signing or re-inserting. false (default) on the first / non-idempotent insert. |
ome.v1.SignRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim | Claim | — | ENG-784 protovalidate: claim is required (must be set on the wire). |
| 2 | signer_key_ref | string | — | DEPRECATED (ENG-783 / ADR-035). Use the structured key_source oneof at tags 4-5 instead. This free-form string carries path-traversal and cross- workspace enumeration risk (see ADR-035 §Risk). Retained on the wire so pre-v0.2 SDKs (AP00013 Python ≤v0.1, AP00014 TypeScript ≤v0.1) continue to interop until the v1.0 wire freeze; the server MUST: (a) prefer key_source when set (5310 OSY-MEM-5310 if both forms are populated — caller bug); (b) accept this legacy field if key_source is unset, emit an audit event tagged signer_key_ref.deprecated=true, and log a deprecation-warn line via osyra-response-common. Removal is gated on v1.0 wire freeze + the AP00013/AP00014 SDKs cutting a release that emits the oneof exclusively. ENG-784 protovalidate: ≤512-byte cap (DoS guard on the legacy free-form form; the structured key_source oneof at tags 4-5 carries its own tighter regex constraints via ENG-784 protovalidate annotations). |
| 3 | signer_pub_hint | bytes | optional | Optional: caller-pre-resolved signer pubkey (skip the DID-resolve round-trip if the Edge Gateway already cached it). Field unset → server resolves the pubkey from the issuer DID itself. SECURITY CONTRACT: the server MUST treat this field as a PERFORMANCE HINT ONLY. The server MUST resolve the issuer DID to the canonical pubkey via IAM ResolveDid (or KMS-key metadata) and verify that signer_pub_hint == canonical_pubkey before populating SignedClaim.signer_pub from the hint. Otherwise an attacker-supplied hint could be embedded in the SignedClaim's signer_pub field and mislead a future downstream verifier on the in-band trust path. ENG-784 protovalidate: when set, MUST be 32 bytes (Ed25519 raw pubkey). optional keyword tracks presence — protovalidate auto-skips zero-value (unset) so no explicit ignore = IGNORE_IF_ZERO_VALUE is needed. |
| 4 | kms_key_id | string | — | |
| 5 | secrets_manager_secret_arn | string | — | DEPRECATED + UNSUPPORTED for claim signing (ENG-3373 / ADR-374). Production signing custody is KMS-wrapped per-workspace (ADR-040); no deployment profile implements a durable, workspace-bound Secrets Manager signer. The server REJECTS this arm at the RPC boundary with OSY-MEM-5149 (INVALID_ARGUMENT) and MUST NOT map the ARN onto the standard KMS key. Populate kms_key_id instead. Scheduled for hard removal (this tag becomes reserved) at the v1.0 wire freeze; callers MUST NOT send it. |
ome.v1.SignResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | signed_claim | SignedClaim | — | |
| 2 | encoded_cbor | bytes | — | Form B canonical-CBOR encoding of the signed claim. Bit-identical to the Go reference impl in osyra-labs/prototypes/osymem/ (archived). The §12.6 cross-language contract test (downstream of new common-libs creation) verifies byte-equality across Go ↔ Java ↔ Python ↔ TypeScript implementations. |
ome.v1.SignedClaim
A Claim wrapped with an Ed25519 signature; the on-the-wire form.
OAP-MEM v0.1 §4.2 wire-key mapping. SignedClaim fields are 1:1 between proto and CBOR today, but encoders MUST go through the canonical osyra-claims-common mapping artifact (github.com/osyra-ai/osyra-claims-common per ADR-027; spec/CLAIM_FIELD_MAPPING.md; owner ENG-715) to lock in this contract — a future rename of any of these proto fields MUST also update the encoder mapping.
Proto field → OAP-MEM CBOR key ───────────────────────────────── claim → "claim" sig_alg → "sig_alg" sig → "sig" signer_pub → "signer_pub"
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim | Claim | — | |
| 2 | sig_alg | string | — | Algorithm identifier; "Ed25519" is the only V1 value. Forward-compat gating — V2 may introduce post-quantum hybrid (Ed25519 + ML-DSA-65) per design §1.4 V2. |
| 3 | sig | bytes | — | 64-byte Ed25519 signature over the canonical CBOR Form B preimage. ENG-784 protovalidate: exact 64-byte length (Ed25519 raw signature). |
| 4 | signer_pub | bytes | — | 32-byte Ed25519 public key. Optional post-ADR-008: out-of-band trust-anchor lookups (via IAM ResolveDid) are preferred over in-band signer_pub. ENG-784 protovalidate: when populated, MUST be exactly 32 bytes (Ed25519 raw pubkey). Empty bytes (proto3 default) is the "not populated" case; ignore = IGNORE_IF_ZERO_VALUE skips validation on the empty/default case. This field is NOT optional, so we set the ignore option explicitly. Per SignedClaim's pre-ENG-784 docstring this matches the original v1 intent (Buf v1's empty buf.lock blocked the IGNORE_IF_UNPOPULATED enum resolution; v2 dep resolution is clean). |
ome.v1.SignerPubChangeEvent
SignerPubChangeEvent — v0.4 13-field LOCKED wire contract per ADR-040 v0.4 §3.4.3.
Three event_type variants: ROTATED — emitted by RotateMGuardSigningKey: pub_old → retired, pub_new → active. revocation_reason MUST be UNSPECIFIED; signerpub_revoked_at_unix_ms MUST be 0. REVOKED — emitted by RevokeSignerPub: target row → revoked terminal state. revocation_reason MUST be COMPROMISE/POLICY_CHANGE/OPERATOR_PUSHED. signerpub_revoked_at_unix_ms MUST be non-zero. KEK_REVOKED — emitted by ADR-016 KEK cascade: ALL workspace rows → revoked. revocation_reason MUST be KEK_CASCADE. signerpub_revoked_at_unix_ms MUST be non-zero. signer_did MAY be empty if unrecoverable at cascade time.
Edge consumers MUST validate the (event_type, revocation_reason) tuple at parse-time and reject mismatches with structured error before any cache mutation.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | ds_tag | string | — | MUST be "osyra-ome-signerpub-change-v1" exactly (29 bytes UTF-8); preimage[0]. |
| 2 | event_type | EventType | — | |
| 3 | workspace_did | string | — | Workspace DID (e.g., "did:osyra:ws:{ws_uuid}"). |
| 4 | signer_pub | bytes | — | 32-byte raw Ed25519 pubkey (RFC 8032). |
| 5 | effective_at_unix_ms | uint64 | — | When the change takes effect (cache eviction time). uint64 Unix-ms for signed-preimage canonicalization (cross-SDK byte-equality). |
| 6 | source_region | string | — | AWS region designator of the emitter (e.g., "us-east-1"). |
| 7 | sequence_number | uint64 | — | Monotonic per (source_region, workspace_did) tuple. Allocated by signer_pub_change_event_sequence table (ADR-040 v0.4 §3.20.9, V13 migration). |
| 8 | emitted_at_unix_ms | uint64 | — | When the event was emitted (NOT when it takes effect). |
| 9 | ome_service_signer_pub | bytes | — | OME service identity (distinct from per-workspace MGUARD keys). Multi-region KMS key per ADR-040 v0.4 §3.20.7. Dev/staging: MAY be empty (UNSIGNED emit path). Prod: MUST be non-empty (ProductionStartupGuard enforces). |
| 10 | ome_service_sig | bytes | — | Ed25519 signature over canonical_cbor preimage: [tstr(ds_tag), event_type, workspace_did, signer_pub, effective_at_unix_ms, source_region, sequence_number, emitted_at_unix_ms, ome_service_signer_pub, signer_did, revocation_reason, signerpub_revoked_at_unix_ms] Signed-preimage canonicalization rules per §1.6 (uint64 Unix-ms; bytes raw). Dev/staging: MAY be empty bytes (UNSIGNED). Prod: MUST be non-empty. |
| 11 | signer_did | string | — | Per ADR-061: did:osyra:ws:{ws_uuid}:signer:{signer_uuid} (4-segment DID). REQUIRED for ROTATED + REVOKED events. MAY be empty ("") for KEK_REVOKED cascade if signer_did is unrecoverable at cascade time. Consumers MUST tolerate empty for KEK_REVOKED only and reject empty for ROTATED/REVOKED with a structured error. |
| 12 | revocation_reason | RevocationReason | — | ONLY populated when event_type ∈ {REVOKED, KEK_REVOKED}. UNSPECIFIED (0) for ROTATED events. Consumers MUST validate the (event_type, revocation_reason) tuple at parse-time. Mismatches (e.g., ROTATED + non-UNSPECIFIED, or REVOKED + UNSPECIFIED) MUST be rejected without any cache mutation. |
| 13 | signerpub_revoked_at_unix_ms | uint64 | — | ONLY populated when event_type ∈ {REVOKED, KEK_REVOKED}; 0 for ROTATED. Distinct from effective_at_unix_ms which records WHEN the event is APPLIED (causality: effective_at_unix_ms ≥ signerpub_revoked_at_unix_ms). Mirrors the workspace_mguard_signing_key.signerpub_revoked_at TIMESTAMPTZ column from V6 migration. |
Nested types: ome.v1.SignerPubChangeEvent.EventType
ome.v1.SubjectBundleManifestProto
Server-side echo of the .ome-subject bundle's signed manifest, surfaced in the first stream chunk so the client can validate workspace identity + content type + SHA anchors BEFORE consuming the raw ZIP payload chunks.
All fields are populated from the SubjectBundleExportResult (server side). The client SHOULD verify:
- content_type == "application/vnd.osyra.ome.subject-bundle.v1+zip"
- bundle_sha256 over the reassembled ZIP bytes matches this field
- manifest_sha256 over the extracted manifest.cbor matches this field
- signer_pub matches the workspace's published Ed25519 public key (extractable from any Claim's signature chain in the bundle)
- subject_did_hash matches SHA-256(dsTag || 0x00 || workspace_id || subject_did) if the client wishes to bind a known DID to this artifact
These are the same wire-freeze quantities the ome-subject-spec-freeze-gate
CI workflow byte-checks across platforms (spec §10).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bundle_sha256 | bytes | — | SHA-256 of the complete .ome-subject.zip bytes. 32 bytes raw. |
| 2 | manifest_sha256 | bytes | — | SHA-256 of the manifest.cbor ZIP entry bytes. 32 bytes raw. |
| 3 | signature_sha256 | bytes | — | SHA-256 of the 64-byte Ed25519 signature in bundler.sig. 32 bytes raw. |
| 4 | bundle_bytes | uint64 | — | Total size of the .ome-subject.zip bundle in bytes (echo for client sanity). |
| 5 | n_direct_claims | uint64 | — | Number of direct-match Claims embedded in the bundle (claims/.cbor count). |
| 6 | n_transitive_parents | uint64 | — | Number of transitive-parent Claims embedded in the bundle (parents/.cbor count). |
| 7 | signer_pub | bytes | — | Raw 32-byte Ed25519 public key the manifest was signed under (workspace signing key per ADR-040 — same key that signed each individual Claim). |
| 8 | content_type | string | — | Bundle's content_type label (spec §5.1). Always "application/vnd.osyra.ome.subject-bundle.v1+zip" for v1.0. |
| 9 | subject_did_hash | bytes | — | 32-byte SHA-256 of subject identity binding: SHA-256(dsTag_bytes || 0x00 || workspace_id_16_bytes || subject_did_utf8) Offline-recomputable by the verifier. NOTE: raw subject_did is NOT on the wire's transport surfaces — only this hash. The Manifest body inside the ZIP necessarily contains the raw subject_did (it is the artifact's organising principle); the hash here on the gRPC manifest-chunk lets intermediaries cross-reference without re-exposing PII to logs. |
| 10 | jmt_root_hex | bytes | — | 32-byte raw JMT root at proof-snapshot time. Per-claim proofs in the bundle's proofs/*.proof entries validate against THIS root. |
| 11 | jmt_snapshot_at_ms | int64 | — | Unix milliseconds — wall-clock when the bundler took the JMT snapshot. |
ome.v1.SurfacedContradiction
A surfaced merge contradiction (decoded view of an ommp-audit-entry): the LOSING
assertion kept as a tombstone + the loser→winner superseded_by edge. Shared by
MergeArchivesResponse + VerifyMergeReceiptResponse (the recomputed echo).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | subject | string | — | |
| 2 | predicate | string | — | |
| 3 | tombstone_value | string | — | |
| 4 | tombstone_origin | string | — | the loser's canonical_text |
| 5 | superseded_by | bytes | — | the loser's origin vendor (the c349 tiebreak axis) |
ome.v1.TombstoneRequest
ENG-583: GDPR Art. 17 right-to-erasure request.
reason_detail is a free-text DSAR / ticket / case reference, capped at 256
characters server-side. It is never logged in plaintext to the audit
pipeline — the audit event carries only SHA-256(reason_detail) in the
reason_detail_hash payload field. PII MUST NOT be included in reason_detail
(callers should reference DSAR/case IDs, not personal data).
actor_id is an optional override; default = MDC userId resolved from the
caller JWT sub. Used for forensic attribution in the audit event.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | ENG-784 protovalidate: exact 16-byte UUIDv7. |
| 2 | reason_code | TombstoneReasonCode | — | ENG-784 protovalidate: required enum (UNSPECIFIED=0 rejected at app layer per OSY-MEM-5184); the proto-layer not_in: [0] enforces it before the gRPC call. |
| 3 | reason_detail | string | — | ENG-784 protovalidate: ≤256 UTF-8 bytes (matches docstring cap; hashed server-side). |
| 4 | actor_id | string | — | ENG-784 protovalidate: ≤512-byte cap (DID URI form or opaque user-id). |
ome.v1.TombstoneResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | new_root | bytes | — | |
| 3 | era_index | uint32 | — | workspace_jmt_root after tombstone FIELD 2 INTENTIONALLY RESERVED — was bytes salt pre-ENG-583. Exposing the salt on the wire during an active era reconstructs the dictionary-attack surface ADR-016 closes (§Decision lines 98-119). Removed by ENG-583 B-1/sec. |
| 4 | redacted_at | google.protobuf.Timestamp | — | |
| 5 | audit_correlation_id | string | — | |
| 6 | tombstoned_at_sequence | uint64 | — | |
ome.v1.TombstoneWitness
Tombstone witness for a redacted chain node. Mirrors ENG-583 / ENG-584 tombstone- aware reader pattern: the witness proves what WAS redacted without leaking the pre-redaction body. actor_did_hash is the SHA-256 of the redacting actor's DID (workspace-binding domain-separated) to prevent operator-enumeration.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tombstoned_at_unix_ms | int64 | — | |
| 2 | reason_code | string | — | |
| 3 | actor_did_hash | bytes | — | GDPR_ART_17 | SUBJECT_REQUEST | LEGAL_HOLD | OPERATOR |
ome.v1.TraceProjection
TraceProjection — the queryable indexed projection of a committed trace (design §4). It is recomputable from the signed CBOR (the source of truth), so a DB-row tamper is caught on offline re-verify. The PRODUCER commitments (prompt_hash/output_hash/…) and retrieved_memory live in the signed CBOR, reachable via ExportTraceBundle — they are NOT re-projected here (the projection is the cheap query surface, not the full body).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | trace_id | bytes | — | 16-byte UUIDv7 trace id. |
| 2 | workspace_id | string | — | Workspace UUID — server-stamped from the GUC identity; always the caller's workspace. |
| 3 | trace_hash | bytes | — | SHA-256 Form-B link identity (32 bytes). |
| 4 | broker_request_id | string | — | Model-broker request identity. |
| 5 | model_id | string | — | Resolved model id. |
| 6 | ts | uint64 | — | Attested capture timestamp, Unix milliseconds. |
| 7 | epoch | uint64 | — | Store-currency stamp. |
ome.v1.TransparencyWitness
JMT witness anchor for the chain's bound era. Edge embeds this in response.witness. Verifier semantics: ome_jmt_root_hex anchors the workspace JMT at snapshot moment; verdict carries the chain-quality verdict (PASS / QUARANTINED / TOMBSTONED).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | ome_jmt_root | bytes | — | |
| 2 | ome_jmt_snapshot_at_unix_ms | int64 | — | 32 bytes |
| 3 | verdict | string | — | |
ome.v1.VerifiedMemoryReceiptProjection
Per-receipt sanitized projection (AC2). The ONLY fields surfaced to the
edge gateway + frontend dashboard. Maps 1:1 to
AP00001-edge VerifiedMemoryReceiptNode in verified_memory.graphql.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | receipt_id | string | — | Lowercase hex SHA-256 of the outer envelope bytes (64 chars). |
| 2 | emitted_at_unix_ms | int64 | — | Emission timestamp from envelope.emitted_at_unix_ms. |
| 3 | purpose_did | string | — | |
| 4 | retriever_did | string | — | |
| 5 | workspace_did | string | — | |
| 6 | ome_jmt_anchor | bytes | — | 32-byte OME JMT anchor commitment (not a secret). |
| 7 | query_commit | bytes | — | 32-byte query commitment. |
| 8 | verdict | VerifiedMemoryVerdict | — | Server-computed verdict per ADR-050. |
| 9 | deny_reason | string | optional | Optional human-readable deny reason. Populated only when verdict=FAIL (V2 re-verification-on-read path); always absent on V1 row inserts. |
| 10 | receipt_verified | bool | — | Strict boolean from VerifyOutcome.Verified. V1: always TRUE on insert (OME emits its own valid signature). |
| 11 | facts | RetrievedFactProjection | repeated | Per-fact sanitized projection. |
| 12 | l_meet | LMeetProjection | — | L_meet operator witness (sanitized — raw proof bytes never on wire). |
ome.v1.VerifyBundleRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bundle_zip | bytes | — | ENG-784 protovalidate: ≤500 MB cap (524288000 bytes) per PR #2 spec. Zip-bomb defense remains a server-side concern (the post-decode expansion ratio is what kills you — proto-layer cap only bounds upload size). |
| 2 | trust_anchors | bytes | repeated | BYO trust anchors. If non-empty, audit_mode MUST also be true; otherwise the server rejects with OSY-MEM-5310 (WBW_BINDING_MISMATCH). Empty (and audit_mode=false) → server uses the workspace's pinned anchors from the placement-service registry. ENG-784 protovalidate: each anchor is a 32-byte Ed25519 pubkey; ≤64 anchors (DoS guard — the cross-validation cost scales O(anchors × claims)). |
| 3 | audit_mode | bool | — | When true, allows trust_anchors override and requires the caller to hold an audit-mode authz scope (server-side check). Default false → workspace pinned anchors (ignores trust_anchors). Per /osyra-security H6 PR #2 review: this surfaces the privilege boundary at the API layer so a standard caller cannot accidentally pass attacker-supplied anchors. |
ome.v1.VerifyBundleResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | reason | string | — | |
| 3 | manifest | BundleManifest | — | |
| 4 | anchors_used | bytes | repeated | Trust anchors actually used in the verification (echo). Allows downstream consumers (audit log, compliance dashboard) to verify which trust set produced the verdict. Equal to either VerifyBundleRequest.trust_anchors (when audit_mode=true) or the workspace's pinned anchors. Per /osyra-security H6 PR #2 review. |
ome.v1.VerifyCanonicityRequest
Request for VerifyCanonicity. The workspace is SERVER-AUTHORITATIVE (OS-Workspace-ID header → ome.workspace_id GUC) and the seq/epoch floor is server-anchored — NEITHER is carried here (a caller-supplied floor would defeat anti-truncation, ADR-330 §6).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | receipt_envelope | bytes | — | The on-wire omlc.v1 COSE_Sign1 EAT envelope to re-decide (the body rides the opaque receipt_body claim). ≤64 KiB body cap (the family-wide DoS body bound). |
| 2 | signer_pub | bytes | — | The relying-party-PINNED OME index Ed25519 public key the envelope COSE_Sign1 is verified against (ROOT_SIG). 32 raw bytes. |
| 3 | witnesses | OmlcLogWitness | repeated | The SUPPLIED complete authorized log (the honest-but-reverifiable issuer control — ADR-330 §2). DoS-bounded: > MAX_LOG_ENTRIES entries OR > the byte-size bound fails closed OMLC_LOG_TOO_LARGE. Re-derivation is over an epoch-windowed/checkpointed sub-log. |
| 4 | immutable_keys | string | repeated | The relying-party-held contradiction bundle (TWO views — the predicate's key sets + the digest below). The verifier RE-RUNS this predicate during CANONICITY (never trusts an issuer "admitted" flag) and pins its digest via POLICY_PINNED. |
| 5 | monotonic_keys | string | repeated | |
| 6 | policy_cid | bytes | — | The relying-party-pinned AP00019 contradiction-bundle digest (32 bytes). POLICY_PINNED: body.policy_cid MUST equal this. |
ome.v1.VerifyCanonicityResponse
VerifyCanonicity verdict — the re-decision outcome. accepted=false with a non-OK
reason (an OMLC_* band reason, e.g. "OMLC_CANONICITY") is a RESULT (a fail-closed
reject), NOT a transport error.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | accepted | bool | — | |
| 2 | reason | string | — | |
| 3 | detail | string | — | |
| 4 | server_epoch_floor | uint64 | — | The SERVER-ANCHORED seq/epoch floor applied (from workspace_jmt_root.sequence_no). |
| 5 | committed_max_seq | uint64 | — | The receipt body's committed max_seq (== epoch); 0 if the body did not decode. |
ome.v1.VerifyFullRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB. |
| 2 | body | bytes | optional | Optional: caller-supplied body for content-hash verification. Field unset (proto3 default — distinguished via optional) → server skips the H(body) == content_hash check (signature-only verify). An empty bytes value (b"") is NOT equivalent to unset — it means "verify against the empty-body content hash" and the server will reject if content_hash != H(b""). |
| 3 | signer_did | string | optional | ENG-569 — Optional signer DID for out-of-band pubkey resolution via AP00002-iam-service.IAMDidService.ResolveDID. When set, the server resolves the active public keys for this DID and verifies the signature under one of them; the verifier MUST cross-check that any in-band SignedClaim.signer_pub equals the resolved pubkey (forgery defense). When unset, the server falls back to the in-band SignedClaim.signer_pub (legacy pre-ADR-008 path, deprecation-warn logged). Format: did:osyra:ws:{workspace_uuid_v4}:signer:{signer_uuid_v4} (lowercase hex). Mismatch → OSY-MEM-DID-5320 (unresolved). |
ome.v1.VerifyGrantRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | Form B canonical-CBOR signed grant (dsTag: "osyra-ome-grant-v1"). ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB. |
ome.v1.VerifyGrantResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | reason | string | — | |
| 3 | source_workspace_id | string | — | OSY-MEM-5302 if cross-org in V1 |
| 4 | target_workspace_id | string | — | |
ome.v1.VerifyInBandRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB. |
ome.v1.VerifyMergeReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | merge_receipt | bytes | — | The EAT-hosted Merge Receipt (COSE_Sign1) to re-decide. |
| 2 | input_archives | bytes | repeated | The input OMP archives the receipt binds — re-decision recomputes the merge over these and forces claim == recompute. Order-tolerant; ≤64 (DoS guard). |
| 3 | signer_pub | bytes | — | The relying-party-pinned merger Ed25519 public key (32 bytes) the COSE_Sign1 is verified under (relying-party pins the trust anchor; not read from the envelope). |
ome.v1.VerifyMergeReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | True iff the COSE_Sign1 verifies, the content-addressed nonce binds, the input ids match, and the recomputed live+audit digests/counts equal the receipt's claim. |
| 2 | reason | string | — | |
| 3 | recomputed_contradictions | SurfacedContradiction | repeated | OSY-EAT-6390..6399 on failure The INDEPENDENTLY-recomputed audit set (decoded view) on a valid re-decision. |
ome.v1.VerifyProofRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | root | bytes | — | ENG-784 protovalidate: 32-byte JMT root. |
| 2 | claim_id | bytes | — | ENG-784 protovalidate: 16-byte UUIDv7. |
| 3 | value_hash | bytes | — | ENG-784 protovalidate: 32-byte SHA-256 digest. |
| 4 | proof | JMTProof | — | ENG-784 protovalidate: proof message required. |
ome.v1.VerifyProofResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
ome.v1.VerifyResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | reason | string | — | OSY-MEM-NNNN error code on failure (empty when valid=true). |
| 3 | resolved_claim | Claim | — | Decoded Claim for caller convenience (avoids re-decoding encoded_cbor). Populated for both valid and invalid responses. |
| 4 | osyra_retrieval_receipt | bytes | — | VM-4 (ENG-1042) — populated for PRO/ENTERPRISE-tier workspaces with the canonical-CBOR-encoded osyra-receipt-envelope-v1 wrapper (per ADR-039 v0.2 §1 mandatory envelope contract). FREE/STARTER-tier workspaces and any request without the os-workspace-tier header set to a receipt-enabled tier receive proto3 default (empty bytes) — byte-equivalent to pre-ENG-910 wire format per ENG-1042 AC8 FreeTierByteEqualityTest. Wire authority: ADR-039 v0.2 envelope format with inner_ds_tag = "osyra-ome-mguard-v1" + freshness contract (180d MaxAge / 5min MaxSkew). Decode via osyra-mguard-common OsyraReceiptEnvelopeCodec. ENG-2279 Task 5: renamed mguard_retrieval_receipt → osyra_retrieval_receipt (Tier-1 trade-secret-vocabulary rename per docs/RENAME-PLAN-v1.0.md). Field NUMBER 4 is PRESERVED — this is a name-only change, binary-wire-compatible (protobuf wire uses field numbers, not names). The inner_ds_tag string "osyra-ome-mguard-v1" is an unchanged wire-format crypto constant, not the field name. |
ome.v1.VerifyRetrievalHit
VerifyRetrievalHit is one per-hit re-decision (ai.osyra.ome.osyidx.OsyidxDecision): the item id, whether it was admitted (passed all legs), and the OSY-OSYIDX-84xx reason code + descriptive string.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | item_id | string | — | |
| 2 | admitted | bool | — | |
| 3 | reason_code | string | — | |
| 4 | reason | string | — | |
ome.v1.VerifyRetrievalRequest
VerifyRetrievalRequest carries the osyidx.v1 receipt body + detached disclosure witnesses to re-decide, plus the relying-party PINNED inputs: the index public key (32-byte Ed25519, never receipt-supplied) the manifestSig is verified under, and the consumer freshness high-water-mark. workspace is the AUTHORITATIVE OS-Workspace-ID identity (server-resolved), never a request field.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | body_bytes | bytes | — | |
| 2 | witness_bytes | bytes | — | |
| 3 | index_public_key | bytes | — | |
| 4 | hwm | int64 | — | |
ome.v1.VerifyRetrievalResponse
VerifyRetrievalResponse mirrors ai.osyra.ome.osyidx.OsyidxReDecision plus the manifest commitments (index_id / manifest_ver / manifest_root, decoded from the osyidx body) for the FE viewer. manifest_accepted = manifestSig AND fresh (the HWM-advance state); hwm_after == hwm_before on a stale/forged manifest (monotone, never rewinds).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | manifest_accepted | bool | — | |
| 2 | manifest_reason | string | — | |
| 3 | hwm_before | int64 | — | |
| 4 | hwm_after | int64 | — | |
| 5 | index_id | string | — | |
| 6 | manifest_ver | int64 | — | |
| 7 | manifest_root | bytes | — | |
| 8 | admitted_item_ids | string | repeated | |
| 9 | trace | VerifyRetrievalHit | repeated | |
ome.v1.VerifyTokenCapitalRequest
Request for VerifyTokenCapital. The workspace is server-authoritative
(OS-Workspace-ID header → ome.workspace_id GUC), NOT carried here — it is the
verified ws the body's LEG0 tenant binding (key 2) is checked against.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | otcc_body | bytes | — | The canonical-CBOR otcc.v1 receipt body (otcc-v1.cddl otcc-body, keyasint keys 1..13) to re-decide. The body commits ensemble_cid/bench_cid (resolved against the OME corpus) + the signed Δ + the FROZEN digests. ≤64 KiB (the family-wide DoS body cap; the body is a small fixed-shape map). |
| 2 | epoch_floor | uint64 | — | OPTIONAL relying-party currency floor: a committed epoch < this is rejected OTCC_EPOCH_STALE (replay). 0 (default) = no floor pinned. |
| 3 | max_tolerance | uint64 | — | OPTIONAL largest epsilon_ppm accepted for a TOLERANCE cert (the relying party's max_tolerance). A TOLERANCE cert with ε > this is rejected OTCC_EPSILON_RANGE. 0 (default) ⇒ accept EXACT only (any ε>0 TOLERANCE cert is out of range). |
| 4 | max_rederivation_cost | uint64 | — | OPTIONAL tighter LEG3 DoS ceiling on the |members|·|B| re-derivation cost. 0 (default) ⇒ the server default (100M member·item products). |
ome.v1.VerifyTokenCapitalResponse
VerifyTokenCapital verdict — the re-decision outcome. accepted=false with a
non-OK reason is a RESULT (a fail-closed reject), NOT a transport error.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | accepted | bool | — | Whether every rung passed (ACCEPT) or the first rung failed (REJECT). |
| 2 | reason | string | — | The OTCC reject reason on a REJECT (the FIRST failing rung, identical to the Go re-decider's reason text, e.g. "OTCC_GAIN_DIVERGED"); "OK" on ACCEPT. The OSY-OTCC-8900-8999 numeric band is reserved-not-minted at GA. |
| 3 | detail | string | — | A non-sensitive diagnostic (never echoes raw weights / secrets). |
| 4 | determinism_class | int64 | — | The body's determinism_class (0 EXACT / 1 TOLERANCE). -1 if the body did not decode (a pre-decode shape/canonical/version reject). |
| 5 | epsilon_ppm | int64 | — | The body's committed epsilon_ppm (0 for EXACT). -1 if the body did not decode. |
| 6 | rederivation_ran | bool | — | Whether a forward pass actually ran (LEG3 reached) — gates rederived_delta_ppm. |
| 7 | rederived_delta_ppm | int64 | — | The re-derived Δ' (NEVER the issuer's signed value). Meaningful only when rederivation_ran is true; on an ACCEPT it equals the committed Δ within the class tolerance. |
| 8 | rederivation_cost | uint64 | — | The O(|members|·|B|) forward-pass cost the relying party paid (0 if not reached). The DoS budget surface (ADR-270). |
ome.v1.VerifyWithPubkeyRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB (matches Claim.body cap; empty bytes are a structural failure since no valid canonical-CBOR is 0-len). |
| 2 | signer_pub | bytes | — | ENG-784 protovalidate: exact 32-byte Ed25519 pubkey. |
ome.v1.VerifyWitnessRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB. |
| 2 | signer_pub | bytes | — | ENG-784 protovalidate: exact 32-byte Ed25519 pubkey. |
| 3 | expected_root | bytes | — | ENG-784 protovalidate: exact 32-byte JMT root. |
| 4 | min_epoch | uint64 | — | |
| 5 | max_epoch | uint64 | — | |
| 6 | root_anchoring | RootAnchoringMode | — | ENG-2157 — opt-in server-anchored root verification mode. UNSPECIFIED(0)/OFFLINE(1): the offline/portable contract, byte-for-byte unchanged — witness.root() is compared ONLY to the caller-supplied expected_root (the signer is still bound to the workspace trust anchors per WITNESS-1 / #187). SERVER_ANCHORED(2): ALSO require witness.root() to be a member of the GUC-bound workspace's append-only, server-attested JMT root history; fail-closed OSY-MEM-5214 (root not anchored) on no-match, OSY-MEM-5215 (server-anchoring not enabled) if the arm is not wired. The mode NEVER weakens the signer binding. SERVER_ANCHORED resolves the workspace from the OS-Workspace-ID header (MDC), NEVER the request body — so it is inherently same-workspace. Cross-workspace / portable verification is NOT supported under SERVER_ANCHORED; use OFFLINE for portability across workspace boundaries. See ADR-152 + design doc AP00011-OME-WITNESS-ROOT-ANCHORING-DESIGN.md. |
ome.v1.VerifyWitnessResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | reason | string | — | |
| 3 | root_attestation | RootAttestation | — | OSY-MEM-NNNN code on failure ENG-2157 — server-DERIVED root trust attestation. NEVER echoed from the request; computed from server state behind the GUC tenancy gate. An absent or UNSPECIFIED level on the wire (older server) MUST be treated by the consumer as ROOT_ANCHOR_LEVEL_CALLER_ASSERTED (the lowest trust) — never upgraded or inferred to SERVER_ANCHORED. Compose downstream by min-fold (trust can only be lowered, never raised). See ADR-153. |
ome.v1.WitnessEventNode
ENG-2073: one witness event = one signed claim projected for the auditor.
Maps 1:1 to the Edge GraphQL WitnessEventNode. operator is an OPEN set
(String, not enum) so an operator added in a later paper revision never fails
GraphQL parsing; the Edge renders an unknown operator as "⊕ <name>".
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | id | string | — | Canonical UUID string of the claim id (Edge GraphQL ID). |
| 2 | occurred_at_unix_ms | int64 | — | Event time as Unix milliseconds (claim.created_at). |
| 3 | operator | string | — | Lattice operator label, derived from ClaimKind (assertion / derivation / tombstone / consolidation / unspecified). OPEN set; Edge passes through. |
| 4 | signer | string | — | Signer DID / KMS key alias (claim.signer_did). |
| 5 | claim_kind | string | — | ClaimKind namespace, e.g. "osyra.claim.derivation.v1". |
| 6 | input_hash | string | — | Hex SHA-256 of the operator input (claim.content_hash). |
| 7 | output_hash | string | — | Hex SHA-256 of the operator output (claim.value_hash; falls back to content_hash on pre-V4 rows that predate value_hash). |
| 8 | verdict | string | — | Verdict ∈ {valid, invalid, pending, sealed} — computed from REAL per-row re-verification, never hardcoded. valid means the embedded signature is self-consistent under the claim's OWN signer_pub AND the stored content_hash binding is intact; it does NOT assert the signer is a workspace-AUTHORIZED issuer (that is the stronger VerifyFull / verifyWithDid trust-anchor path). The auditor surfaces valid for human review, not as an authorization claim. |
| 9 | notes | string | — | Optional one-line note (verify reason / tombstone reason); empty when none. |
ome.v1.WitnessTopRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | k | uint64 | — | top-K to attest. V1 max: 65536. Server returns OSY-MEM-5204 (WITNESS_TOP_K_OUT_OF_RANGE) if exceeded. The bound prevents witness DoS (a request with k=10⁹ would generate ~32 GB of top_values + boundaries). ENG-784 protovalidate: 1 ≤ k ≤ 65536 (matches SEC M2 from PR #2; closes the "future protovalidate annotation" deferral noted in earlier drafts at the proto layer). |
| 2 | sort_key | string | — | V1: "uuid-v7" only. ENG-784 protovalidate: enforce single-value allowlist; future sort keys (lex, ts, etc.) graduate by adding to the in set. |
| 3 | issuer_did | string | — | Issuer DID URI (W3C DID Core §3.2 canonical form). ENG-784 protovalidate: DID URI pattern + ≤512 UTF-8 cap. |
| 4 | signer_key_ref | string | — | DEPRECATED (ENG-783 / ADR-035). Use the key_source oneof at tags 7-8 instead — same semantics as SignRequest.key_source. Retained for wire- compat until the v1.0 freeze; the server applies the same dual-form OSY-MEM-5310 rejection rule documented on SignRequest. ENG-784 protovalidate: ≤512-byte cap on the legacy free-form arm. |
| 5 | tombstone_salts | map<string, bytes> | — | Optional caller-supplied tombstone-salt map (claim_id hex → 16-byte salt) for known tombstones in the gap range. The salts feed into the witness's gap_digest, which is part of the Ed25519-signed Form B preimage (dsTag "osyra-ome-cw-v1") — so the salts ARE part of the cryptographic contract that an offline verifier will treat as authoritative. SECURITY CONTRACT (ENG-782 / ADR-036): audit_mode == AUDIT_MODE_UNSPECIFIED (proto3 default — pre-ENG-782 wire compatibility shim, see ADR-036 §Compat-Shim) OR audit_mode == AUDIT_MODE_ENFORCE: - This map MUST be empty. A non-empty submission with these modes is rejected with OSY-MEM-5212 (TOMBSTONE_SALTS_REQUIRES_AUDIT_MODE). - The server derives every salt deterministically from the per-era era_secret (osyra-claims-common.deriveTombstoneSalt(era_index, claim_id)) and stamps the gap_digest from those server-derived salts. This is the safe default for every standard caller. audit_mode == AUDIT_MODE_AUDIT: - This map MAY be populated. Each entry is server-VERIFIED against the era_secret-derived salt for the (claim_id, era_index) pair before inclusion. Mismatch → OSY-MEM-5351 (ERA_SECRET_UNAVAILABLE) or OSY-MEM-5213 (TOMBSTONE_SALT_MISMATCH). - The Edge Gateway / interceptor MUST verify the caller carries the audit:read OPA scope before forwarding the request; the gRPC service rejects without the scope (PERMISSION_DENIED / 5310). The privilege boundary at the API layer (ENG-782 Option A intent) is surfaced via the audit_mode field — a standard caller cannot reach the salt-override path even with workspace-scoped credentials. |
| 6 | audit_mode | AuditMode | — | ENG-782 / ADR-036 — Audit-mode discriminator. Controls whether the server accepts caller-supplied salt overrides on tombstone_salts (above). See the AuditMode enum for the full state table and the tombstone_salts SECURITY CONTRACT above for the per-mode behaviour. Default (UNSPECIFIED) is treated as ENFORCE for wire-compat with pre- ENG-782 callers — they NEVER populated tombstone_salts in practice (the field was undocumented as caller-facing), so default-deny is safe. |
| 7 | kms_key_id | string | — | |
| 8 | secrets_manager_secret_arn | string | — | DEPRECATED + UNSUPPORTED for claim signing (ENG-3373 / ADR-374). Same contract as SignRequest.secrets_manager_secret_arn: production custody is KMS-only (ADR-040); the server REJECTS this arm with OSY-MEM-5149 and never maps the ARN onto the KMS key. Populate kms_key_id. Removed at v1.0 freeze. |
ome.v1.WitnessTopResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | witness | CompletenessWitness | — | |
| 2 | encoded_cbor | bytes | — | |
ome.v1.WorkspaceFilter
WorkspaceFilter — request envelope for OMEService.StreamSignerPubChanges.
Per ADR-040 v0.4 §3.4.2 + orchestrator-locked Q7 (OPA scope osyra:ome:signerpub:stream:read).
The OPA gate clamps the workspace_dids set to the subscriber's authorized intersection; out-of-bounds workspace_dids are silently dropped from the filter (NOT rejected outright — avoids leaking workspace existence to misconfigured subscribers per /osyra-security /security-review B1 enumeration defense). PERMISSION_DENIED is returned ONLY when the resulting intersection is empty (no authorized workspaces overlap with requested).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | workspace_dids | string | repeated | Workspaces this subscriber is requesting events for. Each entry MUST be in did:osyra:workspace:{uuid} or ADR-061 4-segment did:osyra:ws:{uuid}:signer:{signer_uuid} form. Server normalizes to canonical did:osyra:workspace:{uuid} before OPA evaluation. Cardinality cap: 1024 entries per request (DoS hardening); requests exceeding this limit MUST be rejected with INVALID_ARGUMENT (OSY-MEM-5143). Per-entry length cap: 256 bytes UTF-8. ENG-784 protovalidate: ≤1024 entries, each ≤256 UTF-8 bytes (per docstring spec). |
| 2 | resume_from | ResumeCursor | repeated | Optional resume-from cursor. Edge persists last-seen (source_region, workspace_did, sequence_number) per its bootstrap active-set. Server emits historical events from this point onward IF still in the 7-day in-process retention window (orchestrator- locked Q10). Beyond retention → server emits Status.DATA_LOSS + MEMORY_SIGNERPUB_GAP_DETECTED audit, and Edge MUST trigger full cache rebuild via existing ListSignerPubs path before resuming. Cardinality cap: 1024 entries per request (matches workspace_dids). ENG-784 protovalidate: ≤1024 entries (matches workspace_dids cap). |
ome.v1.WrapReceiptEnvelopeRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | inner_payload | bytes | — | Already-signed inner Pillar-1 receipt payload (canonical-CBOR encoded). For V1 GA: only osyra-ome-mguard-v1 inner_ds_tag is supported; future releases extend to osyra-drift-v1 (BAR), osyra-omp-archive-v1, and osyra-forget-receipt-v1. Size cap: 1 MiB (OSY-MEM-5119 on overflow per ADR-039 v0.2 + ENG-1012). ENG-784 protovalidate: 1B ≤ inner_payload ≤ 1 MiB. |
| 2 | inner_ds_tag | string | — | The Pillar-1 protocol identifier — must be in the V1 allowlist: "osyra-ome-mguard-v1" (this release) "osyra-drift-v1" (osyrastream BAR; future) "osyra-omp-archive-v1" (OMP archive; future) "osyra-forget-receipt-v1" (FORGET-RECEIPT deletion; future) OSY-MEM-5117 (MEM_ENVELOPE_DS_TAG_UNKNOWN) on values outside the allowlist. ENG-784 protovalidate: server-side allowlist + proto layer pattern (lowercase identifier ending in -vN); server-side in: [...] would force a proto bump on every new tag, so we keep just the structural pattern here. |
| 3 | workspace_did | string | — | Workspace DID — bound into the envelope's workspace_did field per ADR-039 v0.2 envelope schema. MUST be consistent with the workspace pinned via the per-connection ome.workspace_id GUC; the server enforces the binding via the BilateralBindingValidator. ENG-784 protovalidate: DID URI + ≤512-byte cap (REQUIRED). |
ome.v1.WrapReceiptEnvelopeResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | envelope_cbor | bytes | — | Canonical-CBOR-encoded osyra-receipt-envelope-v1 wrapper bytes ready to ship over the wire. Decode via osyra-mguard-common OsyraReceiptEnvelopeCodec. |
| 2 | emitted_at_unix_ms | uint64 | — | Server-clock-derived emission timestamp embedded in the envelope's emitted_at_unix_ms field. Returned to callers for trace correlation + receipt-freshness diagnostics. |
osyrastream.v1.AnchorBatchRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tenant_id | string | — | |
| 2 | agent_did | string | — | |
| 3 | batch_size | uint32 | — | optional hint; may be empty to anchor over all agents |
osyrastream.v1.AnchorBatchResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | batch_id | bytes | — | Deterministic RFC 9562 UUIDv8 JMT anchor ID (same derivation as the wire-frozen claim_id field used by OME Insert; not a signed Claim ID). |
| 2 | mmr_root | bytes | — | |
| 3 | batch_timestamp | int64 | — | 32-byte MMR root committed |
| 4 | leaf_count | uint64 | — | epoch-ns of batch |
osyrastream.v1.AnchorTermReceiptRequest
AnchorTermReceipt (ENG-2038): anchor an AP00007 termination-receipt root. The receipt ITSELF travels nowhere here — only its 32-byte SHA-256 root is committed (the signed envelope is verified by AP00016 and archived by AP00007/AP00005; AP00012 only anchors).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tenant_id | string | — | |
| 2 | session_binding | bytes | — | validated tenant id; MUST match the authenticated OS-Tenant-Id; hashed into the JMT path (never raw) |
| 3 | receipt_root | bytes | — | 32 bytes — the receipt's session_binding (the per-session anchor-slot key) |
osyrastream.v1.AnchorTermReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | Wire-frozen field name. Deterministic RFC 9562 UUIDv8 anchor ID derived from the domain-separated anchor path; this is not a signed Claim ID and is deliberately not time-sortable UUIDv7. |
| 2 | anchor_path | string | — | |
| 3 | anchor_timestamp | int64 | — | the committed JMT subtree path (audit/debug view) Wire-frozen name. Epoch-ns when AP00012 acknowledges THIS RPC after AP00011 success; it is not AP00011's authoritative first-commit timestamp. An identical idempotent replay retains claim_id/anchor_path but receives a new acknowledgement timestamp. |
osyrastream.v1.AttlogRecordItem
AttlogRecordItem carries one osyra-attlog-v1 attested-log record. encoded_record is the
canonical signed CBOR wire (SOURCE OF TRUTH — the consumer re-verifies the Ed25519 signature +
the gap-free causal chain OFFLINE from it); the remaining fields are decoded VIEWS for routing /
display WITHOUT re-encoding (WIRE-TRUTH INVARIANT). record_hash is SHA-256 over the canonical
UNSIGNED body — the causal-chain link value (a successor's prev_record_hash equals it) and the
per-tenant record-MMR leaf value. ENG-2512.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_record | bytes | — | |
| 2 | version | string | — | |
| 3 | tenant_id | string | — | "osyra-attlog-v1" |
| 4 | agent_did | string | — | |
| 5 | seq | uint64 | — | |
| 6 | prev_record_hash | bytes | — | per-(tenant,stream) gap-free monotonic sequence |
| 7 | t_unix_ns | int64 | — | 32-byte causal hash-link (genesis = 32 zero bytes) |
| 8 | payload_kind | uint32 | — | |
| 9 | payload_key_id | string | — | 0 = CLEARTEXT, 1 = SEALED (the uint8 wire kind, widened to proto uint32) |
| 10 | record_hash | bytes | — | SEALED per-record key handle; empty for CLEARTEXT |
osyrastream.v1.BARReceipt
BARReceipt is the per-BAR result of EmitBAR.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bar_content_hash | bytes | — | |
| 2 | mmr_position | uint64 | — | sha256(canonical_cbor(signed BAR)) |
| 3 | batch_id | bytes | — | leaf index in the per-tenant MMR |
| 4 | status | Status | — | JMT anchor CID once batched (empty until anchored) |
Nested types: osyrastream.v1.BARReceipt.Status
osyrastream.v1.Bar
Bar carries the osyra-drift-v1 BAR opaquely: the canonical-CBOR bytes (source of truth) plus decoded view fields the server needs for routing WITHOUT re-encoding. Verifiers re-derive the signing input from canonical_cbor, never from the view.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | canonical_cbor | bytes | — | |
| 2 | version | string | — | the signed osyra-drift-v1 CBOR (source of truth) |
| 3 | tenant_id | string | — | "osyra-drift-v1" (decoded view; MUST match cbor) |
| 4 | agent_did | string | — | routing key (decoded view; MUST match cbor) |
| 5 | workspace_path | string | — | routing (decoded view) |
| 6 | t_unix_ns | int64 | — | routing (decoded view) |
osyrastream.v1.CountActiveAgentsRequest
CountActiveAgentsRequest scopes the distinct-agent cardinality query to one tenant over a
half-open-ish time window [since_unix_ns, until_unix_ns] (a 0 bound is treated as unbounded
on that side). tenant_id is a decoded VIEW carried for parity with the other RPCs — the
server resolves the AUTHORITATIVE tenant from the OS-Tenant-Id ingress metadata and uses
this field ONLY for the confused-deputy match (it MUST match the authenticated tenant if
set, §8.1.1).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tenant_id | string | — | |
| 2 | since_unix_ns | int64 | — | routing view ONLY; authz is the OS-Tenant-Id ingress identity |
| 3 | until_unix_ns | int64 | — | inclusive window start (0 = unbounded) |
osyrastream.v1.CountActiveAgentsResponse
CountActiveAgentsResponse carries ONLY aggregate counts — never an agent_did, never a
per-agent list (cardinality / PII discipline, §11.1). distinct_agent_count is the number
of distinct sha256(agent_did) that emitted ≥1 BAR in scope. bars_scanned is a best-effort
count of cold blob keys + hot entries examined (observability, not billed). exact is true
only when the window aligns to UTC day boundaries (see CountActiveAgents EXACTNESS); a false
exact means the day-granular cold scan over-counts the partial boundary days (upper bound).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | distinct_agent_count | uint64 | — | |
| 2 | bars_scanned | uint64 | — | distinct sha256(agent_did) emitting ≥1 BAR in scope |
| 3 | exact | bool | — | best-effort keys/entries examined (observability) |
osyrastream.v1.DriftEvent
DriftEvent is pushed to SubscribeDrift subscribers for each non-OK terminal BAR
status. It carries the offending BAR opaquely (bar.canonical_cbor = source of
truth; the subscriber re-derives the signing input from it for VerifyBAR — NEVER
re-encodes the view, WIRE-TRUTH INVARIANT) plus the decoded view fields the enforcer
routes on. status reuses the frozen BARReceipt.Status enum and is NEVER OK on the
wire (every non-OK value — the full 6210/6211/6212/6220/6230/6240 set — is pushed).
drift_score/drift_budget are NOT duplicated here: they live inside canonical_cbor
and the subscriber obtains them by decoding-for-display — duplicating them would risk
view/cbor divergence.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bar | Bar | — | |
| 2 | status | BARReceipt.Status | — | the offending BAR (canonical_cbor source of truth + decoded views) |
| 3 | mmr_position | uint64 | — | drift verdict (frozen enum; never OK on the wire) |
| 4 | bar_content_hash | bytes | — | MMR leaf index; 0 for a verification-failure BAR (never appended) — route on tenant/workspace, not this |
| 5 | emitted_at_unix_ns | int64 | — | sha256(canonical_cbor); matches BARReceipt.bar_content_hash |
| 6 | dropped_since | uint64 | — | server-side push-classification time (staleness/observability) |
osyrastream.v1.EmitBARRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bar | Bar | — | |
osyrastream.v1.GetAttlogTrajectoryRequest
GetAttlogTrajectoryRequest selects one (tenant_id, agent_did) attested-log stream over an optional [since_unix_ns, until_unix_ns] window (0 = open bound). tenant_id is a routing VIEW; authorization is the OS-Tenant-Id ingress identity (§8.1.1 confused-deputy defense). ENG-2512.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tenant_id | string | — | |
| 2 | agent_did | string | — | |
| 3 | since_unix_ns | int64 | — | |
| 4 | until_unix_ns | int64 | — | |
osyrastream.v1.GetTrajectoryRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tenant_id | string | — | |
| 2 | agent_did | string | — | |
| 3 | workspace_path | string | — | |
| 4 | since_unix_ns | int64 | — | |
| 5 | until_unix_ns | int64 | — | |
| 6 | include_proofs | bool | — | |
osyrastream.v1.SubscribeDriftRequest
SubscribeDriftRequest opens a live drift-event subscription. tenant_id is a decoded
VIEW carried for parity with the other RPCs — the server resolves the AUTHORITATIVE
tenant from the OS-Tenant-Id ingress metadata and IGNORES this field for authorization
(it MUST match the authenticated tenant if set; confused-deputy defense §8.1.1).
workspace_path optionally narrows the feed to one workspace (empty = all workspaces
in the tenant). agent_did optionally narrows to one agent (empty = all agents in scope).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tenant_id | string | — | |
| 2 | workspace_path | string | — | routing view ONLY; authz is the OS-Tenant-Id ingress identity |
| 3 | agent_did | string | — | optional server-side filter; empty = all workspaces in tenant |
osyrastream.v1.TrajectoryItem
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bar | Bar | — | |
| 2 | mmr_jmt_proof | bytes | — | |
osyrastream.v1.VerifyBARRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | bar | Bar | — | |
| 2 | baseline_cid | bytes | — | |
| 3 | jmt_proof | bytes | — | optional; expected baseline anchor (T-DRIFT-3 productized half) |
osyrastream.v1.VerifyBARResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | failure_reasons | string | repeated | |
| 3 | drift_budget | uint32 | — | OSY-DRIFT-* codes |
| 4 | drift_actual | uint32 | — | |
| 5 | monotonicity_check | bool | — | |
| 6 | jmt_anchor_check | bool | — | |
vir.v1.EmitEATReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | receipt_kind | string | — | The oversight receipt-kind to mint (the EAT claim -65537 discriminator): "osyra-oversight-redecision-v1" or "osyra-oversight-coverage-v1". Any other kind is rejected. |
| 2 | receipt_body | bytes | — | The PRE-CANONICALIZED, kind-specific receipt body (keyasint CN-CBC). The verifier re-encodes- and-compares it and signs ONLY the canonical bytes (OVERSIGHT_BODY_NONCANONICAL on mismatch) — so the re-decider re-decides exactly the bytes the signer signed (the moat). |
| 3 | ws | string | — | The ASSERTED workspace/tenant. NOT trusted on the caller's word: cross-checked against tenant_cap (T-13b) AND must equal the body's signed ws, then bound into the envelope -65540 ws + the per-tenant kid selection. |
| 4 | eat_nonce | bytes | — | A fresh single-use EAT nonce (8..64 bytes, RFC 9711 §4.1), burned at the envelope layer on verify. |
| 5 | tenant_cap | bytes | — | The INDEPENDENT per-tenant capability token (audience=AP00016, subject=ws, short TTL) the caller obtained from an authority it does NOT control (AP00002 IAM). The verifier fail-closed-verifies it covers ws BEFORE selecting the kid — AP00022 cannot just assert ws (confused-deputy defense). |
| 6 | alg_suite | uint32 | — | The emit alg-suite (service numbering, ADR-142): 0 or 1 = Ed25519 (the v1.0 only suite). Any other value is rejected (forward-compatible with the OCHE hybrid-PQC slot, ENG-2004). |
vir.v1.EmitEATReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | eat_wire | bytes | — | The signed on-wire EAT envelope ("osyra-eat-v1" COSE_Sign1) — empty on a fail-closed reject. |
| 2 | cti | bytes | — | The receipt id (CWT cti) = the single-use burn anchor + the coverage receipts_root leaf. Empty on reject. |
| 3 | reason | string | — | "" on success; an OVERSIGHT_* fail-closed reject reason otherwise (a reject is NOT a gRPC error — the caller inspects this field). E.g. OVERSIGHT_BODY_NONCANONICAL, OVERSIGHT_WS_UNAUTHORIZED. |
vir.v1.EmitReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | ws | string | — | ENG-784 protovalidate: workspace id ≤512 bytes (matches OME workspace_did cap). |
| 2 | subj | string | — | ENG-784 protovalidate: DID URI pattern + ≤512-byte cap. |
| 3 | oaec_cap | string | — | ENG-784 protovalidate: opaque capability id ≤256 bytes. |
| 4 | src | string | — | ENG-784 protovalidate: source-protocol discriminator pattern osyra.vir.src.<name>.vN | x-<name> | p-<name> Length cap 128 bytes prevents abuse of the discriminator string. |
| 5 | intent | IntentBody | — | |
| 6 | merkle_root | bytes | — | canonical projection of the ingested intent ENG-784 protovalidate: merkle_root is either empty (standalone) OR 32 bytes (SHA-256 originating-envelope root). The bytes.len = 32 rule with ignore = IGNORE_IF_ZERO_VALUE captures this — empty bytes is the proto3 zero value, which is the "standalone" branch. |
| 7 | alg_suite | uint32 | — | ENG-784 protovalidate: alg_suite is the registered identifier. v1.0 1 = Ed25519 (emit), 2 = ES256 (verify-only) The enum-allowlist in: [1, 2] is enforced even before the gRPC trip. |
| 8 | trust_floor | string | — | ENG-784 protovalidate: ≤128-byte cap on trust_floor (opaque trust-tier id). |
| 9 | infer_intent | InferIntentBody | — | ENG-2036: the FIRST-CLASS typed inference ARM (EPIC ENG-2034). Carried ONLY when src == "osyra.vir.src.osyra-infer.v1"; the intent (payment IntentBody) and infer_intent arms are MUTUALLY EXCLUSIVE — a payment source-kind carrying infer_intent, or the inference source-kind carrying payment scalars, is rejected FailedPrecondition by EmitReceipt. Modeled as a SEPARATE additive field (NOT a oneof) so it is buf-breaking-safe (additive) and the existing payment intent field number/shape is untouched. /osyra-arch flag: separate-field vs oneof — separate-field chosen for additivity (a oneof retrofit over field 5 would be a wire break); the server enforces exclusivity in code. |
vir.v1.EmitReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the signed canonical VIR (COSE_Sign1 over Form B, dsTag "osyra-vir-v1"). |
| 2 | vir_id | bytes | — | |
| 3 | signer | string | — | decoded view: VIR id (UUIDv7 raw, 16 bytes) |
| 4 | ts | uint64 | — | decoded view: L5 verifier-of-record attestor DID |
vir.v1.GetMlBomRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the canonical COSE_Sign1 EAT envelope bytes (dsTag "osyra-eat-v1") carrying an oadr.v1 receipt. The verifier re-decides it under the SAME issuer-key resolution + nonce burn + kind dispatch as VerifyEnvelope before projecting; a non-oadr.v1 kind or a failed re-decision yields a coded reason + empty ml_bom (fail-closed — never project an unverified body). ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB (matches the VIR/OME/EAT cap). |
| 2 | ws | string | — | Caller workspace. MUST equal the SIGNED workspace claim (OI-1) in the envelope (cross-tenant rejected); the eat_nonce is burned single-use within this workspace (same as VerifyEnvelope). ENG-784 protovalidate: workspace id 1..512 bytes. |
| 3 | disclosed | bytes | — | The detached, UNSIGNED eat-disclosure-v1 carrier (ADR-183 / ARC-15). oadr.v1 is a CLASS-B kind: the signed body commits the per-parent leaves + roots, but the per-request OriginAttestations (+ shard bytes when CONTENT_BOUND) ride this carrier, trusted SOLELY by re-derivation against the signed body. REQUIRED for an oadr.v1 receipt to re-decide; a nil carrier fails closed (EAT_DISCLOSURE_REQUIRED) — the verifier will not project a body it could not re-decide. ENG-784 protovalidate: bounded by the verifier's MaxDisclosureBytes; the 16 MiB cap mirrors the encoded_cbor envelope ceiling. Empty fails closed in the handler (not a proto constraint — the emptiness is the Class-B disclosure-required signal, not a malformed request). |
vir.v1.GetMlBomResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | ml_bom | bytes | — | The CycloneDX-1.7 ML-BOM JSON bytes (deterministic projection of the verified oadr.v1 body + the pinned attestor-registry snapshot). Empty on any fail-closed reject (NO STUBS — never a hollow regulator artifact). |
| 2 | media_type | string | — | The CycloneDX-1.7 JSON media type the BOM is served under, e.g. "application/vnd.cyclonedx+json; version=1.7". Empty on reject. |
| 3 | reason | string | — | "" on success; a coded, non-informative reject reason otherwise (a reject is NOT a gRPC error — the caller inspects this field). E.g. an OSY-EAT/OSY-VIR re-decision code, or "ml-bom projection unavailable" when the attestor-registry snapshot is not configured. |
| 4 | receipt_kind | string | — | The dispatched receipt-kind discriminator (decoded view; populated once the claim set decodes, even on some failures, for diagnosis). On success it is "oadr.v1"; a non-oadr.v1 verified receipt carries its own kind here alongside the reject reason. |
vir.v1.GetOirTrustAnchorsRequest
No scalar fields (empty message or wrapper).
vir.v1.GetOirTrustAnchorsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | gateway_key | bytes | — | The pinned gateway COSE_Sign1 Ed25519 public key (32 bytes). EMPTY when OIR verification is NOT configured on this verifier — the relying party detects "OIR verify unavailable" and does not attempt a verify under a null key (NO STUBS). |
| 2 | model_keys | OirModelKey | repeated | The pinned per-model countersignature keys, sorted by model_id for a deterministic response. |
| 3 | min_ver_floor | uint64 | — | The relying-party anti-rollback min_ver floor + currency epoch floor the KindOIR re-decider applies — published so the offline/edge verify enforces the SAME floors as the server. |
| 4 | epoch_floor | uint64 | — | |
vir.v1.GetReceiptKindsRequest
No scalar fields (empty message or wrapper).
vir.v1.GetReceiptKindsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | receipt_kinds | string | repeated | The registered EAT receipt-kind discriminators (sorted), e.g. "VIR", "OIR", "OEV". |
vir.v1.GetReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | vir_id | bytes | — | ENG-784 protovalidate: exact 16-byte UUIDv7 (per docstring contract). |
| 2 | ws | string | — | ENG-784 protovalidate: workspace id ≤512 bytes. |
vir.v1.GetReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the persisted canonical VIR bytes from the linkage store. |
vir.v1.InferIntentBody
InferIntentBody is the FIRST-CLASS typed inference-execution projection AP00008 hands to
EmitReceipt when src == "osyra.vir.src.osyra-infer.v1" (ENG-2036, EPIC ENG-2034). It is the
proto view of the FROZEN infer-receipt-preimage-map
(docs/architecture/cddl/inference-receipt-v1.cddl; design §4.3.3 "rides VIR first-class").
This is the typed inference ARM of EmitReceipt: a non-payment ride. It does NOT replace the
generic forward-compat tail (the V1 tenant-private p-<org-uuid>.osyra.infer.v1 fallback in
design §4.3.3 stays working) — it promotes inference to a frozen, non-experimental
source-kind so the receipt carries NO trust_floor stamp (first-class, not experimental).
WIRE-TRUTH: the codec encodes these 9 fields as the CLOSED canonical-CBOR
infer-receipt-preimage-map (no * tstr => any tail — §4.3.3 sec#3 / C-9); presence is
governed by the canonical CBOR, NOT proto zero-values. All 9 fields are REQUIRED in the
closed map; the codec rejects a wrong-length io_content_hash or out-of-enum backend_class.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | org_id | string | — | ENG-2036 protovalidate: bound tenant org (self-describing; signed). sec#2. |
| 2 | workspace_id | string | — | ENG-2036 protovalidate: bound tenant workspace (signed; == VIR envelope ws, §9C). sec#2. |
| 3 | model_id | string | — | ENG-2036 protovalidate: broker-chosen model identifier (executor-reported). |
| 4 | backend_class | string | — | ENG-2036 protovalidate: executor family — one of vllm / bedrock / custom_gpu (infer-backend-class; ADR-127). The enum-allowlist is also re-checked in the codec. |
| 5 | pool_id | string | — | ENG-2036 protovalidate: concrete pool that executed (served_by.pool_id). |
| 6 | prompt_tokens | uint64 | — | |
| 7 | completion_tokens | uint64 | — | executor-reported §5.2 single-source token count |
| 8 | io_content_hash | bytes | — | executor-reported §5.2 single-source token count ENG-2036 protovalidate: sha256(canonical_cbor_form_b(infer-io-preimage)) — EXACTLY 32 bytes (qa#1). The codec ALSO enforces the 32-byte length (a wire reject, not just a proto guard). |
| 9 | served_region | string | — | ENG-2036 protovalidate: serving region (data-residency provenance). |
vir.v1.IntentBody
IntentBody is the canonical projection of an ingested economic intent (wire-spec §5.1 vir-intent-body). Monetary amounts are integer minor-units, never floats. All fields are OPTIONAL in the wire CDDL; field PRESENCE is governed by the canonical CBOR, NOT by proto zero-values — a proto3 singular scalar cannot distinguish absent from zero, so the codec (ENG-1753) MUST source presence from encoded_cbor to preserve WIRE-TRUTH re-encode-and-compare byte-identity.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | payment_id | string | — | ENG-784 protovalidate: ≤128-byte cap on payment_id (opaque issuer-side token). |
| 2 | amount | uint64 | — | |
| 3 | currency | string | — | minor units (e.g. micro-USDC); never a float ENG-784 protovalidate: 3–8 byte cap on currency (ISO-4217 = 3 chars; asset symbols ≤8 chars). Enforces uppercase A-Z, also dashes for hyphenated assets. |
| 4 | settlement_asset | string | — | ENG-784 protovalidate: ≤32-byte cap on settlement_asset. |
| 5 | recipient | string | — | ENG-784 protovalidate: ≤512-byte cap on recipient (DID URI or address form). |
| 6 | expiry | uint64 | — | |
vir.v1.ListReceiptsRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | ws | string | — | ENG-784 protovalidate: workspace id 1..512 bytes (required scope; matches GetReceipt). |
| 2 | since_ts | uint64 | — | Inclusive emitted-at lower bound, Unix ms. 0 = open (no lower bound). |
| 3 | until_ts | uint64 | — | Inclusive emitted-at upper bound, Unix ms. 0 = open (no upper bound). |
| 4 | src | string | — | Optional source-kind exact-match filter (osyra.vir.src.<name>.vN | x-… | p-…). Empty = any source. ENG-784 protovalidate: ≤128-byte cap (no min_bytes — empty is valid). |
| 5 | page_size | uint32 | — | Page size 1..100; 0 → server default (50). ENG-784 protovalidate: ≤100. |
| 6 | page_token | string | — | Opaque continuation cursor from a prior ListReceiptsResponse.next_page_token. Empty = first page. ENG-784 protovalidate: ≤256-byte cap. |
vir.v1.ListReceiptsResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | receipts | ReceiptSummary | repeated | Workspace receipt summaries, ordered emitted-at DESC then vir_id (stable tiebreak). |
| 2 | next_page_token | string | — | Opaque continuation cursor; empty when the final page has been returned. |
vir.v1.OeraserByokBundle
OeraserByokBundle carries the customer's AWS CloudTrail digest + log file alongside a bounded BYOK oeraser-body so the relying party can re-decide event inclusion OFFLINE (no AWS call).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | digest_content | bytes | — | The AWS-signed CloudTrail digest JSON (whose SHA-256 the body's byok_witness commits + the per-Region RSA signature attests). Bounded by the verifier's MaxDigestBytes. |
| 2 | log_file | bytes | — | The CloudTrail log file the digest commits (its SHA-256 == the witness log_hash) and which carries the ScheduleKeyDeletion record. Bounded by the verifier's MaxLogFileBytes. |
vir.v1.OirModelKey
One pinned per-model OIR countersignature key.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | model_id | string | — | The model identifier the countersigning key is pinned to (e.g. "claude-opus-4.5"). |
| 2 | public_key | bytes | — | The model's pinned Ed25519 countersignature public key (32 bytes). |
vir.v1.OirReDecision
OirReDecision is the server's authoritative re-decision verdict — the SAME verdict the KindOIR EAT
re-decider produces, surfaced for a standalone OIR. accepted is the conjunction of all wire + policy
legs; reason is "ok" on accept or a coded, non-informative "OIR_*: detail" on reject. The decoded
views (oir_id / model_id / ts) are populated once the gateway-signed preimage authenticates (i.e. on
accept) for the caller's display + the durable-list key — never trusted from an UNVERIFIED body.
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | accepted | bool | — | True iff every wire leg (gateway sig + REQUIRED model countersignature + byte-allowlists + dsTag + canonical CBOR + collapsed-domain guard + fixed-width shape) AND every policy leg (alg_suite + src + ts freshness + epoch currency floor + min_ver_floor) re-decided under the config-pinned anchors. |
| 2 | reason | string | — | "ok" on accept; an "OIR_*: detail" reject reason otherwise (carried verbatim, non-informative on the cross-tenant/unconfigured path). A reject is NOT a gRPC error — the caller inspects this field. |
| 3 | oir_id | bytes | — | Decoded view: the OIR id (UUIDv7 raw, 16 bytes) — populated only when accepted=true (the durable-list key). On reject it is empty (an unauthenticated body's fields are never surfaced). |
| 4 | model_id | string | — | Decoded view: the model the receipt declares (key 14) — populated only when accepted=true. |
| 5 | ts | uint64 | — | Decoded view: the receipt's emitted_at Unix ms (key 7) — populated only when accepted=true. |
vir.v1.ProjectCapabilityRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | oaec_cap | string | — | ENG-784 protovalidate: capability id ≤256 bytes. |
| 2 | target_proto | string | — | ENG-784 protovalidate: target protocol id ≤128 bytes (e.g. "x402"). |
| 3 | ws | string | — | ENG-784 protovalidate: workspace id ≤512 bytes. |
| 4 | receiver_id | string | — | ENG-784 protovalidate: receiver id ≤512 bytes (cross-network exclusivity key). |
vir.v1.ProjectCapabilityResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | tightening_claim_cbor | bytes | — | WIRE-TRUTH: both sidecars are signed canonical artifacts (distinct dsTags), so they are named explicitly rather than collapsed to a single encoded_cbor. |
| 2 | projection_event_cbor | bytes | — | osyra-tightening-claim-v1 (ADR-054 Layer 2) |
| 3 | accepted | bool | — | osyra-vir-projection-event-v1 (ADR-054 Layer 3) |
| 4 | reason | string | — | |
vir.v1.ReceiptSummary
ReceiptSummary is a lightweight list projection — the decoded fields needed to render a row and open the detail view. It deliberately OMITS encoded_cbor (keeps the list cheap); the detail view fetches the full signed receipt via GetReceipt. These fields mirror the wire-spec §5.1 preimage (id/signer/subj/src/content_hash/ts) but are decoded views — on any discrepancy the canonical encoded_cbor (via GetReceipt) is authoritative (WIRE-TRUTH).
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | vir_id | bytes | — | VIR id (UUIDv7 raw, 16 bytes) — the GetReceipt key. |
| 2 | signer | string | — | L5 verifier-of-record attestor DID (≤512 bytes). |
| 3 | subj | string | — | Subject / agent DID (≤512 bytes). |
| 4 | src | string | — | Source-protocol discriminator (≤128 bytes). |
| 5 | content_hash | bytes | — | SHA-256 of the canonical intent body (32 bytes). |
| 6 | ts | uint64 | — | emitted_at Unix ms. |
| 7 | decided_action | uint32 | optional | ── OGVR summary projection (ENG-2823) ───────────────────────────────────────────── decided_action / max_score are the ogvr.v1 (guardrail-verdict receipt) list projection AP00016 decodes ONCE server-side, at list time, from the persisted signed EAT body — retiring the AP00001 edge's per-page GetReceipt fan-out (ENG-2802 review #14: an N+1 that shipped whole envelopes over the WAN to project two ints). They are OGVR-ONLY and OPTIONAL: set ONLY on an src == "ogvr.v1" row whose signed body AP00016 could canonically decode; UNSET (proto3 explicit-presence absent) on every non-ogvr row AND on any ogvr.v1 row the projection could not derive (a legacy pre-ENG-2823 row / a decode failure) — for which the edge falls back to its ENG-2802 verify-path GetReceipt enrichment. ADDITIVE / backward- compatible (new optional scalar fields on the previously-free tags 7/8; ENG-557 proto-SoT — wire- and JSON-compatible; buf breaking WIRE_JSON passes). WIRE-TRUTH: both are decoded VIEWS of the signed body; on any discrepancy the canonical encoded_cbor (via GetReceipt) is authoritative. The committed severity-max guardrail action (ogvr-v1.cddl key 10, decided_action): 0=LOG_ONLY 1=FLAG 2=REDACT 3=BLOCK 4=DENY. lte=4 mirrors the ogvr.v1 body domain. |
| 8 | max_score | uint32 | optional | The highest committed verdict milli-score across the ogvr.v1 verdict array (max over the ogvr-v1.cddl key-8 verdict score, an integer 0.000..1.000 fixed-point, so 0..1000). The at-a-glance severity signal the guardrail timeline sorts by. lte=1000 mirrors the body domain. |
vir.v1.VerifyEnvelopeRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the canonical COSE_Sign1 EAT envelope bytes to verify (dsTag "osyra-eat-v1"). The receipt_kind discriminator + opaque receipt_body live inside the SIGNED claim set. ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB (matches the VIR/OME cap). |
| 2 | ws | string | — | Caller workspace. MUST equal the SIGNED workspace claim (OI-1) in the envelope, else the verify is rejected (cross-tenant). The eat_nonce is burned single-use within this workspace. ENG-784 protovalidate: workspace id 1..512 bytes. |
| 3 | oeraser_byok_bundle | OeraserByokBundle | — | OPTIONAL BYOK CloudTrail bundle (ENG-2337) — the off-body digest JSON + log file for the FULL-TIER BYOK keyDestroyed re-decision of an OERaseR receipt whose witness is a customer CloudTrail ScheduleKeyDeletion event. ABSENT ⇒ a BYOK body re-decides body-only and fails closed OERASER_INCLUSION_UNPROVEN (6377) — inclusion is unprovable from the bounded body alone. The bundle is NOT separately signed: it is integrity-bound to the SIGNED body's committed digest_sha256 + log_hash (a tampered bundle fails the inclusion re-decision). |
| 4 | disclosed | bytes | — | The detached, UNSIGNED EAT disclosure carrier (eat-disclosure-v1; ADR-183 / ARC-15) for a Class-B receipt kind whose signed body commits ROOTS of per-request, externally-disclosed witnesses (e.g. OLTR's OMP items / OEV receipt / predecessor receipts; cddl/eat-disclosure-v1.cddl). It carries NO issuer signature: its sole integrity binding is the kind's re-decider RECOMPUTING each committed root in the SIGNED body from these witnesses and failing closed on any mismatch (the §5.3 trust boundary). EMPTY for Class-A kinds and for callers not performing disclosure-bound verification. ADDITIVE / backward-compatible (a new optional bytes field; ENG-557 proto-SoT: an additive optional field is wire- and JSON-compatible). The signed envelope (field 1) is untouched — disclosed never enters any signature or nonce burn; MaxDisclosureBytes is enforced before decode. RECONCILE (2026-06-20): renumbered from tag 3 → tag 4 to resolve the additive field-number collision with ENG-2337's oeraser_byok_bundle (which landed on authoritative main at tag 3 first). ENG-784 protovalidate: the disclosure carrier is bounded at decode time by the verifier's MaxDisclosureBytes; the 16 MiB cap mirrors the encoded_cbor envelope ceiling. Empty is valid (Class-A / non-disclosure callers), so the cap ignores the proto3 zero value. |
| 5 | ocar_cosign_bundle | bytes | — | OPTIONAL OCAR co-sign bundle (ENG-2505 / ADR-182; ocar-cosign-v1) — the detached counterparty co-sign sidecar for the relying-party OCAR TRUST-MODE. When present AND the verifier has a pinned counterparty allowlist + threshold configured (VIR_OCAR_COUNTERPARTY_ALLOWLIST / VIR_OCAR_THRESHOLD), VerifyEnvelope builds the post-host OCAR gate (internal/verifier/ocarcosign) and admits the host receipt only if >= threshold DISTINCT allowlisted counterparties co-signed the SAME action root the host body projects (fail-closed on fabrication / cross-tenant / threshold-unmet). ABSENT, or with no allowlist configured => plain issuer-signed re-decision (graceful degradation; existing callers are unaffected). The bundle carries NO issuer signature and never enters the envelope signature or the single-use nonce burn; MaxBundleBytes (64 KiB) is enforced before any decode. ADDITIVE / backward- compatible (a new optional bytes field; ENG-557 proto-SoT — wire- and JSON-compatible). ENG-784 protovalidate: bound at the OCAR MaxBundleBytes (64 KiB); empty is valid (no OCAR mode). |
vir.v1.VerifyEnvelopeResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | accepted | bool | — | |
| 2 | reason | string | — | issuer sig OK AND the kind's re-decider accepted AND nonce fresh+burned |
| 3 | receipt_kind | string | — | "ok", or an OSY-EAT-57xx / OSY-VIR-56xx code + detail on failure Decoded views — populated once the claim set decodes (even on some failures, for diagnosis). |
| 4 | cti | bytes | — | the dispatched ARDV kind discriminator |
vir.v1.VerifyOirRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the on-wire standalone OIR COSE_Sign1 bytes (dsTag "osyra-oir-v1"). The verifier re-decides it via oir.ReDecide under the config-pinned anchors; a forged/stale/downgraded/key-drifted receipt re-decides REJECT fail-closed. ENG-784 protovalidate: 1B <= encoded_cbor <= 16 MiB (matches the VIR/OME/EAT cap). |
| 2 | ws | string | — | Caller workspace. MUST equal the SIGNED workspace (key 3) the OIR self-commits (cross-tenant rejected), so the re-decide is not a cross-tenant validity oracle and the durable persist is scoped to the tenant. ENG-784 protovalidate: workspace id 1..512 bytes. |
vir.v1.VerifyOirResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | decision | OirReDecision | — | The server's authoritative OIR re-decision (the SAME verdict the KindOIR re-decider produces). |
vir.v1.VerifyReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the canonical VIR bytes to verify (signature is over these, not proto). ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB (matches OME cap). |
| 2 | ws | string | — | ENG-784 protovalidate: workspace id ≤512 bytes. |
vir.v1.VerifyReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | reason | string | — | |
| 3 | vir_id | bytes | — | OSY-VIR-56xx on failure; non-informative cross-tenant |
| 4 | ts | uint64 | — | decoded view (populated only when valid) |
vir.v1.VerifyTerminationReceiptRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | encoded_cbor | bytes | — | WIRE-TRUTH: the canonical COSE_Sign1 termination-receipt bytes (dsTag "osyra-term-receipt-v1"). ENG-784 protovalidate: 1B ≤ encoded_cbor ≤ 16 MiB (matches the VIR/OME cap). |
| 2 | ws | string | — | Caller workspace; the issuer trust anchor is resolved for it. ENG-784: 1..512 bytes. |
vir.v1.VerifyTerminationReceiptResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | valid | bool | — | |
| 2 | reason | string | — | |
| 3 | receipt_session_binding | bytes | — | OSY-TERM-41xx on failure; non-informative cross-tenant Decoded views — populated only when valid=true. |
| 4 | agent_did | string | — | 32-byte session binding rooting the watchdog chain |
| 5 | stop_reason_class | uint32 | — | the terminated agent DID |
| 6 | risk_tier | uint32 | — | 1..6 (graceful/policy/security/resource/watchdog/crash) |
| 7 | watchdog_count | uint32 | — | 1..3 (low/medium/high) |
| 8 | proof_at_ns | uint64 | — | verified watchdog co-witness count |
Enums
ome.v1.AbsentKind
| # | Value | Description |
|---|-------|-------------|
| 0 | ABSENT_KIND_UNSPECIFIED | Server contract: ABSENT_KIND_UNSPECIFIED on a JMTProof MUST be rejected with OSY-MEM-5152 (PROOF_VERIFICATION_FAILED). Verifiers MUST NOT treat UNSPECIFIED as "membership proof by default" — callers must be explicit about whether the proof asserts membership (use ProveResponse.is_present = true and leave absent_kind = UNSPECIFIED is REJECTED on Verify) or absence (set absent_kind to EMPTY_SLOT or DIFFERENT_LEAF). Rationale: a forgetful caller submitting a non-membership proof without setting absent_kind would otherwise have it silently verified as a (zero-hash) membership proof — leaking proof-verification side-channel info to a probing attacker. Mirrors the DispatchMode UNSPECIFIED reject contract. |
| 1 | ABSENT_KIND_EMPTY_SLOT | |
| 2 | ABSENT_KIND_DIFFERENT_LEAF | path terminates at a nil child |
ome.v1.AuditMode
ENG-782 / ADR-036 — Audit-mode discriminator for tombstone-salt overrides.
Surfaces the privilege boundary between "standard caller (server-derives salts)" and "trusted audit consumer (caller-supplied salts accepted with server verification)" at the API layer, so an Edge Gateway / interceptor can scope-check the field VALUE without inspecting message payloads.
SCOPE: applies to every Request type that carries a caller-supplied
tombstone_salts map — currently WitnessTopRequest and ExportBundleRequest.
V1.5 additions follow the same enum.
Pre-ENG-782 callers always sent the proto3 default (zero), so default- deny on UNSPECIFIED → ENFORCE is wire-compatible.
Compared with the discarded "split into a separate audit-mode RPC" Option A:
the privilege boundary is identical (the interceptor refuses
AUDIT_MODE_AUDIT without the audit:read OPA scope) but the SDK surface
does not double (no parallel WitnessTopWithSalts / ExportBundleAudit RPCs).
| # | Value | Description |
|---|-------|-------------|
| 0 | AUDIT_MODE_UNSPECIFIED | Wire-compat shim for pre-ENG-782 callers. The server treats UNSPECIFIED identically to AUDIT_MODE_ENFORCE — tombstone_salts MUST be empty, server-derives all salts from era_secret. Standard callers SHOULD set AUDIT_MODE_ENFORCE explicitly once they upgrade past the ENG-782 SDK boundary; UNSPECIFIED is reserved for legacy-wire-compat detection in server-side audit logs (an UNSPECIFIED on a post-ENG-782-SDK request is a caller bug worth flagging). |
| 1 | AUDIT_MODE_ENFORCE | Standard caller. Server derives every tombstone salt from era_secret and stamps the signed preimage from those. Any non-empty tombstone_salts map is rejected with OSY-MEM-5212 (TOMBSTONE_SALTS_REQUIRES_AUDIT_MODE). |
| 2 | AUDIT_MODE_AUDIT | Trusted audit consumer. Caller-supplied tombstone_salts are server- VERIFIED against era_secret-derived values before inclusion in the signed preimage. Mismatch → OSY-MEM-5213 (TOMBSTONE_SALT_MISMATCH); era_secret unavailable → OSY-MEM-5351 (ERA_SECRET_UNAVAILABLE). PRIVILEGE GATE: the Edge Gateway / OPA interceptor MUST refuse this value unless the caller bearer-token carries the audit:read scope. The gRPC service additionally enforces the scope (defense-in-depth) and rejects without it with PERMISSION_DENIED + OSY-MEM-5310. |
ome.v1.ClaimKind
| # | Value | Description |
|---|-------|-------------|
| 0 | CLAIM_KIND_UNSPECIFIED | |
| 1 | CLAIM_KIND_ASSERTION | |
| 2 | CLAIM_KIND_DERIVATION | OAP-MEM kind=1 |
| 3 | CLAIM_KIND_TOMBSTONE | OAP-MEM kind=2 |
| 4 | CLAIM_KIND_CONSOLIDATION | OAP-MEM kind=3 |
| 16 | CLAIM_KIND_REDACTION | CLAIM_KIND_REDACTION (ENG-2769; ADR-270 §14 re-bless lane) — dedicated transport discriminator for a signed PII/PHI redaction receipt. This is an additive tag; existing enum values remain wire-identical. |
ome.v1.DispatchMode
| # | Value | Description |
|---|-------|-------------|
| 0 | DISPATCH_MODE_UNSPECIFIED | Server contract: DISPATCH_MODE_UNSPECIFIED MUST be rejected with OSY-MEM-5453 (INVALID_ARGUMENT). The server MUST NOT default-coerce to STRICT or PERMISSIVE — callers must be explicit. Rationale: silent defaulting to PERMISSIVE opens an unknown-ClaimKind attack surface; silent defaulting to STRICT silently breaks callers on SDK upgrade. Adopt proto3 best practice (UNSPECIFIED = 0); shift design-doc values up by 1. Pre-deployment, no consumer expects the old wire numbers. |
| 1 | DISPATCH_MODE_STRICT | |
| 2 | DISPATCH_MODE_PERMISSIVE | reject unknown ClaimKind URIs |
| 3 | DISPATCH_MODE_POLICY | wrap unknown kinds in opaque.v1 |
ome.v1.PolicyDecision
ENG-2569: the policy verdict enum (ADR-291 D2). IMPLICIT_DENY is the fail-closed
sentinel distinct from an explicit policy DENY — it marks "we could not obtain an
affirmative ALLOW" (unreachable enforcer / no verified bundle / indeterminate eval),
which mirrors the AP00019 reference default allow := false. UNSPECIFIED (0) is a
wire-compat shim a server MUST NOT emit; a client treats it as IMPLICIT_DENY.
| # | Value | Description |
|---|-------|-------------|
| 0 | POLICY_DECISION_UNSPECIFIED | |
| 1 | POLICY_DECISION_ALLOW | |
| 2 | POLICY_DECISION_DENY | |
| 3 | POLICY_DECISION_IMPLICIT_DENY | |
ome.v1.RevocationReason
RevocationReason — file-scope enum (NOT nested in SignerPubChangeEvent) for reuse across RevokeSignerPubRequest + SignerPubChangeEvent. Per ADR-040 v0.4 §3.20.3.
5 values LOCKED at v0.4 ratification:
| # | Value | Description |
|---|-------|-------------|
| 0 | REVOCATION_REASON_UNSPECIFIED | INVALID for REVOKED/KEK_REVOKED events; server rejects RevokeSignerPub RPC with INVALID_ARGUMENT; Edge consumers reject SignerPubChangeEvent at parse. |
| 1 | REVOCATION_REASON_COMPROMISE | Key suspected compromised. Most common emergency case (insider threat, DB exfil, memory disclosure). Operator runbook: invoke RevokeSignerPub (assumes MFA fresh) OR MGuardGlobalKillSwitch=true FIRST (MFA not fresh). |
| 2 | REVOCATION_REASON_POLICY_CHANGE | Workspace policy mandated revocation (e.g., contract termination, customer offboarding, deprovisioned signer identity). |
| 3 | REVOCATION_REASON_OPERATOR_PUSHED | Routine operational revocation (e.g., quarterly key hygiene, scheduled retirement of long-lived signer pubs). |
| 4 | REVOCATION_REASON_KEK_CASCADE | INTERNAL — emitted by ADR-016 KEK cascade ONLY. External callers MAY NOT pass this value via RevokeSignerPub RPC (server INVALID_ARGUMENT). Edge consumers MAY NOT accept this reason from non-OME-service identities (defense vs spoofed cascade). |
ome.v1.RootAnchorLevel
ENG-2157 — server-derived root trust band (response). UNSPECIFIED(0) is a fail-closed sentinel: an absent/zero level MUST be treated as the lowest trust by consumers; it composes as an OAEC-monotone floor (ADR-153).
| # | Value | Description |
|---|-------|-------------|
| 0 | ROOT_ANCHOR_LEVEL_UNSPECIFIED | Not computed / older server — consumers MUST treat as the lowest trust. |
| 1 | ROOT_ANCHOR_LEVEL_CALLER_ASSERTED | Root compared only to the caller-supplied expected_root (offline path). |
| 2 | ROOT_ANCHOR_LEVEL_SERVER_ANCHORED | Root re-derived as a member of the server-attested root history. |
ome.v1.RootAnchoringMode
ENG-2157 — VerifyWitness root-anchoring mode (request). Default-zero (UNSPECIFIED) preserves the offline/portable contract for every existing caller. See ADR-152.
| # | Value | Description |
|---|-------|-------------|
| 0 | ROOT_ANCHORING_MODE_UNSPECIFIED | Wire-compat default; the server treats UNSPECIFIED identically to OFFLINE. |
| 1 | ROOT_ANCHORING_MODE_OFFLINE | Explicit offline / portable verification; root = CALLER_ASSERTED. |
| 2 | ROOT_ANCHORING_MODE_SERVER_ANCHORED | Require witness.root() to be a member of the workspace's server-attested JMT root history (fail-closed on no-match). |
ome.v1.SignerPubChangeEvent.EventType
| # | Value | Description |
|---|-------|-------------|
| 0 | EVENT_TYPE_UNSPECIFIED | |
| 1 | EVENT_TYPE_ROTATED | |
| 2 | EVENT_TYPE_REVOKED | per RotateMGuardSigningKey |
| 3 | EVENT_TYPE_KEK_REVOKED | per ENG-1235 RevokeSignerPub |
ome.v1.TombstoneReasonCode
ENG-583: enumerated reason codes prevent free-text PII at the audit-pipeline boundary (B-6/sec). UNSPECIFIED is rejected at the application layer with OSY-MEM-5184 (mirrors the DispatchMode + AbsentKind UNSPECIFIED reject contract).
| # | Value | Description |
|---|-------|-------------|
| 0 | TOMBSTONE_REASON_UNSPECIFIED | |
| 1 | TOMBSTONE_REASON_GDPR_ART17_DSAR | |
| 2 | TOMBSTONE_REASON_LEGAL_HOLD_EXPIRY | |
| 3 | TOMBSTONE_REASON_CUSTOMER_OFFBOARDING | |
| 4 | TOMBSTONE_REASON_OPERATOR_REDACTION | |
| 5 | TOMBSTONE_REASON_REGULATORY_OTHER | |
ome.v1.VerifiedMemoryQuarantineClass
Per-fact quarantine routing class decided at OME pre-signing time.
| # | Value | Description |
|---|-------|-------------|
| 0 | VERIFIED_MEMORY_QUARANTINE_CLASS_UNSPECIFIED | |
| 1 | VERIFIED_MEMORY_QUARANTINE_CLASS_CLEAN | distance ≤ budget; forwarded to production LLM unmodified. |
| 2 | VERIFIED_MEMORY_QUARANTINE_CLASS_SHADOW | distance ∈ (budget, 2×budget]; routed to shadow LLM. |
| 3 | VERIFIED_MEMORY_QUARANTINE_CLASS_BLOCK | distance > 2×budget; blocked at the broker. |
ome.v1.VerifiedMemoryVerdict
Per-receipt verdict scalar per ADR-050. Precedence FAIL > QUARANTINE > WARN > PASS.
| # | Value | Description |
|---|-------|-------------|
| 0 | VERIFIED_MEMORY_VERDICT_UNSPECIFIED | |
| 1 | VERIFIED_MEMORY_VERDICT_PASS | |
| 2 | VERIFIED_MEMORY_VERDICT_WARN | |
| 3 | VERIFIED_MEMORY_VERDICT_QUARANTINE | |
| 4 | VERIFIED_MEMORY_VERDICT_FAIL | |
osyrastream.v1.BARReceipt.Status
Status mirrors the design §2.1.1 enum exactly. (buf ENUM_VALUE_PREFIX is excepted in buf.yaml; OK=0 is the wire contract.)
| # | Value | Description |
|---|-------|-------------|
| 0 | OK | |
| 1 | DRIFT_BUDGET_EXCEEDED | |
| 2 | MONOTONICITY_VIOLATION | T-DRIFT-1 (OSY-DRIFT-6210) |
| 3 | BASELINE_MISMATCH | T-DRIFT-2 (OSY-DRIFT-6211) |
| 4 | SIGNATURE_INVALID | T-DRIFT-3 (OSY-DRIFT-6212) |
| 5 | TENANT_UNREGISTERED | OSY-DRIFT-6220 |
| 6 | SESSION_KEY_EXPIRED | OSY-DRIFT-6230 |
| 7 | CONSISTENCY_VIOLATION | OSY-DRIFT-6240 (fail-closed) L1-consistency: drift_vector != L1Distance(H_t, baseline) — a STRUCTURAL tampering signal (OSY-DRIFT-6213), distinct from the T-DRIFT-1 budget LAW. Carved pre-GA-enum-freeze (HOT-CODE-02) while there are zero shipped consumers so AP00016/edge/policy can distinguish tampering from a legitimate budget exhaustion — both previously collapsed onto DRIFT_BUDGET_EXCEEDED. |