@corca-org/ceal-host-linux-arm64 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2987 @@
1
+ #!/usr/bin/env node
2
+
3
+ // packages/ceal-client-protocol/src/canonical-json.ts
4
+ function cealCanonicalJson(value) {
5
+ if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
6
+ if (typeof value === "number") {
7
+ if (!Number.isFinite(value)) throw new TypeError("Ceal canonical JSON does not support non-finite numbers.");
8
+ return JSON.stringify(value);
9
+ }
10
+ if (value === void 0) throw new TypeError("Ceal canonical JSON does not support undefined values.");
11
+ if (Array.isArray(value)) {
12
+ const entries = [];
13
+ for (let index = 0; index < value.length; index += 1) {
14
+ if (!Object.hasOwn(value, index)) throw new TypeError("Ceal canonical JSON does not support sparse arrays.");
15
+ entries.push(cealCanonicalJson(value[index]));
16
+ }
17
+ return `[${entries.join(",")}]`;
18
+ }
19
+ if (!isPlainRecord(value)) throw new TypeError("Ceal canonical JSON only supports JSON data.");
20
+ return `{${Object.keys(value).sort(cealCompareOrdered).map((key) => `${JSON.stringify(key)}:${cealCanonicalJson(value[key])}`).join(",")}}`;
21
+ }
22
+ function cealCompareOrdered(left, right) {
23
+ return left < right ? -1 : left > right ? 1 : 0;
24
+ }
25
+ function isPlainRecord(value) {
26
+ const prototype = Object.getPrototypeOf(value);
27
+ return prototype === Object.prototype || prototype === null;
28
+ }
29
+
30
+ // packages/ceal-client-protocol/client-wire-contract.json
31
+ var client_wire_contract_default = {
32
+ schema_version: "ceal.client_wire_contract.v1",
33
+ canonical_json: {
34
+ ordering: "utf16_code_unit_ascending"
35
+ },
36
+ artifact_descriptor: {
37
+ operation_contract_bundle_schema_version: "ceal.operation_contract_bundle.v1",
38
+ schema_version: "ceal.verified_artifact_descriptor.v1",
39
+ binding_schema_version: "ceal.verified_artifact_binding.v1",
40
+ kind: "verified_artifact",
41
+ binding_kind: "catalog",
42
+ media_type: "application/json",
43
+ digest: {
44
+ algorithm: "sha256",
45
+ encoding: "lowercase_hex",
46
+ length: 64,
47
+ pattern: "^[a-f0-9]{64}$"
48
+ },
49
+ catalog_revision: {
50
+ prefix: "catalog:",
51
+ digest_length: 64,
52
+ length: 72,
53
+ pattern: "^catalog:[a-f0-9]{64}$"
54
+ },
55
+ max_bytes: 4194304,
56
+ envelope_max_bytes: 389
57
+ },
58
+ command_request: {
59
+ schema_version: "ceal.command_request.v1",
60
+ absolute_transport_max_bytes: 65536
61
+ },
62
+ command_response: {
63
+ schema_version: "ceal.command_response.v1",
64
+ descriptor_field: "verified_artifact",
65
+ required_fields: [
66
+ "schema_version",
67
+ "exit_code",
68
+ "document"
69
+ ],
70
+ optional_fields: [
71
+ "verified_artifact"
72
+ ],
73
+ bare_document_fields: [
74
+ "invocation",
75
+ "next",
76
+ "common_concepts",
77
+ "operations",
78
+ "catalog_revision"
79
+ ],
80
+ exit_code_max: 125,
81
+ bare_document_max_bytes: 65536,
82
+ complete_max_bytes: 66019,
83
+ absolute_transport_max_bytes: 4194304
84
+ }
85
+ };
86
+
87
+ // packages/ceal-client-protocol/src/client-wire-contract.ts
88
+ var CEAL_CLIENT_WIRE_CONTRACT = Object.freeze(client_wire_contract_default);
89
+ var artifact = CEAL_CLIENT_WIRE_CONTRACT.artifact_descriptor;
90
+ var request = CEAL_CLIENT_WIRE_CONTRACT.command_request;
91
+ var response = CEAL_CLIENT_WIRE_CONTRACT.command_response;
92
+ var CEAL_OPERATION_CONTRACT_BUNDLE_SCHEMA_VERSION = artifact.operation_contract_bundle_schema_version;
93
+ var CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_SCHEMA_VERSION = artifact.schema_version;
94
+ var CEAL_VERIFIED_ARTIFACT_BINDING_SCHEMA_VERSION = artifact.binding_schema_version;
95
+ var CEAL_VERIFIED_ARTIFACT_KIND = artifact.kind;
96
+ var CEAL_VERIFIED_ARTIFACT_BINDING_KIND = artifact.binding_kind;
97
+ var CEAL_VERIFIED_ARTIFACT_MEDIA_TYPE = artifact.media_type;
98
+ var CEAL_VERIFIED_ARTIFACT_DIGEST_LENGTH = artifact.digest.length;
99
+ var CEAL_VERIFIED_ARTIFACT_DIGEST_PATTERN = artifact.digest.pattern;
100
+ var CEAL_VERIFIED_ARTIFACT_CATALOG_REVISION_LENGTH = artifact.catalog_revision.length;
101
+ var CEAL_VERIFIED_ARTIFACT_CATALOG_REVISION_PATTERN = artifact.catalog_revision.pattern;
102
+ var CEAL_VERIFIED_ARTIFACT_MAX_BYTES = artifact.max_bytes;
103
+ var CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_MAX_BYTES = artifact.envelope_max_bytes;
104
+ var CEAL_COMMAND_REQUEST_SCHEMA_VERSION = request.schema_version;
105
+ var CEAL_COMMAND_REQUEST_MAX_BYTES = request.absolute_transport_max_bytes;
106
+ var CEAL_COMMAND_RESPONSE_BARE_DOCUMENT_FIELDS = response.bare_document_fields;
107
+ var CEAL_COMMAND_RESPONSE_BARE_DOCUMENT_MAX_BYTES = response.bare_document_max_bytes;
108
+ var CEAL_COMMAND_RESPONSE_MAX_BYTES = response.absolute_transport_max_bytes;
109
+
110
+ // packages/ceal-client-protocol/src/vocabulary.ts
111
+ function vocabulary(words) {
112
+ return Object.freeze(words);
113
+ }
114
+
115
+ // packages/ceal-client-protocol/src/operation-contract-types.ts
116
+ var CEAL_JSON_SCHEMA_2020_12 = "https://json-schema.org/draft/2020-12/schema";
117
+ var CEAL_OPERATION_ERROR_SCHEMA_VERSION = "ceal.operation_error.v1";
118
+ var CEAL_JSON_SCHEMA_TYPES = vocabulary(["object", "array", "string", "integer", "number", "boolean", "null"]);
119
+ var OBSERVATION_POSTURES = vocabulary(["direct_readback", "approved_no_readback", "operator_mediated", "excluded"]);
120
+ var EFFECT_DOMAINS = vocabulary(["none", "gateway_state", "provider", "external_world"]);
121
+ var SAFETY_CLASSES = vocabulary(["routine", "sensitive", "high_impact"]);
122
+ var IDEMPOTENCY_CLASSES = vocabulary(["idempotent", "conditionally_idempotent", "non_idempotent"]);
123
+ var REVERSIBILITY_CLASSES = vocabulary(["none", "reversible", "compensatable", "irreversible"]);
124
+ var COMPENSATION_OWNERS = vocabulary(["none", "connector", "operator"]);
125
+ var CANCELLATION_BOUNDARIES = vocabulary(["before_admission", "before_handoff", "after_handoff_reconcile"]);
126
+ var HANDOFF_CLASSES = vocabulary(["not_applicable", "submission", "effect"]);
127
+ var AUTHORITATIVE_READBACK_CLASSES = vocabulary(["required", "unavailable"]);
128
+ var PROVIDER_READBACK_CLASSES = vocabulary(["required", "not_available", "not_applicable"]);
129
+ var RECONCILIATION_CLASSES = vocabulary(["none", "automatic", "operator"]);
130
+ var NO_READBACK_APPROVAL_CLASSES = vocabulary(["not_applicable", "explicit", "operator"]);
131
+ var REPLAY_PREREQUISITES = vocabulary(["never", "fresh_admission", "reconciled_non_application", "operator_approval"]);
132
+ var UNKNOWN_OUTCOMES = vocabulary(["reconcile", "operator_action", "excluded"]);
133
+ var RECOVERY_OWNERS = vocabulary(["gateway", "connector", "operator"]);
134
+ var CEAL_OPERATION_ADMISSION_STATES = vocabulary(["proposed", "refused", "admitted"]);
135
+ var CEAL_OPERATION_EXECUTION_STATES = vocabulary(["not_started", "started", "completed"]);
136
+ var CEAL_OPERATION_PROVIDER_HANDOFF_STATES = vocabulary(["not_offered", "offered", "accepted", "rejected", "unknown"]);
137
+ var CEAL_OPERATION_EFFECT_STATES = vocabulary(["none", "applied", "failed", "unknown", "compensated"]);
138
+ var CEAL_OPERATION_OBSERVATION_STATES = vocabulary(["not_started", "not_required", "pending", "observed", "unavailable"]);
139
+ var CEAL_OPERATION_RECOVERY_KINDS = vocabulary(["none", "reconcile", "compensate", "operator_action"]);
140
+ var CEAL_OPERATION_RECOVERY_STATUSES = vocabulary(["not_started", "active", "completed"]);
141
+ var CEAL_OPERATION_PROVIDER_READBACK_AVAILABILITY = vocabulary(["not_started", "not_applicable", "not_available", "pending", "available"]);
142
+ var CEAL_OPERATION_OFFERED_HANDOFF_STATES = vocabulary(["accepted", "rejected", "unknown"]);
143
+ var CEAL_OPERATION_APPROVAL_DISPOSITIONS = vocabulary([
144
+ "approval_not_required_by_policy",
145
+ "interactive_pending",
146
+ "interactive_granted",
147
+ "interactive_denied",
148
+ "interactive_expired",
149
+ "interactive_unavailable"
150
+ ]);
151
+
152
+ // packages/ceal-client-protocol/src/gateway-response-types.ts
153
+ var CEAL_CAPABILITY_READINESS_VALUES = vocabulary(["ready", "degraded", "unavailable", "unknown"]);
154
+ var CEAL_TARGET_REQUIREMENTS = vocabulary(["required", "optional", "none"]);
155
+ var CEAL_AUDIT_OUTCOMES = vocabulary(["succeeded", "denied", "failed"]);
156
+ var CEAL_GATEWAY_PROVIDER_STEP_OUTCOMES = vocabulary(["completed", "rejected", "throttled", "failed"]);
157
+ var CEAL_POLICY_DECISIONS = vocabulary(["allowed", "denied", "not_evaluated"]);
158
+ var CEAL_CONNECTOR_ROUTE_PHASES = vocabulary(["scope_observation", "target_selection", "route_resolution"]);
159
+ var CEAL_CONNECTOR_ROUTE_CAUSES = vocabulary(["provider_throttled", "provider_unavailable", "binding_invalid", "scope_limit_exceeded"]);
160
+ var CEAL_WRITE_SOURCE_KINDS = vocabulary(["authenticated_registered_client", "agent_lease_admission", "provider_authenticated_event"]);
161
+ var CEAL_REFRESH_DELIVERIES = vocabulary(["initial", "recovery", "replay", "terminal_failure", "recovery_unavailable"]);
162
+ var CEAL_CLIENT_OPERATIONS = vocabulary(["handshake", "discover", "call", "readback"]);
163
+ var CEAL_WRITE_IDEMPOTENCY_POSTURES = vocabulary(["required", "optional", "not_required"]);
164
+ var CEAL_WRITE_PROVIDER_READBACK_POSTURES = vocabulary(["required", "best_effort", "not_available"]);
165
+ var CEAL_WRITE_ATTRIBUTIONS = vocabulary(["subject", "requester_event", "connector_integration"]);
166
+ var CEAL_PROTOCOL_VERSION = "1.4.0";
167
+ var CEAL_CONNECTOR_ROUTE_FAILURE_KEYS = vocabulary(["connector_kind", "phase", "schema_version"]);
168
+ var CEAL_CLASSIFIED_CONNECTOR_ROUTE_FAILURE_KEYS = vocabulary(["cause", ...CEAL_CONNECTOR_ROUTE_FAILURE_KEYS]);
169
+ var CEAL_UNCLASSIFIED_CONNECTOR_ROUTE_FAILURE_KEYS = vocabulary(["connector_kind", "error_class", "phase", "schema_version"]);
170
+
171
+ // packages/ceal-client-protocol/src/gateway-validation-primitives.ts
172
+ var CealProtocolValidationError = class extends Error {
173
+ name = "CealProtocolValidationError";
174
+ code;
175
+ constructor(code) {
176
+ super(code === "invalid_gateway_request" ? "Ceal Gateway request is invalid." : "Ceal client response is invalid.");
177
+ this.code = code;
178
+ }
179
+ };
180
+ var SAFE_REF = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
181
+ var MAX_SAFE_TOKEN_LENGTH = 64;
182
+ var SAFE_CODE = new RegExp(`^[a-z][a-z0-9_]{0,${MAX_SAFE_TOKEN_LENGTH - 1}}$`, "u");
183
+ var SAFE_CONNECTOR_KIND = new RegExp(`^[a-z][a-z0-9-]{0,${MAX_SAFE_TOKEN_LENGTH - 1}}$`, "u");
184
+ var FORBIDDEN_SECRET_KEY = /^(?:[a-z0-9_]*(?:token|secret|password|credential(?:s)?|private_?key)|api_?key|authorization|bearer|raw_?provider_?payload|provider_?payload)$/iu;
185
+ var FORBIDDEN_AUTHORITY_KEY = /^(?:actor_?ref|owner_?ref|registration_?ref|runner_?ref|auth_?decision|policy_?decision|host_?decision)$/iu;
186
+ var TEXT_ENCODER = new TextEncoder();
187
+ var CEAL_WIRE_SAFE_TEXT_MAX_BYTES = 8 * 1024;
188
+ function assertSafeJsonValue(value, options, depth = 0, count = { value: 0 }) {
189
+ count.value += 1;
190
+ if (depth > 8 || count.value > (options.maxNodes ?? 512)) invalidByContext(options);
191
+ if (value === null || typeof value === "boolean") return;
192
+ if (typeof value === "number") return assertSafeJsonNumber(value, options);
193
+ if (typeof value === "string") return assertSafeJsonString(value, options);
194
+ if (Array.isArray(value)) {
195
+ return assertSafeJsonArray(value, options, depth, count);
196
+ }
197
+ assertSafeJsonRecord(requireRecord(value), options, depth, count);
198
+ }
199
+ function assertSafeJsonNumber(value, options) {
200
+ if (!Number.isFinite(value)) invalidByContext(options);
201
+ }
202
+ function assertSafeJsonString(value, options) {
203
+ if (byteLength(value) > CEAL_WIRE_SAFE_TEXT_MAX_BYTES || firstDisallowedControl(value, "multi_line") !== null) invalidByContext(options);
204
+ }
205
+ function assertSafeJsonArray(value, options, depth, count) {
206
+ if (value.length > 128) invalidByContext(options);
207
+ for (const item of value) assertSafeJsonValue(item, options, depth + 1, count);
208
+ }
209
+ function assertSafeJsonRecord(record6, options, depth, count) {
210
+ const entries = Object.entries(record6);
211
+ if (entries.length > 128) invalidByContext(options);
212
+ const sourceUrlColumn = options.allowHttpsUrl ? compactSourceUrlColumn(record6.fields) : null;
213
+ for (const [key, child] of entries) {
214
+ if (key === "credential_material_included" && child !== false) invalidByContext(options);
215
+ if (!isSafeNegativeMaterialAssertion(key, child)) assertSafeJsonKey(key, options);
216
+ if (key === "rows" && sourceUrlColumn !== null) {
217
+ assertSafeJsonCompactRows(child, sourceUrlColumn, options, depth, count);
218
+ continue;
219
+ }
220
+ assertSafeJsonRecordChild(key, child, options, depth, count);
221
+ }
222
+ }
223
+ function assertSafeJsonRecordChild(key, child, options, depth, count) {
224
+ if (options.allowResultContent && (key === "text" || key === "text_preview")) {
225
+ if (!isSafeResultContent(child, key)) invalidByContext(options);
226
+ return;
227
+ }
228
+ if ((key === "url" || key === "source_url") && options.allowHttpsUrl && isSafeExternalHttpsUrl(child)) return;
229
+ assertSafeJsonValue(child, options, depth + 1, count);
230
+ }
231
+ function compactSourceUrlColumn(fields) {
232
+ if (!Array.isArray(fields)) return null;
233
+ const index = fields.indexOf("source_url");
234
+ return index < 0 ? null : index;
235
+ }
236
+ function assertSafeJsonCompactRows(value, sourceUrlColumn, options, depth, count) {
237
+ if (!Array.isArray(value) || value.length > 128) invalidByContext(options);
238
+ for (const row of value) {
239
+ if (!Array.isArray(row) || row.length > 128) invalidByContext(options);
240
+ for (const [index, cell] of row.entries()) {
241
+ if (index === sourceUrlColumn && (cell === null || isSafeExternalHttpsUrl(cell))) continue;
242
+ assertSafeJsonValue(cell, options, depth + 2, count);
243
+ }
244
+ }
245
+ }
246
+ function isSafeNegativeMaterialAssertion(key, value) {
247
+ return key === "credential_material_included" && value === false;
248
+ }
249
+ function assertSafeJsonKey(key, options) {
250
+ const invalid2 = !/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(key) || FORBIDDEN_SECRET_KEY.test(key) || options.forbidAuthorityKeys && FORBIDDEN_AUTHORITY_KEY.test(key);
251
+ if (invalid2) invalidByContext(options);
252
+ }
253
+ function isSafeExternalHttpsUrl(value) {
254
+ if (!isSafeExternalHttpsUrlInput(value)) return false;
255
+ try {
256
+ const url = new URL(value);
257
+ return isSafeExternalHttpsUrlShape(url);
258
+ } catch {
259
+ return false;
260
+ }
261
+ }
262
+ function isSafeExternalHttpsUrlInput(value) {
263
+ return typeof value === "string" && byteLength(value) <= 2048;
264
+ }
265
+ function isSafeExternalHttpsUrlShape(url) {
266
+ return url.protocol === "https:" && url.username === "" && url.password === "" && url.hash === "";
267
+ }
268
+ function isSafeResultContent(value, key) {
269
+ const maximum = key === "text" ? 8192 : 1024;
270
+ return typeof value === "string" && byteLength(value) <= maximum && firstDisallowedControl(value, "multi_line") === null;
271
+ }
272
+ function normalizeCealSingleLineText(value) {
273
+ return value.split("").map((character) => hasControlCharacter(character) ? " " : character).join("").trim();
274
+ }
275
+ function byteLength(value) {
276
+ return TEXT_ENCODER.encode(value).byteLength;
277
+ }
278
+ var LAYOUT_CODE_POINTS = [9, 10, 13];
279
+ function firstDisallowedControl(value, shape) {
280
+ let index = 0;
281
+ for (const character of value) {
282
+ const codePoint = character.codePointAt(0) ?? 0;
283
+ const laysOutALine = shape === "multi_line" && LAYOUT_CODE_POINTS.includes(codePoint);
284
+ if (!laysOutALine && (codePoint <= 31 || codePoint === 127)) return { codePoint, index };
285
+ index += character.length;
286
+ }
287
+ return null;
288
+ }
289
+ function hasControlCharacter(value) {
290
+ return firstDisallowedControl(value, "single_line") !== null;
291
+ }
292
+ var AUTHORITY_METADATA_SUFFIX = "(?:_(?:refs?|revisions?|versions?|generations?|ids?))*$";
293
+ var UNDECLARED_AUTHORITY_STATE_KEY = new RegExp(`(?:^|_)(?:decisions?|authority|grants?|policy|policies|scopes?|tokens?|credentials?|secrets?|permissions?|roles?)${AUTHORITY_METADATA_SUFFIX}`, "iu");
294
+ var UNDECLARED_HANDLE_REF_KEY = new RegExp(`(?:^|_)refs?${AUTHORITY_METADATA_SUFFIX}`, "iu");
295
+ function requireRecord(value) {
296
+ if (!isCealJsonRecord(value)) invalidRequestOrResponse();
297
+ const prototype = Object.getPrototypeOf(value);
298
+ if (prototype !== Object.prototype && prototype !== null) invalidRequestOrResponse();
299
+ return value;
300
+ }
301
+ function isCealJsonRecord(value) {
302
+ return value !== null && typeof value === "object" && !Array.isArray(value);
303
+ }
304
+ var CEAL_VALIDATION_STATUSES = vocabulary(["not_applicable", "valid", "invalid"]);
305
+ var CEAL_PARSE_STATUSES = vocabulary(["not_applicable", "parsed", "parse_failed"]);
306
+ function invalidByContext(options) {
307
+ if (options.forbidAuthorityKeys) invalidRequest();
308
+ invalidResponse();
309
+ }
310
+ var InvalidWireShapeError = class extends Error {
311
+ };
312
+ function invalidRequestOrResponse() {
313
+ throw new InvalidWireShapeError();
314
+ }
315
+ function invalidRequest() {
316
+ throw new CealProtocolValidationError("invalid_gateway_request");
317
+ }
318
+ function invalidResponse() {
319
+ throw new CealProtocolValidationError("invalid_client_response");
320
+ }
321
+
322
+ // packages/ceal-client-protocol/src/refusal-fact.ts
323
+ var REFUSAL_VALUE_MAX_CHARS = 160;
324
+ function renderText(value) {
325
+ return normalizeCealSingleLineText(value);
326
+ }
327
+ var REFUSAL_LIST_HEAD = 5;
328
+ var REFUSAL_FACTS_MAX_CHARS = 360;
329
+ var REFUSAL_SENTENCE_MAX_BYTES = 384;
330
+ var REFUSAL_CLOSING_MAX_BYTES = REFUSAL_SENTENCE_MAX_BYTES / 2;
331
+ function refusalFact(name, value, expected) {
332
+ const rendered = `${JSON.stringify(name)}=${renderRefusalValue(value)}`;
333
+ return expected === void 0 ? rendered : `${rendered}; expected ${cut(renderText(expected))}`;
334
+ }
335
+ function refusalFacts(facts) {
336
+ const joined = facts.map((fact) => refusalFact(fact.name, fact.value, fact.expected)).join("; ");
337
+ return joined.length <= REFUSAL_FACTS_MAX_CHARS ? joined : `${joined.slice(0, REFUSAL_FACTS_MAX_CHARS)}...(+${joined.length - REFUSAL_FACTS_MAX_CHARS} chars, ${facts.length} facts)`;
338
+ }
339
+ function renderRefusalValue(value) {
340
+ if (typeof value === "object" && value !== null) return renderStructure(value);
341
+ if (typeof value === "string") return cut(JSON.stringify(renderText(value)));
342
+ if (typeof value === "function") return `function ${value.name === "" ? "(anonymous)" : value.name} -- a fact must be a value`;
343
+ if (typeof value === "symbol") return value.toString();
344
+ if (typeof value === "bigint") return `${value}n`;
345
+ return String(value);
346
+ }
347
+ function renderStructure(value) {
348
+ if (Array.isArray(value)) return cut(renderList(value));
349
+ if (value instanceof Error) return `${value.name}${"code" in value && typeof value.code === "string" ? `(${value.code})` : ""}`;
350
+ if (value instanceof Date) return value.toISOString();
351
+ if (ArrayBuffer.isView(value)) return `<${value.byteLength} bytes>`;
352
+ return renderRecord(value);
353
+ }
354
+ function renderRecord(value) {
355
+ if (value instanceof Map) return cut(renderList([...value].map(([key, entry2]) => `${renderRefusalValue(key)}=${renderRefusalValue(entry2)}`), true));
356
+ if (value instanceof Set) return cut(renderList([...value]));
357
+ if (isStatRecord(value)) return `{"mode":"0o${Number(value.mode).toString(8)}","size":${Number(value.size)},"kind":"${statKind(value)}"}`;
358
+ return cut(renderText(JSON.stringify(value, serializable) ?? String(value)));
359
+ }
360
+ function statKind(value) {
361
+ if (value.isDirectory()) return "directory";
362
+ return value.isFile() ? "file" : "other";
363
+ }
364
+ function isStatRecord(value) {
365
+ return "mode" in value && (typeof value.mode === "number" || typeof value.mode === "bigint") && "size" in value && (typeof value.size === "number" || typeof value.size === "bigint") && "isDirectory" in value && typeof value.isDirectory === "function" && "isFile" in value && typeof value.isFile === "function";
366
+ }
367
+ function serializable(_key, entry2) {
368
+ if (typeof entry2 === "bigint") return `${entry2}n`;
369
+ return ArrayBuffer.isView(entry2) ? `<${entry2.byteLength} bytes>` : entry2;
370
+ }
371
+ function renderList(value, rendered = false) {
372
+ const head = value.slice(0, REFUSAL_LIST_HEAD).map((item) => rendered ? String(item) : renderRefusalValue(item));
373
+ const rest = value.length - head.length;
374
+ return `[${head.join(", ")}${rest > 0 ? `, ...${rest} more` : ""}] (${value.length} items)`;
375
+ }
376
+ function cut(text) {
377
+ return text.length <= REFUSAL_VALUE_MAX_CHARS ? text : `${text.slice(0, REFUSAL_VALUE_MAX_CHARS)}...(+${text.length - REFUSAL_VALUE_MAX_CHARS} chars)`;
378
+ }
379
+
380
+ // packages/ceal-client-protocol/src/safe-json-budget.ts
381
+ var SAFE_JSON_MIN_BYTES_PER_NODE = 4;
382
+ function safeJsonNodeBudgetForBytes(maxBytes) {
383
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < SAFE_JSON_MIN_BYTES_PER_NODE) {
384
+ throw new RangeError(`safe-JSON byte cap is invalid: ${refusalFact("maxBytes", maxBytes, `at least ${SAFE_JSON_MIN_BYTES_PER_NODE} bytes`)}`);
385
+ }
386
+ return Math.floor(maxBytes / SAFE_JSON_MIN_BYTES_PER_NODE);
387
+ }
388
+
389
+ // packages/ceal-client-protocol/src/protocol-bounds.ts
390
+ var CEAL_PROTOCOL_RESPONSE_VALUE_MAX_BYTES = 64 * 1024;
391
+ var CEAL_PROTOCOL_RESPONSE_VALUE_MAX_NODES = safeJsonNodeBudgetForBytes(CEAL_PROTOCOL_RESPONSE_VALUE_MAX_BYTES);
392
+ var OPERATION_SCHEMA_LITERAL_MAX_BYTES = CEAL_PROTOCOL_RESPONSE_VALUE_MAX_BYTES / 4;
393
+ var CEAL_OPERATION_JSON_SCHEMA_BUDGET = Object.freeze({
394
+ max_depth: 8,
395
+ max_properties: 96,
396
+ max_string_length: OPERATION_SCHEMA_LITERAL_MAX_BYTES / 4,
397
+ max_alternatives: 8,
398
+ max_enum_values: 64,
399
+ max_literal_bytes: OPERATION_SCHEMA_LITERAL_MAX_BYTES
400
+ });
401
+
402
+ // packages/ceal-client-protocol/src/operation-validation-primitives.ts
403
+ var ISO_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/u;
404
+ function isOperationRecord(value) {
405
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
406
+ const prototype = Object.getPrototypeOf(value);
407
+ return prototype === Object.prototype || prototype === null;
408
+ }
409
+ function requireOperationRecord(value, message) {
410
+ if (!isOperationRecord(value)) throw new TypeError(message);
411
+ }
412
+ function requireClosedValue(value, members, message) {
413
+ if (typeof value !== "string" || !members.includes(value)) throw new TypeError(message);
414
+ }
415
+ function requireIsoTimestamp(value, message) {
416
+ if (typeof value !== "string" || !ISO_TIMESTAMP.test(value) || !Number.isFinite(Date.parse(value))) throw new TypeError(message);
417
+ }
418
+
419
+ // packages/ceal-client-protocol/src/operation-contract-validation.ts
420
+ var CEAL_OPERATION_AUTHORITY_POLICY_KEYS = Object.freeze(["profile", "instance_binding", "target", "admission_recheck"]);
421
+ var MAX_OPERATION_INPUT_RESOLVER_BINDINGS = 96;
422
+ var CEAL_OPERATION_RESULT_KEYS = vocabulary(["ok", "operation_id", "operation_receipt", "schema_version", "value"]);
423
+ var CEAL_OPERATION_COMPACT_RESULT_KEYS = vocabulary(["ok", "operation_evidence", "operation_id", "schema_version", "value"]);
424
+
425
+ // packages/ceal-client-protocol/src/operation-catalog.ts
426
+ var CEAL_OPERATION_CATALOG_SCHEMA_VERSION = "ceal.catalog.v3";
427
+ var CLIENT_AUDIENCES = Object.freeze(["ceal", "cealctl", "agent"]);
428
+ var CLIENT_AUDIENCE_SET = new Set(CLIENT_AUDIENCES);
429
+
430
+ // packages/ceal-client-protocol/src/schema-literals.ts
431
+ var CEAL_SCHEMA_LITERALS = [
432
+ "ceal.activation_transport.v1",
433
+ "ceal.capability_access.v1",
434
+ CEAL_OPERATION_CATALOG_SCHEMA_VERSION,
435
+ "ceal.client_refresh_request.v2",
436
+ "ceal.client_refresh_result.v2",
437
+ "ceal.client_revoke_request.v1",
438
+ "ceal.client_revoke_result.v1",
439
+ CEAL_COMMAND_REQUEST_SCHEMA_VERSION,
440
+ "ceal.device_enrollment_challenge.v1",
441
+ "ceal.device_enrollment_challenge_request.v1",
442
+ "ceal.device_enrollment_hpke_aad.v1",
443
+ "ceal.device_enrollment_hpke_info.v1",
444
+ "ceal.device_enrollment_poll.v1",
445
+ "ceal.device_enrollment_poll_result.v1",
446
+ "ceal.device_enrollment_proof.v1",
447
+ "ceal.device_enrollment_start.v1",
448
+ "ceal.device_enrollment_start_result.v1",
449
+ "ceal.effect_approval.v1",
450
+ "ceal.effect_approval_confirmation.v1",
451
+ "ceal.enrollment_create.v1",
452
+ "ceal.enrollment_create_result.v1",
453
+ "ceal.enrollment_exchange.v1",
454
+ "ceal.enrollment_result.v1",
455
+ "ceal.first_activation_causal_join.v1",
456
+ "ceal.gateway_aggregate_authorization_snapshot.v2",
457
+ "ceal.gateway_announcement_policy.v1",
458
+ "ceal.gateway_audit_call_detail.v1",
459
+ "ceal.gateway_audit_event.v1",
460
+ "ceal.gateway_audit_readback.v1",
461
+ "ceal.gateway_authorization_snapshot.v1",
462
+ "ceal.gateway_cache_origin.v1",
463
+ "ceal.gateway_call_result.v1",
464
+ "ceal.gateway_command_resolution.v1",
465
+ "ceal.gateway_connector_route_failure.v1",
466
+ "ceal.gateway_discovery.v3",
467
+ "ceal.gateway_handshake.v1",
468
+ "ceal.gateway_installation_activation_code_issue_request.v1",
469
+ "ceal.gateway_installation_activation_code_issue_result.v1",
470
+ "ceal.gateway_installation_activation_code_list_result.v1",
471
+ "ceal.gateway_installation_activation_code_revoke_request.v1",
472
+ "ceal.gateway_installation_activation_code_revoke_result.v1",
473
+ "ceal.gateway_installation_activation_credential.v1",
474
+ "ceal.gateway_installation_activation_request.v1",
475
+ "ceal.gateway_installation_active_state.v1",
476
+ "ceal.gateway_installation_list_result.v1",
477
+ "ceal.gateway_installation_revoke_request.v1",
478
+ "ceal.gateway_installation_revoke_result.v1",
479
+ "ceal.gateway_policy_denial.v1",
480
+ "ceal.gateway_rate_limit_policy.v1",
481
+ "ceal.gateway_refresh_audit_detail.v1",
482
+ "ceal.gateway_scoped_identity_projection.v1",
483
+ "ceal.gateway_write_receipt_readback.v1",
484
+ "ceal.gateway_write_request_receipt.v1",
485
+ "ceal.host_observation.v1",
486
+ "ceal.host_registration_request.v1",
487
+ "ceal.host_registration_result.v1",
488
+ "ceal.leased-resource-stream.v2",
489
+ "ceal.leased_consumer_attachment_stream_frame.v2",
490
+ "ceal.leased_consumer_attachment_stream_request.v2",
491
+ "ceal.leased_consumer_attachment_stream_transport.v2",
492
+ "ceal.operation_descriptor.v1",
493
+ "ceal.operation_error.v1",
494
+ "ceal.operation_failure.v1",
495
+ "ceal.operation_receipt.v1",
496
+ "ceal.operation_result.v1",
497
+ "ceal.operation_result.compact.v1",
498
+ "ceal.local_result_materialization.v1",
499
+ "ceal.local_result_root.v1",
500
+ "ceal.owner_bootstrap_exchange_request.v1",
501
+ "ceal.owner_bootstrap_exchange_result.v1",
502
+ "ceal.protocol_negotiation.v1",
503
+ "ceal.request.v1",
504
+ "ceal.request_artifact.v1",
505
+ "ceal.request_cancellation.v1",
506
+ "ceal.request_graph_revision.v1",
507
+ "ceal.request_occurrence_correlation.v1",
508
+ "ceal.request_projection.v1"
509
+ ];
510
+ var CEAL_SCHEMA_LITERAL_SET = new Set(CEAL_SCHEMA_LITERALS);
511
+
512
+ // packages/ceal-client-protocol/src/bounded-series.ts
513
+ import { join } from "node:path";
514
+ var CEAL_BOUNDED_SERIES_CATALOG = Object.freeze({
515
+ usage_record: (root) => join(root, "run-usage.jsonl"),
516
+ control_commit: (root) => join(root, "control-auto-commit.jsonl"),
517
+ engagement_signal: (root) => join(root, "runtime-state", "slack-feedback.jsonl"),
518
+ runtime_error: (root) => join(root, "runtime-state", "runtime-errors.jsonl"),
519
+ provider_retry: (root) => join(root, "observability", "provider-retry-queue", "queue.jsonl"),
520
+ turn_bridge_request: (root) => join(root, ".ceal", "turn-bridge", "requests.jsonl"),
521
+ channel_log: (root) => join(root, "log.jsonl"),
522
+ thread_run_events: (root) => join(root, "run-events.jsonl"),
523
+ bounded_store_sidecar: (root) => `${root}.jsonl`,
524
+ gateway_audit_archive: (root) => `${root}.jsonl`,
525
+ gateway_capability_audit: (root) => join(root, "capability-audit.jsonl"),
526
+ gateway_retrieval_waste_partition: (root) => `${root}.jsonl`,
527
+ gateway_access_policy_publication: (root) => join(root, "access-policy-publications.jsonl"),
528
+ gateway_event_lease_journal: (root) => `${root}.journal.jsonl`,
529
+ gateway_control_audit: (root) => `${root}.control-audits.jsonl`,
530
+ gateway_profile_connector_control_audit: (root) => `${root}.audit.jsonl`,
531
+ gateway_profile_connector_scope_audit: (root) => join(root, "profile-connector-scope-audit.jsonl"),
532
+ gateway_profile_connector_activity_scope_audit: (root) => join(root, "profile-connector-activity-scope-audit.jsonl"),
533
+ gateway_profile_connector_readiness_audit: (root) => join(root, "profile-connector-readiness.audit.jsonl"),
534
+ gateway_organization_audit_ledger: (root) => join(root, "organization-ledger.jsonl"),
535
+ gateway_personal_client_audit: (root) => join(root, "audit.jsonl"),
536
+ gateway_personal_client_access_audit: (root) => join(root, "access-audit.jsonl"),
537
+ gateway_admin_enrollment: (root) => join(root, "enrollments.jsonl"),
538
+ gateway_admin_login: (root) => join(root, "logins.jsonl"),
539
+ gateway_admin_family: (root) => join(root, "families.jsonl"),
540
+ gateway_admin_refresh_token: (root) => join(root, "refresh-tokens.jsonl"),
541
+ gateway_admin_access_token: (root) => join(root, "access-tokens.jsonl")
542
+ });
543
+
544
+ // packages/ceal-client-protocol/src/host-registration.ts
545
+ var CEAL_HOST_REGISTRATION_RESULT_KEYS = Object.freeze(["credential_generation", "host_access_token", "host_installation_ref", "host_source_ref", "ok", "registration_attempt_ref", "schema_version", "status"]);
546
+
547
+ // packages/ceal-client-protocol/src/agent-session-handoff.ts
548
+ var CEAL_AGENT_ADMISSION_PHASES = vocabulary([
549
+ "incumbent_admitted",
550
+ "incumbent_draining",
551
+ "drained",
552
+ "candidate_admitted",
553
+ "candidate_draining",
554
+ "rollback_admitted"
555
+ ]);
556
+ var CEAL_AGENT_SERVICE_SESSION_RECORD_KEYS = vocabulary([
557
+ "admission_fence",
558
+ "admission_state",
559
+ "admission_state_generation",
560
+ "bearer",
561
+ "consumer_ref",
562
+ "credential_generation",
563
+ "expires_at",
564
+ "gateway_instance",
565
+ "gateway_origin",
566
+ "gateway_serving_generation",
567
+ "issued_at",
568
+ "record_sha256",
569
+ "renew_after",
570
+ "renew_by",
571
+ "schema_version",
572
+ "session_revision"
573
+ ]);
574
+ var CEAL_AGENT_SESSION_COMMIT_KEYS = vocabulary(["attempt_ref", "expected_session_revision", "session_revision"]);
575
+
576
+ // packages/ceal-client-protocol/src/operation-next-actions.ts
577
+ var CALLER_RECOVERABLE_NEXT_ACTION_VALUES = [
578
+ "select_did_you_mean",
579
+ // The graph, not the argument list, is what the caller must change: the
580
+ // resolver that owns this input has no producing node upstream, and no edit
581
+ // to the invocation can conjure one. `resolver_dependency_absent` carried no
582
+ // remedy at all rather than borrow a word that means something else, so the
583
+ // scorer read a fully-diagnosed, caller-fixable refusal as a failed run.
584
+ "request.graph.append",
585
+ "choose_new_output_path",
586
+ "choose_new_idempotency_key",
587
+ "restart_search",
588
+ "repeat_original_arguments",
589
+ "choose_new_request_identity",
590
+ // A refusal that names the argument (invalid_argument with `property`) tells the caller exactly what to change.
591
+ "correct_argument",
592
+ // A resolver-owned input must move from caller operands into the declared
593
+ // resolver selection field.
594
+ "supply_resolver_selections",
595
+ // The graph names an upstream node whose Operation produces the resolver's
596
+ // occurrence, and it has not produced one yet. The caller runs that node
597
+ // first; the refusal used to share a code with a malformed resolver result,
598
+ // which is not fixable, so neither could carry a remedy.
599
+ "run_resolver_dependency",
600
+ // A replay carries the input the occurrence durably admitted, and this one
601
+ // carries a different one. The caller fixes it by presenting the original
602
+ // invocation, so it is a remedy; the coordinator minted the word at the
603
+ // replay guard and never declared it, which read as unguided to the scorer.
604
+ "use_original_input",
605
+ // The same mismatch on the Request binding rather than the input: the
606
+ // occurrence was admitted under one binding and the replay presents another.
607
+ "use_original_request_binding"
608
+ ];
609
+ var CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS = Object.freeze(CALLER_RECOVERABLE_NEXT_ACTION_VALUES);
610
+ var NON_REMEDY_NEXT_ACTION_VALUES = [
611
+ "await_pending_approval",
612
+ "check_gateway",
613
+ "inspect_context_store",
614
+ "inspect_gateway",
615
+ "inspect_local_cache",
616
+ // The thin client prints these on its own behalf, before or after the wire.
617
+ // They were declared only as `CealClientLocalRemedy` keys and, for two of
618
+ // them, only as Go string literals -- a second and third vocabulary for one
619
+ // thing. `CealClientLocalRemedy` derives from this list now, so the client's
620
+ // remedies cannot drift from the words the protocol knows.
621
+ "inspect_local_client",
622
+ "inspect_local_command",
623
+ "inspect_local_output",
624
+ "inspect_local_route",
625
+ "inspect_receipt",
626
+ "inspect_request",
627
+ "none",
628
+ "recover",
629
+ "reconcile",
630
+ // Reconciliation of one named occurrence, not of the deployment: a legacy
631
+ // occurrence with no admitted input commitment cannot be replayed safely and
632
+ // no edit to the call changes that. `reconcile` is the deployment-wide word.
633
+ "reconcile_occurrence",
634
+ "reduce_request_size",
635
+ "repair_or_adopt_session",
636
+ "request.effect_approval.read",
637
+ "request.run",
638
+ "retry",
639
+ // The owner -- a correlation hook, an approval hook -- is not serving right
640
+ // now. The caller changes nothing and the same call succeeds once the owner
641
+ // is back, so this is not a remedy the scorer may count as guidance.
642
+ "retry_after_owner_recovery",
643
+ "retry_same_receipt_read",
644
+ "run_file_search_again",
645
+ "select_exact_approval"
646
+ ];
647
+ var CEAL_NON_REMEDY_NEXT_ACTIONS = Object.freeze(NON_REMEDY_NEXT_ACTION_VALUES);
648
+ var DECLARED = /* @__PURE__ */ new Set([...CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS, ...CEAL_NON_REMEDY_NEXT_ACTIONS]);
649
+ var RECOVERABLE = new Set(CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS);
650
+
651
+ // packages/ceal-client-protocol/src/operation-contract-artifact.ts
652
+ var CATALOG_REVISION = new RegExp(CEAL_VERIFIED_ARTIFACT_CATALOG_REVISION_PATTERN, "u");
653
+ var SHA256 = new RegExp(CEAL_VERIFIED_ARTIFACT_DIGEST_PATTERN, "u");
654
+ var CEAL_OPERATION_CONTRACT_REQUIRED_FIELDS = Object.freeze(["input_schema", "result_schema"]);
655
+ var CEAL_OPERATION_CONTRACT_OPTIONAL_FIELDS = Object.freeze(["summary", "input_resolution"]);
656
+ var CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_JSON_SCHEMA = Object.freeze({
657
+ $schema: CEAL_JSON_SCHEMA_2020_12,
658
+ $id: "https://ceal.dev/schemas/verified-artifact-descriptor.v1.schema.json",
659
+ title: "Ceal verified artifact descriptor",
660
+ type: "object",
661
+ additionalProperties: false,
662
+ required: ["schema_version", "kind", "media_type", "byte_count", "sha256", "binding"],
663
+ properties: {
664
+ schema_version: { const: CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_SCHEMA_VERSION },
665
+ kind: { const: CEAL_VERIFIED_ARTIFACT_KIND },
666
+ media_type: { const: CEAL_VERIFIED_ARTIFACT_MEDIA_TYPE },
667
+ byte_count: { type: "integer", minimum: 1, maximum: CEAL_VERIFIED_ARTIFACT_MAX_BYTES },
668
+ sha256: { type: "string", minLength: CEAL_VERIFIED_ARTIFACT_DIGEST_LENGTH, maxLength: CEAL_VERIFIED_ARTIFACT_DIGEST_LENGTH, pattern: CEAL_VERIFIED_ARTIFACT_DIGEST_PATTERN },
669
+ binding: {
670
+ type: "object",
671
+ additionalProperties: false,
672
+ required: ["schema_version", "kind", "catalog_revision"],
673
+ properties: {
674
+ schema_version: { const: CEAL_VERIFIED_ARTIFACT_BINDING_SCHEMA_VERSION },
675
+ kind: { const: CEAL_VERIFIED_ARTIFACT_BINDING_KIND },
676
+ catalog_revision: { type: "string", minLength: CEAL_VERIFIED_ARTIFACT_CATALOG_REVISION_LENGTH, maxLength: CEAL_VERIFIED_ARTIFACT_CATALOG_REVISION_LENGTH, pattern: CEAL_VERIFIED_ARTIFACT_CATALOG_REVISION_PATTERN }
677
+ }
678
+ }
679
+ }
680
+ });
681
+
682
+ // packages/ceal-client-protocol/src/operation-occurrence.ts
683
+ var MAX_RECEIPT_REVISION = Number.MAX_SAFE_INTEGER - 1;
684
+
685
+ // packages/ceal-client-protocol/src/leased-resource-stream.ts
686
+ var CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_MAGIC = new Uint8Array([67, 69, 65, 76, 82, 83, 50, 0]);
687
+ var CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_RECORD_PREFIX_BYTES = 8;
688
+ var CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_MAX_HEADER_BYTES = 16 * 1024;
689
+ var CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_CHUNK_BYTES = 64 * 1024;
690
+ var CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_MAX_RECORD_BYTES = CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_RECORD_PREFIX_BYTES + CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_MAX_HEADER_BYTES + CEAL_LEASED_CONSUMER_ATTACHMENT_STREAM_CHUNK_BYTES;
691
+ var CEAL_ATTACHMENT_UNREAD_REASONS = vocabulary(["blocked", "unavailable", "too_large", "unsupported", "download_failed", "digest_mismatch"]);
692
+
693
+ // packages/ceal-client-protocol/src/request-validation-primitives.ts
694
+ import { createHash } from "node:crypto";
695
+ var DIGEST = /^[a-f0-9]{64}$/u;
696
+ function isCealDigest(value) {
697
+ return typeof value === "string" && DIGEST.test(value);
698
+ }
699
+ function cealRequestSha256(value) {
700
+ return createHash("sha256").update(cealCanonicalJson(value), "utf8").digest("hex");
701
+ }
702
+ function operationRecord(value, message) {
703
+ requireOperationRecord(value, message);
704
+ return value;
705
+ }
706
+ function invalid(message) {
707
+ throw new TypeError(message);
708
+ }
709
+ function requirePrefixedRef(value, prefix, message) {
710
+ if (typeof value !== "string" || !SAFE_REF.test(value) || !value.startsWith(prefix)) invalid(message);
711
+ }
712
+
713
+ // packages/ceal-client-protocol/src/request-authority.ts
714
+ var CEAL_REQUEST_SCHEMA_VERSION = "ceal.request.v1";
715
+ var CEAL_REQUEST_ARTIFACT_OWNERS = vocabulary(["gateway", "host", "connector"]);
716
+ var CEAL_REQUEST_HOST_BINDING_KEYS = vocabulary(["prompt_ref", "host_session_ref", "host_turn_ref", "host_source_ref"]);
717
+ var CEAL_REQUEST_ARTIFACT_RETENTION_CLASSES = vocabulary(["request", "source", "result"]);
718
+ var CANCELLATION_STATES = vocabulary(["requested", "cancelled"]);
719
+ var CEAL_REQUEST_KEYS = Object.freeze(["schema_version", "ceal_request_ref", "created_at", "authority", "prompt_ref", "host_session_ref", "host_turn_ref", "host_source_ref"]);
720
+ var CEAL_REQUEST_JSON_SCHEMA = {
721
+ type: "object",
722
+ maxProperties: 9,
723
+ additionalProperties: false,
724
+ properties: {
725
+ schema_version: { type: "string", const: CEAL_REQUEST_SCHEMA_VERSION, maxLength: 32 },
726
+ ceal_request_ref: { type: "string", minLength: 1, maxLength: 128, pattern: "^ceal-request:[A-Za-z0-9][A-Za-z0-9._:-]{0,114}$" },
727
+ created_at: { type: "string", minLength: 1, maxLength: 64 },
728
+ authority: {
729
+ type: "object",
730
+ maxProperties: 5,
731
+ additionalProperties: false,
732
+ properties: {
733
+ instance_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
734
+ profile_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
735
+ principal_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
736
+ execution_subject_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
737
+ authority_revision_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source }
738
+ },
739
+ required: ["instance_ref", "profile_ref", "principal_ref", "execution_subject_ref", "authority_revision_ref"]
740
+ },
741
+ prompt_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
742
+ host_session_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
743
+ host_turn_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
744
+ host_input_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
745
+ host_source_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source }
746
+ },
747
+ required: CEAL_REQUEST_KEYS
748
+ };
749
+
750
+ // packages/ceal-client-protocol/src/request-operands.ts
751
+ var CEAL_REQUEST_MAX_RESOLVER_SELECTIONS = 128;
752
+ var CEAL_REQUEST_MAX_SELECTOR_PROPERTIES = 16;
753
+ var CEAL_REQUEST_MAX_SELECTOR_VALUE_LENGTH = 1024;
754
+ var CEAL_REQUEST_RESOLVER_SELECTION_JSON_SCHEMA = {
755
+ type: "object",
756
+ maxProperties: 2,
757
+ additionalProperties: false,
758
+ properties: {
759
+ property: { type: "string", minLength: 1, maxLength: 128 },
760
+ selectors: {
761
+ type: "object",
762
+ maxProperties: CEAL_REQUEST_MAX_SELECTOR_PROPERTIES,
763
+ properties: {},
764
+ additionalProperties: { type: "string", minLength: 1, maxLength: CEAL_REQUEST_MAX_SELECTOR_VALUE_LENGTH }
765
+ }
766
+ },
767
+ required: ["property", "selectors"]
768
+ };
769
+
770
+ // packages/ceal-client-protocol/src/request-graph.ts
771
+ var CEAL_REQUEST_MAX_GRAPH_NODES = 128;
772
+
773
+ // packages/ceal-client-protocol/src/request-run.ts
774
+ var CEAL_REQUEST_NODE_STANDING_OCCURRENCE_SCHEMA_VERSION = "ceal.request_node_standing_occurrence.v1";
775
+ var CEAL_REQUEST_RUN_BATCH_SCHEMA_VERSION = "ceal.request_run_batch.v3";
776
+ var REQUEST_ACTION_SAFE_REF_SCHEMA = { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source };
777
+ var REQUEST_ACTION_DIGEST_SCHEMA = { type: "string", minLength: 64, maxLength: 64, pattern: "^[a-f0-9]{64}$" };
778
+ var REQUEST_NODE_STANDING_OCCURRENCE_SCHEMA = {
779
+ type: "object",
780
+ maxProperties: 9,
781
+ additionalProperties: false,
782
+ properties: {
783
+ schema_version: { type: "string", const: CEAL_REQUEST_NODE_STANDING_OCCURRENCE_SCHEMA_VERSION, maxLength: 64 },
784
+ node_ref: REQUEST_ACTION_SAFE_REF_SCHEMA,
785
+ operation_id: REQUEST_ACTION_SAFE_REF_SCHEMA,
786
+ correlation_ref: REQUEST_ACTION_SAFE_REF_SCHEMA,
787
+ occurrence_ref: REQUEST_ACTION_SAFE_REF_SCHEMA,
788
+ graph_revision: { type: "integer", minimum: 1, maximum: Number.MAX_SAFE_INTEGER },
789
+ graph_revision_digest: REQUEST_ACTION_DIGEST_SCHEMA,
790
+ admitted_input_sha256: REQUEST_ACTION_DIGEST_SCHEMA,
791
+ reason: { type: "string", minLength: 1, maxLength: 1024 }
792
+ },
793
+ required: ["schema_version", "node_ref", "operation_id", "correlation_ref", "occurrence_ref", "graph_revision", "graph_revision_digest", "admitted_input_sha256", "reason"]
794
+ };
795
+ var REQUEST_EXECUTION_PREPARE_REFUSAL_SCHEMA = {
796
+ type: "object",
797
+ additionalProperties: false,
798
+ maxProperties: 9,
799
+ properties: {
800
+ schema_version: { type: "string", const: CEAL_OPERATION_ERROR_SCHEMA_VERSION, maxLength: 64 },
801
+ code: REQUEST_ACTION_SAFE_REF_SCHEMA,
802
+ message: { type: "string", minLength: 1, maxLength: 2048 },
803
+ property: { type: "string", minLength: 1, maxLength: 256 },
804
+ next_action: REQUEST_ACTION_SAFE_REF_SCHEMA,
805
+ retryable: { type: "boolean" },
806
+ repaired_input: {},
807
+ unrepaired_pointers: { type: "array", maxItems: 128, items: { type: "string", minLength: 1, maxLength: 256 } },
808
+ provider_handoff: { type: "string", const: "not_offered", maxLength: 32 }
809
+ },
810
+ required: ["schema_version", "code", "message", "next_action", "retryable"]
811
+ };
812
+ var CEAL_REQUEST_EXECUTION_ORDERS = vocabulary(["graph_dependency", "caller"]);
813
+ var CEAL_REQUEST_CALL_BUDGET_JSON_SCHEMA = {
814
+ type: "object",
815
+ additionalProperties: false,
816
+ maxProperties: 2,
817
+ properties: {
818
+ gateway_calls_so_far: { type: "integer", minimum: 1, maximum: Number.MAX_SAFE_INTEGER },
819
+ floor_for_this_graph: { type: "integer", minimum: 1, maximum: Number.MAX_SAFE_INTEGER }
820
+ },
821
+ required: ["gateway_calls_so_far", "floor_for_this_graph"]
822
+ };
823
+ var CEAL_REQUEST_RUN_BATCH_JSON_SCHEMA = {
824
+ type: "object",
825
+ additionalProperties: false,
826
+ maxProperties: 5,
827
+ properties: {
828
+ schema_version: { type: "string", const: CEAL_REQUEST_RUN_BATCH_SCHEMA_VERSION, maxLength: 64 },
829
+ order: { enum: [...CEAL_REQUEST_EXECUTION_ORDERS] },
830
+ nodes: {
831
+ type: "array",
832
+ minItems: 1,
833
+ maxItems: CEAL_REQUEST_MAX_GRAPH_NODES,
834
+ items: {
835
+ // The runtime validator owns "exactly one of a result, a refusal
836
+ // and a standing run". The result envelope already names the
837
+ // Operation that ran.
838
+ type: "object",
839
+ additionalProperties: false,
840
+ maxProperties: 4,
841
+ properties: { node_ref: REQUEST_ACTION_SAFE_REF_SCHEMA, result: {}, refusal: REQUEST_EXECUTION_PREPARE_REFUSAL_SCHEMA, standing: REQUEST_ACTION_SAFE_REF_SCHEMA },
842
+ required: ["node_ref"]
843
+ }
844
+ },
845
+ standing_reading: { type: "string", minLength: 1, maxLength: 512 },
846
+ call_budget: CEAL_REQUEST_CALL_BUDGET_JSON_SCHEMA
847
+ },
848
+ required: ["schema_version", "order", "nodes", "call_budget"]
849
+ };
850
+
851
+ // packages/ceal-client-protocol/src/host-observation.ts
852
+ var CEAL_HOST_OBSERVATION_REF_PREFIX = "host-observation:";
853
+ function validateCealHostObservationDraft(value) {
854
+ const record6 = operationRecord(value, "Ceal Host observation draft is invalid.");
855
+ requirePrefixedRef(record6.observation_ref, CEAL_HOST_OBSERVATION_REF_PREFIX, "Ceal Host observation reference is invalid.");
856
+ requireClosedValue(record6.observation_kind, CEAL_HOST_OBSERVATION_KINDS, "Ceal Host observation kind is invalid.");
857
+ requireIsoTimestamp(record6.observed_at, "Ceal Host observation time is invalid.");
858
+ assertHostObservationValue(record6.value, record6.observation_kind);
859
+ }
860
+ var CEAL_REQUEST_MAX_OBSERVATION_VALUE_BYTES = 64 * 1024;
861
+ var CEAL_HOST_OBSERVATION_KINDS = vocabulary(["prompt", "session", "turn", "model", "token", "cost", "timing"]);
862
+ function isCealHostPromptObservationValue(value) {
863
+ return isOperationRecord(value) && Object.keys(value).length === 1 && isCealDigest(value.body_sha256);
864
+ }
865
+ var HOST_RESERVED_KEY = /^(?:admission|approval|audit|authorization|cancellation|capability|effect|grant|occurrence|operation|policy|profile|provider_readback|receipt|reconciliation|replay|target|write_request)(?:_|$)/iu;
866
+ function assertHostObservationValue(value, kind) {
867
+ if (value === void 0) invalid("Ceal Host observation value is invalid.");
868
+ if (kind === "prompt" && !isCealHostPromptObservationValue(value)) invalid("Ceal Host prompt observation must contain only its body digest.");
869
+ assertSafeJsonValue(value, { forbidAuthorityKeys: true, maxNodes: 512 });
870
+ if (byteLength(JSON.stringify(value) ?? "") > CEAL_REQUEST_MAX_OBSERVATION_VALUE_BYTES) invalid("Ceal Host observation value is oversized.");
871
+ inspectHostKeys(value);
872
+ }
873
+ function inspectHostKeys(value) {
874
+ if (Array.isArray(value)) {
875
+ for (const entry2 of value) inspectHostKeys(entry2);
876
+ return;
877
+ }
878
+ if (value === null || typeof value !== "object") return;
879
+ for (const [key, child] of Object.entries(value)) {
880
+ if (HOST_RESERVED_KEY.test(key)) invalid("Ceal Host observation cannot restate Gateway-owned facts.");
881
+ inspectHostKeys(child);
882
+ }
883
+ }
884
+
885
+ // packages/ceal-client-protocol/src/request-effect-approval.ts
886
+ var CEAL_EFFECT_APPROVAL_DECISION_CHECK_PHRASES = Object.freeze([
887
+ "observed after this approval was raised and before it expires",
888
+ "from this same Host session and Host source",
889
+ "not the Host input that opened the Request",
890
+ "an input that has decided no other approval"
891
+ ]);
892
+ var CEAL_EFFECT_APPROVAL_DECISION_INSTRUCTION = `Submit exactly one phrase below in a Host input ${CEAL_EFFECT_APPROVAL_DECISION_CHECK_PHRASES.join(", ")}.`;
893
+
894
+ // packages/ceal-client-protocol/src/request-projection.ts
895
+ var CEAL_REQUEST_STATUSES = vocabulary(["pending", "partial", "completed", "cancelled", "failed", "unknown_effect", "reconciled", "incomplete", "contradiction"]);
896
+ var OWNER_WRITE_STATES = Object.freeze(["attempt_started", "provider_acknowledged", "verified", "outcome_unknown", "reconciled"]);
897
+ var OWNER_EFFECT_STATES = Object.freeze(["none", "applied", "failed", "unknown", "reconciled"]);
898
+ var OWNER_RECEIPT_STATES = Object.freeze(["pending", "available", "failed", "unknown", "reconciled"]);
899
+
900
+ // packages/ceal-client-protocol/src/request-graph-readiness.ts
901
+ var REQUEST_GRAPH_PRODUCER_TO_APPEND_SCHEMA = {
902
+ type: "object",
903
+ maxProperties: 4,
904
+ additionalProperties: false,
905
+ properties: {
906
+ operation_id: { type: "string", minLength: 1, maxLength: 128 },
907
+ edge_to_node_ref: { type: "string", minLength: 1, maxLength: 128 },
908
+ edge_from_node_refs: { type: "array", minItems: 1, maxItems: CEAL_REQUEST_MAX_GRAPH_NODES, items: { type: "string", minLength: 1, maxLength: 128 } },
909
+ remedy: { type: "string", minLength: 1, maxLength: 512 }
910
+ },
911
+ required: ["operation_id", "edge_to_node_ref", "remedy"]
912
+ };
913
+ var REQUEST_GRAPH_RESOLVER_CONSUMERS_SCHEMA = {
914
+ type: "object",
915
+ maxProperties: 2,
916
+ additionalProperties: false,
917
+ properties: {
918
+ consumer_node_refs: { type: "array", minItems: 1, maxItems: CEAL_REQUEST_MAX_GRAPH_NODES, items: { type: "string", minLength: 1, maxLength: 128 } },
919
+ remedy: { type: "string", minLength: 1, maxLength: 512 }
920
+ },
921
+ required: ["consumer_node_refs", "remedy"]
922
+ };
923
+ var REQUEST_GRAPH_RESOLVER_REUSE_SCHEMA = {
924
+ type: "object",
925
+ maxProperties: 3,
926
+ additionalProperties: false,
927
+ properties: {
928
+ reuse_node_ref: { type: "string", minLength: 1, maxLength: 128 },
929
+ consumer_node_refs: { type: "array", maxItems: CEAL_REQUEST_MAX_GRAPH_NODES, items: { type: "string", minLength: 1, maxLength: 128 } },
930
+ remedy: { type: "string", minLength: 1, maxLength: 512 }
931
+ },
932
+ required: ["reuse_node_ref", "consumer_node_refs", "remedy"]
933
+ };
934
+ var RESOLVER_OWNED_INPUT_SCHEMA = {
935
+ type: "object",
936
+ maxProperties: 5,
937
+ additionalProperties: false,
938
+ properties: {
939
+ property: { type: "string", minLength: 1, maxLength: 128 },
940
+ resolver_operation_id: { type: "string", minLength: 1, maxLength: 128 },
941
+ resolver_selection_template: CEAL_REQUEST_RESOLVER_SELECTION_JSON_SCHEMA,
942
+ producing_node_refs: { type: "array", maxItems: CEAL_REQUEST_MAX_RESOLVER_SELECTIONS, items: { type: "string", minLength: 1, maxLength: 128 } },
943
+ append_producer: REQUEST_GRAPH_PRODUCER_TO_APPEND_SCHEMA
944
+ },
945
+ required: ["property", "resolver_operation_id", "producing_node_refs"]
946
+ };
947
+ var USER_OPERANDS_TEMPLATE_SCHEMA = {
948
+ type: "object",
949
+ maxProperties: 2,
950
+ additionalProperties: false,
951
+ properties: {
952
+ required_properties: { type: "array", maxItems: MAX_OPERATION_INPUT_RESOLVER_BINDINGS, items: { type: "string", minLength: 1, maxLength: 128 } },
953
+ operands: { type: "object", properties: {}, maxProperties: MAX_OPERATION_INPUT_RESOLVER_BINDINGS, additionalProperties: {} }
954
+ },
955
+ required: ["required_properties", "operands"]
956
+ };
957
+ var CEAL_REQUEST_GRAPH_NODE_PREPARE_READINESS_JSON_SCHEMA = {
958
+ type: "object",
959
+ maxProperties: 9,
960
+ additionalProperties: false,
961
+ properties: {
962
+ node_ref: { type: "string", minLength: 1, maxLength: 128 },
963
+ operation_id: { type: "string", minLength: 1, maxLength: 128 },
964
+ resolver_owned: { type: "array", maxItems: MAX_OPERATION_INPUT_RESOLVER_BINDINGS, items: RESOLVER_OWNED_INPUT_SCHEMA },
965
+ gateway_derived: { type: "array", maxItems: MAX_OPERATION_INPUT_RESOLVER_BINDINGS, items: { type: "string", minLength: 1, maxLength: 128 } },
966
+ result_bound: { type: "array", maxItems: MAX_OPERATION_INPUT_RESOLVER_BINDINGS, items: { type: "string", minLength: 1, maxLength: 128 } },
967
+ user_operands_template: { type: "array", maxItems: CEAL_OPERATION_JSON_SCHEMA_BUDGET.max_alternatives, items: USER_OPERANDS_TEMPLATE_SCHEMA },
968
+ unfed_resolver: REQUEST_GRAPH_RESOLVER_CONSUMERS_SCHEMA,
969
+ redundant_resolver: REQUEST_GRAPH_RESOLVER_REUSE_SCHEMA,
970
+ standing_occurrence: REQUEST_NODE_STANDING_OCCURRENCE_SCHEMA
971
+ },
972
+ required: ["node_ref", "operation_id", "resolver_owned", "gateway_derived"]
973
+ };
974
+
975
+ // packages/ceal-client-protocol/src/host-invocation-authentication.ts
976
+ var CEAL_HOST_INVOCATION_AUTHENTICATION_RESULT_SCHEMA = "ceal.host_invocation_authentication_result.v1";
977
+ var CEAL_HOST_INVOCATION_CONTEXT_PATH = "/api/ceal/v2/host-invocation-context";
978
+ var CEAL_HOST_CLIENT_NONCE_PATTERN = /^[A-Za-z0-9_-]{43}$/u;
979
+ var CEAL_HOST_CONTEXT_TOKEN_PATTERN = /^ceal_context_[A-Za-z0-9_-]{43}$/u;
980
+ function decodeCealHostInvocationAuthenticationResult(value, now = /* @__PURE__ */ new Date()) {
981
+ if (!isCealJsonRecord(value) || !exactKeys(value, ["schema_version", "context_token", "expires_at"]) || value.schema_version !== CEAL_HOST_INVOCATION_AUTHENTICATION_RESULT_SCHEMA || typeof value.context_token !== "string" || !CEAL_HOST_CONTEXT_TOKEN_PATTERN.test(value.context_token) || typeof value.expires_at !== "string" || !validFutureTimestamp(value.expires_at, now)) {
982
+ throw new TypeError("The Host invocation authentication result is invalid.");
983
+ }
984
+ return Object.freeze({ schema_version: CEAL_HOST_INVOCATION_AUTHENTICATION_RESULT_SCHEMA, context_token: value.context_token, expires_at: value.expires_at });
985
+ }
986
+ function validFutureTimestamp(value, now) {
987
+ const timestamp3 = Date.parse(value);
988
+ return Number.isFinite(timestamp3) && new Date(timestamp3).toISOString() === value && timestamp3 > now.getTime();
989
+ }
990
+ function exactKeys(value, expected) {
991
+ const keys = Object.keys(value);
992
+ return keys.length === expected.length && expected.every((key) => Object.hasOwn(value, key));
993
+ }
994
+
995
+ // packages/ceal-client-protocol/src/client-result-materialization.ts
996
+ var REQUIRED_FIELDS = Object.freeze(["schema_version", "operation_id", "local_path", "content_json_pointer", "size_bytes", "sha256", "read_argv"]);
997
+ var FIELDS = /* @__PURE__ */ new Set([...REQUIRED_FIELDS, "local_result_root", "model_disclosure"]);
998
+
999
+ // packages/ceal-client-protocol/src/conversation-contracts.ts
1000
+ var CEAL_APPROVAL_POLICY_KINDS = vocabulary(["requester_only", "named_users", "role_based"]);
1001
+ var CEAL_APPROVAL_TARGET_KINDS = vocabulary([
1002
+ "repo_change",
1003
+ "investigation",
1004
+ "skill_creation",
1005
+ "command_creation",
1006
+ "connector_creation",
1007
+ "generic"
1008
+ ]);
1009
+ var CEAL_PROGRESS_PHASES = vocabulary(["request_review", "information_gathering", "work_execution", "result_check"]);
1010
+
1011
+ // packages/ceal-client-protocol/src/gateway-cache-origin-validation.ts
1012
+ var CEAL_MAX_CACHE_ORIGIN_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
1013
+
1014
+ // packages/ceal-client-protocol/src/gateway-write-contract.ts
1015
+ var CEAL_GATEWAY_WRITE_CONTRACT_CLOSED_VOCABULARIES = Object.freeze({
1016
+ idempotency: CEAL_WRITE_IDEMPOTENCY_POSTURES,
1017
+ provider_readback: CEAL_WRITE_PROVIDER_READBACK_POSTURES,
1018
+ dry_run: Object.freeze(["supported", "unsupported"]),
1019
+ attribution: CEAL_WRITE_ATTRIBUTIONS,
1020
+ provenance_binding: Object.freeze(["gateway_attested_requester_event_v1"])
1021
+ });
1022
+ var REQUIRED_KEYS = Object.freeze(["side_effect_class", "idempotency", "provider_readback"]);
1023
+
1024
+ // packages/ceal-client-protocol/src/gateway-proof-claims.ts
1025
+ var CEAL_GATEWAY_PROOF_AXES = Object.freeze(["host_decision", "provider_execution", "production_audit"]);
1026
+ var CEAL_GATEWAY_PROOF_AXIS_NON_CLAIMS = Object.freeze({
1027
+ host_decision: null,
1028
+ provider_execution: "provider_execution_not_reached",
1029
+ production_audit: "production_audit_not_reached"
1030
+ });
1031
+ var CEAL_PROOF_LEVELS = vocabulary(["surface", "readiness", "worker_queued", "host_decision", "provider_roundtrip"]);
1032
+ var CEAL_GATEWAY_HOST_NON_CLAIM_ORDER = Object.freeze(["provider_execution_not_reached", "target_authorization_not_observed", "production_audit_not_reached"]);
1033
+ var CEAL_GATEWAY_ANNOUNCEMENT_POLICY_NON_CLAIMS = vocabulary([
1034
+ "policy_projection_does_not_authorize",
1035
+ "provider_roundtrip_not_established_by_discovery",
1036
+ "target_specific_scope_not_declared"
1037
+ ]);
1038
+
1039
+ // packages/ceal-client-protocol/src/gateway-discovery-response-validation.ts
1040
+ var ANNOUNCEMENT_POLICY_CAPABILITY_BINDINGS = Object.freeze({
1041
+ "github.repository.get": [{ effect: "read", scopeStatementKind: "github_app_installation_repositories", providerAuthorityKind: "github_app" }],
1042
+ "collection.search": [{ effect: "read", scopeStatementKind: "github_app_installation_repositories", providerAuthorityKind: "github_app" }],
1043
+ "github.issue.get": [{ effect: "read", scopeStatementKind: "github_app_installation_repositories", providerAuthorityKind: "github_app" }],
1044
+ "github.pull_request.get": [{ effect: "read", scopeStatementKind: "github_app_installation_repositories", providerAuthorityKind: "github_app" }],
1045
+ "github.workflow_run.get": [{ effect: "read", scopeStatementKind: "github_app_installation_repositories", providerAuthorityKind: "github_app" }],
1046
+ "message.search": [{ effect: "read", scopeStatementKind: "slack_public_app_member_channels_only", providerAuthorityKind: "slack_app" }],
1047
+ "message.get": [{ effect: "read", scopeStatementKind: "slack_public_app_member_channels_only", providerAuthorityKind: "slack_app" }],
1048
+ "resource.resolve": [
1049
+ { effect: "read", scopeStatementKind: "slack_public_app_member_channels_only", providerAuthorityKind: "slack_app" },
1050
+ { effect: "read", scopeStatementKind: "notion_connected_logical_area", providerAuthorityKind: "notion_integration" }
1051
+ ],
1052
+ "conversation.thread.get": [{ effect: "read", scopeStatementKind: "slack_public_app_member_channels_only", providerAuthorityKind: "slack_app" }],
1053
+ "notion.search": [{ effect: "read", scopeStatementKind: "notion_connected_logical_area", providerAuthorityKind: "notion_integration" }],
1054
+ "notion.page.get": [{ effect: "read", scopeStatementKind: "notion_connected_logical_area", providerAuthorityKind: "notion_integration" }],
1055
+ "calendar.availability": [{ effect: "read", scopeStatementKind: "google_workspace_calendar_read_only", providerAuthorityKind: "google_service_account" }],
1056
+ "calendar.event.search": [{ effect: "read", scopeStatementKind: "google_workspace_calendar_read_only", providerAuthorityKind: "google_service_account" }],
1057
+ "calendar.event.get": [{ effect: "read", scopeStatementKind: "google_workspace_calendar_read_only", providerAuthorityKind: "google_service_account" }],
1058
+ "file.search": [{ effect: "read", scopeStatementKind: "google_workspace_ceal_drive_or_direct_share_metadata", providerAuthorityKind: "google_service_account" }],
1059
+ "sheets.values.read": [{ effect: "read", scopeStatementKind: "google_workspace_ceal_drive_or_direct_share_sheet_ranges", providerAuthorityKind: "google_service_account" }],
1060
+ "sheets.tabs.list": [{ effect: "read", scopeStatementKind: "google_workspace_ceal_drive_or_direct_share_sheet_tabs", providerAuthorityKind: "google_service_account" }],
1061
+ "sheets.values.update": [{ effect: "write", scopeStatementKind: "google_workspace_ceal_drive_or_direct_share_editable_sheet_ranges", providerAuthorityKind: "google_service_account" }],
1062
+ "sheets.values.clear": [{ effect: "write", scopeStatementKind: "google_workspace_ceal_drive_or_direct_share_editable_sheet_clear_ranges", providerAuthorityKind: "google_service_account" }]
1063
+ });
1064
+ var ANNOUNCEMENT_SCOPE_STATEMENTS = Object.freeze({
1065
+ github_app_installation_repositories: "Repositories in the installed GitHub App installation.",
1066
+ slack_public_app_member_channels_only: "Public channels where the installed Slack app is a member; private channels, direct messages, multi-person direct messages, and requester membership are not declared by this connector.",
1067
+ notion_connected_logical_area: "Connected Notion logical area under provider-enforced sharing; descendant inventory is not declared.",
1068
+ google_workspace_calendar_read_only: "Approved Calendar availability and event reads only; Calendar mutation is not declared.",
1069
+ google_workspace_ceal_drive_or_direct_share_metadata: "Metadata search for files in the organization shared drive named Ceal Drive and files directly shared with the provider application; file-content read and mutation are not declared.",
1070
+ google_workspace_ceal_drive_or_direct_share_sheet_ranges: "Bounded values reads from governed Google Sheets in the organization shared drive named Ceal Drive and directly shared files; file mutation is not declared.",
1071
+ google_workspace_ceal_drive_or_direct_share_editable_sheet_ranges: "Bounded values updates in governed editable Google Sheets in the organization shared drive named Ceal Drive and directly shared files; Docs, Slides, and other Drive file mutation are not declared.",
1072
+ google_workspace_ceal_drive_or_direct_share_editable_sheet_clear_ranges: "Bounded values clears in governed editable Google Sheets in the organization shared drive named Ceal Drive and directly shared files; Docs, Slides, and other Drive file mutation are not declared."
1073
+ });
1074
+
1075
+ // packages/ceal-client-protocol/src/gateway-write-identity.ts
1076
+ var CEAL_GATEWAY_WRITE_IDENTITY_ROLES = Object.freeze(["replay_identity", "lookup_handle", "collision_evidence"]);
1077
+ var CEAL_GATEWAY_WRITE_IDENTITY_FIELDS = Object.freeze({
1078
+ replay_identity: "idempotency_claim_sha256",
1079
+ lookup_handle: "write_request_sha256",
1080
+ collision_evidence: "normalized_mutation_sha256"
1081
+ });
1082
+
1083
+ // packages/ceal-client-protocol/src/gateway-scoped-identity-projection-validation.ts
1084
+ var PROJECTION_REVISION_KEYS = Object.freeze(["graph_revision", "subject_key_revision", "projection_revision"]);
1085
+
1086
+ // packages/ceal-client-protocol/src/protocol-negotiation.ts
1087
+ var CEAL_SUPPORTED_GATEWAY_PROTOCOL_RANGE = Object.freeze({
1088
+ minimum: CEAL_PROTOCOL_VERSION,
1089
+ maximum: CEAL_PROTOCOL_VERSION
1090
+ });
1091
+
1092
+ // packages/ceal-client-protocol/src/admin-projection-vocabulary.ts
1093
+ var ADMIN_PROJECTION_STATES = vocabulary(["ready", "empty", "partial", "unknown"]);
1094
+ var ADMIN_VIEW_KINDS = vocabulary(["request_detail", "resource_access_timeline", "weekly_usage"]);
1095
+ var ADMIN_GAP_KINDS = vocabulary(["unknown", "unavailable", "partial"]);
1096
+ var ADMIN_UNAVAILABLE_REASONS = vocabulary([
1097
+ "not_recorded",
1098
+ "legacy",
1099
+ "invalid_observation",
1100
+ "redacted",
1101
+ "owner_unavailable",
1102
+ "unit_unknown",
1103
+ "retention_gap",
1104
+ "source_owner_limit"
1105
+ ]);
1106
+ var ADMIN_SOURCE_OWNERS = vocabulary([
1107
+ "request",
1108
+ "operation",
1109
+ "authority",
1110
+ "occurrence",
1111
+ "approval",
1112
+ "audit",
1113
+ "provider_readback",
1114
+ "host_observation",
1115
+ "person",
1116
+ "resource",
1117
+ "prompt",
1118
+ "usage"
1119
+ ]);
1120
+ var ADMIN_COMPLETENESS_STATES = vocabulary(["complete", "partial", "unknown"]);
1121
+ var ADMIN_OPERATION_OUTCOMES = vocabulary(["completed", "failed", "denied", "cancelled", "unknown"]);
1122
+ var ADMIN_APPROVAL_DISPOSITIONS = CEAL_OPERATION_APPROVAL_DISPOSITIONS;
1123
+ var ADMIN_APPROVAL_POSTURES = vocabulary([...ADMIN_APPROVAL_DISPOSITIONS, "not_applicable"]);
1124
+ var ADMIN_LINEAGE_NODE_KINDS = vocabulary(["source_read", "synthesis_preview", "approval", "effect", "readback"]);
1125
+
1126
+ // packages/ceal-client-protocol/src/actor-kind.ts
1127
+ var CEAL_ACTOR_KINDS = vocabulary(["human", "bot", "app", "unknown"]);
1128
+
1129
+ // packages/ceal-client-protocol/src/leased-consumer-vocabulary.ts
1130
+ var CEAL_TERMINAL_DISPOSITIONS = vocabulary(["completed", "failed", "cancelled"]);
1131
+ var CEAL_LEASE_DISPOSITIONS = vocabulary([...CEAL_TERMINAL_DISPOSITIONS, "deferred"]);
1132
+ var CEAL_AUTOMATIC_FEEDBACK_INTENTS = vocabulary(["reaction", "progress_start", "progress_finish"]);
1133
+ var CEAL_LEASED_MESSAGE_DELIVERY_CAPABILITY_IDS = vocabulary(["message.create", "message.update", "message.delete"]);
1134
+ var CEAL_REPOSITORY_VISIBILITIES = vocabulary(["public", "private", "internal"]);
1135
+ var CEAL_RESULT_DELIVERY_OFFERS = vocabulary(["pending", "offered", "transport_lost"]);
1136
+ var CEAL_RESULT_DELIVERY_STATES = vocabulary(["unavailable", ...CEAL_RESULT_DELIVERY_OFFERS]);
1137
+ var CEAL_PROVIDER_OUTCOMES = vocabulary(["not_attempted", "outcome_unknown", "verified"]);
1138
+ var CEAL_ACTIVITY_GAP_CODES = vocabulary([
1139
+ "provider_page_budget",
1140
+ "related_item_budget",
1141
+ "provider_cursor_unavailable",
1142
+ "malformed_provider_page",
1143
+ "visibility_incomplete",
1144
+ "unsupported_event_kind"
1145
+ ]);
1146
+ var CEAL_ACTIVITY_COVERAGE_STATUSES = vocabulary(["complete_for_target", "continuation_required", "blocked"]);
1147
+ var CEAL_ACTIVITY_EVENT_KINDS = vocabulary([
1148
+ "slack.message",
1149
+ "slack.reply",
1150
+ "github.commit.authored",
1151
+ "github.issue.opened",
1152
+ "github.pull_request.opened",
1153
+ "github.review.submitted",
1154
+ "github.issue_comment.created",
1155
+ "github.review_comment.created",
1156
+ "calendar.organized",
1157
+ "calendar.accepted_invite",
1158
+ "calendar.recorded"
1159
+ ]);
1160
+ var CEAL_ACTIVITY_TIMESTAMP_BASES = vocabulary([
1161
+ "message_created",
1162
+ "commit_authored",
1163
+ "resource_created",
1164
+ "review_submitted",
1165
+ "comment_created",
1166
+ "event_start",
1167
+ "all_day_start"
1168
+ ]);
1169
+ var CEAL_ARTIFACT_STAGE_TERMINALS = vocabulary(["chunk_accepted", "artifact_ready", "idempotency_replayed"]);
1170
+ var CEAL_READ_ITEM_KINDS = vocabulary(["conversation", "identity", "usergroup", "message", "file", "document"]);
1171
+ var CEAL_RESOURCE_RESOLVE_KINDS = vocabulary(["conversation", "identity", "usergroup", "permalink"]);
1172
+ var CEAL_OPAQUE_HANDLE_KINDS = vocabulary(["target", "message", "thread", "artifact", "document", "object"]);
1173
+ var CEAL_WRITE_OBJECT_KINDS = vocabulary(["document", "comment", "cell_range"]);
1174
+ var CEAL_CONVERSATION_KINDS = vocabulary(["channel", "dm", "group"]);
1175
+ var CEAL_FILE_TYPE_FAMILIES = vocabulary(["all", "image", "pdf"]);
1176
+ var CEAL_GITHUB_ISSUE_STATES = vocabulary(["open", "closed", "all"]);
1177
+ var CEAL_NOTION_UPDATABLE_BLOCK_TYPES = vocabulary([
1178
+ "paragraph",
1179
+ "heading_1",
1180
+ "heading_2",
1181
+ "heading_3",
1182
+ "bulleted_list_item",
1183
+ "numbered_list_item",
1184
+ "to_do",
1185
+ "code"
1186
+ ]);
1187
+ var CEAL_NOTION_NEUTRAL_TYPES = vocabulary([
1188
+ "text",
1189
+ "number",
1190
+ "boolean",
1191
+ "date",
1192
+ "select",
1193
+ "multi_select",
1194
+ "people",
1195
+ "url",
1196
+ "email",
1197
+ "phone",
1198
+ "unsupported"
1199
+ ]);
1200
+ var CEAL_NOTION_IDENTITY_GAP_REASONS = vocabulary([
1201
+ "identity_unavailable",
1202
+ "identity_stale",
1203
+ "identity_ambiguous",
1204
+ "identity_revoked",
1205
+ "identity_unlinked"
1206
+ ]);
1207
+ var CEAL_NOTION_STRING_VALUE_TYPES = vocabulary(["text", "select", "url", "email", "phone"]);
1208
+ var CEAL_UNREAD_REASONS = vocabulary(["blocked", "unavailable", "too_large", "unsupported", "download_failed", "permission_denied"]);
1209
+ var CEAL_PLAN_ITEM_STATUSES = vocabulary(["pending", "active", "completed"]);
1210
+ var CEAL_FINAL_PRESENTATION_INTENTS = vocabulary(["final", "stop", "transient_notice"]);
1211
+ var CEAL_PRESENTATION_INTENTS = vocabulary(["progress", ...CEAL_FINAL_PRESENTATION_INTENTS]);
1212
+
1213
+ // packages/ceal-client-protocol/src/personal-client-vocabulary.ts
1214
+ var CEAL_PERSONAL_CLIENT_BINDING_KEYS = vocabulary([
1215
+ "profile_ref",
1216
+ "membership_ref",
1217
+ "registration_ref",
1218
+ "client_ref",
1219
+ "subject_ref",
1220
+ "instance_ref"
1221
+ ]);
1222
+ var CEAL_ENROLLMENT_FAILURE_CODES = vocabulary(["enrollment_invalid", "enrollment_expired", "enrollment_used"]);
1223
+ var CEAL_REFRESH_FAILURE_CODES = vocabulary([
1224
+ "refresh_invalid",
1225
+ "refresh_expired",
1226
+ "refresh_inactive",
1227
+ "refresh_replayed",
1228
+ "refresh_revoked",
1229
+ "authority_replaced",
1230
+ "refresh_recovery_unavailable"
1231
+ ]);
1232
+
1233
+ // packages/ceal-client-protocol/src/device-enrollment.ts
1234
+ var CEAL_DEVICE_ENROLLMENT_POLL_FAILURE_CODES = Object.freeze(["unsupported_feature", "recovery_required", "expired"]);
1235
+ var POLL_RESULT_KEYS = Object.freeze(["retry_after_ms", "schema_version", "status"]);
1236
+
1237
+ // packages/ceal-client-protocol/src/personal-client-session.ts
1238
+ var REFRESH_FAILURE_CODES = new Set(CEAL_REFRESH_FAILURE_CODES);
1239
+
1240
+ // packages/ceal-client-protocol/src/index.ts
1241
+ var MAX_REQUEST_BYTES = 32 * 1024;
1242
+ var MAX_ARGUMENT_BYTES = 16 * 1024;
1243
+ var HANDSHAKE_IDENTITY_KEYS = Object.freeze(["membership_ref", "registration_ref", "client_ref", "subject_ref", "instance_ref"]);
1244
+ var AUDIT_IDENTITY_KEYS = Object.freeze(["event_ref", "membership_ref", "registration_ref", "client_ref", "subject_ref", "instance_ref"]);
1245
+ var FAILURE_RESPONSE_KEYS = Object.freeze(["error", "ok", "proof_ref_or_unavailable", "protocol_version", "request_id"]);
1246
+ var MAX_RECOVERY_RETRY_AFTER_MS = 60 * 60 * 1e3;
1247
+
1248
+ // host/invocation-authentication-client-command.ts
1249
+ var MAX_DETAIL_CHARACTERS = 240;
1250
+ var HOST_OWNED_CODE = /^[a-z][a-z0-9]*(?:_[a-z0-9]+){0,7}$/u;
1251
+ function hostTerminalFailure(error, component) {
1252
+ const code = errorCode(error);
1253
+ const detail = failureDetail(error);
1254
+ if (code === "ENOENT") return { code: "host_dependency_unavailable", message: `A command or file the ${component} Host needs is unavailable: ${detail}`, next_action: "Install the missing dependency or restore the missing file, then rerun this command." };
1255
+ if (code === "EACCES" || code === "EPERM") return { code: "host_permission_denied", message: `The ${component} Host was refused access to a local path: ${detail}`, next_action: "Repair the ownership or mode of the named path, then rerun this command." };
1256
+ if (code === "ENOSPC") return { code: "host_storage_unavailable", message: `The ${component} Host could not write local state: ${detail}`, next_action: "Free local disk space, then rerun this command." };
1257
+ if (code !== null && HOST_OWNED_CODE.test(code)) return { code, message: `The ${component} Host command failed: ${detail}`, next_action: `Resolve the named failure above; run \`ceal-host doctor --json\` only if it reports installed ${component} Host drift.` };
1258
+ return { code: "host_failure_unclassified", message: `The ${component} Host command failed for a cause it cannot classify: ${detail}`, next_action: `Run \`ceal-host doctor --json\`; if it reports no drift then the ${component} Host configuration is not the cause, and the message above is the only evidence of what is.` };
1259
+ }
1260
+ var DOCTOR_FLAGS = Object.freeze({
1261
+ "--expected-sha256": "expected_sha256",
1262
+ "--expected-source-commit": "expected_source_commit",
1263
+ "--expected-instance-ref": "expected_instance_ref"
1264
+ });
1265
+ function failureDetail(error) {
1266
+ const text = error instanceof Error ? `${error.name}: ${error.message}` : typeof error === "string" ? error : "";
1267
+ const safe = normalizeCealSingleLineText(text).slice(0, MAX_DETAIL_CHARACTERS);
1268
+ return safe === "" ? "the command threw no readable error text" : safe;
1269
+ }
1270
+ function errorCode(error) {
1271
+ return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string" ? error.code : null;
1272
+ }
1273
+
1274
+ // host/relay/src/host-relay-runtime.ts
1275
+ import { O_NOFOLLOW as O_NOFOLLOW3, O_RDONLY as O_RDONLY4 } from "node:constants";
1276
+ import { lstat as lstat4, open as open4 } from "node:fs/promises";
1277
+ import { dirname as dirname3, join as join6 } from "node:path";
1278
+
1279
+ // host/absolute-path.ts
1280
+ import { posix, win32 } from "node:path";
1281
+ function isAbsoluteNormalizedNonRootPath(value, flavor = process.platform, allowRoot = false) {
1282
+ const pathApi = flavor === "win32" || flavor === "windows" ? win32 : posix;
1283
+ return typeof value === "string" && value.length <= 4096 && !value.includes("\0") && pathApi.isAbsolute(value) && pathApi.normalize(value) === value && (allowRoot || pathApi.parse(value).root !== value);
1284
+ }
1285
+
1286
+ // host/abortable-wait.ts
1287
+ function waitForAbort(signal, milliseconds) {
1288
+ if (signal.aborted) return Promise.resolve();
1289
+ return new Promise((resolve) => {
1290
+ const timer = setTimeout(finish, milliseconds);
1291
+ function finish() {
1292
+ clearTimeout(timer);
1293
+ signal.removeEventListener("abort", finish);
1294
+ resolve();
1295
+ }
1296
+ signal.addEventListener("abort", finish, { once: true });
1297
+ });
1298
+ }
1299
+
1300
+ // host/json-duplicate-guard.ts
1301
+ function rejectDuplicateJsonKeys(text, errors) {
1302
+ const end = scanJsonValue(text, skipWhitespace(text, 0), errors);
1303
+ if (skipWhitespace(text, end) !== text.length) throw errors.invalid();
1304
+ }
1305
+ function scanJsonValue(text, start, errors) {
1306
+ const marker = text[start];
1307
+ if (marker === "{") return scanJsonObject(text, start, errors);
1308
+ if (marker === "[") return scanJsonArray(text, start, errors);
1309
+ if (marker === '"') return scanJsonString(text, start, errors);
1310
+ return scanJsonPrimitive(text, start, errors);
1311
+ }
1312
+ function scanJsonObject(text, start, errors) {
1313
+ let index = skipWhitespace(text, start + 1);
1314
+ const keys = /* @__PURE__ */ new Set();
1315
+ if (text[index] === "}") return index + 1;
1316
+ while (index < text.length) {
1317
+ if (text[index] !== '"') throw errors.invalid();
1318
+ const end = scanJsonString(text, index, errors);
1319
+ let key;
1320
+ try {
1321
+ key = JSON.parse(text.slice(index, end));
1322
+ } catch {
1323
+ throw errors.invalid();
1324
+ }
1325
+ if (typeof key !== "string" || keys.has(key)) throw errors.duplicate();
1326
+ keys.add(key);
1327
+ index = skipWhitespace(text, end);
1328
+ if (text[index] !== ":") throw errors.invalid();
1329
+ index = skipWhitespace(text, scanJsonValue(text, skipWhitespace(text, index + 1), errors));
1330
+ if (text[index] === "}") return index + 1;
1331
+ if (text[index] !== ",") throw errors.invalid();
1332
+ index = skipWhitespace(text, index + 1);
1333
+ }
1334
+ throw errors.invalid();
1335
+ }
1336
+ function scanJsonArray(text, start, errors) {
1337
+ let index = skipWhitespace(text, start + 1);
1338
+ if (text[index] === "]") return index + 1;
1339
+ while (index < text.length) {
1340
+ index = skipWhitespace(text, scanJsonValue(text, index, errors));
1341
+ if (text[index] === "]") return index + 1;
1342
+ if (text[index] !== ",") throw errors.invalid();
1343
+ index = skipWhitespace(text, index + 1);
1344
+ }
1345
+ throw errors.invalid();
1346
+ }
1347
+ function scanJsonString(text, start, errors) {
1348
+ for (let index = start + 1; index < text.length; index += 1) {
1349
+ if (text[index] === "\\") {
1350
+ index += 1;
1351
+ continue;
1352
+ }
1353
+ if (text[index] === '"') return index + 1;
1354
+ }
1355
+ throw errors.invalid();
1356
+ }
1357
+ function scanJsonPrimitive(text, start, errors) {
1358
+ let index = start;
1359
+ while (index < text.length && !/[\s,\]}]/u.test(text[index] ?? "")) index += 1;
1360
+ if (index === start) throw errors.invalid();
1361
+ return index;
1362
+ }
1363
+ function skipWhitespace(text, start) {
1364
+ let index = start;
1365
+ while (index < text.length && /\s/u.test(text[index] ?? "")) index += 1;
1366
+ return index;
1367
+ }
1368
+
1369
+ // host/relay/src/producer-frame.ts
1370
+ import { createHash as createHash2 } from "node:crypto";
1371
+ var HOST_PRODUCER_FRAME_SCHEMA = "ceal.host_producer_frame.v1";
1372
+ var HOST_PRODUCER_MAX_JSON_BYTES = 262144;
1373
+ var SAFE_REF2 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
1374
+ var DIGEST2 = /^[a-f0-9]{64}$/u;
1375
+ var PRODUCERS = /* @__PURE__ */ new Set(["codex", "claude"]);
1376
+ var HOST_PRODUCER_FRAME_KINDS = ["session_started", "turn_started", "user_input", "turn_terminal", "producer_status"];
1377
+ var FRAME_KINDS = new Set(HOST_PRODUCER_FRAME_KINDS);
1378
+ function isHostProducerFrameKind(value) {
1379
+ return typeof value === "string" && FRAME_KINDS.has(value);
1380
+ }
1381
+ var HostProducerFrameError = class extends Error {
1382
+ code;
1383
+ constructor(code, message = code) {
1384
+ super(message);
1385
+ this.code = code;
1386
+ }
1387
+ };
1388
+ function encodeHostProducerFrame(frame) {
1389
+ validateFrame(frame);
1390
+ const json = Buffer.from(JSON.stringify(frame), "utf8");
1391
+ if (json.byteLength > HOST_PRODUCER_MAX_JSON_BYTES) throw new HostProducerFrameError("frame_too_large", `frame_too_large: ${refusalFact("frame_bytes", json.byteLength, `at most ${HOST_PRODUCER_MAX_JSON_BYTES}`)}`);
1392
+ const result2 = Buffer.allocUnsafe(json.byteLength + 4);
1393
+ result2.writeUInt32BE(json.byteLength, 0);
1394
+ json.copy(result2, 4);
1395
+ return result2;
1396
+ }
1397
+ function decodeHostProducerFrame(input) {
1398
+ if (input.byteLength < 4) throw new HostProducerFrameError("frame_truncated", `frame_truncated: ${refusalFact("frame_bytes", input.byteLength, "at least 4")}`);
1399
+ const length = input.readUInt32BE(0);
1400
+ if (length > HOST_PRODUCER_MAX_JSON_BYTES) throw new HostProducerFrameError("frame_too_large", `frame_too_large: ${refusalFact("declared_bytes", length, `at most ${HOST_PRODUCER_MAX_JSON_BYTES}`)}`);
1401
+ if (length === 0) throw new HostProducerFrameError("invalid_frame_length");
1402
+ if (input.byteLength !== length + 4) throw new HostProducerFrameError(input.byteLength < length + 4 ? "frame_truncated" : "invalid_frame_length");
1403
+ const bytes2 = input.subarray(4);
1404
+ const text = new TextDecoder("utf-8", { fatal: true });
1405
+ let value;
1406
+ try {
1407
+ value = JSON.parse(text.decode(bytes2));
1408
+ } catch (error) {
1409
+ if (error instanceof TypeError) throw new HostProducerFrameError("invalid_frame_encoding");
1410
+ throw new HostProducerFrameError("frame_truncated");
1411
+ }
1412
+ validateFrame(value);
1413
+ return value;
1414
+ }
1415
+ function hostProducerFrameHash(frame) {
1416
+ return createHash2("sha256").update(JSON.stringify(frame), "utf8").digest("hex");
1417
+ }
1418
+ function hostProducerIdentityRefs(hostSourceRef, frame, localSessionRef, localTurnRef, localInputRef) {
1419
+ if (!opaqueHostSourceRef(hostSourceRef)) throw new TypeError("Gateway host source reference is invalid.");
1420
+ const host_session_ref = localSessionRef === void 0 ? void 0 : `ceal-host-session:${cealRequestSha256({ host_source_ref: hostSourceRef, producer_id: frame.producer_id, producer_installation_ref: frame.producer_installation_ref, local_session_ref: localSessionRef })}`;
1421
+ const host_turn_ref = host_session_ref === void 0 || localTurnRef === void 0 ? void 0 : `ceal-host-turn:${cealRequestSha256({ host_session_ref, local_turn_ref: localTurnRef })}`;
1422
+ const host_input_ref = host_turn_ref === void 0 || localInputRef === void 0 ? void 0 : `ceal-host-input:${cealRequestSha256({ host_turn_ref, local_input_ref: localInputRef })}`;
1423
+ const submission_ref = `ceal-host-frame:${cealRequestSha256({ host_source_ref: hostSourceRef, producer_id: frame.producer_id, producer_installation_ref: frame.producer_installation_ref, sequence: frame.sequence })}`;
1424
+ return { host_session_ref: host_session_ref ?? "", ...host_turn_ref === void 0 ? {} : { host_turn_ref }, ...host_input_ref === void 0 ? {} : { host_input_ref }, submission_ref };
1425
+ }
1426
+ function hostProducerSessionRef(hostSourceRef, frame, localSessionRef) {
1427
+ return requiredIdentity(hostProducerIdentityRefs(hostSourceRef, frame, localSessionRef).host_session_ref);
1428
+ }
1429
+ function hostProducerTurnRef(hostSourceRef, frame, localSessionRef, localTurnRef) {
1430
+ return requiredIdentity(hostProducerIdentityRefs(hostSourceRef, frame, localSessionRef, localTurnRef).host_turn_ref);
1431
+ }
1432
+ function hostProducerInputRef(hostSourceRef, frame, localSessionRef, localTurnRef, localInputRef) {
1433
+ return requiredIdentity(hostProducerIdentityRefs(hostSourceRef, frame, localSessionRef, localTurnRef, localInputRef).host_input_ref);
1434
+ }
1435
+ function hostProducerSubmissionRef(hostSourceRef, frame) {
1436
+ return requiredIdentity(hostProducerIdentityRefs(hostSourceRef, frame).submission_ref);
1437
+ }
1438
+ function hostProducerPromptRef(promptSha256) {
1439
+ if (!DIGEST2.test(promptSha256)) throw new TypeError("Canonical Host prompt digest is invalid.");
1440
+ return `ceal-host-prompt:${promptSha256}`;
1441
+ }
1442
+ function opaqueHostSourceRef(value) {
1443
+ return typeof value === "string" && SAFE_REF2.test(value) && !value.startsWith("ceal-host-source:");
1444
+ }
1445
+ function requiredIdentity(value) {
1446
+ if (value === void 0) throw new TypeError("Canonical Host identity is incomplete.");
1447
+ return value;
1448
+ }
1449
+ function validateFrame(value) {
1450
+ if (!record(value)) throw new HostProducerFrameError("invalid_frame_shape");
1451
+ if (value.schema_version !== HOST_PRODUCER_FRAME_SCHEMA) throw new HostProducerFrameError("unsupported_frame_schema", `unsupported_frame_schema: ${refusalFact("schema_version", value.schema_version, HOST_PRODUCER_FRAME_SCHEMA)}`);
1452
+ if (!exactKeys2(value, ["schema_version", "producer_id", "producer_installation_ref", "producer_epoch", "sequence", "frame_kind", "occurred_at", "payload"])) throw new HostProducerFrameError("invalid_frame_shape");
1453
+ if (!PRODUCERS.has(String(value.producer_id)) || !safeRef(value.producer_installation_ref)) throw new HostProducerFrameError("invalid_producer_identity");
1454
+ if (!positive(value.producer_epoch) || !positive(value.sequence) || !hostProducerFrameKind(value.frame_kind) || !timestamp(value.occurred_at) || !record(value.payload)) throw new HostProducerFrameError("invalid_frame_shape");
1455
+ validatePayload(value.frame_kind, value.payload);
1456
+ }
1457
+ function validatePayload(kind, value) {
1458
+ const valid = kind === "session_started" ? validSession(value) : kind === "turn_started" ? validTurn(value) : kind === "user_input" ? validInput(value) : kind === "turn_terminal" ? validTerminal(value) : validStatus(value);
1459
+ if (!valid) throw new HostProducerFrameError("invalid_frame_shape");
1460
+ }
1461
+ function validSession(value) {
1462
+ return exactOptional(value, ["local_session_ref", "working_directory_ref"], ["model", "host_version", "observations"]) && safeRef(value.local_session_ref) && safeRef(value.working_directory_ref) && optionalText(value.model, 256) && optionalText(value.host_version, 256) && validObservations(value.observations);
1463
+ }
1464
+ function validTurn(value) {
1465
+ return exactOptional(value, ["local_session_ref", "local_turn_ref"], ["model", "observations"]) && safeRef(value.local_session_ref) && safeRef(value.local_turn_ref) && optionalText(value.model, 256) && validObservations(value.observations);
1466
+ }
1467
+ function validInput(value) {
1468
+ return exactOptional(value, ["local_session_ref", "local_turn_ref", "local_input_ref", "origin_input", "observations"], ["decision", "local_turn_aliases", "context_expires_at"]) && safeRef(value.local_session_ref) && safeRef(value.local_turn_ref) && safeRef(value.local_input_ref) && validInputObservations(value.observations) && typeof value.origin_input === "boolean" && validInputOptionals(value);
1469
+ }
1470
+ function validInputObservations(value) {
1471
+ return validObservations(value) && Array.isArray(value) && value.filter((item) => record(item) && item.observation_kind === "prompt").length === 1;
1472
+ }
1473
+ function validInputOptionals(value) {
1474
+ return validDecision(value.decision) && optionalRefs(value.local_turn_aliases) && (value.context_expires_at === void 0 || timestamp(value.context_expires_at));
1475
+ }
1476
+ function validTerminal(value) {
1477
+ return exactOptional(value, ["local_session_ref", "local_turn_ref", "terminal_state"], ["abort_reason", "duration_ms", "time_to_first_token_ms", "usage", "observations"]) && safeRef(value.local_session_ref) && safeRef(value.local_turn_ref) && validTerminalDisposition(value.terminal_state, value.abort_reason) && optionalNonNegative(value.duration_ms) && optionalNonNegative(value.time_to_first_token_ms) && (value.usage === void 0 || jsonValue(value.usage)) && validObservations(value.observations);
1478
+ }
1479
+ function validTerminalDisposition(state, reason) {
1480
+ return (state === "completed" || state === "aborted") && (reason === void 0 || state === "aborted" && safeRef(reason));
1481
+ }
1482
+ function validStatus(value) {
1483
+ return exactOptional(value, ["status", "reason_code"], ["detail"]) && ["ready", "degraded", "stopping"].includes(String(value.status)) && safeRef(value.reason_code) && optionalText(value.detail, 4096);
1484
+ }
1485
+ function validDecision(value) {
1486
+ return value === void 0 || record(value) && exactKeys2(value, ["decision", "approval_ref"]) && (value.decision === "approved" || value.decision === "denied") && safeRef(value.approval_ref);
1487
+ }
1488
+ function optionalText(value, maxLength) {
1489
+ return value === void 0 || typeof value === "string" && value.length > 0 && value.length <= maxLength;
1490
+ }
1491
+ function optionalNonNegative(value) {
1492
+ return value === void 0 || typeof value === "number" && Number.isFinite(value) && value >= 0;
1493
+ }
1494
+ function optionalRefs(value) {
1495
+ return value === void 0 || Array.isArray(value) && value.length <= 16 && value.every(safeRef);
1496
+ }
1497
+ function validObservations(value) {
1498
+ if (value === void 0) return true;
1499
+ if (!Array.isArray(value) || value.length > 32) return false;
1500
+ return value.every((item) => {
1501
+ try {
1502
+ validateCealHostObservationDraft(item);
1503
+ return true;
1504
+ } catch {
1505
+ return false;
1506
+ }
1507
+ });
1508
+ }
1509
+ function jsonValue(value, depth = 0) {
1510
+ if (depth > 16) return false;
1511
+ if (value === null || typeof value === "string" || typeof value === "boolean") return true;
1512
+ if (typeof value === "number") return Number.isFinite(value);
1513
+ if (Array.isArray(value)) return value.length <= 256 && value.every((item) => jsonValue(item, depth + 1));
1514
+ return record(value) && Object.keys(value).length <= 256 && Object.entries(value).every(([key, item]) => key.length > 0 && key.length <= 128 && jsonValue(item, depth + 1));
1515
+ }
1516
+ function record(value) {
1517
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1518
+ }
1519
+ function safeRef(value) {
1520
+ return typeof value === "string" && SAFE_REF2.test(value);
1521
+ }
1522
+ function positive(value) {
1523
+ return Number.isSafeInteger(value) && Number(value) > 0;
1524
+ }
1525
+ function timestamp(value) {
1526
+ return typeof value === "string" && Number.isFinite(Date.parse(value));
1527
+ }
1528
+ function hostProducerFrameKind(value) {
1529
+ return isHostProducerFrameKind(value);
1530
+ }
1531
+ function exactKeys2(value, keys) {
1532
+ return JSON.stringify(Object.keys(value).sort()) === JSON.stringify([...keys].sort());
1533
+ }
1534
+ function exactOptional(value, required, optional) {
1535
+ const keys = Object.keys(value);
1536
+ return required.every((key) => keys.includes(key)) && keys.every((key) => required.includes(key) || optional.includes(key));
1537
+ }
1538
+
1539
+ // host/relay/src/relay-admission-store.ts
1540
+ import { readFile as readFile2 } from "node:fs/promises";
1541
+ import { join as join3 } from "node:path";
1542
+
1543
+ // host/relay/src/durable-atomic-replacement.ts
1544
+ import { O_RDONLY } from "node:constants";
1545
+ import { lstat, mkdir, open, rename, unlink } from "node:fs/promises";
1546
+ import { dirname } from "node:path";
1547
+ var DEFAULT_PORT = {
1548
+ platform: process.platform,
1549
+ mkdir: (path, options) => mkdir(path, options),
1550
+ lstat: (path) => lstat(path),
1551
+ open_file: (path) => open(path, "wx", 384),
1552
+ rename,
1553
+ unlink,
1554
+ open_directory: (path) => open(path, O_RDONLY),
1555
+ unique_ref: () => `${process.pid}.${crypto.randomUUID()}`
1556
+ };
1557
+ async function durableAtomicReplace(target, data, port = DEFAULT_PORT) {
1558
+ const parent = dirname(target);
1559
+ await port.mkdir(parent, { recursive: true, mode: 448 });
1560
+ const parentStats = await port.lstat(parent);
1561
+ if (!parentStats.isDirectory() || parentStats.isSymbolicLink() || !ownerPrivate(parentStats, port.platform)) throw new TypeError(`Host Relay durable-state directory is unsafe: ${refusalFacts([{ name: "parent_stats", value: parentStats, expected: "an owner-private directory" }, { name: "platform", value: port.platform }])}.`);
1562
+ const temporary = `${target}.${port.unique_ref()}.new`;
1563
+ let staged;
1564
+ const failures = [];
1565
+ try {
1566
+ staged = await port.open_file(temporary);
1567
+ await staged.writeFile(data, typeof data === "string" ? { encoding: "utf8" } : void 0);
1568
+ await staged.sync();
1569
+ const closing = staged;
1570
+ staged = void 0;
1571
+ await closing.close();
1572
+ await port.rename(temporary, target);
1573
+ await syncParentDirectory(parent, port);
1574
+ } catch (error) {
1575
+ failures.push(error);
1576
+ }
1577
+ await closeStaged(staged, failures);
1578
+ await removeTemporary(temporary, port, failures);
1579
+ throwFailures(failures);
1580
+ }
1581
+ async function syncParentDirectory(path, port) {
1582
+ if (port.platform === "win32") return;
1583
+ const handle = await port.open_directory(path);
1584
+ let failure;
1585
+ try {
1586
+ await handle.sync();
1587
+ } catch (error) {
1588
+ if (!directorySyncUnsupported(error)) failure = error;
1589
+ }
1590
+ try {
1591
+ await handle.close();
1592
+ } catch (error) {
1593
+ if (failure === void 0) failure = error;
1594
+ else failure = new AggregateError([failure, error], "Host Relay directory sync and close failed.");
1595
+ }
1596
+ if (failure !== void 0) throw failure;
1597
+ }
1598
+ function ownerPrivate(stats, platform) {
1599
+ if (platform === "win32") return true;
1600
+ const uid = typeof process.geteuid === "function" ? process.geteuid() : stats.uid;
1601
+ return stats.uid === uid && (stats.mode & 63) === 0;
1602
+ }
1603
+ async function closeStaged(staged, failures) {
1604
+ if (staged !== void 0) try {
1605
+ await staged.close();
1606
+ } catch (error) {
1607
+ failures.push(error);
1608
+ }
1609
+ }
1610
+ async function removeTemporary(path, port, failures) {
1611
+ try {
1612
+ await port.unlink(path);
1613
+ } catch (error) {
1614
+ if (errorCode2(error) !== "ENOENT") failures.push(error);
1615
+ }
1616
+ }
1617
+ function throwFailures(failures) {
1618
+ if (failures.length === 1) throw failures[0];
1619
+ if (failures.length > 1) throw new AggregateError(failures, "Host Relay durable replacement and cleanup failed.");
1620
+ }
1621
+ function directorySyncUnsupported(error) {
1622
+ return ["EINVAL", "ENOSYS", "ENOTSUP"].includes(errorCode2(error) ?? "");
1623
+ }
1624
+ function errorCode2(error) {
1625
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : null;
1626
+ }
1627
+
1628
+ // host/relay/src/relay-quarantine-store.ts
1629
+ import { createHash as createHash3 } from "node:crypto";
1630
+ import { readFile } from "node:fs/promises";
1631
+ import { join as join2 } from "node:path";
1632
+ var RELAY_QUARANTINE_SCHEMA = "ceal.host_relay_quarantine_state.v1";
1633
+ var RELAY_QUARANTINE_MAX_RECORDS = 512;
1634
+ var RELAY_QUARANTINE_MAX_BYTES = 16 * 1024 * 1024;
1635
+ var MAX_CAPTURE_BYTES = 262148;
1636
+ var PRODUCERS2 = ["codex", "claude", "unknown"];
1637
+ var RelayQuarantineStore = class {
1638
+ root;
1639
+ maxRecords;
1640
+ maxBytes;
1641
+ tail = Promise.resolve();
1642
+ constructor(root, limits = {}) {
1643
+ this.root = root;
1644
+ this.maxRecords = limits.max_records ?? RELAY_QUARANTINE_MAX_RECORDS;
1645
+ this.maxBytes = limits.max_bytes ?? RELAY_QUARANTINE_MAX_BYTES;
1646
+ if (!Number.isSafeInteger(this.maxRecords) || this.maxRecords < 1 || this.maxRecords > RELAY_QUARANTINE_MAX_RECORDS) throw new TypeError(`Relay quarantine record cap is invalid: ${refusalFact("max_records", this.maxRecords, `between 1 and ${RELAY_QUARANTINE_MAX_RECORDS}`)}.`);
1647
+ if (!Number.isSafeInteger(this.maxBytes) || this.maxBytes < 1 || this.maxBytes > RELAY_QUARANTINE_MAX_BYTES) throw new TypeError(`Relay quarantine byte cap is invalid: ${refusalFact("max_bytes", this.maxBytes, `between 1 and ${RELAY_QUARANTINE_MAX_BYTES}`)}.`);
1648
+ }
1649
+ async retainFrame(frame, reason, capturedAt = (/* @__PURE__ */ new Date()).toISOString()) {
1650
+ await this.retain(encodeHostProducerFrame(frame), frame.producer_id, reason, capturedAt);
1651
+ }
1652
+ async retainMalformed(rawFrame, reason, capturedAt = (/* @__PURE__ */ new Date()).toISOString()) {
1653
+ await this.retain(rawFrame, inferProducer(rawFrame), reason, capturedAt);
1654
+ }
1655
+ async read(producerId, limit = this.maxRecords) {
1656
+ if (!PRODUCERS2.includes(producerId) || !Number.isSafeInteger(limit) || limit < 0) throw new TypeError("Relay quarantine read arguments are invalid.");
1657
+ await this.tail;
1658
+ const state = await this.readState();
1659
+ const records = state.producers[producerId].slice(-Math.min(limit, this.maxRecords)).map((record6) => structuredClone(record6));
1660
+ return { producer_id: producerId, records, total_bytes: records.reduce((total, record6) => total + record6.charged_bytes, 0) };
1661
+ }
1662
+ async snapshot() {
1663
+ await this.tail;
1664
+ return this.readState();
1665
+ }
1666
+ async retain(rawFrame, producerId, reason, capturedAt) {
1667
+ const run = this.tail.then(async () => {
1668
+ if (!PRODUCERS2.includes(producerId) || !Number.isFinite(Date.parse(capturedAt))) throw new TypeError("Relay quarantine record identity is invalid.");
1669
+ const raw = Buffer.from(rawFrame).subarray(0, MAX_CAPTURE_BYTES);
1670
+ const state = await this.readState();
1671
+ const record6 = {
1672
+ quarantine_ref: `quarantine:${createHash3("sha256").update(`${producerId}\0${reason}\0${capturedAt}\0`).update(raw).digest("hex")}`,
1673
+ producer_id: producerId,
1674
+ reason,
1675
+ captured_at: capturedAt,
1676
+ frame_sha256: createHash3("sha256").update(raw).digest("hex"),
1677
+ charged_bytes: raw.byteLength,
1678
+ raw_frame_base64: raw.toString("base64")
1679
+ };
1680
+ const records = state.producers[producerId];
1681
+ records.push(record6);
1682
+ while (records.length > this.maxRecords || totalBytes(records) > this.maxBytes) records.shift();
1683
+ await durableAtomicReplace(join2(this.root, "quarantine.json"), JSON.stringify(state));
1684
+ });
1685
+ this.tail = run.then(() => void 0, () => void 0);
1686
+ await run;
1687
+ }
1688
+ async readState() {
1689
+ try {
1690
+ return decodeState(JSON.parse(await readFile(join2(this.root, "quarantine.json"), "utf8")));
1691
+ } catch (error) {
1692
+ if (errorCode3(error) === "ENOENT") return emptyState();
1693
+ throw error;
1694
+ }
1695
+ }
1696
+ };
1697
+ function emptyState() {
1698
+ return { schema_version: RELAY_QUARANTINE_SCHEMA, producers: { codex: [], claude: [], unknown: [] } };
1699
+ }
1700
+ function totalBytes(records) {
1701
+ return records.reduce((total, record6) => total + record6.charged_bytes, 0);
1702
+ }
1703
+ function decodeState(value) {
1704
+ if (!record2(value) || value.schema_version !== RELAY_QUARANTINE_SCHEMA) throw new TypeError(`Host Relay quarantine state is invalid: ${refusalFact("schema_version", record2(value) ? value.schema_version : void 0, RELAY_QUARANTINE_SCHEMA)}.`);
1705
+ if (!record2(value.producers)) throw new TypeError(`Host Relay quarantine state is invalid: ${refusalFact("producer_ids", record2(value.producers) ? Object.keys(value.producers) : [], `the ${PRODUCERS2.length} quarantine producer buckets`)}.`);
1706
+ const state = emptyState();
1707
+ for (const producerId of PRODUCERS2) {
1708
+ const records = value.producers[producerId];
1709
+ if (!Array.isArray(records) || !records.every(validRecord)) throw new TypeError("Host Relay quarantine records are invalid.");
1710
+ state.producers[producerId] = records.map((item) => structuredClone(item));
1711
+ }
1712
+ return state;
1713
+ }
1714
+ function validRecord(value) {
1715
+ if (!record2(value) || typeof value.quarantine_ref !== "string" || !quarantineProducer(value.producer_id) || typeof value.reason !== "string" || !Number.isFinite(Date.parse(String(value.captured_at))) || typeof value.frame_sha256 !== "string" || typeof value.charged_bytes !== "number" || !Number.isSafeInteger(value.charged_bytes) || value.charged_bytes < 0 || typeof value.raw_frame_base64 !== "string") return false;
1716
+ return true;
1717
+ }
1718
+ function quarantineProducer(value) {
1719
+ return value === "codex" || value === "claude" || value === "unknown";
1720
+ }
1721
+ function inferProducer(rawFrame) {
1722
+ try {
1723
+ const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(Buffer.from(rawFrame).subarray(4)));
1724
+ return record2(value) && (value.producer_id === "codex" || value.producer_id === "claude") ? value.producer_id : "unknown";
1725
+ } catch {
1726
+ return "unknown";
1727
+ }
1728
+ }
1729
+ function record2(value) {
1730
+ return value !== null && typeof value === "object" && !Array.isArray(value);
1731
+ }
1732
+ function errorCode3(error) {
1733
+ return record2(error) && typeof error.code === "string" ? error.code : null;
1734
+ }
1735
+
1736
+ // host/relay/src/relay-admission-store.ts
1737
+ var DEFAULT_LIMITS = { global_count: 8192, global_bytes: 64 * 1024 * 1024, producer_count: 4096, producer_bytes: 32 * 1024 * 1024 };
1738
+ var PRODUCER_ORDER = ["codex", "claude"];
1739
+ var RETRY_SECONDS = [1, 2, 4, 8, 16, 32, 60];
1740
+ var RelayAdmissionStore = class {
1741
+ tail = Promise.resolve();
1742
+ root;
1743
+ quarantine;
1744
+ limits;
1745
+ faultHooks;
1746
+ constructor(root, limits = DEFAULT_LIMITS, faultHooks = {}, quarantine = new RelayQuarantineStore(join3(root, "quarantine"))) {
1747
+ this.root = root;
1748
+ this.quarantine = quarantine;
1749
+ this.limits = limits;
1750
+ this.faultHooks = faultHooks;
1751
+ }
1752
+ async admit(frame) {
1753
+ const run = this.tail.then(() => this.admitLocked(frame));
1754
+ this.tail = run.then(() => void 0, () => void 0);
1755
+ return run;
1756
+ }
1757
+ async snapshot() {
1758
+ await this.tail;
1759
+ return this.read();
1760
+ }
1761
+ async drainRound(deliver, options) {
1762
+ const run = this.tail.then(() => this.drainLocked(deliver, options));
1763
+ this.tail = run.then(() => void 0, () => void 0);
1764
+ return run;
1765
+ }
1766
+ async admitLocked(frame) {
1767
+ const state = await this.read();
1768
+ const key = installationKey(frame);
1769
+ const installation2 = state.installations[key] ?? { epoch: frame.producer_epoch, admitted_through_sequence: 0, delivered_through_sequence: 0 };
1770
+ if (frame.producer_epoch < installation2.epoch) return result("producer_epoch_stale", installation2);
1771
+ if (frame.producer_epoch > installation2.epoch) installation2.epoch = frame.producer_epoch;
1772
+ const existing = state.entries.find((entry2) => entry2.producer_id === frame.producer_id && entry2.producer_installation_ref === frame.producer_installation_ref && entry2.sequence === frame.sequence);
1773
+ const hash = hostProducerFrameHash(frame);
1774
+ const replay = replayCode(existing, hash, frame.sequence, installation2);
1775
+ if (replay !== null) {
1776
+ if (replay === "frame_identity_conflict") await this.quarantine.retainFrame(frame, replay);
1777
+ return result(replay, installation2);
1778
+ }
1779
+ if (frame.sequence !== installation2.admitted_through_sequence + 1) {
1780
+ await this.quarantine.retainFrame(frame, "sequence_gap");
1781
+ return result("sequence_gap", installation2);
1782
+ }
1783
+ const chargedBytes = 4 + Buffer.byteLength(JSON.stringify(frame), "utf8");
1784
+ const queueFull = this.queueFullCode(state.entries, frame.producer_id, chargedBytes);
1785
+ if (queueFull !== null) return result(queueFull, installation2);
1786
+ installation2.admitted_through_sequence = frame.sequence;
1787
+ state.installations[key] = installation2;
1788
+ state.entries.push({ producer_id: frame.producer_id, producer_installation_ref: frame.producer_installation_ref, sequence: frame.sequence, hash, charged_bytes: chargedBytes, frame: structuredClone(frame), retry_attempts: 0, retry_at_ms: 0 });
1789
+ await this.write(state);
1790
+ await this.faultHooks.after_admission_fsync?.({ fault_point: "after_admission_fsync", frame: structuredClone(frame), frame_sha256: hash });
1791
+ return result("admitted", installation2);
1792
+ }
1793
+ queueFullCode(entries, producerId, chargedBytes) {
1794
+ const producerEntries = entries.filter((entry2) => entry2.producer_id === producerId);
1795
+ if (producerEntries.length >= this.limits.producer_count || bytes(producerEntries) + chargedBytes > this.limits.producer_bytes) return "producer_queue_full";
1796
+ if (entries.length >= this.limits.global_count || bytes(entries) + chargedBytes > this.limits.global_bytes) return "relay_queue_full";
1797
+ return null;
1798
+ }
1799
+ async drainLocked(deliver, options) {
1800
+ if (!opaqueHostSourceRef(options.host_source_ref)) throw new TypeError("Gateway host source reference is invalid.");
1801
+ const state = await this.read();
1802
+ const delivered = [];
1803
+ const retained = [];
1804
+ const refused = [];
1805
+ for (const producerId of PRODUCER_ORDER) {
1806
+ const head = state.entries.find((entry2) => entry2.producer_id === producerId);
1807
+ if (!head || head.retry_at_ms > options.now_ms) continue;
1808
+ const input = { frame: structuredClone(head.frame), host_source_ref: options.host_source_ref, submission_ref: hostProducerSubmissionRef(options.host_source_ref, head.frame) };
1809
+ const outcome = await deliver(input);
1810
+ if (outcome.status === "retryable") {
1811
+ scheduleRetry(head, options.now_ms, outcome.reason);
1812
+ retained.push(input.submission_ref);
1813
+ await this.write(state);
1814
+ continue;
1815
+ }
1816
+ const installation2 = state.installations[installationKey(head.frame)];
1817
+ if (!installation2) throw new TypeError("Host Relay delivery installation is unavailable.");
1818
+ if (outcome.status === "refused") {
1819
+ await this.quarantine.retainFrame(head.frame, "gateway_refused");
1820
+ installation2.last_refusal = { sequence: head.sequence, submission_ref: input.submission_ref, code: outcome.code, message: outcome.message, refused_at_ms: options.now_ms };
1821
+ refused.push(input.submission_ref);
1822
+ } else {
1823
+ await options.after_gateway_accept_before_delivery_fsync?.({ fault_point: "after_gateway_accept_before_delivery_fsync", delivery: structuredClone(input) });
1824
+ delivered.push(input.submission_ref);
1825
+ }
1826
+ state.entries.splice(state.entries.indexOf(head), 1);
1827
+ installation2.delivered_through_sequence = Math.max(installation2.delivered_through_sequence, head.sequence);
1828
+ await this.write(state);
1829
+ }
1830
+ return { delivered, retained, refused };
1831
+ }
1832
+ async read() {
1833
+ try {
1834
+ return decodeState2(JSON.parse(await readFile2(join3(this.root, "admission.json"), "utf8")));
1835
+ } catch (error) {
1836
+ if (errorCode4(error) === "ENOENT") return { schema_version: "ceal.host_relay_admission_state.v1", installations: {}, entries: [] };
1837
+ throw error;
1838
+ }
1839
+ }
1840
+ async write(state) {
1841
+ await durableAtomicReplace(join3(this.root, "admission.json"), JSON.stringify(state));
1842
+ }
1843
+ };
1844
+ function installationKey(frame) {
1845
+ return `${frame.producer_id}\0${frame.producer_installation_ref}`;
1846
+ }
1847
+ function replayCode(existing, hash, sequence, installation2) {
1848
+ if (existing !== void 0) return existing.hash === hash ? "already_admitted" : "frame_identity_conflict";
1849
+ return sequence <= installation2.delivered_through_sequence ? "already_admitted" : null;
1850
+ }
1851
+ function bytes(entries) {
1852
+ return entries.reduce((total, entry2) => total + entry2.charged_bytes, 0);
1853
+ }
1854
+ function scheduleRetry(entry2, nowMs, reason) {
1855
+ if (reason === void 0) delete entry2.retry_reason;
1856
+ else entry2.retry_reason = reason;
1857
+ entry2.retry_attempts += 1;
1858
+ entry2.retry_at_ms = nowMs + 1e3 * (RETRY_SECONDS[Math.min(entry2.retry_attempts - 1, RETRY_SECONDS.length - 1)] ?? 60);
1859
+ }
1860
+ function result(code, state) {
1861
+ return { code, admitted_through_sequence: state.admitted_through_sequence, delivered_through_sequence: state.delivered_through_sequence };
1862
+ }
1863
+ function errorCode4(error) {
1864
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : null;
1865
+ }
1866
+ function decodeState2(value) {
1867
+ if (!stateRecord(value)) throw new TypeError("Host Relay admission state is invalid.");
1868
+ const installations = {};
1869
+ for (const [key, item] of Object.entries(value.installations)) {
1870
+ if (!installation(item)) throw new TypeError("Host Relay installation state is invalid.");
1871
+ installations[key] = item;
1872
+ }
1873
+ const entries = [];
1874
+ for (const item of value.entries) {
1875
+ if (!entry(item)) throw new TypeError("Host Relay entry state is invalid.");
1876
+ entries.push(item);
1877
+ }
1878
+ return { schema_version: "ceal.host_relay_admission_state.v1", installations, entries };
1879
+ }
1880
+ function stateRecord(value) {
1881
+ return object(value) && value.schema_version === "ceal.host_relay_admission_state.v1" && object(value.installations) && Array.isArray(value.entries);
1882
+ }
1883
+ function installation(value) {
1884
+ return typeof value === "object" && value !== null && !Array.isArray(value) && "epoch" in value && "admitted_through_sequence" in value && "delivered_through_sequence" in value && [value.epoch, value.admitted_through_sequence, value.delivered_through_sequence].every(Number.isSafeInteger) && (!("last_refusal" in value) || refusalRecord(value.last_refusal));
1885
+ }
1886
+ function refusalRecord(value) {
1887
+ return object(value) && Number.isSafeInteger(value.sequence) && typeof value.submission_ref === "string" && typeof value.code === "string" && typeof value.message === "string" && Number.isSafeInteger(value.refused_at_ms);
1888
+ }
1889
+ function entry(value) {
1890
+ return object(value) && producer(value.producer_id) && typeof value.producer_installation_ref === "string" && Number.isSafeInteger(value.sequence) && typeof value.hash === "string" && Number.isSafeInteger(value.charged_bytes) && object(value.frame) && Number.isSafeInteger(value.retry_attempts) && Number.isSafeInteger(value.retry_at_ms);
1891
+ }
1892
+ function producer(value) {
1893
+ return value === "codex" || value === "claude";
1894
+ }
1895
+ function object(value) {
1896
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1897
+ }
1898
+
1899
+ // host/relay/src/relay-gateway-bridge.ts
1900
+ import { readFile as readFile3 } from "node:fs/promises";
1901
+ import { join as join5 } from "node:path";
1902
+
1903
+ // host/relay/src/relay-request-binding-store.ts
1904
+ import { O_NOFOLLOW, O_RDONLY as O_RDONLY2 } from "node:constants";
1905
+ import { open as open2 } from "node:fs/promises";
1906
+ import { join as join4 } from "node:path";
1907
+ var HOST_RELAY_REQUEST_BINDING_SCHEMA = "ceal.host_relay_request_binding.v1";
1908
+ var STATE_SCHEMA = "ceal.host_relay_request_binding_state.v1";
1909
+ var SAFE_REF3 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
1910
+ var MAX_BINDINGS = 8192;
1911
+ var MAX_STATE_BYTES = 8 * 1024 * 1024;
1912
+ var HostRelayBindingError = class extends TypeError {
1913
+ name = "HostRelayBindingError";
1914
+ code;
1915
+ constructor(code, message) {
1916
+ super(message);
1917
+ this.code = code;
1918
+ }
1919
+ };
1920
+ var RelayRequestBindingStore = class {
1921
+ tail = Promise.resolve();
1922
+ root;
1923
+ constructor(root) {
1924
+ if (typeof root !== "string" || root.length === 0) throw new TypeError("Host Relay binding root is invalid.");
1925
+ this.root = root;
1926
+ }
1927
+ bind(input, now = /* @__PURE__ */ new Date()) {
1928
+ const run = this.tail.then(() => this.bindLocked(input, now));
1929
+ this.tail = run.then(() => void 0, () => void 0);
1930
+ return run;
1931
+ }
1932
+ query(input) {
1933
+ const run = this.tail.then(() => this.queryLocked(input));
1934
+ this.tail = run.then(() => void 0, () => void 0);
1935
+ return run;
1936
+ }
1937
+ async bindLocked(input, now) {
1938
+ const candidate = bindingFromGateway(input, now);
1939
+ const state = await this.read();
1940
+ const existing = state.bindings.find((item) => sameCanonicalIdentity(item, candidate));
1941
+ if (existing !== void 0) {
1942
+ if (!sameBinding(existing, candidate)) throw new HostRelayBindingError("canonical_turn_rebound", `Host Relay canonical turn is already bound to another Request: ${refusalFacts([{ name: "candidate_request_ref", value: candidate.request_ref, expected: existing.request_ref }, { name: "candidate_prompt_ref", value: candidate.prompt_ref, expected: existing.prompt_ref }, { name: "candidate_context_expires_at", value: candidate.context_expires_at, expected: String(existing.context_expires_at) }, { name: "candidate_local_turn_aliases", value: candidate.local_turn_aliases, expected: JSON.stringify(existing.local_turn_aliases) }])}.`);
1943
+ return existing;
1944
+ }
1945
+ if (state.bindings.length >= MAX_BINDINGS) throw new HostRelayBindingError("binding_capacity_exhausted", `Host Relay request binding capacity is exhausted: ${refusalFact("binding_count", state.bindings.length, `below ${MAX_BINDINGS}`)}.`);
1946
+ const next = { schema_version: STATE_SCHEMA, bindings: [...state.bindings, candidate] };
1947
+ await this.write(next);
1948
+ return structuredClone(candidate);
1949
+ }
1950
+ async queryLocked(input) {
1951
+ validateQuery(input);
1952
+ const state = await this.read();
1953
+ const matches = state.bindings.filter((binding2) => queryMatches(input, binding2));
1954
+ if (matches.length === 0) return { status: "no_binding" };
1955
+ const binding = matches[0];
1956
+ if (binding === void 0) throw new TypeError("Host Relay binding query result is invalid.");
1957
+ return { status: "ready", binding: structuredClone(binding) };
1958
+ }
1959
+ async read() {
1960
+ let handle;
1961
+ try {
1962
+ handle = await open2(join4(this.root, "request-bindings.json"), O_RDONLY2 | O_NOFOLLOW);
1963
+ const stats = await handle.stat();
1964
+ if (!stats.isFile() || !ownerPrivate2(stats)) throw new TypeError(`Host Relay binding state is unsafe: ${refusalFacts([{ name: "state_is_file", value: stats.isFile(), expected: "true" }, { name: "state_uid", value: stats.uid, expected: String(process.geteuid?.() ?? stats.uid) }, { name: "state_mode", value: (stats.mode & 511).toString(8), expected: "no group or other permission bits" }])}.`);
1965
+ if (stats.size > MAX_STATE_BYTES) throw new TypeError(`Host Relay binding state is unsafe: ${refusalFact("state_bytes", stats.size, `at most ${MAX_STATE_BYTES}`)}.`);
1966
+ return decodeState3(JSON.parse(await handle.readFile("utf8")));
1967
+ } catch (error) {
1968
+ if (errorCode5(error) === "ENOENT") return { schema_version: STATE_SCHEMA, bindings: [] };
1969
+ throw error;
1970
+ } finally {
1971
+ await handle?.close();
1972
+ }
1973
+ }
1974
+ async write(state) {
1975
+ const encoded = JSON.stringify(state);
1976
+ if (Buffer.byteLength(encoded, "utf8") > MAX_STATE_BYTES) throw new TypeError(`Host Relay binding state is too large: ${refusalFact("state_bytes", Buffer.byteLength(encoded, "utf8"), `at most ${MAX_STATE_BYTES}`)}.`);
1977
+ await durableAtomicReplace(join4(this.root, "request-bindings.json"), encoded);
1978
+ }
1979
+ };
1980
+ function relayRequestWorkContextFromBinding(binding) {
1981
+ return createRelayRequestWorkContext({ request_ref: binding.request_ref, host_binding: {
1982
+ host_source_ref: binding.host_source_ref,
1983
+ host_session_ref: binding.host_session_ref,
1984
+ host_turn_ref: binding.host_turn_ref,
1985
+ host_input_ref: binding.host_input_ref,
1986
+ prompt_ref: binding.prompt_ref
1987
+ } });
1988
+ }
1989
+ function createRelayRequestWorkContext(input) {
1990
+ if (!record3(input) || !exactKeys3(input, ["request_ref", "host_binding"]) || !safeRef2(input.request_ref) || !record3(input.host_binding)) {
1991
+ throw new HostRelayBindingError("context_identity_missing", "Host Relay work context does not contain the complete acknowledged Host tuple.");
1992
+ }
1993
+ const hostBinding = input.host_binding;
1994
+ if (!exactKeys3(hostBinding, ["host_source_ref", "host_session_ref", "host_turn_ref", "host_input_ref", "prompt_ref"]) || ![hostBinding.host_source_ref, hostBinding.host_session_ref, hostBinding.host_turn_ref, hostBinding.host_input_ref, hostBinding.prompt_ref].every(safeRef2)) {
1995
+ throw new HostRelayBindingError("context_identity_missing", "Host Relay work context does not contain the complete acknowledged Host tuple.");
1996
+ }
1997
+ const hostSourceRef = requiredRef(hostBinding.host_source_ref);
1998
+ const hostSessionRef = requiredRef(hostBinding.host_session_ref);
1999
+ const hostTurnRef = requiredRef(hostBinding.host_turn_ref);
2000
+ const hostInputRef = requiredRef(hostBinding.host_input_ref);
2001
+ const promptRef = requiredRef(hostBinding.prompt_ref);
2002
+ return Object.freeze({ request_ref: input.request_ref, host_binding: Object.freeze({
2003
+ host_source_ref: hostSourceRef,
2004
+ host_session_ref: hostSessionRef,
2005
+ host_turn_ref: hostTurnRef,
2006
+ host_input_ref: hostInputRef,
2007
+ prompt_ref: promptRef
2008
+ }) });
2009
+ }
2010
+ function bindingFromGateway(input, now) {
2011
+ const payload = input.frame.payload;
2012
+ const candidate = {
2013
+ schema_version: HOST_RELAY_REQUEST_BINDING_SCHEMA,
2014
+ producer_id: input.frame.producer_id,
2015
+ producer_installation_ref: input.frame.producer_installation_ref,
2016
+ local_session_ref: requiredRef(payload.local_session_ref),
2017
+ local_turn_ref: requiredRef(payload.local_turn_ref),
2018
+ local_turn_aliases: optionalRefs2(payload.local_turn_aliases),
2019
+ prompt_ref: requiredRef(input.prompt_ref),
2020
+ request_ref: requiredRef(input.request_ref),
2021
+ bound_at: timestamp2(now.toISOString()),
2022
+ ...payload.context_expires_at === void 0 ? {} : { context_expires_at: timestamp2(payload.context_expires_at) },
2023
+ host_source_ref: requiredRef(input.host_binding.host_source_ref),
2024
+ host_session_ref: requiredRef(input.host_binding.host_session_ref),
2025
+ host_turn_ref: requiredRef(input.host_binding.host_turn_ref),
2026
+ host_input_ref: requiredRef(input.host_binding.host_input_ref)
2027
+ };
2028
+ if (input.host_binding.prompt_ref !== input.prompt_ref) throw new HostRelayBindingError("context_identity_mismatch", "Host Relay binding prompt reference does not match the acknowledged submission.");
2029
+ validateBinding(candidate);
2030
+ return candidate;
2031
+ }
2032
+ function decodeState3(value) {
2033
+ if (!record3(value) || !exactKeys3(value, ["schema_version", "bindings"])) throw new TypeError(`Host Relay binding state is invalid: ${refusalFact("state_keys", record3(value) ? Object.keys(value) : [], "exactly schema_version and bindings")}.`);
2034
+ if (value.schema_version !== STATE_SCHEMA) throw new TypeError(`Host Relay binding state is invalid: ${refusalFact("schema_version", value.schema_version, STATE_SCHEMA)}.`);
2035
+ if (!Array.isArray(value.bindings)) throw new TypeError(`Host Relay binding state is invalid: ${refusalFact("bindings", value.bindings, "an array")}.`);
2036
+ const bindings = value.bindings.map((item) => {
2037
+ validateBinding(item);
2038
+ return item;
2039
+ });
2040
+ const keys = bindings.map(bindingKey);
2041
+ if (new Set(keys).size !== keys.length) throw new TypeError("Host Relay binding state contains duplicate canonical turns.");
2042
+ return { schema_version: STATE_SCHEMA, bindings };
2043
+ }
2044
+ function validateBinding(value) {
2045
+ if (!record3(value) || !exactOptionalKeys(value, ["schema_version", "producer_id", "producer_installation_ref", "local_session_ref", "local_turn_ref", "local_turn_aliases", "prompt_ref", "request_ref", "bound_at", "host_source_ref", "host_session_ref", "host_turn_ref", "host_input_ref"], ["context_expires_at"]) || !validBindingIdentity(value) || !validBindingRequest(value)) throw new TypeError("Host Relay request binding is invalid.");
2046
+ }
2047
+ function validBindingIdentity(value) {
2048
+ return value.schema_version === HOST_RELAY_REQUEST_BINDING_SCHEMA && producer2(value.producer_id) && [value.producer_installation_ref, value.local_session_ref, value.local_turn_ref].every(safeRef2) && refList(value.local_turn_aliases);
2049
+ }
2050
+ function validBindingRequest(value) {
2051
+ const tuple = [value.host_source_ref, value.host_session_ref, value.host_turn_ref, value.host_input_ref];
2052
+ return safeRef2(value.prompt_ref) && safeRef2(value.request_ref) && validTimestamp(value.bound_at) && (value.context_expires_at === void 0 || validTimestamp(value.context_expires_at)) && tuple.every(safeRef2);
2053
+ }
2054
+ function validateQuery(value) {
2055
+ if (!record3(value) || !exactKeys3(value, ["producer_id", "producer_installation_ref", "local_session_ref", "local_turn_ref"]) || !producer2(value.producer_id) || !safeRef2(value.producer_installation_ref) || !safeRef2(value.local_session_ref) || !safeRef2(value.local_turn_ref)) throw new TypeError("Host Relay binding query is invalid.");
2056
+ }
2057
+ function queryMatches(query, binding) {
2058
+ return query.producer_id === binding.producer_id && query.local_session_ref === binding.local_session_ref && (query.local_turn_ref === binding.local_turn_ref || binding.local_turn_aliases.includes(query.local_turn_ref)) && query.producer_installation_ref === binding.producer_installation_ref;
2059
+ }
2060
+ function sameCanonicalIdentity(left, right) {
2061
+ return bindingKey(left) === bindingKey(right);
2062
+ }
2063
+ function sameBinding(left, right) {
2064
+ return left.request_ref === right.request_ref && left.prompt_ref === right.prompt_ref && left.context_expires_at === right.context_expires_at && left.host_source_ref === right.host_source_ref && left.host_session_ref === right.host_session_ref && left.host_turn_ref === right.host_turn_ref && left.host_input_ref === right.host_input_ref && JSON.stringify(left.local_turn_aliases) === JSON.stringify(right.local_turn_aliases);
2065
+ }
2066
+ function bindingKey(value) {
2067
+ return `${value.producer_id}\0${value.producer_installation_ref}\0${value.local_session_ref}\0${value.local_turn_ref}`;
2068
+ }
2069
+ function requiredRef(value) {
2070
+ if (!safeRef2(value)) throw new TypeError("Host Relay binding reference is invalid.");
2071
+ return value;
2072
+ }
2073
+ function optionalRefs2(value) {
2074
+ if (value === void 0) return [];
2075
+ if (!refList(value)) throw new TypeError("Host Relay binding aliases are invalid.");
2076
+ return [...value];
2077
+ }
2078
+ function timestamp2(value) {
2079
+ if (!validTimestamp(value)) throw new TypeError("Host Relay binding timestamp is invalid.");
2080
+ return value;
2081
+ }
2082
+ function producer2(value) {
2083
+ return value === "codex" || value === "claude";
2084
+ }
2085
+ function safeRef2(value) {
2086
+ return typeof value === "string" && SAFE_REF3.test(value);
2087
+ }
2088
+ function refList(value) {
2089
+ return Array.isArray(value) && value.length <= 16 && value.every(safeRef2) && new Set(value).size === value.length;
2090
+ }
2091
+ function validTimestamp(value) {
2092
+ return typeof value === "string" && Number.isFinite(Date.parse(value));
2093
+ }
2094
+ function record3(value) {
2095
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2096
+ }
2097
+ function exactKeys3(value, keys) {
2098
+ return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
2099
+ }
2100
+ function exactOptionalKeys(value, required, optional) {
2101
+ const keys = Object.keys(value);
2102
+ return required.every((key) => Object.hasOwn(value, key)) && keys.every((key) => required.includes(key) || optional.includes(key));
2103
+ }
2104
+ function errorCode5(error) {
2105
+ return record3(error) && typeof error.code === "string" ? error.code : null;
2106
+ }
2107
+ function ownerPrivate2(stats) {
2108
+ if (process.platform === "win32") return true;
2109
+ const uid = typeof process.geteuid === "function" ? process.geteuid() : stats.uid;
2110
+ return stats.uid === uid && (stats.mode & 63) === 0;
2111
+ }
2112
+
2113
+ // host/relay/src/relay-gateway-bridge.ts
2114
+ var STATE_SCHEMA2 = "ceal.host_relay_gateway_state.v1";
2115
+ var SAFE_REF4 = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
2116
+ var HOST_GATEWAY_ACKNOWLEDGEMENT_DISPOSITIONS = ["created", "adopted", "replayed", "approval_approved", "approval_denied", "approval_replayed"];
2117
+ function isHostGatewayAcknowledgementDisposition(value) {
2118
+ return typeof value === "string" && HOST_GATEWAY_ACKNOWLEDGEMENT_DISPOSITIONS.some((disposition) => disposition === value);
2119
+ }
2120
+ var RelayGatewayBridge = class {
2121
+ statePath;
2122
+ hostSourceRef;
2123
+ gateway;
2124
+ timeoutMs;
2125
+ onRequestBound;
2126
+ tail = Promise.resolve();
2127
+ constructor(options) {
2128
+ if (typeof options.state_root !== "string" || options.state_root.length === 0 || !opaqueHostSourceRef(options.host_source_ref) || typeof options.gateway?.submitHostTurn !== "function") throw new TypeError("Host Relay Gateway bridge configuration is invalid.");
2129
+ if (!validOptionalTimeout(options.timeout_ms)) throw new TypeError("Host Relay Gateway timeout is invalid.");
2130
+ this.statePath = join5(options.state_root, "gateway-state.json");
2131
+ this.hostSourceRef = options.host_source_ref;
2132
+ this.gateway = options.gateway;
2133
+ this.timeoutMs = options.timeout_ms ?? 5e3;
2134
+ this.onRequestBound = options.on_request_bound ?? (() => void 0);
2135
+ }
2136
+ deliver(input) {
2137
+ const run = this.tail.then(() => this.deliverLocked(input));
2138
+ this.tail = run.then(() => void 0, () => void 0);
2139
+ return run;
2140
+ }
2141
+ async deliverLocked(input) {
2142
+ if (input.host_source_ref !== this.hostSourceRef) throw new TypeError(`Host Relay source binding does not match the Gateway source: ${refusalFacts([{ name: "input_host_source_ref", value: input.host_source_ref }, { name: "configured_host_source_ref", value: this.hostSourceRef }])}.`);
2143
+ if (input.frame.frame_kind === "producer_status") return { status: "created" };
2144
+ const state = await this.readState();
2145
+ if (input.frame.frame_kind === "session_started") return this.stageSession(state, input);
2146
+ if (input.frame.frame_kind === "turn_started") return this.stageTurn(state, input);
2147
+ return input.frame.frame_kind === "user_input" ? this.deliverInput(state, input) : this.deliverTerminal(state, input);
2148
+ }
2149
+ async stageSession(state, input) {
2150
+ const localSessionRef = payloadRef(input.frame, "local_session_ref");
2151
+ const hostSessionRef = hostProducerSessionRef(this.hostSourceRef, input.frame, localSessionRef);
2152
+ const next = { ...state, sessions: { ...state.sessions, [hostSessionRef]: { observations: payloadObservations(input.frame), submission_ref: input.submission_ref } } };
2153
+ await this.writeState(next);
2154
+ return { status: "created" };
2155
+ }
2156
+ async stageTurn(state, input) {
2157
+ const refs = frameRefs(input.frame, this.hostSourceRef);
2158
+ const existing = state.turns[refs.host_turn_ref];
2159
+ const nextTurn = {
2160
+ host_session_ref: refs.host_session_ref,
2161
+ observations: payloadObservations(input.frame),
2162
+ submission_ref: input.submission_ref,
2163
+ ...existing?.request_ref === void 0 ? {} : { request_ref: existing.request_ref },
2164
+ ...existing?.prompt_ref === void 0 ? {} : { prompt_ref: existing.prompt_ref },
2165
+ ...existing?.origin_host_input_ref === void 0 ? {} : { origin_host_input_ref: existing.origin_host_input_ref },
2166
+ ...existing?.input_refused === void 0 ? {} : { input_refused: existing.input_refused }
2167
+ };
2168
+ await this.writeState({ ...state, turns: { ...state.turns, [refs.host_turn_ref]: nextTurn } });
2169
+ return { status: "created" };
2170
+ }
2171
+ async deliverInput(state, input) {
2172
+ const prepared = prepareInput(state, input, this.hostSourceRef);
2173
+ const outcome = await this.submit(prepared.submission);
2174
+ if ("refusal" in outcome) {
2175
+ if (outcome.refusal.definitive && prepared.turn !== void 0) await this.writeState({ ...state, turns: { ...state.turns, [prepared.refs.host_turn_ref]: { ...prepared.turn, input_refused: { code: outcome.refusal.code, message: outcome.refusal.message } } } });
2176
+ return deliveryRefusal(outcome.refusal);
2177
+ }
2178
+ const acknowledgement2 = outcome.acknowledgement;
2179
+ const nextTurn = bindInput(prepared, acknowledgement2.request_ref, input.submission_ref);
2180
+ await this.writeState({ ...state, turns: { ...state.turns, [prepared.refs.host_turn_ref]: nextTurn } });
2181
+ const binding = { frame: structuredClone(input.frame), request_ref: acknowledgement2.request_ref, prompt_ref: prepared.promptRef, host_binding: {
2182
+ host_source_ref: prepared.submission.identity.host_source_ref,
2183
+ host_session_ref: prepared.submission.identity.host_session_ref,
2184
+ host_turn_ref: prepared.submission.identity.host_turn_ref,
2185
+ host_input_ref: prepared.hostInputRef,
2186
+ prompt_ref: prepared.promptRef
2187
+ } };
2188
+ const context = createRelayRequestWorkContext({ request_ref: acknowledgement2.request_ref, host_binding: binding.host_binding });
2189
+ try {
2190
+ await this.onRequestBound(binding, context);
2191
+ } catch (error) {
2192
+ if (error instanceof HostRelayBindingError) return { status: "refused", code: error.code, message: error.message };
2193
+ return { status: "retryable", reason: `binding_store: ${errorMessage(error)}` };
2194
+ }
2195
+ return { status: "created" };
2196
+ }
2197
+ async deliverTerminal(state, input) {
2198
+ const refs = frameRefs(input.frame, this.hostSourceRef);
2199
+ const turn = state.turns[refs.host_turn_ref];
2200
+ if (turn === void 0) return { status: "refused", code: "origin_turn_unknown", message: "The terminal frame names a turn whose start was never admitted." };
2201
+ if (turn.request_ref === void 0 || turn.prompt_ref === void 0 || turn.origin_host_input_ref === void 0) {
2202
+ if (turn.input_refused !== void 0) return { status: "refused", code: "origin_input_refused", message: `The terminal frame names a turn whose input was refused (${turn.input_refused.code}: ${turn.input_refused.message}).` };
2203
+ return { status: "retryable", reason: "origin_turn_unbound" };
2204
+ }
2205
+ const outcome = await this.submit({
2206
+ identity: { host_source_ref: this.hostSourceRef, host_session_ref: refs.host_session_ref, host_turn_ref: refs.host_turn_ref },
2207
+ host_input_ref: turn.origin_host_input_ref,
2208
+ prompt_ref: turn.prompt_ref,
2209
+ observations: payloadObservations(input.frame),
2210
+ request_ref: turn.request_ref,
2211
+ submission_ref: input.submission_ref
2212
+ });
2213
+ return "refusal" in outcome ? deliveryRefusal(outcome.refusal) : { status: "created" };
2214
+ }
2215
+ async submit(input) {
2216
+ const controller2 = new AbortController();
2217
+ const timeout = setTimeout(() => controller2.abort(), this.timeoutMs);
2218
+ try {
2219
+ const acknowledgement2 = await this.gateway.submitHostTurn(input, controller2.signal);
2220
+ return SAFE_REF4.test(acknowledgement2.request_ref) && isHostGatewayAcknowledgementDisposition(acknowledgement2.disposition) ? { acknowledgement: acknowledgement2 } : { refusal: { code: "invalid_response", message: "Gateway acknowledgement identity is invalid.", definitive: false } };
2221
+ } catch (error) {
2222
+ return { refusal: submissionRefusal(error) };
2223
+ } finally {
2224
+ clearTimeout(timeout);
2225
+ }
2226
+ }
2227
+ async readState() {
2228
+ try {
2229
+ const state = decodeState4(JSON.parse(await readFile3(this.statePath, "utf8")));
2230
+ if (state.host_source_ref !== this.hostSourceRef) throw new TypeError(`Host Relay Gateway source binding changed: ${refusalFacts([{ name: "stored_host_source_ref", value: state.host_source_ref }, { name: "configured_host_source_ref", value: this.hostSourceRef }])}.`);
2231
+ return state;
2232
+ } catch (error) {
2233
+ if (errorCode6(error) === "ENOENT") return { schema_version: STATE_SCHEMA2, host_source_ref: this.hostSourceRef, sessions: {}, turns: {} };
2234
+ throw error;
2235
+ }
2236
+ }
2237
+ async writeState(state) {
2238
+ await durableAtomicReplace(this.statePath, JSON.stringify(state));
2239
+ }
2240
+ };
2241
+ var RETRYABLE_HTTP_STATUSES = /* @__PURE__ */ new Set([401, 403, 408, 429]);
2242
+ function submissionRefusal(error) {
2243
+ const status = isRecord(error) && typeof error.status === "number" ? error.status : void 0;
2244
+ const code = errorCode6(error) ?? "gateway_unavailable";
2245
+ const definitive = code === "payload_rejected" || status !== void 0 && status >= 400 && status < 500 && !RETRYABLE_HTTP_STATUSES.has(status);
2246
+ return { code, message: errorMessage(error), definitive };
2247
+ }
2248
+ function deliveryRefusal(refusal) {
2249
+ return refusal.definitive ? { status: "refused", code: refusal.code, message: refusal.message } : { status: "retryable", reason: `${refusal.code}: ${refusal.message}` };
2250
+ }
2251
+ function errorMessage(error) {
2252
+ return error instanceof Error ? error.message : String(error);
2253
+ }
2254
+ function frameRefs(frame, hostSourceRef) {
2255
+ const localSessionRef = payloadRef(frame, "local_session_ref");
2256
+ const localTurnRef = payloadRef(frame, "local_turn_ref");
2257
+ const hostSessionRef = hostProducerSessionRef(hostSourceRef, frame, localSessionRef);
2258
+ return { local_session_ref: localSessionRef, local_turn_ref: localTurnRef, host_session_ref: hostSessionRef, host_turn_ref: hostProducerTurnRef(hostSourceRef, frame, localSessionRef, localTurnRef) };
2259
+ }
2260
+ function prepareInput(state, input, hostSourceRef) {
2261
+ const refs = frameRefs(input.frame, hostSourceRef);
2262
+ const turn = state.turns[refs.host_turn_ref];
2263
+ const promptRef = turn?.prompt_ref ?? hostProducerPromptRef(payloadPromptDigest(input.frame));
2264
+ const hostInputRef = hostProducerInputRef(hostSourceRef, input.frame, refs.local_session_ref, refs.local_turn_ref, payloadRef(input.frame, "local_input_ref"));
2265
+ const observations = uniqueObservations([...state.sessions[refs.host_session_ref]?.observations ?? [], ...turn?.observations ?? [], ...payloadObservations(input.frame)]);
2266
+ const submission = compactSubmission({
2267
+ identity: { host_source_ref: hostSourceRef, host_session_ref: refs.host_session_ref, host_turn_ref: refs.host_turn_ref },
2268
+ host_input_ref: hostInputRef,
2269
+ prompt_ref: promptRef,
2270
+ observations,
2271
+ decision: payloadDecision(input.frame),
2272
+ request_ref: turn?.request_ref,
2273
+ submission_ref: input.submission_ref
2274
+ });
2275
+ return { refs, turn, promptRef, hostInputRef, submission };
2276
+ }
2277
+ function bindInput(prepared, requestRef, submissionRef) {
2278
+ return {
2279
+ host_session_ref: prepared.refs.host_session_ref,
2280
+ observations: prepared.turn?.observations ?? [],
2281
+ submission_ref: prepared.turn?.submission_ref ?? submissionRef,
2282
+ request_ref: requestRef,
2283
+ prompt_ref: prepared.promptRef,
2284
+ origin_host_input_ref: prepared.turn?.origin_host_input_ref ?? prepared.hostInputRef
2285
+ };
2286
+ }
2287
+ function payloadRef(frame, key) {
2288
+ const value = frame.payload[key];
2289
+ if (typeof value !== "string" || !SAFE_REF4.test(value)) throw new TypeError("Host Relay frame reference is invalid.");
2290
+ return value;
2291
+ }
2292
+ function payloadPromptDigest(frame) {
2293
+ const prompt = payloadObservations(frame).find((observation) => observation.observation_kind === "prompt");
2294
+ if (prompt === void 0 || !isCealHostPromptObservationValue(prompt.value)) throw new TypeError("Host Relay prompt observation is invalid.");
2295
+ return prompt.value.body_sha256;
2296
+ }
2297
+ function payloadObservations(frame) {
2298
+ return Array.isArray(frame.payload.observations) ? frame.payload.observations.filter(isObservation) : [];
2299
+ }
2300
+ function payloadDecision(frame) {
2301
+ const value = frame.payload.decision;
2302
+ return isRecord(value) && (value.decision === "approved" || value.decision === "denied") && typeof value.approval_ref === "string" ? { decision: value.decision, approval_ref: value.approval_ref } : void 0;
2303
+ }
2304
+ function uniqueObservations(values) {
2305
+ const seen = /* @__PURE__ */ new Set();
2306
+ return values.filter((value) => !seen.has(value.observation_ref) && Boolean(seen.add(value.observation_ref)));
2307
+ }
2308
+ function compactSubmission(value) {
2309
+ return { identity: value.identity, host_input_ref: value.host_input_ref, prompt_ref: value.prompt_ref, observations: value.observations, submission_ref: value.submission_ref, ...value.decision === void 0 ? {} : { decision: value.decision }, ...value.request_ref === void 0 ? {} : { request_ref: value.request_ref } };
2310
+ }
2311
+ function isObservation(value) {
2312
+ try {
2313
+ validateCealHostObservationDraft(value);
2314
+ return true;
2315
+ } catch {
2316
+ return false;
2317
+ }
2318
+ }
2319
+ function isRecord(value) {
2320
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2321
+ }
2322
+ function validOptionalTimeout(value) {
2323
+ return value === void 0 || Number.isSafeInteger(value) && Number(value) >= 1 && Number(value) <= 6e4;
2324
+ }
2325
+ function errorCode6(error) {
2326
+ return isRecord(error) && typeof error.code === "string" ? error.code : null;
2327
+ }
2328
+ function decodeState4(value) {
2329
+ if (!isRecord(value) || value.schema_version !== STATE_SCHEMA2) throw new TypeError(`Host Relay Gateway state is invalid: ${refusalFact("schema_version", isRecord(value) ? value.schema_version : void 0, STATE_SCHEMA2)}.`);
2330
+ if (!opaqueHostSourceRef(value.host_source_ref)) throw new TypeError(`Host Relay Gateway state is invalid: ${refusalFact("host_source_ref", value.host_source_ref, "an opaque Host source reference")}.`);
2331
+ if (!isRecord(value.sessions) || !isRecord(value.turns)) throw new TypeError(`Host Relay Gateway state is invalid: ${refusalFacts([{ name: "sessions_is_object", value: isRecord(value.sessions), expected: "true" }, { name: "turns_is_object", value: isRecord(value.turns), expected: "true" }])}.`);
2332
+ return { schema_version: STATE_SCHEMA2, host_source_ref: value.host_source_ref, sessions: decodeSessions(value.sessions), turns: decodeTurns(value.turns) };
2333
+ }
2334
+ function decodeSessions(value) {
2335
+ const result2 = {};
2336
+ for (const [key, item] of Object.entries(value)) {
2337
+ if (!SAFE_REF4.test(key) || !isRecord(item) || !Array.isArray(item.observations) || !item.observations.every(isObservation) || typeof item.submission_ref !== "string") throw new TypeError("Host Relay staged Session is invalid.");
2338
+ result2[key] = { observations: item.observations, submission_ref: item.submission_ref };
2339
+ }
2340
+ return result2;
2341
+ }
2342
+ function decodeTurns(value) {
2343
+ const result2 = {};
2344
+ for (const [key, item] of Object.entries(value)) {
2345
+ if (!SAFE_REF4.test(key)) throw new TypeError("Host Relay staged turn is invalid.");
2346
+ result2[key] = decodeTurn(item);
2347
+ }
2348
+ return result2;
2349
+ }
2350
+ function decodeTurn(item) {
2351
+ if (!isRecord(item) || typeof item.host_session_ref !== "string" || !Array.isArray(item.observations) || !item.observations.every(isObservation) || typeof item.submission_ref !== "string") throw new TypeError("Host Relay staged turn is invalid.");
2352
+ return {
2353
+ host_session_ref: item.host_session_ref,
2354
+ observations: item.observations,
2355
+ submission_ref: item.submission_ref,
2356
+ ...decodeTurnBinding(item),
2357
+ ...isInputRefusal(item.input_refused) ? { input_refused: { code: item.input_refused.code, message: item.input_refused.message } } : {}
2358
+ };
2359
+ }
2360
+ function decodeTurnBinding(item) {
2361
+ return { ...typeof item.request_ref === "string" ? { request_ref: item.request_ref } : {}, ...typeof item.prompt_ref === "string" ? { prompt_ref: item.prompt_ref } : {}, ...typeof item.origin_host_input_ref === "string" ? { origin_host_input_ref: item.origin_host_input_ref } : {} };
2362
+ }
2363
+ function isInputRefusal(value) {
2364
+ return isRecord(value) && typeof value.code === "string" && typeof value.message === "string";
2365
+ }
2366
+
2367
+ // host/relay/src/relay-gateway-http.ts
2368
+ import { O_NOFOLLOW as O_NOFOLLOW2, O_RDONLY as O_RDONLY3 } from "node:constants";
2369
+ import { lstat as lstat2, open as open3 } from "node:fs/promises";
2370
+ import { dirname as dirname2 } from "node:path";
2371
+
2372
+ // host/gateway-http.ts
2373
+ var SAFE_HOST_REF = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u;
2374
+ function hostIngressBody(input, invalidEventTime) {
2375
+ const prompt = input.observations.find((observation) => observation.observation_kind === "prompt");
2376
+ const observedAt = prompt?.observed_at ?? input.observations[0]?.observed_at;
2377
+ if (observedAt === void 0 || !Number.isFinite(Date.parse(observedAt))) throw invalidEventTime();
2378
+ return {
2379
+ submission_ref: input.submission_ref,
2380
+ host_source_ref: input.identity.host_source_ref,
2381
+ host_session_ref: input.identity.host_session_ref,
2382
+ host_turn_ref: input.identity.host_turn_ref,
2383
+ host_input_ref: input.host_input_ref,
2384
+ prompt_ref: input.prompt_ref,
2385
+ observed_at: observedAt,
2386
+ observations: input.observations,
2387
+ ...input.request_ref === void 0 ? {} : { request_ref: input.request_ref },
2388
+ ...input.decision === void 0 ? {} : { decision: input.decision.decision, approval_ref: input.decision.approval_ref }
2389
+ };
2390
+ }
2391
+ async function responseJson(response2, invalidResponse2) {
2392
+ try {
2393
+ return await response2.json();
2394
+ } catch {
2395
+ throw invalidResponse2();
2396
+ }
2397
+ }
2398
+ async function submitHostIngress(options) {
2399
+ if (options.input.identity.host_source_ref !== options.expected_host_source_ref) throw options.sourceMismatch();
2400
+ const body = JSON.stringify(hostIngressBody(options.input, options.invalidEventTime));
2401
+ let response2;
2402
+ try {
2403
+ response2 = await options.fetcher(options.endpoint, {
2404
+ method: "POST",
2405
+ ...options.redirect === void 0 ? {} : { redirect: options.redirect },
2406
+ headers: { authorization: `Bearer ${options.credential}`, "content-type": "application/json" },
2407
+ body,
2408
+ signal: options.signal
2409
+ });
2410
+ } catch {
2411
+ throw options.unavailable();
2412
+ }
2413
+ const responseBody = await responseJson(response2, options.invalidResponse);
2414
+ if (!response2.ok) throw options.refused(response2.status, responseBody);
2415
+ return options.acknowledgement(responseBody);
2416
+ }
2417
+
2418
+ // host/relay/src/relay-gateway-http.ts
2419
+ var HOST_REGISTRATION_STATE_KEYS = Object.freeze([
2420
+ "credential_generation",
2421
+ "gateway_request_origin",
2422
+ "host_access_token",
2423
+ "host_installation_ref",
2424
+ "host_source_ref",
2425
+ "registration_attempt_ref",
2426
+ "schema_version",
2427
+ "status"
2428
+ ]);
2429
+ var HOST_INGRESS_PATH = "/api/ceal/v2/host-ingress";
2430
+ var HostRelayGatewayError = class extends Error {
2431
+ name = "HostRelayGatewayError";
2432
+ code;
2433
+ /** HTTP status of a Gateway refusal, when one answered. */
2434
+ status;
2435
+ constructor(code, message, status) {
2436
+ super(message);
2437
+ this.code = code;
2438
+ if (status !== void 0) this.status = status;
2439
+ }
2440
+ };
2441
+ function refusalMessage(status, body) {
2442
+ const record6 = isCealJsonRecord(body) ? body : {};
2443
+ const code = typeof record6.error_code === "string" ? record6.error_code : "unknown";
2444
+ const message = typeof record6.message === "string" ? `: ${record6.message}` : "";
2445
+ return `Gateway Host ingress refused the submission (${status} ${code}${message}).`;
2446
+ }
2447
+ function createHostRelayGatewayHttpPort(options) {
2448
+ if (!SAFE_HOST_REF.test(options.host_source_ref) || options.host_source_ref.startsWith("ceal-host-source:") || typeof options.registration_state_file !== "string" || options.registration_state_file.length === 0) {
2449
+ throw new HostRelayGatewayError("configuration", "Host Relay Gateway binding is invalid.");
2450
+ }
2451
+ return Object.freeze({
2452
+ async submitHostTurn(input, signal) {
2453
+ if (input.identity.host_source_ref !== options.host_source_ref) throw new HostRelayGatewayError("payload_rejected", `Host Relay source binding changed: ${refusalFacts([{ name: "input_host_source_ref", value: input.identity.host_source_ref }, { name: "configured_host_source_ref", value: options.host_source_ref }])}.`);
2454
+ const registration = await readHostRegistrationAuthority(options.registration_state_file, options.host_source_ref);
2455
+ const endpoint = hostRelayGatewayEndpoint(registration.gateway_request_origin);
2456
+ return await submitHostIngress({
2457
+ input,
2458
+ expected_host_source_ref: options.host_source_ref,
2459
+ endpoint,
2460
+ credential: registration.host_access_token,
2461
+ fetcher: options.fetch ?? fetch,
2462
+ signal,
2463
+ redirect: "error",
2464
+ sourceMismatch: () => new HostRelayGatewayError("payload_rejected", "Host Relay source binding changed."),
2465
+ invalidEventTime: () => new HostRelayGatewayError("payload_rejected", "Host Relay submission has no event time."),
2466
+ unavailable: () => new HostRelayGatewayError("gateway_unavailable", "Gateway Host ingress is unavailable."),
2467
+ invalidResponse: () => new HostRelayGatewayError("invalid_response", "Gateway Host ingress response is not JSON."),
2468
+ refused: (status, body) => new HostRelayGatewayError("gateway_refused", refusalMessage(status, body), status),
2469
+ acknowledgement
2470
+ });
2471
+ },
2472
+ async mintInvocationContext(input, signal) {
2473
+ const registration = await readHostRegistrationAuthority(options.registration_state_file, options.host_source_ref);
2474
+ let response2;
2475
+ try {
2476
+ response2 = await (options.fetch ?? fetch)(hostRelayGatewayRoute(registration.gateway_request_origin, CEAL_HOST_INVOCATION_CONTEXT_PATH), {
2477
+ method: "POST",
2478
+ redirect: "error",
2479
+ signal,
2480
+ headers: { authorization: `Bearer ${registration.host_access_token}`, "content-type": "application/json" },
2481
+ body: JSON.stringify({ schema_version: "ceal.gateway_host_invocation_context_request.v1", ...input })
2482
+ });
2483
+ } catch {
2484
+ throw new HostRelayGatewayError("gateway_unavailable", "Gateway Host invocation context is unavailable.");
2485
+ }
2486
+ if (!response2.ok) throw new HostRelayGatewayError(response2.status === 401 ? "credential" : "gateway_refused", `Gateway Host invocation context was refused (${response2.status}).`, response2.status);
2487
+ let value;
2488
+ try {
2489
+ value = await response2.json();
2490
+ } catch {
2491
+ throw new HostRelayGatewayError("invalid_response", "Gateway Host invocation context response is not JSON.");
2492
+ }
2493
+ try {
2494
+ return decodeCealHostInvocationAuthenticationResult(value);
2495
+ } catch {
2496
+ throw new HostRelayGatewayError("invalid_response", "Gateway Host invocation context response is invalid.");
2497
+ }
2498
+ }
2499
+ });
2500
+ }
2501
+ function hostRelayGatewayEndpoint(value) {
2502
+ return hostRelayGatewayRoute(value, HOST_INGRESS_PATH);
2503
+ }
2504
+ function hostRelayGatewayRoute(value, path) {
2505
+ let parsed;
2506
+ try {
2507
+ parsed = new URL(value);
2508
+ } catch {
2509
+ throw new HostRelayGatewayError("configuration", "Host Relay Gateway origin is invalid.");
2510
+ }
2511
+ const hostname = parsed.hostname.toLowerCase().replace(/\.+$/u, "");
2512
+ if (/\s|\0/u.test(value) || hostname === "" || !validPort(parsed) || !isExplicitLoopbackHttp(parsed, hostname) && !isSecureHttps(parsed)) {
2513
+ throw new HostRelayGatewayError("configuration", `Host Relay Gateway origin is invalid: ${refusalFacts([{ name: "protocol", value: parsed.protocol, expected: "https:, or http: with an explicit loopback port" }, { name: "hostname", value: hostname }, { name: "port", value: parsed.port }])}.`);
2514
+ }
2515
+ if (hasOriginDecoration(value, parsed)) {
2516
+ throw new HostRelayGatewayError("configuration", `Host Relay Gateway origin is invalid: ${refusalFacts([{ name: "origin", value: parsed.origin }, { name: "has_userinfo", value: parsed.username !== "" || parsed.password !== "", expected: "false" }, { name: "pathname", value: parsed.pathname, expected: "/" }, { name: "search", value: parsed.search, expected: "an empty query" }, { name: "hash", value: parsed.hash, expected: "an empty fragment" }])}.`);
2517
+ }
2518
+ return `${parsed.origin}${path}`;
2519
+ }
2520
+ function isExplicitLoopbackHttp(parsed, hostname) {
2521
+ return parsed.protocol === "http:" && parsed.port !== "" && (hostname === "127.0.0.1" || hostname === "[::1]");
2522
+ }
2523
+ function isSecureHttps(parsed) {
2524
+ return parsed.protocol === "https:";
2525
+ }
2526
+ function validPort(parsed) {
2527
+ if (parsed.port === "") return true;
2528
+ const port = Number(parsed.port);
2529
+ return Number.isInteger(port) && port >= 1 && port <= 65535;
2530
+ }
2531
+ function hasOriginDecoration(value, parsed) {
2532
+ const schemeEnd = value.indexOf("://");
2533
+ const authority = schemeEnd < 0 ? "" : value.slice(schemeEnd + 3);
2534
+ const suffixOffset = authority.search(/[\\/?#]/u);
2535
+ const rawSuffix = suffixOffset < 0 ? "" : authority.slice(suffixOffset);
2536
+ return parsed.username !== "" || parsed.password !== "" || parsed.pathname !== "/" || parsed.search !== "" || parsed.hash !== "" || rawSuffix !== "" && rawSuffix !== "/";
2537
+ }
2538
+ async function readHostRegistrationAuthority(path, expectedHostSourceRef) {
2539
+ let handle;
2540
+ try {
2541
+ await assertOwnerPrivateDirectory(dirname2(path));
2542
+ handle = await open3(path, O_RDONLY3 | O_NOFOLLOW2);
2543
+ const stats = await handle.stat();
2544
+ if (!stats.isFile() || !ownerPrivate3(stats)) throw new HostRelayGatewayError("credential", "Host Relay credential file is not owner-private.");
2545
+ const raw = await handle.readFile("utf8");
2546
+ if (raw.length > 65536) throw new HostRelayGatewayError("credential", `Host registration state is invalid: ${refusalFact("registration_state_bytes", Buffer.byteLength(raw, "utf8"), "at most 65536")}.`);
2547
+ let value;
2548
+ try {
2549
+ value = JSON.parse(raw);
2550
+ } catch {
2551
+ throw new HostRelayGatewayError("credential", "Host registration state is invalid.");
2552
+ }
2553
+ return decodeHostRegistrationAuthority(value, expectedHostSourceRef);
2554
+ } catch (error) {
2555
+ if (error instanceof HostRelayGatewayError) throw error;
2556
+ throw new HostRelayGatewayError("credential", "Host Relay credential file is unavailable.");
2557
+ } finally {
2558
+ await handle?.close();
2559
+ }
2560
+ }
2561
+ function decodeHostRegistrationAuthority(value, expectedHostSourceRef) {
2562
+ const keys = HOST_REGISTRATION_STATE_KEYS;
2563
+ const fieldCount = isCealJsonRecord(value) ? Object.keys(value).length : 0;
2564
+ const missing = isCealJsonRecord(value) ? keys.filter((key) => !Object.hasOwn(value, key)).length : keys.length;
2565
+ if (!isCealJsonRecord(value) || fieldCount !== keys.length || missing !== 0) throw new HostRelayGatewayError("credential", `Host registration state is invalid or does not match this Relay: ${refusalFacts([{ name: "registration_field_count", value: fieldCount, expected: `exactly ${keys.length}` }, { name: "missing_registration_field_count", value: missing, expected: "0" }])}.`);
2566
+ if (!validRegistrationIdentity(value, expectedHostSourceRef)) throw new HostRelayGatewayError("credential", `Host registration state is invalid or does not match this Relay: ${refusalFacts([{ name: "schema_version", value: value.schema_version, expected: "ceal.host_registration_state.v1" }, { name: "status", value: value.status, expected: "active" }, { name: "host_source_ref", value: value.host_source_ref, expected: expectedHostSourceRef }, { name: "registration_attempt_ref", value: value.registration_attempt_ref, expected: "host-registration-attempt:<uuid>" }, { name: "host_installation_ref", value: value.host_installation_ref, expected: "host-installation:<uuid>" }])}.`);
2567
+ if (!validRegistrationCredential(value)) throw new HostRelayGatewayError("credential", `Host registration state is invalid or does not match this Relay: ${refusalFacts([{ name: "credential_generation", value: value.credential_generation, expected: "a positive safe integer" }, { name: "host_access_token_matches_registered_shape", value: validHostAccessToken(value.host_access_token), expected: "true" }])}.`);
2568
+ if (!validGatewayOrigin(value.gateway_request_origin)) throw new HostRelayGatewayError("credential", `Host registration state is invalid or does not match this Relay: ${refusalFact("gateway_request_origin", value.gateway_request_origin, "an HTTPS origin or explicit-port loopback HTTP origin")}.`);
2569
+ return { gateway_request_origin: value.gateway_request_origin, host_access_token: value.host_access_token };
2570
+ }
2571
+ function validRegistrationIdentity(value, expectedHostSourceRef) {
2572
+ return value.schema_version === "ceal.host_registration_state.v1" && value.status === "active" && value.host_source_ref === expectedHostSourceRef && typeof value.registration_attempt_ref === "string" && /^host-registration-attempt:[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/u.test(value.registration_attempt_ref) && typeof value.host_installation_ref === "string" && /^host-installation:[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/u.test(value.host_installation_ref) && typeof value.host_source_ref === "string" && /^host-source:[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/u.test(value.host_source_ref);
2573
+ }
2574
+ function validRegistrationCredential(value) {
2575
+ return Number.isSafeInteger(value.credential_generation) && Number(value.credential_generation) > 0 && validHostAccessToken(value.host_access_token);
2576
+ }
2577
+ function validHostAccessToken(value) {
2578
+ return typeof value === "string" && /^ceal_host_[A-Za-z0-9_-]{43}$/u.test(value);
2579
+ }
2580
+ function validGatewayOrigin(value) {
2581
+ try {
2582
+ if (typeof value !== "string") return false;
2583
+ hostRelayGatewayEndpoint(value);
2584
+ return true;
2585
+ } catch {
2586
+ return false;
2587
+ }
2588
+ }
2589
+ async function assertOwnerPrivateDirectory(path) {
2590
+ const stats = await lstat2(path);
2591
+ if (!stats.isDirectory() || stats.isSymbolicLink() || !ownerPrivate3(stats)) throw new HostRelayGatewayError("credential", "Host Relay credential directory is not owner-private.");
2592
+ }
2593
+ function ownerPrivate3(stats) {
2594
+ if (process.platform === "win32") return true;
2595
+ const uid = typeof process.geteuid === "function" ? process.geteuid() : stats.uid;
2596
+ return stats.uid === uid && (stats.mode & 63) === 0;
2597
+ }
2598
+ function acknowledgement(value) {
2599
+ const fields = isCealJsonRecord(value) ? value : {};
2600
+ if (!isCealJsonRecord(value) || value.ok !== true || value.status !== "accepted" || typeof value.request_ref !== "string" || !SAFE_HOST_REF.test(value.request_ref) || !isHostGatewayAcknowledgementDisposition(value.disposition)) {
2601
+ throw new HostRelayGatewayError("invalid_response", `Gateway Host ingress acknowledgement is invalid: ${refusalFacts([{ name: "ok", value: fields.ok, expected: "true" }, { name: "status", value: fields.status, expected: "accepted" }, { name: "request_ref", value: fields.request_ref, expected: "a safe Host reference" }, { name: "disposition", value: fields.disposition, expected: "a Gateway acknowledgement disposition" }])}.`);
2602
+ }
2603
+ return { request_ref: value.request_ref, disposition: value.disposition };
2604
+ }
2605
+
2606
+ // host/relay/src/relay-ipc.ts
2607
+ import { chmod, lstat as lstat3, unlink as unlink2 } from "node:fs/promises";
2608
+ import { createConnection, createServer } from "node:net";
2609
+ var HOST_RELAY_REQUEST_BINDING_KEYS = Object.freeze([
2610
+ "schema_version",
2611
+ "producer_id",
2612
+ "producer_installation_ref",
2613
+ "local_session_ref",
2614
+ "local_turn_ref",
2615
+ "local_turn_aliases",
2616
+ "prompt_ref",
2617
+ "request_ref",
2618
+ "bound_at",
2619
+ "host_source_ref",
2620
+ "host_session_ref",
2621
+ "host_turn_ref",
2622
+ "host_input_ref"
2623
+ ]);
2624
+ var HOST_RELAY_IPC_RESPONSE_SCHEMA = "ceal.host_relay_admission.v1";
2625
+ var HOST_RELAY_BINDING_QUERY_SCHEMA = "ceal.host_relay_binding_query.v1";
2626
+ var HOST_RELAY_BINDING_RESULT_SCHEMA = "ceal.host_relay_binding_result.v1";
2627
+ var HOST_RELAY_INVOCATION_CONTEXT_QUERY_SCHEMA = "ceal.host_relay_invocation_context_query.v1";
2628
+ var HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA = "ceal.host_relay_invocation_context_result.v1";
2629
+ var HostRelayIpcError = class extends Error {
2630
+ code;
2631
+ constructor(code, message = code) {
2632
+ super(message);
2633
+ this.code = code;
2634
+ }
2635
+ };
2636
+ async function startHostRelayIpcServer(options) {
2637
+ await assertEndpointVacant(options.endpoint);
2638
+ const active = /* @__PURE__ */ new Map();
2639
+ const sockets = /* @__PURE__ */ new Set();
2640
+ const quarantine = options.quarantine ?? options.admission.quarantine;
2641
+ const server = createServer((socket) => serveSocket(socket, options.admission, options.bindings, options.mintInvocationContext, quarantine, active, sockets));
2642
+ await listen(server, options.endpoint);
2643
+ if (process.platform !== "win32") await chmod(options.endpoint, 384);
2644
+ return { endpoint: options.endpoint, close: () => closeServer(server, sockets, options.endpoint) };
2645
+ }
2646
+ function encodeHostRelayIpcResponse(response2) {
2647
+ const body = Buffer.from(JSON.stringify(response2), "utf8");
2648
+ const result2 = Buffer.allocUnsafe(body.length + 4);
2649
+ result2.writeUInt32BE(body.length, 0);
2650
+ body.copy(result2, 4);
2651
+ return result2;
2652
+ }
2653
+ function serveSocket(socket, admission, bindings, mintInvocationContext, quarantine, active, sockets) {
2654
+ const state = { buffer: Buffer.alloc(0), closed: false, tail: Promise.resolve() };
2655
+ sockets.add(socket);
2656
+ socket.on("data", (chunk) => {
2657
+ state.buffer = Buffer.concat([state.buffer, Buffer.from(chunk)]);
2658
+ state.tail = state.tail.then(() => drainFrames(socket, state, admission, bindings, mintInvocationContext, quarantine, active)).catch(() => {
2659
+ writeResponse(socket, errorResponse("relay_unavailable"));
2660
+ socket.end();
2661
+ });
2662
+ });
2663
+ socket.once("error", () => closeConnection(socket, state, active, sockets));
2664
+ socket.once("close", () => closeConnection(socket, state, active, sockets));
2665
+ socket.once("end", () => {
2666
+ if (state.buffer.length > 0) void quarantine.retainMalformed(state.buffer, "frame_truncated").finally(() => {
2667
+ writeResponse(socket, errorResponse("frame_truncated"));
2668
+ socket.end();
2669
+ });
2670
+ else socket.end();
2671
+ });
2672
+ }
2673
+ async function drainFrames(socket, state, admission, bindings, mintInvocationContext, quarantine, active) {
2674
+ while (!state.closed && state.buffer.length >= 4 && await processBufferedRequest(socket, state, admission, bindings, mintInvocationContext, quarantine, active)) {
2675
+ }
2676
+ }
2677
+ async function processBufferedRequest(socket, state, admission, bindings, mintInvocationContext, quarantine, active) {
2678
+ const length = state.buffer.readUInt32BE(0);
2679
+ if (length === 0 || length > HOST_PRODUCER_MAX_JSON_BYTES) {
2680
+ const code = length === 0 ? "invalid_frame_length" : "frame_too_large";
2681
+ const raw = state.buffer.subarray(0, Math.min(state.buffer.length, length + 4));
2682
+ await quarantine.retainMalformed(raw, code);
2683
+ writeResponse(socket, errorResponse(code));
2684
+ state.buffer = Buffer.alloc(0);
2685
+ socket.end();
2686
+ return false;
2687
+ }
2688
+ if (state.buffer.length < length + 4) return false;
2689
+ const encoded = state.buffer.subarray(0, length + 4);
2690
+ state.buffer = state.buffer.subarray(length + 4);
2691
+ let request2;
2692
+ try {
2693
+ request2 = decodeIpcRequest(encoded);
2694
+ } catch (error) {
2695
+ const code = error instanceof HostProducerFrameError ? error.code : "invalid_frame_shape";
2696
+ await quarantine.retainMalformed(encoded, code);
2697
+ writeResponse(socket, errorResponse(code));
2698
+ return true;
2699
+ }
2700
+ if (await processHostQuery(socket, request2, bindings, mintInvocationContext)) return true;
2701
+ await processProducerRequest(socket, state, request2, encoded, admission, quarantine, active);
2702
+ return true;
2703
+ }
2704
+ async function processProducerRequest(socket, state, request2, encoded, admission, quarantine, active) {
2705
+ if (!("producer_epoch" in request2)) throw new HostRelayIpcError("relay_unavailable");
2706
+ const ownership = claimProducer(socket, state, request2, active);
2707
+ if (ownership !== null) {
2708
+ if (ownership === "invalid_producer_identity") await quarantine.retainMalformed(encoded, ownership);
2709
+ writeResponse(socket, errorResponse(ownership));
2710
+ if (ownership === "invalid_producer_identity") socket.end();
2711
+ return;
2712
+ }
2713
+ writeResponse(socket, admissionResponse(await admission.admit(request2)));
2714
+ }
2715
+ async function processHostQuery(socket, request2, bindings, mint) {
2716
+ if (request2.schema_version === HOST_RELAY_BINDING_QUERY_SCHEMA) {
2717
+ writeBindingResponse(socket, await bindings.query(bindingQueryFromRequest(request2)));
2718
+ return true;
2719
+ }
2720
+ if (request2.schema_version === HOST_RELAY_INVOCATION_CONTEXT_QUERY_SCHEMA) {
2721
+ writeInvocationContextResponse(socket, await resolveInvocationContext(request2, bindings, mint));
2722
+ return true;
2723
+ }
2724
+ return false;
2725
+ }
2726
+ function claimProducer(socket, state, frame, active) {
2727
+ const key = producerKey(frame);
2728
+ if (state.producer_key !== void 0) return state.producer_key === key && state.producer_epoch === frame.producer_epoch ? null : "invalid_producer_identity";
2729
+ const incumbent = active.get(key);
2730
+ if (incumbent !== void 0 && incumbent.socket !== socket) {
2731
+ if (frame.producer_epoch <= incumbent.epoch) return "producer_already_connected";
2732
+ incumbent.socket.destroy();
2733
+ }
2734
+ state.producer_key = key;
2735
+ state.producer_epoch = frame.producer_epoch;
2736
+ active.set(key, { socket, epoch: frame.producer_epoch });
2737
+ return null;
2738
+ }
2739
+ function closeConnection(socket, state, active, sockets) {
2740
+ state.closed = true;
2741
+ sockets.delete(socket);
2742
+ if (state.producer_key !== void 0 && active.get(state.producer_key)?.socket === socket) active.delete(state.producer_key);
2743
+ }
2744
+ function writeResponse(socket, response2) {
2745
+ if (!socket.destroyed) socket.write(encodeHostRelayIpcResponse(response2));
2746
+ }
2747
+ function writeBindingResponse(socket, result2) {
2748
+ const response2 = { schema_version: HOST_RELAY_BINDING_RESULT_SCHEMA, ...result2 };
2749
+ if (!socket.destroyed) socket.write(encodeLengthPrefixed(response2));
2750
+ }
2751
+ function writeInvocationContextResponse(socket, response2) {
2752
+ if (!socket.destroyed) socket.write(encodeLengthPrefixed(response2));
2753
+ }
2754
+ async function resolveInvocationContext(request2, bindings, mint) {
2755
+ if (mint === void 0) throw new HostRelayIpcError("relay_unavailable");
2756
+ const binding = await bindings.query(bindingQueryFromRequest(request2));
2757
+ if (binding.status !== "ready") return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, ...binding };
2758
+ const result2 = await mint({ client_nonce: request2.client_nonce, context_expires_at: binding.binding.context_expires_at ?? binding.binding.bound_at, request_work_context: relayRequestWorkContextFromBinding(binding.binding) }, new AbortController().signal);
2759
+ return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "ready", result: result2 };
2760
+ }
2761
+ function admissionResponse(result2) {
2762
+ return { schema_version: HOST_RELAY_IPC_RESPONSE_SCHEMA, ...result2 };
2763
+ }
2764
+ function errorResponse(code) {
2765
+ return { schema_version: HOST_RELAY_IPC_RESPONSE_SCHEMA, code, admitted_through_sequence: 0, delivered_through_sequence: 0 };
2766
+ }
2767
+ function producerKey(frame) {
2768
+ return `${frame.producer_id}\0${frame.producer_installation_ref}`;
2769
+ }
2770
+ function record4(value) {
2771
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2772
+ }
2773
+ function decodeIpcRequest(input) {
2774
+ const value = decodeLengthPrefixedJson(input, HOST_PRODUCER_MAX_JSON_BYTES);
2775
+ if (value !== null && record4(value) && value.schema_version === HOST_RELAY_BINDING_QUERY_SCHEMA) {
2776
+ if (!validBindingQueryRequest(value)) throw new HostProducerFrameError("invalid_frame_shape");
2777
+ return value;
2778
+ }
2779
+ if (value !== null && record4(value) && value.schema_version === HOST_RELAY_INVOCATION_CONTEXT_QUERY_SCHEMA) {
2780
+ if (!validInvocationContextQueryRequest(value)) throw new HostProducerFrameError("invalid_frame_shape");
2781
+ return value;
2782
+ }
2783
+ return decodeHostProducerFrame(input);
2784
+ }
2785
+ function validBindingQueryRequest(value) {
2786
+ return validQueryIdentity(value, HOST_RELAY_BINDING_QUERY_SCHEMA) && exactKeys4(value, ["schema_version", "producer_id", "producer_installation_ref", "local_session_ref", "local_turn_ref"]);
2787
+ }
2788
+ function bindingQueryFromRequest(value) {
2789
+ return { producer_id: value.producer_id, producer_installation_ref: value.producer_installation_ref, local_session_ref: value.local_session_ref, local_turn_ref: value.local_turn_ref };
2790
+ }
2791
+ function validInvocationContextQueryRequest(value) {
2792
+ return validQueryIdentity(value, HOST_RELAY_INVOCATION_CONTEXT_QUERY_SCHEMA) && exactKeys4(value, ["schema_version", "producer_id", "producer_installation_ref", "local_session_ref", "local_turn_ref", "client_nonce"]) && typeof value.client_nonce === "string" && CEAL_HOST_CLIENT_NONCE_PATTERN.test(value.client_nonce);
2793
+ }
2794
+ function validQueryIdentity(value, schema) {
2795
+ return record4(value) && value.schema_version === schema && (value.producer_id === "codex" || value.producer_id === "claude") && safeRef3(value.producer_installation_ref) && safeRef3(value.local_session_ref) && safeRef3(value.local_turn_ref);
2796
+ }
2797
+ function decodeLengthPrefixedJson(input, maximum) {
2798
+ if (input.length < 4) return null;
2799
+ const length = input.readUInt32BE(0);
2800
+ if (length === 0 || length > maximum) throw new HostRelayIpcError("relay_unavailable", `Host Relay IPC message length is invalid: ${refusalFact("declared_bytes", length, `between 1 and ${maximum}`)}.`);
2801
+ if (input.length < length + 4) return null;
2802
+ if (input.length !== length + 4) throw new HostRelayIpcError("relay_unavailable", `Host Relay IPC message has trailing bytes: ${refusalFacts([{ name: "declared_bytes", value: length, expected: "the received message length minus 4" }, { name: "received_bytes", value: input.byteLength, expected: `exactly ${length + 4}` }])}.`);
2803
+ try {
2804
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(input.subarray(4)));
2805
+ } catch {
2806
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC message is invalid.");
2807
+ }
2808
+ }
2809
+ function encodeLengthPrefixed(value) {
2810
+ const body = Buffer.from(JSON.stringify(value), "utf8");
2811
+ const output = Buffer.allocUnsafe(body.length + 4);
2812
+ output.writeUInt32BE(body.length, 0);
2813
+ body.copy(output, 4);
2814
+ return output;
2815
+ }
2816
+ function exactKeys4(value, keys) {
2817
+ return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
2818
+ }
2819
+ function safeRef3(value) {
2820
+ return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(value);
2821
+ }
2822
+ async function assertEndpointVacant(endpoint) {
2823
+ try {
2824
+ await lstat3(endpoint);
2825
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is already present.");
2826
+ } catch (error) {
2827
+ if (errorCode7(error) !== "ENOENT") throw error;
2828
+ }
2829
+ }
2830
+ function listen(server, endpoint) {
2831
+ return new Promise((resolve, reject) => {
2832
+ server.once("error", reject);
2833
+ server.listen(endpoint, () => {
2834
+ server.removeListener("error", reject);
2835
+ resolve();
2836
+ });
2837
+ });
2838
+ }
2839
+ async function closeServer(server, sockets, endpoint) {
2840
+ for (const socket of sockets) socket.destroy();
2841
+ await new Promise((resolve) => server.close(() => resolve()));
2842
+ if (process.platform !== "win32") await unlink2(endpoint).catch(() => void 0);
2843
+ }
2844
+ function errorCode7(error) {
2845
+ return record4(error) && typeof error.code === "string" ? error.code : null;
2846
+ }
2847
+
2848
+ // host/relay/src/host-relay-runtime.ts
2849
+ var HOST_RELAY_CONFIG_SCHEMA = "ceal.host_relay_config.v1";
2850
+ var HostRelayConfigError = class extends Error {
2851
+ name = "HostRelayConfigError";
2852
+ code;
2853
+ constructor(code, message) {
2854
+ super(message);
2855
+ this.code = code;
2856
+ }
2857
+ };
2858
+ async function readHostRelayConfig(path) {
2859
+ if (!isAbsoluteNormalizedNonRootPath(path, process.platform, true)) throw new HostRelayConfigError("invalid_config_path", `invalid_config_path: Host Relay config path is invalid: ${refusalFact("config_path", path, "absolute, normalized, and non-root")}.`);
2860
+ let handle;
2861
+ try {
2862
+ await assertOwnerPrivateDirectory2(dirname3(path));
2863
+ handle = await open4(path, O_RDONLY4 | O_NOFOLLOW3);
2864
+ const stats = await handle.stat();
2865
+ if (!stats.isFile() || !ownerPrivate4(stats)) throw new HostRelayConfigError("config_not_private", "Host Relay config file is not owner-private.");
2866
+ if (stats.size < 2 || stats.size > 65536) throw new HostRelayConfigError("invalid_config", `invalid_config: Host Relay config size is invalid: ${refusalFact("config_bytes", stats.size, "between 2 and 65536")}.`);
2867
+ const text = await handle.readFile("utf8");
2868
+ assertNoDuplicateJsonKeys(text);
2869
+ let value;
2870
+ try {
2871
+ value = JSON.parse(text);
2872
+ } catch {
2873
+ throw new HostRelayConfigError("invalid_json", "Host Relay config is not JSON.");
2874
+ }
2875
+ return decodeHostRelayConfig(value);
2876
+ } catch (error) {
2877
+ if (error instanceof HostRelayConfigError) throw error;
2878
+ throw new HostRelayConfigError("config_unavailable", "Host Relay config is unavailable.");
2879
+ } finally {
2880
+ await handle?.close();
2881
+ }
2882
+ }
2883
+ function decodeHostRelayConfig(value) {
2884
+ const required = ["schema_version", "registration_state_file", "host_source_ref", "state_root", "ipc_endpoint"];
2885
+ const optional = ["drain_interval_ms", "gateway_timeout_ms"];
2886
+ if (!record5(value) || !exactOptionalKeys2(value, required, optional) || !validConfigIdentity(value) || !validConfigRuntime(value)) {
2887
+ throw new HostRelayConfigError("invalid_config", "Host Relay config shape is invalid.");
2888
+ }
2889
+ return {
2890
+ schema_version: HOST_RELAY_CONFIG_SCHEMA,
2891
+ registration_state_file: value.registration_state_file,
2892
+ host_source_ref: value.host_source_ref,
2893
+ state_root: value.state_root,
2894
+ ipc_endpoint: value.ipc_endpoint,
2895
+ drain_interval_ms: value.drain_interval_ms ?? 250,
2896
+ gateway_timeout_ms: value.gateway_timeout_ms ?? 5e3
2897
+ };
2898
+ }
2899
+ function validConfigIdentity(value) {
2900
+ return value.schema_version === HOST_RELAY_CONFIG_SCHEMA && isAbsoluteNormalizedNonRootPath(value.registration_state_file, process.platform, true) && opaqueHostSourceRef(value.host_source_ref);
2901
+ }
2902
+ function validConfigRuntime(value) {
2903
+ return isAbsoluteNormalizedNonRootPath(value.state_root, process.platform, true) && isAbsoluteNormalizedNonRootPath(value.ipc_endpoint, process.platform, true) && boundedInteger(value.drain_interval_ms, 50, 3e4, true) && boundedInteger(value.gateway_timeout_ms, 100, 6e4, true);
2904
+ }
2905
+ async function serveHostRelay(config, signal, dependencies = {}) {
2906
+ const admission = new RelayAdmissionStore(join6(config.state_root, "admission"));
2907
+ const bindings = new RelayRequestBindingStore(join6(config.state_root, "bindings"));
2908
+ const gateway = (dependencies.createGateway ?? createHostRelayGatewayHttpPort)({ registration_state_file: config.registration_state_file, host_source_ref: config.host_source_ref });
2909
+ const bridge = new RelayGatewayBridge({ state_root: join6(config.state_root, "gateway"), host_source_ref: config.host_source_ref, gateway, timeout_ms: config.gateway_timeout_ms, on_request_bound: async (binding) => {
2910
+ await bindings.bind(binding);
2911
+ } });
2912
+ let server;
2913
+ try {
2914
+ server = await (dependencies.startIpc ?? startHostRelayIpcServer)({ endpoint: config.ipc_endpoint, admission, bindings, mintInvocationContext: (input, invocationSignal) => gateway.mintInvocationContext(input, invocationSignal) });
2915
+ while (!signal.aborted) {
2916
+ const round = await admission.drainRound((input) => bridge.deliver(input), { now_ms: (dependencies.now ?? Date.now)(), host_source_ref: config.host_source_ref });
2917
+ if (round.delivered.length === 0 && round.refused.length === 0) await (dependencies.wait ?? ((milliseconds, waitSignal) => waitForAbort(waitSignal, milliseconds)))(config.drain_interval_ms, signal);
2918
+ }
2919
+ } finally {
2920
+ await server?.close();
2921
+ }
2922
+ }
2923
+ async function runHostRelayCli(args, signal, dependencies = {}) {
2924
+ try {
2925
+ const configPath = parseServeArgs(args);
2926
+ const config = await (dependencies.readConfig ?? readHostRelayConfig)(configPath);
2927
+ await serveHostRelay(config, signal, dependencies);
2928
+ return { ok: true, status: "stopped" };
2929
+ } catch (error) {
2930
+ if (error instanceof HostRelayConfigError) return { ok: false, code: error.code };
2931
+ return { ok: false, ...hostTerminalFailure(error, "Relay") };
2932
+ }
2933
+ }
2934
+ function parseServeArgs(args) {
2935
+ if (args.length !== 3 || args[0] !== "serve" || args[1] !== "--config" || !isAbsoluteNormalizedNonRootPath(args[2], process.platform, true)) {
2936
+ throw new HostRelayConfigError("invalid_config_path", `invalid_config_path: Use: relay.mjs serve --config <absolute-owner-private-json>: ${refusalFact("args", args, "serve --config <absolute normalized non-root path>")}.`);
2937
+ }
2938
+ return args[2];
2939
+ }
2940
+ async function assertOwnerPrivateDirectory2(path) {
2941
+ try {
2942
+ const stats = await lstat4(path);
2943
+ if (!stats.isDirectory() || stats.isSymbolicLink() || !ownerPrivate4(stats)) throw new HostRelayConfigError("config_not_private", "Host Relay config directory is not owner-private.");
2944
+ } catch (error) {
2945
+ if (error instanceof HostRelayConfigError) throw error;
2946
+ throw new HostRelayConfigError("config_unavailable", "Host Relay config directory is unavailable.");
2947
+ }
2948
+ }
2949
+ function ownerPrivate4(stats) {
2950
+ if (process.platform === "win32") return true;
2951
+ const uid = typeof process.geteuid === "function" ? process.geteuid() : stats.uid;
2952
+ return stats.uid === uid && (stats.mode & 63) === 0;
2953
+ }
2954
+ function assertNoDuplicateJsonKeys(text) {
2955
+ rejectDuplicateJsonKeys(text, {
2956
+ invalid: () => new HostRelayConfigError("invalid_json", "Host Relay config is not JSON."),
2957
+ duplicate: () => new HostRelayConfigError("duplicate_config_field", "Host Relay config contains a duplicate field.")
2958
+ });
2959
+ }
2960
+ function boundedInteger(value, minimum, maximum, optional) {
2961
+ return optional && value === void 0 || Number.isSafeInteger(value) && Number(value) >= minimum && Number(value) <= maximum;
2962
+ }
2963
+ function record5(value) {
2964
+ return value !== null && typeof value === "object" && !Array.isArray(value);
2965
+ }
2966
+ function exactOptionalKeys2(value, required, optional) {
2967
+ const keys = Object.keys(value);
2968
+ return required.every((key) => Object.hasOwn(value, key)) && keys.every((key) => required.includes(key) || optional.includes(key));
2969
+ }
2970
+
2971
+ // host/relay/bin/ceal-host-relay.ts
2972
+ var controller = new AbortController();
2973
+ var stop = () => controller.abort();
2974
+ process.once("SIGINT", stop);
2975
+ process.once("SIGTERM", stop);
2976
+ void runHostRelayCli(process.argv.slice(2), controller.signal).then((result2) => {
2977
+ process.stdout.write(`${JSON.stringify({ schema_version: "ceal.host_relay_command.v1", ...result2 })}
2978
+ `);
2979
+ process.exitCode = result2.ok ? 0 : 1;
2980
+ }).catch((error) => {
2981
+ process.stdout.write(`${JSON.stringify({ schema_version: "ceal.host_relay_command.v1", ok: false, ...hostTerminalFailure(error, "Relay") })}
2982
+ `);
2983
+ process.exitCode = 1;
2984
+ }).finally(() => {
2985
+ process.removeListener("SIGINT", stop);
2986
+ process.removeListener("SIGTERM", stop);
2987
+ });