Skip to main content

harn_vm/session_bundle/
schema.rs

1use serde_json::{json, Value as JsonValue};
2
3use super::{
4    SessionBundleError, SESSION_BUNDLE_SCHEMA_ID, SESSION_BUNDLE_SCHEMA_VERSION,
5    SESSION_BUNDLE_TYPE,
6};
7
8pub fn session_bundle_schema() -> JsonValue {
9    json!({
10        "$schema": "https://json-schema.org/draft/2020-12/schema",
11        "$id": SESSION_BUNDLE_SCHEMA_ID,
12        "title": "Harn Session Bundle v1",
13        "type": "object",
14        "additionalProperties": true,
15        "required": [
16            "_type",
17            "schema_version",
18            "bundle_id",
19            "created_at",
20            "producer",
21            "source",
22            "runtime",
23            "transcript",
24            "tools",
25            "permissions",
26            "replay",
27            "redaction",
28            "attachments"
29        ],
30        "properties": {
31            "_type": {"const": SESSION_BUNDLE_TYPE},
32            "schema_version": {"type": "integer", "minimum": 1, "maximum": SESSION_BUNDLE_SCHEMA_VERSION},
33            "bundle_id": {"type": "string", "minLength": 1},
34            "created_at": {"type": "string", "minLength": 1},
35            "producer": {
36                "type": "object",
37                "required": ["name", "version", "schema_id"],
38                "additionalProperties": true,
39                "properties": {
40                    "name": {"type": "string"},
41                    "version": {"type": "string"},
42                    "schema_id": {"type": "string"}
43                }
44            },
45            "source": {
46                "type": "object",
47                "required": ["kind", "run_record_id", "workflow_id", "task", "status"],
48                "additionalProperties": true,
49                "properties": {
50                    "kind": {"type": "string"},
51                    "run_record_id": {"type": "string"},
52                    "workflow_id": {"type": "string"},
53                    "workflow_name": {"type": ["string", "null"]},
54                    "task": {"type": "string"},
55                    "status": {"type": "string"},
56                    "started_at": {"type": "string"},
57                    "finished_at": {"type": ["string", "null"]},
58                    "persisted_path": {"type": ["string", "null"]},
59                    "root_run_id": {"type": ["string", "null"]},
60                    "parent_run_id": {"type": ["string", "null"]},
61                    "child_run_count": {"type": "integer", "minimum": 0}
62                }
63            },
64            "runtime": {
65                "type": "object",
66                "required": ["harn_version", "provider_models"],
67                "additionalProperties": true,
68                "properties": {
69                    "harn_version": {"type": "string"},
70                    "provider_models": {"type": "array", "items": {"type": "string"}},
71                    "usage": {"type": ["object", "null"]},
72                    "metadata": {"type": "object"}
73                }
74            },
75            "workspace": {"type": ["object", "null"]},
76            "transcript": {
77                "type": "object",
78                "required": ["sections"],
79                "additionalProperties": true,
80                "properties": {
81                    "sections": {
82                        "type": "array",
83                        "items": {"$ref": "#/$defs/transcript_section"}
84                    }
85                }
86            },
87            "tools": {
88                "type": "object",
89                "required": ["schemas", "calls"],
90                "additionalProperties": true,
91                "properties": {
92                    "schemas": {"type": "array", "items": {"$ref": "#/$defs/json_entry"}},
93                    "calls": {"type": "array", "items": {"type": "object"}}
94                }
95            },
96            "permissions": {"type": "array", "items": {"type": "object"}},
97            "replay": {
98                "type": "object",
99                "required": ["event_log_pointers", "transitions", "checkpoints", "trace_spans", "deterministic_events"],
100                "additionalProperties": true,
101                "properties": {
102                    "replay_fixture": {"type": ["object", "null"]},
103                    "run_record": {"type": ["object", "null"]},
104                    "event_log_pointers": {"type": "array", "items": {"type": "object"}},
105                    "transitions": {"type": "array", "items": {"type": "object"}},
106                    "checkpoints": {"type": "array", "items": {"type": "object"}},
107                    "trace_spans": {"type": "array", "items": {"type": "object"}},
108                    "deterministic_events": {"type": "array", "items": {"$ref": "#/$defs/json_entry"}}
109                }
110            },
111            "redaction": {
112                "type": "object",
113                "required": ["mode", "policy", "placeholder", "entries", "unsafe_secret_markers_rejected"],
114                "additionalProperties": true,
115                "properties": {
116                    "mode": {"enum": ["local", "sanitized", "replay_only"]},
117                    "policy": {"type": "string"},
118                    "placeholder": {"type": "string"},
119                    "entries": {"type": "array", "items": {"type": "object"}},
120                    "unsafe_secret_markers_rejected": {"type": "boolean"}
121                }
122            },
123            "attachments": {"type": "array", "items": {"type": "object"}},
124            "metadata": {"type": "object"}
125        },
126        "$defs": {
127            "json_entry": {
128                "type": "object",
129                "required": ["source", "index", "value"],
130                "additionalProperties": true,
131                "properties": {
132                    "source": {"type": "string"},
133                    "index": {"type": "integer", "minimum": 0},
134                    "value": true
135                }
136            },
137            "transcript_section": {
138                "type": "object",
139                "required": ["id", "label", "scope", "location", "messages", "events", "assets", "metadata"],
140                "additionalProperties": true,
141                "properties": {
142                    "id": {"type": "string"},
143                    "label": {"type": "string"},
144                    "scope": {"type": "string"},
145                    "location": {"type": "string"},
146                    "summary": {"type": ["string", "null"]},
147                    "messages": {"type": "array", "items": true},
148                    "events": {"type": "array", "items": true},
149                    "assets": {"type": "array", "items": true},
150                    "metadata": {"type": "object"}
151                }
152            }
153        }
154    })
155}
156
157pub fn session_bundle_schema_pretty() -> Result<String, SessionBundleError> {
158    serde_json::to_string_pretty(&session_bundle_schema())
159        .map(|schema| format!("{schema}\n"))
160        .map_err(|error| SessionBundleError::Encode(error.to_string()))
161}