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 | |
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.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.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.InsertRequest
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | claim_id | bytes | — | ENG-784 protovalidate: exact 16-byte UUIDv7. |
| 2 | value_hash | bytes | — | ENG-784 protovalidate: exact 32-byte SHA-256 digest. |
ome.v1.InsertResponse
| # | Field | Type | Label | Description |
|---|-------|------|-------|-------------|
| 1 | new_root | bytes | — | |
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 | |
| 7 | include_tombstoned | bool | optional | ClaimKind enum filter |
| 8 | limit | int32 | — | Pagination. limit: server-clamped to [1, 200]; 0 → default 50. cursor: opaque base64url(<created_at_unix_ms>:<claim_id_hex>); 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 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.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.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.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 | — | |
| 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 | — | |
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.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 | — | |
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 | — | |
| 2 | mmr_root | bytes | — | JMT anchor CID / claim_id |
| 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 | — | |
| 2 | anchor_path | string | — | deterministic UUIDv7 derived from the anchor path (the AP00011 claim) |
| 3 | anchor_timestamp | int64 | — | the committed JMT subtree path (audit/debug view) |
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. |
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 |
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. |