// AUTO-GENERATED by build.rs from schemas/*.schema.json
// DO NOT EDIT — changes will be overwritten on next build.
// To modify types, edit the JSON Schema files in schemas/ and rebuild.
/// Error types.
pub mod error {
/// Error from a `TryFrom` or `FromStr` implementation.
pub struct ConversionError(::std::borrow::Cow<'static, str>);
impl ::std::error::Error for ConversionError {}
impl ::std::fmt::Display for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Display::fmt(&self.0, f)
}
}
impl ::std::fmt::Debug for ConversionError {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> Result<(), ::std::fmt::Error> {
::std::fmt::Debug::fmt(&self.0, f)
}
}
impl From<&'static str> for ConversionError {
fn from(value: &'static str) -> Self {
Self(value.into())
}
}
impl From<String> for ConversionError {
fn from(value: String) -> Self {
Self(value.into())
}
}
}
///Who ratified or changed a policy. 'system' = library seeding, 'migration' = migration 037. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Who ratified or changed a policy. 'system' = library seeding, 'migration' = migration 037. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "user",
/// "system",
/// "migration"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct ActorKind(pub ::std::string::String);
impl ::std::ops::Deref for ActorKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ActorKind> for ::std::string::String {
fn from(value: ActorKind) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for ActorKind {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for ActorKind {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for ActorKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///What KIND of work an agent does — the PRD's `AgentType` enum, renamed here because this schema's AgentType is already taken by the CloudEvents 'source' agent-platform vocabulary (claude-code, cursor, …) mirrored in src/core/envelope/known_types.rs. The two are unrelated; do not merge them. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What KIND of work an agent does — the PRD's `AgentType` enum, renamed here because this schema's AgentType is already taken by the CloudEvents 'source' agent-platform vocabulary (claude-code, cursor, …) mirrored in src/core/envelope/known_types.rs. The two are unrelated; do not merge them. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "coding",
/// "analysis",
/// "ops",
/// "content",
/// "service"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct AgentCategory(pub ::std::string::String);
impl ::std::ops::Deref for AgentCategory {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AgentCategory> for ::std::string::String {
fn from(value: AgentCategory) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for AgentCategory {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for AgentCategory {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for AgentCategory {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///The business function the platform assigned to an agent's owner — the frozen 14-value vocabulary of the Agent Ownership PRD (D9: adding a value is already a contract change plus a client release, so a closed enum here couples nothing new). Closed enum, like ChurnLayer: it is the value type of a policy rule's conditions[].value (policy-bundle.schema.json), where the client compares by enum equality and a value it does not know fails that ONE rule at deserialization (dropped as unrecognized_field, the bundle stays active) — never the whole document. It is deliberately NOT the type of client_config.agent_context.function, which stays an open string carrying this list as x-known-values: client_config is deserialized as one typed object outside the per-rule tolerance, so an enum there would fail the whole bundle (fail-static fleet-wide) on a single unrecognised value. That buys tolerance for an unrecognised WORD only — a non-string function still fails the whole document, because client_config is typed either way. 'unknown' is an ordinary member — a rule listing it matches only agents whose function is 'unknown'; it is never a wildcard.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The business function the platform assigned to an agent's owner — the frozen 14-value vocabulary of the Agent Ownership PRD (D9: adding a value is already a contract change plus a client release, so a closed enum here couples nothing new). Closed enum, like ChurnLayer: it is the value type of a policy rule's conditions[].value (policy-bundle.schema.json), where the client compares by enum equality and a value it does not know fails that ONE rule at deserialization (dropped as unrecognized_field, the bundle stays active) — never the whole document. It is deliberately NOT the type of client_config.agent_context.function, which stays an open string carrying this list as x-known-values: client_config is deserialized as one typed object outside the per-rule tolerance, so an enum there would fail the whole bundle (fail-static fleet-wide) on a single unrecognised value. That buys tolerance for an unrecognised WORD only — a non-string function still fails the whole document, because client_config is typed either way. 'unknown' is an ordinary member — a rule listing it matches only agents whose function is 'unknown'; it is never a wildcard.",
/// "type": "string",
/// "enum": [
/// "engineering",
/// "product",
/// "data",
/// "security",
/// "it_ops",
/// "sales",
/// "marketing",
/// "finance",
/// "legal",
/// "hr",
/// "support",
/// "research",
/// "other",
/// "unknown"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum AgentFunction {
#[serde(rename = "engineering")]
Engineering,
#[serde(rename = "product")]
Product,
#[serde(rename = "data")]
Data,
#[serde(rename = "security")]
Security,
#[serde(rename = "it_ops")]
ItOps,
#[serde(rename = "sales")]
Sales,
#[serde(rename = "marketing")]
Marketing,
#[serde(rename = "finance")]
Finance,
#[serde(rename = "legal")]
Legal,
#[serde(rename = "hr")]
Hr,
#[serde(rename = "support")]
Support,
#[serde(rename = "research")]
Research,
#[serde(rename = "other")]
Other,
#[serde(rename = "unknown")]
Unknown,
}
impl ::std::fmt::Display for AgentFunction {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Engineering => f.write_str("engineering"),
Self::Product => f.write_str("product"),
Self::Data => f.write_str("data"),
Self::Security => f.write_str("security"),
Self::ItOps => f.write_str("it_ops"),
Self::Sales => f.write_str("sales"),
Self::Marketing => f.write_str("marketing"),
Self::Finance => f.write_str("finance"),
Self::Legal => f.write_str("legal"),
Self::Hr => f.write_str("hr"),
Self::Support => f.write_str("support"),
Self::Research => f.write_str("research"),
Self::Other => f.write_str("other"),
Self::Unknown => f.write_str("unknown"),
}
}
}
impl ::std::str::FromStr for AgentFunction {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"engineering" => Ok(Self::Engineering),
"product" => Ok(Self::Product),
"data" => Ok(Self::Data),
"security" => Ok(Self::Security),
"it_ops" => Ok(Self::ItOps),
"sales" => Ok(Self::Sales),
"marketing" => Ok(Self::Marketing),
"finance" => Ok(Self::Finance),
"legal" => Ok(Self::Legal),
"hr" => Ok(Self::Hr),
"support" => Ok(Self::Support),
"research" => Ok(Self::Research),
"other" => Ok(Self::Other),
"unknown" => Ok(Self::Unknown),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for AgentFunction {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for AgentFunction {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for AgentFunction {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Lifecycle of an anomaly in the inbox; carried alongside read_at / archived_at. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Lifecycle of an anomaly in the inbox; carried alongside read_at / archived_at. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "open",
/// "pending_ask",
/// "answered",
/// "retired"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct AnomalyStatus(pub ::std::string::String);
impl ::std::ops::Deref for AnomalyStatus {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AnomalyStatus> for ::std::string::String {
fn from(value: AnomalyStatus) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for AnomalyStatus {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for AnomalyStatus {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for AnomalyStatus {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Discriminator for a policy-bundle artifacts[] entry. Two-stage parse: the envelope is typed, the per-kind body is selected by this value in application code (build.rs strips if/then/else before typify, so the discriminator cannot live in the schema). An unknown kind means the item is SKIPPED, never the bundle rejected. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Discriminator for a policy-bundle artifacts[] entry. Two-stage parse: the envelope is typed, the per-kind body is selected by this value in application code (build.rs strips if/then/else before typify, so the discriminator cannot live in the schema). An unknown kind means the item is SKIPPED, never the bundle rejected. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "t1_predicate_tree",
/// "t2_register_program",
/// "t3_hold",
/// "exception",
/// "command",
/// "request"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct ArtifactKind(pub ::std::string::String);
impl ::std::ops::Deref for ArtifactKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ArtifactKind> for ::std::string::String {
fn from(value: ArtifactKind) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for ArtifactKind {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for ArtifactKind {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for ArtifactKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///State of one ASK ground — the deduplicated question an ask verdict opens. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "State of one ASK ground — the deduplicated question an ask verdict opens. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "pending",
/// "answered_allow",
/// "answered_block",
/// "auto_resolved",
/// "retired"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct AskGroundState(pub ::std::string::String);
impl ::std::ops::Deref for AskGroundState {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AskGroundState> for ::std::string::String {
fn from(value: AskGroundState) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for AskGroundState {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for AskGroundState {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for AskGroundState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///How widely a human's answer to an ASK applies, narrowest to widest. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "How widely a human's answer to an ASK applies, narrowest to widest. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "exact_action",
/// "resource_class",
/// "rule_agent",
/// "rule_zone"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct AskScope(pub ::std::string::String);
impl ::std::ops::Deref for AskScope {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<AskScope> for ::std::string::String {
fn from(value: AskScope) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for AskScope {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for AskScope {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for AskScope {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Response from GET /api/v1/users/me for auth status validation (D-19) and PostHog identity stitching (telemetry Phase C). user_db_id, when present, is used as the persistent distinct_id and triggers a one-time $create_alias merging prior agent_id events into the platform person. Mirrors the `id` field on the platform side; both carry the stable better-auth user TEXT primary key.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Response from GET /api/v1/users/me for auth status validation (D-19) and PostHog identity stitching (telemetry Phase C). user_db_id, when present, is used as the persistent distinct_id and triggers a one-time $create_alias merging prior agent_id events into the platform person. Mirrors the `id` field on the platform side; both carry the stable better-auth user TEXT primary key.",
/// "examples": [
/// {
/// "id": "usr_019d8af1-f8da-73b3-92eb-79a99e59b10b",
/// "user_db_id": "usr_019d8af1-f8da-73b3-92eb-79a99e59b10b",
/// "email": "alice@example.com",
/// "organization_id": "a1b2c3d4-e5f6-4000-a000-000000000001",
/// "organization_name": "Acme Corp"
/// }
/// ],
/// "type": "object",
/// "properties": {
/// "email": {
/// "description": "Email of the authenticated user.",
/// "type": "string"
/// },
/// "id": {
/// "description": "Stable database identifier for the authenticated user (better-auth user.id). Mirror of user_db_id — either field may be read; prefer user_db_id for telemetry alias semantics.",
/// "type": "string"
/// },
/// "organization_id": {
/// "description": "Organization id for the user's active organization.",
/// "type": "string"
/// },
/// "organization_name": {
/// "description": "Human-readable display name of the user's active organization. Surfaced by the client on re-runs of `openlatch init` so the user can confirm which org their cached credential belongs to. Optional — when absent, the client displays `Authenticated` without the parenthetical org suffix.",
/// "type": "string"
/// },
/// "user_db_id": {
/// "description": "Stable database identifier for the authenticated user. Used as the PostHog distinct_id post-auth and as the alias target for $create_alias. Optional in this client schema for backwards compatibility — older platforms may not return it; client falls back to agent_id and skips the alias when absent.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true,
/// "x-postgresql-skip": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct AuthMeResponse {
///Email of the authenticated user.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub email: ::std::option::Option<::std::string::String>,
///Stable database identifier for the authenticated user (better-auth user.id). Mirror of user_db_id — either field may be read; prefer user_db_id for telemetry alias semantics.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub id: ::std::option::Option<::std::string::String>,
///Organization id for the user's active organization.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub organization_id: ::std::option::Option<::std::string::String>,
///Human-readable display name of the user's active organization. Surfaced by the client on re-runs of `openlatch init` so the user can confirm which org their cached credential belongs to. Optional — when absent, the client displays `Authenticated` without the parenthetical org suffix.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub organization_name: ::std::option::Option<::std::string::String>,
///Stable database identifier for the authenticated user. Used as the PostHog distinct_id post-auth and as the alias target for $create_alias. Optional in this client schema for backwards compatibility — older platforms may not return it; client falls back to agent_id and skips the alias when absent.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub user_db_id: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for AuthMeResponse {
fn default() -> Self {
Self {
email: Default::default(),
id: Default::default(),
organization_id: Default::default(),
organization_name: Default::default(),
user_db_id: Default::default(),
}
}
}
///Which ADAPTER produced a decision — the binding names the adapter, never the transport. Every binding here reaches a local decision and nothing else: Mode 2 is a thin Python adapter over the local daemon, strictly required — one hop, no in-process engine, and it never degrades to the network. 'remote_decide' names the remote decision endpoint, which is specified and not built; were it ever delivered it would be a departure recorded for the one named runtime that needed it, never a fallback another binding may reach for. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Which ADAPTER produced a decision — the binding names the adapter, never the transport. Every binding here reaches a local decision and nothing else: Mode 2 is a thin Python adapter over the local daemon, strictly required — one hop, no in-process engine, and it never degrades to the network. 'remote_decide' names the remote decision endpoint, which is specified and not built; were it ever delivered it would be a departure recorded for the one named runtime that needed it, never a fallback another binding may reach for. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "claude_code_hook",
/// "langchain_middleware",
/// "langgraph_middleware",
/// "openai_agents",
/// "mcp_gate",
/// "foundry_client",
/// "foundry_approver",
/// "agent_gateway_extension",
/// "adk_callback",
/// "remote_decide"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct Binding(pub ::std::string::String);
impl ::std::ops::Deref for Binding {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Binding> for ::std::string::String {
fn from(value: Binding) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for Binding {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for Binding {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for Binding {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///`BundleFact`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "BundleFact",
/// "type": "object",
/// "properties": {
/// "closed_world": {
/// "description": "Whether membership in this fact is exhaustive. True means 'not in the set' is a real negative; false means it is unknown, and a leaf testing non-membership is inconclusive rather than matching. The difference between 'this host is not approved' and 'we do not know whether it is'.",
/// "type": "boolean"
/// },
/// "fact_id": {
/// "description": "Identifier a fact leaf names. Open, carrying the known vocabulary as x-known-values: a fact the client does not know is still carried and still resolvable by id, because the evaluator matches on the id, not on a variant.",
/// "$ref": "#/$defs/FactId"
/// },
/// "kind": {
/// "description": "The fact's shape — what `value` holds and how a leaf may compare against it (a set, a scalar, a table). Open, and a fact whose kind the client cannot interpret resolves as ABSENT rather than as a default.",
/// "type": "string"
/// },
/// "leeway_s": {
/// "description": "Grace added to max_age_s, in seconds, so ordinary clock skew and a late refresh do not flip a fact to absent and turn every rule reading it inconclusive at once.",
/// "type": "integer"
/// },
/// "max_age_s": {
/// "description": "How old the observation may be before the fact resolves as absent, in seconds. The client compares against the daemon-injected now_ms, never the wall clock read inside the evaluator.",
/// "type": "integer"
/// },
/// "observed_at": {
/// "description": "RFC 3339 UTC timestamp of when the value was observed at the source, NOT when the bundle was built. Age is measured from here, so a bundle rebuild cannot make a stale fact look fresh.",
/// "type": "string"
/// },
/// "revision": {
/// "description": "Monotonic revision of this fact, matching its entry in inputs.fact_revs.",
/// "type": "integer"
/// },
/// "source": {
/// "description": "Where the value came from — which connector or upload produced it. Shown to whoever has to answer for a fact-driven deny.",
/// "type": "string"
/// },
/// "valid_from": {
/// "description": "Optional RFC 3339 lower bound on when this value applies. Absent means it applies from observed_at.",
/// "type": "string"
/// },
/// "valid_until": {
/// "description": "Optional RFC 3339 upper bound. Past it the fact is ABSENT, not false.",
/// "type": "string"
/// },
/// "value": {
/// "description": "The fact's content, in the shape its `kind` declares. Deliberately unconstrained — the evaluator interprets it per kind, and a type keyword here would fail the whole bundle on one fact whose kind the schema had not anticipated."
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct BundleFact {
///Whether membership in this fact is exhaustive. True means 'not in the set' is a real negative; false means it is unknown, and a leaf testing non-membership is inconclusive rather than matching. The difference between 'this host is not approved' and 'we do not know whether it is'.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub closed_world: ::std::option::Option<bool>,
///Identifier a fact leaf names. Open, carrying the known vocabulary as x-known-values: a fact the client does not know is still carried and still resolvable by id, because the evaluator matches on the id, not on a variant.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub fact_id: ::std::option::Option<FactId>,
///The fact's shape — what `value` holds and how a leaf may compare against it (a set, a scalar, a table). Open, and a fact whose kind the client cannot interpret resolves as ABSENT rather than as a default.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub kind: ::std::option::Option<::std::string::String>,
///Grace added to max_age_s, in seconds, so ordinary clock skew and a late refresh do not flip a fact to absent and turn every rule reading it inconclusive at once.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub leeway_s: ::std::option::Option<i64>,
///How old the observation may be before the fact resolves as absent, in seconds. The client compares against the daemon-injected now_ms, never the wall clock read inside the evaluator.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub max_age_s: ::std::option::Option<i64>,
///RFC 3339 UTC timestamp of when the value was observed at the source, NOT when the bundle was built. Age is measured from here, so a bundle rebuild cannot make a stale fact look fresh.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub observed_at: ::std::option::Option<::std::string::String>,
///Monotonic revision of this fact, matching its entry in inputs.fact_revs.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub revision: ::std::option::Option<i64>,
///Where the value came from — which connector or upload produced it. Shown to whoever has to answer for a fact-driven deny.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub source: ::std::option::Option<::std::string::String>,
///Optional RFC 3339 lower bound on when this value applies. Absent means it applies from observed_at.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub valid_from: ::std::option::Option<::std::string::String>,
///Optional RFC 3339 upper bound. Past it the fact is ABSENT, not false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub valid_until: ::std::option::Option<::std::string::String>,
///The fact's content, in the shape its `kind` declares. Deliberately unconstrained — the evaluator interprets it per kind, and a type keyword here would fail the whole bundle on one fact whose kind the schema had not anticipated.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub value: ::std::option::Option<::serde_json::Value>,
}
impl ::std::default::Default for BundleFact {
fn default() -> Self {
Self {
closed_world: Default::default(),
fact_id: Default::default(),
kind: Default::default(),
leeway_s: Default::default(),
max_age_s: Default::default(),
observed_at: Default::default(),
revision: Default::default(),
source: Default::default(),
valid_from: Default::default(),
valid_until: Default::default(),
value: Default::default(),
}
}
}
///`BundleFactRef`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "BundleFactRef",
/// "type": "object",
/// "properties": {
/// "fact_id": {
/// "description": "Identifier a fact leaf names, exactly as for an inline fact — a leaf cannot tell whether its fact arrived inline or by reference.",
/// "$ref": "#/$defs/FactId"
/// },
/// "max_age_s": {
/// "description": "How old the observation may be before the fact resolves as absent, in seconds.",
/// "type": "integer"
/// },
/// "observed_at": {
/// "description": "RFC 3339 UTC timestamp of observation at the source, as for an inline fact.",
/// "type": "string"
/// },
/// "revision": {
/// "description": "Monotonic revision, matching this fact's entry in inputs.fact_revs. A changed revision is what tells the poller to refetch.",
/// "type": "integer"
/// },
/// "sha256": {
/// "description": "Lowercase hex digest of the fetched bytes. A mismatch resolves the fact as absent; the client never evaluates against bytes it could not verify.",
/// "type": "string"
/// },
/// "size_bytes": {
/// "description": "Expected size, so a response that is wildly wrong is abandoned before it is buffered.",
/// "type": "integer"
/// },
/// "url": {
/// "description": "Where the bytes are fetched from. Fetched by the poller, off the verdict path — an evaluation that needed a round trip to decide would be a design error, not a slow path.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct BundleFactRef {
///Identifier a fact leaf names, exactly as for an inline fact — a leaf cannot tell whether its fact arrived inline or by reference.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub fact_id: ::std::option::Option<FactId>,
///How old the observation may be before the fact resolves as absent, in seconds.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub max_age_s: ::std::option::Option<i64>,
///RFC 3339 UTC timestamp of observation at the source, as for an inline fact.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub observed_at: ::std::option::Option<::std::string::String>,
///Monotonic revision, matching this fact's entry in inputs.fact_revs. A changed revision is what tells the poller to refetch.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub revision: ::std::option::Option<i64>,
///Lowercase hex digest of the fetched bytes. A mismatch resolves the fact as absent; the client never evaluates against bytes it could not verify.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub sha256: ::std::option::Option<::std::string::String>,
///Expected size, so a response that is wildly wrong is abandoned before it is buffered.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub size_bytes: ::std::option::Option<i64>,
///Where the bytes are fetched from. Fetched by the poller, off the verdict path — an evaluation that needed a round trip to decide would be a design error, not a slow path.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub url: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for BundleFactRef {
fn default() -> Self {
Self {
fact_id: Default::default(),
max_age_s: Default::default(),
observed_at: Default::default(),
revision: Default::default(),
sha256: Default::default(),
size_bytes: Default::default(),
url: Default::default(),
}
}
}
///Which prompt-cache layer a kind=request policy rule targets — the frozen churn_layer enum owned by the Model Boundary Enforcement Layer. 'tools' invalidates everything downstream on a change; 'messages' the least. Closed enum, like Verdict: the values are a contract between the platform's rule author and the client's boundary listener, so the client branches exhaustively on them. A hand-written boundary-internal twin exists at src/boundary/churn.rs; this $def is the wire-side type and the single owner of the values.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Which prompt-cache layer a kind=request policy rule targets — the frozen churn_layer enum owned by the Model Boundary Enforcement Layer. 'tools' invalidates everything downstream on a change; 'messages' the least. Closed enum, like Verdict: the values are a contract between the platform's rule author and the client's boundary listener, so the client branches exhaustively on them. A hand-written boundary-internal twin exists at src/boundary/churn.rs; this $def is the wire-side type and the single owner of the values.",
/// "type": "string",
/// "enum": [
/// "tools",
/// "system",
/// "messages"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum ChurnLayer {
#[serde(rename = "tools")]
Tools,
#[serde(rename = "system")]
System,
#[serde(rename = "messages")]
Messages,
}
impl ::std::fmt::Display for ChurnLayer {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Tools => f.write_str("tools"),
Self::System => f.write_str("system"),
Self::Messages => f.write_str("messages"),
}
}
}
impl ::std::str::FromStr for ChurnLayer {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"tools" => Ok(Self::Tools),
"system" => Ok(Self::System),
"messages" => Ok(Self::Messages),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for ChurnLayer {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for ChurnLayer {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for ChurnLayer {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///HTTP request body for POST /api/v1/events/ingest sent by openlatch-client. CloudEvents v1.0.2 batch mode — a bare JSON array of EventEnvelope objects, sent with Content-Type: application/cloudevents-batch+json. Client-wide metadata (schema_version, agent_id) is carried on each CloudEvent via extension attributes rather than a wrapper object.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "HTTP request body for POST /api/v1/events/ingest sent by openlatch-client. CloudEvents v1.0.2 batch mode — a bare JSON array of EventEnvelope objects, sent with Content-Type: application/cloudevents-batch+json. Client-wide metadata (schema_version, agent_id) is carried on each CloudEvent via extension attributes rather than a wrapper object.",
/// "examples": [
/// [
/// {
/// "specversion": "1.0",
/// "id": "evt_019d8af1-f8da-73b3-92eb-79a99e59b10b",
/// "source": "claude-code",
/// "type": "pre_tool_use",
/// "time": "2026-04-16T12:00:00Z",
/// "datacontenttype": "application/json",
/// "subject": "sess_abc123",
/// "data": {
/// "tool_name": "Bash",
/// "tool_input": {
/// "command": "ls -la"
/// }
/// },
/// "os": "linux",
/// "arch": "x86_64",
/// "clientversion": "0.2.0"
/// }
/// ]
/// ],
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/EventEnvelope"
/// },
/// "maxItems": 100,
/// "minItems": 1,
/// "x-postgresql-skip": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(transparent)]
pub struct CloudIngestionRequest(pub ::std::vec::Vec<EventEnvelope>);
impl ::std::ops::Deref for CloudIngestionRequest {
type Target = ::std::vec::Vec<EventEnvelope>;
fn deref(&self) -> &::std::vec::Vec<EventEnvelope> {
&self.0
}
}
impl ::std::convert::From<CloudIngestionRequest> for ::std::vec::Vec<EventEnvelope> {
fn from(value: CloudIngestionRequest) -> Self {
value.0
}
}
impl ::std::convert::From<::std::vec::Vec<EventEnvelope>> for CloudIngestionRequest {
fn from(value: ::std::vec::Vec<EventEnvelope>) -> Self {
Self(value)
}
}
///HTTP response body for POST /api/v1/events/ingest returned to openlatch-client. The client uses status to determine whether to retry, and event_id to correlate verdicts.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "HTTP response body for POST /api/v1/events/ingest returned to openlatch-client. The client uses status to determine whether to retry, and event_id to correlate verdicts.",
/// "examples": [
/// {
/// "status": "accepted",
/// "event_id": "019d8af1-f8da-73b3-92eb-79a99e59b10b"
/// },
/// {
/// "status": "rejected",
/// "error": "Envelope failed schema validation: missing required attribute 'specversion'"
/// }
/// ],
/// "type": "object",
/// "required": [
/// "status"
/// ],
/// "properties": {
/// "error": {
/// "description": "Human-readable error description. Present when status is rejected.",
/// "type": "string"
/// },
/// "event_id": {
/// "description": "Server-assigned UUIDv7 event_id for the stored event. Present when status is accepted.",
/// "type": "string"
/// },
/// "status": {
/// "description": "Ingestion outcome — accepted means persisted (or duplicate), rejected means permanently invalid.",
/// "type": "string",
/// "enum": [
/// "accepted",
/// "rejected"
/// ]
/// }
/// },
/// "additionalProperties": false,
/// "x-postgresql-skip": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct CloudIngestionResponse {
///Human-readable error description. Present when status is rejected.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub error: ::std::option::Option<::std::string::String>,
///Server-assigned UUIDv7 event_id for the stored event. Present when status is accepted.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub event_id: ::std::option::Option<::std::string::String>,
///Ingestion outcome — accepted means persisted (or duplicate), rejected means permanently invalid.
pub status: CloudIngestionResponseStatus,
}
///Ingestion outcome — accepted means persisted (or duplicate), rejected means permanently invalid.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Ingestion outcome — accepted means persisted (or duplicate), rejected means permanently invalid.",
/// "type": "string",
/// "enum": [
/// "accepted",
/// "rejected"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum CloudIngestionResponseStatus {
#[serde(rename = "accepted")]
Accepted,
#[serde(rename = "rejected")]
Rejected,
}
impl ::std::fmt::Display for CloudIngestionResponseStatus {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Accepted => f.write_str("accepted"),
Self::Rejected => f.write_str("rejected"),
}
}
}
impl ::std::str::FromStr for CloudIngestionResponseStatus {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"accepted" => Ok(Self::Accepted),
"rejected" => Ok(Self::Rejected),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for CloudIngestionResponseStatus {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for CloudIngestionResponseStatus {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for CloudIngestionResponseStatus {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///How much control OpenLatch actually exercises over an install. Derived (D7), never authored: 'enforced' has Enforce-mode policies acting on it, 'monitored' is recorded-only, 'known' has nothing enforced. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "How much control OpenLatch actually exercises over an install. Derived (D7), never authored: 'enforced' has Enforce-mode policies acting on it, 'monitored' is recorded-only, 'known' has nothing enforced. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "enforced",
/// "monitored",
/// "known"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct ControlLevel(pub ::std::string::String);
impl ::std::ops::Deref for ControlLevel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ControlLevel> for ::std::string::String {
fn from(value: ControlLevel) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for ControlLevel {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for ControlLevel {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for ControlLevel {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///What actually HAPPENED to the action, as distinct from the Verdict that was returned. 'deferred' = a headless (-p) hold handed back to the orchestrating integration, which resumes with `claude -p --resume <id>` once the answer is readable at GET /holds/{tool_use_id}. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What actually HAPPENED to the action, as distinct from the Verdict that was returned. 'deferred' = a headless (-p) hold handed back to the orchestrating integration, which resumes with `claude -p --resume <id>` once the answer is readable at GET /holds/{tool_use_id}. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "allowed",
/// "blocked",
/// "rewritten",
/// "steered",
/// "held_approved",
/// "held_rejected",
/// "held_timeout",
/// "deferred",
/// "flagged"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct DecisionResult(pub ::std::string::String);
impl ::std::ops::Deref for DecisionResult {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<DecisionResult> for ::std::string::String {
fn from(value: DecisionResult) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for DecisionResult {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for DecisionResult {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for DecisionResult {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Which axis of the Autonomy Zone a policy governs. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Which axis of the Autonomy Zone a policy governs. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "quality",
/// "economics",
/// "security",
/// "safety",
/// "compliance"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct Dimension(pub ::std::string::String);
impl ::std::ops::Deref for Dimension {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Dimension> for ::std::string::String {
fn from(value: Dimension) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for Dimension {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for Dimension {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for Dimension {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///`DirectiveTemplate`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "DirectiveTemplate",
/// "type": "object",
/// "properties": {
/// "kind": {
/// "description": "What sort of directive this is. Open, and a hold naming a template whose kind the client cannot render falls back to its on_timeout verdict rather than emitting nothing.",
/// "type": "string"
/// },
/// "params": {
/// "description": "Names of the substitutions `text` expects. The client fills only these, from the event and the artifact — never from anything the model said.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "template_id": {
/// "description": "Identifier a t3_hold body names in directive_template_id.",
/// "type": "string"
/// },
/// "text": {
/// "description": "The directive itself, with its parameter placeholders. Deliberately unconstrained: a length keyword would make the generated Rust type a newtype whose deserializer fails the WHOLE bundle on one long template.",
/// "type": "string"
/// },
/// "version": {
/// "description": "Bumped whenever the owner edits the text, so a recorded reinforcement can be tied to the wording that produced it.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct DirectiveTemplate {
///What sort of directive this is. Open, and a hold naming a template whose kind the client cannot render falls back to its on_timeout verdict rather than emitting nothing.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub kind: ::std::option::Option<::std::string::String>,
///Names of the substitutions `text` expects. The client fills only these, from the event and the artifact — never from anything the model said.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub params: ::std::vec::Vec<::std::string::String>,
///Identifier a t3_hold body names in directive_template_id.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub template_id: ::std::option::Option<::std::string::String>,
///The directive itself, with its parameter placeholders. Deliberately unconstrained: a length keyword would make the generated Rust type a newtype whose deserializer fails the WHOLE bundle on one long template.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub text: ::std::option::Option<::std::string::String>,
///Bumped whenever the owner edits the text, so a recorded reinforcement can be tied to the wording that produced it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub version: ::std::option::Option<i64>,
}
impl ::std::default::Default for DirectiveTemplate {
fn default() -> Self {
Self {
kind: Default::default(),
params: Default::default(),
template_id: Default::default(),
text: Default::default(),
version: Default::default(),
}
}
}
///`EffectClassEntry`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "EffectClassEntry",
/// "type": "object",
/// "properties": {
/// "effects": {
/// "description": "The effect tuples a matching call produces.",
/// "type": "array",
/// "items": {
/// "title": "EffectTuple",
/// "type": "object",
/// "properties": {
/// "attrs": {
/// "description": "Attributes attached to this tuple, readable from a leaf as effect.attrs.<name> (D-16). The first is is_production, resolved from the env_selectors fact — a starter-library entry already reads effect.attrs.is_production, and without this the entry is unmatchable as written. Open by construction: an attribute the client does not know makes a leaf naming it inconclusive, never false.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "target_class": {
/// "description": "What it does it to.",
/// "$ref": "#/$defs/TargetClass"
/// },
/// "verb": {
/// "description": "What the action does.",
/// "$ref": "#/$defs/EffectVerb"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "id": {
/// "description": "Stable identifier for this entry.",
/// "type": "string"
/// },
/// "modified": {
/// "description": "Feed version or RFC 3339 timestamp of the last change to the entry.",
/// "type": "string"
/// },
/// "related": {
/// "description": "Ids of entries a reviewer should look at alongside this one.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "selectors": {
/// "description": "Attribute leaves narrowing WHICH calls of tool_key this entry classifies — the same leaf shape a Tier 1 predicate tree uses, so one classifier reads both. An entry with no selectors classifies every call of the tool.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/t1_leaf"
/// }
/// },
/// "since": {
/// "description": "Feed version or RFC 3339 timestamp at which the entry first appeared.",
/// "type": "string"
/// },
/// "status": {
/// "description": "Lifecycle of the entry in the feed. Open: an unknown status leaves the entry usable, because dropping a classification on a word the client did not recognise would silently widen what a rule fails to match.",
/// "type": "string"
/// },
/// "tool_key": {
/// "description": "The tool this entry classifies, as the evaluator sees it — 'Bash', or 'mcp__<server>__<tool>' for MCP.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct EffectClassEntry {
///The effect tuples a matching call produces.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub effects: ::std::vec::Vec<EffectTuple>,
///Stable identifier for this entry.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub id: ::std::option::Option<::std::string::String>,
///Feed version or RFC 3339 timestamp of the last change to the entry.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub modified: ::std::option::Option<::std::string::String>,
///Ids of entries a reviewer should look at alongside this one.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub related: ::std::vec::Vec<::std::string::String>,
///Attribute leaves narrowing WHICH calls of tool_key this entry classifies — the same leaf shape a Tier 1 predicate tree uses, so one classifier reads both. An entry with no selectors classifies every call of the tool.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub selectors: ::std::vec::Vec<T1Leaf>,
///Feed version or RFC 3339 timestamp at which the entry first appeared.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub since: ::std::option::Option<::std::string::String>,
///Lifecycle of the entry in the feed. Open: an unknown status leaves the entry usable, because dropping a classification on a word the client did not recognise would silently widen what a rule fails to match.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub status: ::std::option::Option<::std::string::String>,
///The tool this entry classifies, as the evaluator sees it — 'Bash', or 'mcp__<server>__<tool>' for MCP.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub tool_key: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for EffectClassEntry {
fn default() -> Self {
Self {
effects: Default::default(),
id: Default::default(),
modified: Default::default(),
related: Default::default(),
selectors: Default::default(),
since: Default::default(),
status: Default::default(),
tool_key: Default::default(),
}
}
}
///`EffectTuple`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "EffectTuple",
/// "type": "object",
/// "properties": {
/// "attrs": {
/// "description": "Attributes attached to this tuple, readable from a leaf as effect.attrs.<name> (D-16). The first is is_production, resolved from the env_selectors fact — a starter-library entry already reads effect.attrs.is_production, and without this the entry is unmatchable as written. Open by construction: an attribute the client does not know makes a leaf naming it inconclusive, never false.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "target_class": {
/// "description": "What it does it to.",
/// "$ref": "#/$defs/TargetClass"
/// },
/// "verb": {
/// "description": "What the action does.",
/// "$ref": "#/$defs/EffectVerb"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct EffectTuple {
///Attributes attached to this tuple, readable from a leaf as effect.attrs.<name> (D-16). The first is is_production, resolved from the env_selectors fact — a starter-library entry already reads effect.attrs.is_production, and without this the entry is unmatchable as written. Open by construction: an attribute the client does not know makes a leaf naming it inconclusive, never false.
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub attrs: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///What it does it to.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub target_class: ::std::option::Option<TargetClass>,
///What the action does.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verb: ::std::option::Option<EffectVerb>,
}
impl ::std::default::Default for EffectTuple {
fn default() -> Self {
Self {
attrs: Default::default(),
target_class: Default::default(),
verb: Default::default(),
}
}
}
///The verb half of a classified effect tuple (verb, target_class). 'unknown' is an ordinary member and is what forces an ASK: one unmapped sibling in a pipeline must never erase a confident tuple. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The verb half of a classified effect tuple (verb, target_class). 'unknown' is an ordinary member and is what forces an ASK: one unmapped sibling in a pipeline must never erase a confident tuple. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "read",
/// "write",
/// "delete",
/// "execute",
/// "network_egress",
/// "send",
/// "spend",
/// "escalate",
/// "delegate",
/// "unknown"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct EffectVerb(pub ::std::string::String);
impl ::std::ops::Deref for EffectVerb {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<EffectVerb> for ::std::string::String {
fn from(value: EffectVerb) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for EffectVerb {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for EffectVerb {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for EffectVerb {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///The autonomy zone this install actually landed in, and how it got there.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "EffectiveZone",
/// "description": "The autonomy zone this install actually landed in, and how it got there.",
/// "type": "object",
/// "properties": {
/// "node_id": {
/// "description": "Identifier of the resolved zone node.",
/// "type": "string"
/// },
/// "path": {
/// "description": "Root-to-node path, so 'which zone am I in?' is answerable from the bundle alone.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "resolved_from": {
/// "description": "Whether the assignment was derived from the directory (auto) or set by a person (manual). An open string rather than a closed set, per R14.",
/// "type": "string",
/// "x-known-values": [
/// "auto",
/// "manual"
/// ]
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct EffectiveZone {
///Identifier of the resolved zone node.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub node_id: ::std::option::Option<::std::string::String>,
///Root-to-node path, so 'which zone am I in?' is answerable from the bundle alone.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub path: ::std::vec::Vec<::std::string::String>,
///Whether the assignment was derived from the directory (auto) or set by a person (manual). An open string rather than a closed set, per R14.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub resolved_from: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for EffectiveZone {
fn default() -> Self {
Self {
node_id: Default::default(),
path: Default::default(),
resolved_from: Default::default(),
}
}
}
///Which environment an install runs against. Defaults to 'production' when nothing resolves it — the safe direction. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Which environment an install runs against. Defaults to 'production' when nothing resolves it — the safe direction. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "production",
/// "staging",
/// "development",
/// "unknown"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct Environment(pub ::std::string::String);
impl ::std::ops::Deref for Environment {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Environment> for ::std::string::String {
fn from(value: Environment) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for Environment {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for Environment {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for Environment {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///CloudEvents v1.0.2 structured-mode envelope for agent hook events. Content-Type is application/cloudevents+json (single) or application/cloudevents-batch+json (batch). The 'data' field contains the raw agent payload untouched; all OpenLatch metadata lives in CloudEvents extension attributes. Extension attribute names MUST match ^[a-z0-9]+$ per the CloudEvents spec. verdict and latency_ms are produced by the daemon after processing and stamped onto hook-derived envelopes as the olverdict and ollatencyms extension attributes — these ride the outbound envelope as well as the local audit line, and are deliberately not declared here. Replayed, config-monitor and tamper envelopes are never stamped. The three egress-shape attributes — proxytype, proxysource and proxyintercepted — are stamped the same way and are deliberately not declared here either: a DECLARED property is validated by type at ingest, where one bad value rejects the whole event, while an undeclared attribute lands in the consumer's extension remainder, where a per-attribute guard can drop only the attribute at fault. Do not re-add them; PROXY-EXTENSIONS.md carries their names, types, meanings and known values, and RECORD-V2.md documents the record extensions on the same terms.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "CloudEvents v1.0.2 structured-mode envelope for agent hook events. Content-Type is application/cloudevents+json (single) or application/cloudevents-batch+json (batch). The 'data' field contains the raw agent payload untouched; all OpenLatch metadata lives in CloudEvents extension attributes. Extension attribute names MUST match ^[a-z0-9]+$ per the CloudEvents spec. verdict and latency_ms are produced by the daemon after processing and stamped onto hook-derived envelopes as the olverdict and ollatencyms extension attributes — these ride the outbound envelope as well as the local audit line, and are deliberately not declared here. Replayed, config-monitor and tamper envelopes are never stamped. The three egress-shape attributes — proxytype, proxysource and proxyintercepted — are stamped the same way and are deliberately not declared here either: a DECLARED property is validated by type at ingest, where one bad value rejects the whole event, while an undeclared attribute lands in the consumer's extension remainder, where a per-attribute guard can drop only the attribute at fault. Do not re-add them; PROXY-EXTENSIONS.md carries their names, types, meanings and known values, and RECORD-V2.md documents the record extensions on the same terms.",
/// "examples": [
/// {
/// "specversion": "1.0",
/// "id": "evt_019d8af1-f8da-73b3-92eb-79a99e59b10b",
/// "source": "claude-code",
/// "type": "pre_tool_use",
/// "time": "2026-04-16T12:00:00Z",
/// "datacontenttype": "application/json",
/// "subject": "sess_abc123",
/// "data": {
/// "tool_name": "Bash",
/// "tool_input": {
/// "command": "ls -la"
/// }
/// },
/// "os": "linux",
/// "arch": "x86_64",
/// "localipv4": "192.168.1.42",
/// "publicipv4": "203.0.113.7",
/// "clientversion": "0.2.0",
/// "agentversion": "1.2.0"
/// }
/// ],
/// "type": "object",
/// "required": [
/// "id",
/// "source",
/// "specversion",
/// "time",
/// "type"
/// ],
/// "properties": {
/// "agentid": {
/// "description": "OpenLatch extension. Stamped by the daemon on outbound events — identifies the AI agent install (one openlatch-client installation) that emitted this event (agt_<uuid>).",
/// "type": "string"
/// },
/// "agentversion": {
/// "description": "OpenLatch extension (was 'agent_version'). Agent software version, if reported by the hook.",
/// "type": "string"
/// },
/// "arch": {
/// "description": "OpenLatch extension. CPU architecture ('x86_64', 'aarch64').",
/// "type": "string"
/// },
/// "clientversion": {
/// "description": "OpenLatch extension (was 'client_version'). Semver of the openlatch-client that emitted the envelope.",
/// "type": "string"
/// },
/// "data": {
/// "description": "Raw agent payload, forwarded verbatim. Shape is agent-specific (e.g. Claude Code PreToolUse emits { tool_name, tool_input, … }; Cursor beforeShellExecution emits { command, … }). OpenLatch does NOT normalise this field. When `type` is `ai.openlatch.config.*` and `configkind` is `mcp`, the payload may additionally include an optional `scope` key — one of `enterprise` / `personal` / `project` / `local` — declaring the precedence tier of the source path; the cloud routing engine reads it to resolve same-named MCP servers across multiple filesystem locations."
/// },
/// "datacontenttype": {
/// "description": "Media type of the 'data' field. CloudEvents core optional attribute. Fixed to application/json for all OpenLatch events.",
/// "type": "string",
/// "const": "application/json"
/// },
/// "gitemail": {
/// "description": "OpenLatch extension. git config user.email for the session's working directory. Absent outside a repository.",
/// "type": "string"
/// },
/// "id": {
/// "description": "Unique event identifier — UUIDv7 with 'evt_' prefix. CloudEvents core attribute.",
/// "type": "string"
/// },
/// "localipv4": {
/// "description": "OpenLatch extension (was 'local_ipv4'). Machine's local IPv4 address. Detected once at daemon startup, cached for the process lifetime. Omitted when no non-loopback interface is available.",
/// "type": "string",
/// "format": "ipv4"
/// },
/// "localipv6": {
/// "description": "OpenLatch extension (was 'local_ipv6'). Machine's local IPv6 address.",
/// "type": "string",
/// "format": "ipv6"
/// },
/// "os": {
/// "description": "OpenLatch extension. Operating system ('linux', 'macos', 'windows'). CloudEvents extension — lowercase alphanumeric attribute name.",
/// "type": "string"
/// },
/// "osuser": {
/// "description": "OpenLatch extension. Logged-in OS user on the host. Absent when capture is disabled or no interactive user exists.",
/// "type": "string"
/// },
/// "provideracct": {
/// "description": "OpenLatch extension. AI-provider account identifier, or the literal shared-key when the credential carries no human. Never a token or key.",
/// "type": "string"
/// },
/// "publicipv4": {
/// "description": "OpenLatch extension (was 'public_ipv4'). Machine's public IPv4 address.",
/// "type": "string",
/// "format": "ipv4"
/// },
/// "publicipv6": {
/// "description": "OpenLatch extension (was 'public_ipv6'). Machine's public IPv6 address.",
/// "type": "string",
/// "format": "ipv6"
/// },
/// "source": {
/// "description": "Agent platform identifier (was 'agent_platform'). CloudEvents core attribute. Bare string per OpenLatch convention; any string is valid. See x-known-values in enums.schema.json#/$defs/AgentType for the canonical set.",
/// "$ref": "#/$defs/AgentType"
/// },
/// "specversion": {
/// "description": "CloudEvents spec version. MUST be '1.0' for CloudEvents v1.0.2.",
/// "type": "string",
/// "const": "1.0"
/// },
/// "subject": {
/// "description": "CloudEvents 'subject' attribute. OpenLatch uses this for the agent session identifier (was 'session_id'). Consumers can group events by subject for per-session analytics.",
/// "type": "string"
/// },
/// "time": {
/// "description": "Event creation timestamp (was 'timestamp'). RFC 3339 UTC with Z suffix. CloudEvents core attribute.",
/// "type": "string",
/// "format": "date-time"
/// },
/// "type": {
/// "description": "Hook event lifecycle name (was 'event_type'). CloudEvents core attribute. Any string is valid. See x-known-values in enums.schema.json#/$defs/HookEventType for the canonical set.",
/// "$ref": "#/$defs/HookEventType"
/// },
/// "wireformat": {
/// "description": "OpenLatch extension. The provider wire protocol the emitting agent's request plane speaks: 'anthropic-messages', 'openai-chat-completions', 'openai-responses' or 'google-generate-content'. An attribute of the AGENT, not of the component that observed the event, so it is stamped once at the client's single egress — resolved from 'source' through that agent's binding — and rides hook, config and economics events alike. The client writes it on every outbound envelope, carrying the literal 'unknown' when the source cannot be resolved to an agent with a request plane on that host; it is declared optional here because that is a producer guarantee, not a wire requirement, and a consumer must tolerate its absence.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true,
/// "x-postgresql-skip": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct EventEnvelope {
///OpenLatch extension. Stamped by the daemon on outbound events — identifies the AI agent install (one openlatch-client installation) that emitted this event (agt_<uuid>).
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub agentid: ::std::option::Option<::std::string::String>,
///OpenLatch extension (was 'agent_version'). Agent software version, if reported by the hook.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub agentversion: ::std::option::Option<::std::string::String>,
///OpenLatch extension. CPU architecture ('x86_64', 'aarch64').
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub arch: ::std::option::Option<::std::string::String>,
///OpenLatch extension (was 'client_version'). Semver of the openlatch-client that emitted the envelope.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub clientversion: ::std::option::Option<::std::string::String>,
///Raw agent payload, forwarded verbatim. Shape is agent-specific (e.g. Claude Code PreToolUse emits { tool_name, tool_input, … }; Cursor beforeShellExecution emits { command, … }). OpenLatch does NOT normalise this field. When `type` is `ai.openlatch.config.*` and `configkind` is `mcp`, the payload may additionally include an optional `scope` key — one of `enterprise` / `personal` / `project` / `local` — declaring the precedence tier of the source path; the cloud routing engine reads it to resolve same-named MCP servers across multiple filesystem locations.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub data: ::std::option::Option<::serde_json::Value>,
///Media type of the 'data' field. CloudEvents core optional attribute. Fixed to application/json for all OpenLatch events.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub datacontenttype: ::std::option::Option<::std::string::String>,
///OpenLatch extension. git config user.email for the session's working directory. Absent outside a repository.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub gitemail: ::std::option::Option<::std::string::String>,
///Unique event identifier — UUIDv7 with 'evt_' prefix. CloudEvents core attribute.
pub id: ::std::string::String,
///OpenLatch extension (was 'local_ipv4'). Machine's local IPv4 address. Detected once at daemon startup, cached for the process lifetime. Omitted when no non-loopback interface is available.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub localipv4: ::std::option::Option<::std::net::Ipv4Addr>,
///OpenLatch extension (was 'local_ipv6'). Machine's local IPv6 address.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub localipv6: ::std::option::Option<::std::net::Ipv6Addr>,
///OpenLatch extension. Operating system ('linux', 'macos', 'windows'). CloudEvents extension — lowercase alphanumeric attribute name.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub os: ::std::option::Option<::std::string::String>,
///OpenLatch extension. Logged-in OS user on the host. Absent when capture is disabled or no interactive user exists.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub osuser: ::std::option::Option<::std::string::String>,
///OpenLatch extension. AI-provider account identifier, or the literal shared-key when the credential carries no human. Never a token or key.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub provideracct: ::std::option::Option<::std::string::String>,
///OpenLatch extension (was 'public_ipv4'). Machine's public IPv4 address.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub publicipv4: ::std::option::Option<::std::net::Ipv4Addr>,
///OpenLatch extension (was 'public_ipv6'). Machine's public IPv6 address.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub publicipv6: ::std::option::Option<::std::net::Ipv6Addr>,
///Agent platform identifier (was 'agent_platform'). CloudEvents core attribute. Bare string per OpenLatch convention; any string is valid. See x-known-values in enums.schema.json#/$defs/AgentType for the canonical set.
pub source: crate::core::envelope::known_types::AgentType,
///CloudEvents spec version. MUST be '1.0' for CloudEvents v1.0.2.
pub specversion: ::std::string::String,
///CloudEvents 'subject' attribute. OpenLatch uses this for the agent session identifier (was 'session_id'). Consumers can group events by subject for per-session analytics.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub subject: ::std::option::Option<::std::string::String>,
///Event creation timestamp (was 'timestamp'). RFC 3339 UTC with Z suffix. CloudEvents core attribute.
pub time: ::chrono::DateTime<::chrono::offset::Utc>,
///Hook event lifecycle name (was 'event_type'). CloudEvents core attribute. Any string is valid. See x-known-values in enums.schema.json#/$defs/HookEventType for the canonical set.
#[serde(rename = "type")]
pub type_: crate::core::envelope::known_types::HookEventType,
///OpenLatch extension. The provider wire protocol the emitting agent's request plane speaks: 'anthropic-messages', 'openai-chat-completions', 'openai-responses' or 'google-generate-content'. An attribute of the AGENT, not of the component that observed the event, so it is stamped once at the client's single egress — resolved from 'source' through that agent's binding — and rides hook, config and economics events alike. The client writes it on every outbound envelope, carrying the literal 'unknown' when the source cannot be resolved to an agent with a request plane on that host; it is declared optional here because that is a producer guarantee, not a wire requirement, and a consumer must tolerate its absence.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub wireformat: ::std::option::Option<::std::string::String>,
}
///Body of an artifact whose kind is 'exception' — a stored answer to an earlier ask, replayed so the same question is not put to a person twice. Evaluated AFTER Tier 1 and 2 and BEFORE the join: an exception with verdict allow short-circuits its atom to allow when the selector matches, and one with verdict block forces block. Selected by `kind` in application code, not by a discriminator in this schema.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ExceptionArtifact",
/// "description": "Body of an artifact whose kind is 'exception' — a stored answer to an earlier ask, replayed so the same question is not put to a person twice. Evaluated AFTER Tier 1 and 2 and BEFORE the join: an exception with verdict allow short-circuits its atom to allow when the selector matches, and one with verdict block forces block. Selected by `kind` in application code, not by a discriminator in this schema.",
/// "type": "object",
/// "properties": {
/// "answered_at": {
/// "description": "RFC 3339 UTC timestamp of when the answer was given. What the console shows next to 'who allowed this, and when'.",
/// "type": "string"
/// },
/// "expires_at": {
/// "description": "RFC 3339 UTC expiry, or null for none. Null is the current behaviour: an answered ground stays answered until it is retired, because an exception that silently expires re-asks a question the organization believed it had settled.",
/// "type": [
/// "string",
/// "null"
/// ]
/// },
/// "ground_key": {
/// "description": "sha256 of the atom_id and the canonical JSON of the selector — the identity of the question that was answered, so the same ground is recognised across sessions and hosts.",
/// "type": "string"
/// },
/// "scope": {
/// "description": "How far the answer reaches, narrowest to widest: exact_action, resource_class, rule_agent, rule_zone. What the person answering chose, never widened afterwards by the client.",
/// "$ref": "#/$defs/AskScope"
/// },
/// "selector": {
/// "description": "What the answer applies to; the shape follows `scope`. exact_action: {action_hash} — matches when the current action's hash equals it. resource_class: {effect: {verb, target_class}} — matches when any effect tuple of the current action equals it. rule_agent: {atom_id, agent_row_id} — matches when the deciding atom and the agent both match. rule_zone: {atom_id, zone_id} — matches when the atom matches and the agent's assigned zone is zone_id or below it. Left untyped for the same reason artifacts[].body is: the per-scope shapes cannot be discriminated in this schema, so the loader picks on `scope`.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "verdict": {
/// "description": "The stored answer: allow (the exception grants) or block (it forbids). An answer is not a hint — it decides.",
/// "$ref": "#/$defs/Verdict"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct Exception {
///RFC 3339 UTC timestamp of when the answer was given. What the console shows next to 'who allowed this, and when'.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub answered_at: ::std::option::Option<::std::string::String>,
///RFC 3339 UTC expiry, or null for none. Null is the current behaviour: an answered ground stays answered until it is retired, because an exception that silently expires re-asks a question the organization believed it had settled.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub expires_at: ::std::option::Option<::std::string::String>,
///sha256 of the atom_id and the canonical JSON of the selector — the identity of the question that was answered, so the same ground is recognised across sessions and hosts.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub ground_key: ::std::option::Option<::std::string::String>,
///How far the answer reaches, narrowest to widest: exact_action, resource_class, rule_agent, rule_zone. What the person answering chose, never widened afterwards by the client.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub scope: ::std::option::Option<AskScope>,
///What the answer applies to; the shape follows `scope`. exact_action: {action_hash} — matches when the current action's hash equals it. resource_class: {effect: {verb, target_class}} — matches when any effect tuple of the current action equals it. rule_agent: {atom_id, agent_row_id} — matches when the deciding atom and the agent both match. rule_zone: {atom_id, zone_id} — matches when the atom matches and the agent's assigned zone is zone_id or below it. Left untyped for the same reason artifacts[].body is: the per-scope shapes cannot be discriminated in this schema, so the loader picks on `scope`.
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub selector: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///The stored answer: allow (the exception grants) or block (it forbids). An answer is not a hint — it decides.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verdict: ::std::option::Option<Verdict>,
}
impl ::std::default::Default for Exception {
fn default() -> Self {
Self {
answered_at: Default::default(),
expires_at: Default::default(),
ground_key: Default::default(),
scope: Default::default(),
selector: Default::default(),
verdict: Default::default(),
}
}
}
///Identifier of a fact set the bundle carries in facts[] and an atom references from fact_refs[]. A TYPO in a fact_id currently yields a bottom 'absent' answer, the atom silently takes its on_inconclusive branch, and nothing ever surfaces the typo. This list gives the loader something to WARN against; it must never reject a bundle, so an unknown fact id stays valid. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Identifier of a fact set the bundle carries in facts[] and an atom references from fact_refs[]. A TYPO in a fact_id currently yields a bottom 'absent' answer, the atom silently takes its on_inconclusive branch, and nothing ever surfaces the typo. This list gives the loader something to WARN against; it must never reject a bundle, so an unknown fact id stays valid. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "env_selectors",
/// "data_store_roots",
/// "classified_sources",
/// "approved_registries",
/// "approved_mcp_servers",
/// "approved_domains",
/// "approved_region_hosts",
/// "pricebook"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct FactId(pub ::std::string::String);
impl ::std::ops::Deref for FactId {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<FactId> for ::std::string::String {
fn from(value: FactId) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for FactId {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for FactId {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for FactId {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Whether an atom's ASK holds the action or lets it proceed. 'hold' is a per-atom irreversible opt-in; 'none' means allow-and-flag. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Whether an atom's ASK holds the action or lets it proceed. 'hold' is a per-atom irreversible opt-in; 'none' means allow-and-flag. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "none",
/// "hold"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct HoldMode(pub ::std::string::String);
impl ::std::ops::Deref for HoldMode {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<HoldMode> for ::std::string::String {
fn from(value: HoldMode) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for HoldMode {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for HoldMode {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for HoldMode {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///State of one held action (hold_requests). 'retired' = the atom, policy or zone retired while the hold was pending: the daemon's next poll returns it and RE-EVALUATES the action against the current bundle, without the retired atom, applying that verdict. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "State of one held action (hold_requests). 'retired' = the atom, policy or zone retired while the hold was pending: the daemon's next poll returns it and RE-EVALUATES the action against the current bundle, without the retired atom, applying that verdict. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "pending",
/// "approved",
/// "rejected",
/// "timed_out",
/// "retired"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct HoldState(pub ::std::string::String);
impl ::std::ops::Deref for HoldState {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<HoldState> for ::std::string::String {
fn from(value: HoldState) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for HoldState {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for HoldState {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for HoldState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Kind of asynchronous platform job. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Kind of asynchronous platform job. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "transcribe",
/// "extract",
/// "rewrite",
/// "compile",
/// "replay",
/// "bundle"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct JobKind(pub ::std::string::String);
impl ::std::ops::Deref for JobKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<JobKind> for ::std::string::String {
fn from(value: JobKind) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for JobKind {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for JobKind {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for JobKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///State of an asynchronous platform job. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "State of an asynchronous platform job. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "queued",
/// "running",
/// "succeeded",
/// "failed"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct JobState(pub ::std::string::String);
impl ::std::ops::Deref for JobState {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<JobState> for ::std::string::String {
fn from(value: JobState) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for JobState {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for JobState {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for JobState {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Which optimisation lever an 'optimize' verdict pulled. Supersedes the Model Boundary Enforcement Layer's own lever enum. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Which optimisation lever an 'optimize' verdict pulled. Supersedes the Model Boundary Enforcement Layer's own lever enum. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "effort_clamp",
/// "context_edit",
/// "prefix_guard",
/// "loop_stop",
/// "narrow_output",
/// "steer",
/// "substitute"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct Lever(pub ::std::string::String);
impl ::std::ops::Deref for Lever {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<Lever> for ::std::string::String {
fn from(value: Lever) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for Lever {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for Lever {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for Lever {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///`NarrowOutputEntry`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "NarrowOutputEntry",
/// "type": "object",
/// "properties": {
/// "command_prefix": {
/// "description": "Prefix of the normalised command string this entry applies to.",
/// "type": "string"
/// },
/// "filter": {
/// "description": "How the output is narrowed for that prefix.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct NarrowOutputEntry {
///Prefix of the normalised command string this entry applies to.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub command_prefix: ::std::option::Option<::std::string::String>,
///How the output is narrowed for that prefix.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub filter: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for NarrowOutputEntry {
fn default() -> Self {
Self {
command_prefix: Default::default(),
filter: Default::default(),
}
}
}
///What an atom does when its predicate evaluates to Kleene UNKNOWN — a fact absent or stale, an open-world miss, an unclassifiable command. A Monitor-mode policy is ALWAYS 'allow_and_flag' regardless of what the atom declares. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What an atom does when its predicate evaluates to Kleene UNKNOWN — a fact absent or stale, an open-world miss, an unclassifiable command. A Monitor-mode policy is ALWAYS 'allow_and_flag' regardless of what the atom declares. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "allow_and_flag",
/// "ask",
/// "block"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct OnInconclusive(pub ::std::string::String);
impl ::std::ops::Deref for OnInconclusive {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<OnInconclusive> for ::std::string::String {
fn from(value: OnInconclusive) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for OnInconclusive {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for OnInconclusive {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for OnInconclusive {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///`PolicyArtifact`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PolicyArtifact",
/// "type": "object",
/// "properties": {
/// "artifact_id": {
/// "description": "Stable identifier for this compiled artifact. Reported on the verdict as olpolicyruleid — the schema-2 artifact and the schema-1 rule_id share that extension, because what the record names is 'the thing that decided', on whichever plane it lived.",
/// "type": "string"
/// },
/// "atom_id": {
/// "description": "The ratified intent atom this artifact was compiled from. Several artifacts may share one atom: a session leaf compiles to its own Tier 2 program alongside the atom's Tier 1 trigger. Recorded as olatomid.",
/// "type": "string"
/// },
/// "body": {
/// "description": "The artifact's payload, whose shape is the $def named by `kind`. Left untyped HERE on purpose: this is the second stage of the two-stage parse described on the parent, and the shapes are documented in $defs.t1_predicate_tree, $defs.t2_register_program, $defs.t3_hold and $defs.exception rather than discriminated in the schema, because build.rs strips the conditional that would do the discriminating.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "dimension": {
/// "description": "Which dimension the owning policy belongs to. Recorded as oldimension. An open string carrying the vocabulary as x-known-values, not a closed set, so a dimension added platform-side never fails a bundle.",
/// "$ref": "#/$defs/Dimension"
/// },
/// "hold_mode": {
/// "description": "Whether an ask verdict from this artifact HOLDS the action pending an answer (hold) or merely flags it (none). An irreversible opt-in per atom: holding blocks the developer's agent until someone answers, so it is never inferred from the verdict alone.",
/// "$ref": "#/$defs/HoldMode"
/// },
/// "kind": {
/// "description": "Which $def `body` conforms to. Open, and the client MUST skip an artifact whose kind it does not recognise while keeping the rest of the bundle active — a closed set here would fail deserialization of the whole document instead.",
/// "$ref": "#/$defs/ArtifactKind"
/// },
/// "min_client_version": {
/// "description": "Optional per-artifact floor, for an artifact using a capability the org-wide client_floor does not yet require. A client below it SKIPS this artifact and keeps the rest of the bundle — a per-item floor degrades to one missing rule, where the root-level floor would have withheld the whole document.",
/// "type": "string"
/// },
/// "mode": {
/// "description": "The composed mode of this artifact: monitor or enforce (a disabled policy is never composed, so the third value never reaches a bundle). A monitor_only atom composes with monitor regardless of its policy's mode. Recorded as olmode. Overridden to monitor for every artifact when enforcement_enabled is false, exactly as the schema-1 rule mode is.",
/// "$ref": "#/$defs/PolicyMode"
/// },
/// "on_inconclusive": {
/// "description": "What this artifact's verdict becomes when a fact leaf evaluated to absent and the artifact could therefore not be decided (R15's third value). Monitor mode is always allow_and_flag; enforce mode chooses. The inconclusive facts themselves are recorded as olinconclusive so the gap is visible rather than silently resolved.",
/// "$ref": "#/$defs/OnInconclusive"
/// },
/// "policy_id": {
/// "description": "Internal identifier of the policy owning the atom. Recorded as olpolicyid.",
/// "type": "string"
/// },
/// "policy_public_id": {
/// "description": "The identifier the console and the developer-facing deny reason show. Separate from policy_id so an internal id never has to appear in front of a developer.",
/// "type": "string"
/// },
/// "spec_hash": {
/// "description": "Hash of the artifact's compiled specification, stable across rebuilds that did not change its meaning. Recorded as olspechash: the key that answers 'is this the same rule that fired yesterday?' without comparing bodies.",
/// "type": "string"
/// },
/// "tier": {
/// "description": "Which evaluator tier decides this artifact: 1 (stateless predicate tree), 2 (register program over session state) or 3 (hold). An INTEGER, not a string vocabulary — the tier is an ordinal the evaluator dispatches on, and every number on this bundle is an integer with |n| <= 2^53-1. Recorded as oltier.",
/// "type": "integer"
/// },
/// "zone_layer": {
/// "title": "ZoneLayer",
/// "description": "Which layer of the autonomy zone tree contributed this artifact — the unit it was INHERITED from, which is not necessarily the agent's own zone. Recorded as ollayer, and what makes 'why am I subject to this?' answerable without a round trip.",
/// "type": "object",
/// "properties": {
/// "node_id": {
/// "description": "Identifier of the contributing zone node.",
/// "type": "string"
/// },
/// "path": {
/// "description": "Root-to-node path, so the console can render the inheritance chain without holding the tree.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyArtifact {
///Stable identifier for this compiled artifact. Reported on the verdict as olpolicyruleid — the schema-2 artifact and the schema-1 rule_id share that extension, because what the record names is 'the thing that decided', on whichever plane it lived.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub artifact_id: ::std::option::Option<::std::string::String>,
///The ratified intent atom this artifact was compiled from. Several artifacts may share one atom: a session leaf compiles to its own Tier 2 program alongside the atom's Tier 1 trigger. Recorded as olatomid.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub atom_id: ::std::option::Option<::std::string::String>,
///The artifact's payload, whose shape is the $def named by `kind`. Left untyped HERE on purpose: this is the second stage of the two-stage parse described on the parent, and the shapes are documented in $defs.t1_predicate_tree, $defs.t2_register_program, $defs.t3_hold and $defs.exception rather than discriminated in the schema, because build.rs strips the conditional that would do the discriminating.
#[serde(default, skip_serializing_if = "::serde_json::Map::is_empty")]
pub body: ::serde_json::Map<::std::string::String, ::serde_json::Value>,
///Which dimension the owning policy belongs to. Recorded as oldimension. An open string carrying the vocabulary as x-known-values, not a closed set, so a dimension added platform-side never fails a bundle.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub dimension: ::std::option::Option<Dimension>,
///Whether an ask verdict from this artifact HOLDS the action pending an answer (hold) or merely flags it (none). An irreversible opt-in per atom: holding blocks the developer's agent until someone answers, so it is never inferred from the verdict alone.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub hold_mode: ::std::option::Option<HoldMode>,
///Which $def `body` conforms to. Open, and the client MUST skip an artifact whose kind it does not recognise while keeping the rest of the bundle active — a closed set here would fail deserialization of the whole document instead.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub kind: ::std::option::Option<ArtifactKind>,
///Optional per-artifact floor, for an artifact using a capability the org-wide client_floor does not yet require. A client below it SKIPS this artifact and keeps the rest of the bundle — a per-item floor degrades to one missing rule, where the root-level floor would have withheld the whole document.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub min_client_version: ::std::option::Option<::std::string::String>,
///The composed mode of this artifact: monitor or enforce (a disabled policy is never composed, so the third value never reaches a bundle). A monitor_only atom composes with monitor regardless of its policy's mode. Recorded as olmode. Overridden to monitor for every artifact when enforcement_enabled is false, exactly as the schema-1 rule mode is.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub mode: ::std::option::Option<PolicyMode>,
///What this artifact's verdict becomes when a fact leaf evaluated to absent and the artifact could therefore not be decided (R15's third value). Monitor mode is always allow_and_flag; enforce mode chooses. The inconclusive facts themselves are recorded as olinconclusive so the gap is visible rather than silently resolved.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub on_inconclusive: ::std::option::Option<OnInconclusive>,
///Internal identifier of the policy owning the atom. Recorded as olpolicyid.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub policy_id: ::std::option::Option<::std::string::String>,
///The identifier the console and the developer-facing deny reason show. Separate from policy_id so an internal id never has to appear in front of a developer.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub policy_public_id: ::std::option::Option<::std::string::String>,
///Hash of the artifact's compiled specification, stable across rebuilds that did not change its meaning. Recorded as olspechash: the key that answers 'is this the same rule that fired yesterday?' without comparing bodies.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub spec_hash: ::std::option::Option<::std::string::String>,
///Which evaluator tier decides this artifact: 1 (stateless predicate tree), 2 (register program over session state) or 3 (hold). An INTEGER, not a string vocabulary — the tier is an ordinal the evaluator dispatches on, and every number on this bundle is an integer with |n| <= 2^53-1. Recorded as oltier.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub tier: ::std::option::Option<i64>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub zone_layer: ::std::option::Option<ZoneLayer>,
}
impl ::std::default::Default for PolicyArtifact {
fn default() -> Self {
Self {
artifact_id: Default::default(),
atom_id: Default::default(),
body: Default::default(),
dimension: Default::default(),
hold_mode: Default::default(),
kind: Default::default(),
min_client_version: Default::default(),
mode: Default::default(),
on_inconclusive: Default::default(),
policy_id: Default::default(),
policy_public_id: Default::default(),
spec_hash: Default::default(),
tier: Default::default(),
zone_layer: Default::default(),
}
}
}
///The policy bundle served by GET /api/v1/policy/bundle and held resident by the daemon. Canonicalized by the platform with RFC 8785 (JCS); the ETag is 'sha256:<hex>' over exactly those bytes and the client verifies the digest against the raw response body it received — it MUST NOT re-serialize before hashing. The bundle carries strings, booleans, integers and null only: no floats anywhere, which eliminates the RFC 8785 ES6 Number::toString divergence between Python and Rust by construction. A resident bundle keeps enforcing offline forever; there is no expiry.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The policy bundle served by GET /api/v1/policy/bundle and held resident by the daemon. Canonicalized by the platform with RFC 8785 (JCS); the ETag is 'sha256:<hex>' over exactly those bytes and the client verifies the digest against the raw response body it received — it MUST NOT re-serialize before hashing. The bundle carries strings, booleans, integers and null only: no floats anywhere, which eliminates the RFC 8785 ES6 Number::toString divergence between Python and Rust by construction. A resident bundle keeps enforcing offline forever; there is no expiry.",
/// "examples": [
/// {
/// "schema_version": 1,
/// "organization_id": "0192f8a1-4c3b-7e2a-9f10-5d8c3b1a7e42",
/// "revision": 42,
/// "built_at": "2026-07-21T09:00:00Z",
/// "enforcement_enabled": true,
/// "rules": [
/// {
/// "rule_id": "OL-CMD-001",
/// "kind": "command",
/// "match_pattern": "*rm -rf /*",
/// "action": "deny",
/// "mode": "enforce",
/// "severity": "critical",
/// "reason": "Recursive delete of a root path"
/// }
/// ],
/// "signature": null
/// },
/// {
/// "schema_version": 1,
/// "organization_id": "0192f8a1-4c3b-7e2a-9f10-5d8c3b1a7e42",
/// "revision": 1,
/// "built_at": "2026-07-20T11:30:00Z",
/// "enforcement_enabled": true,
/// "rules": [],
/// "signature": null
/// },
/// {
/// "schema_version": 1,
/// "organization_id": "0192f8a1-4c3b-7e2a-9f10-5d8c3b1a7e42",
/// "revision": 77,
/// "built_at": "2026-07-24T14:05:00Z",
/// "enforcement_enabled": true,
/// "rules": [
/// {
/// "rule_id": "OL-CMD-001",
/// "kind": "command",
/// "match_pattern": "*rm -rf /*",
/// "action": "deny",
/// "mode": "enforce",
/// "severity": "critical",
/// "reason": "Recursive delete of a root path"
/// },
/// {
/// "rule_id": "OL-REQ-001",
/// "kind": "request",
/// "rule_version": 3,
/// "action": "prefix_reorder",
/// "select": {
/// "model_in": [
/// "claude-opus-5"
/// ],
/// "exclude_layers": [
/// "tools"
/// ]
/// },
/// "mode": "observe",
/// "severity": "low",
/// "reason": "Stabilize the cache prefix so the tool block stops churning"
/// },
/// {
/// "rule_id": "OL-ECO-CACHE-3f9c1a2b",
/// "kind": "request",
/// "rule_version": 1,
/// "action": "prefix_reorder",
/// "params": {
/// "mechanism": "insert_breakpoints"
/// },
/// "mode": "observe",
/// "severity": "medium",
/// "reason": "Repeated context is served at full input price (only 22% cache-read); caching the stable prefix recovers most of it"
/// },
/// {
/// "rule_id": "OL-REQ-002",
/// "kind": "request",
/// "rule_version": 1,
/// "action": "history_trim",
/// "select": {
/// "min_messages": 40
/// },
/// "params": {
/// "keep_messages": 20
/// },
/// "mode": "observe",
/// "severity": "low",
/// "reason": "Long sessions carry more history than the task needs"
/// }
/// ],
/// "signature": null
/// },
/// {
/// "schema_version": 1,
/// "organization_id": "0192f8a1-4c3b-7e2a-9f10-5d8c3b1a7e42",
/// "revision": 79,
/// "built_at": "2026-08-16T08:00:00Z",
/// "enforcement_enabled": true,
/// "rules": [
/// {
/// "rule_id": "OL-CMD-001",
/// "kind": "command",
/// "match_pattern": "*rm -rf /*",
/// "action": "deny",
/// "mode": "enforce",
/// "severity": "critical",
/// "reason": "Recursive delete of a root path"
/// },
/// {
/// "rule_id": "OL-CMD-002",
/// "kind": "command",
/// "match_pattern": "*psql*",
/// "conditions": [
/// {
/// "field": "agent.function",
/// "op": "in",
/// "value": [
/// "marketing",
/// "sales"
/// ]
/// }
/// ],
/// "action": "deny",
/// "mode": "enforce",
/// "severity": "high",
/// "reason": "Direct database access is not part of a marketing or sales workflow"
/// }
/// ],
/// "signature": null
/// },
/// {
/// "schema_version": 1,
/// "organization_id": "0192f8a1-4c3b-7e2a-9f10-5d8c3b1a7e42",
/// "revision": 80,
/// "built_at": "2026-08-16T08:00:00Z",
/// "enforcement_enabled": true,
/// "rules": [
/// {
/// "rule_id": "OL-CMD-003",
/// "kind": "command",
/// "match_pattern": "*curl*",
/// "conditions": [
/// {
/// "field": "agent.function",
/// "op": "in",
/// "value": [
/// "unknown"
/// ]
/// }
/// ],
/// "action": "deny",
/// "mode": "observe",
/// "severity": "medium",
/// "reason": "Outbound transfers from an agent nobody has claimed are reviewed before they are allowed"
/// }
/// ],
/// "signature": null,
/// "client_config": {
/// "capture_identity_signals": true,
/// "agent_context": {
/// "function": "unknown"
/// }
/// }
/// }
/// ],
/// "type": "object",
/// "required": [
/// "built_at",
/// "enforcement_enabled",
/// "organization_id",
/// "revision",
/// "rules",
/// "schema_version",
/// "signature"
/// ],
/// "properties": {
/// "artifacts": {
/// "description": "The compiled policy artifacts — schema 2's evaluation plane, sorted by artifact_id so the serialization is deterministic. Each entry is a TYPED ENVELOPE around an UNTYPED body whose shape is selected by `kind`: $defs.t1_predicate_tree, $defs.t2_register_program, $defs.t3_hold and $defs.exception. The two-stage parse is deliberate and not a shortcut. build.rs strips if/then/else before typify sees it (typify hard-panics on conditionals), so a discriminator written as an if/then or an allOf on `kind` would silently NOT EXIST in the generated types — the same failure that already forced src/core/policy/validate.rs to be hand-written. The loader parses the envelope, reads `kind`, parses the body against the matching $def, and SKIPS the item on failure: one unparseable artifact must never cost the fleet its denies, and an unknown `kind` is skipped for the same reason. No field is required, so a truncated artifact is skipped rather than failing the document. New in schema 2; same emission rule as install_id.",
/// "type": "array",
/// "items": {
/// "title": "PolicyArtifact",
/// "type": "object",
/// "properties": {
/// "artifact_id": {
/// "description": "Stable identifier for this compiled artifact. Reported on the verdict as olpolicyruleid — the schema-2 artifact and the schema-1 rule_id share that extension, because what the record names is 'the thing that decided', on whichever plane it lived.",
/// "type": "string"
/// },
/// "atom_id": {
/// "description": "The ratified intent atom this artifact was compiled from. Several artifacts may share one atom: a session leaf compiles to its own Tier 2 program alongside the atom's Tier 1 trigger. Recorded as olatomid.",
/// "type": "string"
/// },
/// "body": {
/// "description": "The artifact's payload, whose shape is the $def named by `kind`. Left untyped HERE on purpose: this is the second stage of the two-stage parse described on the parent, and the shapes are documented in $defs.t1_predicate_tree, $defs.t2_register_program, $defs.t3_hold and $defs.exception rather than discriminated in the schema, because build.rs strips the conditional that would do the discriminating.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "dimension": {
/// "description": "Which dimension the owning policy belongs to. Recorded as oldimension. An open string carrying the vocabulary as x-known-values, not a closed set, so a dimension added platform-side never fails a bundle.",
/// "$ref": "#/$defs/Dimension"
/// },
/// "hold_mode": {
/// "description": "Whether an ask verdict from this artifact HOLDS the action pending an answer (hold) or merely flags it (none). An irreversible opt-in per atom: holding blocks the developer's agent until someone answers, so it is never inferred from the verdict alone.",
/// "$ref": "#/$defs/HoldMode"
/// },
/// "kind": {
/// "description": "Which $def `body` conforms to. Open, and the client MUST skip an artifact whose kind it does not recognise while keeping the rest of the bundle active — a closed set here would fail deserialization of the whole document instead.",
/// "$ref": "#/$defs/ArtifactKind"
/// },
/// "min_client_version": {
/// "description": "Optional per-artifact floor, for an artifact using a capability the org-wide client_floor does not yet require. A client below it SKIPS this artifact and keeps the rest of the bundle — a per-item floor degrades to one missing rule, where the root-level floor would have withheld the whole document.",
/// "type": "string"
/// },
/// "mode": {
/// "description": "The composed mode of this artifact: monitor or enforce (a disabled policy is never composed, so the third value never reaches a bundle). A monitor_only atom composes with monitor regardless of its policy's mode. Recorded as olmode. Overridden to monitor for every artifact when enforcement_enabled is false, exactly as the schema-1 rule mode is.",
/// "$ref": "#/$defs/PolicyMode"
/// },
/// "on_inconclusive": {
/// "description": "What this artifact's verdict becomes when a fact leaf evaluated to absent and the artifact could therefore not be decided (R15's third value). Monitor mode is always allow_and_flag; enforce mode chooses. The inconclusive facts themselves are recorded as olinconclusive so the gap is visible rather than silently resolved.",
/// "$ref": "#/$defs/OnInconclusive"
/// },
/// "policy_id": {
/// "description": "Internal identifier of the policy owning the atom. Recorded as olpolicyid.",
/// "type": "string"
/// },
/// "policy_public_id": {
/// "description": "The identifier the console and the developer-facing deny reason show. Separate from policy_id so an internal id never has to appear in front of a developer.",
/// "type": "string"
/// },
/// "spec_hash": {
/// "description": "Hash of the artifact's compiled specification, stable across rebuilds that did not change its meaning. Recorded as olspechash: the key that answers 'is this the same rule that fired yesterday?' without comparing bodies.",
/// "type": "string"
/// },
/// "tier": {
/// "description": "Which evaluator tier decides this artifact: 1 (stateless predicate tree), 2 (register program over session state) or 3 (hold). An INTEGER, not a string vocabulary — the tier is an ordinal the evaluator dispatches on, and every number on this bundle is an integer with |n| <= 2^53-1. Recorded as oltier.",
/// "type": "integer"
/// },
/// "zone_layer": {
/// "title": "ZoneLayer",
/// "description": "Which layer of the autonomy zone tree contributed this artifact — the unit it was INHERITED from, which is not necessarily the agent's own zone. Recorded as ollayer, and what makes 'why am I subject to this?' answerable without a round trip.",
/// "type": "object",
/// "properties": {
/// "node_id": {
/// "description": "Identifier of the contributing zone node.",
/// "type": "string"
/// },
/// "path": {
/// "description": "Root-to-node path, so the console can render the inheritance chain without holding the tree.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "built_at": {
/// "description": "RFC 3339 UTC timestamp with a Z suffix (microsecond precision allowed) recording when the rule content last actually changed — not when the bundle was served. Drives olpolicybundleage (now minus built_at, clamped at 0), which measures policy freshness. It does NOT drive the staleness warning, which is measured from the last successful fetch. Deliberately a plain string rather than format: date-time so the generated Rust type stays a String; the poller parses it once into a SystemTime.",
/// "type": "string"
/// },
/// "client_config": {
/// "description": "Client-bound configuration delivered on the bundle — the only client-bound configuration channel. Optional; a client that never receives it captures nothing (fail closed). The platform MUST NOT emit this field to a fleet that still runs clients predating it: the bundle root is additionalProperties:false, so such a client rejects the whole document (OL-1212) and fails static on its previous rules.",
/// "type": "object",
/// "properties": {
/// "agent_context": {
/// "description": "This install's own agent context, composed by the platform at serve time from the X-OpenLatch-Agent-Id header the poller sends — one object about THIS agent, never a fleet roster. Optional: a client that never receives it holds no context, and every rule carrying conditions matches nothing (absent context is not 'unknown'). Tolerant like its parent, so a newer platform can add keys without failing older clients.",
/// "type": "object",
/// "properties": {
/// "function": {
/// "description": "The business function assigned to this agent's owner. Deliberately an OPEN string carrying the AgentFunction vocabulary as x-known-values rather than a $ref to that enum — the same reasoning as params.mechanism: client_config is deserialized as one typed object outside the per-rule tolerance, so an enum here would fail the WHOLE bundle (fleet-wide fail-static) on a single out-of-vocabulary value. The client parses it into AgentFunction at load; a STRING value it cannot parse reads as no context, so scoped rules match nothing rather than the bundle being rejected. The tolerance is over the vocabulary, not the shape: a non-string value here (or a non-object agent_context) is a malformed client_config and does fail the whole document, exactly as a malformed capture_identity_signals does. 'unknown' is a real platform-assigned value, distinct from the field being absent.",
/// "type": "string",
/// "x-known-values": [
/// "engineering",
/// "product",
/// "data",
/// "security",
/// "it_ops",
/// "sales",
/// "marketing",
/// "finance",
/// "legal",
/// "hr",
/// "support",
/// "research",
/// "other",
/// "unknown"
/// ]
/// }
/// },
/// "additionalProperties": true
/// },
/// "capture_identity_signals": {
/// "description": "The client's copy of the org setting identity.capture_signals. Identity signals are captured and stamped only when this is explicitly true.",
/// "type": "boolean"
/// },
/// "hold": {
/// "description": "Bounds on the Tier 3 hold path — the one place where a verdict waits on a human. Both bounds exist so that a console that never answers, or an agent that fires holds faster than anyone can read them, degrades into a prompt deny with a legible reason rather than into an agent that appears hung.",
/// "type": "object",
/// "properties": {
/// "host_timeout_s": {
/// "description": "How long the daemon holds a pending action before applying the artifact's on_timeout verdict, in seconds. Bounded below by the agent's own hook timeout in practice: a hold that outlives the hook is decided by the harness, not by us.",
/// "type": "integer"
/// },
/// "max_pending_holds": {
/// "description": "The hold buffer's explicit cap, default 16. A hold artifact firing beyond it is NOT buffered: the daemon prints an immediate deny whose reason names the full buffer, and records result: held_timeout. An unbounded buffer would turn a runaway agent into an unbounded queue of prompts nobody will ever answer.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
/// },
/// "jitter_pct": {
/// "description": "Percentage of poll_interval_s to spread each client's next poll over, so a fleet that started together does not stay synchronised and hammer the endpoint on the same second. An integer percentage, applied by the client to its own interval; absent means the client keeps its own default.",
/// "type": "integer"
/// },
/// "levers": {
/// "description": "One optional block per lever (the Lever vocabulary in enums.schema.json). An ABSENT block means measure only — the lever's atoms still evaluate and still record, but the client performs no intervention. This is the safe default and the reason each block is optional rather than defaulted: a lever the organization never configured must never start rewriting an agent's traffic because a bundle grew a field. Every rewrite-capable block may carry visible_in_monitor (default false), the Monitor-visible rewrite opt-in: with it false a monitor-mode lever records what it WOULD have done and changes nothing, which is what makes Monitor mode honest.",
/// "type": "object",
/// "properties": {
/// "context_edit": {
/// "description": "Clears stale tool results out of the context window once it crosses a trigger. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "clear_at_least": {
/// "description": "Minimum tokens an edit must reclaim to be worth doing — below it the edit is skipped, because an edit that reclaims almost nothing still costs the whole prefix its cache.",
/// "type": "integer"
/// },
/// "exclude_tools": {
/// "description": "Tool names whose results are never cleared. Tool-name globs, matched the same way the atom language matches does_what.tools.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "keep": {
/// "description": "How many of the most recent tool results survive an edit.",
/// "type": "integer"
/// },
/// "trigger": {
/// "description": "Token count at which an edit is considered. Integer tokens, never a fraction of a window.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "effort_clamp": {
/// "description": "Caps the reasoning effort an agent may request, per agent category. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "by_agent_type": {
/// "description": "Map of agent category (the AgentCategory vocabulary — coding, analysis, ops, content, service) to the effort level that category is clamped to. A map rather than a list so one category can be retuned as a one-key delta, and an open one so an unknown category is carried rather than rejected.",
/// "type": "object",
/// "additionalProperties": {
/// "type": "string"
/// }
/// },
/// "quality_floor": {
/// "description": "The level the clamp may never go below, whatever by_agent_type says. Present so that tightening the clamp org-wide cannot silently drop an agent under the quality bar its owner signed up for.",
/// "type": "string"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false: monitor records the would-have and changes nothing.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "loop_stop": {
/// "description": "Stops an agent that is repeating itself. Keys on identical (tool, normalised input, result hash) — deliberately distinct from the run_le session shape, which keys on action shape and therefore treats Read a.py and Read b.py as the same. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "exempt_patterns": {
/// "description": "Calls matching these are never counted toward either bound — polling loops that are supposed to repeat.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "n_errors": {
/// "description": "Consecutive erroring calls before the loop is stopped. Default 3.",
/// "type": "integer"
/// },
/// "n_identical": {
/// "description": "Consecutive identical calls before the loop is stopped. Default 4.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's intervention while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "narrow_output": {
/// "description": "Filters a command's output down to what the agent actually needs, instead of feeding a whole log back into the context. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "allowlist": {
/// "description": "The only commands whose output is narrowed. An allowlist rather than a denylist: narrowing output the author did not anticipate is a correctness risk, so an unlisted command passes through untouched.",
/// "type": "array",
/// "items": {
/// "title": "NarrowOutputEntry",
/// "type": "object",
/// "properties": {
/// "command_prefix": {
/// "description": "Prefix of the normalised command string this entry applies to.",
/// "type": "string"
/// },
/// "filter": {
/// "description": "How the output is narrowed for that prefix.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "prefix_guard": {
/// "description": "Pins the stable prefix so a volatile block cannot keep invalidating the cache. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pin_ttl": {
/// "description": "How long a pin survives, as a duration string ('1h'), or null for no expiry. The one duration on this bundle that is not an integer of seconds, because it is passed through to the provider verbatim rather than computed on.",
/// "type": [
/// "string",
/// "null"
/// ]
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "steer": {
/// "description": "Injects the atom's steer_instruction into the agent's context instead of blocking it. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "dedupe_window_s": {
/// "description": "How long the same instruction is suppressed after being delivered, in seconds. Without it a steer atom that keeps matching repeats itself every call and becomes noise the model learns to ignore.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "substitute": {
/// "description": "Replaces one call with a cheaper or safer equivalent. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pairs": {
/// "description": "The substitutions, applied in order.",
/// "type": "array",
/// "items": {
/// "title": "SubstitutePair",
/// "type": "object",
/// "properties": {
/// "from": {
/// "description": "What is matched.",
/// "type": "string"
/// },
/// "to": {
/// "description": "What replaces it.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "additionalProperties": true
/// },
/// "poll_interval_s": {
/// "description": "How often the poller asks for a new bundle, in seconds. Platform-controlled so the fleet's load can be moved without a client release. Absent means the client keeps its own default (300s). Seconds, integer — durations on this bundle are never fractional, because a float would reintroduce the RFC 8785 ES6 Number::toString divergence the integers-only rule eliminates by construction.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
/// },
/// "client_floor": {
/// "description": "The minimum client version this bundle is safe to serve to (D35). The bundle root is additionalProperties:false, so a client predating a section rejects the WHOLE document (OL-1212), fails static on its previous rules, and then never updates again — the per-rule tolerance in parse_bundle_tolerant does not help, because the root-level failure happens before it is ever reached. The platform therefore composes schema 2 only for installs at or above the floor and keeps serving schema 1 below it, and the client reports its own version on every poll so the platform can tell which. A client that reads this field and finds ITSELF below the floor keeps its resident bundle and reports the gap rather than downgrading silently. New in schema 2; same emission rule as install_id.",
/// "type": "object",
/// "properties": {
/// "min_client_version": {
/// "description": "Semantic version string, e.g. '0.9.0'. Deliberately unconstrained: a pattern keyword here would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one malformed value, which is exactly the failure the floor exists to prevent.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// },
/// "directive_templates": {
/// "description": "The text a Tier 3 hold puts in front of the model when it asks for a fact ('Before this call, state whether ...'). Generated AT COMPILE TIME by the compiler from the atom's fact leaf and editable by the owner in the wizard — never composed at runtime, so the client renders a template it was given rather than writing a prompt of its own. New in schema 2; same emission rule as install_id.",
/// "type": "array",
/// "items": {
/// "title": "DirectiveTemplate",
/// "type": "object",
/// "properties": {
/// "kind": {
/// "description": "What sort of directive this is. Open, and a hold naming a template whose kind the client cannot render falls back to its on_timeout verdict rather than emitting nothing.",
/// "type": "string"
/// },
/// "params": {
/// "description": "Names of the substitutions `text` expects. The client fills only these, from the event and the artifact — never from anything the model said.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "template_id": {
/// "description": "Identifier a t3_hold body names in directive_template_id.",
/// "type": "string"
/// },
/// "text": {
/// "description": "The directive itself, with its parameter placeholders. Deliberately unconstrained: a length keyword would make the generated Rust type a newtype whose deserializer fails the WHOLE bundle on one long template.",
/// "type": "string"
/// },
/// "version": {
/// "description": "Bumped whenever the owner edits the text, so a recorded reinforcement can be tied to the wording that produced it.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "effect_classes": {
/// "description": "The effect-class feed the client's classifier resolves a tool call into (verb, target_class) tuples with (R13) — what lets a rule say 'delete from a data store' instead of naming every tool that can do it. Shipped on the bundle rather than compiled into the binary so a newly popular tool becomes classifiable without a client release. An action may carry several tuples, and an effect leaf matches if ANY tuple matches. New in schema 2; same emission rule as install_id.",
/// "type": "object",
/// "properties": {
/// "entries": {
/// "description": "The feed's entries, one per classifiable tool key.",
/// "type": "array",
/// "items": {
/// "title": "EffectClassEntry",
/// "type": "object",
/// "properties": {
/// "effects": {
/// "description": "The effect tuples a matching call produces.",
/// "type": "array",
/// "items": {
/// "title": "EffectTuple",
/// "type": "object",
/// "properties": {
/// "attrs": {
/// "description": "Attributes attached to this tuple, readable from a leaf as effect.attrs.<name> (D-16). The first is is_production, resolved from the env_selectors fact — a starter-library entry already reads effect.attrs.is_production, and without this the entry is unmatchable as written. Open by construction: an attribute the client does not know makes a leaf naming it inconclusive, never false.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "target_class": {
/// "description": "What it does it to.",
/// "$ref": "#/$defs/TargetClass"
/// },
/// "verb": {
/// "description": "What the action does.",
/// "$ref": "#/$defs/EffectVerb"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "id": {
/// "description": "Stable identifier for this entry.",
/// "type": "string"
/// },
/// "modified": {
/// "description": "Feed version or RFC 3339 timestamp of the last change to the entry.",
/// "type": "string"
/// },
/// "related": {
/// "description": "Ids of entries a reviewer should look at alongside this one.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "selectors": {
/// "description": "Attribute leaves narrowing WHICH calls of tool_key this entry classifies — the same leaf shape a Tier 1 predicate tree uses, so one classifier reads both. An entry with no selectors classifies every call of the tool.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/t1_leaf"
/// }
/// },
/// "since": {
/// "description": "Feed version or RFC 3339 timestamp at which the entry first appeared.",
/// "type": "string"
/// },
/// "status": {
/// "description": "Lifecycle of the entry in the feed. Open: an unknown status leaves the entry usable, because dropping a classification on a word the client did not recognise would silently widen what a rule fails to match.",
/// "type": "string"
/// },
/// "tool_key": {
/// "description": "The tool this entry classifies, as the evaluator sees it — 'Bash', or 'mcp__<server>__<tool>' for MCP.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "feed_version": {
/// "description": "Version of the feed as published. A string, not a number: '1.2' as a JSON number would be a float, and this bundle carries no floats anywhere.",
/// "type": "string"
/// },
/// "required_engine_version": {
/// "description": "The minimum classifier engine version that can read this feed correctly. A client below it keeps its BUILT-IN feed rather than mis-reading this one — a classifier that half-understands a feed produces wrong effect tuples, which is worse than an old but coherent one.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// },
/// "enforcement_enabled": {
/// "description": "The organization-wide kill switch. When false, every rule behaves as observe regardless of its own mode — matches produce a shadow verdict and nothing is blocked. Stored outside the built artifact on the platform so it survives every rebuild.",
/// "type": "boolean"
/// },
/// "fact_refs": {
/// "description": "Facts too large to inline (above 2,000 members or 64 KB), fetched out of band and verified against sha256. An unfetchable, oversize or hash-mismatching ref resolves as an ABSENT fact — never a default, never a bundle rejection. That is the whole point of the split: a fact the client could not get must degrade to 'unknown', which the artifact's on_inconclusive then decides, rather than to a silent pass. New in schema 2; same emission rule as install_id.",
/// "type": "array",
/// "items": {
/// "title": "BundleFactRef",
/// "type": "object",
/// "properties": {
/// "fact_id": {
/// "description": "Identifier a fact leaf names, exactly as for an inline fact — a leaf cannot tell whether its fact arrived inline or by reference.",
/// "$ref": "#/$defs/FactId"
/// },
/// "max_age_s": {
/// "description": "How old the observation may be before the fact resolves as absent, in seconds.",
/// "type": "integer"
/// },
/// "observed_at": {
/// "description": "RFC 3339 UTC timestamp of observation at the source, as for an inline fact.",
/// "type": "string"
/// },
/// "revision": {
/// "description": "Monotonic revision, matching this fact's entry in inputs.fact_revs. A changed revision is what tells the poller to refetch.",
/// "type": "integer"
/// },
/// "sha256": {
/// "description": "Lowercase hex digest of the fetched bytes. A mismatch resolves the fact as absent; the client never evaluates against bytes it could not verify.",
/// "type": "string"
/// },
/// "size_bytes": {
/// "description": "Expected size, so a response that is wildly wrong is abandoned before it is buffered.",
/// "type": "integer"
/// },
/// "url": {
/// "description": "Where the bytes are fetched from. Fetched by the poller, off the verdict path — an evaluation that needed a round trip to decide would be a design error, not a slow path.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "facts": {
/// "description": "Inline facts the evaluator resolves fact leaves against — the world model a rule reads ('is this host approved?', 'is this ticket closed?'). Inline up to the cap of 2,000 members or 64 KB; larger ones ship as fact_refs below. A fact is three-valued (R15): present and matching, present and not matching, or ABSENT — and absent is never silently a default. New in schema 2; same emission rule as install_id.",
/// "type": "array",
/// "items": {
/// "title": "BundleFact",
/// "type": "object",
/// "properties": {
/// "closed_world": {
/// "description": "Whether membership in this fact is exhaustive. True means 'not in the set' is a real negative; false means it is unknown, and a leaf testing non-membership is inconclusive rather than matching. The difference between 'this host is not approved' and 'we do not know whether it is'.",
/// "type": "boolean"
/// },
/// "fact_id": {
/// "description": "Identifier a fact leaf names. Open, carrying the known vocabulary as x-known-values: a fact the client does not know is still carried and still resolvable by id, because the evaluator matches on the id, not on a variant.",
/// "$ref": "#/$defs/FactId"
/// },
/// "kind": {
/// "description": "The fact's shape — what `value` holds and how a leaf may compare against it (a set, a scalar, a table). Open, and a fact whose kind the client cannot interpret resolves as ABSENT rather than as a default.",
/// "type": "string"
/// },
/// "leeway_s": {
/// "description": "Grace added to max_age_s, in seconds, so ordinary clock skew and a late refresh do not flip a fact to absent and turn every rule reading it inconclusive at once.",
/// "type": "integer"
/// },
/// "max_age_s": {
/// "description": "How old the observation may be before the fact resolves as absent, in seconds. The client compares against the daemon-injected now_ms, never the wall clock read inside the evaluator.",
/// "type": "integer"
/// },
/// "observed_at": {
/// "description": "RFC 3339 UTC timestamp of when the value was observed at the source, NOT when the bundle was built. Age is measured from here, so a bundle rebuild cannot make a stale fact look fresh.",
/// "type": "string"
/// },
/// "revision": {
/// "description": "Monotonic revision of this fact, matching its entry in inputs.fact_revs.",
/// "type": "integer"
/// },
/// "source": {
/// "description": "Where the value came from — which connector or upload produced it. Shown to whoever has to answer for a fact-driven deny.",
/// "type": "string"
/// },
/// "valid_from": {
/// "description": "Optional RFC 3339 lower bound on when this value applies. Absent means it applies from observed_at.",
/// "type": "string"
/// },
/// "valid_until": {
/// "description": "Optional RFC 3339 upper bound. Past it the fact is ABSENT, not false.",
/// "type": "string"
/// },
/// "value": {
/// "description": "The fact's content, in the shape its `kind` declares. Deliberately unconstrained — the evaluator interprets it per kind, and a type keyword here would fail the whole bundle on one fact whose kind the schema had not anticipated."
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "inputs": {
/// "description": "The revisions this bundle was materialised from — the composition's inputs, never its content. Equal inputs mean byte-identical output, which is what lets built_at stay memoised at the last real content change instead of being restamped on every poll, and what lets a replay reconstruct a composition from four integers. New in schema 2; the platform MUST NOT emit it to a fleet that still runs clients predating it (see install_id for why that would be fatal rather than merely ignored).",
/// "type": "object",
/// "properties": {
/// "effect_class_rev": {
/// "description": "Revision of the effect-class feed carried in effect_classes below — the classifier's input, versioned separately from policy because a feed refresh changes what a rule matches without any rule having been edited.",
/// "type": "integer"
/// },
/// "fact_revs": {
/// "description": "Per-fact revision, keyed by fact_id. A map rather than a list so refreshing one fact is a one-key delta; keys carry the FactId vocabulary, which is open, so an unrecognised key is carried rather than rejected.",
/// "type": "object",
/// "additionalProperties": {
/// "type": "integer"
/// }
/// },
/// "policy_rev": {
/// "description": "Revision of the ratified policy set composed into this bundle. Monotonic per organization.",
/// "type": "integer"
/// },
/// "zone_rev": {
/// "description": "Revision of the autonomy zone tree at composition time. Re-parenting a unit moves this without touching policy_rev, and it is the input that explains a bundle change no policy edit accounts for.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
/// },
/// "install_id": {
/// "description": "Canonical UUID of the install this bundle was composed FOR — the (organization, agent) pair the poller authenticated as, not the organization itself. One organization has many installs, and artifacts, facts and meta.effective_zone below are composed per install, so a replay needs this to reconstruct the exact composition that produced a verdict. New in schema 2. The platform MUST NOT emit this field to a fleet that still runs clients predating it: the bundle root is additionalProperties:false, so such a client rejects the whole document (OL-1212) and fails static on its previous rules. That is what client_floor.min_client_version exists to prevent, and it is why the floor is a correctness requirement rather than a nicety.",
/// "type": "string"
/// },
/// "meta": {
/// "description": "What this install resolved to at composition time — the context a developer needs to read a verdict, and the context a support conversation starts from. Informational: nothing here is evaluated. New in schema 2; same emission rule as install_id.",
/// "type": "object",
/// "properties": {
/// "agent_type": {
/// "description": "The CATEGORY of work this agent does — coding, analysis, ops, content, service. The wire name is agent_type because that is the frozen contract name, but the type it carries is AgentCategory: in this repository AgentType already means the agent PLATFORM (claude-code, cursor, ...), which is a different axis entirely. Read either in full where both could be meant.",
/// "$ref": "#/$defs/AgentCategory"
/// },
/// "effective_zone": {
/// "title": "EffectiveZone",
/// "description": "The autonomy zone this install actually landed in, and how it got there.",
/// "type": "object",
/// "properties": {
/// "node_id": {
/// "description": "Identifier of the resolved zone node.",
/// "type": "string"
/// },
/// "path": {
/// "description": "Root-to-node path, so 'which zone am I in?' is answerable from the bundle alone.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "resolved_from": {
/// "description": "Whether the assignment was derived from the directory (auto) or set by a person (manual). An open string rather than a closed set, per R14.",
/// "type": "string",
/// "x-known-values": [
/// "auto",
/// "manual"
/// ]
/// }
/// },
/// "additionalProperties": true
/// },
/// "environment": {
/// "description": "The environment this install was classified into. Defaults to production platform-side, because the safe reading of an unclassified host is the one that assumes the blast radius is real.",
/// "$ref": "#/$defs/Environment"
/// },
/// "omitted_kinds": {
/// "description": "Artifact kinds the platform DELIBERATELY left out of this bundle, because this install's reported version cannot evaluate them. The difference between 'there is no such rule' and 'there is one and you are not running it' — without this, a client below a capability floor looks compliant while silently enforcing less than the organization authored.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/ArtifactKind"
/// }
/// }
/// },
/// "additionalProperties": true
/// },
/// "organization_id": {
/// "description": "Canonical UUID form of the owning organization, matching the platform's organization_id column — not the API-key prefix. The client learns its own org from GET /api/v1/users/me, caches it in bundle.meta.json, and MUST reject a bundle whose value differs (OL-1211). Never evaluate another org's rules.",
/// "type": "string"
/// },
/// "revision": {
/// "description": "Monotonic per organization, incrementing only on real content change — a rebuild over unchanged rules is a no-op that leaves this untouched. Serialized as a JSON number and treated as i64 in Rust. Recorded on every verdict as olpolicybundlerev: the replay key.",
/// "type": "integer"
/// },
/// "rules": {
/// "description": "The active rule set, sorted by rule_id so the serialization is deterministic. May be empty, which means 'allow everything' and is distinguishable in telemetry from 'no bundle' because olpolicybundlerev is still stamped. Rules disabled by the author are omitted at build time — every rule present here is active.",
/// "type": "array",
/// "items": {
/// "title": "PolicyRule",
/// "description": "One authored rule, on either plane. A kind=command rule is evaluated against the normalized command string extracted from a pre_tool_use envelope. A kind=request rule targets an outbound model request at the boundary and is held, not evaluated, in v1. The allOf below is the per-kind/per-action gate: the platform enforces it at authoring time (422) and the client validates every rule against it individually at bundle load, skipping the ones that fail — one bad rule must never cost the fleet its denies.",
/// "type": "object",
/// "required": [
/// "action",
/// "kind",
/// "mode",
/// "reason",
/// "rule_id",
/// "severity"
/// ],
/// "properties": {
/// "action": {
/// "description": "What a match does. Authorable actions are 'deny' (the only one on kind=command) and 'prefix_reorder', 'history_trim', 'prompt_edit' (kind=request). Which action is legal for which kind is owned by the gate below, not by this list. An open string for the same forward-compatibility reason as kind.",
/// "type": "string"
/// },
/// "conditions": {
/// "description": "Which agents the rule applies to, decided locally by the client against the client_config.agent_context THIS install received — the network is not on the evaluation path. Absent (or empty) means unconditional: the rule applies on every agent, exactly as before this field existed. When present, EVERY condition must hold (AND semantics), and a rule whose context never arrived matches nothing — absent context is not 'unknown'. v1 is the command plane only: forbidden on kind=request by the gate below, and the only vocabulary is field 'agent.function' with op 'in'. The field/op enums are the general shape, so widening either later is additive; a client that predates a widening drops that one rule at load (unrecognized_field) and keeps the bundle. Values are the closed AgentFunction enum, so a value the client does not know fails that one rule at deserialization, never the whole document. 'unknown' is an ordinary value, not a wildcard.",
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "field",
/// "op",
/// "value"
/// ],
/// "properties": {
/// "field": {
/// "description": "The agent-context attribute the condition reads. v1 knows exactly one: 'agent.function', read from client_config.agent_context.function.",
/// "type": "string",
/// "enum": [
/// "agent.function"
/// ]
/// },
/// "op": {
/// "description": "The comparison. v1 knows exactly one: 'in' — the attribute's value is a member of `value`. Several conditions on the same field AND together, so two 'in' sets intersect.",
/// "type": "string",
/// "enum": [
/// "in"
/// ]
/// },
/// "value": {
/// "description": "The set the attribute must belong to. At least one member — an empty set would match nothing while looking like a scoped rule, and the platform rejects it at authoring (422). Compared by enum equality on the client.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/AgentFunction"
/// },
/// "minItems": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "kind": {
/// "description": "Which plane the rule acts on. Two kinds are authorable: 'command' (a shell command intercepted at the pre_tool_use hook) and 'request' (an outbound model request intercepted at the boundary). Deliberately an open string rather than a closed enum: the client MUST skip a rule whose kind it does not recognize and keep the rest of the bundle active, so that a v1 client tolerates a v1.1 bundle. A closed enum would fail deserialization of the whole document instead.",
/// "type": "string"
/// },
/// "match_pattern": {
/// "description": "Required for kind=command and forbidden for kind=request — see the gate below; it is optional in the base only so that a request rule does not fail deserialization on a client that predates the gate. Fully-anchored, case-sensitive glob over the entire normalized command string. Exactly two metacharacters: '*' (any sequence including empty, crossing '/' and every other character — this is not path-aware globbing) and '?' (exactly one character). No character classes, no escapes, no alternation, no regex. Anchoring surprises authors: 'rm -rf /*' does not match 'sudo rm -rf /tmp'; write '*rm -rf*' to catch a command anywhere in the string. The platform normalizes and validates this at authoring time and rejects empty, over-1024-character, control-character-bearing, and bare-'*' patterns with 422.",
/// "type": "string"
/// },
/// "mode": {
/// "description": "Staged rollout control. 'observe' records a shadow verdict and allows the action; 'enforce' denies it. Most restrictive wins across matching rules. Overridden to observe for every rule when enforcement_enabled is false.",
/// "type": "string",
/// "enum": [
/// "observe",
/// "enforce"
/// ]
/// },
/// "params": {
/// "description": "How a kind=request rule transforms the request. Forbidden on kind=command. Exactly which keys are required and which are rejected is per-action, in the gate below.",
/// "type": "object",
/// "properties": {
/// "keep_messages": {
/// "description": "How many of the most recent messages history_trim retains. Required by history_trim, rejected everywhere else.",
/// "type": "integer"
/// },
/// "marker": {
/// "description": "The literal marker prompt_edit rewrites around. Deliberately unconstrained here: a length or pattern keyword would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one over-long value. Length is bounded platform-side at authoring.",
/// "type": "string"
/// },
/// "max_system_tokens": {
/// "description": "Token ceiling prompt_edit trims the system block to. Alternative to marker — exactly one of the two is required.",
/// "type": "integer"
/// },
/// "mechanism": {
/// "description": "Which caching intervention a prefix_reorder rule means. The detector that authors these rules fires on two different causes needing two different interventions, and the action alone cannot tell them apart: 'insert_breakpoints' — nothing is being cached at all, so cache_control breakpoints must be INJECTED; 'reorder_blocks' — breakpoints exist but a volatile block sits early in the prefix and must be MOVED after the stable ones. Read by prefix_reorder only. Deliberately an OPEN string rather than an enum, for the same reason as kind and action: an out-of-vocabulary value must fail one rule, not deserialization of the whole bundle. An enum here would be a known field with an unknown value, which the unknown-FIELD tolerance does not cover. Absent means the rule names no mechanism — a client that cannot infer one skips it rather than guessing.",
/// "examples": [
/// "insert_breakpoints",
/// "reorder_blocks"
/// ],
/// "type": "string"
/// }
/// },
/// "additionalProperties": false
/// },
/// "provenance": {
/// "description": "Where this schema-1 rule came from in the schema-2 authoring model, when the platform composed it from a ratified atom rather than from a hand-written rule. Purely informational on the client: it is stamped onto the record (olatomid, olpolicyid, oldimension, ollayer, olmode) so a verdict can be traced back to the policy that produced it, and it never changes what the rule matches or what it does. Absent on a rule with no atom behind it. Tolerant like every schema-2 object, so a newer platform can add a provenance key without failing an older client — the enclosing rule object stays additionalProperties:false, so an unknown key at RULE level still skips that one rule (never the document), which is the tolerance parse_bundle_tolerant provides.",
/// "type": "object",
/// "properties": {
/// "atom_id": {
/// "description": "The ratified intent atom this rule was compiled from. Recorded on the verdict as olatomid.",
/// "type": "string"
/// },
/// "dimension": {
/// "description": "Which dimension the owning policy belongs to. Recorded as oldimension.",
/// "$ref": "#/$defs/Dimension"
/// },
/// "mode": {
/// "description": "The composed mode of the owning policy (monitor or enforce; a disabled policy is never composed). Distinct from the rule's own `mode` field, which is the schema-1 observe/enforce control the evaluator actually reads — this one is recorded as olmode and describes the policy, not this rule's rollout stage.",
/// "$ref": "#/$defs/PolicyMode"
/// },
/// "policy_id": {
/// "description": "The policy owning that atom. Recorded as olpolicyid; the public identifier the console shows is policy_public_id on the artifact plane.",
/// "type": "string"
/// },
/// "zone_layer": {
/// "description": "Identifier of the autonomy-zone unit this rule was inherited from — the layer that contributed it, not the agent's own zone. Recorded as ollayer.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// },
/// "reason": {
/// "description": "Plain-language explanation shown to the developer verbatim when the rule blocks an action. A deny the developer cannot understand is a broken feature.",
/// "type": "string"
/// },
/// "rule_id": {
/// "description": "Stable public identifier, e.g. 'OL-CMD-001'. Unique within the organization. Reported on the verdict as olpolicyruleid, and the tiebreak key: the lexicographically first rule within the deciding set is the one reported.",
/// "type": "string"
/// },
/// "rule_version": {
/// "description": "Required for kind=request, absent on kind=command — the middle term of the D-04 replay tuple, so a would-have report can be tied to the exact rule text that produced it. Platform-managed: set on create and incremented on every edit, never authored by hand.",
/// "type": "integer"
/// },
/// "select": {
/// "description": "Which requests a kind=request rule applies to; an absent select means every request the boundary sees. Forbidden on kind=command. Each key is narrowed further per action by the gate below — a key that an action does not read is rejected rather than silently ignored.",
/// "type": "object",
/// "properties": {
/// "exclude_layers": {
/// "description": "Cache layers this rule must leave untouched. Read by prefix_reorder only.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/ChurnLayer"
/// }
/// },
/// "min_messages": {
/// "description": "Apply only once the in-context history has at least this many messages. Read by history_trim only.",
/// "type": "integer"
/// },
/// "model_in": {
/// "description": "Apply only to requests whose model identifier is in this list. Matched verbatim against the model string on the wire; no globbing.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": false
/// },
/// "severity": {
/// "description": "Author-assigned severity, surfaced on the verdict returned to the agent hook.",
/// "type": "string",
/// "enum": [
/// "low",
/// "medium",
/// "high",
/// "critical"
/// ]
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "schema_version": {
/// "description": "Bundle format version. 1 is the v1 format; 2 adds the artifact, fact, effect-class, directive-template and meta sections and the header's install_id, inputs and client_floor. A client that reads this file knows both and MUST accept either. The client MUST still refuse a bundle whose schema_version it does not know and keep the previous bundle (OL-1212). Forward compatibility is the platform's responsibility, not the client's — and because the root is additionalProperties:false, a client that only knows 1 rejects a schema-2 document outright, which is what client_floor.min_client_version exists to prevent.",
/// "type": "integer"
/// },
/// "signature": {
/// "description": "Reserved for a detached Ed25519 signature over the canonical bytes. Required but always null in v1, and the client MUST accept null. A client that cannot verify a non-null signature MUST reject the bundle rather than ignore the field, so that enabling signing later cannot be silently downgraded by an old client.",
/// "default": null,
/// "type": [
/// "string",
/// "null"
/// ]
/// }
/// },
/// "additionalProperties": false,
/// "x-postgresql-skip": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PolicyBundle {
///The compiled policy artifacts — schema 2's evaluation plane, sorted by artifact_id so the serialization is deterministic. Each entry is a TYPED ENVELOPE around an UNTYPED body whose shape is selected by `kind`: $defs.t1_predicate_tree, $defs.t2_register_program, $defs.t3_hold and $defs.exception. The two-stage parse is deliberate and not a shortcut. build.rs strips if/then/else before typify sees it (typify hard-panics on conditionals), so a discriminator written as an if/then or an allOf on `kind` would silently NOT EXIST in the generated types — the same failure that already forced src/core/policy/validate.rs to be hand-written. The loader parses the envelope, reads `kind`, parses the body against the matching $def, and SKIPS the item on failure: one unparseable artifact must never cost the fleet its denies, and an unknown `kind` is skipped for the same reason. No field is required, so a truncated artifact is skipped rather than failing the document. New in schema 2; same emission rule as install_id.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub artifacts: ::std::vec::Vec<PolicyArtifact>,
///RFC 3339 UTC timestamp with a Z suffix (microsecond precision allowed) recording when the rule content last actually changed — not when the bundle was served. Drives olpolicybundleage (now minus built_at, clamped at 0), which measures policy freshness. It does NOT drive the staleness warning, which is measured from the last successful fetch. Deliberately a plain string rather than format: date-time so the generated Rust type stays a String; the poller parses it once into a SystemTime.
pub built_at: ::std::string::String,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub client_config: ::std::option::Option<PolicyBundleClientConfig>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub client_floor: ::std::option::Option<PolicyBundleClientFloor>,
///The text a Tier 3 hold puts in front of the model when it asks for a fact ('Before this call, state whether ...'). Generated AT COMPILE TIME by the compiler from the atom's fact leaf and editable by the owner in the wizard — never composed at runtime, so the client renders a template it was given rather than writing a prompt of its own. New in schema 2; same emission rule as install_id.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub directive_templates: ::std::vec::Vec<DirectiveTemplate>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub effect_classes: ::std::option::Option<PolicyBundleEffectClasses>,
///The organization-wide kill switch. When false, every rule behaves as observe regardless of its own mode — matches produce a shadow verdict and nothing is blocked. Stored outside the built artifact on the platform so it survives every rebuild.
pub enforcement_enabled: bool,
///Facts too large to inline (above 2,000 members or 64 KB), fetched out of band and verified against sha256. An unfetchable, oversize or hash-mismatching ref resolves as an ABSENT fact — never a default, never a bundle rejection. That is the whole point of the split: a fact the client could not get must degrade to 'unknown', which the artifact's on_inconclusive then decides, rather than to a silent pass. New in schema 2; same emission rule as install_id.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub fact_refs: ::std::vec::Vec<BundleFactRef>,
///Inline facts the evaluator resolves fact leaves against — the world model a rule reads ('is this host approved?', 'is this ticket closed?'). Inline up to the cap of 2,000 members or 64 KB; larger ones ship as fact_refs below. A fact is three-valued (R15): present and matching, present and not matching, or ABSENT — and absent is never silently a default. New in schema 2; same emission rule as install_id.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub facts: ::std::vec::Vec<BundleFact>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub inputs: ::std::option::Option<PolicyBundleInputs>,
///Canonical UUID of the install this bundle was composed FOR — the (organization, agent) pair the poller authenticated as, not the organization itself. One organization has many installs, and artifacts, facts and meta.effective_zone below are composed per install, so a replay needs this to reconstruct the exact composition that produced a verdict. New in schema 2. The platform MUST NOT emit this field to a fleet that still runs clients predating it: the bundle root is additionalProperties:false, so such a client rejects the whole document (OL-1212) and fails static on its previous rules. That is what client_floor.min_client_version exists to prevent, and it is why the floor is a correctness requirement rather than a nicety.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub install_id: ::std::option::Option<::std::string::String>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub meta: ::std::option::Option<PolicyBundleMeta>,
///Canonical UUID form of the owning organization, matching the platform's organization_id column — not the API-key prefix. The client learns its own org from GET /api/v1/users/me, caches it in bundle.meta.json, and MUST reject a bundle whose value differs (OL-1211). Never evaluate another org's rules.
pub organization_id: ::std::string::String,
///Monotonic per organization, incrementing only on real content change — a rebuild over unchanged rules is a no-op that leaves this untouched. Serialized as a JSON number and treated as i64 in Rust. Recorded on every verdict as olpolicybundlerev: the replay key.
pub revision: i64,
///The active rule set, sorted by rule_id so the serialization is deterministic. May be empty, which means 'allow everything' and is distinguishable in telemetry from 'no bundle' because olpolicybundlerev is still stamped. Rules disabled by the author are omitted at build time — every rule present here is active.
pub rules: ::std::vec::Vec<PolicyRule>,
///Bundle format version. 1 is the v1 format; 2 adds the artifact, fact, effect-class, directive-template and meta sections and the header's install_id, inputs and client_floor. A client that reads this file knows both and MUST accept either. The client MUST still refuse a bundle whose schema_version it does not know and keep the previous bundle (OL-1212). Forward compatibility is the platform's responsibility, not the client's — and because the root is additionalProperties:false, a client that only knows 1 rejects a schema-2 document outright, which is what client_floor.min_client_version exists to prevent.
pub schema_version: i64,
///Reserved for a detached Ed25519 signature over the canonical bytes. Required but always null in v1, and the client MUST accept null. A client that cannot verify a non-null signature MUST reject the bundle rather than ignore the field, so that enabling signing later cannot be silently downgraded by an old client.
pub signature: ::std::option::Option<::std::string::String>,
}
///Client-bound configuration delivered on the bundle — the only client-bound configuration channel. Optional; a client that never receives it captures nothing (fail closed). The platform MUST NOT emit this field to a fleet that still runs clients predating it: the bundle root is additionalProperties:false, so such a client rejects the whole document (OL-1212) and fails static on its previous rules.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Client-bound configuration delivered on the bundle — the only client-bound configuration channel. Optional; a client that never receives it captures nothing (fail closed). The platform MUST NOT emit this field to a fleet that still runs clients predating it: the bundle root is additionalProperties:false, so such a client rejects the whole document (OL-1212) and fails static on its previous rules.",
/// "type": "object",
/// "properties": {
/// "agent_context": {
/// "description": "This install's own agent context, composed by the platform at serve time from the X-OpenLatch-Agent-Id header the poller sends — one object about THIS agent, never a fleet roster. Optional: a client that never receives it holds no context, and every rule carrying conditions matches nothing (absent context is not 'unknown'). Tolerant like its parent, so a newer platform can add keys without failing older clients.",
/// "type": "object",
/// "properties": {
/// "function": {
/// "description": "The business function assigned to this agent's owner. Deliberately an OPEN string carrying the AgentFunction vocabulary as x-known-values rather than a $ref to that enum — the same reasoning as params.mechanism: client_config is deserialized as one typed object outside the per-rule tolerance, so an enum here would fail the WHOLE bundle (fleet-wide fail-static) on a single out-of-vocabulary value. The client parses it into AgentFunction at load; a STRING value it cannot parse reads as no context, so scoped rules match nothing rather than the bundle being rejected. The tolerance is over the vocabulary, not the shape: a non-string value here (or a non-object agent_context) is a malformed client_config and does fail the whole document, exactly as a malformed capture_identity_signals does. 'unknown' is a real platform-assigned value, distinct from the field being absent.",
/// "type": "string",
/// "x-known-values": [
/// "engineering",
/// "product",
/// "data",
/// "security",
/// "it_ops",
/// "sales",
/// "marketing",
/// "finance",
/// "legal",
/// "hr",
/// "support",
/// "research",
/// "other",
/// "unknown"
/// ]
/// }
/// },
/// "additionalProperties": true
/// },
/// "capture_identity_signals": {
/// "description": "The client's copy of the org setting identity.capture_signals. Identity signals are captured and stamped only when this is explicitly true.",
/// "type": "boolean"
/// },
/// "hold": {
/// "description": "Bounds on the Tier 3 hold path — the one place where a verdict waits on a human. Both bounds exist so that a console that never answers, or an agent that fires holds faster than anyone can read them, degrades into a prompt deny with a legible reason rather than into an agent that appears hung.",
/// "type": "object",
/// "properties": {
/// "host_timeout_s": {
/// "description": "How long the daemon holds a pending action before applying the artifact's on_timeout verdict, in seconds. Bounded below by the agent's own hook timeout in practice: a hold that outlives the hook is decided by the harness, not by us.",
/// "type": "integer"
/// },
/// "max_pending_holds": {
/// "description": "The hold buffer's explicit cap, default 16. A hold artifact firing beyond it is NOT buffered: the daemon prints an immediate deny whose reason names the full buffer, and records result: held_timeout. An unbounded buffer would turn a runaway agent into an unbounded queue of prompts nobody will ever answer.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
/// },
/// "jitter_pct": {
/// "description": "Percentage of poll_interval_s to spread each client's next poll over, so a fleet that started together does not stay synchronised and hammer the endpoint on the same second. An integer percentage, applied by the client to its own interval; absent means the client keeps its own default.",
/// "type": "integer"
/// },
/// "levers": {
/// "description": "One optional block per lever (the Lever vocabulary in enums.schema.json). An ABSENT block means measure only — the lever's atoms still evaluate and still record, but the client performs no intervention. This is the safe default and the reason each block is optional rather than defaulted: a lever the organization never configured must never start rewriting an agent's traffic because a bundle grew a field. Every rewrite-capable block may carry visible_in_monitor (default false), the Monitor-visible rewrite opt-in: with it false a monitor-mode lever records what it WOULD have done and changes nothing, which is what makes Monitor mode honest.",
/// "type": "object",
/// "properties": {
/// "context_edit": {
/// "description": "Clears stale tool results out of the context window once it crosses a trigger. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "clear_at_least": {
/// "description": "Minimum tokens an edit must reclaim to be worth doing — below it the edit is skipped, because an edit that reclaims almost nothing still costs the whole prefix its cache.",
/// "type": "integer"
/// },
/// "exclude_tools": {
/// "description": "Tool names whose results are never cleared. Tool-name globs, matched the same way the atom language matches does_what.tools.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "keep": {
/// "description": "How many of the most recent tool results survive an edit.",
/// "type": "integer"
/// },
/// "trigger": {
/// "description": "Token count at which an edit is considered. Integer tokens, never a fraction of a window.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "effort_clamp": {
/// "description": "Caps the reasoning effort an agent may request, per agent category. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "by_agent_type": {
/// "description": "Map of agent category (the AgentCategory vocabulary — coding, analysis, ops, content, service) to the effort level that category is clamped to. A map rather than a list so one category can be retuned as a one-key delta, and an open one so an unknown category is carried rather than rejected.",
/// "type": "object",
/// "additionalProperties": {
/// "type": "string"
/// }
/// },
/// "quality_floor": {
/// "description": "The level the clamp may never go below, whatever by_agent_type says. Present so that tightening the clamp org-wide cannot silently drop an agent under the quality bar its owner signed up for.",
/// "type": "string"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false: monitor records the would-have and changes nothing.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "loop_stop": {
/// "description": "Stops an agent that is repeating itself. Keys on identical (tool, normalised input, result hash) — deliberately distinct from the run_le session shape, which keys on action shape and therefore treats Read a.py and Read b.py as the same. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "exempt_patterns": {
/// "description": "Calls matching these are never counted toward either bound — polling loops that are supposed to repeat.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "n_errors": {
/// "description": "Consecutive erroring calls before the loop is stopped. Default 3.",
/// "type": "integer"
/// },
/// "n_identical": {
/// "description": "Consecutive identical calls before the loop is stopped. Default 4.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's intervention while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "narrow_output": {
/// "description": "Filters a command's output down to what the agent actually needs, instead of feeding a whole log back into the context. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "allowlist": {
/// "description": "The only commands whose output is narrowed. An allowlist rather than a denylist: narrowing output the author did not anticipate is a correctness risk, so an unlisted command passes through untouched.",
/// "type": "array",
/// "items": {
/// "title": "NarrowOutputEntry",
/// "type": "object",
/// "properties": {
/// "command_prefix": {
/// "description": "Prefix of the normalised command string this entry applies to.",
/// "type": "string"
/// },
/// "filter": {
/// "description": "How the output is narrowed for that prefix.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "prefix_guard": {
/// "description": "Pins the stable prefix so a volatile block cannot keep invalidating the cache. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pin_ttl": {
/// "description": "How long a pin survives, as a duration string ('1h'), or null for no expiry. The one duration on this bundle that is not an integer of seconds, because it is passed through to the provider verbatim rather than computed on.",
/// "type": [
/// "string",
/// "null"
/// ]
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "steer": {
/// "description": "Injects the atom's steer_instruction into the agent's context instead of blocking it. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "dedupe_window_s": {
/// "description": "How long the same instruction is suppressed after being delivered, in seconds. Without it a steer atom that keeps matching repeats itself every call and becomes noise the model learns to ignore.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "substitute": {
/// "description": "Replaces one call with a cheaper or safer equivalent. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pairs": {
/// "description": "The substitutions, applied in order.",
/// "type": "array",
/// "items": {
/// "title": "SubstitutePair",
/// "type": "object",
/// "properties": {
/// "from": {
/// "description": "What is matched.",
/// "type": "string"
/// },
/// "to": {
/// "description": "What replaces it.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "additionalProperties": true
/// },
/// "poll_interval_s": {
/// "description": "How often the poller asks for a new bundle, in seconds. Platform-controlled so the fleet's load can be moved without a client release. Absent means the client keeps its own default (300s). Seconds, integer — durations on this bundle are never fractional, because a float would reintroduce the RFC 8785 ES6 Number::toString divergence the integers-only rule eliminates by construction.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfig {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub agent_context: ::std::option::Option<PolicyBundleClientConfigAgentContext>,
///The client's copy of the org setting identity.capture_signals. Identity signals are captured and stamped only when this is explicitly true.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub capture_identity_signals: ::std::option::Option<bool>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub hold: ::std::option::Option<PolicyBundleClientConfigHold>,
///Percentage of poll_interval_s to spread each client's next poll over, so a fleet that started together does not stay synchronised and hammer the endpoint on the same second. An integer percentage, applied by the client to its own interval; absent means the client keeps its own default.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub jitter_pct: ::std::option::Option<i64>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub levers: ::std::option::Option<PolicyBundleClientConfigLevers>,
///How often the poller asks for a new bundle, in seconds. Platform-controlled so the fleet's load can be moved without a client release. Absent means the client keeps its own default (300s). Seconds, integer — durations on this bundle are never fractional, because a float would reintroduce the RFC 8785 ES6 Number::toString divergence the integers-only rule eliminates by construction.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub poll_interval_s: ::std::option::Option<i64>,
}
impl ::std::default::Default for PolicyBundleClientConfig {
fn default() -> Self {
Self {
agent_context: Default::default(),
capture_identity_signals: Default::default(),
hold: Default::default(),
jitter_pct: Default::default(),
levers: Default::default(),
poll_interval_s: Default::default(),
}
}
}
///This install's own agent context, composed by the platform at serve time from the X-OpenLatch-Agent-Id header the poller sends — one object about THIS agent, never a fleet roster. Optional: a client that never receives it holds no context, and every rule carrying conditions matches nothing (absent context is not 'unknown'). Tolerant like its parent, so a newer platform can add keys without failing older clients.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "This install's own agent context, composed by the platform at serve time from the X-OpenLatch-Agent-Id header the poller sends — one object about THIS agent, never a fleet roster. Optional: a client that never receives it holds no context, and every rule carrying conditions matches nothing (absent context is not 'unknown'). Tolerant like its parent, so a newer platform can add keys without failing older clients.",
/// "type": "object",
/// "properties": {
/// "function": {
/// "description": "The business function assigned to this agent's owner. Deliberately an OPEN string carrying the AgentFunction vocabulary as x-known-values rather than a $ref to that enum — the same reasoning as params.mechanism: client_config is deserialized as one typed object outside the per-rule tolerance, so an enum here would fail the WHOLE bundle (fleet-wide fail-static) on a single out-of-vocabulary value. The client parses it into AgentFunction at load; a STRING value it cannot parse reads as no context, so scoped rules match nothing rather than the bundle being rejected. The tolerance is over the vocabulary, not the shape: a non-string value here (or a non-object agent_context) is a malformed client_config and does fail the whole document, exactly as a malformed capture_identity_signals does. 'unknown' is a real platform-assigned value, distinct from the field being absent.",
/// "type": "string",
/// "x-known-values": [
/// "engineering",
/// "product",
/// "data",
/// "security",
/// "it_ops",
/// "sales",
/// "marketing",
/// "finance",
/// "legal",
/// "hr",
/// "support",
/// "research",
/// "other",
/// "unknown"
/// ]
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigAgentContext {
///The business function assigned to this agent's owner. Deliberately an OPEN string carrying the AgentFunction vocabulary as x-known-values rather than a $ref to that enum — the same reasoning as params.mechanism: client_config is deserialized as one typed object outside the per-rule tolerance, so an enum here would fail the WHOLE bundle (fleet-wide fail-static) on a single out-of-vocabulary value. The client parses it into AgentFunction at load; a STRING value it cannot parse reads as no context, so scoped rules match nothing rather than the bundle being rejected. The tolerance is over the vocabulary, not the shape: a non-string value here (or a non-object agent_context) is a malformed client_config and does fail the whole document, exactly as a malformed capture_identity_signals does. 'unknown' is a real platform-assigned value, distinct from the field being absent.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub function: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for PolicyBundleClientConfigAgentContext {
fn default() -> Self {
Self {
function: Default::default(),
}
}
}
///Bounds on the Tier 3 hold path — the one place where a verdict waits on a human. Both bounds exist so that a console that never answers, or an agent that fires holds faster than anyone can read them, degrades into a prompt deny with a legible reason rather than into an agent that appears hung.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Bounds on the Tier 3 hold path — the one place where a verdict waits on a human. Both bounds exist so that a console that never answers, or an agent that fires holds faster than anyone can read them, degrades into a prompt deny with a legible reason rather than into an agent that appears hung.",
/// "type": "object",
/// "properties": {
/// "host_timeout_s": {
/// "description": "How long the daemon holds a pending action before applying the artifact's on_timeout verdict, in seconds. Bounded below by the agent's own hook timeout in practice: a hold that outlives the hook is decided by the harness, not by us.",
/// "type": "integer"
/// },
/// "max_pending_holds": {
/// "description": "The hold buffer's explicit cap, default 16. A hold artifact firing beyond it is NOT buffered: the daemon prints an immediate deny whose reason names the full buffer, and records result: held_timeout. An unbounded buffer would turn a runaway agent into an unbounded queue of prompts nobody will ever answer.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigHold {
///How long the daemon holds a pending action before applying the artifact's on_timeout verdict, in seconds. Bounded below by the agent's own hook timeout in practice: a hold that outlives the hook is decided by the harness, not by us.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub host_timeout_s: ::std::option::Option<i64>,
///The hold buffer's explicit cap, default 16. A hold artifact firing beyond it is NOT buffered: the daemon prints an immediate deny whose reason names the full buffer, and records result: held_timeout. An unbounded buffer would turn a runaway agent into an unbounded queue of prompts nobody will ever answer.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub max_pending_holds: ::std::option::Option<i64>,
}
impl ::std::default::Default for PolicyBundleClientConfigHold {
fn default() -> Self {
Self {
host_timeout_s: Default::default(),
max_pending_holds: Default::default(),
}
}
}
///One optional block per lever (the Lever vocabulary in enums.schema.json). An ABSENT block means measure only — the lever's atoms still evaluate and still record, but the client performs no intervention. This is the safe default and the reason each block is optional rather than defaulted: a lever the organization never configured must never start rewriting an agent's traffic because a bundle grew a field. Every rewrite-capable block may carry visible_in_monitor (default false), the Monitor-visible rewrite opt-in: with it false a monitor-mode lever records what it WOULD have done and changes nothing, which is what makes Monitor mode honest.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "One optional block per lever (the Lever vocabulary in enums.schema.json). An ABSENT block means measure only — the lever's atoms still evaluate and still record, but the client performs no intervention. This is the safe default and the reason each block is optional rather than defaulted: a lever the organization never configured must never start rewriting an agent's traffic because a bundle grew a field. Every rewrite-capable block may carry visible_in_monitor (default false), the Monitor-visible rewrite opt-in: with it false a monitor-mode lever records what it WOULD have done and changes nothing, which is what makes Monitor mode honest.",
/// "type": "object",
/// "properties": {
/// "context_edit": {
/// "description": "Clears stale tool results out of the context window once it crosses a trigger. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "clear_at_least": {
/// "description": "Minimum tokens an edit must reclaim to be worth doing — below it the edit is skipped, because an edit that reclaims almost nothing still costs the whole prefix its cache.",
/// "type": "integer"
/// },
/// "exclude_tools": {
/// "description": "Tool names whose results are never cleared. Tool-name globs, matched the same way the atom language matches does_what.tools.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "keep": {
/// "description": "How many of the most recent tool results survive an edit.",
/// "type": "integer"
/// },
/// "trigger": {
/// "description": "Token count at which an edit is considered. Integer tokens, never a fraction of a window.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "effort_clamp": {
/// "description": "Caps the reasoning effort an agent may request, per agent category. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "by_agent_type": {
/// "description": "Map of agent category (the AgentCategory vocabulary — coding, analysis, ops, content, service) to the effort level that category is clamped to. A map rather than a list so one category can be retuned as a one-key delta, and an open one so an unknown category is carried rather than rejected.",
/// "type": "object",
/// "additionalProperties": {
/// "type": "string"
/// }
/// },
/// "quality_floor": {
/// "description": "The level the clamp may never go below, whatever by_agent_type says. Present so that tightening the clamp org-wide cannot silently drop an agent under the quality bar its owner signed up for.",
/// "type": "string"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false: monitor records the would-have and changes nothing.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "loop_stop": {
/// "description": "Stops an agent that is repeating itself. Keys on identical (tool, normalised input, result hash) — deliberately distinct from the run_le session shape, which keys on action shape and therefore treats Read a.py and Read b.py as the same. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "exempt_patterns": {
/// "description": "Calls matching these are never counted toward either bound — polling loops that are supposed to repeat.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "n_errors": {
/// "description": "Consecutive erroring calls before the loop is stopped. Default 3.",
/// "type": "integer"
/// },
/// "n_identical": {
/// "description": "Consecutive identical calls before the loop is stopped. Default 4.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's intervention while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "narrow_output": {
/// "description": "Filters a command's output down to what the agent actually needs, instead of feeding a whole log back into the context. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "allowlist": {
/// "description": "The only commands whose output is narrowed. An allowlist rather than a denylist: narrowing output the author did not anticipate is a correctness risk, so an unlisted command passes through untouched.",
/// "type": "array",
/// "items": {
/// "title": "NarrowOutputEntry",
/// "type": "object",
/// "properties": {
/// "command_prefix": {
/// "description": "Prefix of the normalised command string this entry applies to.",
/// "type": "string"
/// },
/// "filter": {
/// "description": "How the output is narrowed for that prefix.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "prefix_guard": {
/// "description": "Pins the stable prefix so a volatile block cannot keep invalidating the cache. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pin_ttl": {
/// "description": "How long a pin survives, as a duration string ('1h'), or null for no expiry. The one duration on this bundle that is not an integer of seconds, because it is passed through to the provider verbatim rather than computed on.",
/// "type": [
/// "string",
/// "null"
/// ]
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "steer": {
/// "description": "Injects the atom's steer_instruction into the agent's context instead of blocking it. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "dedupe_window_s": {
/// "description": "How long the same instruction is suppressed after being delivered, in seconds. Without it a steer atom that keeps matching repeats itself every call and becomes noise the model learns to ignore.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// },
/// "substitute": {
/// "description": "Replaces one call with a cheaper or safer equivalent. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pairs": {
/// "description": "The substitutions, applied in order.",
/// "type": "array",
/// "items": {
/// "title": "SubstitutePair",
/// "type": "object",
/// "properties": {
/// "from": {
/// "description": "What is matched.",
/// "type": "string"
/// },
/// "to": {
/// "description": "What replaces it.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLevers {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub context_edit: ::std::option::Option<PolicyBundleClientConfigLeversContextEdit>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub effort_clamp: ::std::option::Option<PolicyBundleClientConfigLeversEffortClamp>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub loop_stop: ::std::option::Option<PolicyBundleClientConfigLeversLoopStop>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub narrow_output: ::std::option::Option<PolicyBundleClientConfigLeversNarrowOutput>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub prefix_guard: ::std::option::Option<PolicyBundleClientConfigLeversPrefixGuard>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub steer: ::std::option::Option<PolicyBundleClientConfigLeversSteer>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub substitute: ::std::option::Option<PolicyBundleClientConfigLeversSubstitute>,
}
impl ::std::default::Default for PolicyBundleClientConfigLevers {
fn default() -> Self {
Self {
context_edit: Default::default(),
effort_clamp: Default::default(),
loop_stop: Default::default(),
narrow_output: Default::default(),
prefix_guard: Default::default(),
steer: Default::default(),
substitute: Default::default(),
}
}
}
///Clears stale tool results out of the context window once it crosses a trigger. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Clears stale tool results out of the context window once it crosses a trigger. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "clear_at_least": {
/// "description": "Minimum tokens an edit must reclaim to be worth doing — below it the edit is skipped, because an edit that reclaims almost nothing still costs the whole prefix its cache.",
/// "type": "integer"
/// },
/// "exclude_tools": {
/// "description": "Tool names whose results are never cleared. Tool-name globs, matched the same way the atom language matches does_what.tools.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "keep": {
/// "description": "How many of the most recent tool results survive an edit.",
/// "type": "integer"
/// },
/// "trigger": {
/// "description": "Token count at which an edit is considered. Integer tokens, never a fraction of a window.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversContextEdit {
///Minimum tokens an edit must reclaim to be worth doing — below it the edit is skipped, because an edit that reclaims almost nothing still costs the whole prefix its cache.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub clear_at_least: ::std::option::Option<i64>,
///Tool names whose results are never cleared. Tool-name globs, matched the same way the atom language matches does_what.tools.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub exclude_tools: ::std::vec::Vec<::std::string::String>,
///How many of the most recent tool results survive an edit.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub keep: ::std::option::Option<i64>,
///Token count at which an edit is considered. Integer tokens, never a fraction of a window.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub trigger: ::std::option::Option<i64>,
///Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversContextEdit {
fn default() -> Self {
Self {
clear_at_least: Default::default(),
exclude_tools: Default::default(),
keep: Default::default(),
trigger: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///Caps the reasoning effort an agent may request, per agent category. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Caps the reasoning effort an agent may request, per agent category. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "by_agent_type": {
/// "description": "Map of agent category (the AgentCategory vocabulary — coding, analysis, ops, content, service) to the effort level that category is clamped to. A map rather than a list so one category can be retuned as a one-key delta, and an open one so an unknown category is carried rather than rejected.",
/// "type": "object",
/// "additionalProperties": {
/// "type": "string"
/// }
/// },
/// "quality_floor": {
/// "description": "The level the clamp may never go below, whatever by_agent_type says. Present so that tightening the clamp org-wide cannot silently drop an agent under the quality bar its owner signed up for.",
/// "type": "string"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false: monitor records the would-have and changes nothing.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversEffortClamp {
///Map of agent category (the AgentCategory vocabulary — coding, analysis, ops, content, service) to the effort level that category is clamped to. A map rather than a list so one category can be retuned as a one-key delta, and an open one so an unknown category is carried rather than rejected.
#[serde(
default,
skip_serializing_if = ":: std :: collections :: HashMap::is_empty"
)]
pub by_agent_type: ::std::collections::HashMap<::std::string::String, ::std::string::String>,
///The level the clamp may never go below, whatever by_agent_type says. Present so that tightening the clamp org-wide cannot silently drop an agent under the quality bar its owner signed up for.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub quality_floor: ::std::option::Option<::std::string::String>,
///Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false: monitor records the would-have and changes nothing.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversEffortClamp {
fn default() -> Self {
Self {
by_agent_type: Default::default(),
quality_floor: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///Stops an agent that is repeating itself. Keys on identical (tool, normalised input, result hash) — deliberately distinct from the run_le session shape, which keys on action shape and therefore treats Read a.py and Read b.py as the same. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Stops an agent that is repeating itself. Keys on identical (tool, normalised input, result hash) — deliberately distinct from the run_le session shape, which keys on action shape and therefore treats Read a.py and Read b.py as the same. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "exempt_patterns": {
/// "description": "Calls matching these are never counted toward either bound — polling loops that are supposed to repeat.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "n_errors": {
/// "description": "Consecutive erroring calls before the loop is stopped. Default 3.",
/// "type": "integer"
/// },
/// "n_identical": {
/// "description": "Consecutive identical calls before the loop is stopped. Default 4.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's intervention while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversLoopStop {
///Calls matching these are never counted toward either bound — polling loops that are supposed to repeat.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub exempt_patterns: ::std::vec::Vec<::std::string::String>,
///Consecutive erroring calls before the loop is stopped. Default 3.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub n_errors: ::std::option::Option<i64>,
///Consecutive identical calls before the loop is stopped. Default 4.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub n_identical: ::std::option::Option<i64>,
///Opt in to performing this lever's intervention while the atom is in monitor mode. Default false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversLoopStop {
fn default() -> Self {
Self {
exempt_patterns: Default::default(),
n_errors: Default::default(),
n_identical: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///Filters a command's output down to what the agent actually needs, instead of feeding a whole log back into the context. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Filters a command's output down to what the agent actually needs, instead of feeding a whole log back into the context. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "allowlist": {
/// "description": "The only commands whose output is narrowed. An allowlist rather than a denylist: narrowing output the author did not anticipate is a correctness risk, so an unlisted command passes through untouched.",
/// "type": "array",
/// "items": {
/// "title": "NarrowOutputEntry",
/// "type": "object",
/// "properties": {
/// "command_prefix": {
/// "description": "Prefix of the normalised command string this entry applies to.",
/// "type": "string"
/// },
/// "filter": {
/// "description": "How the output is narrowed for that prefix.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversNarrowOutput {
///The only commands whose output is narrowed. An allowlist rather than a denylist: narrowing output the author did not anticipate is a correctness risk, so an unlisted command passes through untouched.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub allowlist: ::std::vec::Vec<NarrowOutputEntry>,
///Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversNarrowOutput {
fn default() -> Self {
Self {
allowlist: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///Pins the stable prefix so a volatile block cannot keep invalidating the cache. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Pins the stable prefix so a volatile block cannot keep invalidating the cache. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pin_ttl": {
/// "description": "How long a pin survives, as a duration string ('1h'), or null for no expiry. The one duration on this bundle that is not an integer of seconds, because it is passed through to the provider verbatim rather than computed on.",
/// "type": [
/// "string",
/// "null"
/// ]
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversPrefixGuard {
///How long a pin survives, as a duration string ('1h'), or null for no expiry. The one duration on this bundle that is not an integer of seconds, because it is passed through to the provider verbatim rather than computed on.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub pin_ttl: ::std::option::Option<::std::string::String>,
///Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversPrefixGuard {
fn default() -> Self {
Self {
pin_ttl: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///Injects the atom's steer_instruction into the agent's context instead of blocking it. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Injects the atom's steer_instruction into the agent's context instead of blocking it. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "dedupe_window_s": {
/// "description": "How long the same instruction is suppressed after being delivered, in seconds. Without it a steer atom that keeps matching repeats itself every call and becomes noise the model learns to ignore.",
/// "type": "integer"
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversSteer {
///How long the same instruction is suppressed after being delivered, in seconds. Without it a steer atom that keeps matching repeats itself every call and becomes noise the model learns to ignore.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub dedupe_window_s: ::std::option::Option<i64>,
///Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversSteer {
fn default() -> Self {
Self {
dedupe_window_s: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///Replaces one call with a cheaper or safer equivalent. Measure only when absent.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Replaces one call with a cheaper or safer equivalent. Measure only when absent.",
/// "type": "object",
/// "properties": {
/// "pairs": {
/// "description": "The substitutions, applied in order.",
/// "type": "array",
/// "items": {
/// "title": "SubstitutePair",
/// "type": "object",
/// "properties": {
/// "from": {
/// "description": "What is matched.",
/// "type": "string"
/// },
/// "to": {
/// "description": "What replaces it.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "visible_in_monitor": {
/// "description": "Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.",
/// "type": "boolean"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientConfigLeversSubstitute {
///The substitutions, applied in order.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub pairs: ::std::vec::Vec<SubstitutePair>,
///Opt in to performing this lever's rewrite while the atom is in monitor mode. Default false.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub visible_in_monitor: ::std::option::Option<bool>,
}
impl ::std::default::Default for PolicyBundleClientConfigLeversSubstitute {
fn default() -> Self {
Self {
pairs: Default::default(),
visible_in_monitor: Default::default(),
}
}
}
///The minimum client version this bundle is safe to serve to (D35). The bundle root is additionalProperties:false, so a client predating a section rejects the WHOLE document (OL-1212), fails static on its previous rules, and then never updates again — the per-rule tolerance in parse_bundle_tolerant does not help, because the root-level failure happens before it is ever reached. The platform therefore composes schema 2 only for installs at or above the floor and keeps serving schema 1 below it, and the client reports its own version on every poll so the platform can tell which. A client that reads this field and finds ITSELF below the floor keeps its resident bundle and reports the gap rather than downgrading silently. New in schema 2; same emission rule as install_id.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The minimum client version this bundle is safe to serve to (D35). The bundle root is additionalProperties:false, so a client predating a section rejects the WHOLE document (OL-1212), fails static on its previous rules, and then never updates again — the per-rule tolerance in parse_bundle_tolerant does not help, because the root-level failure happens before it is ever reached. The platform therefore composes schema 2 only for installs at or above the floor and keeps serving schema 1 below it, and the client reports its own version on every poll so the platform can tell which. A client that reads this field and finds ITSELF below the floor keeps its resident bundle and reports the gap rather than downgrading silently. New in schema 2; same emission rule as install_id.",
/// "type": "object",
/// "properties": {
/// "min_client_version": {
/// "description": "Semantic version string, e.g. '0.9.0'. Deliberately unconstrained: a pattern keyword here would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one malformed value, which is exactly the failure the floor exists to prevent.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleClientFloor {
///Semantic version string, e.g. '0.9.0'. Deliberately unconstrained: a pattern keyword here would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one malformed value, which is exactly the failure the floor exists to prevent.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub min_client_version: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for PolicyBundleClientFloor {
fn default() -> Self {
Self {
min_client_version: Default::default(),
}
}
}
///The effect-class feed the client's classifier resolves a tool call into (verb, target_class) tuples with (R13) — what lets a rule say 'delete from a data store' instead of naming every tool that can do it. Shipped on the bundle rather than compiled into the binary so a newly popular tool becomes classifiable without a client release. An action may carry several tuples, and an effect leaf matches if ANY tuple matches. New in schema 2; same emission rule as install_id.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The effect-class feed the client's classifier resolves a tool call into (verb, target_class) tuples with (R13) — what lets a rule say 'delete from a data store' instead of naming every tool that can do it. Shipped on the bundle rather than compiled into the binary so a newly popular tool becomes classifiable without a client release. An action may carry several tuples, and an effect leaf matches if ANY tuple matches. New in schema 2; same emission rule as install_id.",
/// "type": "object",
/// "properties": {
/// "entries": {
/// "description": "The feed's entries, one per classifiable tool key.",
/// "type": "array",
/// "items": {
/// "title": "EffectClassEntry",
/// "type": "object",
/// "properties": {
/// "effects": {
/// "description": "The effect tuples a matching call produces.",
/// "type": "array",
/// "items": {
/// "title": "EffectTuple",
/// "type": "object",
/// "properties": {
/// "attrs": {
/// "description": "Attributes attached to this tuple, readable from a leaf as effect.attrs.<name> (D-16). The first is is_production, resolved from the env_selectors fact — a starter-library entry already reads effect.attrs.is_production, and without this the entry is unmatchable as written. Open by construction: an attribute the client does not know makes a leaf naming it inconclusive, never false.",
/// "type": "object",
/// "additionalProperties": true
/// },
/// "target_class": {
/// "description": "What it does it to.",
/// "$ref": "#/$defs/TargetClass"
/// },
/// "verb": {
/// "description": "What the action does.",
/// "$ref": "#/$defs/EffectVerb"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "id": {
/// "description": "Stable identifier for this entry.",
/// "type": "string"
/// },
/// "modified": {
/// "description": "Feed version or RFC 3339 timestamp of the last change to the entry.",
/// "type": "string"
/// },
/// "related": {
/// "description": "Ids of entries a reviewer should look at alongside this one.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "selectors": {
/// "description": "Attribute leaves narrowing WHICH calls of tool_key this entry classifies — the same leaf shape a Tier 1 predicate tree uses, so one classifier reads both. An entry with no selectors classifies every call of the tool.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/t1_leaf"
/// }
/// },
/// "since": {
/// "description": "Feed version or RFC 3339 timestamp at which the entry first appeared.",
/// "type": "string"
/// },
/// "status": {
/// "description": "Lifecycle of the entry in the feed. Open: an unknown status leaves the entry usable, because dropping a classification on a word the client did not recognise would silently widen what a rule fails to match.",
/// "type": "string"
/// },
/// "tool_key": {
/// "description": "The tool this entry classifies, as the evaluator sees it — 'Bash', or 'mcp__<server>__<tool>' for MCP.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// }
/// },
/// "feed_version": {
/// "description": "Version of the feed as published. A string, not a number: '1.2' as a JSON number would be a float, and this bundle carries no floats anywhere.",
/// "type": "string"
/// },
/// "required_engine_version": {
/// "description": "The minimum classifier engine version that can read this feed correctly. A client below it keeps its BUILT-IN feed rather than mis-reading this one — a classifier that half-understands a feed produces wrong effect tuples, which is worse than an old but coherent one.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleEffectClasses {
///The feed's entries, one per classifiable tool key.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub entries: ::std::vec::Vec<EffectClassEntry>,
///Version of the feed as published. A string, not a number: '1.2' as a JSON number would be a float, and this bundle carries no floats anywhere.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub feed_version: ::std::option::Option<::std::string::String>,
///The minimum classifier engine version that can read this feed correctly. A client below it keeps its BUILT-IN feed rather than mis-reading this one — a classifier that half-understands a feed produces wrong effect tuples, which is worse than an old but coherent one.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub required_engine_version: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for PolicyBundleEffectClasses {
fn default() -> Self {
Self {
entries: Default::default(),
feed_version: Default::default(),
required_engine_version: Default::default(),
}
}
}
///The revisions this bundle was materialised from — the composition's inputs, never its content. Equal inputs mean byte-identical output, which is what lets built_at stay memoised at the last real content change instead of being restamped on every poll, and what lets a replay reconstruct a composition from four integers. New in schema 2; the platform MUST NOT emit it to a fleet that still runs clients predating it (see install_id for why that would be fatal rather than merely ignored).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The revisions this bundle was materialised from — the composition's inputs, never its content. Equal inputs mean byte-identical output, which is what lets built_at stay memoised at the last real content change instead of being restamped on every poll, and what lets a replay reconstruct a composition from four integers. New in schema 2; the platform MUST NOT emit it to a fleet that still runs clients predating it (see install_id for why that would be fatal rather than merely ignored).",
/// "type": "object",
/// "properties": {
/// "effect_class_rev": {
/// "description": "Revision of the effect-class feed carried in effect_classes below — the classifier's input, versioned separately from policy because a feed refresh changes what a rule matches without any rule having been edited.",
/// "type": "integer"
/// },
/// "fact_revs": {
/// "description": "Per-fact revision, keyed by fact_id. A map rather than a list so refreshing one fact is a one-key delta; keys carry the FactId vocabulary, which is open, so an unrecognised key is carried rather than rejected.",
/// "type": "object",
/// "additionalProperties": {
/// "type": "integer"
/// }
/// },
/// "policy_rev": {
/// "description": "Revision of the ratified policy set composed into this bundle. Monotonic per organization.",
/// "type": "integer"
/// },
/// "zone_rev": {
/// "description": "Revision of the autonomy zone tree at composition time. Re-parenting a unit moves this without touching policy_rev, and it is the input that explains a bundle change no policy edit accounts for.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleInputs {
///Revision of the effect-class feed carried in effect_classes below — the classifier's input, versioned separately from policy because a feed refresh changes what a rule matches without any rule having been edited.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub effect_class_rev: ::std::option::Option<i64>,
///Per-fact revision, keyed by fact_id. A map rather than a list so refreshing one fact is a one-key delta; keys carry the FactId vocabulary, which is open, so an unrecognised key is carried rather than rejected.
#[serde(
default,
skip_serializing_if = ":: std :: collections :: HashMap::is_empty"
)]
pub fact_revs: ::std::collections::HashMap<::std::string::String, i64>,
///Revision of the ratified policy set composed into this bundle. Monotonic per organization.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub policy_rev: ::std::option::Option<i64>,
///Revision of the autonomy zone tree at composition time. Re-parenting a unit moves this without touching policy_rev, and it is the input that explains a bundle change no policy edit accounts for.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub zone_rev: ::std::option::Option<i64>,
}
impl ::std::default::Default for PolicyBundleInputs {
fn default() -> Self {
Self {
effect_class_rev: Default::default(),
fact_revs: Default::default(),
policy_rev: Default::default(),
zone_rev: Default::default(),
}
}
}
///What this install resolved to at composition time — the context a developer needs to read a verdict, and the context a support conversation starts from. Informational: nothing here is evaluated. New in schema 2; same emission rule as install_id.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "What this install resolved to at composition time — the context a developer needs to read a verdict, and the context a support conversation starts from. Informational: nothing here is evaluated. New in schema 2; same emission rule as install_id.",
/// "type": "object",
/// "properties": {
/// "agent_type": {
/// "description": "The CATEGORY of work this agent does — coding, analysis, ops, content, service. The wire name is agent_type because that is the frozen contract name, but the type it carries is AgentCategory: in this repository AgentType already means the agent PLATFORM (claude-code, cursor, ...), which is a different axis entirely. Read either in full where both could be meant.",
/// "$ref": "#/$defs/AgentCategory"
/// },
/// "effective_zone": {
/// "title": "EffectiveZone",
/// "description": "The autonomy zone this install actually landed in, and how it got there.",
/// "type": "object",
/// "properties": {
/// "node_id": {
/// "description": "Identifier of the resolved zone node.",
/// "type": "string"
/// },
/// "path": {
/// "description": "Root-to-node path, so 'which zone am I in?' is answerable from the bundle alone.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// },
/// "resolved_from": {
/// "description": "Whether the assignment was derived from the directory (auto) or set by a person (manual). An open string rather than a closed set, per R14.",
/// "type": "string",
/// "x-known-values": [
/// "auto",
/// "manual"
/// ]
/// }
/// },
/// "additionalProperties": true
/// },
/// "environment": {
/// "description": "The environment this install was classified into. Defaults to production platform-side, because the safe reading of an unclassified host is the one that assumes the blast radius is real.",
/// "$ref": "#/$defs/Environment"
/// },
/// "omitted_kinds": {
/// "description": "Artifact kinds the platform DELIBERATELY left out of this bundle, because this install's reported version cannot evaluate them. The difference between 'there is no such rule' and 'there is one and you are not running it' — without this, a client below a capability floor looks compliant while silently enforcing less than the organization authored.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/ArtifactKind"
/// }
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyBundleMeta {
///The CATEGORY of work this agent does — coding, analysis, ops, content, service. The wire name is agent_type because that is the frozen contract name, but the type it carries is AgentCategory: in this repository AgentType already means the agent PLATFORM (claude-code, cursor, ...), which is a different axis entirely. Read either in full where both could be meant.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub agent_type: ::std::option::Option<AgentCategory>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub effective_zone: ::std::option::Option<EffectiveZone>,
///The environment this install was classified into. Defaults to production platform-side, because the safe reading of an unclassified host is the one that assumes the blast radius is real.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub environment: ::std::option::Option<Environment>,
///Artifact kinds the platform DELIBERATELY left out of this bundle, because this install's reported version cannot evaluate them. The difference between 'there is no such rule' and 'there is one and you are not running it' — without this, a client below a capability floor looks compliant while silently enforcing less than the organization authored.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub omitted_kinds: ::std::vec::Vec<ArtifactKind>,
}
impl ::std::default::Default for PolicyBundleMeta {
fn default() -> Self {
Self {
agent_type: Default::default(),
effective_zone: Default::default(),
environment: Default::default(),
omitted_kinds: Default::default(),
}
}
}
///How a policy acts. Policy-level; the bundle only ever carries 'monitor' or 'enforce', because a disabled policy is not composed into it at all. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "How a policy acts. Policy-level; the bundle only ever carries 'monitor' or 'enforce', because a disabled policy is not composed into it at all. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "disabled",
/// "monitor",
/// "enforce"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct PolicyMode(pub ::std::string::String);
impl ::std::ops::Deref for PolicyMode {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PolicyMode> for ::std::string::String {
fn from(value: PolicyMode) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for PolicyMode {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for PolicyMode {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for PolicyMode {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///One authored rule, on either plane. A kind=command rule is evaluated against the normalized command string extracted from a pre_tool_use envelope. A kind=request rule targets an outbound model request at the boundary and is held, not evaluated, in v1. The allOf below is the per-kind/per-action gate: the platform enforces it at authoring time (422) and the client validates every rule against it individually at bundle load, skipping the ones that fail — one bad rule must never cost the fleet its denies.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "PolicyRule",
/// "description": "One authored rule, on either plane. A kind=command rule is evaluated against the normalized command string extracted from a pre_tool_use envelope. A kind=request rule targets an outbound model request at the boundary and is held, not evaluated, in v1. The allOf below is the per-kind/per-action gate: the platform enforces it at authoring time (422) and the client validates every rule against it individually at bundle load, skipping the ones that fail — one bad rule must never cost the fleet its denies.",
/// "type": "object",
/// "required": [
/// "action",
/// "kind",
/// "mode",
/// "reason",
/// "rule_id",
/// "severity"
/// ],
/// "properties": {
/// "action": {
/// "description": "What a match does. Authorable actions are 'deny' (the only one on kind=command) and 'prefix_reorder', 'history_trim', 'prompt_edit' (kind=request). Which action is legal for which kind is owned by the gate below, not by this list. An open string for the same forward-compatibility reason as kind.",
/// "type": "string"
/// },
/// "conditions": {
/// "description": "Which agents the rule applies to, decided locally by the client against the client_config.agent_context THIS install received — the network is not on the evaluation path. Absent (or empty) means unconditional: the rule applies on every agent, exactly as before this field existed. When present, EVERY condition must hold (AND semantics), and a rule whose context never arrived matches nothing — absent context is not 'unknown'. v1 is the command plane only: forbidden on kind=request by the gate below, and the only vocabulary is field 'agent.function' with op 'in'. The field/op enums are the general shape, so widening either later is additive; a client that predates a widening drops that one rule at load (unrecognized_field) and keeps the bundle. Values are the closed AgentFunction enum, so a value the client does not know fails that one rule at deserialization, never the whole document. 'unknown' is an ordinary value, not a wildcard.",
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "field",
/// "op",
/// "value"
/// ],
/// "properties": {
/// "field": {
/// "description": "The agent-context attribute the condition reads. v1 knows exactly one: 'agent.function', read from client_config.agent_context.function.",
/// "type": "string",
/// "enum": [
/// "agent.function"
/// ]
/// },
/// "op": {
/// "description": "The comparison. v1 knows exactly one: 'in' — the attribute's value is a member of `value`. Several conditions on the same field AND together, so two 'in' sets intersect.",
/// "type": "string",
/// "enum": [
/// "in"
/// ]
/// },
/// "value": {
/// "description": "The set the attribute must belong to. At least one member — an empty set would match nothing while looking like a scoped rule, and the platform rejects it at authoring (422). Compared by enum equality on the client.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/AgentFunction"
/// },
/// "minItems": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// },
/// "kind": {
/// "description": "Which plane the rule acts on. Two kinds are authorable: 'command' (a shell command intercepted at the pre_tool_use hook) and 'request' (an outbound model request intercepted at the boundary). Deliberately an open string rather than a closed enum: the client MUST skip a rule whose kind it does not recognize and keep the rest of the bundle active, so that a v1 client tolerates a v1.1 bundle. A closed enum would fail deserialization of the whole document instead.",
/// "type": "string"
/// },
/// "match_pattern": {
/// "description": "Required for kind=command and forbidden for kind=request — see the gate below; it is optional in the base only so that a request rule does not fail deserialization on a client that predates the gate. Fully-anchored, case-sensitive glob over the entire normalized command string. Exactly two metacharacters: '*' (any sequence including empty, crossing '/' and every other character — this is not path-aware globbing) and '?' (exactly one character). No character classes, no escapes, no alternation, no regex. Anchoring surprises authors: 'rm -rf /*' does not match 'sudo rm -rf /tmp'; write '*rm -rf*' to catch a command anywhere in the string. The platform normalizes and validates this at authoring time and rejects empty, over-1024-character, control-character-bearing, and bare-'*' patterns with 422.",
/// "type": "string"
/// },
/// "mode": {
/// "description": "Staged rollout control. 'observe' records a shadow verdict and allows the action; 'enforce' denies it. Most restrictive wins across matching rules. Overridden to observe for every rule when enforcement_enabled is false.",
/// "type": "string",
/// "enum": [
/// "observe",
/// "enforce"
/// ]
/// },
/// "params": {
/// "description": "How a kind=request rule transforms the request. Forbidden on kind=command. Exactly which keys are required and which are rejected is per-action, in the gate below.",
/// "type": "object",
/// "properties": {
/// "keep_messages": {
/// "description": "How many of the most recent messages history_trim retains. Required by history_trim, rejected everywhere else.",
/// "type": "integer"
/// },
/// "marker": {
/// "description": "The literal marker prompt_edit rewrites around. Deliberately unconstrained here: a length or pattern keyword would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one over-long value. Length is bounded platform-side at authoring.",
/// "type": "string"
/// },
/// "max_system_tokens": {
/// "description": "Token ceiling prompt_edit trims the system block to. Alternative to marker — exactly one of the two is required.",
/// "type": "integer"
/// },
/// "mechanism": {
/// "description": "Which caching intervention a prefix_reorder rule means. The detector that authors these rules fires on two different causes needing two different interventions, and the action alone cannot tell them apart: 'insert_breakpoints' — nothing is being cached at all, so cache_control breakpoints must be INJECTED; 'reorder_blocks' — breakpoints exist but a volatile block sits early in the prefix and must be MOVED after the stable ones. Read by prefix_reorder only. Deliberately an OPEN string rather than an enum, for the same reason as kind and action: an out-of-vocabulary value must fail one rule, not deserialization of the whole bundle. An enum here would be a known field with an unknown value, which the unknown-FIELD tolerance does not cover. Absent means the rule names no mechanism — a client that cannot infer one skips it rather than guessing.",
/// "examples": [
/// "insert_breakpoints",
/// "reorder_blocks"
/// ],
/// "type": "string"
/// }
/// },
/// "additionalProperties": false
/// },
/// "provenance": {
/// "description": "Where this schema-1 rule came from in the schema-2 authoring model, when the platform composed it from a ratified atom rather than from a hand-written rule. Purely informational on the client: it is stamped onto the record (olatomid, olpolicyid, oldimension, ollayer, olmode) so a verdict can be traced back to the policy that produced it, and it never changes what the rule matches or what it does. Absent on a rule with no atom behind it. Tolerant like every schema-2 object, so a newer platform can add a provenance key without failing an older client — the enclosing rule object stays additionalProperties:false, so an unknown key at RULE level still skips that one rule (never the document), which is the tolerance parse_bundle_tolerant provides.",
/// "type": "object",
/// "properties": {
/// "atom_id": {
/// "description": "The ratified intent atom this rule was compiled from. Recorded on the verdict as olatomid.",
/// "type": "string"
/// },
/// "dimension": {
/// "description": "Which dimension the owning policy belongs to. Recorded as oldimension.",
/// "$ref": "#/$defs/Dimension"
/// },
/// "mode": {
/// "description": "The composed mode of the owning policy (monitor or enforce; a disabled policy is never composed). Distinct from the rule's own `mode` field, which is the schema-1 observe/enforce control the evaluator actually reads — this one is recorded as olmode and describes the policy, not this rule's rollout stage.",
/// "$ref": "#/$defs/PolicyMode"
/// },
/// "policy_id": {
/// "description": "The policy owning that atom. Recorded as olpolicyid; the public identifier the console shows is policy_public_id on the artifact plane.",
/// "type": "string"
/// },
/// "zone_layer": {
/// "description": "Identifier of the autonomy-zone unit this rule was inherited from — the layer that contributed it, not the agent's own zone. Recorded as ollayer.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
/// },
/// "reason": {
/// "description": "Plain-language explanation shown to the developer verbatim when the rule blocks an action. A deny the developer cannot understand is a broken feature.",
/// "type": "string"
/// },
/// "rule_id": {
/// "description": "Stable public identifier, e.g. 'OL-CMD-001'. Unique within the organization. Reported on the verdict as olpolicyruleid, and the tiebreak key: the lexicographically first rule within the deciding set is the one reported.",
/// "type": "string"
/// },
/// "rule_version": {
/// "description": "Required for kind=request, absent on kind=command — the middle term of the D-04 replay tuple, so a would-have report can be tied to the exact rule text that produced it. Platform-managed: set on create and incremented on every edit, never authored by hand.",
/// "type": "integer"
/// },
/// "select": {
/// "description": "Which requests a kind=request rule applies to; an absent select means every request the boundary sees. Forbidden on kind=command. Each key is narrowed further per action by the gate below — a key that an action does not read is rejected rather than silently ignored.",
/// "type": "object",
/// "properties": {
/// "exclude_layers": {
/// "description": "Cache layers this rule must leave untouched. Read by prefix_reorder only.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/ChurnLayer"
/// }
/// },
/// "min_messages": {
/// "description": "Apply only once the in-context history has at least this many messages. Read by history_trim only.",
/// "type": "integer"
/// },
/// "model_in": {
/// "description": "Apply only to requests whose model identifier is in this list. Matched verbatim against the model string on the wire; no globbing.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": false
/// },
/// "severity": {
/// "description": "Author-assigned severity, surfaced on the verdict returned to the agent hook.",
/// "type": "string",
/// "enum": [
/// "low",
/// "medium",
/// "high",
/// "critical"
/// ]
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PolicyRule {
///What a match does. Authorable actions are 'deny' (the only one on kind=command) and 'prefix_reorder', 'history_trim', 'prompt_edit' (kind=request). Which action is legal for which kind is owned by the gate below, not by this list. An open string for the same forward-compatibility reason as kind.
pub action: ::std::string::String,
///Which agents the rule applies to, decided locally by the client against the client_config.agent_context THIS install received — the network is not on the evaluation path. Absent (or empty) means unconditional: the rule applies on every agent, exactly as before this field existed. When present, EVERY condition must hold (AND semantics), and a rule whose context never arrived matches nothing — absent context is not 'unknown'. v1 is the command plane only: forbidden on kind=request by the gate below, and the only vocabulary is field 'agent.function' with op 'in'. The field/op enums are the general shape, so widening either later is additive; a client that predates a widening drops that one rule at load (unrecognized_field) and keeps the bundle. Values are the closed AgentFunction enum, so a value the client does not know fails that one rule at deserialization, never the whole document. 'unknown' is an ordinary value, not a wildcard.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub conditions: ::std::vec::Vec<PolicyRuleConditionsItem>,
///Which plane the rule acts on. Two kinds are authorable: 'command' (a shell command intercepted at the pre_tool_use hook) and 'request' (an outbound model request intercepted at the boundary). Deliberately an open string rather than a closed enum: the client MUST skip a rule whose kind it does not recognize and keep the rest of the bundle active, so that a v1 client tolerates a v1.1 bundle. A closed enum would fail deserialization of the whole document instead.
pub kind: ::std::string::String,
///Required for kind=command and forbidden for kind=request — see the gate below; it is optional in the base only so that a request rule does not fail deserialization on a client that predates the gate. Fully-anchored, case-sensitive glob over the entire normalized command string. Exactly two metacharacters: '*' (any sequence including empty, crossing '/' and every other character — this is not path-aware globbing) and '?' (exactly one character). No character classes, no escapes, no alternation, no regex. Anchoring surprises authors: 'rm -rf /*' does not match 'sudo rm -rf /tmp'; write '*rm -rf*' to catch a command anywhere in the string. The platform normalizes and validates this at authoring time and rejects empty, over-1024-character, control-character-bearing, and bare-'*' patterns with 422.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub match_pattern: ::std::option::Option<::std::string::String>,
///Staged rollout control. 'observe' records a shadow verdict and allows the action; 'enforce' denies it. Most restrictive wins across matching rules. Overridden to observe for every rule when enforcement_enabled is false.
pub mode: PolicyRuleMode,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub params: ::std::option::Option<PolicyRuleParams>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub provenance: ::std::option::Option<PolicyRuleProvenance>,
///Plain-language explanation shown to the developer verbatim when the rule blocks an action. A deny the developer cannot understand is a broken feature.
pub reason: ::std::string::String,
///Stable public identifier, e.g. 'OL-CMD-001'. Unique within the organization. Reported on the verdict as olpolicyruleid, and the tiebreak key: the lexicographically first rule within the deciding set is the one reported.
pub rule_id: ::std::string::String,
///Required for kind=request, absent on kind=command — the middle term of the D-04 replay tuple, so a would-have report can be tied to the exact rule text that produced it. Platform-managed: set on create and incremented on every edit, never authored by hand.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub rule_version: ::std::option::Option<i64>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub select: ::std::option::Option<PolicyRuleSelect>,
///Author-assigned severity, surfaced on the verdict returned to the agent hook.
pub severity: PolicyRuleSeverity,
}
///`PolicyRuleConditionsItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "field",
/// "op",
/// "value"
/// ],
/// "properties": {
/// "field": {
/// "description": "The agent-context attribute the condition reads. v1 knows exactly one: 'agent.function', read from client_config.agent_context.function.",
/// "type": "string",
/// "enum": [
/// "agent.function"
/// ]
/// },
/// "op": {
/// "description": "The comparison. v1 knows exactly one: 'in' — the attribute's value is a member of `value`. Several conditions on the same field AND together, so two 'in' sets intersect.",
/// "type": "string",
/// "enum": [
/// "in"
/// ]
/// },
/// "value": {
/// "description": "The set the attribute must belong to. At least one member — an empty set would match nothing while looking like a scoped rule, and the platform rejects it at authoring (422). Compared by enum equality on the client.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/AgentFunction"
/// },
/// "minItems": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PolicyRuleConditionsItem {
///The agent-context attribute the condition reads. v1 knows exactly one: 'agent.function', read from client_config.agent_context.function.
pub field: PolicyRuleConditionsItemField,
///The comparison. v1 knows exactly one: 'in' — the attribute's value is a member of `value`. Several conditions on the same field AND together, so two 'in' sets intersect.
pub op: PolicyRuleConditionsItemOp,
///The set the attribute must belong to. At least one member — an empty set would match nothing while looking like a scoped rule, and the platform rejects it at authoring (422). Compared by enum equality on the client.
pub value: ::std::vec::Vec<AgentFunction>,
}
///The agent-context attribute the condition reads. v1 knows exactly one: 'agent.function', read from client_config.agent_context.function.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The agent-context attribute the condition reads. v1 knows exactly one: 'agent.function', read from client_config.agent_context.function.",
/// "type": "string",
/// "enum": [
/// "agent.function"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyRuleConditionsItemField {
#[serde(rename = "agent.function")]
AgentFunction,
}
impl ::std::fmt::Display for PolicyRuleConditionsItemField {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::AgentFunction => f.write_str("agent.function"),
}
}
}
impl ::std::str::FromStr for PolicyRuleConditionsItemField {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"agent.function" => Ok(Self::AgentFunction),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyRuleConditionsItemField {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyRuleConditionsItemField {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyRuleConditionsItemField {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///The comparison. v1 knows exactly one: 'in' — the attribute's value is a member of `value`. Several conditions on the same field AND together, so two 'in' sets intersect.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The comparison. v1 knows exactly one: 'in' — the attribute's value is a member of `value`. Several conditions on the same field AND together, so two 'in' sets intersect.",
/// "type": "string",
/// "enum": [
/// "in"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyRuleConditionsItemOp {
#[serde(rename = "in")]
In,
}
impl ::std::fmt::Display for PolicyRuleConditionsItemOp {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::In => f.write_str("in"),
}
}
}
impl ::std::str::FromStr for PolicyRuleConditionsItemOp {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"in" => Ok(Self::In),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyRuleConditionsItemOp {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyRuleConditionsItemOp {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyRuleConditionsItemOp {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Staged rollout control. 'observe' records a shadow verdict and allows the action; 'enforce' denies it. Most restrictive wins across matching rules. Overridden to observe for every rule when enforcement_enabled is false.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Staged rollout control. 'observe' records a shadow verdict and allows the action; 'enforce' denies it. Most restrictive wins across matching rules. Overridden to observe for every rule when enforcement_enabled is false.",
/// "type": "string",
/// "enum": [
/// "observe",
/// "enforce"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyRuleMode {
#[serde(rename = "observe")]
Observe,
#[serde(rename = "enforce")]
Enforce,
}
impl ::std::fmt::Display for PolicyRuleMode {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Observe => f.write_str("observe"),
Self::Enforce => f.write_str("enforce"),
}
}
}
impl ::std::str::FromStr for PolicyRuleMode {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"observe" => Ok(Self::Observe),
"enforce" => Ok(Self::Enforce),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyRuleMode {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyRuleMode {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyRuleMode {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///How a kind=request rule transforms the request. Forbidden on kind=command. Exactly which keys are required and which are rejected is per-action, in the gate below.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "How a kind=request rule transforms the request. Forbidden on kind=command. Exactly which keys are required and which are rejected is per-action, in the gate below.",
/// "type": "object",
/// "properties": {
/// "keep_messages": {
/// "description": "How many of the most recent messages history_trim retains. Required by history_trim, rejected everywhere else.",
/// "type": "integer"
/// },
/// "marker": {
/// "description": "The literal marker prompt_edit rewrites around. Deliberately unconstrained here: a length or pattern keyword would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one over-long value. Length is bounded platform-side at authoring.",
/// "type": "string"
/// },
/// "max_system_tokens": {
/// "description": "Token ceiling prompt_edit trims the system block to. Alternative to marker — exactly one of the two is required.",
/// "type": "integer"
/// },
/// "mechanism": {
/// "description": "Which caching intervention a prefix_reorder rule means. The detector that authors these rules fires on two different causes needing two different interventions, and the action alone cannot tell them apart: 'insert_breakpoints' — nothing is being cached at all, so cache_control breakpoints must be INJECTED; 'reorder_blocks' — breakpoints exist but a volatile block sits early in the prefix and must be MOVED after the stable ones. Read by prefix_reorder only. Deliberately an OPEN string rather than an enum, for the same reason as kind and action: an out-of-vocabulary value must fail one rule, not deserialization of the whole bundle. An enum here would be a known field with an unknown value, which the unknown-FIELD tolerance does not cover. Absent means the rule names no mechanism — a client that cannot infer one skips it rather than guessing.",
/// "examples": [
/// "insert_breakpoints",
/// "reorder_blocks"
/// ],
/// "type": "string"
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PolicyRuleParams {
///How many of the most recent messages history_trim retains. Required by history_trim, rejected everywhere else.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub keep_messages: ::std::option::Option<i64>,
///The literal marker prompt_edit rewrites around. Deliberately unconstrained here: a length or pattern keyword would make the generated Rust type a constrained newtype whose deserializer fails the WHOLE bundle on one over-long value. Length is bounded platform-side at authoring.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub marker: ::std::option::Option<::std::string::String>,
///Token ceiling prompt_edit trims the system block to. Alternative to marker — exactly one of the two is required.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub max_system_tokens: ::std::option::Option<i64>,
///Which caching intervention a prefix_reorder rule means. The detector that authors these rules fires on two different causes needing two different interventions, and the action alone cannot tell them apart: 'insert_breakpoints' — nothing is being cached at all, so cache_control breakpoints must be INJECTED; 'reorder_blocks' — breakpoints exist but a volatile block sits early in the prefix and must be MOVED after the stable ones. Read by prefix_reorder only. Deliberately an OPEN string rather than an enum, for the same reason as kind and action: an out-of-vocabulary value must fail one rule, not deserialization of the whole bundle. An enum here would be a known field with an unknown value, which the unknown-FIELD tolerance does not cover. Absent means the rule names no mechanism — a client that cannot infer one skips it rather than guessing.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub mechanism: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for PolicyRuleParams {
fn default() -> Self {
Self {
keep_messages: Default::default(),
marker: Default::default(),
max_system_tokens: Default::default(),
mechanism: Default::default(),
}
}
}
///Where this schema-1 rule came from in the schema-2 authoring model, when the platform composed it from a ratified atom rather than from a hand-written rule. Purely informational on the client: it is stamped onto the record (olatomid, olpolicyid, oldimension, ollayer, olmode) so a verdict can be traced back to the policy that produced it, and it never changes what the rule matches or what it does. Absent on a rule with no atom behind it. Tolerant like every schema-2 object, so a newer platform can add a provenance key without failing an older client — the enclosing rule object stays additionalProperties:false, so an unknown key at RULE level still skips that one rule (never the document), which is the tolerance parse_bundle_tolerant provides.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Where this schema-1 rule came from in the schema-2 authoring model, when the platform composed it from a ratified atom rather than from a hand-written rule. Purely informational on the client: it is stamped onto the record (olatomid, olpolicyid, oldimension, ollayer, olmode) so a verdict can be traced back to the policy that produced it, and it never changes what the rule matches or what it does. Absent on a rule with no atom behind it. Tolerant like every schema-2 object, so a newer platform can add a provenance key without failing an older client — the enclosing rule object stays additionalProperties:false, so an unknown key at RULE level still skips that one rule (never the document), which is the tolerance parse_bundle_tolerant provides.",
/// "type": "object",
/// "properties": {
/// "atom_id": {
/// "description": "The ratified intent atom this rule was compiled from. Recorded on the verdict as olatomid.",
/// "type": "string"
/// },
/// "dimension": {
/// "description": "Which dimension the owning policy belongs to. Recorded as oldimension.",
/// "$ref": "#/$defs/Dimension"
/// },
/// "mode": {
/// "description": "The composed mode of the owning policy (monitor or enforce; a disabled policy is never composed). Distinct from the rule's own `mode` field, which is the schema-1 observe/enforce control the evaluator actually reads — this one is recorded as olmode and describes the policy, not this rule's rollout stage.",
/// "$ref": "#/$defs/PolicyMode"
/// },
/// "policy_id": {
/// "description": "The policy owning that atom. Recorded as olpolicyid; the public identifier the console shows is policy_public_id on the artifact plane.",
/// "type": "string"
/// },
/// "zone_layer": {
/// "description": "Identifier of the autonomy-zone unit this rule was inherited from — the layer that contributed it, not the agent's own zone. Recorded as ollayer.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct PolicyRuleProvenance {
///The ratified intent atom this rule was compiled from. Recorded on the verdict as olatomid.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub atom_id: ::std::option::Option<::std::string::String>,
///Which dimension the owning policy belongs to. Recorded as oldimension.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub dimension: ::std::option::Option<Dimension>,
///The composed mode of the owning policy (monitor or enforce; a disabled policy is never composed). Distinct from the rule's own `mode` field, which is the schema-1 observe/enforce control the evaluator actually reads — this one is recorded as olmode and describes the policy, not this rule's rollout stage.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub mode: ::std::option::Option<PolicyMode>,
///The policy owning that atom. Recorded as olpolicyid; the public identifier the console shows is policy_public_id on the artifact plane.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub policy_id: ::std::option::Option<::std::string::String>,
///Identifier of the autonomy-zone unit this rule was inherited from — the layer that contributed it, not the agent's own zone. Recorded as ollayer.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub zone_layer: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for PolicyRuleProvenance {
fn default() -> Self {
Self {
atom_id: Default::default(),
dimension: Default::default(),
mode: Default::default(),
policy_id: Default::default(),
zone_layer: Default::default(),
}
}
}
///Which requests a kind=request rule applies to; an absent select means every request the boundary sees. Forbidden on kind=command. Each key is narrowed further per action by the gate below — a key that an action does not read is rejected rather than silently ignored.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Which requests a kind=request rule applies to; an absent select means every request the boundary sees. Forbidden on kind=command. Each key is narrowed further per action by the gate below — a key that an action does not read is rejected rather than silently ignored.",
/// "type": "object",
/// "properties": {
/// "exclude_layers": {
/// "description": "Cache layers this rule must leave untouched. Read by prefix_reorder only.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/ChurnLayer"
/// }
/// },
/// "min_messages": {
/// "description": "Apply only once the in-context history has at least this many messages. Read by history_trim only.",
/// "type": "integer"
/// },
/// "model_in": {
/// "description": "Apply only to requests whose model identifier is in this list. Matched verbatim against the model string on the wire; no globbing.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct PolicyRuleSelect {
///Cache layers this rule must leave untouched. Read by prefix_reorder only.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub exclude_layers: ::std::vec::Vec<ChurnLayer>,
///Apply only once the in-context history has at least this many messages. Read by history_trim only.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub min_messages: ::std::option::Option<i64>,
///Apply only to requests whose model identifier is in this list. Matched verbatim against the model string on the wire; no globbing.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub model_in: ::std::vec::Vec<::std::string::String>,
}
impl ::std::default::Default for PolicyRuleSelect {
fn default() -> Self {
Self {
exclude_layers: Default::default(),
min_messages: Default::default(),
model_in: Default::default(),
}
}
}
///Author-assigned severity, surfaced on the verdict returned to the agent hook.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Author-assigned severity, surfaced on the verdict returned to the agent hook.",
/// "type": "string",
/// "enum": [
/// "low",
/// "medium",
/// "high",
/// "critical"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum PolicyRuleSeverity {
#[serde(rename = "low")]
Low,
#[serde(rename = "medium")]
Medium,
#[serde(rename = "high")]
High,
#[serde(rename = "critical")]
Critical,
}
impl ::std::fmt::Display for PolicyRuleSeverity {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Low => f.write_str("low"),
Self::Medium => f.write_str("medium"),
Self::High => f.write_str("high"),
Self::Critical => f.write_str("critical"),
}
}
}
impl ::std::str::FromStr for PolicyRuleSeverity {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"low" => Ok(Self::Low),
"medium" => Ok(Self::Medium),
"high" => Ok(Self::High),
"critical" => Ok(Self::Critical),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for PolicyRuleSeverity {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for PolicyRuleSeverity {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for PolicyRuleSeverity {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Authoring lifecycle of a policy. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Authoring lifecycle of a policy. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "draft",
/// "ratified",
/// "retired"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct PolicyStatus(pub ::std::string::String);
impl ::std::ops::Deref for PolicyStatus {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<PolicyStatus> for ::std::string::String {
fn from(value: PolicyStatus) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for PolicyStatus {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for PolicyStatus {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for PolicyStatus {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///Where a policy's source material came from. 'action' = the Execution Graph entry point; 'seed' = the seed tool via POST /policies/stated. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Where a policy's source material came from. 'action' = the Execution Graph entry point; 'seed' = the seed tool via POST /policies/stated. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "paste",
/// "upload",
/// "record",
/// "migrated",
/// "library",
/// "seed",
/// "action"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct SourceKind(pub ::std::string::String);
impl ::std::ops::Deref for SourceKind {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<SourceKind> for ::std::string::String {
fn from(value: SourceKind) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for SourceKind {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for SourceKind {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for SourceKind {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///`SubstitutePair`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "SubstitutePair",
/// "type": "object",
/// "properties": {
/// "from": {
/// "description": "What is matched.",
/// "type": "string"
/// },
/// "to": {
/// "description": "What replaces it.",
/// "type": "string"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct SubstitutePair {
///What is matched.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub from: ::std::option::Option<::std::string::String>,
///What replaces it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub to: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for SubstitutePair {
fn default() -> Self {
Self {
from: Default::default(),
to: Default::default(),
}
}
}
///One predicate over the action being evaluated: a field, a predicate name, and whichever payload that predicate reads. The compiled projection of the authored Pred language — an authored in_fact_set leaf compiles to the `set_ref` payload (the ATTRIBUTE is the subject and the fact supplies the set: 'url.host is in approved_domains'), and an authored fact leaf compiles to the `fact` payload (the FACT is the subject: 'is the ticket approved?'). Both are three-valued when the fact is absent: the leaf is inconclusive, and the artifact's on_inconclusive decides.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T1Leaf",
/// "description": "One predicate over the action being evaluated: a field, a predicate name, and whichever payload that predicate reads. The compiled projection of the authored Pred language — an authored in_fact_set leaf compiles to the `set_ref` payload (the ATTRIBUTE is the subject and the fact supplies the set: 'url.host is in approved_domains'), and an authored fact leaf compiles to the `fact` payload (the FACT is the subject: 'is the ticket approved?'). Both are three-valued when the fact is absent: the leaf is inconclusive, and the artifact's on_inconclusive decides.",
/// "type": "object",
/// "properties": {
/// "effect": {
/// "title": "T1LeafEffect",
/// "description": "For pred 'effect': the tuple the action must produce. An action may carry several tuples, and the leaf matches if ANY of them equals this one.",
/// "type": "object",
/// "properties": {
/// "target_class": {
/// "description": "The target class to match.",
/// "$ref": "#/$defs/TargetClass"
/// },
/// "verb": {
/// "description": "The effect verb to match.",
/// "$ref": "#/$defs/EffectVerb"
/// }
/// },
/// "additionalProperties": true
/// },
/// "fact": {
/// "title": "T1LeafFact",
/// "description": "For pred 'fact': the fact IS the subject of the question ('is the ticket approved?'). Three-valued — an absent, expired or unfetchable fact makes the leaf inconclusive, never false.",
/// "type": "object",
/// "properties": {
/// "fact_id": {
/// "description": "Which fact is being asked about.",
/// "$ref": "#/$defs/FactId"
/// },
/// "op": {
/// "description": "How the fact's value is compared: in_set, equals or int_cmp. Open per R14.",
/// "type": "string",
/// "x-known-values": [
/// "in_set",
/// "equals",
/// "int_cmp"
/// ]
/// },
/// "value": {
/// "description": "What it is compared against. Unconstrained, for the same reason as the leaf's own `value`."
/// }
/// },
/// "additionalProperties": true
/// },
/// "field": {
/// "description": "Which attribute of the action the leaf reads. Three of the families are PREFIXED rather than literal, so they cannot be listed as values: 'input.<json_pointer>' is an RFC 6901 pointer into tool_input (input./command, input./file_path, input./url); 'fact.<fact_id>' reads a resolved fact; and 'effect.attrs.<name>' reads an attribute the classifier attached to an effect tuple (D-16) — is_production is the first, from the env_selectors resolver, and it is listed below because a starter-library entry already reads effect.attrs.is_production and would otherwise be unmatchable. result.* fields exist only on post events: result.exit_code is null on anything but a shell command, and a leaf reading it there is false, not inconclusive. An open string per R14, and a field the client does not know makes the artifact unparseable rather than the bundle unreadable.",
/// "type": "string",
/// "x-known-values": [
/// "tool.name",
/// "input.strings",
/// "result.strings",
/// "result.exit_code",
/// "command.program",
/// "command.argv",
/// "command.simple",
/// "path.class",
/// "path.value",
/// "url.host",
/// "url.tld",
/// "url.scheme",
/// "url.boundary",
/// "effect.verb",
/// "effect.target_class",
/// "effect.attrs.is_production",
/// "agent.type",
/// "agent.environment",
/// "agent.function",
/// "agent.id",
/// "agent.principal",
/// "session.elapsed_ms",
/// "session.tool_calls",
/// "session.spend_micro_usd",
/// "session.tokens"
/// ]
/// },
/// "pattern": {
/// "description": "The glob or regex_lite source, for the predicates that take one. Unconstrained here and validated by the loader, which skips the item rather than the bundle when it does not compile.",
/// "type": "string"
/// },
/// "pred": {
/// "description": "Which comparison this leaf performs. regex_lite is ASCII (?-u) mode with no look-around, no back-references and a size limit, validated by regex-syntax at compile time and again by the loader, which skips the item on failure. int_cmp carries its {op, n} in `value`. An open string per R14: an unknown predicate makes the artifact unparseable and the loader skips that artifact.",
/// "type": "string",
/// "x-known-values": [
/// "equals",
/// "in_set",
/// "prefix",
/// "glob",
/// "keyword",
/// "regex_lite",
/// "tld_in",
/// "int_cmp",
/// "exists",
/// "effect",
/// "fact"
/// ]
/// },
/// "set_ref": {
/// "description": "For in_set-style predicates whose set comes from a fact rather than from a literal: the fact_id supplying the members. A scalar, not an object — the fact is the SOURCE of the set here, not the subject of the question. Absent or unresolvable makes the leaf inconclusive.",
/// "$ref": "#/$defs/FactId"
/// },
/// "value": {
/// "description": "The literal the predicate compares against — a string, an integer, a boolean, a list of them, or {op, n} for int_cmp. Deliberately unconstrained: the shape follows `pred`, and a type keyword here would fail the whole document on one leaf whose predicate the schema had not anticipated."
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T1Leaf {
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub effect: ::std::option::Option<T1LeafEffect>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub fact: ::std::option::Option<T1LeafFact>,
///Which attribute of the action the leaf reads. Three of the families are PREFIXED rather than literal, so they cannot be listed as values: 'input.<json_pointer>' is an RFC 6901 pointer into tool_input (input./command, input./file_path, input./url); 'fact.<fact_id>' reads a resolved fact; and 'effect.attrs.<name>' reads an attribute the classifier attached to an effect tuple (D-16) — is_production is the first, from the env_selectors resolver, and it is listed below because a starter-library entry already reads effect.attrs.is_production and would otherwise be unmatchable. result.* fields exist only on post events: result.exit_code is null on anything but a shell command, and a leaf reading it there is false, not inconclusive. An open string per R14, and a field the client does not know makes the artifact unparseable rather than the bundle unreadable.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub field: ::std::option::Option<::std::string::String>,
///The glob or regex_lite source, for the predicates that take one. Unconstrained here and validated by the loader, which skips the item rather than the bundle when it does not compile.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub pattern: ::std::option::Option<::std::string::String>,
///Which comparison this leaf performs. regex_lite is ASCII (?-u) mode with no look-around, no back-references and a size limit, validated by regex-syntax at compile time and again by the loader, which skips the item on failure. int_cmp carries its {op, n} in `value`. An open string per R14: an unknown predicate makes the artifact unparseable and the loader skips that artifact.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub pred: ::std::option::Option<::std::string::String>,
///For in_set-style predicates whose set comes from a fact rather than from a literal: the fact_id supplying the members. A scalar, not an object — the fact is the SOURCE of the set here, not the subject of the question. Absent or unresolvable makes the leaf inconclusive.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub set_ref: ::std::option::Option<FactId>,
///The literal the predicate compares against — a string, an integer, a boolean, a list of them, or {op, n} for int_cmp. Deliberately unconstrained: the shape follows `pred`, and a type keyword here would fail the whole document on one leaf whose predicate the schema had not anticipated.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub value: ::std::option::Option<::serde_json::Value>,
}
impl ::std::default::Default for T1Leaf {
fn default() -> Self {
Self {
effect: Default::default(),
fact: Default::default(),
field: Default::default(),
pattern: Default::default(),
pred: Default::default(),
set_ref: Default::default(),
value: Default::default(),
}
}
}
///For pred 'effect': the tuple the action must produce. An action may carry several tuples, and the leaf matches if ANY of them equals this one.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T1LeafEffect",
/// "description": "For pred 'effect': the tuple the action must produce. An action may carry several tuples, and the leaf matches if ANY of them equals this one.",
/// "type": "object",
/// "properties": {
/// "target_class": {
/// "description": "The target class to match.",
/// "$ref": "#/$defs/TargetClass"
/// },
/// "verb": {
/// "description": "The effect verb to match.",
/// "$ref": "#/$defs/EffectVerb"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T1LeafEffect {
///The target class to match.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub target_class: ::std::option::Option<TargetClass>,
///The effect verb to match.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verb: ::std::option::Option<EffectVerb>,
}
impl ::std::default::Default for T1LeafEffect {
fn default() -> Self {
Self {
target_class: Default::default(),
verb: Default::default(),
}
}
}
///For pred 'fact': the fact IS the subject of the question ('is the ticket approved?'). Three-valued — an absent, expired or unfetchable fact makes the leaf inconclusive, never false.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T1LeafFact",
/// "description": "For pred 'fact': the fact IS the subject of the question ('is the ticket approved?'). Three-valued — an absent, expired or unfetchable fact makes the leaf inconclusive, never false.",
/// "type": "object",
/// "properties": {
/// "fact_id": {
/// "description": "Which fact is being asked about.",
/// "$ref": "#/$defs/FactId"
/// },
/// "op": {
/// "description": "How the fact's value is compared: in_set, equals or int_cmp. Open per R14.",
/// "type": "string",
/// "x-known-values": [
/// "in_set",
/// "equals",
/// "int_cmp"
/// ]
/// },
/// "value": {
/// "description": "What it is compared against. Unconstrained, for the same reason as the leaf's own `value`."
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T1LeafFact {
///Which fact is being asked about.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub fact_id: ::std::option::Option<FactId>,
///How the fact's value is compared: in_set, equals or int_cmp. Open per R14.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub op: ::std::option::Option<::std::string::String>,
///What it is compared against. Unconstrained, for the same reason as the leaf's own `value`.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub value: ::std::option::Option<::serde_json::Value>,
}
impl ::std::default::Default for T1LeafFact {
fn default() -> Self {
Self {
fact_id: Default::default(),
op: Default::default(),
value: Default::default(),
}
}
}
///One node of a Tier 1 predicate tree — an operator over children, or a leaf. Recursive by $ref, so the same shape nests to any depth the compiler emits. Also the shape of a t3_hold trigger.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T1Node",
/// "description": "One node of a Tier 1 predicate tree — an operator over children, or a leaf. Recursive by $ref, so the same shape nests to any depth the compiler emits. Also the shape of a t3_hold trigger.",
/// "type": "object",
/// "properties": {
/// "children": {
/// "description": "Sub-nodes, for and/or/not. Absent on a leaf node.",
/// "type": "array",
/// "items": {
/// "$ref": "#/$defs/t1_node"
/// }
/// },
/// "leaf": {
/// "description": "The predicate this node tests, when op is leaf. Absent on an operator node.",
/// "$ref": "#/$defs/t1_leaf"
/// },
/// "op": {
/// "description": "How this node combines: and, or, not, or leaf (this node carries `leaf` instead of `children`). An open string per R14 — an unrecognised operator makes the ARTIFACT unparseable, and the loader skips that one artifact rather than failing the bundle.",
/// "type": "string",
/// "x-known-values": [
/// "and",
/// "or",
/// "not",
/// "leaf"
/// ]
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T1Node {
///Sub-nodes, for and/or/not. Absent on a leaf node.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub children: ::std::vec::Vec<T1Node>,
///The predicate this node tests, when op is leaf. Absent on an operator node.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub leaf: ::std::option::Option<T1Leaf>,
///How this node combines: and, or, not, or leaf (this node carries `leaf` instead of `children`). An open string per R14 — an unrecognised operator makes the ARTIFACT unparseable, and the loader skips that one artifact rather than failing the bundle.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub op: ::std::option::Option<::std::string::String>,
}
impl ::std::default::Default for T1Node {
fn default() -> Self {
Self {
children: Default::default(),
leaf: Default::default(),
op: Default::default(),
}
}
}
///Body of an artifact whose kind is 't1_predicate_tree' — the stateless plane. A boolean tree over attributes of the single action being evaluated; no session state, no history, no network. Selected by `kind` in application code, NOT by a discriminator in this schema: build.rs strips if/then/else before typify sees it, so a conditional here would silently not exist in the generated types.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T1PredicateTree",
/// "description": "Body of an artifact whose kind is 't1_predicate_tree' — the stateless plane. A boolean tree over attributes of the single action being evaluated; no session state, no history, no network. Selected by `kind` in application code, NOT by a discriminator in this schema: build.rs strips if/then/else before typify sees it, so a conditional here would silently not exist in the generated types.",
/// "type": "object",
/// "properties": {
/// "node": {
/// "description": "Root of the tree. The artifact fires when this evaluates true.",
/// "$ref": "#/$defs/t1_node"
/// },
/// "reason": {
/// "description": "Plain-language explanation shown to the developer verbatim when this artifact blocks an action. A deny the developer cannot understand is a broken feature.",
/// "type": "string"
/// },
/// "verdict": {
/// "description": "What happens when the tree fires. The one closed enum on this bundle (R14): a verdict the client cannot interpret is not a value to tolerate, it is an action nobody can take.",
/// "$ref": "#/$defs/Verdict"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T1PredicateTree {
///Root of the tree. The artifact fires when this evaluates true.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub node: ::std::option::Option<T1Node>,
///Plain-language explanation shown to the developer verbatim when this artifact blocks an action. A deny the developer cannot understand is a broken feature.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<::std::string::String>,
///What happens when the tree fires. The one closed enum on this bundle (R14): a verdict the client cannot interpret is not a value to tolerate, it is an action nobody can take.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verdict: ::std::option::Option<Verdict>,
}
impl ::std::default::Default for T1PredicateTree {
fn default() -> Self {
Self {
node: Default::default(),
reason: Default::default(),
verdict: Default::default(),
}
}
}
///Body of an artifact whose kind is 't2_register_program' — the session plane. A fixed-width register machine over per-session state, emitted only from the compiler's session-shape templates (count_le, seen, elapsed_le, run_le, budget_le, followed_by); there are no other op sequences. No loops and no register-indexed addressing, so evaluation is bounded by the program's own length and cannot be made expensive by a crafted session. Selected by `kind` in application code, not by a discriminator in this schema.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T2RegisterProgram",
/// "description": "Body of an artifact whose kind is 't2_register_program' — the session plane. A fixed-width register machine over per-session state, emitted only from the compiler's session-shape templates (count_le, seen, elapsed_le, run_le, budget_le, followed_by); there are no other op sequences. No loops and no register-indexed addressing, so evaluation is bounded by the program's own length and cannot be made expensive by a crafted session. Selected by `kind` in application code, not by a discriminator in this schema.",
/// "type": "object",
/// "properties": {
/// "on_evict": {
/// "description": "What happens when the session state this program needs was evicted — the honest question a stateful evaluator has to answer out loud. reinit starts over (counting from zero), unknown treats the shape as undecidable and defers to on_inconclusive, fail_static keeps the artifact's verdict. An open string per R14.",
/// "type": "string",
/// "x-known-values": [
/// "reinit",
/// "unknown",
/// "fail_static"
/// ]
/// },
/// "post": {
/// "description": "Instructions run AFTER the action, on the post event — the half that updates state (counting, latching, accumulating spend). Same instruction encoding as `pre`. Budget shapes accumulate here and decide in `pre`, which is why a budget is post-hoc (R7): the client learns what a call cost only once it has been made.",
/// "type": "array",
/// "items": {
/// "type": "array"
/// }
/// },
/// "pre": {
/// "description": "Instructions run BEFORE the action, on the deciding event — this is the half that can produce a verdict. Each instruction is a positional array of [op, args...]. Ops: MATCH pred->b, INC_SAT c if b, RESET c, CMP_GE c K->b, SET/CLR/TEST f, TS_STORE t if b, TS_ELAPSED t->a, ADD_SAT a event.field, CMP_GE a B->b, RUN_TRACK shape->run, AND/OR/NOT b, VERDICT b->verdict, ANOMALY b code, DONE b. Positional arrays rather than objects because the sequence is machine-generated and machine-read, never hand-authored; the inner items are unconstrained so one unknown op cannot fail the document.",
/// "type": "array",
/// "items": {
/// "type": "array"
/// }
/// },
/// "reason": {
/// "description": "Plain-language explanation shown to the developer verbatim when this artifact blocks an action.",
/// "type": "string"
/// },
/// "state_layout": {
/// "title": "T2StateLayout",
/// "description": "How much per-session state this program needs. Declared up front so the daemon can size and evict session state without executing anything.",
/// "type": "object",
/// "properties": {
/// "a": {
/// "description": "Number of saturating amount accumulators (tokens, micro-USD).",
/// "type": "integer"
/// },
/// "c": {
/// "description": "Number of saturating counters.",
/// "type": "integer"
/// },
/// "f": {
/// "description": "Number of flag bits.",
/// "type": "integer"
/// },
/// "run": {
/// "description": "Whether the program tracks a run of same-shape actions. Action shape is sha256(tool_name, first effect tuple, command.program), so argument values are ignored and 'Read a.py' and 'Read b.py' share a shape.",
/// "type": "boolean"
/// },
/// "t": {
/// "description": "Number of timestamp slots.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
/// },
/// "verdict": {
/// "description": "What a VERDICT instruction resolves to when the program fires.",
/// "$ref": "#/$defs/Verdict"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T2RegisterProgram {
///What happens when the session state this program needs was evicted — the honest question a stateful evaluator has to answer out loud. reinit starts over (counting from zero), unknown treats the shape as undecidable and defers to on_inconclusive, fail_static keeps the artifact's verdict. An open string per R14.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub on_evict: ::std::option::Option<::std::string::String>,
///Instructions run AFTER the action, on the post event — the half that updates state (counting, latching, accumulating spend). Same instruction encoding as `pre`. Budget shapes accumulate here and decide in `pre`, which is why a budget is post-hoc (R7): the client learns what a call cost only once it has been made.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub post: ::std::vec::Vec<::std::vec::Vec<::serde_json::Value>>,
///Instructions run BEFORE the action, on the deciding event — this is the half that can produce a verdict. Each instruction is a positional array of [op, args...]. Ops: MATCH pred->b, INC_SAT c if b, RESET c, CMP_GE c K->b, SET/CLR/TEST f, TS_STORE t if b, TS_ELAPSED t->a, ADD_SAT a event.field, CMP_GE a B->b, RUN_TRACK shape->run, AND/OR/NOT b, VERDICT b->verdict, ANOMALY b code, DONE b. Positional arrays rather than objects because the sequence is machine-generated and machine-read, never hand-authored; the inner items are unconstrained so one unknown op cannot fail the document.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub pre: ::std::vec::Vec<::std::vec::Vec<::serde_json::Value>>,
///Plain-language explanation shown to the developer verbatim when this artifact blocks an action.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<::std::string::String>,
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub state_layout: ::std::option::Option<T2StateLayout>,
///What a VERDICT instruction resolves to when the program fires.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verdict: ::std::option::Option<Verdict>,
}
impl ::std::default::Default for T2RegisterProgram {
fn default() -> Self {
Self {
on_evict: Default::default(),
post: Default::default(),
pre: Default::default(),
reason: Default::default(),
state_layout: Default::default(),
verdict: Default::default(),
}
}
}
///How much per-session state this program needs. Declared up front so the daemon can size and evict session state without executing anything.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T2StateLayout",
/// "description": "How much per-session state this program needs. Declared up front so the daemon can size and evict session state without executing anything.",
/// "type": "object",
/// "properties": {
/// "a": {
/// "description": "Number of saturating amount accumulators (tokens, micro-USD).",
/// "type": "integer"
/// },
/// "c": {
/// "description": "Number of saturating counters.",
/// "type": "integer"
/// },
/// "f": {
/// "description": "Number of flag bits.",
/// "type": "integer"
/// },
/// "run": {
/// "description": "Whether the program tracks a run of same-shape actions. Action shape is sha256(tool_name, first effect tuple, command.program), so argument values are ignored and 'Read a.py' and 'Read b.py' share a shape.",
/// "type": "boolean"
/// },
/// "t": {
/// "description": "Number of timestamp slots.",
/// "type": "integer"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T2StateLayout {
///Number of saturating amount accumulators (tokens, micro-USD).
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub a: ::std::option::Option<i64>,
///Number of saturating counters.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub c: ::std::option::Option<i64>,
///Number of flag bits.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub f: ::std::option::Option<i64>,
///Whether the program tracks a run of same-shape actions. Action shape is sha256(tool_name, first effect tuple, command.program), so argument values are ignored and 'Read a.py' and 'Read b.py' share a shape.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub run: ::std::option::Option<bool>,
///Number of timestamp slots.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub t: ::std::option::Option<i64>,
}
impl ::std::default::Default for T2StateLayout {
fn default() -> Self {
Self {
a: Default::default(),
c: Default::default(),
f: Default::default(),
run: Default::default(),
t: Default::default(),
}
}
}
///Body of an artifact whose kind is 't3_hold' — the plane that stops and asks. The only place a verdict waits on something outside the process, which is why every field here is a bound: how long, how many attempts, and what happens when the answer never comes. Selected by `kind` in application code, not by a discriminator in this schema.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "T3Hold",
/// "description": "Body of an artifact whose kind is 't3_hold' — the plane that stops and asks. The only place a verdict waits on something outside the process, which is why every field here is a bound: how long, how many attempts, and what happens when the answer never comes. Selected by `kind` in application code, not by a discriminator in this schema.",
/// "type": "object",
/// "properties": {
/// "directive_template_id": {
/// "description": "For reinforcement: which directive_templates entry to render. Optional — a human-resolved hold needs no directive.",
/// "type": "string"
/// },
/// "max_attempts": {
/// "description": "How many times a reinforcement may be re-asked before the hold gives up and applies on_timeout. Without a bound, a model that never answers in the expected shape loops forever on the developer's critical path.",
/// "type": "integer"
/// },
/// "on_timeout": {
/// "description": "The verdict applied when nobody answered in time. Holding is an irreversible opt-in precisely because this is a real outcome, not a theoretical one.",
/// "$ref": "#/$defs/Verdict"
/// },
/// "reason": {
/// "description": "Plain-language explanation shown to the developer verbatim when this artifact holds an action. A hold the developer cannot understand is worse than a deny they can: the action has stopped and nothing on screen says why. Present on t1_predicate_tree and t2_register_program since schema 2 and omitted here by oversight — compiled bundles have been shipping it all along, so this row describes what is already on the wire rather than adding a field.",
/// "type": "string"
/// },
/// "resolve": {
/// "description": "Who answers: 'human' holds the action for a console answer; 'reinforcement' puts the directive in front of the model and reads its reply. An open string per R14.",
/// "type": "string",
/// "x-known-values": [
/// "human",
/// "reinforcement"
/// ]
/// },
/// "timeout_s": {
/// "description": "How long the hold waits, in seconds, bounded in practice by client_config.hold.host_timeout_s and by the agent's own hook timeout.",
/// "type": "integer"
/// },
/// "trigger": {
/// "description": "The predicate tree that decides whether this hold applies to the action. Same shape as a Tier 1 tree, so one evaluator reads both.",
/// "$ref": "#/$defs/t1_node"
/// },
/// "verdict_on_approve": {
/// "description": "The verdict when the answer approves the action.",
/// "$ref": "#/$defs/Verdict"
/// },
/// "verdict_on_reject": {
/// "description": "The verdict when the answer rejects it.",
/// "$ref": "#/$defs/Verdict"
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct T3Hold {
///For reinforcement: which directive_templates entry to render. Optional — a human-resolved hold needs no directive.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub directive_template_id: ::std::option::Option<::std::string::String>,
///How many times a reinforcement may be re-asked before the hold gives up and applies on_timeout. Without a bound, a model that never answers in the expected shape loops forever on the developer's critical path.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub max_attempts: ::std::option::Option<i64>,
///The verdict applied when nobody answered in time. Holding is an irreversible opt-in precisely because this is a real outcome, not a theoretical one.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub on_timeout: ::std::option::Option<Verdict>,
///Plain-language explanation shown to the developer verbatim when this artifact holds an action. A hold the developer cannot understand is worse than a deny they can: the action has stopped and nothing on screen says why. Present on t1_predicate_tree and t2_register_program since schema 2 and omitted here by oversight — compiled bundles have been shipping it all along, so this row describes what is already on the wire rather than adding a field.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<::std::string::String>,
///Who answers: 'human' holds the action for a console answer; 'reinforcement' puts the directive in front of the model and reads its reply. An open string per R14.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub resolve: ::std::option::Option<::std::string::String>,
///How long the hold waits, in seconds, bounded in practice by client_config.hold.host_timeout_s and by the agent's own hook timeout.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub timeout_s: ::std::option::Option<i64>,
///The predicate tree that decides whether this hold applies to the action. Same shape as a Tier 1 tree, so one evaluator reads both.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub trigger: ::std::option::Option<T1Node>,
///The verdict when the answer approves the action.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verdict_on_approve: ::std::option::Option<Verdict>,
///The verdict when the answer rejects it.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub verdict_on_reject: ::std::option::Option<Verdict>,
}
impl ::std::default::Default for T3Hold {
fn default() -> Self {
Self {
directive_template_id: Default::default(),
max_attempts: Default::default(),
on_timeout: Default::default(),
reason: Default::default(),
resolve: Default::default(),
timeout_s: Default::default(),
trigger: Default::default(),
verdict_on_approve: Default::default(),
verdict_on_reject: Default::default(),
}
}
}
///The target half of a classified effect tuple (verb, target_class) — what the action acts ON, resolved from a path, host, or command by the client evaluator's classification tables. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The target half of a classified effect tuple (verb, target_class) — what the action acts ON, resolved from a path, host, or command by the client evaluator's classification tables. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "workspace_file",
/// "data_store",
/// "secret_material",
/// "classified_source",
/// "agent_config",
/// "system_path",
/// "vcs_remote",
/// "production_namespace",
/// "network_host",
/// "shell",
/// "opaque_code",
/// "model_call",
/// "financial_account",
/// "messaging_channel",
/// "identity_permission"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct TargetClass(pub ::std::string::String);
impl ::std::ops::Deref for TargetClass {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<TargetClass> for ::std::string::String {
fn from(value: TargetClass) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for TargetClass {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for TargetClass {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for TargetClass {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}
///The verdict the evaluator produced for one action. A closed enum, and the one the PRD freezes; the extensible vocabularies added for schema 2 are open strings with x-known-values (AgentFunction and ChurnLayer remain closed for their own, older reasons). allow = inside the zone, untouched. ask = allowed and flagged for asynchronous review (it holds only on a per-atom irreversible opt-in). block = refused before impact. optimize = the action proceeded on a changed path. WIRE COMPATIBILITY: 'approve' and 'deny' are accepted on INBOUND parse for one release and normalised to 'ask' and 'block' respectively — see normalise_verdict() in src/core/policy/. They are deliberately absent from this enum because a value listed here is also a value this client may EMIT, and D14 forbids emitting them.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "The verdict the evaluator produced for one action. A closed enum, and the one the PRD freezes; the extensible vocabularies added for schema 2 are open strings with x-known-values (AgentFunction and ChurnLayer remain closed for their own, older reasons). allow = inside the zone, untouched. ask = allowed and flagged for asynchronous review (it holds only on a per-atom irreversible opt-in). block = refused before impact. optimize = the action proceeded on a changed path. WIRE COMPATIBILITY: 'approve' and 'deny' are accepted on INBOUND parse for one release and normalised to 'ask' and 'block' respectively — see normalise_verdict() in src/core/policy/. They are deliberately absent from this enum because a value listed here is also a value this client may EMIT, and D14 forbids emitting them.",
/// "type": "string",
/// "enum": [
/// "allow",
/// "ask",
/// "block",
/// "optimize"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize,
::serde::Serialize,
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
)]
pub enum Verdict {
#[serde(rename = "allow")]
Allow,
#[serde(rename = "ask")]
Ask,
#[serde(rename = "block")]
Block,
#[serde(rename = "optimize")]
Optimize,
}
impl ::std::fmt::Display for Verdict {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
match *self {
Self::Allow => f.write_str("allow"),
Self::Ask => f.write_str("ask"),
Self::Block => f.write_str("block"),
Self::Optimize => f.write_str("optimize"),
}
}
}
impl ::std::str::FromStr for Verdict {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
match value {
"allow" => Ok(Self::Allow),
"ask" => Ok(Self::Ask),
"block" => Ok(Self::Block),
"optimize" => Ok(Self::Optimize),
_ => Err("invalid value".into()),
}
}
}
impl ::std::convert::TryFrom<&str> for Verdict {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for Verdict {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for Verdict {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
///Verdict response returned to the agent hook after processing. The client passes this through to the agent hook without interpreting the verdict itself. Mirrors the cloud response schema. Schema version '1.1' adds the optional 'context' object (headline / body / evidence[]) carrying user-facing copy that the agent renders in its end-user notification (D-16 of OpenRouter of Security).
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Verdict response returned to the agent hook after processing. The client passes this through to the agent hook without interpreting the verdict itself. Mirrors the cloud response schema. Schema version '1.1' adds the optional 'context' object (headline / body / evidence[]) carrying user-facing copy that the agent renders in its end-user notification (D-16 of OpenRouter of Security).",
/// "examples": [
/// {
/// "schema_version": "1.0",
/// "verdict": "allow",
/// "event_id": "019d8af1-f8da-73b3-92eb-79a99e59b10b",
/// "latency_ms": 42
/// },
/// {
/// "schema_version": "1.1",
/// "verdict": "deny",
/// "event_id": "019d8af1-f8da-73b3-92eb-000000000002",
/// "latency_ms": 88,
/// "reason": "Credential detected in tool output",
/// "severity": "critical",
/// "threat_category": "credential_detection",
/// "rule_id": "rule_cred_001",
/// "details_url": "https://app.openlatch.ai/events/019d8af1-f8da-73b3-92eb-000000000002",
/// "offline": false,
/// "context": {
/// "headline": "Credential detected",
/// "body": "This action would share a credential (API key, token, password). Remove the credential and use a secrets manager.",
/// "evidence": [
/// {
/// "label": "credential_kind",
/// "value_redacted": "github_pat (ghp_****)"
/// }
/// ]
/// }
/// },
/// {
/// "schema_version": "1.1",
/// "verdict": "allow",
/// "event_id": "019d8af1-f8da-73b3-92eb-000000000003",
/// "latency_ms": 201,
/// "offline": true,
/// "context": {
/// "headline": "Security tools unreachable",
/// "body": "Your security detection tools are currently unreachable. This action was allowed to avoid blocking work. Check the platform routing page for status.",
/// "evidence": []
/// }
/// }
/// ],
/// "type": "object",
/// "required": [
/// "event_id",
/// "latency_ms",
/// "schema_version",
/// "verdict"
/// ],
/// "properties": {
/// "context": {
/// "description": "Schema 1.1+. Optional user-facing copy for rendering an end-user-visible notification when the verdict is rendered to the human. Clients render context.headline + context.body + context.evidence directly. 'remediation' is intentionally NOT on the wire (D-16) — it is stored on the platform and accessible via details_url. Older clients (1.0) ignore this field. Nullability is expressed via anyOf (object | null) instead of `\"type\": [\"object\", \"null\"]` because typify (the Rust codegen) does not yet support the JSON Schema 2020-12 type-array form for inline object shapes.",
/// "default": null,
/// "anyOf": [
/// {
/// "type": "null"
/// },
/// {
/// "type": "object",
/// "required": [
/// "body",
/// "headline"
/// ],
/// "properties": {
/// "body": {
/// "description": "One-paragraph explanation shown below the headline.",
/// "type": "string",
/// "maxLength": 500,
/// "minLength": 1
/// },
/// "evidence": {
/// "default": [],
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "label"
/// ],
/// "properties": {
/// "label": {
/// "description": "Short tag, e.g. 'credit_card', 'host', 'tool_name'.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// },
/// "value_redacted": {
/// "description": "Redacted display string. Provider redacts before submission; platform re-runs SENSITIVE_FIELD_PATTERNS defensively.",
/// "type": "string",
/// "maxLength": 200
/// }
/// },
/// "additionalProperties": false
/// },
/// "maxItems": 16
/// },
/// "headline": {
/// "description": "One-line summary shown as the toast / notification title.",
/// "type": "string",
/// "maxLength": 120,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
/// }
/// ]
/// },
/// "details_url": {
/// "description": "URL to the OpenLatch dashboard with detailed event analysis. Omitted when not available.",
/// "type": "string"
/// },
/// "event_id": {
/// "description": "Server-assigned or client-generated ID of the event this verdict responds to.",
/// "type": "string"
/// },
/// "latency_ms": {
/// "description": "Total end-to-end processing latency in milliseconds, including cloud round-trip when applicable.",
/// "type": "number",
/// "minimum": 0.0
/// },
/// "offline": {
/// "description": "Schema 1.1+. True when all configured security tools were unreachable. The verdict is fail-open ('allow') and 'context.headline' will read 'Security tools unreachable'. Older clients ignore this field.",
/// "default": false,
/// "type": "boolean"
/// },
/// "reason": {
/// "description": "Human-readable explanation for the verdict. Omitted for allow verdicts.",
/// "type": "string"
/// },
/// "rule_id": {
/// "description": "Identifier of the detection rule that triggered this verdict. Omitted when no rule matched.",
/// "type": "string"
/// },
/// "schema_version": {
/// "description": "Schema version for forward compatibility. '1.0' = legacy. '1.1' = adds optional 'context' + 'offline' fields (D-16 of OpenRouter of Security). Older clients ignore unknown fields and remain compatible.",
/// "type": "string"
/// },
/// "severity": {
/// "description": "Threat severity level (e.g., 'critical', 'high', 'medium', 'low'). Omitted when no threat was detected.",
/// "type": "string"
/// },
/// "threat_category": {
/// "description": "Category of detected threat (e.g., 'credential_exfiltration', 'command_injection'). Omitted when no threat detected.",
/// "type": "string"
/// },
/// "verdict": {
/// "description": "The verdict: allow = proceed, approve = user-confirmed allow, deny = blocked.",
/// "$ref": "#/$defs/Verdict"
/// }
/// },
/// "additionalProperties": false,
/// "x-postgresql-skip": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct VerdictResponse {
///Schema 1.1+. Optional user-facing copy for rendering an end-user-visible notification when the verdict is rendered to the human. Clients render context.headline + context.body + context.evidence directly. 'remediation' is intentionally NOT on the wire (D-16) — it is stored on the platform and accessible via details_url. Older clients (1.0) ignore this field. Nullability is expressed via anyOf (object | null) instead of `"type": ["object", "null"]` because typify (the Rust codegen) does not yet support the JSON Schema 2020-12 type-array form for inline object shapes.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub context: ::std::option::Option<VerdictResponseContext>,
///URL to the OpenLatch dashboard with detailed event analysis. Omitted when not available.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub details_url: ::std::option::Option<::std::string::String>,
///Server-assigned or client-generated ID of the event this verdict responds to.
pub event_id: ::std::string::String,
///Total end-to-end processing latency in milliseconds, including cloud round-trip when applicable.
pub latency_ms: f64,
///Schema 1.1+. True when all configured security tools were unreachable. The verdict is fail-open ('allow') and 'context.headline' will read 'Security tools unreachable'. Older clients ignore this field.
#[serde(default)]
pub offline: bool,
///Human-readable explanation for the verdict. Omitted for allow verdicts.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub reason: ::std::option::Option<::std::string::String>,
///Identifier of the detection rule that triggered this verdict. Omitted when no rule matched.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub rule_id: ::std::option::Option<::std::string::String>,
///Schema version for forward compatibility. '1.0' = legacy. '1.1' = adds optional 'context' + 'offline' fields (D-16 of OpenRouter of Security). Older clients ignore unknown fields and remain compatible.
pub schema_version: ::std::string::String,
///Threat severity level (e.g., 'critical', 'high', 'medium', 'low'). Omitted when no threat was detected.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub severity: ::std::option::Option<::std::string::String>,
///Category of detected threat (e.g., 'credential_exfiltration', 'command_injection'). Omitted when no threat detected.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub threat_category: ::std::option::Option<::std::string::String>,
///The verdict: allow = proceed, approve = user-confirmed allow, deny = blocked.
pub verdict: Verdict,
}
///`VerdictResponseContext`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "body",
/// "headline"
/// ],
/// "properties": {
/// "body": {
/// "description": "One-paragraph explanation shown below the headline.",
/// "type": "string",
/// "maxLength": 500,
/// "minLength": 1
/// },
/// "evidence": {
/// "default": [],
/// "type": "array",
/// "items": {
/// "type": "object",
/// "required": [
/// "label"
/// ],
/// "properties": {
/// "label": {
/// "description": "Short tag, e.g. 'credit_card', 'host', 'tool_name'.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// },
/// "value_redacted": {
/// "description": "Redacted display string. Provider redacts before submission; platform re-runs SENSITIVE_FIELD_PATTERNS defensively.",
/// "type": "string",
/// "maxLength": 200
/// }
/// },
/// "additionalProperties": false
/// },
/// "maxItems": 16
/// },
/// "headline": {
/// "description": "One-line summary shown as the toast / notification title.",
/// "type": "string",
/// "maxLength": 120,
/// "minLength": 1
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct VerdictResponseContext {
///One-paragraph explanation shown below the headline.
pub body: VerdictResponseContextBody,
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub evidence: ::std::vec::Vec<VerdictResponseContextEvidenceItem>,
///One-line summary shown as the toast / notification title.
pub headline: VerdictResponseContextHeadline,
}
///One-paragraph explanation shown below the headline.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "One-paragraph explanation shown below the headline.",
/// "type": "string",
/// "maxLength": 500,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerdictResponseContextBody(::std::string::String);
impl ::std::ops::Deref for VerdictResponseContextBody {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerdictResponseContextBody> for ::std::string::String {
fn from(value: VerdictResponseContextBody) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerdictResponseContextBody {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 500usize {
return Err("longer than 500 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VerdictResponseContextBody {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for VerdictResponseContextBody {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for VerdictResponseContextBody {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for VerdictResponseContextBody {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///`VerdictResponseContextEvidenceItem`
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "type": "object",
/// "required": [
/// "label"
/// ],
/// "properties": {
/// "label": {
/// "description": "Short tag, e.g. 'credit_card', 'host', 'tool_name'.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
/// },
/// "value_redacted": {
/// "description": "Redacted display string. Provider redacts before submission; platform re-runs SENSITIVE_FIELD_PATTERNS defensively.",
/// "type": "string",
/// "maxLength": 200
/// }
/// },
/// "additionalProperties": false
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
#[serde(deny_unknown_fields)]
pub struct VerdictResponseContextEvidenceItem {
///Short tag, e.g. 'credit_card', 'host', 'tool_name'.
pub label: VerdictResponseContextEvidenceItemLabel,
///Redacted display string. Provider redacts before submission; platform re-runs SENSITIVE_FIELD_PATTERNS defensively.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub value_redacted: ::std::option::Option<VerdictResponseContextEvidenceItemValueRedacted>,
}
///Short tag, e.g. 'credit_card', 'host', 'tool_name'.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Short tag, e.g. 'credit_card', 'host', 'tool_name'.",
/// "type": "string",
/// "maxLength": 64,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerdictResponseContextEvidenceItemLabel(::std::string::String);
impl ::std::ops::Deref for VerdictResponseContextEvidenceItemLabel {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerdictResponseContextEvidenceItemLabel> for ::std::string::String {
fn from(value: VerdictResponseContextEvidenceItemLabel) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerdictResponseContextEvidenceItemLabel {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 64usize {
return Err("longer than 64 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VerdictResponseContextEvidenceItemLabel {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for VerdictResponseContextEvidenceItemLabel {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for VerdictResponseContextEvidenceItemLabel {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for VerdictResponseContextEvidenceItemLabel {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Redacted display string. Provider redacts before submission; platform re-runs SENSITIVE_FIELD_PATTERNS defensively.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Redacted display string. Provider redacts before submission; platform re-runs SENSITIVE_FIELD_PATTERNS defensively.",
/// "type": "string",
/// "maxLength": 200
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerdictResponseContextEvidenceItemValueRedacted(::std::string::String);
impl ::std::ops::Deref for VerdictResponseContextEvidenceItemValueRedacted {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerdictResponseContextEvidenceItemValueRedacted>
for ::std::string::String
{
fn from(value: VerdictResponseContextEvidenceItemValueRedacted) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerdictResponseContextEvidenceItemValueRedacted {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 200usize {
return Err("longer than 200 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VerdictResponseContextEvidenceItemValueRedacted {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String>
for VerdictResponseContextEvidenceItemValueRedacted
{
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String>
for VerdictResponseContextEvidenceItemValueRedacted
{
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for VerdictResponseContextEvidenceItemValueRedacted {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///One-line summary shown as the toast / notification title.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "One-line summary shown as the toast / notification title.",
/// "type": "string",
/// "maxLength": 120,
/// "minLength": 1
///}
/// ```
/// </details>
#[derive(::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[serde(transparent)]
pub struct VerdictResponseContextHeadline(::std::string::String);
impl ::std::ops::Deref for VerdictResponseContextHeadline {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<VerdictResponseContextHeadline> for ::std::string::String {
fn from(value: VerdictResponseContextHeadline) -> Self {
value.0
}
}
impl ::std::str::FromStr for VerdictResponseContextHeadline {
type Err = self::error::ConversionError;
fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
if value.chars().count() > 120usize {
return Err("longer than 120 characters".into());
}
if value.chars().count() < 1usize {
return Err("shorter than 1 characters".into());
}
Ok(Self(value.to_string()))
}
}
impl ::std::convert::TryFrom<&str> for VerdictResponseContextHeadline {
type Error = self::error::ConversionError;
fn try_from(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<&::std::string::String> for VerdictResponseContextHeadline {
type Error = self::error::ConversionError;
fn try_from(
value: &::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl ::std::convert::TryFrom<::std::string::String> for VerdictResponseContextHeadline {
type Error = self::error::ConversionError;
fn try_from(
value: ::std::string::String,
) -> ::std::result::Result<Self, self::error::ConversionError> {
value.parse()
}
}
impl<'de> ::serde::Deserialize<'de> for VerdictResponseContextHeadline {
fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error>
where
D: ::serde::Deserializer<'de>,
{
::std::string::String::deserialize(deserializer)?
.parse()
.map_err(|e: self::error::ConversionError| {
<D::Error as ::serde::de::Error>::custom(e.to_string())
})
}
}
///Which layer of the autonomy zone tree contributed this artifact — the unit it was INHERITED from, which is not necessarily the agent's own zone. Recorded as ollayer, and what makes 'why am I subject to this?' answerable without a round trip.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "title": "ZoneLayer",
/// "description": "Which layer of the autonomy zone tree contributed this artifact — the unit it was INHERITED from, which is not necessarily the agent's own zone. Recorded as ollayer, and what makes 'why am I subject to this?' answerable without a round trip.",
/// "type": "object",
/// "properties": {
/// "node_id": {
/// "description": "Identifier of the contributing zone node.",
/// "type": "string"
/// },
/// "path": {
/// "description": "Root-to-node path, so the console can render the inheritance chain without holding the tree.",
/// "type": "array",
/// "items": {
/// "type": "string"
/// }
/// }
/// },
/// "additionalProperties": true
///}
/// ```
/// </details>
#[derive(::serde::Deserialize, ::serde::Serialize, Clone, Debug, PartialEq)]
pub struct ZoneLayer {
///Identifier of the contributing zone node.
#[serde(default, skip_serializing_if = "::std::option::Option::is_none")]
pub node_id: ::std::option::Option<::std::string::String>,
///Root-to-node path, so the console can render the inheritance chain without holding the tree.
#[serde(default, skip_serializing_if = "::std::vec::Vec::is_empty")]
pub path: ::std::vec::Vec<::std::string::String>,
}
impl ::std::default::Default for ZoneLayer {
fn default() -> Self {
Self {
node_id: Default::default(),
path: Default::default(),
}
}
}
///Time window a zone view aggregates over. 'all' means the retention horizon (180 days), not unbounded. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.
///
/// <details><summary>JSON schema</summary>
///
/// ```json
///{
/// "description": "Time window a zone view aggregates over. 'all' means the retention horizon (180 days), not unbounded. Open string with x-known-values, never a closed enum (R14): typify and datamodel-code-generator fail the WHOLE document on an unknown closed value, which would fail-static the fleet on a single new vocabulary member.",
/// "type": "string",
/// "x-known-values": [
/// "24h",
/// "3d",
/// "7d",
/// "all"
/// ]
///}
/// ```
/// </details>
#[derive(
::serde::Deserialize, ::serde::Serialize, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd,
)]
#[serde(transparent)]
pub struct ZoneWindow(pub ::std::string::String);
impl ::std::ops::Deref for ZoneWindow {
type Target = ::std::string::String;
fn deref(&self) -> &::std::string::String {
&self.0
}
}
impl ::std::convert::From<ZoneWindow> for ::std::string::String {
fn from(value: ZoneWindow) -> Self {
value.0
}
}
impl ::std::convert::From<::std::string::String> for ZoneWindow {
fn from(value: ::std::string::String) -> Self {
Self(value)
}
}
impl ::std::str::FromStr for ZoneWindow {
type Err = ::std::convert::Infallible;
fn from_str(value: &str) -> ::std::result::Result<Self, Self::Err> {
Ok(Self(value.to_string()))
}
}
impl ::std::fmt::Display for ZoneWindow {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
self.0.fmt(f)
}
}