@corca-org/ceal-host-linux-arm64 1.0.17 → 1.0.19

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.
@@ -109,6 +109,9 @@ var client_wire_contract_default = {
109
109
  "document"
110
110
  ],
111
111
  optional_fields: [
112
+ "operation_id",
113
+ "visible_output_max_bytes",
114
+ "local_delivery",
112
115
  "verified_artifact"
113
116
  ],
114
117
  bare_document_fields: [
@@ -195,11 +198,15 @@ var CEAL_COMMAND_RESPONSE_FOCUSED_PROMPT_CONTINUATION_DOCUMENT_FIELDS = Object.f
195
198
  var CEAL_COMMAND_RESPONSE_DISCOVERY_COMMAND = response.discovery_command;
196
199
  var CEAL_COMMAND_RESPONSE_DISCOVERY_MANIFEST_SCHEMA_VERSION = response.discovery_manifest_schema_version;
197
200
  var CEAL_COMMAND_RESPONSE_DISCOVERY_MANIFEST_DOCUMENT_FIELDS = Object.freeze([...response.discovery_manifest_document_fields]);
201
+ var CEAL_COMMAND_RESPONSE_MAX_BYTES = CEAL_ENCODED_JSON_DOCUMENT_MAX_BYTES;
198
202
 
199
203
  // packages/ceal-client-protocol/src/vocabulary.ts
200
204
  function vocabulary(words) {
201
205
  return Object.freeze(words);
202
206
  }
207
+ function isVocabularyWord(words, value) {
208
+ return words.some((word) => word === value);
209
+ }
203
210
 
204
211
  // packages/ceal-client-protocol/src/gateway-response-types.ts
205
212
  var CEAL_OPERATION_READINESS_VALUES = vocabulary(["ready", "degraded", "unavailable", "unknown"]);
@@ -222,6 +229,7 @@ var CEAL_WRITE_RECEIPT_PROVIDER_STATES = vocabulary(["outcome_unknown", "verifie
222
229
  var CEAL_WRITE_RECEIPT_PROVIDER_READBACKS = vocabulary(["outcome_unknown", "verified", "not_applied"]);
223
230
  var CEAL_PROTOCOL_VERSION = "1.4.0";
224
231
  var CEAL_OPERATION_ACCESS_SCHEMA_VERSION = "ceal.operation_access.v1";
232
+ var CEAL_GATEWAY_CONTINUATION_CURSOR_PHASES = vocabulary(["scan", "delivery", "terminal"]);
225
233
  var CEAL_GATEWAY_ACTIVE_CALL_PHASES = vocabulary([
226
234
  "audited_call_pending",
227
235
  "continuation_read_pending",
@@ -245,6 +253,7 @@ var CEAL_GATEWAY_ORGANIZATION_ROUTE_FACT_CALL_KEYS = Object.freeze([
245
253
  // packages/ceal-client-protocol/src/operation-next-actions.ts
246
254
  var CEAL_REPEAT_REQUEST_NEXT_ACTION = "repeat_request";
247
255
  var CEAL_INSPECT_RECEIPT_NEXT_ACTION = "inspect_receipt";
256
+ var CEAL_ANSWER_WITH_GAP_NEXT_ACTION = "answer_with_gap";
248
257
  var CALLER_RECOVERABLE_NEXT_ACTION_VALUES = [
249
258
  "select_did_you_mean",
250
259
  "choose_new_output_path",
@@ -298,10 +307,20 @@ var CALLER_RECOVERABLE_NEXT_ACTION_VALUES = [
298
307
  "retry_after",
299
308
  // The ref names a container of rows (a Notion database or data source), which
300
309
  // has no body of its own; the caller searches its rows instead of reading it.
301
- "search_container_rows"
310
+ "search_container_rows",
311
+ // A settled unknown write names the exact receipt Operation that can inspect
312
+ // its outcome without issuing another provider mutation.
313
+ "write_receipt.get",
314
+ // Command resolution carries the exact required Operation sequence beside
315
+ // this action, so the caller can execute each declared input in order.
316
+ "follow_required_action_sequence",
317
+ // The command needs caller-owned local materialization (for example an
318
+ // @path file) before the Gateway can receive the argument.
319
+ "materialize_local_argument"
302
320
  ];
303
321
  var CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS = Object.freeze(CALLER_RECOVERABLE_NEXT_ACTION_VALUES);
304
322
  var NON_REMEDY_NEXT_ACTION_VALUES = [
323
+ CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
305
324
  // Only an administrator can take the named step -- approving a place for an
306
325
  // Operation, granting a withheld capability -- so a non-administrator asks
307
326
  // one. The refusal names the administrator step; this word is the ask.
@@ -349,7 +368,58 @@ var NON_REMEDY_NEXT_ACTION_VALUES = [
349
368
  "select_exact_approval"
350
369
  ];
351
370
  var CEAL_NON_REMEDY_NEXT_ACTIONS = Object.freeze(NON_REMEDY_NEXT_ACTION_VALUES);
352
- var DECLARED = /* @__PURE__ */ new Set([...CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS, ...CEAL_NON_REMEDY_NEXT_ACTIONS]);
371
+ var CEAL_DECLARED_NEXT_ACTIONS = Object.freeze([...CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS, ...CEAL_NON_REMEDY_NEXT_ACTIONS]);
372
+ var DECLARED = new Set(CEAL_DECLARED_NEXT_ACTIONS);
373
+ function defineCealNonModelNextActions(actions) {
374
+ return actions;
375
+ }
376
+ var NON_MODEL_NEXT_ACTION_VALUES = defineCealNonModelNextActions([
377
+ CEAL_INSPECT_RECEIPT_NEXT_ACTION,
378
+ "await_pending_approval",
379
+ "inspect_gateway",
380
+ "operator_action",
381
+ "none",
382
+ "check_gateway",
383
+ "inspect_context_store",
384
+ "inspect_local_cache",
385
+ "inspect_local_client",
386
+ "inspect_local_command",
387
+ "inspect_local_output",
388
+ "inspect_local_route",
389
+ "inspect_request",
390
+ "reconcile",
391
+ "reconcile_occurrence",
392
+ "retry_after_owner_recovery",
393
+ "select_exact_approval"
394
+ ]);
395
+ var NON_MODEL_NEXT_ACTIONS = new Set(NON_MODEL_NEXT_ACTION_VALUES);
396
+ function isCealModelActionableNonRemedyNextAction(action) {
397
+ return !NON_MODEL_NEXT_ACTIONS.has(action);
398
+ }
399
+ var CEAL_MODEL_ACTIONABLE_NEXT_ACTIONS = Object.freeze([
400
+ ...CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS,
401
+ ...CEAL_NON_REMEDY_NEXT_ACTIONS.filter(isCealModelActionableNonRemedyNextAction)
402
+ ]);
403
+ var MODEL_ACTIONABLE = new Set(CEAL_MODEL_ACTIONABLE_NEXT_ACTIONS);
404
+ var NON_MODEL_ACTION_TO_MODEL_ACTION = Object.freeze({
405
+ [CEAL_INSPECT_RECEIPT_NEXT_ACTION]: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
406
+ await_pending_approval: "ask_admin",
407
+ inspect_gateway: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
408
+ operator_action: "ask_admin",
409
+ none: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
410
+ check_gateway: "ask_admin",
411
+ inspect_context_store: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
412
+ inspect_local_cache: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
413
+ inspect_local_client: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
414
+ inspect_local_command: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
415
+ inspect_local_output: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
416
+ inspect_local_route: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
417
+ inspect_request: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
418
+ reconcile: CEAL_ANSWER_WITH_GAP_NEXT_ACTION,
419
+ reconcile_occurrence: "ask_admin",
420
+ retry_after_owner_recovery: "ask_admin",
421
+ select_exact_approval: "ask_admin"
422
+ });
353
423
  var RETRY_PROMISE_NEXT_ACTIONS = ["retry", "retry_after"];
354
424
  var RETRY_PROMISE = new Set(RETRY_PROMISE_NEXT_ACTIONS);
355
425
  var RECOVERABLE = new Set(CEAL_CALLER_RECOVERABLE_NEXT_ACTIONS);
@@ -619,21 +689,15 @@ var CEAL_OPERATION_ACCESS_CLASSES = vocabulary(["read", "write"]);
619
689
  // packages/ceal-client-protocol/src/domain-vocabulary.ts
620
690
  var CEAL_CONNECTOR_STATUSES = vocabulary(["active", "disabled", "disconnected"]);
621
691
  var CEAL_CONNECTOR_CUSTODIES = vocabulary(["organization", "personal"]);
622
- var CEAL_PROVIDER_BOUNDARY_KINDS = vocabulary([
623
- "github_account",
624
- "github_organization",
625
- "google_workspace_domain",
626
- "notion_workspace",
627
- "slack_workspace"
628
- ]);
629
- var CEAL_PROVIDER_BOUNDARY_EVIDENCE = vocabulary(["provider_readback", "operator_stated"]);
630
692
  var CEAL_ACCESS_LEVELS = vocabulary(["none", "read", "read_write"]);
631
693
  var CEAL_PERSONAL_ACCESS_CEILINGS = vocabulary(["disabled", "read", "read_write"]);
632
694
  var CEAL_TARGET_REF_PATTERN = "^[^\\p{Cc}]+$";
633
695
  var TARGET_REF = new RegExp(CEAL_TARGET_REF_PATTERN, "u");
634
696
  var CEAL_TARGET_VISIBILITIES = vocabulary(["public", "private"]);
635
- var CEAL_PRINCIPAL_KINDS = vocabulary(["human", "service", "runtime"]);
697
+ var CEAL_PRINCIPAL_KINDS = vocabulary(["human", "runtime"]);
698
+ var CEAL_PERSISTED_PRINCIPAL_KINDS = vocabulary(["human", "service", "runtime"]);
636
699
  var CEAL_ORGANIZATION_ROLES = vocabulary(["member", "admin"]);
700
+ var CEAL_CALENDAR_PERIODS = vocabulary(["day", "week", "month"]);
637
701
  var LABEL_EXPECTATION = `public-safe display text of at most ${CEAL_PUBLIC_DISPLAY_NAME_MAX_BYTES} bytes`;
638
702
 
639
703
  // packages/ceal-client-protocol/src/safe-json-budget.ts
@@ -809,7 +873,7 @@ var CEAL_SCHEMA_LITERALS = [
809
873
  "ceal.operation_receipt.v1",
810
874
  "ceal.operation_result.v1",
811
875
  "ceal.operation_result.compact.v1",
812
- "ceal.local_result_materialization.v1",
876
+ "ceal.local_result_file.v1",
813
877
  "ceal.local_result_root.v1",
814
878
  "ceal.owner_bootstrap_exchange_request.v1",
815
879
  "ceal.owner_bootstrap_exchange_result.v1",
@@ -839,6 +903,9 @@ var CEAL_BOUNDED_SERIES_CATALOG = Object.freeze({
839
903
  gateway_personal_client_access_audit: (root) => join(root, "access-audit.jsonl")
840
904
  });
841
905
 
906
+ // packages/ceal-client-protocol/src/canonical-http-boundary.ts
907
+ var CEAL_CANONICAL_HTTP_MAX_RESPONSE_BYTES = CEAL_COMMAND_RESPONSE_MAX_BYTES;
908
+
842
909
  // packages/ceal-client-protocol/src/gateway-installation-activation.ts
843
910
  var CEAL_GATEWAY_INSTALLATION_ACTIVATION_CODE_DATA_CHARACTERS = 32;
844
911
  var CEAL_GATEWAY_INSTALLATION_ACTIVATION_CODE_CHECK_CHARACTERS = 8;
@@ -904,41 +971,6 @@ var CEAL_VERIFIED_ARTIFACT_DESCRIPTOR_JSON_SCHEMA = Object.freeze({
904
971
  }
905
972
  });
906
973
 
907
- // packages/ceal-client-protocol/src/provider-operation-vocabulary.ts
908
- var CEAL_FILE_TYPE_FAMILIES = vocabulary(["all", "image", "pdf"]);
909
- var CEAL_GITHUB_ISSUE_STATES = vocabulary(["open", "closed", "all"]);
910
- var CEAL_NOTION_UPDATABLE_BLOCK_TYPES = vocabulary([
911
- "paragraph",
912
- "heading_1",
913
- "heading_2",
914
- "heading_3",
915
- "bulleted_list_item",
916
- "numbered_list_item",
917
- "to_do",
918
- "code"
919
- ]);
920
- var CEAL_NOTION_NEUTRAL_TYPES = vocabulary([
921
- "text",
922
- "number",
923
- "boolean",
924
- "date",
925
- "select",
926
- "multi_select",
927
- "people",
928
- "url",
929
- "email",
930
- "phone",
931
- "unsupported"
932
- ]);
933
- var CEAL_NOTION_IDENTITY_GAP_REASONS = vocabulary([
934
- "identity_unavailable",
935
- "identity_stale",
936
- "identity_ambiguous",
937
- "identity_revoked",
938
- "identity_unlinked"
939
- ]);
940
- var CEAL_NOTION_STRING_VALUE_TYPES = vocabulary(["text", "select", "url", "email", "phone"]);
941
-
942
974
  // packages/ceal-client-protocol/src/opaque-reference.ts
943
975
  var CEAL_OPAQUE_HANDLE_KINDS = vocabulary(["target", "message", "thread", "artifact", "document", "block", "object"]);
944
976
  var CEAL_OPAQUE_REF_KINDS = vocabulary([...CEAL_OPAQUE_HANDLE_KINDS, "result", "operation-receipt", "reply-receipt", "field", "notion-data-source"]);
@@ -950,7 +982,7 @@ var OPTIONAL_FIELDS = CEAL_CLIENT_WIRE_CONTRACT.command_response.bare_document_o
950
982
  // packages/ceal-client-protocol/src/resource-row.ts
951
983
  var CEAL_RESOURCE_SEARCH_ORDERS = vocabulary(["relevance", "modified", "viewed", "created"]);
952
984
  var CEAL_RESOURCE_SEARCH_DIRECTIONS = vocabulary(["ascending", "descending"]);
953
- var CEAL_RESOURCE_SEARCH_FILTERS = vocabulary(["query", "modified_since", "since", "until", "authored_by_me", "include_replies", "kinds", "container_ref", "container_refs", "container_names", "addressed_to_me", "unread"]);
985
+ var CEAL_RESOURCE_SEARCH_FILTERS = vocabulary(["query", "modified_since", "since", "until", "authored_by_me", "authored_by", "include_replies", "kinds", "container_ref", "container_refs", "container_names", "addressed_to_me", "unread"]);
954
986
  var CEAL_RESOURCE_TIME_BASES = vocabulary(["created", "modified", "viewed"]);
955
987
  var CEAL_REPOSITORY_VISIBILITIES = vocabulary(["public", "private", "internal"]);
956
988
  var CEAL_ACTIVITY_V3_KINDS = vocabulary(["authored", "edited", "messaged", "responded"]);
@@ -971,6 +1003,7 @@ var CEAL_ACTIVITY_TIMESTAMP_BASES = vocabulary([
971
1003
  "resource_modified"
972
1004
  ]);
973
1005
  var CEAL_ACTIVITY_CONNECTOR_KINDS = vocabulary(["slack", "github", "google-calendar", "google-drive", "notion"]);
1006
+ var CEAL_ACTIVITY_UNSUPPORTED_EVENT_KIND_CODE = "unsupported_event_kind";
974
1007
  var CEAL_ACTIVITY_GAP_CODES = vocabulary([
975
1008
  "provider_page_budget",
976
1009
  "call_deadline",
@@ -978,7 +1011,7 @@ var CEAL_ACTIVITY_GAP_CODES = vocabulary([
978
1011
  "provider_cursor_unavailable",
979
1012
  "malformed_provider_page",
980
1013
  "visibility_incomplete",
981
- "unsupported_event_kind",
1014
+ CEAL_ACTIVITY_UNSUPPORTED_EVENT_KIND_CODE,
982
1015
  "direct_messages_excluded"
983
1016
  ]);
984
1017
  var CEAL_ACTIVITY_EVENT_KINDS = vocabulary([
@@ -1029,6 +1062,7 @@ var RESOURCE_ROW_KEY_RULES = Object.freeze({
1029
1062
  ref: { required: true, timestamp: false },
1030
1063
  next: { required: true, timestamp: false },
1031
1064
  kind: { required: true, timestamp: false },
1065
+ matched_kinds: { required: false, timestamp: false },
1032
1066
  title: { required: true, timestamp: false },
1033
1067
  container_label: { required: true, timestamp: false },
1034
1068
  container_ref: { required: false, timestamp: false },
@@ -1042,6 +1076,8 @@ var RESOURCE_ROW_KEY_RULES = Object.freeze({
1042
1076
  modified_at: { required: false, timestamp: true },
1043
1077
  modified_at_local: { required: false, timestamp: true },
1044
1078
  viewed_by_me_at: { required: false, timestamp: true },
1079
+ own_ceal_write: { required: false, timestamp: false },
1080
+ owned_by_me: { required: false, timestamp: false },
1045
1081
  visibility: { required: false, timestamp: false },
1046
1082
  start: { required: false, timestamp: false },
1047
1083
  end: { required: false, timestamp: false },
@@ -1075,6 +1111,15 @@ function cealExcludedTargetCoverageJsonSchema() {
1075
1111
  };
1076
1112
  }
1077
1113
 
1114
+ // packages/ceal-client-protocol/src/gateway-write-identity.ts
1115
+ var CEAL_GATEWAY_WRITE_IDENTITY_ROLES = Object.freeze(["replay_identity", "lookup_handle", "collision_evidence"]);
1116
+ var CEAL_GATEWAY_WRITE_REQUEST_REF_PATTERN = /^gateway-write-request:[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$/u;
1117
+ var CEAL_GATEWAY_WRITE_IDENTITY_FIELDS = Object.freeze({
1118
+ replay_identity: "idempotency_claim_sha256",
1119
+ lookup_handle: "write_request_sha256",
1120
+ collision_evidence: "normalized_mutation_sha256"
1121
+ });
1122
+
1078
1123
  // packages/ceal-client-protocol/src/write-safety-finding.ts
1079
1124
  var CEAL_WRITE_SAFETY_FINDING_STATUSES = vocabulary(["warning", "unchecked"]);
1080
1125
  var CEAL_WRITE_SAFETY_AUDIENCES = vocabulary(["workspace", "person", "members", "unknown"]);
@@ -1102,7 +1147,11 @@ var CEAL_REFRESH_FAILURE_CODES = vocabulary([
1102
1147
  "refresh_revoked",
1103
1148
  "authority_replaced",
1104
1149
  "refresh_recovery_unavailable",
1105
- "refresh_recovery_expired"
1150
+ "refresh_recovery_expired",
1151
+ // The serving gate answers this while the Gateway is still starting and the
1152
+ // refresh was never attempted; the same attempt stays retryable. It is never
1153
+ // stored by the session owner, only answered at the serving edge.
1154
+ "gateway_starting"
1106
1155
  ]);
1107
1156
 
1108
1157
  // packages/ceal-client-protocol/src/request-validation-primitives.ts
@@ -1135,7 +1184,7 @@ var CANCELLATION_STATES = vocabulary(["requested", "cancelled"]);
1135
1184
  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"]);
1136
1185
  var CEAL_REQUEST_JSON_SCHEMA = {
1137
1186
  type: "object",
1138
- maxProperties: 10,
1187
+ maxProperties: 11,
1139
1188
  additionalProperties: false,
1140
1189
  properties: {
1141
1190
  schema_version: { type: "string", const: CEAL_REQUEST_SCHEMA_VERSION, maxLength: 32 },
@@ -1159,7 +1208,8 @@ var CEAL_REQUEST_JSON_SCHEMA = {
1159
1208
  host_turn_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
1160
1209
  host_input_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
1161
1210
  host_source_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source },
1162
- requester_timezone: { type: "string", minLength: 1, maxLength: 128, description: "IANA timezone observed for the requester on this Request." }
1211
+ requester_timezone: { type: "string", minLength: 1, maxLength: 128, description: "IANA timezone observed for the requester on this Request." },
1212
+ device_ref: { type: "string", minLength: 1, maxLength: 128, pattern: SAFE_REF.source, description: "Device that submitted this Request through its client session; absent for Host turns and older records." }
1163
1213
  },
1164
1214
  required: CEAL_REQUEST_KEYS
1165
1215
  };
@@ -1218,6 +1268,7 @@ var REQUEST_EXECUTION_PREPARE_REFUSAL_PROPERTIES = {
1218
1268
  retryable: { type: "boolean" },
1219
1269
  source: { type: "string", enum: ["provider", "gateway"] },
1220
1270
  retry_after_ms: { type: "integer", minimum: 0, maximum: CEAL_RETRY_AFTER_MAX_MS },
1271
+ write_request_ref: { type: "string", pattern: CEAL_GATEWAY_WRITE_REQUEST_REF_PATTERN.source, maxLength: 128 },
1221
1272
  excluded_targets: cealExcludedTargetCoverageJsonSchema(),
1222
1273
  repaired_input: {},
1223
1274
  unrepaired_pointers: { type: "array", maxItems: 128, items: { type: "string", minLength: 1, maxLength: 256 } },
@@ -1276,6 +1327,7 @@ function isCealHostInputKind(value) {
1276
1327
  return typeof value === "string" && CEAL_HOST_INPUT_KINDS.some((kind) => kind === value);
1277
1328
  }
1278
1329
  var CEAL_HOST_OBSERVATION_REF_PREFIX = "host-observation:";
1330
+ var HOST_TOKEN_OBSERVATION_BREAKDOWN_KEYS = vocabulary(["cached_input", "cache_write_input", "reasoning_output"]);
1279
1331
  function validateCealHostObservationDraft(value) {
1280
1332
  const record6 = operationRecord(value, "Ceal Host observation draft is invalid.");
1281
1333
  requirePrefixedRef(record6.observation_ref, CEAL_HOST_OBSERVATION_REF_PREFIX, "Ceal Host observation reference is invalid.");
@@ -1419,6 +1471,104 @@ var CEAL_HOST_INVOCATION_AUTHENTICATION_RESULT_MAX_BYTES = new TextEncoder().enc
1419
1471
  expires_at: (/* @__PURE__ */ new Date("+010000-01-01T00:00:00.000Z")).toISOString()
1420
1472
  })}
1421
1473
  `).byteLength;
1474
+ var CEAL_HOST_MINT_REQUEST_CONTEXT_REFUSAL_REASONS = vocabulary([
1475
+ "request_authority_unavailable",
1476
+ "request_missing",
1477
+ "authority_mismatch",
1478
+ "host_source_mismatch",
1479
+ "host_session_mismatch",
1480
+ "host_turn_mismatch",
1481
+ "host_input_mismatch",
1482
+ "host_prompt_mismatch"
1483
+ ]);
1484
+ var CEAL_HOST_AUTHENTICATION_CAUSES = vocabulary([
1485
+ "invalid_arguments",
1486
+ "options_invalid",
1487
+ "session_unavailable",
1488
+ "context_unavailable",
1489
+ "context_replaced",
1490
+ "no_binding",
1491
+ "context_stale",
1492
+ "context_expired",
1493
+ "host_source_refused",
1494
+ "host_credential_refused",
1495
+ "gateway_unavailable",
1496
+ "gateway_rate_limited",
1497
+ "gateway_refused",
1498
+ "gateway_response_invalid",
1499
+ "producer_frame_invalid",
1500
+ "relay_permission_denied",
1501
+ "relay_unavailable",
1502
+ "transient_retryable",
1503
+ "mint_failed",
1504
+ "relay_failed",
1505
+ "host_refusal_invalid"
1506
+ ]);
1507
+ var CEAL_HOST_AUTHENTICATION_POLICY = Object.freeze({
1508
+ invalid_arguments: Object.freeze({ classification: "host_arguments_invalid", next_action: "answer_with_gap" }),
1509
+ options_invalid: Object.freeze({ classification: "host_configuration_invalid", next_action: "answer_with_gap" }),
1510
+ session_unavailable: Object.freeze({ classification: "host_session_unavailable", next_action: "answer_with_gap" }),
1511
+ context_unavailable: Object.freeze({ classification: "host_context_unavailable", next_action: "refresh_host_invocation_context", remedy: "the Host has no invocation context from the current transcript turn; run `ceal-host install` to repair the Host hook registration, then retry this command on a fresh Host turn" }),
1512
+ context_replaced: Object.freeze({ classification: "host_invocation_context_stale", next_action: "refresh_host_invocation_context" }),
1513
+ no_binding: Object.freeze({ classification: "host_binding_unavailable", next_action: "refresh_host_invocation_context" }),
1514
+ context_stale: Object.freeze({ classification: "host_invocation_context_stale", next_action: "refresh_host_invocation_context" }),
1515
+ context_expired: Object.freeze({ classification: "host_invocation_context_expired", next_action: "refresh_host_invocation_context" }),
1516
+ host_source_refused: Object.freeze({ classification: "host_source_refused", next_action: "answer_with_gap" }),
1517
+ host_credential_refused: Object.freeze({ classification: "host_registration_credential_refused", next_action: "ask_admin" }),
1518
+ gateway_unavailable: Object.freeze({ classification: "host_mint_gateway_unavailable", next_action: "ask_admin" }),
1519
+ gateway_rate_limited: Object.freeze({ classification: "host_mint_gateway_rate_limited", next_action: "answer_with_gap" }),
1520
+ gateway_refused: Object.freeze({ classification: "host_mint_gateway_refused", next_action: "answer_with_gap" }),
1521
+ gateway_response_invalid: Object.freeze({ classification: "host_mint_gateway_response_invalid", next_action: "answer_with_gap" }),
1522
+ producer_frame_invalid: Object.freeze({ classification: "host_producer_frame_invalid", next_action: "ask_admin", remedy: "ask an administrator to inspect and repair the producer frame, then start a fresh Host turn" }),
1523
+ relay_permission_denied: Object.freeze({ classification: "host_relay_permission_denied", next_action: "rerun_outside_agent_sandbox", remedy: "an agent sandbox denied the Host Relay socket; run `ceal` as the only command, with no pipe, redirect, or `&&`, so the Host allow rule runs it outside the sandbox" }),
1524
+ relay_unavailable: Object.freeze({ classification: "host_relay_unavailable", next_action: "answer_with_gap" }),
1525
+ transient_retryable: Object.freeze({ classification: "host_mint_transient_retryable", next_action: "retry" }),
1526
+ mint_failed: Object.freeze({ classification: "host_mint_failed", next_action: "answer_with_gap" }),
1527
+ relay_failed: Object.freeze({ classification: "host_relay_failed", next_action: "answer_with_gap" }),
1528
+ host_refusal_invalid: Object.freeze({ classification: "host_refusal_invalid", next_action: "answer_with_gap" })
1529
+ });
1530
+ function projectCealHostAuthenticationCause(diagnostic) {
1531
+ return projectRelayCodeCause(diagnostic) ?? projectGatewayCodeCause(diagnostic) ?? projectGatewayStatusCause(diagnostic) ?? "mint_failed";
1532
+ }
1533
+ function projectRelayCodeCause(diagnostic) {
1534
+ switch (diagnostic.relayCode) {
1535
+ case "credential":
1536
+ return "host_credential_refused";
1537
+ case "configuration":
1538
+ return "options_invalid";
1539
+ case "payload_rejected":
1540
+ return "producer_frame_invalid";
1541
+ case "invalid_response":
1542
+ return "gateway_response_invalid";
1543
+ case "gateway_refused":
1544
+ return projectGatewayRefusedCause(diagnostic);
1545
+ case "gateway_unavailable":
1546
+ return diagnostic.exhausted === true ? void 0 : "gateway_unavailable";
1547
+ case void 0:
1548
+ case "":
1549
+ return void 0;
1550
+ default:
1551
+ return "mint_failed";
1552
+ }
1553
+ }
1554
+ function projectGatewayRefusedCause(diagnostic) {
1555
+ if (diagnostic.gatewayStatus === 401 || diagnostic.gatewayStatus === 403) return "host_credential_refused";
1556
+ const stale = projectGatewayCodeCause(diagnostic);
1557
+ if (stale !== void 0) return stale;
1558
+ if (diagnostic.exhausted === true && (diagnostic.gatewayStatus === 408 || diagnostic.gatewayStatus === 429)) return "gateway_rate_limited";
1559
+ return "gateway_refused";
1560
+ }
1561
+ function projectGatewayCodeCause(diagnostic) {
1562
+ if (diagnostic.gatewayCode === "request_context_refused" && diagnostic.gatewayReason !== void 0 && isVocabularyWord(CEAL_HOST_MINT_REQUEST_CONTEXT_REFUSAL_REASONS, diagnostic.gatewayReason)) return "context_stale";
1563
+ if (diagnostic.gatewayCode === "context_expired") return "context_expired";
1564
+ if (diagnostic.gatewayCode === "host_source_refused") return "host_source_refused";
1565
+ return void 0;
1566
+ }
1567
+ function projectGatewayStatusCause(diagnostic) {
1568
+ if (diagnostic.gatewayStatus === 401 || diagnostic.gatewayStatus === 403) return "host_credential_refused";
1569
+ if (diagnostic.exhausted === true && (diagnostic.gatewayStatus === 408 || diagnostic.gatewayStatus === 429)) return "gateway_rate_limited";
1570
+ return void 0;
1571
+ }
1422
1572
  function decodeCealHostInvocationAuthenticationResult(value, now = /* @__PURE__ */ new Date()) {
1423
1573
  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)) {
1424
1574
  throw new TypeError("The Host invocation authentication result is invalid.");
@@ -1434,11 +1584,36 @@ function exactKeys(value, expected) {
1434
1584
  return keys.length === expected.length && expected.every((key) => Object.hasOwn(value, key));
1435
1585
  }
1436
1586
 
1587
+ // packages/ceal-client-protocol/src/host-service-diagnostic.ts
1588
+ var CEAL_HOST_SERVICE_DIAGNOSTIC_PRODUCERS = vocabulary(["claude", "codex"]);
1589
+ var CEAL_HOST_SERVICE_DIAGNOSTIC_EVENTS = vocabulary([
1590
+ "hook_invoked",
1591
+ "registration_written",
1592
+ "hook_failed",
1593
+ "watcher_turn_observed",
1594
+ "current_prompt_registered",
1595
+ "current_prompt_registration_failed",
1596
+ "activation_recorded",
1597
+ "activation_failed",
1598
+ "watcher_scan_failed",
1599
+ "activation_wait_skipped",
1600
+ "activation_wait_engaged",
1601
+ "activation_wait_completed",
1602
+ "activation_wait_exhausted"
1603
+ ]);
1604
+ var CEAL_HOST_SERVICE_DIAGNOSTIC_FAILURE_KINDS = vocabulary([
1605
+ "malformed_line",
1606
+ "other",
1607
+ "payload_rejected",
1608
+ "read_error",
1609
+ "size_budget",
1610
+ "symlink"
1611
+ ]);
1612
+
1437
1613
  // packages/ceal-client-protocol/src/client-result-materialization.ts
1438
1614
  var CEAL_UNREAD_REASONS = vocabulary(["blocked", "unavailable", "too_large", "unsupported", "download_failed", "permission_denied"]);
1439
- var CEAL_MODEL_VISIBLE_COMMAND_OUTPUT_MAX_BYTES = 32 * 1024;
1440
- var REQUIRED_FIELDS2 = Object.freeze(["schema_version", "operation_id"]);
1441
- var FIELDS = /* @__PURE__ */ new Set([...REQUIRED_FIELDS2, "read_argv", "local_result_root", "continue_argv", "model_disclosure", "item_read_argv"]);
1615
+ var REQUIRED_FIELDS2 = Object.freeze(["schema_version", "operation_id", "path", "sha256"]);
1616
+ var FIELDS = /* @__PURE__ */ new Set([...REQUIRED_FIELDS2, "items_path", "row_count", "result_complete", "coverage", "local_result_root", "model_disclosure", "continue_argv", "how_to_read"]);
1442
1617
 
1443
1618
  // packages/ceal-client-protocol/src/gateway-cache-origin-validation.ts
1444
1619
  var CEAL_MAX_CACHE_ORIGIN_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
@@ -1468,14 +1643,6 @@ var CEAL_GATEWAY_ANNOUNCEMENT_POLICY_NON_CLAIMS = vocabulary([
1468
1643
  "target_specific_scope_not_declared"
1469
1644
  ]);
1470
1645
 
1471
- // packages/ceal-client-protocol/src/gateway-write-identity.ts
1472
- var CEAL_GATEWAY_WRITE_IDENTITY_ROLES = Object.freeze(["replay_identity", "lookup_handle", "collision_evidence"]);
1473
- var CEAL_GATEWAY_WRITE_IDENTITY_FIELDS = Object.freeze({
1474
- replay_identity: "idempotency_claim_sha256",
1475
- lookup_handle: "write_request_sha256",
1476
- collision_evidence: "normalized_mutation_sha256"
1477
- });
1478
-
1479
1646
  // packages/ceal-client-protocol/src/gateway-scoped-identity-projection-validation.ts
1480
1647
  var PROJECTION_REVISION_KEYS = Object.freeze(["graph_revision", "subject_key_revision", "projection_revision"]);
1481
1648
 
@@ -1488,6 +1655,18 @@ var CEAL_SUPPORTED_GATEWAY_PROTOCOL_RANGE = Object.freeze({
1488
1655
  // packages/ceal-client-protocol/src/admin-projection-vocabulary.ts
1489
1656
  var ADMIN_PROJECTION_STATES = vocabulary(["ready", "empty", "partial", "unknown"]);
1490
1657
  var ADMIN_VIEW_KINDS = vocabulary(["request_detail", "resource_access_timeline", "weekly_usage"]);
1658
+ var ADMIN_RECORD_PROJECTION_KINDS = vocabulary([
1659
+ "request_list",
1660
+ "usage_series",
1661
+ "connector_health",
1662
+ "person_connections",
1663
+ "client_sessions",
1664
+ "knowledge_base",
1665
+ "change_history",
1666
+ "approval_queue",
1667
+ "access_group_list",
1668
+ "capability_catalogue"
1669
+ ]);
1491
1670
  var ADMIN_GAP_KINDS = vocabulary(["unknown", "unavailable", "partial"]);
1492
1671
  var ADMIN_UNAVAILABLE_REASONS = vocabulary([
1493
1672
  "not_recorded",
@@ -1511,7 +1690,11 @@ var ADMIN_SOURCE_OWNERS = vocabulary([
1511
1690
  "person",
1512
1691
  "resource",
1513
1692
  "prompt",
1514
- "usage"
1693
+ "usage",
1694
+ "connector",
1695
+ "session",
1696
+ "knowledge",
1697
+ "policy"
1515
1698
  ]);
1516
1699
  var ADMIN_COMPLETENESS_STATES = vocabulary(["complete", "partial", "unknown"]);
1517
1700
  var ADMIN_OPERATION_OUTCOMES = vocabulary(["completed", "failed", "denied", "cancelled", "unknown"]);
@@ -1649,7 +1832,7 @@ function assertHostRelaySourcePaths(stateRoot, config, platform = process.platfo
1649
1832
  // host/relay/src/host-relay-runtime.ts
1650
1833
  import { O_NOFOLLOW as O_NOFOLLOW3, O_RDONLY as O_RDONLY4 } from "node:constants";
1651
1834
  import { lstat as lstat4, open as open5 } from "node:fs/promises";
1652
- import { dirname as dirname3, join as join6 } from "node:path";
1835
+ import { dirname as dirname4, join as join7 } from "node:path";
1653
1836
 
1654
1837
  // host/abortable-wait.ts
1655
1838
  function waitForAbort(signal, milliseconds) {
@@ -1746,6 +1929,15 @@ var FRAME_KINDS = new Set(HOST_PRODUCER_FRAME_KINDS);
1746
1929
  function isHostProducerFrameKind(value) {
1747
1930
  return typeof value === "string" && FRAME_KINDS.has(value);
1748
1931
  }
1932
+ var HOST_PRODUCER_FRAME_ERROR_CODES = [
1933
+ "invalid_frame_encoding",
1934
+ "invalid_frame_length",
1935
+ "frame_truncated",
1936
+ "unsupported_frame_schema",
1937
+ "invalid_frame_shape",
1938
+ "invalid_producer_identity",
1939
+ "frame_too_large"
1940
+ ];
1749
1941
  var HostProducerFrameError = class extends Error {
1750
1942
  code;
1751
1943
  constructor(code, message = code) {
@@ -1753,6 +1945,9 @@ var HostProducerFrameError = class extends Error {
1753
1945
  this.code = code;
1754
1946
  }
1755
1947
  };
1948
+ function assertHostProducerFrame(value) {
1949
+ validateFrame(value);
1950
+ }
1756
1951
  function encodeHostProducerFrame(frame) {
1757
1952
  validateFrame(frame);
1758
1953
  const json = Buffer.from(JSON.stringify(frame), "utf8");
@@ -1783,6 +1978,30 @@ function decodeHostProducerFrame(input) {
1783
1978
  function hostProducerFrameHash(frame) {
1784
1979
  return createHash3("sha256").update(JSON.stringify(frame), "utf8").digest("hex");
1785
1980
  }
1981
+ function extractHostBindingSelector(frame) {
1982
+ if (frame.frame_kind !== "user_input") return null;
1983
+ if (!PRODUCERS.has(frame.producer_id) || !safeRef(frame.producer_installation_ref)) return null;
1984
+ const payload = frame.payload;
1985
+ if (!safeRef(payload.local_session_ref) || !safeRef(payload.local_turn_ref)) return null;
1986
+ const aliases = payload.local_turn_aliases;
1987
+ if (aliases === void 0) {
1988
+ return Object.freeze({
1989
+ producer_id: frame.producer_id,
1990
+ producer_installation_ref: frame.producer_installation_ref,
1991
+ local_session_ref: payload.local_session_ref,
1992
+ local_turn_ref: payload.local_turn_ref,
1993
+ local_turn_aliases: Object.freeze([])
1994
+ });
1995
+ }
1996
+ if (!Array.isArray(aliases) || aliases.length > 16 || !aliases.every(safeRef) || new Set(aliases).size !== aliases.length) return null;
1997
+ return Object.freeze({
1998
+ producer_id: frame.producer_id,
1999
+ producer_installation_ref: frame.producer_installation_ref,
2000
+ local_session_ref: payload.local_session_ref,
2001
+ local_turn_ref: payload.local_turn_ref,
2002
+ local_turn_aliases: Object.freeze([...aliases])
2003
+ });
2004
+ }
1786
2005
  function hostProducerIdentityRefs(hostSourceRef, frame, localSessionRef, localTurnRef, localInputRef) {
1787
2006
  if (!opaqueHostSourceRef(hostSourceRef)) throw new TypeError("Gateway host source reference is invalid.");
1788
2007
  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 })}`;
@@ -1806,6 +2025,31 @@ function hostProducerSubmissionRef(hostSourceRef, frame) {
1806
2025
  function opaqueHostSourceRef(value) {
1807
2026
  return typeof value === "string" && SAFE_REF2.test(value) && !value.startsWith("ceal-host-source:");
1808
2027
  }
2028
+ function isHostSafeRef(value) {
2029
+ return safeRef(value);
2030
+ }
2031
+ var BOUNDED_REFUSAL_WORD = /^[a-z][a-z0-9_]{0,63}$/u;
2032
+ function isBoundedRefusalWord(value) {
2033
+ return typeof value === "string" && BOUNDED_REFUSAL_WORD.test(value);
2034
+ }
2035
+ function hasExactKeys2(value, required, optional = []) {
2036
+ return required.every((key) => Object.hasOwn(value, key)) && Object.keys(value).every((key) => required.includes(key) || optional.includes(key));
2037
+ }
2038
+ function isUndefinedOr(value, guard) {
2039
+ return value === void 0 || guard(value);
2040
+ }
2041
+ var HOST_RELAY_GATEWAY_ERROR_CODES = [
2042
+ "configuration",
2043
+ "credential",
2044
+ "gateway_unavailable",
2045
+ "gateway_refused",
2046
+ "invalid_response",
2047
+ "payload_rejected"
2048
+ ];
2049
+ function isRelayGatewayErrorCode(value) {
2050
+ return isVocabularyWord(HOST_RELAY_GATEWAY_ERROR_CODES, value);
2051
+ }
2052
+ var RELAY_DELIVERY_DIAGNOSTIC_KEYS = ["relayCode", "gatewayStatus", "gatewayCode", "gatewayReason", "exhausted"];
1809
2053
  function requiredIdentity(value) {
1810
2054
  if (value === void 0) throw new TypeError("Canonical Host identity is incomplete.");
1811
2055
  return value;
@@ -2234,6 +2478,8 @@ var RELAY_QUARANTINE_MAX_RECORDS = 512;
2234
2478
  var RELAY_QUARANTINE_MAX_BYTES = 16 * 1024 * 1024;
2235
2479
  var MAX_CAPTURE_BYTES = 262148;
2236
2480
  var PRODUCERS2 = ["codex", "claude", "unknown"];
2481
+ var RELAY_QUARANTINE_FRAME_REASONS = ["frame_identity_conflict", "sequence_gap", "gateway_refused"];
2482
+ var RELAY_QUARANTINE_REASONS = [...RELAY_QUARANTINE_FRAME_REASONS, ...HOST_PRODUCER_FRAME_ERROR_CODES];
2237
2483
  var RelayQuarantineStore = class {
2238
2484
  root;
2239
2485
  maxRecords;
@@ -2246,8 +2492,8 @@ var RelayQuarantineStore = class {
2246
2492
  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}`)}.`);
2247
2493
  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}`)}.`);
2248
2494
  }
2249
- async retainFrame(frame, reason, capturedAt = (/* @__PURE__ */ new Date()).toISOString()) {
2250
- await this.retain(encodeHostProducerFrame(frame), frame.producer_id, reason, capturedAt);
2495
+ async retainFrame(frame, reason, attribution, capturedAt = (/* @__PURE__ */ new Date()).toISOString()) {
2496
+ await this.retain(encodeHostProducerFrame(frame), frame.producer_id, reason, capturedAt, attribution);
2251
2497
  }
2252
2498
  async retainMalformed(rawFrame, reason, capturedAt = (/* @__PURE__ */ new Date()).toISOString()) {
2253
2499
  await this.retain(rawFrame, inferProducer(rawFrame), reason, capturedAt);
@@ -2259,11 +2505,26 @@ var RelayQuarantineStore = class {
2259
2505
  const records = state.producers[producerId].slice(-Math.min(limit, this.maxRecords)).map((record6) => structuredClone(record6));
2260
2506
  return { producer_id: producerId, records, total_bytes: records.reduce((total, record6) => total + record6.charged_bytes, 0) };
2261
2507
  }
2508
+ /**
2509
+ * The newest quarantined record whose exact-turn attribution matches the
2510
+ * query, or null when evicted, unattributed, or for another turn. The
2511
+ * file-backed state survives drain, restart, and overwrite.
2512
+ */
2513
+ async findNewestAttributedMatch(query) {
2514
+ await this.tail;
2515
+ const state = await this.readState();
2516
+ const bucket = query.producer_id === "codex" || query.producer_id === "claude" ? state.producers[query.producer_id] : [];
2517
+ for (let index = bucket.length - 1; index >= 0; index -= 1) {
2518
+ const record6 = bucket[index];
2519
+ if (record6 !== void 0 && attributedRecordMatchesQuery(record6, query)) return structuredClone(record6);
2520
+ }
2521
+ return null;
2522
+ }
2262
2523
  async snapshot() {
2263
2524
  await this.tail;
2264
2525
  return this.readState();
2265
2526
  }
2266
- async retain(rawFrame, producerId, reason, capturedAt) {
2527
+ async retain(rawFrame, producerId, reason, capturedAt, attribution) {
2267
2528
  const run = this.tail.then(async () => {
2268
2529
  if (!PRODUCERS2.includes(producerId) || !Number.isFinite(Date.parse(capturedAt))) throw new TypeError("Relay quarantine record identity is invalid.");
2269
2530
  const raw = Buffer.from(rawFrame).subarray(0, MAX_CAPTURE_BYTES);
@@ -2275,7 +2536,8 @@ var RelayQuarantineStore = class {
2275
2536
  captured_at: capturedAt,
2276
2537
  frame_sha256: createHash4("sha256").update(raw).digest("hex"),
2277
2538
  charged_bytes: raw.byteLength,
2278
- raw_frame_base64: raw.toString("base64")
2539
+ raw_frame_base64: raw.toString("base64"),
2540
+ ...attribution === void 0 ? {} : { attribution: structuredClone(attribution) }
2279
2541
  };
2280
2542
  const records = state.producers[producerId];
2281
2543
  records.push(record6);
@@ -2312,8 +2574,47 @@ function decodeState2(value) {
2312
2574
  return state;
2313
2575
  }
2314
2576
  function validRecord(value) {
2315
- if (!record3(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;
2316
- return true;
2577
+ if (!record3(value) || !validRecordIdentity(value)) return false;
2578
+ return value.attribution === void 0 || validAttribution(value.attribution);
2579
+ }
2580
+ function validRecordIdentity(value) {
2581
+ return typeof value.quarantine_ref === "string" && quarantineProducer(value.producer_id) && validReason(value.reason) && Number.isFinite(Date.parse(String(value.captured_at))) && typeof value.frame_sha256 === "string" && typeof value.raw_frame_base64 === "string" && validChargedBytes(value.charged_bytes);
2582
+ }
2583
+ function validReason(value) {
2584
+ return typeof value === "string" && RELAY_QUARANTINE_REASONS.includes(value);
2585
+ }
2586
+ function validChargedBytes(value) {
2587
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
2588
+ }
2589
+ var ATTRIBUTION_REQUIRED_KEYS = ["producer_id", "producer_installation_ref", "local_session_ref", "local_turn_ref", "local_turn_aliases", "sequence", "frame_sha256"];
2590
+ var ATTRIBUTION_OPTIONAL_KEYS = ["diagnostic"];
2591
+ function validAttribution(value) {
2592
+ if (!record3(value) || !hasExactKeys2(value, ATTRIBUTION_REQUIRED_KEYS, ATTRIBUTION_OPTIONAL_KEYS)) return false;
2593
+ return validAttributionIdentity(value) && validAttributionAliases(value.local_turn_aliases) && validAttributionEnvelope(value) && (value.diagnostic === void 0 || validAttributionDiagnostic(value.diagnostic));
2594
+ }
2595
+ function validAttributionIdentity(value) {
2596
+ return (value.producer_id === "codex" || value.producer_id === "claude") && isHostSafeRef(value.producer_installation_ref) && isHostSafeRef(value.local_session_ref) && isHostSafeRef(value.local_turn_ref);
2597
+ }
2598
+ function validAttributionAliases(value) {
2599
+ return Array.isArray(value) && value.length <= 16 && value.every(isHostSafeRef);
2600
+ }
2601
+ function validAttributionEnvelope(value) {
2602
+ return typeof value.sequence === "number" && Number.isSafeInteger(value.sequence) && value.sequence > 0 && typeof value.frame_sha256 === "string";
2603
+ }
2604
+ function validAttributionDiagnostic(value) {
2605
+ if (!record3(value) || !hasExactKeys2(value, [], RELAY_DELIVERY_DIAGNOSTIC_KEYS)) return false;
2606
+ return isUndefinedOr(value.relayCode, isRelayGatewayErrorCode) && isUndefinedOr(value.gatewayStatus, isSafeInteger) && isUndefinedOr(value.gatewayCode, isBoundedRefusalWord) && isUndefinedOr(value.gatewayReason, isBoundedRefusalWord) && isUndefinedOr(value.exhausted, isBoolean);
2607
+ }
2608
+ function isSafeInteger(value) {
2609
+ return Number.isSafeInteger(value);
2610
+ }
2611
+ function isBoolean(value) {
2612
+ return typeof value === "boolean";
2613
+ }
2614
+ function attributedRecordMatchesQuery(recordValue, query) {
2615
+ const attribution = recordValue.attribution;
2616
+ if (attribution === void 0) return false;
2617
+ return attribution.producer_id === query.producer_id && attribution.producer_installation_ref === query.producer_installation_ref && attribution.local_session_ref === query.local_session_ref && (attribution.local_turn_ref === query.local_turn_ref || attribution.local_turn_aliases.includes(query.local_turn_ref));
2317
2618
  }
2318
2619
  function quarantineProducer(value) {
2319
2620
  return value === "codex" || value === "claude" || value === "unknown";
@@ -2401,11 +2702,11 @@ var RelayAdmissionStore = class {
2401
2702
  const hash = hostProducerFrameHash(frame);
2402
2703
  const replay = replayCode(existing, hash, frame.sequence, installation2);
2403
2704
  if (replay !== null) {
2404
- if (replay === "frame_identity_conflict") await this.quarantine.retainFrame(frame, replay);
2705
+ if (replay === "frame_identity_conflict") await this.quarantine.retainFrame(frame, replay, attributionForFrame(frame, hash, frame.sequence));
2405
2706
  return result(replay, installation2);
2406
2707
  }
2407
2708
  if (frame.sequence !== installation2.admitted_through_sequence + 1) {
2408
- await this.quarantine.retainFrame(frame, "sequence_gap");
2709
+ await this.quarantine.retainFrame(frame, "sequence_gap", attributionForFrame(frame, hash, frame.sequence));
2409
2710
  return result("sequence_gap", installation2);
2410
2711
  }
2411
2712
  const chargedBytes = 4 + Buffer.byteLength(JSON.stringify(frame), "utf8");
@@ -2433,31 +2734,54 @@ var RelayAdmissionStore = class {
2433
2734
  for (const producerId of PRODUCER_ORDER) {
2434
2735
  const head = state.entries.find((entry2) => entry2.producer_id === producerId);
2435
2736
  if (!head || head.retry_at_ms > options.now_ms) continue;
2436
- const input = { frame: structuredClone(head.frame), host_source_ref: options.host_source_ref, submission_ref: hostProducerSubmissionRef(options.host_source_ref, head.frame) };
2437
- const outcome = await deliver(input);
2438
- const exhausted = retryExhausted(outcome, head);
2439
- if (outcome.status === "retryable" && !exhausted) {
2440
- scheduleRetry(head, options.now_ms, outcome.reason);
2441
- retained.push(input.submission_ref);
2442
- await this.write(state);
2443
- continue;
2444
- }
2445
- const installation2 = state.installations[installationKey(head.frame)];
2446
- if (!installation2) throw new TypeError("Host Relay delivery installation is unavailable.");
2447
- if (outcome.status === "refused" || exhausted) {
2448
- await this.quarantine.retainFrame(head.frame, "gateway_refused");
2449
- installation2.last_refusal = { sequence: head.sequence, submission_ref: input.submission_ref, ...refusalCause(outcome, head), refused_at_ms: options.now_ms };
2450
- refused.push(input.submission_ref);
2451
- } else {
2452
- await options.after_gateway_accept_before_delivery_fsync?.({ fault_point: "after_gateway_accept_before_delivery_fsync", delivery: structuredClone(input) });
2453
- delivered.push(input.submission_ref);
2454
- }
2455
- state.entries.splice(state.entries.indexOf(head), 1);
2456
- installation2.delivered_through_sequence = Math.max(installation2.delivered_through_sequence, head.sequence);
2457
- await this.write(state);
2737
+ if (await this.refusePoisonHead(state, head, options, refused)) continue;
2738
+ await this.deliverHead(state, head, deliver, options, delivered, retained, refused);
2458
2739
  }
2459
2740
  return { delivered, retained, refused };
2460
2741
  }
2742
+ async deliverHead(state, head, deliver, options, delivered, retained, refused) {
2743
+ const input = { frame: structuredClone(head.frame), host_source_ref: options.host_source_ref, submission_ref: hostProducerSubmissionRef(options.host_source_ref, head.frame) };
2744
+ const outcome = await deliver(input);
2745
+ const exhausted = retryExhausted(outcome, head);
2746
+ if (outcome.status === "retryable" && !exhausted) {
2747
+ scheduleRetry(head, options.now_ms, outcome.reason);
2748
+ retained.push(input.submission_ref);
2749
+ await this.write(state);
2750
+ return;
2751
+ }
2752
+ const installation2 = state.installations[installationKey(head.frame)];
2753
+ if (!installation2) throw new TypeError("Host Relay delivery installation is unavailable.");
2754
+ if (outcome.status === "refused" || exhausted) {
2755
+ const diagnostic = exhaustedDiagnostic(outcome, exhausted);
2756
+ await this.quarantine.retainFrame(head.frame, "gateway_refused", attributionForFrame(head.frame, head.hash, head.sequence, diagnostic));
2757
+ installation2.last_refusal = { sequence: head.sequence, submission_ref: input.submission_ref, ...refusalCause(outcome, head), ...diagnostic === void 0 ? {} : { diagnostic }, refused_at_ms: options.now_ms };
2758
+ refused.push(input.submission_ref);
2759
+ } else {
2760
+ await options.after_gateway_accept_before_delivery_fsync?.({ fault_point: "after_gateway_accept_before_delivery_fsync", delivery: structuredClone(input) });
2761
+ delivered.push(input.submission_ref);
2762
+ }
2763
+ state.entries.splice(state.entries.indexOf(head), 1);
2764
+ installation2.delivered_through_sequence = Math.max(installation2.delivered_through_sequence, head.sequence);
2765
+ await this.write(state);
2766
+ }
2767
+ async refusePoisonHead(state, head, options, refused) {
2768
+ const poison = poisonFrameError(head.frame);
2769
+ if (poison === null) return false;
2770
+ const installation2 = state.installations[installationKey(head)];
2771
+ if (!hasIntactAdmissionEnvelope(head, installation2)) throw new TypeError("Host Relay admission state is invalid.");
2772
+ const json = Buffer.from(JSON.stringify(head.frame), "utf8");
2773
+ const raw = Buffer.allocUnsafe(json.byteLength + 4);
2774
+ raw.writeUInt32BE(json.byteLength, 0);
2775
+ json.copy(raw, 4);
2776
+ await this.quarantine.retainMalformed(raw, poison.code);
2777
+ const submissionRef = hostProducerSubmissionRef(options.host_source_ref, { producer_id: head.producer_id, producer_installation_ref: head.producer_installation_ref, sequence: head.sequence });
2778
+ installation2.last_refusal = { sequence: head.sequence, submission_ref: submissionRef, code: poison.code, message: `Host Relay persisted frame is invalid: ${poison.code}.`, refused_at_ms: options.now_ms };
2779
+ refused.push(submissionRef);
2780
+ state.entries.splice(state.entries.indexOf(head), 1);
2781
+ installation2.delivered_through_sequence = Math.max(installation2.delivered_through_sequence, head.sequence);
2782
+ await this.write(state);
2783
+ return true;
2784
+ }
2461
2785
  async read() {
2462
2786
  try {
2463
2787
  return decodeState3(JSON.parse(await readFile2(join4(this.root, "admission.json"), "utf8")));
@@ -2474,17 +2798,22 @@ function installationKey(frame) {
2474
2798
  return `${frame.producer_id}\0${frame.producer_installation_ref}`;
2475
2799
  }
2476
2800
  function pendingFrameMatchesBindingQuery(entry2, query) {
2477
- if (entry2.frame.frame_kind !== "user_input") return false;
2478
- const payload = entry2.frame.payload;
2479
- if (typeof payload.local_session_ref !== "string" || typeof payload.local_turn_ref !== "string") return false;
2480
- const aliases = Array.isArray(payload.local_turn_aliases) ? payload.local_turn_aliases.filter((value) => typeof value === "string") : [];
2481
- return relayRequestBindingMatchesQuery(query, {
2482
- producer_id: entry2.frame.producer_id,
2483
- producer_installation_ref: entry2.frame.producer_installation_ref,
2484
- local_session_ref: payload.local_session_ref,
2485
- local_turn_ref: payload.local_turn_ref,
2486
- local_turn_aliases: aliases
2487
- });
2801
+ const selector = extractHostBindingSelector(entry2.frame);
2802
+ if (selector === null) return false;
2803
+ return relayRequestBindingMatchesQuery(query, selector);
2804
+ }
2805
+ function attributionForFrame(frame, hash, sequence, diagnostic) {
2806
+ const selector = extractHostBindingSelector(frame);
2807
+ if (selector === null) return void 0;
2808
+ if (frame.producer_id !== selector.producer_id || frame.producer_installation_ref !== selector.producer_installation_ref || frame.sequence !== sequence) return void 0;
2809
+ if (hostProducerFrameHash(frame) !== hash) return void 0;
2810
+ return { ...selector, sequence, frame_sha256: hash, ...diagnostic === void 0 ? {} : { diagnostic } };
2811
+ }
2812
+ function exhaustedDiagnostic(outcome, exhausted) {
2813
+ if (outcome.status !== "retryable" && outcome.status !== "refused") return void 0;
2814
+ if (outcome.diagnostic !== void 0) return exhausted ? { ...outcome.diagnostic, exhausted: true } : outcome.diagnostic;
2815
+ if (exhausted) return { exhausted: true };
2816
+ return void 0;
2488
2817
  }
2489
2818
  function replayCode(existing, hash, sequence, installation2) {
2490
2819
  if (existing !== void 0) return existing.hash === hash ? "already_admitted" : "frame_identity_conflict";
@@ -2523,6 +2852,8 @@ function decodeState3(value) {
2523
2852
  const entries = [];
2524
2853
  for (const item of value.entries) {
2525
2854
  if (!entry(item)) throw new TypeError("Host Relay entry state is invalid.");
2855
+ poisonFrameError(item.frame);
2856
+ if (!hasIntactAdmissionEnvelope(item, installations[installationKey(item)])) throw new TypeError("Host Relay admission state is invalid.");
2526
2857
  entries.push(item);
2527
2858
  }
2528
2859
  return { schema_version: "ceal.host_relay_admission_state.v1", installations, entries };
@@ -2534,7 +2865,17 @@ function installation(value) {
2534
2865
  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));
2535
2866
  }
2536
2867
  function refusalRecord(value) {
2537
- 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);
2868
+ 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) && (value.diagnostic === void 0 || validDiagnostic(value.diagnostic));
2869
+ }
2870
+ function validDiagnostic(value) {
2871
+ if (!object(value) || !hasExactKeys2(value, [], RELAY_DELIVERY_DIAGNOSTIC_KEYS)) return false;
2872
+ return isUndefinedOr(value.relayCode, isRelayGatewayErrorCode) && isUndefinedOr(value.gatewayStatus, isSafeInteger2) && isUndefinedOr(value.gatewayCode, isBoundedRefusalWord) && isUndefinedOr(value.gatewayReason, isBoundedRefusalWord) && isUndefinedOr(value.exhausted, isBoolean2);
2873
+ }
2874
+ function isSafeInteger2(value) {
2875
+ return Number.isSafeInteger(value);
2876
+ }
2877
+ function isBoolean2(value) {
2878
+ return typeof value === "boolean";
2538
2879
  }
2539
2880
  function entry(value) {
2540
2881
  return object(value) && producer2(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);
@@ -2545,6 +2886,60 @@ function producer2(value) {
2545
2886
  function object(value) {
2546
2887
  return typeof value === "object" && value !== null && !Array.isArray(value);
2547
2888
  }
2889
+ function poisonFrameError(frame) {
2890
+ try {
2891
+ assertHostProducerFrame(frame);
2892
+ return null;
2893
+ } catch (error) {
2894
+ if (error instanceof HostProducerFrameError) return error;
2895
+ throw error;
2896
+ }
2897
+ }
2898
+ function hasIntactAdmissionEnvelope(entryValue, installation2) {
2899
+ if (installation2 === void 0) return false;
2900
+ return poisonIdentityValid(entryValue) && poisonEnvelopeMatches(entryValue, installation2) && poisonIntegrityMatches(entryValue) && poisonSequenceInRange(entryValue, installation2);
2901
+ }
2902
+ function poisonIdentityValid(entryValue) {
2903
+ if (entryValue.producer_id !== "codex" && entryValue.producer_id !== "claude") return false;
2904
+ if (!opaqueHostSourceRef(entryValue.producer_installation_ref)) return false;
2905
+ return Number.isSafeInteger(entryValue.sequence) && entryValue.sequence > 0;
2906
+ }
2907
+ function poisonEnvelopeMatches(entryValue, installation2) {
2908
+ const frame = entryValue.frame;
2909
+ if (!object(frame)) return false;
2910
+ return poisonEnvelopeSchema(frame) && poisonEnvelopeProducer(frame, entryValue) && poisonEnvelopeInstallation(frame, entryValue) && poisonEnvelopeEpoch(frame, installation2) && poisonEnvelopeSequence(frame, entryValue) && poisonEnvelopeKind(frame) && poisonEnvelopeTimestamp(frame);
2911
+ }
2912
+ function poisonEnvelopeSchema(frame) {
2913
+ return frame.schema_version === "ceal.host_producer_frame.v1";
2914
+ }
2915
+ function poisonEnvelopeProducer(frame, entryValue) {
2916
+ return producer2(frame.producer_id) && frame.producer_id === entryValue.producer_id;
2917
+ }
2918
+ function poisonEnvelopeInstallation(frame, entryValue) {
2919
+ return opaqueHostSourceRef(frame.producer_installation_ref) && frame.producer_installation_ref === entryValue.producer_installation_ref;
2920
+ }
2921
+ function poisonEnvelopeEpoch(frame, installation2) {
2922
+ return Number.isSafeInteger(frame.producer_epoch) && typeof frame.producer_epoch === "number" && frame.producer_epoch > 0 && frame.producer_epoch <= installation2.epoch;
2923
+ }
2924
+ function poisonEnvelopeSequence(frame, entryValue) {
2925
+ return Number.isSafeInteger(frame.sequence) && frame.sequence === entryValue.sequence;
2926
+ }
2927
+ function poisonEnvelopeKind(frame) {
2928
+ return isHostProducerFrameKind(frame.frame_kind);
2929
+ }
2930
+ function poisonEnvelopeTimestamp(frame) {
2931
+ return typeof frame.occurred_at === "string" && Number.isFinite(Date.parse(frame.occurred_at));
2932
+ }
2933
+ function poisonIntegrityMatches(entryValue) {
2934
+ const frame = entryValue.frame;
2935
+ if (!object(frame)) return false;
2936
+ const json = JSON.stringify(frame);
2937
+ return entryValue.charged_bytes === 4 + Buffer.byteLength(json, "utf8") && entryValue.hash === hostProducerFrameHash(entryValue.frame);
2938
+ }
2939
+ function poisonSequenceInRange(entryValue, installation2) {
2940
+ if (entryValue.sequence <= installation2.delivered_through_sequence) return false;
2941
+ return entryValue.sequence <= installation2.admitted_through_sequence;
2942
+ }
2548
2943
 
2549
2944
  // host/relay/src/relay-gateway-bridge.ts
2550
2945
  import { readFile as readFile3 } from "node:fs/promises";
@@ -2688,10 +3083,22 @@ function submissionRefusal(error) {
2688
3083
  const status = isRecord(error) && typeof error.status === "number" ? error.status : void 0;
2689
3084
  const code = errorCode7(error) ?? "gateway_unavailable";
2690
3085
  const definitive = code === "payload_rejected" || status !== void 0 && status >= 400 && status < 500 && !RETRYABLE_HTTP_STATUSES.has(status);
2691
- return { code, message: errorMessage(error), definitive };
3086
+ return { code, message: errorMessage(error), definitive, diagnostic: typedDiagnostic(error, status) };
3087
+ }
3088
+ function typedDiagnostic(error, status) {
3089
+ if (!isRecord(error)) return status === void 0 ? {} : { gatewayStatus: status };
3090
+ const gatewayCode = isBoundedRefusalWord(error.error_code) ? error.error_code : void 0;
3091
+ const gatewayReason = isBoundedRefusalWord(error.refusal_reason) ? error.refusal_reason : void 0;
3092
+ return {
3093
+ ...typeof error.code === "string" ? { relayCode: error.code } : {},
3094
+ ...status === void 0 ? {} : { gatewayStatus: status },
3095
+ ...gatewayCode === void 0 ? {} : { gatewayCode },
3096
+ ...gatewayReason === void 0 ? {} : { gatewayReason }
3097
+ };
2692
3098
  }
2693
3099
  function deliveryRefusal(refusal) {
2694
- return refusal.definitive ? { status: "refused", code: refusal.code, message: refusal.message } : { status: "retryable", reason: `${refusal.code}: ${refusal.message}` };
3100
+ const diagnostic = refusal.diagnostic === void 0 ? {} : { diagnostic: refusal.diagnostic };
3101
+ return refusal.definitive ? { status: "refused", code: refusal.code, message: refusal.message, ...diagnostic } : { status: "retryable", reason: `${refusal.code}: ${refusal.message}`, ...diagnostic };
2695
3102
  }
2696
3103
  function errorMessage(error) {
2697
3104
  return error instanceof Error ? error.message : String(error);
@@ -2889,22 +3296,35 @@ var HostRelayGatewayError = class extends Error {
2889
3296
  status;
2890
3297
  /** The Gateway's own refusal word, when it named one; a bounded token, never its message. */
2891
3298
  error_code;
2892
- constructor(code, message, status, errorCode9) {
3299
+ /** The Gateway mint refusal's bounded continuity reason, when it named one; a fixed token, never its message. */
3300
+ refusal_reason;
3301
+ constructor(code, message, status, errorCode9, refusalReason) {
2893
3302
  super(message);
2894
3303
  this.code = code;
2895
3304
  if (status !== void 0) this.status = status;
2896
3305
  if (errorCode9 !== void 0) this.error_code = errorCode9;
3306
+ if (refusalReason !== void 0) this.refusal_reason = refusalReason;
2897
3307
  }
2898
3308
  };
2899
3309
  var GATEWAY_REFUSAL_CODE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/u;
2900
- async function gatewayRefusalCode(response2) {
3310
+ async function gatewayRefusal(response2) {
2901
3311
  try {
2902
3312
  const body = await response2.json();
2903
- return isCealJsonRecord(body) && typeof body.error_code === "string" && GATEWAY_REFUSAL_CODE_PATTERN.test(body.error_code) ? body.error_code : void 0;
3313
+ if (!isCealJsonRecord(body)) return {};
3314
+ const code = typeof body.error_code === "string" && GATEWAY_REFUSAL_CODE_PATTERN.test(body.error_code) ? body.error_code : void 0;
3315
+ const reason = code === "request_context_refused" && typeof body.reason === "string" && GATEWAY_REFUSAL_CODE_PATTERN.test(body.reason) && isVocabularyWord(CEAL_HOST_MINT_REQUEST_CONTEXT_REFUSAL_REASONS, body.reason) ? body.reason : void 0;
3316
+ return {
3317
+ ...code === void 0 ? {} : { code },
3318
+ ...reason === void 0 ? {} : { reason }
3319
+ };
2904
3320
  } catch {
2905
- return void 0;
3321
+ return {};
2906
3322
  }
2907
3323
  }
3324
+ function submitRefusalCode(body) {
3325
+ if (!isCealJsonRecord(body) || typeof body.error_code !== "string" || !GATEWAY_REFUSAL_CODE_PATTERN.test(body.error_code)) return void 0;
3326
+ return body.error_code;
3327
+ }
2908
3328
  function refusalMessage(status, body) {
2909
3329
  const record6 = isCealJsonRecord(body) ? body : {};
2910
3330
  const code = typeof record6.error_code === "string" ? record6.error_code : "unknown";
@@ -2932,7 +3352,7 @@ function createHostRelayGatewayHttpPort(options) {
2932
3352
  invalidEventTime: () => new HostRelayGatewayError("payload_rejected", "Host Relay submission has no event time."),
2933
3353
  unavailable: () => new HostRelayGatewayError("gateway_unavailable", "Gateway Host ingress is unavailable."),
2934
3354
  invalidResponse: () => new HostRelayGatewayError("invalid_response", "Gateway Host ingress response is not JSON."),
2935
- refused: (status, body) => new HostRelayGatewayError("gateway_refused", refusalMessage(status, body), status),
3355
+ refused: (status, body) => new HostRelayGatewayError("gateway_refused", refusalMessage(status, body), status, submitRefusalCode(body)),
2936
3356
  acknowledgement
2937
3357
  });
2938
3358
  },
@@ -2950,7 +3370,10 @@ function createHostRelayGatewayHttpPort(options) {
2950
3370
  } catch {
2951
3371
  throw new HostRelayGatewayError("gateway_unavailable", "Gateway Host invocation context is unavailable.");
2952
3372
  }
2953
- if (!response2.ok) throw new HostRelayGatewayError(response2.status === 401 ? "credential" : "gateway_refused", `Gateway Host invocation context was refused (${response2.status}).`, response2.status, await gatewayRefusalCode(response2));
3373
+ if (!response2.ok) {
3374
+ const refusal = await gatewayRefusal(response2);
3375
+ throw new HostRelayGatewayError(response2.status === 401 ? "credential" : "gateway_refused", `Gateway Host invocation context was refused (${response2.status}).`, response2.status, refusal.code, refusal.reason);
3376
+ }
2954
3377
  let value;
2955
3378
  try {
2956
3379
  value = await response2.json();
@@ -3071,8 +3494,9 @@ function acknowledgement(value) {
3071
3494
  }
3072
3495
 
3073
3496
  // host/relay/src/relay-ipc.ts
3074
- import { chmod, lstat as lstat3, unlink as unlink2 } from "node:fs/promises";
3497
+ import { chmod, lstat as lstat3, rename as rename2, unlink as unlink2 } from "node:fs/promises";
3075
3498
  import { createConnection, createServer } from "node:net";
3499
+ import { dirname as dirname3, join as join6 } from "node:path";
3076
3500
 
3077
3501
  // host/relay/src/current-prompt-custody.ts
3078
3502
  import { createHash as createHash5 } from "node:crypto";
@@ -3150,10 +3574,31 @@ var HOST_RELAY_INVOCATION_MINT_REFUSAL_REASONS = vocabulary([
3150
3574
  "gateway_unavailable",
3151
3575
  "gateway_refused",
3152
3576
  "gateway_response_invalid",
3577
+ "gateway_rate_limited",
3578
+ "producer_frame_invalid",
3153
3579
  "deadline",
3154
3580
  "cancelled",
3155
3581
  "mint_failed",
3156
- "relay_failed"
3582
+ "relay_failed",
3583
+ "request_authority_unavailable",
3584
+ "request_missing",
3585
+ "authority_mismatch",
3586
+ "host_source_mismatch",
3587
+ "host_session_mismatch",
3588
+ "host_turn_mismatch",
3589
+ "host_input_mismatch",
3590
+ "host_prompt_mismatch"
3591
+ ]);
3592
+ var HOST_RELAY_DIRECT_WIRE_MINT_REASONS = vocabulary([
3593
+ "context_stale",
3594
+ "context_expired",
3595
+ "host_source_refused",
3596
+ "host_credential_refused",
3597
+ "gateway_unavailable",
3598
+ "gateway_rate_limited",
3599
+ "gateway_refused",
3600
+ "gateway_response_invalid",
3601
+ "producer_frame_invalid"
3157
3602
  ]);
3158
3603
  var HostRelayInvocationMintRefusal = class extends Error {
3159
3604
  reason;
@@ -3185,15 +3630,42 @@ var HostRelayIpcError = class extends Error {
3185
3630
  }
3186
3631
  };
3187
3632
  async function startHostRelayIpcServer(options) {
3188
- await assertEndpointVacant(options.endpoint);
3189
- const active = /* @__PURE__ */ new Map();
3190
- const sockets = /* @__PURE__ */ new Set();
3191
- const quarantine = options.quarantine ?? options.admission.quarantine;
3192
- const currentPrompts = options.currentPrompts ?? new HostCurrentPromptCustody();
3193
- const server = createServer((socket) => serveSocket(socket, options, currentPrompts, quarantine, active, sockets));
3194
- await listen(server, options.endpoint);
3195
- if (process.platform !== "win32") await chmod(options.endpoint, 384);
3196
- return { endpoint: options.endpoint, close: () => closeServer(server, sockets, options.endpoint) };
3633
+ return withRelayEndpointLock(options.endpoint, async () => {
3634
+ if (process.platform === "win32") {
3635
+ await assertEndpointVacant(options.endpoint);
3636
+ } else {
3637
+ await assertTrustedEndpointParent(options.endpoint);
3638
+ await removeStaleRelayEndpoint(options.endpoint, options.testHooks);
3639
+ }
3640
+ const active = /* @__PURE__ */ new Map();
3641
+ const sockets = /* @__PURE__ */ new Set();
3642
+ const quarantine = options.quarantine ?? options.admission.quarantine;
3643
+ const currentPrompts = options.currentPrompts ?? new HostCurrentPromptCustody();
3644
+ const server = createServer((socket) => serveSocket(socket, options, currentPrompts, quarantine, active, sockets));
3645
+ if (process.platform === "win32") {
3646
+ try {
3647
+ await listen(server, options.endpoint);
3648
+ } catch (error) {
3649
+ await abandonRelayServer(server, sockets);
3650
+ throw error;
3651
+ }
3652
+ return { endpoint: options.endpoint, close: () => closeServer(server, sockets, options.endpoint) };
3653
+ }
3654
+ const staging = stagingRelayEndpoint(options.endpoint);
3655
+ await listenStagingRelayEndpoint(server, sockets, staging);
3656
+ let owned;
3657
+ try {
3658
+ await options.testHooks?.beforeCaptureOwnedEndpoint?.(options.endpoint);
3659
+ owned = await readStagingRelayEndpointIdentity(staging);
3660
+ await chmod(staging, 384);
3661
+ const identity = await publishStagingRelayEndpoint(staging, owned, options.endpoint);
3662
+ return { endpoint: options.endpoint, close: () => closeRelayServer(server, sockets, options.endpoint, identity, options.testHooks) };
3663
+ } catch (error) {
3664
+ if (owned !== void 0) await releaseOwnedRelayEndpoint(server, sockets, options.endpoint, owned);
3665
+ else await abandonRelayServer(server, sockets);
3666
+ throw error;
3667
+ }
3668
+ });
3197
3669
  }
3198
3670
  function encodeHostRelayIpcResponse(response2) {
3199
3671
  const body = Buffer.from(JSON.stringify(response2), "utf8");
@@ -3355,17 +3827,68 @@ function writeCurrentPromptResponse(socket, status) {
3355
3827
  async function resolveInvocationContext(request2, admission, bindings, currentPrompts, mint, signal) {
3356
3828
  if (mint === void 0) throw new HostRelayIpcError("relay_unavailable");
3357
3829
  const query = bindingQueryFromRequest(request2);
3830
+ const expectedSequences = pendingAdmissionSequences(await admission.snapshot(), query);
3358
3831
  const binding = await waitForRequestBinding(query, admission, bindings, signal);
3359
- if (binding.status !== "ready") return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "no_binding" };
3832
+ if (binding.status !== "ready") return await unboundInvocationContextRefusal(admission, await admission.snapshot(), query, expectedSequences) ?? { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "no_binding" };
3360
3833
  const currentPrompt = currentPrompts.take({ producer_id: request2.producer_id, producer_installation_ref: request2.producer_installation_ref, local_session_ref: request2.local_session_ref, local_turn_ref: request2.local_turn_ref, prompt_ref: binding.binding.prompt_ref });
3361
3834
  let result2;
3362
3835
  try {
3363
- 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), ...currentPrompt === void 0 ? {} : { current_prompt: currentPrompt } }, signal);
3836
+ 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), ...currentPrompt === void 0 ? {} : { current_prompt: currentPrompt }, ...request2.visible_output_max_bytes === void 0 ? {} : { visible_output_max_bytes: request2.visible_output_max_bytes } }, signal);
3364
3837
  } catch (error) {
3365
3838
  return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "refused", reason: error instanceof HostRelayInvocationMintRefusal ? error.reason : "mint_failed" };
3366
3839
  }
3367
3840
  return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "ready", result: result2 };
3368
3841
  }
3842
+ async function unboundInvocationContextRefusal(admission, snapshot, query, expectedSequences) {
3843
+ if (expectedSequences.length > 0) {
3844
+ const refusal = snapshot.installations[`${query.producer_id}\0${query.producer_installation_ref}`]?.last_refusal;
3845
+ if (refusal !== void 0 && expectedSequences.includes(refusal.sequence)) {
3846
+ const reason2 = mintReasonForDeliveryRefusal(refusal.code, refusal.diagnostic);
3847
+ if (reason2 !== void 0) return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "refused", reason: reason2 };
3848
+ }
3849
+ }
3850
+ const selector = Object.freeze({
3851
+ producer_id: query.producer_id,
3852
+ producer_installation_ref: query.producer_installation_ref,
3853
+ local_session_ref: query.local_session_ref,
3854
+ local_turn_ref: query.local_turn_ref,
3855
+ local_turn_aliases: Object.freeze([])
3856
+ });
3857
+ const match = await admission.quarantine.findNewestAttributedMatch(selector);
3858
+ if (match === null) return null;
3859
+ const reason = mintReasonForQuarantinedMatch(match);
3860
+ if (reason === void 0) return null;
3861
+ return { schema_version: HOST_RELAY_INVOCATION_CONTEXT_RESULT_SCHEMA, status: "refused", reason };
3862
+ }
3863
+ function mintReasonForDeliveryRefusal(code, diagnostic) {
3864
+ if (code !== "gateway_refused") return void 0;
3865
+ if (diagnostic === void 0) return "gateway_refused";
3866
+ return mintReasonForWireCause(projectCealHostAuthenticationCause(diagnostic));
3867
+ }
3868
+ function mintReasonForQuarantinedMatch(match) {
3869
+ if (match === null) return void 0;
3870
+ if (match.reason !== "gateway_refused") return "producer_frame_invalid";
3871
+ const diagnostic = match.attribution?.diagnostic;
3872
+ if (diagnostic === void 0) return void 0;
3873
+ return mintReasonForWireCause(projectCealHostAuthenticationCause(diagnostic));
3874
+ }
3875
+ function mintReasonForWireCause(cause) {
3876
+ if (isDirectWireCause(cause)) return cause;
3877
+ if (cause === "relay_failed" || cause === "relay_unavailable" || cause === "options_invalid") return "relay_failed";
3878
+ return "mint_failed";
3879
+ }
3880
+ function isDirectWireCause(cause) {
3881
+ return isVocabularyWord(HOST_RELAY_DIRECT_WIRE_MINT_REASONS, cause);
3882
+ }
3883
+ function pendingAdmissionSequences(snapshot, query) {
3884
+ const sequences = [];
3885
+ for (const entry2 of snapshot.entries) {
3886
+ const selector = extractHostBindingSelector(entry2.frame);
3887
+ if (selector === null || !relayRequestBindingMatchesQuery(query, selector)) continue;
3888
+ sequences.push(entry2.sequence);
3889
+ }
3890
+ return sequences;
3891
+ }
3369
3892
  async function waitForRequestBinding(query, admission, bindings, signal) {
3370
3893
  let binding = await bindings.query(query);
3371
3894
  if (binding.status === "ready") return binding;
@@ -3483,11 +4006,14 @@ function bindingQueryFromRequest(value) {
3483
4006
  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 };
3484
4007
  }
3485
4008
  function validInvocationContextQueryRequest(value) {
3486
- 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);
4009
+ 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"], ["visible_output_max_bytes"]) && typeof value.client_nonce === "string" && CEAL_HOST_CLIENT_NONCE_PATTERN.test(value.client_nonce) && (value.visible_output_max_bytes === void 0 || validVisibleOutputBudget(value.visible_output_max_bytes));
3487
4010
  }
3488
4011
  function validQueryIdentity(value, schema) {
3489
4012
  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);
3490
4013
  }
4014
+ function validVisibleOutputBudget(value) {
4015
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value <= CEAL_CANONICAL_HTTP_MAX_RESPONSE_BYTES;
4016
+ }
3491
4017
  function decodeLengthPrefixedJson(input, maximum) {
3492
4018
  if (input.length < HOST_RELAY_IPC_LENGTH_BYTES) return null;
3493
4019
  const length = input.readUInt32BE(0);
@@ -3510,8 +4036,9 @@ function encodeLengthPrefixed(value) {
3510
4036
  function currentPromptWire(value) {
3511
4037
  return value.subarray(HOST_RELAY_IPC_LENGTH_BYTES, Math.min(value.length, HOST_RELAY_IPC_LENGTH_BYTES + 128)).includes(Buffer.from(`"schema_version":"${HOST_RELAY_CURRENT_PROMPT_REGISTER_SCHEMA}"`, "utf8"));
3512
4038
  }
3513
- function exactKeys4(value, keys) {
3514
- return Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
4039
+ function exactKeys4(value, required, optional = []) {
4040
+ const keys = Object.keys(value);
4041
+ return required.every((key) => Object.hasOwn(value, key)) && keys.every((key) => required.includes(key) || optional.includes(key));
3515
4042
  }
3516
4043
  function safeRef3(value) {
3517
4044
  return typeof value === "string" && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(value);
@@ -3541,6 +4068,160 @@ async function closeServer(server, sockets, endpoint) {
3541
4068
  await new Promise((resolve) => server.close(() => resolve()));
3542
4069
  if (process.platform !== "win32") await unlink2(endpoint).catch(() => void 0);
3543
4070
  }
4071
+ var relayEndpointLocks = /* @__PURE__ */ new Map();
4072
+ function withRelayEndpointLock(endpoint, run) {
4073
+ const prior = relayEndpointLocks.get(endpoint) ?? Promise.resolve();
4074
+ let release;
4075
+ const gate = new Promise((resolve) => {
4076
+ release = resolve;
4077
+ });
4078
+ const tail = prior.then(() => gate);
4079
+ relayEndpointLocks.set(endpoint, tail);
4080
+ return prior.then(run).finally(() => {
4081
+ release?.();
4082
+ if (relayEndpointLocks.get(endpoint) === tail) relayEndpointLocks.delete(endpoint);
4083
+ });
4084
+ }
4085
+ function currentUid(fallback) {
4086
+ return typeof process.geteuid === "function" ? process.geteuid() : fallback;
4087
+ }
4088
+ async function assertTrustedEndpointParent(endpoint) {
4089
+ const parent = dirname3(endpoint);
4090
+ let stats;
4091
+ try {
4092
+ stats = await lstat3(parent);
4093
+ } catch {
4094
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint parent is unavailable; leaving it untouched.");
4095
+ }
4096
+ if (!stats.isDirectory() || stats.uid !== currentUid(stats.uid) || (stats.mode & 63) !== 0) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint parent is not an owner-private directory; leaving it untouched.");
4097
+ }
4098
+ var HOST_RELAY_ENDPOINT_PROBE_TIMEOUT_MS = 1e3;
4099
+ function probeRelayEndpoint(endpoint) {
4100
+ return new Promise((resolve) => {
4101
+ let settled = false;
4102
+ const socket = createConnection(endpoint);
4103
+ const finish = (outcome) => {
4104
+ if (settled) return;
4105
+ settled = true;
4106
+ clearTimeout(timer);
4107
+ socket.destroy();
4108
+ resolve(outcome);
4109
+ };
4110
+ const timer = setTimeout(() => finish("ambiguous"), HOST_RELAY_ENDPOINT_PROBE_TIMEOUT_MS);
4111
+ timer.unref?.();
4112
+ socket.once("connect", () => finish("live"));
4113
+ socket.once("error", (error) => {
4114
+ const code = errorCode8(error);
4115
+ if (code === "ECONNREFUSED") finish("stale");
4116
+ else if (code === "ENOENT") finish("missing");
4117
+ else finish("ambiguous");
4118
+ });
4119
+ });
4120
+ }
4121
+ async function removeStaleRelayEndpoint(endpoint, testHooks) {
4122
+ const observed = await readEndpointStats(endpoint);
4123
+ if (observed === null) return;
4124
+ if (!observed.isSocket()) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is already present and is not a socket; leaving it untouched.");
4125
+ if (observed.uid !== currentUid(observed.uid)) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is not owned by the current uid; leaving it untouched.");
4126
+ const captured = { uid: observed.uid, dev: observed.dev, ino: observed.ino };
4127
+ await requireStaleEndpoint(endpoint);
4128
+ await testHooks?.beforeRemoveStaleEndpoint?.(endpoint);
4129
+ const current = await readEndpointStats(endpoint);
4130
+ if (current === null) return;
4131
+ requireSameEndpointIdentity(current, captured, "Host Relay IPC endpoint changed before cleanup; leaving it untouched.");
4132
+ await unlinkRelayEndpoint(endpoint);
4133
+ }
4134
+ async function requireStaleEndpoint(endpoint) {
4135
+ switch (await probeRelayEndpoint(endpoint)) {
4136
+ case "missing":
4137
+ case "stale":
4138
+ return;
4139
+ case "live":
4140
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is already served by a live Relay; leaving it untouched.");
4141
+ case "ambiguous":
4142
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint liveness is ambiguous; leaving it untouched.");
4143
+ }
4144
+ }
4145
+ async function readEndpointStats(endpoint) {
4146
+ try {
4147
+ return await lstat3(endpoint);
4148
+ } catch (error) {
4149
+ if (errorCode8(error) === "ENOENT") return null;
4150
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint identity is ambiguous; leaving it untouched.");
4151
+ }
4152
+ }
4153
+ function requireSameEndpointIdentity(current, owned, message) {
4154
+ if (!current.isSocket() || current.uid !== owned.uid || current.dev !== owned.dev || current.ino !== owned.ino) throw new HostRelayIpcError("relay_unavailable", message);
4155
+ }
4156
+ async function unlinkRelayEndpoint(endpoint) {
4157
+ try {
4158
+ await unlink2(endpoint);
4159
+ } catch (error) {
4160
+ if (errorCode8(error) !== "ENOENT") throw error;
4161
+ }
4162
+ }
4163
+ var relayStagingSequence = 0;
4164
+ function stagingRelayEndpoint(canonical) {
4165
+ const parent = dirname3(canonical);
4166
+ const pid = process.pid.toString(36);
4167
+ const sequence = (relayStagingSequence++ % (36 * 36)).toString(36);
4168
+ return join6(parent, `.r${pid}${sequence}`);
4169
+ }
4170
+ async function readStagingRelayEndpointIdentity(staging) {
4171
+ let created;
4172
+ try {
4173
+ created = await lstat3(staging);
4174
+ } catch {
4175
+ throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is unavailable after listen; leaving it untouched.");
4176
+ }
4177
+ if (!created.isSocket()) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint was replaced before this server listened; leaving it untouched.");
4178
+ if (created.uid !== currentUid(created.uid)) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is not owned by the current uid after listen; leaving it untouched.");
4179
+ return { uid: created.uid, dev: created.dev, ino: created.ino };
4180
+ }
4181
+ async function listenStagingRelayEndpoint(server, sockets, staging) {
4182
+ try {
4183
+ await listen(server, staging);
4184
+ } catch (error) {
4185
+ await abandonRelayServer(server, sockets);
4186
+ throw error;
4187
+ }
4188
+ }
4189
+ async function publishStagingRelayEndpoint(staging, owned, canonical) {
4190
+ const incumbent = await readEndpointStats(canonical);
4191
+ if (incumbent !== null) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint was replaced before this server listened; leaving it untouched.");
4192
+ await rename2(staging, canonical);
4193
+ const published = await readEndpointStats(canonical);
4194
+ if (published === null) throw new HostRelayIpcError("relay_unavailable", "Host Relay IPC endpoint is unavailable after listen; leaving it untouched.");
4195
+ requireSameEndpointIdentity(published, owned, "Host Relay IPC endpoint was replaced before this server listened; leaving it untouched.");
4196
+ return { uid: published.uid, dev: published.dev, ino: published.ino };
4197
+ }
4198
+ async function releaseOwnedRelayEndpoint(server, sockets, endpoint, owned) {
4199
+ await abandonRelayServer(server, sockets);
4200
+ try {
4201
+ const current = await readEndpointStats(endpoint);
4202
+ if (current === null) return;
4203
+ requireSameEndpointIdentity(current, owned, "Host Relay IPC endpoint changed while releasing a failed startup; leaving it untouched.");
4204
+ await unlinkRelayEndpoint(endpoint);
4205
+ } catch {
4206
+ }
4207
+ }
4208
+ async function closeRelayServer(server, sockets, endpoint, owned, testHooks) {
4209
+ await withRelayEndpointLock(endpoint, async () => {
4210
+ for (const socket of sockets) socket.destroy();
4211
+ await new Promise((resolve) => server.close(() => resolve()));
4212
+ await testHooks?.beforeRemoveOwnedEndpoint?.(endpoint);
4213
+ const current = await readEndpointStats(endpoint);
4214
+ if (current === null) return;
4215
+ requireSameEndpointIdentity(current, owned, "Host Relay IPC endpoint was replaced after this server listened; leaving it untouched.");
4216
+ await unlinkRelayEndpoint(endpoint);
4217
+ });
4218
+ }
4219
+ async function abandonRelayServer(server, sockets) {
4220
+ for (const socket of sockets) socket.destroy();
4221
+ await new Promise((resolve) => {
4222
+ server.close(() => resolve());
4223
+ });
4224
+ }
3544
4225
  function errorCode8(error) {
3545
4226
  return record4(error) && typeof error.code === "string" ? error.code : null;
3546
4227
  }
@@ -3562,7 +4243,7 @@ async function readHostRelayConfig(path) {
3562
4243
  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")}.`);
3563
4244
  let handle;
3564
4245
  try {
3565
- await assertOwnerPrivateDirectory2(dirname3(path));
4246
+ await assertOwnerPrivateDirectory2(dirname4(path));
3566
4247
  handle = await open5(path, O_RDONLY4 | O_NOFOLLOW3);
3567
4248
  const stats = await handle.stat();
3568
4249
  if (!stats.isFile() || !ownerPrivate4(stats)) throw new HostRelayConfigError("config_not_private", "Host Relay config file is not owner-private.");
@@ -3587,7 +4268,7 @@ async function readHostRelayConfig(path) {
3587
4268
  }
3588
4269
  function validateHostRelaySourcePaths(config) {
3589
4270
  try {
3590
- assertHostRelaySourcePaths(dirname3(config.registration_state_file), config);
4271
+ assertHostRelaySourcePaths(dirname4(config.registration_state_file), config);
3591
4272
  } catch (error) {
3592
4273
  throw new HostRelayConfigError("invalid_config", error instanceof Error ? error.message : "Host Relay source tuple is invalid.");
3593
4274
  }
@@ -3617,10 +4298,10 @@ function validConfigRuntime(value) {
3617
4298
  var HOST_RELAY_INVOCATION_MINT_LOG_TAG = "[host-relay-invocation-mint]";
3618
4299
  var HOST_RELAY_INVOCATION_MINT_LINE = new RegExp(`^${HOST_RELAY_INVOCATION_MINT_LOG_TAG.replace(/[[\]]/gu, "\\$&")} outcome=([a-z_]+)(?: reason=([a-z][a-z0-9_]{0,63}))? elapsed_ms=[0-9]+$`, "u");
3619
4300
  async function serveHostRelay(config, signal, dependencies = {}) {
3620
- const admission = new RelayAdmissionStore(join6(config.state_root, "admission"));
3621
- const bindings = new RelayRequestBindingStore(join6(config.state_root, "bindings"));
4301
+ const admission = new RelayAdmissionStore(join7(config.state_root, "admission"));
4302
+ const bindings = new RelayRequestBindingStore(join7(config.state_root, "bindings"));
3622
4303
  const gateway = (dependencies.createGateway ?? createHostRelayGatewayHttpPort)({ registration_state_file: config.registration_state_file, host_source_ref: config.host_source_ref });
3623
- 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) => {
4304
+ const bridge = new RelayGatewayBridge({ state_root: join7(config.state_root, "gateway"), host_source_ref: config.host_source_ref, gateway, timeout_ms: config.gateway_timeout_ms, on_request_bound: async (binding) => {
3624
4305
  await bindings.bind(binding);
3625
4306
  } });
3626
4307
  let server;
@@ -3661,7 +4342,11 @@ function invocationMintRefusalReason(error, cancellation) {
3661
4342
  if (error.code === "gateway_unavailable") return "gateway_unavailable";
3662
4343
  if (error.code === "invalid_response") return "gateway_response_invalid";
3663
4344
  if (error.code !== "gateway_refused") return "mint_failed";
3664
- return (error.error_code === void 0 ? void 0 : GATEWAY_MINT_REFUSAL_REASONS.get(error.error_code)) ?? "gateway_refused";
4345
+ return gatewayMintRefusalReason(error);
4346
+ }
4347
+ function gatewayMintRefusalReason(error) {
4348
+ if (error.error_code === "request_context_refused" && isVocabularyWord(CEAL_HOST_MINT_REQUEST_CONTEXT_REFUSAL_REASONS, error.refusal_reason)) return error.refusal_reason;
4349
+ return GATEWAY_MINT_REFUSAL_REASONS.get(error.error_code ?? "") ?? "gateway_refused";
3665
4350
  }
3666
4351
  var GATEWAY_MINT_REFUSAL_REASONS = /* @__PURE__ */ new Map([
3667
4352
  ["request_context_refused", "context_stale"],