123 lines
4.8 KiB
JSON
123 lines
4.8 KiB
JSON
|
|
{
|
||
|
|
"$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",
|
||
|
|
"enum": ["chat", "worker", "telegram", "voice", "api"]
|
||
|
|
},
|
||
|
|
"provider": {
|
||
|
|
"type": "string",
|
||
|
|
"description": "Provider class, never a vendor model name. Switchyard resolves the class to a concrete target.",
|
||
|
|
"enum": ["codex", "claude", "local"]
|
||
|
|
},
|
||
|
|
"effort": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["low", "medium", "high", "xhigh"]
|
||
|
|
},
|
||
|
|
"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.",
|
||
|
|
"enum": ["public", "personal", "sensitive", "restricted"]
|
||
|
|
},
|
||
|
|
"redaction": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["level"],
|
||
|
|
"properties": {
|
||
|
|
"level": {"type": "string", "enum": ["none", "partial", "full"]},
|
||
|
|
"reason": {"type": "string", "maxLength": 200}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"actor": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["type", "id"],
|
||
|
|
"properties": {
|
||
|
|
"type": {"type": "string", "enum": ["user", "assistant", "tool", "system", "operator"]},
|
||
|
|
"id": {"type": "string", "minLength": 1, "maxLength": 120},
|
||
|
|
"display": {"type": "string", "maxLength": 120}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"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,
|
||
|
|
"required": ["requested"],
|
||
|
|
"properties": {
|
||
|
|
"requested": {"type": "string", "minLength": 1, "maxLength": 120},
|
||
|
|
"resolved_target": {"type": "string", "maxLength": 120},
|
||
|
|
"provider": {"$ref": "#/$defs/provider"},
|
||
|
|
"effort": {"$ref": "#/$defs/effort"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"build": {
|
||
|
|
"type": "object",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"properties": {
|
||
|
|
"commit": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
|
||
|
|
"image_digest": {"$ref": "#/$defs/sha256"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"provenance": {
|
||
|
|
"type": "object",
|
||
|
|
"description": "Who produced a record, on which surface, under which session/run, through which route, from which build.",
|
||
|
|
"additionalProperties": false,
|
||
|
|
"required": ["surface", "actor", "recorded_at"],
|
||
|
|
"properties": {
|
||
|
|
"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"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"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,
|
||
|
|
"required": ["kind", "id"],
|
||
|
|
"properties": {
|
||
|
|
"kind": {
|
||
|
|
"type": "string",
|
||
|
|
"enum": ["message", "tool_call", "tool_result", "artifact_version", "source", "passage", "memory", "approval", "run", "url", "file", "build", "flux", "pod"]
|
||
|
|
},
|
||
|
|
"id": {"type": "string", "minLength": 1, "maxLength": 200},
|
||
|
|
"uri": {"type": "string", "maxLength": 2000},
|
||
|
|
"hash": {"$ref": "#/$defs/sha256"}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
"tags": {
|
||
|
|
"type": "array",
|
||
|
|
"maxItems": 32,
|
||
|
|
"uniqueItems": true,
|
||
|
|
"items": {"type": "string", "pattern": "^[a-z0-9][a-z0-9-]{0,39}$"}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|