2026-08-23 22:07:38 -03:00
{
"$schema" : "https://json-schema.org/draft/2020-12/schema" ,
"$id" : "https://hermes.bstein.dev/contracts/hux/v1/common.schema.json" ,
"title" : "HUX shared definitions" ,
"description" : "Cross-surface primitives reused by every HUX contract. Identity, time, provenance, sensitivity and evidence are defined once here so Chat, Worker, Telegram, voice and future clients agree on them." ,
"$defs" : {
"id" : {
"type" : "string" ,
"description" : "Opaque, prefix-typed identifier. Prefix names the record kind (evt, mem, prj, conv, art, pol, apr, rcpt, src, psg, cit, nb, sug, rel)." ,
"pattern" : "^[a-z]{2,6}_[A-Za-z0-9._-]{4,80}$"
} ,
"user_ref" : {
"type" : "string" ,
"description" : "Hashed Keycloak subject as already used by the chat router. Never a raw subject, email, or Telegram id." ,
"pattern" : "^usr_[0-9a-f]{16,64}$"
} ,
"timestamp" : {
"type" : "string" ,
"description" : "RFC 3339 UTC timestamp with a trailing Z." ,
"pattern" : "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(\\.[0-9]{1,6})?Z$"
} ,
"sha256" : {
"type" : "string" ,
"pattern" : "^sha256:[0-9a-f]{64}$"
} ,
"surface" : {
"type" : "string" ,
2026-08-24 00:04:37 -03:00
"enum" : [
"chat" ,
"worker" ,
"telegram" ,
"voice" ,
"api"
]
2026-08-23 22:07:38 -03:00
} ,
"provider" : {
"type" : "string" ,
"description" : "Provider class, never a vendor model name. Switchyard resolves the class to a concrete target." ,
2026-08-24 00:04:37 -03:00
"enum" : [
"codex" ,
"claude" ,
"local"
]
2026-08-23 22:07:38 -03:00
} ,
"effort" : {
"type" : "string" ,
2026-08-24 00:04:37 -03:00
"enum" : [
"low" ,
"medium" ,
"high" ,
"xhigh"
]
2026-08-23 22:07:38 -03:00
} ,
"sensitivity" : {
"type" : "string" ,
"description" : "public: safe to show anywhere; personal: user-owned but not sensitive; sensitive: health/finance/legal/relationships; restricted: credentials, minors, biometric, location traces." ,
2026-08-24 00:04:37 -03:00
"enum" : [
"public" ,
"personal" ,
"sensitive" ,
"restricted"
]
2026-08-23 22:07:38 -03:00
} ,
"redaction" : {
"type" : "object" ,
"additionalProperties" : false ,
2026-08-24 00:04:37 -03:00
"required" : [
"level"
] ,
2026-08-23 22:07:38 -03:00
"properties" : {
2026-08-24 00:04:37 -03:00
"level" : {
"type" : "string" ,
"enum" : [
"none" ,
"partial" ,
"full"
]
} ,
"reason" : {
"type" : "string" ,
"maxLength" : 200
}
2026-08-23 22:07:38 -03:00
}
} ,
"actor" : {
"type" : "object" ,
"additionalProperties" : false ,
2026-08-24 00:04:37 -03:00
"required" : [
"type" ,
"id"
] ,
2026-08-23 22:07:38 -03:00
"properties" : {
2026-08-24 00:04:37 -03:00
"type" : {
"type" : "string" ,
"enum" : [
"user" ,
"assistant" ,
"tool" ,
"system" ,
"operator"
]
} ,
"id" : {
"type" : "string" ,
"minLength" : 1 ,
"maxLength" : 120
} ,
"display" : {
"type" : "string" ,
"maxLength" : 120
}
2026-08-23 22:07:38 -03:00
}
} ,
"route" : {
"type" : "object" ,
"description" : "What was asked of Switchyard and what it resolved. requested is a friendly mode or a route id; resolved_target is the Switchyard target name." ,
"additionalProperties" : false ,
2026-08-24 00:04:37 -03:00
"required" : [
"requested"
] ,
2026-08-23 22:07:38 -03:00
"properties" : {
2026-08-24 00:04:37 -03:00
"requested" : {
"type" : "string" ,
"minLength" : 1 ,
"maxLength" : 120
} ,
"resolved_target" : {
"type" : "string" ,
"maxLength" : 120
} ,
"provider" : {
"$ref" : "#/$defs/provider"
} ,
"effort" : {
"$ref" : "#/$defs/effort"
}
2026-08-23 22:07:38 -03:00
}
} ,
"build" : {
"type" : "object" ,
"additionalProperties" : false ,
"properties" : {
2026-08-24 00:04:37 -03:00
"commit" : {
"type" : "string" ,
"pattern" : "^[0-9a-f]{40}$"
} ,
"image_digest" : {
"$ref" : "#/$defs/sha256"
}
2026-08-23 22:07:38 -03:00
}
} ,
"provenance" : {
"type" : "object" ,
"description" : "Who produced a record, on which surface, under which session/run, through which route, from which build." ,
"additionalProperties" : false ,
2026-08-24 00:04:37 -03:00
"required" : [
"surface" ,
"actor" ,
"recorded_at"
] ,
2026-08-23 22:07:38 -03:00
"properties" : {
2026-08-24 00:04:37 -03:00
"surface" : {
"$ref" : "#/$defs/surface"
} ,
"actor" : {
"$ref" : "#/$defs/actor"
} ,
"recorded_at" : {
"$ref" : "#/$defs/timestamp"
} ,
"session_id" : {
"type" : "string" ,
"maxLength" : 120
} ,
"conversation_id" : {
"$ref" : "#/$defs/id"
} ,
"message_id" : {
"type" : "string" ,
"maxLength" : 120
} ,
"run_id" : {
"type" : "string" ,
"maxLength" : 120
} ,
"route" : {
"$ref" : "#/$defs/route"
} ,
"build" : {
"$ref" : "#/$defs/build"
}
2026-08-23 22:07:38 -03:00
}
} ,
"evidence_ref" : {
"type" : "object" ,
"description" : "Pointer to the thing that justifies a record. Never inline the payload here; the UI expands it through the owning API." ,
"additionalProperties" : false ,
2026-08-24 00:04:37 -03:00
"required" : [
"kind" ,
"id"
] ,
2026-08-23 22:07:38 -03:00
"properties" : {
"kind" : {
"type" : "string" ,
2026-08-24 00:04:37 -03:00
"enum" : [
"message" ,
"tool_call" ,
"tool_result" ,
"artifact_version" ,
"source" ,
"passage" ,
"memory" ,
"approval" ,
"run" ,
"url" ,
"file" ,
"build" ,
"flux" ,
2026-08-24 00:27:38 -03:00
"pod" ,
"receipt"
2026-08-24 00:04:37 -03:00
]
} ,
"id" : {
"type" : "string" ,
"minLength" : 1 ,
"maxLength" : 200
2026-08-23 22:07:38 -03:00
} ,
2026-08-24 00:04:37 -03:00
"uri" : {
"type" : "string" ,
"maxLength" : 2000
} ,
"hash" : {
"$ref" : "#/$defs/sha256"
}
2026-08-23 22:07:38 -03:00
}
} ,
"tags" : {
"type" : "array" ,
"maxItems" : 32 ,
"uniqueItems" : true ,
2026-08-24 00:04:37 -03:00
"items" : {
"type" : "string" ,
"pattern" : "^[a-z0-9][a-z0-9-]{0,39}$"
}
} ,
"tenant_slot" : {
"type" : "string" ,
"description" : "Router-assigned tenant process slot." ,
"pattern" : "^slot-[0-9]{1,3}$"
} ,
"trust" : {
"type" : "string" ,
2026-08-24 03:10:13 -03:00
"description" : "How identity was asserted: router, relay, worker, or the loopback-only release evidence producer." ,
2026-08-24 00:04:37 -03:00
"enum" : [
"router" ,
"relay" ,
2026-08-24 03:10:13 -03:00
"worker" ,
"evidence"
2026-08-24 00:04:37 -03:00
]
} ,
"identity" : {
"type" : "object" ,
"description" : "Resolved caller identity. Every record path and authorization check derives from tenant_slot + subject." ,
"additionalProperties" : false ,
"required" : [
"tenant_slot" ,
"subject" ,
"surface" ,
"trust"
] ,
"properties" : {
"tenant_slot" : {
"$ref" : "#/$defs/tenant_slot"
} ,
"subject" : {
"$ref" : "#/$defs/user_ref"
} ,
"surface" : {
"$ref" : "#/$defs/surface"
} ,
"trust" : {
"$ref" : "#/$defs/trust"
}
}
} ,
"revision" : {
"type" : "integer" ,
"description" : "Optimistic concurrency counter. Mutations send If-Match: <revision>; a mismatch is 409." ,
"minimum" : 1
} ,
"idempotency_key" : {
"type" : "string" ,
"description" : "Client-chosen key; a repeat with the same key returns the original record instead of creating a duplicate." ,
"pattern" : "^[A-Za-z0-9._:-]{8,120}$"
} ,
"contract_version" : {
"type" : "string" ,
"pattern" : "^1\\.[0-9]+\\.[0-9]+$"
} ,
"audit_outcome" : {
"type" : "object" ,
"description" : "Result of an authorization decision, written for every read and mutation." ,
"additionalProperties" : false ,
"required" : [
"at" ,
"identity" ,
"action" ,
"resource" ,
"outcome"
] ,
"properties" : {
"at" : {
"$ref" : "#/$defs/timestamp"
} ,
"identity" : {
"$ref" : "#/$defs/identity"
} ,
"action" : {
"type" : "string" ,
"pattern" : "^[a-z_]+\\.[a-z_]+$"
} ,
"resource" : {
"type" : "string" ,
"maxLength" : 200
} ,
"outcome" : {
"type" : "string" ,
"enum" : [
"allow" ,
"deny" ,
"not_found" ,
"conflict" ,
"flag_off"
]
} ,
"reason" : {
"type" : "string" ,
"maxLength" : 200
}
}
2026-08-23 22:07:38 -03:00
}
}
}