{
  "protocol": "bitexact",
  "about": "Conformance vectors for bitexact. Every SDK and recorder must agree with each row: a hello is welcomed or refused (the refusal names the field), an event is accepted or rejected (the reason names the field), a frame decodes or is a protocol error.",
  "hellos": [
    {"name": "a hello", "hello": {"type": "hello", "protocol": "bitexact", "capabilities": ["tokens", "causal"], "max_frame": 4194304}, "refused": null},
    {"name": "a hello with a field this side does not know", "hello": {"type": "hello", "protocol": "bitexact", "capabilities": [], "max_frame": 1048576, "compression": "zstd"}, "refused": null},
    {"name": "another protocol", "hello": {"type": "hello", "protocol": "otlp"}, "refused": "protocol"},
    {"name": "a frame limit too small to carry a batch", "hello": {"type": "hello", "protocol": "bitexact", "max_frame": 1024}, "refused": "max_frame"}
  ],
  "events": [
    {"name": "minimal", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "data": {"tool": "add", "args": [1, 2], "result": 3}}, "problem": null},
    {"name": "with causal fields and a token", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 2, "kind": "model", "prov": "asserted", "actor": "planner", "id": "7f3a91c2b0e4d5a6", "hlc": [1730000000123, 4], "caused_by": ["1b2c4d5e6f708192"], "token": "eyJ...", "data": {"model": "gpt-4o"}}, "problem": null},
    {"name": "an unknown field is ignored", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 3, "kind": "marker", "data": {"note": "x"}, "a_field_no_reader_knows": true}, "problem": null},
    {"name": "seq starts at 1", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 0, "kind": "marker", "data": {}}, "problem": "seq"},
    {"name": "a boolean is not a seq", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": true, "kind": "marker", "data": {}}, "problem": "seq"},
    {"name": "a source cannot seal", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "run_end", "data": {}}, "problem": "kind"},
    {"name": "a source cannot write the source block", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "marker", "data": {"aer_source": {"peer": "spiffe://forged"}}}, "problem": "aer_source"},
    {"name": "a path in the run id", "event": {"run_id": "../etc", "source_id": "c-abc:1", "seq": 1, "kind": "marker", "data": {}}, "problem": "run_id"},
    {"name": "a provenance the kind cannot carry", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "marker", "prov": "observed", "data": {}}, "problem": "prov"},
    {"name": "a malformed causal parent", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "marker", "caused_by": [["c-def:3", 77]], "data": {}}, "problem": "caused_by"},
    {"name": "a malformed event id", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "marker", "id": "a b", "data": {}}, "problem": "id"},
    {"name": "a clock past 2^53 - 1", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "marker", "hlc": [9007199254740992, 0], "data": {}}, "problem": "hlc"},
    {"name": "a label naming the proxy", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "http_call", "sdk": "proxy", "data": {}}, "problem": null},
    {"name": "a label naming the Python SDK", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "sdk-python", "data": {}}, "problem": null},
    {"name": "a label naming the TypeScript SDK", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "sdk-ts", "data": {}}, "problem": null},
    {"name": "a label naming the Go SDK", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "sdk-go", "data": {}}, "problem": null},
    {"name": "a label naming the Java SDK", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "sdk-java", "data": {}}, "problem": null},
    {"name": "a label naming OpenTelemetry ingest", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "model", "sdk": "otel", "data": {}}, "problem": null},
    {"name": "a label naming the LangChain callback", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "model", "sdk": "langchain", "data": {}}, "problem": null},
    {"name": "a label naming the OpenAI Agents SDK processor", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "model", "sdk": "openai-agents", "data": {}}, "problem": null},
    {"name": "a label naming the Claude Agent SDK hooks", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "claude-agent-sdk", "data": {}}, "problem": null},
    {"name": "a label naming the Google ADK plugin", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "model", "sdk": "adk", "data": {}}, "problem": null},
    {"name": "a label naming Auditant", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "policy_check", "sdk": "auditant", "data": {}}, "problem": null},
    {"name": "a label naming the LlamaIndex span handler", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "llamaindex", "data": {}}, "problem": null},
    {"name": "a label naming the Vapi end-of-call report receiver", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "context", "sdk": "vapi", "data": {}}, "problem": null},
    {"name": "a label naming the MCP proxy", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "mcp-proxy", "data": {}}, "problem": null},
    {"name": "a label naming the governance-decision API", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "policy_check", "sdk": "governance", "data": {}}, "problem": null},
    {"name": "a capture path no reader knows is recorded, its label declared", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "sdk-rust", "data": {}}, "problem": null},
    {"name": "a capture path in the wrong case is recorded, its label declared", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": "SDK-TS", "data": {}}, "problem": null},
    {"name": "a label that is not a string is recorded, its label declared", "event": {"run_id": "run-1", "source_id": "c-abc:1", "seq": 1, "kind": "tool_call", "sdk": 7, "data": {}}, "problem": null}
  ],
  "contexts": [
    {"name": "a context", "context": "bxc.7f3a91c2b0e4d5a6.1730000000123.4", "id": "7f3a91c2b0e4d5a6", "hlc": [1730000000123, 4]},
    {"name": "another prefix", "context": "bxd.7f3a91c2b0e4d5a6.1.0", "id": null},
    {"name": "missing the logical part", "context": "bxc.7f3a91c2b0e4d5a6.1", "id": null},
    {"name": "an empty id", "context": "bxc..1.0", "id": null},
    {"name": "an id with a space", "context": "bxc.a b.1.0", "id": null},
    {"name": "a negative clock", "context": "bxc.abc.-1.0", "id": null},
    {"name": "a clock that is not a number", "context": "bxc.abc.one.0", "id": null},
    {"name": "the largest clock every language holds exactly", "context": "bxc.abc.9007199254740991.9007199254740991", "id": "abc", "hlc": [9007199254740991, 9007199254740991]},
    {"name": "a clock past 2^53 - 1", "context": "bxc.abc.9007199254740992.0", "id": null},
    {"name": "a clock past 64 bits", "context": "bxc.abc.99999999999999999999.0", "id": null}
  ],
  "frames": [
    {"name": "a heartbeat", "hex": "0000010f7b2274797065223a22686561727462656174222c22736f757263655f6964223a22632d6162633a31222c2270656e64696e675f6576656e7473223a302c2273706f6f6c5f6279746573223a302c2273706f6f6c5f7265747279696e67223a302c2273706f6f6c5f756e7265616461626c65223a302c2273706f6f6c5f6d61785f6279746573223a313037333734313832342c2264726f707065645f72616e676573223a7b7d2c22756e7265636f72646564223a302c227365656e223a5b7b2272756e5f6964223a2272756e2d31222c2273646b223a2273646b2d7473222c226c6173745f61636365707465645f6174223a22323032362d31302d33305431333a35393a31302b30303a3030227d5d7d", "message": {"type": "heartbeat", "source_id": "c-abc:1", "pending_events": 0, "spool_bytes": 0, "spool_retrying": 0, "spool_unreadable": 0, "spool_max_bytes": 1073741824, "dropped_ranges": {}, "unrecorded": 0, "seen": [{"run_id": "run-1", "sdk": "sdk-ts", "last_accepted_at": "2026-10-30T13:59:10+00:00"}]}, "error": null},
    {"name": "a repeated key", "hex": "000000177b2274797065223a2261222c2274797065223a2262227d", "error": "not JSON"},
    {"name": "an array", "hex": "000000065b312c20325d", "error": "object"},
    {"name": "no type", "hex": "0000000e7b226e6f223a202274797065227d", "error": "type"},
    {"name": "cut short", "hex": "000000327b2274797065223a", "error": "mid-frame"}
  ],
  "identity_fields": {
    "about": "The fields an identity entry's data may carry, in reader order, and the two that take a fixed set of values. workflow_digest is not one: the recorder computes it.",
    "fields": ["principal", "agent_id", "delegation_from", "scope", "policy_version", "prompt_pack_version", "model_version", "workflow", "workflow_version", "environment", "code", "workflow_instance", "on_behalf_of", "on_behalf_of_type", "authority_ref", "interaction_mode"],
    "enums": {"on_behalf_of_type": ["human", "organization", "service", "agent"], "interaction_mode": ["interactive", "autonomous"]}
  },
  "credential_keys": {
    "about": "Query parameters, object keys and key=value names that carry a credential, compared without case. A wrapped client records such a query parameter's value as [redacted], URL-encoded: a parameter's name is matched once URL-decoded, ignoring ASCII case only, and every other byte of the URL (each other parameter, the name as sent, an empty parameter, the fragment) is recorded exactly as sent; a user name or password in the URL is recorded as [redacted] too. The capture policy's credentials detector scrubs them. One table: every SDK's copy is this one.",
    "keys": ["access_token", "api-key", "api_key", "apikey", "auth", "authorization", "key", "password", "secret", "sig", "signature", "subscription-key", "token", "x-api-key"],
    "recorded_urls": [
      {"name": "a key in the query, among other parameters", "url": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=AIzaSyA-example&alt=sse", "recorded": "https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=%5Bredacted%5D&alt=sse"},
      {"name": "a credential name in another case", "url": "https://api.example.com/v1/search?q=claims&API_KEY=s3cr3t", "recorded": "https://api.example.com/v1/search?q=claims&API_KEY=%5Bredacted%5D"},
      {"name": "two credentials", "url": "https://api.example.com/v1/files?token=t0k&sig=abc&page=2", "recorded": "https://api.example.com/v1/files?token=%5Bredacted%5D&sig=%5Bredacted%5D&page=2"},
      {"name": "no credential", "url": "https://api.example.com/v1/search?q=claims&page=2", "recorded": "https://api.example.com/v1/search?q=claims&page=2"},
      {"name": "no query", "url": "https://api.example.com/v1/chat/completions", "recorded": "https://api.example.com/v1/chat/completions"},
      {"name": "every other parameter kept exactly as encoded", "url": "https://api.example.com/v1/search?q=a%20b+c%2Fd&token=t0k&page=%32", "recorded": "https://api.example.com/v1/search?q=a%20b+c%2Fd&token=%5Bredacted%5D&page=%32"},
      {"name": "a credential name sent URL-encoded", "url": "https://api.example.com/v1/search?api%5Fkey=s3cr3t&q=claims", "recorded": "https://api.example.com/v1/search?api%5Fkey=%5Bredacted%5D&q=claims"},
      {"name": "a credential with no value", "url": "https://api.example.com/v1/search?token&page=2", "recorded": "https://api.example.com/v1/search?token=%5Bredacted%5D&page=2"},
      {"name": "a value holding an equals sign", "url": "https://api.example.com/v1/files?sig=a=b%3D&page=2", "recorded": "https://api.example.com/v1/files?sig=%5Bredacted%5D&page=2"},
      {"name": "an empty parameter kept", "url": "https://api.example.com/v1/search?page=2&&key=k", "recorded": "https://api.example.com/v1/search?page=2&&key=%5Bredacted%5D"},
      {"name": "a fragment after the query", "url": "https://api.example.com/v1/search?key=k&q=claims#top", "recorded": "https://api.example.com/v1/search?key=%5Bredacted%5D&q=claims#top"},
      {"name": "a name that does not decode is compared as sent", "url": "https://api.example.com/v1/search?%zz=1&key=k", "recorded": "https://api.example.com/v1/search?%zz=1&key=%5Bredacted%5D"},
      {"name": "a look-alike letter names another parameter", "url": "https://api.example.com/v1/search?%E2%84%AAey=k", "recorded": "https://api.example.com/v1/search?%E2%84%AAey=k"},
      {"name": "a password in the URL", "url": "https://ann:hunter2@api.example.com/v1/chat?page=2", "recorded": "https://%5Bredacted%5D@api.example.com/v1/chat?page=2"},
      {"name": "a password in the URL with no query", "url": "https://ann:p%40ss@api.example.com/v1/chat", "recorded": "https://%5Bredacted%5D@api.example.com/v1/chat"},
      {"name": "a password in the URL with no path", "url": "https://ann:hunter2@api.example.com", "recorded": "https://%5Bredacted%5D@api.example.com"},
      {"name": "a reference with no scheme", "url": "/v1/search?key=k&q=claims", "recorded": "/v1/search?key=%5Bredacted%5D&q=claims"}
    ],
    "scrubbed": [
      {"name": "a query string in text", "value": "GET /v1/search?api_key=s3cr3t-value&q=claims", "scrubbed": "GET /v1/search?api_key=[CREDENTIAL]&q=claims"},
      {"name": "key=value text", "value": "retry with token=abc123 next", "scrubbed": "retry with token=[CREDENTIAL] next"},
      {"name": "a credential name in another case", "value": "Password=hunter2", "scrubbed": "Password=[CREDENTIAL]"},
      {"name": "a JSON object key", "value": {"password": "hunter2", "user": "ann"}, "scrubbed": {"password": "[CREDENTIAL]", "user": "ann"}},
      {"name": "an Authorization header", "value": {"Authorization": "Bearer abc.def.ghi"}, "scrubbed": {"Authorization": "[CREDENTIAL]"}},
      {"name": "a JSON document in a string", "value": "{\"api_key\": \"abc123\"}", "scrubbed": "{\"api_key\": \"[CREDENTIAL]\"}"},
      {"name": "a Bearer token in text", "value": "sent Bearer eyJhbGciOiJIUzI1NiJ9.e30.c2lnbmF0dXJl", "scrubbed": "sent Bearer [CREDENTIAL]"}
    ]
  },
  "custody_hints": {
    "about": "What an agent may say of a field's custody, as the event's own top-level field custody, {path: hint}, never inside its data: a stricter outcome than the policy's (scrub, hash-only - never looser), or that it was cleaned before BitExact saw it (scrubbed-upstream, recorded as the agent's claim; scrubbed-upstream:TOOL names the tool that cleaned it). The event field capture is the collector's alone: a source may never set it.",
    "hints": ["scrub", "hash-only", "scrubbed-upstream"],
    "field": "custody",
    "collector_only": "capture",
    "examples": [
      {"hint": "scrub", "valid": true},
      {"hint": "hash-only", "valid": true},
      {"hint": "scrubbed-upstream", "valid": true},
      {"hint": "scrubbed-upstream:presidio", "valid": true},
      {"hint": "scrubbed-upstream:in-house.v2_1", "valid": true},
      {"hint": "keep", "valid": false},
      {"hint": "Hash-only", "valid": false},
      {"hint": "encrypt", "valid": false},
      {"hint": "scrubbed-upstream:", "valid": false},
      {"hint": "scrubbed-upstream:-presidio", "valid": false},
      {"hint": "scrubbed-upstream:a b", "valid": false}
    ],
    "tool_call": {
      "about": "A tool wrapped with custody sends the hints as its event's custody field, beside the data, not in it; the capture policy declares each field as they say.",
      "tool": "kyc_lookup",
      "custody": {"args": "scrubbed-upstream:presidio", "result": "hash-only"},
      "data": {"tool": "kyc_lookup", "args": ["[PERSON], born [DATE]"], "status": "ok", "result": "match"},
      "declared": {"args": {"mode": "scrubbed-upstream", "by": "presidio"}, "result": {"mode": "hash-only"}}
    }
  },
  "check_outcomes": {
    "about": "The outcomes a policy_check may record, in reader order. decided are the ones a check itself returns: pass, fail, warn, or held - it neither passed nor failed the action but held it for a human. error is a check that raised; unknown is a result that said none of these, recorded as such, never guessed. One vocabulary: every SDK's copy is this one.",
    "outcomes": ["pass", "fail", "warn", "held", "error", "unknown"],
    "decided": ["pass", "fail", "warn", "held"]
  },
  "identity": [
    {"name": "every existing field", "data": {"principal": "svc:loan-adjudicator", "agent_id": "agent:triage", "delegation_from": "app:portal", "scope": ["read:claims"], "policy_version": "pol-3", "prompt_pack_version": "pp-2", "model_version": "m-1", "workflow_version": "v4", "environment": "prod", "code": "abc123", "workflow_instance": "application-77"}, "kept": {"principal": "svc:loan-adjudicator", "agent_id": "agent:triage", "delegation_from": "app:portal", "scope": ["read:claims"], "policy_version": "pol-3", "prompt_pack_version": "pp-2", "model_version": "m-1", "workflow_version": "v4", "environment": "prod", "code": "abc123", "workflow_instance": "application-77"}, "rejected": []},
    {"name": "on behalf of a person, with the authority cited", "data": {"on_behalf_of": "user:7f3a9c", "on_behalf_of_type": "human", "authority_ref": "consent:2026-10-30/88412"}, "kept": {"on_behalf_of": "user:7f3a9c", "on_behalf_of_type": "human", "authority_ref": "consent:2026-10-30/88412"}, "rejected": []},
    {"name": "an entry that states nothing keeps nothing (and every door refuses it whole)", "data": {}, "kept": {}, "rejected": []},
    {"name": "an entry whose every field is null keeps nothing (and every door refuses it whole)", "data": {"principal": null, "on_behalf_of": null}, "kept": {}, "rejected": []},
    {"name": "a key named __proto__ is data like any unknown key, and names no party", "data": {"__proto__": {"on_behalf_of": "x"}, "on_behalf_of_type": "human"}, "kept": {"__proto__": {"on_behalf_of": "x"}}, "rejected": ["on_behalf_of_type"]},
    {"name": "on behalf of an organization", "data": {"on_behalf_of": "org:retail-bank", "on_behalf_of_type": "organization"}, "kept": {"on_behalf_of": "org:retail-bank", "on_behalf_of_type": "organization"}, "rejected": []},
    {"name": "on behalf of a service", "data": {"on_behalf_of": "svc:batch", "on_behalf_of_type": "service"}, "kept": {"on_behalf_of": "svc:batch", "on_behalf_of_type": "service"}, "rejected": []},
    {"name": "on behalf of another agent", "data": {"on_behalf_of": "agent:planner", "on_behalf_of_type": "agent"}, "kept": {"on_behalf_of": "agent:planner", "on_behalf_of_type": "agent"}, "rejected": []},
    {"name": "on behalf of, with no type", "data": {"on_behalf_of": "user:7f3a9c"}, "kept": {"on_behalf_of": "user:7f3a9c"}, "rejected": []},
    {"name": "a person in the session", "data": {"interaction_mode": "interactive"}, "kept": {"interaction_mode": "interactive"}, "rejected": []},
    {"name": "no person in the session", "data": {"interaction_mode": "autonomous"}, "kept": {"interaction_mode": "autonomous"}, "rejected": []},
    {"name": "a mode in the wrong case", "data": {"interaction_mode": "Interactive"}, "kept": {}, "rejected": ["interaction_mode"]},
    {"name": "a mode that is not one of the two", "data": {"interaction_mode": "supervised"}, "kept": {}, "rejected": ["interaction_mode"]},
    {"name": "a party type that is not one of the four", "data": {"on_behalf_of": "user:1", "on_behalf_of_type": "person"}, "kept": {"on_behalf_of": "user:1"}, "rejected": ["on_behalf_of_type"]},
    {"name": "a party type with no party", "data": {"on_behalf_of_type": "human"}, "kept": {}, "rejected": ["on_behalf_of_type"]},
    {"name": "an authority with no party", "data": {"authority_ref": "consent:1"}, "kept": {}, "rejected": ["authority_ref"]},
    {"name": "an empty party", "data": {"on_behalf_of": ""}, "kept": {}, "rejected": ["on_behalf_of"]},
    {"name": "an empty authority", "data": {"on_behalf_of": "user:1", "authority_ref": ""}, "kept": {"on_behalf_of": "user:1"}, "rejected": ["authority_ref"]},
    {"name": "a party that is a number", "data": {"on_behalf_of": 7}, "kept": {}, "rejected": ["on_behalf_of"]},
    {"name": "a rejected party takes its type and authority with it", "data": {"on_behalf_of": "", "on_behalf_of_type": "human", "authority_ref": "consent:1"}, "kept": {}, "rejected": ["authority_ref", "on_behalf_of", "on_behalf_of_type"]},
    {"name": "a workflow digest from the caller", "data": {"workflow_digest": "00ff"}, "kept": {}, "rejected": ["workflow_digest"]},
    {"name": "a principal that is a number", "data": {"principal": 123}, "kept": {}, "rejected": ["principal"]},
    {"name": "a scope that is a string", "data": {"scope": "read:claims"}, "kept": {}, "rejected": ["scope"]},
    {"name": "a scope of numbers", "data": {"scope": [1, 2]}, "kept": {}, "rejected": ["scope"]},
    {"name": "a field left as null is left out", "data": {"principal": null, "environment": "prod"}, "kept": {"environment": "prod"}, "rejected": []},
    {"name": "an unknown key is kept as sent", "data": {"tenant": "t-9", "environment": "prod"}, "kept": {"tenant": "t-9", "environment": "prod"}, "rejected": []},
    {"name": "good fields kept, bad ones listed", "data": {"principal": "svc:a", "interaction_mode": "sometimes", "on_behalf_of": "user:2", "on_behalf_of_type": "human", "scope": "x"}, "kept": {"principal": "svc:a", "on_behalf_of": "user:2", "on_behalf_of_type": "human"}, "rejected": ["interaction_mode", "scope"]}
  ]
}
