agent-embassy 1.6.0 → 1.7.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.
Files changed (97) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +9 -9
  3. package/README.zh-CN.md +9 -9
  4. package/SECURITY.md +34 -77
  5. package/dist/src/gateway/acp-client.d.ts +117 -0
  6. package/dist/src/gateway/acp-client.js +382 -0
  7. package/dist/src/gateway/acp-client.js.map +1 -0
  8. package/dist/src/gateway/acp-provider.d.ts +65 -0
  9. package/dist/src/gateway/acp-provider.js +163 -0
  10. package/dist/src/gateway/acp-provider.js.map +1 -0
  11. package/dist/src/gateway/claude-helper-protocol.d.ts +3 -1
  12. package/dist/src/gateway/claude-helper-protocol.js +15 -5
  13. package/dist/src/gateway/claude-helper-protocol.js.map +1 -1
  14. package/dist/src/gateway/claude-helper-supervisor.d.ts +3 -1
  15. package/dist/src/gateway/claude-helper-supervisor.js +16 -2
  16. package/dist/src/gateway/claude-helper-supervisor.js.map +1 -1
  17. package/dist/src/gateway/claude-helper.js +4 -3
  18. package/dist/src/gateway/claude-helper.js.map +1 -1
  19. package/dist/src/gateway/claude-peer.d.ts +1 -1
  20. package/dist/src/gateway/claude-peer.js +11 -13
  21. package/dist/src/gateway/claude-peer.js.map +1 -1
  22. package/dist/src/gateway/claude-runtime.d.ts +0 -20
  23. package/dist/src/gateway/claude-runtime.js +6 -127
  24. package/dist/src/gateway/claude-runtime.js.map +1 -1
  25. package/dist/src/gateway/cli-copy.en.d.ts +1 -1
  26. package/dist/src/gateway/cli-copy.en.js +2 -2
  27. package/dist/src/gateway/cli-copy.zh-CN.d.ts +1 -1
  28. package/dist/src/gateway/cli-copy.zh-CN.js +2 -2
  29. package/dist/src/gateway/cli.d.ts +1 -1
  30. package/dist/src/gateway/cli.js +26 -5
  31. package/dist/src/gateway/cli.js.map +1 -1
  32. package/dist/src/gateway/codex-app-server.d.ts +5 -74
  33. package/dist/src/gateway/codex-app-server.js +9 -597
  34. package/dist/src/gateway/codex-app-server.js.map +1 -1
  35. package/dist/src/gateway/codex-local-transport.d.ts +8 -26
  36. package/dist/src/gateway/codex-local-transport.js +26 -76
  37. package/dist/src/gateway/codex-local-transport.js.map +1 -1
  38. package/dist/src/gateway/compatibility.d.ts +6 -66
  39. package/dist/src/gateway/compatibility.js +14 -296
  40. package/dist/src/gateway/compatibility.js.map +1 -1
  41. package/dist/src/gateway/config.d.ts +9 -0
  42. package/dist/src/gateway/config.js +6 -2
  43. package/dist/src/gateway/config.js.map +1 -1
  44. package/dist/src/gateway/control.d.ts +16 -1
  45. package/dist/src/gateway/control.js +89 -57
  46. package/dist/src/gateway/control.js.map +1 -1
  47. package/dist/src/gateway/dashboard-copy.d.ts +1 -1
  48. package/dist/src/gateway/dashboard-copy.en.d.ts +14 -44
  49. package/dist/src/gateway/dashboard-copy.en.js +37 -67
  50. package/dist/src/gateway/dashboard-copy.en.js.map +1 -1
  51. package/dist/src/gateway/dashboard-copy.js +14 -44
  52. package/dist/src/gateway/dashboard-copy.js.map +1 -1
  53. package/dist/src/gateway/dashboard-copy.zh-CN.d.ts +14 -44
  54. package/dist/src/gateway/dashboard-copy.zh-CN.js +37 -67
  55. package/dist/src/gateway/dashboard-copy.zh-CN.js.map +1 -1
  56. package/dist/src/gateway/dashboard-model.d.ts +38 -76
  57. package/dist/src/gateway/dashboard-model.js +158 -256
  58. package/dist/src/gateway/dashboard-model.js.map +1 -1
  59. package/dist/src/gateway/dashboard.d.ts +0 -3
  60. package/dist/src/gateway/dashboard.js +75 -76
  61. package/dist/src/gateway/dashboard.js.map +1 -1
  62. package/dist/src/gateway/deepseek-detect.d.ts +7 -6
  63. package/dist/src/gateway/deepseek-detect.js +31 -115
  64. package/dist/src/gateway/deepseek-detect.js.map +1 -1
  65. package/dist/src/gateway/live-dashboard-app/app.js +166 -621
  66. package/dist/src/gateway/live-dashboard-command.js +2 -4
  67. package/dist/src/gateway/live-dashboard-command.js.map +1 -1
  68. package/dist/src/gateway/live-dashboard-http.d.ts +1 -2
  69. package/dist/src/gateway/live-dashboard-http.js +14 -15
  70. package/dist/src/gateway/live-dashboard-http.js.map +1 -1
  71. package/dist/src/gateway/progress-watch-machine.d.ts +1 -4
  72. package/dist/src/gateway/progress-watch-machine.js.map +1 -1
  73. package/dist/src/gateway/provenance-envelope.d.ts +3 -2
  74. package/dist/src/gateway/provenance-envelope.js +44 -11
  75. package/dist/src/gateway/provenance-envelope.js.map +1 -1
  76. package/dist/src/gateway/providers.d.ts +12 -84
  77. package/dist/src/gateway/providers.js +69 -806
  78. package/dist/src/gateway/providers.js.map +1 -1
  79. package/dist/src/gateway/server.d.ts +8 -9
  80. package/dist/src/gateway/server.js +51 -99
  81. package/dist/src/gateway/server.js.map +1 -1
  82. package/dist/src/gateway/service.d.ts +22 -49
  83. package/dist/src/gateway/service.js +196 -432
  84. package/dist/src/gateway/service.js.map +1 -1
  85. package/dist/src/gateway/store.d.ts +20 -29
  86. package/dist/src/gateway/store.js +281 -827
  87. package/dist/src/gateway/store.js.map +1 -1
  88. package/dist/src/gateway/types.d.ts +55 -55
  89. package/dist/src/gateway/types.js +49 -91
  90. package/dist/src/gateway/types.js.map +1 -1
  91. package/docs/CONFIGURATION.md +11 -10
  92. package/docs/CONFIGURATION.zh-CN.md +10 -9
  93. package/docs/DASHBOARD.md +4 -38
  94. package/docs/DASHBOARD.zh-CN.md +4 -2
  95. package/docs/GATEWAY-ARCHITECTURE.md +61 -119
  96. package/package.json +1 -1
  97. package/skills/embassy-peer/SKILL.md +6 -6
@@ -1,15 +1,14 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
2
  import { BridgeError } from "../errors.js";
3
3
  import { KeyedMutex } from "../mutex.js";
4
- import { certifiedCompatibilityVersions, compatibilitySurfaceDefinitions, evaluateCompatibilityAttestation, isCompatibilityAttestation, } from "./compatibility.js";
5
- import { createGatewayConversationId, isGatewaySnapshot, startGatewayControlServer, } from "./control.js";
4
+ import { createGatewayConversationId, isGatewaySnapshot, startGatewayControlServer, pairParamAliases, pairParamThreadAttestation, } from "./control.js";
6
5
  import { publishGatewayDashboard } from "./dashboard.js";
7
6
  import { createDeliveryMachine, isTerminalDeliveryMachine, projectDelivery, projectDeliveryWakeups, transitionDelivery, } from "./delivery-machine.js";
8
7
  import { createCodexRegistrationSuccession, transitionCodexRegistrationSuccession, } from "./codex-registration-succession.js";
9
8
  import { createCodexRegistrationGeneration, isCodexRegistrationGeneration, } from "./codex-registration-generation.js";
10
9
  import { PROGRESS_WATCH_DEFAULT_IDLE_MS } from "./progress-watch-machine.js";
11
10
  import { GatewayStore, } from "./store.js";
12
- import { GATEWAY_PUBLIC_SNAPSHOT_BYTE_BUDGET, gatewayPublicSnapshotLimits, arePublicAvailablePeerSnapshots, projectPublicCompatibilityCheck, projectGatewayPublicSnapshot, } from "./types.js";
11
+ import { GATEWAY_PUBLIC_SNAPSHOT_BYTE_BUDGET, gatewayPublicSnapshotLimits, gatewayRegistrationIngressPrefixes, arePublicAvailablePeerSnapshots, directionId, parseDirection, projectGatewayPublicSnapshot, } from "./types.js";
13
12
  const PUBLIC_ALIAS = /^[a-z][a-z0-9_-]{0,31}@[a-z0-9](?:[a-z0-9.-]{0,61}[a-z0-9])?$/;
14
13
  const CLAUDE_SESSION_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
15
14
  const SAFE_CODE = /^[A-Z][A-Z0-9_]{0,63}$/;
@@ -77,39 +76,13 @@ function bindingKey(binding) {
77
76
  ].join("\0");
78
77
  }
79
78
  function endpointRefreshCallbackKey(event) {
80
- const attestation = {
81
- schemaVersion: event.attestation.schemaVersion,
82
- surface: event.attestation.surface,
83
- version: event.attestation.version,
84
- tier: event.attestation.tier,
85
- checkedAt: event.attestation.checkedAt,
86
- probes: event.attestation.probes.map((probe) => ({
87
- name: probe.name,
88
- outcome: probe.outcome,
89
- ...(probe.safeErrorCode === undefined
90
- ? {}
91
- : { safeErrorCode: probe.safeErrorCode }),
92
- })),
93
- ...(event.attestation.safeErrorCode === undefined
94
- ? {}
95
- : { safeErrorCode: event.attestation.safeErrorCode }),
96
- };
97
- return event.outcome === "compatible"
98
- ? JSON.stringify({
99
- outcome: event.outcome,
100
- previous: event.previous,
101
- current: event.current,
102
- attestation,
103
- routes: [...event.routes]
104
- .map((route) => ({ ...route }))
105
- .sort((left, right) => left.routeHandle.localeCompare(right.routeHandle)),
106
- })
107
- : JSON.stringify({
108
- outcome: event.outcome,
109
- previous: event.previous,
110
- candidate: event.candidate,
111
- attestation,
112
- });
79
+ return JSON.stringify({
80
+ previous: event.previous,
81
+ current: event.current,
82
+ routes: [...event.routes]
83
+ .map((route) => ({ ...route }))
84
+ .sort((left, right) => left.routeHandle.localeCompare(right.routeHandle)),
85
+ });
113
86
  }
114
87
  function stableLease(provider, value) {
115
88
  return `lease_${createHash("sha256").update(provider).update("\0").update(value).digest("base64url")}`;
@@ -149,8 +122,6 @@ export class GatewayService {
149
122
  config;
150
123
  store;
151
124
  adapters;
152
- compatibilityObservers;
153
- compatibilitySurfaceDefinitions;
154
125
  publishDashboard;
155
126
  now;
156
127
  timers;
@@ -176,9 +147,6 @@ export class GatewayService {
176
147
  deliveryTokens = new Map();
177
148
  runtimeAlerts = [];
178
149
  activityEvents = [];
179
- /** Startup probe failures that must preflight cross-provider mutations. */
180
- incompatibleProviderSurfaces = new Map();
181
- activeCodexIncompatibility;
182
150
  activitySequence = 0;
183
151
  detachedReceiptWrites = new Set();
184
152
  nativeIngressByConversation = new Map();
@@ -202,8 +170,6 @@ export class GatewayService {
202
170
  durablyAppliedEndpointRefreshes = new Map();
203
171
  /** Selector transitions staged until their exact registration owns a helper. */
204
172
  pendingSelectorEndpointActivations = new Map();
205
- /** Last incompatible transition already projected per allowed Codex host. */
206
- handledIncompatibleEndpointRefreshes = new Map();
207
173
  /** Process-local dedupe for automatic public activity rows across retries. */
208
174
  endpointRefreshActivityKeys = new Set();
209
175
  callbackWorker;
@@ -247,9 +213,6 @@ export class GatewayService {
247
213
  constructor(options) {
248
214
  this.config = options.config;
249
215
  this.adapters = [...(options.adapters ?? [])];
250
- this.compatibilityObservers = [...(options.compatibilityObservers ?? [])];
251
- this.compatibilitySurfaceDefinitions =
252
- options.compatibilitySurfaceDefinitions ?? compatibilitySurfaceDefinitions;
253
216
  this.publishDashboard = options.publishDashboard ?? publishGatewayDashboard;
254
217
  this.now = options.now ?? (() => new Date());
255
218
  this.store =
@@ -297,28 +260,41 @@ export class GatewayService {
297
260
  }
298
261
  seen.add(key);
299
262
  }
300
- if (this.adapters.length > 0) {
301
- await this.runAutomaticCompatibilityProbesLocked();
302
- assertStartActive();
303
- }
304
263
  for (const adapter of this.adapters) {
305
264
  const observation = await adapter.initialize(this.callbacksFor(adapter));
306
265
  assertStartActive();
266
+ this.captureRegistryObservation(adapter, adapter.latestRegistryObservation?.());
307
267
  await this.store.observeConnector({
308
268
  identity: adapter.identity,
309
269
  health: observation.health,
310
- compatibility: observation.compatibility,
311
270
  protocol: adapter.protocol,
312
271
  protocolVersion: adapter.protocolVersion,
313
272
  ...(observation.safeErrorCode === undefined
314
273
  ? {}
315
274
  : { safeErrorCode: safeCode(observation.safeErrorCode, "ADAPTER_DEGRADED") }),
316
275
  });
276
+ if (observation.ownedRoute !== undefined) {
277
+ const route = observation.ownedRoute;
278
+ const prefix = gatewayRegistrationIngressPrefixes[adapter.identity.provider];
279
+ if (prefix === undefined || !route.alias.startsWith(prefix) ||
280
+ !route.alias.endsWith(`@${adapter.identity.hostId}`) ||
281
+ !PUBLIC_ALIAS.test(route.alias) || !PRIVATE_HANDLE.test(route.routeHandle) ||
282
+ route.state !== "idle") {
283
+ throw new BridgeError("GATEWAY_OWNED_ROUTE_INVALID", "A config-declared provider route has invalid identity evidence.");
284
+ }
285
+ const binding = {
286
+ ...adapter.identity,
287
+ routeHandle: route.routeHandle,
288
+ ownerLease: stableLease(adapter.identity.provider, `${adapter.identity.hostId}\0${route.alias}`),
289
+ };
290
+ await this.registerOrRebind(route.alias, binding, "endpoint_reobserved", route.state, binding.ownerLease, "explicit_opt_in");
291
+ this.rememberBinding(route.alias, binding, route.state);
292
+ bootReactivatedIdleAliases.push(route.alias);
293
+ }
317
294
  assertStartActive();
318
295
  }
319
296
  await this.recoverCodexSuccessionAfterRestartLocked();
320
- bootReactivatedIdleAliases =
321
- await this.reactivateRetainedCodexRoutesAfterRestartLocked();
297
+ bootReactivatedIdleAliases.push(...(await this.reactivateRetainedCodexRoutesAfterRestartLocked()));
322
298
  assertStartActive();
323
299
  const control = await startGatewayControlServer({
324
300
  stateDir: this.store.rootDir,
@@ -460,7 +436,6 @@ export class GatewayService {
460
436
  this.deliveryTrackers.clear();
461
437
  this.deliveryTokens.clear();
462
438
  this.runtimeAlerts.length = 0;
463
- this.incompatibleProviderSurfaces.clear();
464
439
  this.registryEvidenceByConnector.clear();
465
440
  this.registryAdaptersWithParseableRecords.clear();
466
441
  this.detachedReceiptWrites.clear();
@@ -476,7 +451,6 @@ export class GatewayService {
476
451
  this.activatedEndpointRefreshes.clear();
477
452
  this.durablyAppliedEndpointRefreshes.clear();
478
453
  this.pendingSelectorEndpointActivations.clear();
479
- this.handledIncompatibleEndpointRefreshes.clear();
480
454
  this.endpointRefreshActivityKeys.clear();
481
455
  this.codexOrphanCleanupPending.clear();
482
456
  this.candidates.clear();
@@ -536,12 +510,12 @@ export class GatewayService {
536
510
  pair: async (params) => await this.exclusiveDecision(async () => this.pairRoutes(params), {
537
511
  kind: "pairing",
538
512
  action: "routes_paired",
539
- aliases: [params.claudeAlias, params.codexAlias],
513
+ aliases: [...pairParamAliases(params)],
540
514
  }),
541
515
  unpair: async (params) => await this.exclusiveDecision(async () => this.unpairRoutes(params), {
542
516
  kind: "pairing",
543
517
  action: "routes_unpaired",
544
- aliases: [params.claudeAlias, params.codexAlias],
518
+ aliases: [...pairParamAliases(params)],
545
519
  }),
546
520
  listSnapshot: async () => (await this.observeSnapshot()).snapshot,
547
521
  observeSnapshot: async () => await this.observeSnapshot(),
@@ -572,88 +546,6 @@ export class GatewayService {
572
546
  async snapshot() {
573
547
  return (await this.observeSnapshot()).snapshot;
574
548
  }
575
- async runAutomaticCompatibilityProbesLocked() {
576
- const entries = [
577
- ...this.adapters.map((adapter) => {
578
- if (adapter.compatibilitySurface === undefined ||
579
- adapter.runCompatibilityProbes === undefined) {
580
- throw new BridgeError("COMPAT_PROVIDER_UNAVAILABLE", "Every local provider must expose the bounded compatibility probe contract.");
581
- }
582
- return {
583
- observer: adapter,
584
- adapter,
585
- };
586
- }),
587
- ...this.compatibilityObservers.map((observer) => ({ observer })),
588
- ];
589
- const observedEntries = entries.map((entry) => ({
590
- ...entry,
591
- observation: entry.observer.compatibilitySurface(),
592
- }));
593
- const bySurface = new Map(observedEntries.map((entry) => [entry.observation.surface, entry]));
594
- if (bySurface.size !== entries.length) {
595
- throw new BridgeError("COMPAT_PROVIDER_UNAVAILABLE", "Each compatibility observer must expose one distinct surface.");
596
- }
597
- const declared = new Set(this.compatibilitySurfaceDefinitions.map(({ surface }) => surface));
598
- if ([...bySurface.keys()].some((surface) => !declared.has(surface))) {
599
- throw new BridgeError("COMPAT_SURFACE_UNDECLARED", "Every compatibility observer must use a declared surface.");
600
- }
601
- const forbiddenCodexThreadIds = (await this.store.inspectPrivateCodexRoutes()).map((route) => route.binding.routeHandle);
602
- const probeContext = {
603
- stateRoot: this.store.rootDir,
604
- forbiddenCodexThreadIds,
605
- };
606
- const attestations = [];
607
- for (const definition of this.compatibilitySurfaceDefinitions) {
608
- const { surface } = definition;
609
- const entry = bySurface.get(surface);
610
- if (entry === undefined) {
611
- if (!definition.required)
612
- continue;
613
- throw new BridgeError("COMPAT_PROVIDER_UNAVAILABLE", "A required compatibility surface is unavailable.");
614
- }
615
- const probes = entry.adapter === undefined
616
- ? await entry.observer.runCompatibilityProbes()
617
- : await entry.adapter.runCompatibilityProbes(probeContext);
618
- if (entry.adapter !== undefined) {
619
- const writeProbe = entry.adapter.latestWriteCompatibilityProbeObservation?.(entry.adapter.identity.endpointGeneration);
620
- if (writeProbe?.outcome === "fail") {
621
- this.addRuntimeAlert(writeProbe.safeErrorCode, writeProbe.safeErrorCode === "CODEX_WRITE_PROBE_TOOL_ACTIVITY_OBSERVED" ||
622
- writeProbe.safeErrorCode === "CODEX_WRITE_PROBE_CLEANUP_UNCONFIRMED"
623
- ? "error"
624
- : "warning", { provider: "codex", host: entry.adapter.identity.hostId });
625
- }
626
- this.captureRegistryObservation(entry.adapter, entry.adapter.latestRegistryObservation?.());
627
- }
628
- const attestation = evaluateCompatibilityAttestation({
629
- surface,
630
- version: entry.observation.version,
631
- checkedAt: this.now().toISOString(),
632
- certifiedVersions: certifiedCompatibilityVersions[surface],
633
- probes,
634
- });
635
- await this.store.recordCompatibilityAttestation(attestation);
636
- entry.observer.acceptCompatibilityAttestation?.(attestation);
637
- if (attestation.tier === "incompatible" && entry.adapter !== undefined) {
638
- const code = attestation.safeErrorCode ?? "COMPATIBILITY_CHECK_FAILED";
639
- this.incompatibleProviderSurfaces.set(this.providerSurfaceKey(entry.adapter.identity.provider, entry.adapter.identity.hostId), code);
640
- if (surface === "codex") {
641
- this.activeCodexIncompatibility = structuredClone(attestation);
642
- }
643
- }
644
- else if (surface === "codex" &&
645
- attestation.tier === "schema_attested" &&
646
- entry.adapter !== undefined) {
647
- // A live but untested App Server schema is useful for observation only.
648
- // Fence retained boot reactivation before it can trigger endpoint
649
- // refresh churn; an explicit registration may still re-probe a later,
650
- // certified generation through the provider's bounded refresh path.
651
- this.incompatibleProviderSurfaces.set(this.providerSurfaceKey("codex", entry.adapter.identity.hostId), "CODEX_MONITOR_ONLY");
652
- }
653
- attestations.push(attestation);
654
- }
655
- return attestations;
656
- }
657
549
  captureRegistryObservation(adapter, observation) {
658
550
  if (adapter.identity.provider !== "claude" ||
659
551
  observation === undefined ||
@@ -881,50 +773,30 @@ export class GatewayService {
881
773
  });
882
774
  },
883
775
  onEndpointRefresh: (event) => {
776
+ if (!Array.isArray(event.routes))
777
+ return;
778
+ const routeHandles = event.routes.map((route) => route.routeHandle);
884
779
  if (!this.running ||
885
780
  adapter.identity.provider !== "codex" ||
886
781
  event.previous.provider !== "codex" ||
887
782
  event.previous.hostId !== adapter.identity.hostId ||
888
- !isCompatibilityAttestation(event.attestation) ||
889
- event.attestation.surface !== "codex") {
890
- return;
891
- }
892
- if (event.outcome === "compatible") {
893
- const routeHandles = event.routes.map((route) => route.routeHandle);
894
- if (event.current.provider !== "codex" ||
895
- event.current.hostId !== event.previous.hostId ||
896
- event.current.endpointGeneration !==
897
- adapter.identity.endpointGeneration ||
898
- event.attestation.version !== adapter.protocolVersion ||
899
- event.attestation.tier === "incompatible" ||
900
- routeHandles.length > this.config.limits.maxRoutes ||
901
- new Set(routeHandles).size !== routeHandles.length ||
902
- routeHandles.some((routeHandle) => !PRIVATE_HANDLE.test(routeHandle))) {
903
- return;
904
- }
905
- }
906
- else if (event.candidate.provider !== "codex" ||
907
- event.candidate.hostId !== event.previous.hostId ||
908
- event.previous.endpointGeneration !==
783
+ event.current.provider !== "codex" ||
784
+ event.current.hostId !== event.previous.hostId ||
785
+ event.current.endpointGeneration !==
909
786
  adapter.identity.endpointGeneration ||
910
- event.attestation.tier !== "incompatible") {
787
+ routeHandles.length > this.config.limits.maxRoutes ||
788
+ new Set(routeHandles).size !== routeHandles.length ||
789
+ routeHandles.some((routeHandle) => !PRIVATE_HANDLE.test(routeHandle))) {
911
790
  return;
912
791
  }
913
792
  this.enqueueCallback({
914
793
  type: "endpoint_refresh",
915
794
  adapter,
916
- value: event.outcome === "compatible"
917
- ? {
918
- ...event,
919
- previous: { ...event.previous },
920
- current: { ...event.current },
921
- routes: event.routes.map((route) => ({ ...route })),
922
- }
923
- : {
924
- ...event,
925
- previous: { ...event.previous },
926
- candidate: { ...event.candidate },
927
- },
795
+ value: {
796
+ previous: { ...event.previous },
797
+ current: { ...event.current },
798
+ routes: event.routes.map((route) => ({ ...route })),
799
+ },
928
800
  });
929
801
  },
930
802
  };
@@ -1071,7 +943,7 @@ export class GatewayService {
1071
943
  await this.onDelivery(event.source, event.value, event.receivedAt);
1072
944
  }
1073
945
  else if (event.type === "route") {
1074
- if (pendingRefresh?.outcome === "compatible" &&
946
+ if (pendingRefresh !== undefined &&
1075
947
  event.source.provider === "codex" &&
1076
948
  event.source.hostId === pendingRefresh.current.hostId &&
1077
949
  event.source.endpointGeneration ===
@@ -1201,12 +1073,7 @@ export class GatewayService {
1201
1073
  await this.drainDetachedReceiptWritesLocked();
1202
1074
  }
1203
1075
  async failClosedEndpointRefreshConflict(boundary) {
1204
- const identities = [
1205
- boundary.value.previous,
1206
- ...(boundary.value.outcome === "compatible"
1207
- ? [boundary.value.current]
1208
- : []),
1209
- ];
1076
+ const identities = [boundary.value.previous, boundary.value.current];
1210
1077
  for (const identity of identities) {
1211
1078
  const routes = (await this.store.inspectPrivateCodexRoutes()).filter((route) => route.binding.hostId === identity.hostId &&
1212
1079
  route.binding.endpointGeneration === identity.endpointGeneration);
@@ -1308,23 +1175,6 @@ export class GatewayService {
1308
1175
  throw new BridgeError("PROVIDER_UNAVAILABLE", "The selected provider is unavailable.", true);
1309
1176
  return adapter;
1310
1177
  }
1311
- providerSurfaceKey(provider, host) {
1312
- return `${provider}@${host}`;
1313
- }
1314
- incompatibleProviderCode(provider, host) {
1315
- return this.incompatibleProviderSurfaces.get(this.providerSurfaceKey(provider, host));
1316
- }
1317
- /** Reject before either half of a cross-provider mutation can acquire state. */
1318
- assertCrossProviderMutationCompatible(host, options = { allowCodexRefresh: false }) {
1319
- const claudeCode = this.incompatibleProviderCode("claude", host);
1320
- if (claudeCode !== undefined) {
1321
- throw new BridgeError(claudeCode, "The Claude provider is observation-only until Embassy restarts with a compatible runtime.");
1322
- }
1323
- const codexCode = this.incompatibleProviderCode("codex", host);
1324
- if (codexCode !== undefined && !options.allowCodexRefresh) {
1325
- throw new BridgeError(codexCode, "The Codex provider is observation-only until a compatible endpoint is re-observed.");
1326
- }
1327
- }
1328
1178
  async assertClaudeWorkspaceDisjoint(adapter, routeHandle) {
1329
1179
  if (adapter.identity.provider !== "claude") {
1330
1180
  throw new BridgeError("CLAUDE_PROVIDER_MISMATCH", "The selected workspace guard does not belong to Claude.");
@@ -1382,7 +1232,6 @@ export class GatewayService {
1382
1232
  for (const route of retained) {
1383
1233
  if (!route.enabled ||
1384
1234
  route.state !== "stale" ||
1385
- route.compatibility !== "expired" ||
1386
1235
  this.pendingCodexSuccessionRecovery?.journal.new.alias === route.alias ||
1387
1236
  this.codexSuccessionPoisoned.has(route.alias)) {
1388
1237
  continue;
@@ -1395,13 +1244,6 @@ export class GatewayService {
1395
1244
  this.addRuntimeAlert("CODEX_BOOT_REACTIVATION_SKIPPED", "warning", { provider: "codex", host: route.binding.hostId, alias: route.alias });
1396
1245
  continue;
1397
1246
  }
1398
- if (this.incompatibleProviderCode("codex", route.binding.hostId) !==
1399
- undefined ||
1400
- this.incompatibleProviderCode("claude", route.binding.hostId) !==
1401
- undefined) {
1402
- this.addRuntimeAlert("CODEX_BOOT_REACTIVATION_SKIPPED", "warning", { provider: "codex", host: route.binding.hostId, alias: route.alias });
1403
- continue;
1404
- }
1405
1247
  let routeSelected = false;
1406
1248
  let advertiseAttempted = false;
1407
1249
  let storeReactivated = false;
@@ -1439,19 +1281,20 @@ export class GatewayService {
1439
1281
  storeReactivated =
1440
1282
  afterStaging !== undefined &&
1441
1283
  afterStaging.enabled &&
1442
- afterStaging.compatibility === "compatible" &&
1284
+ afterStaging.state !== "stale" &&
1443
1285
  bindingKey(afterStaging.binding) === bindingKey(binding);
1444
1286
  }
1445
1287
  advertiseAttempted = true;
1446
- const advertise = claudeAdapter.advertiseNativeCodexPeer;
1288
+ const advertise = claudeAdapter.advertiseNativeSourcePeer;
1447
1289
  if (advertise === undefined) {
1448
1290
  throw new BridgeError("CODEX_BOOT_REACTIVATION_UNAVAILABLE", "The retained Codex task cannot rebuild its native advertisement.");
1449
1291
  }
1450
1292
  await advertise.call(claudeAdapter, {
1451
1293
  alias: route.alias,
1294
+ sourceProvider: "codex",
1452
1295
  cwd: this.nativePeerCwd,
1453
1296
  });
1454
- await claudeAdapter.updateNativeCodexPeerStatus?.(route.alias, selected.state === "idle"
1297
+ await claudeAdapter.updateNativeSourcePeerStatus?.(route.alias, selected.state === "idle"
1455
1298
  ? "idle"
1456
1299
  : selected.state === "awaiting_approval"
1457
1300
  ? "waiting"
@@ -1495,7 +1338,7 @@ export class GatewayService {
1495
1338
  let cleanupFailed = false;
1496
1339
  if (advertiseAttempted) {
1497
1340
  await claudeAdapter
1498
- .unadvertiseNativeCodexPeer?.(route.alias)
1341
+ .unadvertiseNativeSourcePeer?.(route.alias)
1499
1342
  .catch(() => {
1500
1343
  cleanupFailed = true;
1501
1344
  });
@@ -1627,7 +1470,7 @@ export class GatewayService {
1627
1470
  oldInspection.binding.ownerLease !==
1628
1471
  stableLease("codex", `${lock.hostId}\0${lock.threadId}`) ||
1629
1472
  !oldInspection.enabled ||
1630
- oldInspection.compatibility !== "compatible") {
1473
+ oldInspection.state === "stale") {
1631
1474
  throw new BridgeError("CODEX_SUCCESSION_OWNER_MISMATCH", "The active Codex registration is no longer exact and compatible.");
1632
1475
  }
1633
1476
  const claudeAdapter = this.adapter("claude", params.hostId);
@@ -1936,7 +1779,7 @@ export class GatewayService {
1936
1779
  this.rememberBinding(effect.registration.alias, execution.newBinding, state);
1937
1780
  this.codexRegistrationLocks.delete(this.successionOldRegistration(execution).alias);
1938
1781
  this.codexRegistrationLocks.set(effect.registration.alias, Object.freeze({ ...effect.registration }));
1939
- await claudeAdapter.updateNativeCodexPeerStatus?.(effect.registration.alias, state === "idle"
1782
+ await claudeAdapter.updateNativeSourcePeerStatus?.(effect.registration.alias, state === "idle"
1940
1783
  ? "idle"
1941
1784
  : state === "awaiting_approval"
1942
1785
  ? "waiting"
@@ -2081,8 +1924,8 @@ export class GatewayService {
2081
1924
  throw new BridgeError("CODEX_SUCCESSION_DRAIN_INCOMPLETE", "Interrupted generations cannot close before pending work and receipts are drained. Restart the gateway with embassy serve.");
2082
1925
  }
2083
1926
  const results = await Promise.allSettled([
2084
- claudeAdapter.unadvertiseNativeCodexPeer?.(execution.oldRegistration.alias),
2085
- claudeAdapter.unadvertiseNativeCodexPeer?.(execution.newRegistration.alias),
1927
+ claudeAdapter.unadvertiseNativeSourcePeer?.(execution.oldRegistration.alias),
1928
+ claudeAdapter.unadvertiseNativeSourcePeer?.(execution.newRegistration.alias),
2086
1929
  codexAdapter.releaseRoute?.(execution.oldRegistration.threadId),
2087
1930
  codexAdapter.releaseRoute?.(execution.newRegistration.threadId),
2088
1931
  ]);
@@ -2307,9 +2150,6 @@ export class GatewayService {
2307
2150
  if (!params.alias.startsWith("codex-")) {
2308
2151
  throw new BridgeError("INVALID_CODEX_PEER_ALIAS", "A registered Codex alias must start with codex-.");
2309
2152
  }
2310
- this.assertCrossProviderMutationCompatible(params.hostId, {
2311
- allowCodexRefresh: params.succeedsAlias === undefined,
2312
- });
2313
2153
  if (this.codexSuccessionPoisoned.has(params.alias) ||
2314
2154
  this.codexOrphanCleanupPending.has(params.alias) ||
2315
2155
  (params.succeedsAlias !== undefined &&
@@ -2380,7 +2220,7 @@ export class GatewayService {
2380
2220
  const afterRefresh = await this.store.inspectPrivateRoute(params.alias);
2381
2221
  const alreadyInstalledExactly = afterRefresh !== undefined &&
2382
2222
  afterRefresh.enabled &&
2383
- afterRefresh.compatibility === "compatible" &&
2223
+ afterRefresh.state !== "stale" &&
2384
2224
  bindingKey(afterRefresh.binding) === bindingKey(binding);
2385
2225
  if (!alreadyInstalledExactly || !deferredEndpointRefresh) {
2386
2226
  await this.registerOrRebind(params.alias, binding, "endpoint_reobserved", registered.state);
@@ -2395,15 +2235,16 @@ export class GatewayService {
2395
2235
  try {
2396
2236
  this.rememberBinding(params.alias, binding, registered.state);
2397
2237
  const claudeAdapter = this.adapter("claude", params.hostId);
2398
- const advertise = claudeAdapter.advertiseNativeCodexPeer;
2238
+ const advertise = claudeAdapter.advertiseNativeSourcePeer;
2399
2239
  if (advertise !== undefined) {
2400
2240
  advertiseAttempted = true;
2401
2241
  await advertise.call(claudeAdapter, {
2402
2242
  alias: params.alias,
2243
+ sourceProvider: "codex",
2403
2244
  cwd: this.nativePeerCwd,
2404
2245
  });
2405
2246
  }
2406
- await claudeAdapter.updateNativeCodexPeerStatus?.(params.alias, registered.state === "idle"
2247
+ await claudeAdapter.updateNativeSourcePeerStatus?.(params.alias, registered.state === "idle"
2407
2248
  ? "idle"
2408
2249
  : registered.state === "awaiting_approval"
2409
2250
  ? "waiting"
@@ -2425,8 +2266,7 @@ export class GatewayService {
2425
2266
  }
2426
2267
  catch (error) {
2427
2268
  if (routeBeforeRegistration !== undefined) {
2428
- if (deferredEndpointRefresh &&
2429
- registered.endpointRefresh?.outcome === "compatible") {
2269
+ if (deferredEndpointRefresh && registered.endpointRefresh !== undefined) {
2430
2270
  try {
2431
2271
  await this.store.markConnectorOffline(registered.endpointRefresh.current, "CODEX_ENDPOINT_ACTIVATION_FAILED", [], { preserveQueued: true });
2432
2272
  this.routeStates.set(params.alias, "stale");
@@ -2508,7 +2348,7 @@ export class GatewayService {
2508
2348
  });
2509
2349
  if (advertiseAttempted) {
2510
2350
  await this.adapter("claude", params.hostId)
2511
- .unadvertiseNativeCodexPeer?.(params.alias)
2351
+ .unadvertiseNativeSourcePeer?.(params.alias)
2512
2352
  .catch(() => {
2513
2353
  cleanupFailed = true;
2514
2354
  });
@@ -2535,7 +2375,7 @@ export class GatewayService {
2535
2375
  }
2536
2376
  this.forgetBinding(params.alias);
2537
2377
  await this.adapter("claude", host)
2538
- .unadvertiseNativeCodexPeer?.(params.alias)
2378
+ .unadvertiseNativeSourcePeer?.(params.alias)
2539
2379
  .catch(() => {
2540
2380
  this.dashboardHealthy = false;
2541
2381
  });
@@ -2706,7 +2546,7 @@ export class GatewayService {
2706
2546
  }
2707
2547
  await this.requireUnchangedStaleCodexOrphan(alias, binding);
2708
2548
  if (nativeGeneration !== undefined) {
2709
- const unadvertise = claudeAdapter.unadvertiseNativeCodexPeer;
2549
+ const unadvertise = claudeAdapter.unadvertiseNativeSourcePeer;
2710
2550
  if (unadvertise === undefined) {
2711
2551
  throw new BridgeError("CODEX_ORPHAN_NATIVE_IDENTITY_UNPROVEN", "The native Codex listener cannot be removed exactly.");
2712
2552
  }
@@ -2896,7 +2736,6 @@ export class GatewayService {
2896
2736
  for (const route of persisted) {
2897
2737
  if (!route.enabled ||
2898
2738
  route.state !== "stale" ||
2899
- route.compatibility !== "expired" ||
2900
2739
  !CLAUDE_SESSION_ID.test(route.binding.routeHandle) ||
2901
2740
  route.binding.ownerLease !==
2902
2741
  stableLease("claude", route.binding.routeHandle)) {
@@ -2920,8 +2759,7 @@ export class GatewayService {
2920
2759
  alias,
2921
2760
  provider: "claude",
2922
2761
  host: row.adapter.identity.hostId,
2923
- state: "incompatible",
2924
- compatibility: "incompatible",
2762
+ state: "offline",
2925
2763
  validated: false,
2926
2764
  selected: false,
2927
2765
  safeErrorCode: row.safeErrorCode,
@@ -2939,7 +2777,6 @@ export class GatewayService {
2939
2777
  provider: "claude",
2940
2778
  host: row.adapter.identity.hostId,
2941
2779
  state: row.peer.state,
2942
- compatibility: row.peer.compatibility,
2943
2780
  validated: true,
2944
2781
  selected,
2945
2782
  });
@@ -2948,7 +2785,6 @@ export class GatewayService {
2948
2785
  await this.store.observeRoute({
2949
2786
  binding: selectedBinding,
2950
2787
  state: row.peer.state,
2951
- compatibility: "compatible",
2952
2788
  });
2953
2789
  }
2954
2790
  }
@@ -2963,7 +2799,7 @@ export class GatewayService {
2963
2799
  const inspection = await this.store.inspectPrivateRoute(alias);
2964
2800
  if (inspection !== undefined &&
2965
2801
  inspection.enabled &&
2966
- inspection.compatibility === "compatible") {
2802
+ inspection.state !== "stale") {
2967
2803
  await this.drainPreDeadlineDeliveryCallbacksLocked();
2968
2804
  const inFlightSettlements = await this.planRouteInFlightSettlementsLocked(alias, {
2969
2805
  unwrittenOutcome: "failed",
@@ -3040,7 +2876,6 @@ export class GatewayService {
3040
2876
  const expectedLease = stableLease("claude", candidate.routeHandle);
3041
2877
  if (!persisted.enabled ||
3042
2878
  persisted.state !== "stale" ||
3043
- persisted.compatibility !== "expired" ||
3044
2879
  persisted.binding.provider !== "claude" ||
3045
2880
  candidate.adapter.identity.provider !== "claude" ||
3046
2881
  persisted.binding.hostId !== candidate.adapter.identity.hostId ||
@@ -3106,7 +2941,6 @@ export class GatewayService {
3106
2941
  binding,
3107
2942
  registrationMode: "selected_live_peer",
3108
2943
  state: selected.state,
3109
- compatibility: "compatible",
3110
2944
  });
3111
2945
  this.rememberBinding(candidate.alias, binding, selected.state);
3112
2946
  }
@@ -3158,7 +2992,6 @@ export class GatewayService {
3158
2992
  binding,
3159
2993
  registrationMode: "selected_live_peer",
3160
2994
  state: selectedState,
3161
- compatibility: "compatible",
3162
2995
  },
3163
2996
  inFlightSettlements,
3164
2997
  });
@@ -3231,47 +3064,83 @@ export class GatewayService {
3231
3064
  }
3232
3065
  return candidate.alias;
3233
3066
  }
3234
- assertCodexPairCaller(params) {
3235
- const binding = this.routeBindings.get(params.codexAlias);
3067
+ assertPairThreadAttestation(params) {
3068
+ const attestation = pairParamThreadAttestation(params);
3069
+ const legacyAlias = "codexAlias" in params ? params.codexAlias : undefined;
3070
+ if (attestation === undefined && legacyAlias === undefined)
3071
+ return;
3072
+ const binding = this.routeBindings.get(attestation?.alias ?? legacyAlias);
3236
3073
  if (binding?.provider !== "codex" ||
3237
- (params.codexThreadId !== undefined &&
3238
- binding.routeHandle !== params.codexThreadId)) {
3074
+ (attestation !== undefined && binding.routeHandle !== attestation.threadId)) {
3239
3075
  throw new BridgeError("CODEX_CALLER_MISMATCH", "The inherited Codex task does not own the requested pair endpoint.");
3240
3076
  }
3241
3077
  }
3242
3078
  async pairRoutes(params) {
3243
- this.assertCodexPairCaller(params);
3244
- await this.selectAndPairClaude(params.claudeAlias, params.codexAlias);
3079
+ this.assertPairThreadAttestation(params);
3080
+ if ("claudeAlias" in params) {
3081
+ await this.selectAndPairClaude(params.claudeAlias, params.codexAlias);
3082
+ return;
3083
+ }
3084
+ await this.assertLiveConsentEndpoints(params.aliases);
3085
+ const added = await this.store.addConsentEdge({ aliases: params.aliases });
3086
+ if (added.created)
3087
+ await this.changed();
3088
+ else
3089
+ await this.publish();
3245
3090
  }
3246
3091
  async unpairRoutes(params) {
3247
- this.assertCodexPairCaller(params);
3248
- const selected = await this.selectedClaudeRoute(params.claudeAlias);
3249
- await this.unpairClaudeRoute(selected, params.codexAlias);
3092
+ this.assertPairThreadAttestation(params);
3093
+ const aliases = pairParamAliases(params);
3094
+ if (!("claudeAlias" in params))
3095
+ await this.assertLiveConsentEndpoints(aliases);
3096
+ await this.removeConsentEdge(aliases);
3097
+ }
3098
+ async assertLiveConsentEndpoints(aliases) {
3099
+ const routes = await Promise.all(aliases.map((alias) => this.store.inspectPrivateRoute(alias)));
3100
+ if (routes[0] === undefined || routes[1] === undefined) {
3101
+ throw new BridgeError("CONSENT_EDGE_ROUTE_NOT_FOUND", "Both consent endpoints must be registered.");
3102
+ }
3103
+ for (const route of routes) {
3104
+ const live = this.routeBindings.get(route.alias);
3105
+ if (!route.enabled ||
3106
+ route.state === "stale" ||
3107
+ live === undefined ||
3108
+ bindingKey(live) !== bindingKey(route.binding) ||
3109
+ this.adapter(route.binding.provider, route.binding.hostId).identity.endpointGeneration !==
3110
+ route.binding.endpointGeneration) {
3111
+ throw new BridgeError("ROUTE_UNAVAILABLE", "Both consent endpoints must be exact positively observed live routes.");
3112
+ }
3113
+ }
3114
+ if (routes[0].binding.provider === routes[1].binding.provider || routes[0].binding.hostId !== routes[1].binding.hostId) {
3115
+ throw new BridgeError("INVALID_CONSENT_EDGE", "A consent edge must connect distinct providers on the same host.");
3116
+ }
3117
+ return routes;
3250
3118
  }
3251
- async unpairClaudeRoute(selected, codexAlias) {
3119
+ async removeConsentEdge(aliases) {
3252
3120
  await this.drainPreDeadlineDeliveryCallbacksLocked();
3253
- const pair = {
3254
- claudeAlias: selected.alias,
3255
- codexAlias,
3256
- };
3257
- const inFlightSettlements = await this.planPairInFlightSettlementsLocked(pair, {
3121
+ const routes = await Promise.all(aliases.map((alias) => this.store.inspectPrivateRoute(alias)));
3122
+ const edge = { aliases };
3123
+ const inFlightSettlements = await this.planConsentEdgeInFlightSettlementsLocked(edge, {
3258
3124
  unwrittenOutcome: "cancelled",
3259
3125
  safeErrorCode: "PAIR_REMOVED",
3260
3126
  });
3261
- const result = await this.store.unpairRoutes({
3262
- ...pair,
3127
+ const result = await this.store.removeConsentEdge({
3128
+ ...edge,
3263
3129
  inFlightSettlements,
3264
3130
  });
3265
3131
  for (const settlement of result.settlements) {
3266
3132
  await this.applyTerminalSettlementLocked(settlement);
3267
3133
  }
3268
- this.purgePairCapabilitiesLocked(pair);
3269
- if (result.claudeRouteUnreferenced) {
3270
- const settlements = await this.store.unregisterRoute(selected.alias, selected.binding.ownerLease);
3134
+ this.purgeConsentEdgeCapabilitiesLocked(aliases);
3135
+ for (const alias of result.unreferencedAliases) {
3136
+ const selected = routes.find((route) => route?.alias === alias);
3137
+ if (selected?.binding.provider !== "claude" || selected.registrationMode !== "selected_live_peer")
3138
+ continue;
3139
+ const settlements = await this.store.unregisterRoute(alias, selected.binding.ownerLease);
3271
3140
  for (const settlement of settlements) {
3272
3141
  await this.applyTerminalSettlementLocked(settlement);
3273
3142
  }
3274
- this.forgetBinding(selected.alias);
3143
+ this.forgetBinding(alias);
3275
3144
  await this.adapters
3276
3145
  .find((adapter) => adapter.identity.provider === "claude" &&
3277
3146
  adapter.identity.hostId === selected.binding.hostId)
@@ -3279,7 +3148,7 @@ export class GatewayService {
3279
3148
  .catch(() => {
3280
3149
  this.dashboardHealthy = false;
3281
3150
  });
3282
- this.availablePeers = this.availablePeers.map((peer) => peer.alias === selected.alias ? { ...peer, selected: false } : peer);
3151
+ this.availablePeers = this.availablePeers.map((peer) => peer.alias === alias ? { ...peer, selected: false } : peer);
3283
3152
  }
3284
3153
  await this.changed();
3285
3154
  }
@@ -3288,17 +3157,6 @@ export class GatewayService {
3288
3157
  }
3289
3158
  async selectAndPairClaude(selector, codexAlias) {
3290
3159
  const codexBinding = this.routeBindings.get(codexAlias);
3291
- const retainedCodexRoute = codexBinding?.provider === "codex"
3292
- ? undefined
3293
- : await this.store.inspectPrivateRoute(codexAlias);
3294
- const codexHost = codexBinding?.provider === "codex"
3295
- ? codexBinding.hostId
3296
- : retainedCodexRoute?.binding.provider === "codex"
3297
- ? retainedCodexRoute.binding.hostId
3298
- : undefined;
3299
- if (codexHost !== undefined) {
3300
- this.assertCrossProviderMutationCompatible(codexHost);
3301
- }
3302
3160
  const codexAdapter = codexBinding?.provider === "codex"
3303
3161
  ? this.adapters.find((adapter) => adapter.identity.provider === "codex" &&
3304
3162
  adapter.identity.hostId === codexBinding.hostId)
@@ -3338,10 +3196,7 @@ export class GatewayService {
3338
3196
  }
3339
3197
  let paired;
3340
3198
  try {
3341
- paired = await this.store.pairRoutes({
3342
- claudeAlias: candidate.alias,
3343
- codexAlias,
3344
- });
3199
+ paired = await this.store.addConsentEdge({ aliases: [candidate.alias, codexAlias] });
3345
3200
  }
3346
3201
  catch (error) {
3347
3202
  if (!alreadyLive &&
@@ -3381,7 +3236,7 @@ export class GatewayService {
3381
3236
  async unselectClaude(params) {
3382
3237
  const codexAlias = await this.inferCodexAlias(params.codexThreadId);
3383
3238
  const selected = await this.selectedClaudeRoute(params.alias);
3384
- await this.unpairClaudeRoute(selected, codexAlias);
3239
+ await this.removeConsentEdge([selected.alias, codexAlias]);
3385
3240
  }
3386
3241
  async selectedClaudeRoute(selector) {
3387
3242
  const persisted = await this.store.inspectPrivateClaudeRoutes();
@@ -3393,14 +3248,13 @@ export class GatewayService {
3393
3248
  throw new BridgeError("PEER_NOT_FOUND", "No selected Claude session matches that selector.");
3394
3249
  return selected;
3395
3250
  }
3396
- async registerOrRebind(alias, binding, reason, state, currentOwnerLease = binding.ownerLease) {
3251
+ async registerOrRebind(alias, binding, reason, state, currentOwnerLease = binding.ownerLease, registrationMode = binding.provider === "codex" ? "explicit_opt_in" : "selected_live_peer") {
3397
3252
  try {
3398
3253
  await this.store.registerRoute({
3399
3254
  alias,
3400
3255
  binding,
3401
- registrationMode: binding.provider === "codex" ? "explicit_opt_in" : "selected_live_peer",
3256
+ registrationMode,
3402
3257
  state,
3403
- compatibility: "compatible",
3404
3258
  });
3405
3259
  }
3406
3260
  catch (error) {
@@ -3470,14 +3324,12 @@ export class GatewayService {
3470
3324
  await this.store.observeConnector({
3471
3325
  identity: adapter.identity,
3472
3326
  health: "healthy",
3473
- compatibility: "compatible",
3474
3327
  protocol: adapter.protocol,
3475
3328
  protocolVersion: adapter.protocolVersion,
3476
3329
  });
3477
3330
  await this.store.observeRoute({
3478
3331
  binding,
3479
3332
  state,
3480
- compatibility: "compatible",
3481
3333
  });
3482
3334
  return binding;
3483
3335
  }
@@ -3793,8 +3645,8 @@ export class GatewayService {
3793
3645
  };
3794
3646
  });
3795
3647
  }
3796
- async planPairInFlightSettlementsLocked(pair, input) {
3797
- const affected = await this.store.inspectAffectedPairInFlightMessages(pair);
3648
+ async planConsentEdgeInFlightSettlementsLocked(edge, input) {
3649
+ const affected = await this.store.inspectAffectedConsentEdgeInFlightMessages(edge);
3798
3650
  const observedAt = this.now().getTime();
3799
3651
  return affected.map(({ messageId }) => {
3800
3652
  const tracker = this.deliveryTrackers.get(messageId);
@@ -3825,9 +3677,8 @@ export class GatewayService {
3825
3677
  };
3826
3678
  });
3827
3679
  }
3828
- purgePairCapabilitiesLocked(pair) {
3829
- const matches = (sourceAlias, targetAlias) => (sourceAlias === pair.claudeAlias && targetAlias === pair.codexAlias) ||
3830
- (sourceAlias === pair.codexAlias && targetAlias === pair.claudeAlias);
3680
+ purgeConsentEdgeCapabilitiesLocked(aliases) {
3681
+ const matches = (sourceAlias, targetAlias) => aliases.includes(sourceAlias) && aliases.includes(targetAlias);
3831
3682
  const conversationIds = new Set();
3832
3683
  for (const [conversationId, conversation] of this.conversations) {
3833
3684
  if (conversation.pair !== true ||
@@ -4611,12 +4462,13 @@ export class GatewayService {
4611
4462
  * native-ingress boundary; this preserves the exact connector generation
4612
4463
  * without recreating route authority or accepting a new unsolicited send.
4613
4464
  */
4614
- async enqueueObservedClaudeReplyAfterRouteTeardownLocked(conversation, sourceBinding, text) {
4465
+ async enqueueObservedClaudeReplyAfterRouteTeardownLocked(conversation, sourceBinding, expectedTargetBinding, text) {
4615
4466
  const target = await this.store.resolveRoute(conversation.sourceAlias);
4616
4467
  if (sourceBinding.provider !== "claude" ||
4617
- target.provider !== "codex" ||
4468
+ target.provider === "claude" ||
4469
+ target.provider !== expectedTargetBinding.provider || target.ownerLease !== expectedTargetBinding.ownerLease ||
4618
4470
  sourceBinding.hostId !== target.hostId) {
4619
- throw new BridgeError("RECOVERED_REPLY_ROUTE_MISMATCH", "The retained provider reply no longer matches an exact same-host Codex target.");
4471
+ throw new BridgeError("RECOVERED_REPLY_ROUTE_MISMATCH", "The retained provider reply no longer matches an exact same-host non-Claude target.");
4620
4472
  }
4621
4473
  const sequence = conversation.nextSequence;
4622
4474
  const enqueuedAt = this.now().getTime();
@@ -4647,6 +4499,7 @@ export class GatewayService {
4647
4499
  expectsReply: false,
4648
4500
  sequence,
4649
4501
  targetBindingKey: bindingKey(target),
4502
+ sourceBinding: { ...sourceBinding },
4650
4503
  authorization: "selected_route",
4651
4504
  targetAlias: conversation.sourceAlias,
4652
4505
  deadlineAt,
@@ -4659,7 +4512,7 @@ export class GatewayService {
4659
4512
  deadlineAt,
4660
4513
  });
4661
4514
  await this.changed();
4662
- await this.setNativeCodexStatus(conversation.sourceAlias, "waiting");
4515
+ await this.setNativeSourceStatus(conversation.sourceAlias, "waiting");
4663
4516
  this.scheduleDispatch(conversation.sourceAlias);
4664
4517
  }
4665
4518
  pruneTransient() {
@@ -4879,7 +4732,6 @@ export class GatewayService {
4879
4732
  !dispatchable ||
4880
4733
  inspection === undefined ||
4881
4734
  !inspection.enabled ||
4882
- inspection.compatibility !== "compatible" ||
4883
4735
  !storedDispatchable ||
4884
4736
  bindingKey(inspection.binding) !== bindingKey(binding) ||
4885
4737
  bindingKey(selectedBinding) !== bindingKey(binding)) {
@@ -4969,10 +4821,26 @@ export class GatewayService {
4969
4821
  })).markerActive
4970
4822
  : false;
4971
4823
  }
4824
+ const sourceBinding = context.sourceBinding ??
4825
+ (await this.store.inspectPrivateRoute(item.sourceAlias))?.binding;
4826
+ const parsedDirection = parseDirection(item.direction);
4827
+ if (sourceBinding === undefined ||
4828
+ parsedDirection?.sourceProvider !== sourceBinding.provider ||
4829
+ parsedDirection.targetProvider !== binding.provider ||
4830
+ item.direction !== directionId(sourceBinding.provider, binding.provider)) {
4831
+ await this.finishDelivery({
4832
+ messageId: item.messageId,
4833
+ state: "failed",
4834
+ safeErrorCode: "MESSAGE_DIRECTION_BINDING_MISMATCH",
4835
+ });
4836
+ return;
4837
+ }
4838
+ context.sourceBinding ??= { ...sourceBinding };
4972
4839
  let result;
4973
4840
  try {
4974
4841
  result = await this.awaitDispatchWithNativeHeldLocked(tracker, this.adapter(binding.provider, binding.hostId).dispatch({
4975
4842
  sourceAlias: item.sourceAlias,
4843
+ sourceProvider: sourceBinding.provider,
4976
4844
  targetAlias: item.targetAlias,
4977
4845
  conversationId: context.conversationId,
4978
4846
  binding,
@@ -5065,13 +4933,12 @@ export class GatewayService {
5065
4933
  await this.store.observeRoute({
5066
4934
  binding,
5067
4935
  state: "idle",
5068
- compatibility: "compatible",
5069
4936
  });
5070
4937
  }
5071
4938
  else if (binding.provider === "codex") {
5072
4939
  this.scheduleHeldRedispatch(currentTargetAlias);
5073
4940
  }
5074
- await this.setNativeCodexStatus(currentTargetAlias, "waiting");
4941
+ await this.setNativeSourceStatus(currentTargetAlias, "waiting");
5075
4942
  }
5076
4943
  }
5077
4944
  else if (requeued.status === "settled") {
@@ -5282,13 +5149,12 @@ export class GatewayService {
5282
5149
  .then(() => true)
5283
5150
  .catch(() => false);
5284
5151
  const pairStillActive = conversation.pair !== true ||
5285
- (await this.store.hasPair({
5286
- claudeAlias: conversation.targetAlias,
5287
- codexAlias: conversation.sourceAlias,
5152
+ (await this.store.hasConsentEdge({
5153
+ aliases: [conversation.targetAlias, conversation.sourceAlias],
5288
5154
  }));
5289
5155
  if ((!sourceStillRoutable || !pairStillActive) &&
5290
- sourceBinding?.provider === "claude") {
5291
- await this.enqueueObservedClaudeReplyAfterRouteTeardownLocked(conversation, sourceBinding, replyText);
5156
+ sourceBinding?.provider === "claude" && context.sourceBinding !== undefined) {
5157
+ await this.enqueueObservedClaudeReplyAfterRouteTeardownLocked(conversation, sourceBinding, context.sourceBinding, replyText);
5292
5158
  }
5293
5159
  else {
5294
5160
  await this.enqueue(conversation.targetAlias, conversation.sourceAlias, replyText, false, {
@@ -5381,7 +5247,7 @@ export class GatewayService {
5381
5247
  };
5382
5248
  const collision = this.routeBindings.get(event.sourceAlias);
5383
5249
  if (target === undefined ||
5384
- target.provider !== "codex" ||
5250
+ target.provider === "claude" ||
5385
5251
  target.hostId !== event.endpoint.hostId ||
5386
5252
  (collision !== undefined &&
5387
5253
  bindingKey(collision) !== bindingKey(sourceBinding))) {
@@ -5423,6 +5289,7 @@ export class GatewayService {
5423
5289
  expectsReply: !steer,
5424
5290
  sequence: 0,
5425
5291
  targetBindingKey: bindingKey(target),
5292
+ sourceBinding: { ...sourceBinding },
5426
5293
  authorization: "selected_route",
5427
5294
  targetAlias: event.targetAlias,
5428
5295
  deadlineAt,
@@ -5448,7 +5315,7 @@ export class GatewayService {
5448
5315
  deadlineAt,
5449
5316
  });
5450
5317
  await this.changed();
5451
- await this.setNativeCodexStatus(event.targetAlias, "waiting");
5318
+ await this.setNativeSourceStatus(event.targetAlias, "waiting");
5452
5319
  // Native ingress gets one immediate dispatch opportunity. Only an
5453
5320
  // actual queued/waiting result earns a `held` acknowledgement; an idle
5454
5321
  // fast path can therefore settle with one terminal acknowledgement.
@@ -5518,7 +5385,7 @@ export class GatewayService {
5518
5385
  return activationDeferred;
5519
5386
  }
5520
5387
  finally {
5521
- if (!succeeded && event.outcome === "compatible") {
5388
+ if (!succeeded) {
5522
5389
  adapter.releaseEndpointRefreshSelectorClaim?.(event.current.endpointGeneration);
5523
5390
  }
5524
5391
  if (ownsActiveTransition &&
@@ -5537,56 +5404,29 @@ export class GatewayService {
5537
5404
  }
5538
5405
  }
5539
5406
  async applyCodexEndpointRefresh(adapter, event, transitionKey, options) {
5407
+ const routeHandles = Array.isArray(event.routes)
5408
+ ? event.routes.map((route) => route.routeHandle)
5409
+ : [];
5540
5410
  if (this.closing ||
5541
- (event.outcome !== "compatible" && event.outcome !== "incompatible") ||
5542
- !isCompatibilityAttestation(event.attestation) ||
5543
- event.attestation.surface !== "codex" ||
5544
5411
  event.previous.provider !== "codex" ||
5545
5412
  !PRIVATE_HANDLE.test(event.previous.endpointGeneration) ||
5546
5413
  adapter.identity.provider !== "codex" ||
5547
5414
  adapter.identity.hostId !== event.previous.hostId ||
5548
- !this.config.allowedHosts.includes(event.previous.hostId)) {
5415
+ !this.config.allowedHosts.includes(event.previous.hostId) ||
5416
+ event.current.provider !== "codex" ||
5417
+ event.current.hostId !== event.previous.hostId ||
5418
+ !PRIVATE_HANDLE.test(event.current.endpointGeneration) ||
5419
+ event.current.endpointGeneration === event.previous.endpointGeneration ||
5420
+ adapter.identity.endpointGeneration !== event.current.endpointGeneration ||
5421
+ !Array.isArray(event.routes) ||
5422
+ event.routes.length > this.config.limits.maxRoutes ||
5423
+ new Set(routeHandles).size !== routeHandles.length ||
5424
+ event.routes.some((route) => !PRIVATE_HANDLE.test(route.routeHandle) ||
5425
+ !["idle", "busy", "awaiting_approval"].includes(route.state))) {
5549
5426
  throw new BridgeError("CODEX_ENDPOINT_REFRESH_MISMATCH", "The Codex endpoint transition failed closed runtime validation.");
5550
5427
  }
5551
- if (event.outcome === "compatible") {
5552
- const routeHandles = Array.isArray(event.routes)
5553
- ? event.routes.map((route) => route.routeHandle)
5554
- : [];
5555
- if (event.current.provider !== "codex" ||
5556
- event.current.hostId !== event.previous.hostId ||
5557
- !PRIVATE_HANDLE.test(event.current.endpointGeneration) ||
5558
- event.current.endpointGeneration ===
5559
- event.previous.endpointGeneration ||
5560
- adapter.identity.endpointGeneration !==
5561
- event.current.endpointGeneration ||
5562
- event.attestation.version !== adapter.protocolVersion ||
5563
- event.attestation.tier === "incompatible" ||
5564
- !Array.isArray(event.routes) ||
5565
- event.routes.length > this.config.limits.maxRoutes ||
5566
- new Set(routeHandles).size !== routeHandles.length ||
5567
- event.routes.some((route) => !PRIVATE_HANDLE.test(route.routeHandle) ||
5568
- !["idle", "busy", "awaiting_approval"].includes(route.state))) {
5569
- throw new BridgeError("CODEX_ENDPOINT_REFRESH_MISMATCH", "The refreshed Codex provider identity changed before activation.");
5570
- }
5571
- if (this.activatedEndpointRefreshes.get(event.current.hostId) ===
5572
- transitionKey) {
5573
- return false;
5574
- }
5575
- }
5576
- else {
5577
- if (event.candidate.provider !== "codex" ||
5578
- event.candidate.hostId !== event.previous.hostId ||
5579
- !PRIVATE_HANDLE.test(event.candidate.endpointGeneration) ||
5580
- event.candidate.endpointGeneration ===
5581
- event.previous.endpointGeneration ||
5582
- adapter.identity.endpointGeneration !==
5583
- event.previous.endpointGeneration ||
5584
- event.attestation.tier !== "incompatible") {
5585
- throw new BridgeError("CODEX_ENDPOINT_REFRESH_MISMATCH", "The incompatible Codex candidate no longer matches the active endpoint.");
5586
- }
5587
- if (this.handledIncompatibleEndpointRefreshes.get(event.previous.hostId) === transitionKey) {
5588
- return false;
5589
- }
5428
+ if (this.activatedEndpointRefreshes.get(event.current.hostId) === transitionKey) {
5429
+ return false;
5590
5430
  }
5591
5431
  let inventory = await this.store.inspectPrivateCodexRoutes();
5592
5432
  const previousRoutes = inventory.filter((route) => route.binding.hostId === event.previous.hostId &&
@@ -5604,11 +5444,10 @@ export class GatewayService {
5604
5444
  settlements = await this.store.markConnectorOffline(event.previous, "ENDPOINT_GENERATION_CHANGED", inFlightSettlements, { preserveQueued: true });
5605
5445
  }
5606
5446
  catch (error) {
5607
- const alreadyInvalidatedCompatibleTransition = event.outcome === "compatible" &&
5608
- error instanceof BridgeError &&
5447
+ const alreadyInvalidatedTransition = error instanceof BridgeError &&
5609
5448
  error.code === "CONNECTOR_NOT_FOUND" &&
5610
- previousRoutes.every((route) => route.state === "stale" && route.compatibility === "expired");
5611
- if (!alreadyInvalidatedCompatibleTransition)
5449
+ previousRoutes.every((route) => route.state === "stale");
5450
+ if (!alreadyInvalidatedTransition)
5612
5451
  throw error;
5613
5452
  }
5614
5453
  for (const settlement of settlements) {
@@ -5617,45 +5456,9 @@ export class GatewayService {
5617
5456
  for (const route of previousRoutes) {
5618
5457
  this.routeStates.set(route.alias, "stale");
5619
5458
  }
5620
- await this.store.recordCompatibilityAttestation(event.attestation);
5621
- if (event.outcome === "incompatible") {
5622
- await this.requireEndpointRefreshUnconflicted();
5623
- this.activeCodexIncompatibility = structuredClone(event.attestation);
5624
- this.incompatibleProviderSurfaces.set(this.providerSurfaceKey("codex", event.previous.hostId), event.attestation.safeErrorCode ?? "CODEX_ENDPOINT_INCOMPATIBLE");
5625
- this.addRuntimeAlert(event.attestation.safeErrorCode ?? "CODEX_ENDPOINT_INCOMPATIBLE", "error", { provider: "codex", host: event.previous.hostId });
5626
- this.handledIncompatibleEndpointRefreshes.set(event.previous.hostId, transitionKey);
5627
- await this.changed();
5628
- return false;
5629
- }
5630
- if (event.attestation.tier === "schema_attested") {
5631
- // A passing untested-version schema is useful observation, but it is not
5632
- // durable route or write authority. Settle the provider's pending probe
5633
- // so a later generation can be examined, while leaving every G1 route
5634
- // stale and refusing selector/registration activation.
5635
- await this.requireEndpointRefreshUnconflicted();
5636
- await this.store.observeConnector({
5637
- identity: event.current,
5638
- health: "degraded",
5639
- compatibility: "unknown",
5640
- protocol: adapter.protocol,
5641
- protocolVersion: adapter.protocolVersion,
5642
- safeErrorCode: "CODEX_MONITOR_ONLY",
5643
- });
5644
- adapter.acceptCompatibilityAttestation(event.attestation);
5645
- this.activeCodexIncompatibility = undefined;
5646
- this.incompatibleProviderSurfaces.set(this.providerSurfaceKey("codex", event.current.hostId), "CODEX_MONITOR_ONLY");
5647
- this.handledIncompatibleEndpointRefreshes.delete(event.current.hostId);
5648
- await this.changed();
5649
- if (options.deferActivation === true ||
5650
- options.requiredRoute !== undefined) {
5651
- throw new BridgeError("CODEX_MONITOR_ONLY", "This Codex App Server passed read-only schema probes but cannot authorize a task route or message write.");
5652
- }
5653
- return false;
5654
- }
5655
5459
  await this.store.observeConnector({
5656
5460
  identity: event.current,
5657
5461
  health: "healthy",
5658
- compatibility: "compatible",
5659
5462
  protocol: adapter.protocol,
5660
5463
  protocolVersion: adapter.protocolVersion,
5661
5464
  });
@@ -5710,7 +5513,7 @@ export class GatewayService {
5710
5513
  route.binding.routeHandle === expected.threadId &&
5711
5514
  route.binding.ownerLease === expected.ownerLease &&
5712
5515
  route.enabled &&
5713
- route.compatibility === "compatible");
5516
+ route.state !== "stale");
5714
5517
  return matches.length === 1;
5715
5518
  });
5716
5519
  if (committedExactly) {
@@ -5743,8 +5546,7 @@ export class GatewayService {
5743
5546
  route.binding.hostId !== event.current.hostId ||
5744
5547
  route.binding.endpointGeneration !==
5745
5548
  event.current.endpointGeneration ||
5746
- route.state !== "stale" ||
5747
- route.compatibility !== "expired") {
5549
+ route.state !== "stale") {
5748
5550
  continue;
5749
5551
  }
5750
5552
  await this.registerOrRebind(route.alias, route.binding, "endpoint_reobserved", state, route.binding.ownerLease);
@@ -5759,7 +5561,7 @@ export class GatewayService {
5759
5561
  event.current.endpointGeneration &&
5760
5562
  route.binding.routeHandle === observed.routeHandle &&
5761
5563
  route.enabled &&
5762
- route.compatibility === "compatible");
5564
+ route.state !== "stale");
5763
5565
  if (matches.length > 1) {
5764
5566
  throw new BridgeError("CODEX_ENDPOINT_REFRESH_MISMATCH", "A refreshed Codex task has multiple durable owners.");
5765
5567
  }
@@ -5799,7 +5601,7 @@ export class GatewayService {
5799
5601
  event.current.endpointGeneration &&
5800
5602
  route.binding.routeHandle === requiredRoute.threadId &&
5801
5603
  route.enabled &&
5802
- route.compatibility === "compatible");
5604
+ route.state !== "stale");
5803
5605
  const match = matches[0];
5804
5606
  if (matches.length !== 1 || match === undefined) {
5805
5607
  throw new BridgeError("CODEX_ENDPOINT_REFRESH_MISMATCH", "The registering Codex task was not durably installed exactly.");
@@ -5853,7 +5655,7 @@ export class GatewayService {
5853
5655
  }
5854
5656
  for (const route of activatedRoutes) {
5855
5657
  requireNativeContinuity(route);
5856
- await this.setNativeCodexStatus(route.alias, route.state === "idle"
5658
+ await this.setNativeSourceStatus(route.alias, route.state === "idle"
5857
5659
  ? "idle"
5858
5660
  : route.state === "awaiting_approval"
5859
5661
  ? "waiting"
@@ -5893,10 +5695,7 @@ export class GatewayService {
5893
5695
  for (const route of activatedRoutes) {
5894
5696
  requireNativeContinuity(route);
5895
5697
  }
5896
- // Provider writes remain closed until every durable and native transition
5897
- // above is complete. This acknowledgement is deliberately the final
5898
- // fallible activation step.
5899
- adapter.acceptCompatibilityAttestation(event.attestation);
5698
+ adapter.activateEndpointGeneration(event.current.endpointGeneration);
5900
5699
  }
5901
5700
  catch (error) {
5902
5701
  try {
@@ -5916,9 +5715,6 @@ export class GatewayService {
5916
5715
  ?.transitionKey === transitionKey) {
5917
5716
  this.pendingSelectorEndpointActivations.delete(event.current.hostId);
5918
5717
  }
5919
- this.handledIncompatibleEndpointRefreshes.delete(event.current.hostId);
5920
- this.activeCodexIncompatibility = undefined;
5921
- this.incompatibleProviderSurfaces.delete(this.providerSurfaceKey("codex", event.current.hostId));
5922
5718
  return false;
5923
5719
  }
5924
5720
  async onRouteState(source, event) {
@@ -5940,7 +5736,6 @@ export class GatewayService {
5940
5736
  await this.store.observeConnector({
5941
5737
  identity: source,
5942
5738
  health: event.state === "stale" ? "degraded" : "healthy",
5943
- compatibility: event.state === "stale" ? "expired" : "compatible",
5944
5739
  protocol: adapter.protocol,
5945
5740
  protocolVersion: adapter.protocolVersion,
5946
5741
  ...(event.safeErrorCode === undefined
@@ -5956,7 +5751,6 @@ export class GatewayService {
5956
5751
  await this.store.observeRoute({
5957
5752
  binding,
5958
5753
  state: "stale",
5959
- compatibility: "expired",
5960
5754
  safeErrorCode: staleSafeCode,
5961
5755
  });
5962
5756
  }
@@ -5964,7 +5758,6 @@ export class GatewayService {
5964
5758
  await this.store.observeRoute({
5965
5759
  binding,
5966
5760
  state: event.state,
5967
- compatibility: "compatible",
5968
5761
  ...(event.safeErrorCode === undefined
5969
5762
  ? {}
5970
5763
  : {
@@ -5974,15 +5767,15 @@ export class GatewayService {
5974
5767
  }
5975
5768
  await this.store.touchProgressWatchesForAlias(alias);
5976
5769
  await this.changed();
5977
- if (binding.provider === "codex") {
5978
- await this.setNativeCodexStatus(alias, event.state === "idle"
5770
+ if (binding.provider !== "claude") {
5771
+ await this.setNativeSourceStatus(alias, event.state === "idle"
5979
5772
  ? "idle"
5980
5773
  : event.state === "awaiting_approval"
5981
5774
  ? "waiting"
5982
5775
  : "busy");
5983
- if (previousState === "stale" && event.state !== "stale") {
5984
- adapter.rearmEndpointRefreshActivation?.(binding.endpointGeneration);
5985
- }
5776
+ }
5777
+ if (binding.provider === "codex" && previousState === "stale" && event.state !== "stale") {
5778
+ adapter.rearmEndpointRefreshActivation?.(binding.endpointGeneration);
5986
5779
  }
5987
5780
  if (event.state === "idle" || event.state === "stale") {
5988
5781
  const heldTimer = this.heldRedispatchTimers.get(alias);
@@ -5993,12 +5786,12 @@ export class GatewayService {
5993
5786
  this.scheduleDispatch(alias);
5994
5787
  }
5995
5788
  }
5996
- async setNativeCodexStatus(alias, status, requireSuccess = false) {
5789
+ async setNativeSourceStatus(alias, status, requireSuccess = false) {
5997
5790
  const binding = this.routeBindings.get(alias);
5998
- if (binding?.provider !== "codex")
5791
+ if (binding === undefined || binding.provider === "claude")
5999
5792
  return;
6000
5793
  const adapter = this.adapter("claude", binding.hostId);
6001
- const update = adapter.updateNativeCodexPeerStatus;
5794
+ const update = adapter.updateNativeSourcePeerStatus;
6002
5795
  if (update === undefined) {
6003
5796
  if (requireSuccess) {
6004
5797
  throw new BridgeError("CODEX_ENDPOINT_REFRESH_NATIVE_STATUS_FAILED", "The native listener does not support refreshed Codex status activation.", true);
@@ -6097,30 +5890,6 @@ export class GatewayService {
6097
5890
  }
6098
5891
  async publicSnapshotLocked() {
6099
5892
  const base = await this.store.publicSnapshot();
6100
- const compatibilityChecks = [];
6101
- for (const { surface } of this.compatibilitySurfaceDefinitions) {
6102
- if (surface === "codex" && this.activeCodexIncompatibility !== undefined) {
6103
- compatibilityChecks.push(structuredClone(this.activeCodexIncompatibility));
6104
- continue;
6105
- }
6106
- const currentVersions = [
6107
- ...new Set([...this.adapters, ...this.compatibilityObservers].flatMap((observer) => {
6108
- const observation = observer.compatibilitySurface?.();
6109
- return observation?.surface === surface ? [observation.version] : [];
6110
- })),
6111
- ].sort((left, right) => left.localeCompare(right));
6112
- const currentAttestations = (await Promise.all(currentVersions.map(async (version) => await this.store.inspectCompatibilityAttestation(surface, version))))
6113
- .filter((attestation) => attestation !== undefined)
6114
- .sort((left, right) => {
6115
- const checkedAt = right.checkedAt.localeCompare(left.checkedAt);
6116
- if (checkedAt !== 0)
6117
- return checkedAt;
6118
- return left.version.localeCompare(right.version);
6119
- });
6120
- const selected = currentAttestations[0];
6121
- if (selected !== undefined)
6122
- compatibilityChecks.push(selected);
6123
- }
6124
5893
  const peers = this.availablePeers.map((peer) => ({ ...peer }));
6125
5894
  if (!arePublicAvailablePeerSnapshots(peers)) {
6126
5895
  throw new BridgeError("INVALID_TRANSIENT_INVENTORY", "The transient peer inventory is unsafe.");
@@ -6149,11 +5918,6 @@ export class GatewayService {
6149
5918
  return projectGatewayPublicSnapshot({
6150
5919
  ...base,
6151
5920
  connectors: this.connectorsWithRegistry(base.connectors),
6152
- ...(compatibilityChecks.length === 0
6153
- ? {}
6154
- : {
6155
- compatibilityChecks: compatibilityChecks.map(projectPublicCompatibilityCheck),
6156
- }),
6157
5921
  availablePeers: peers,
6158
5922
  activityEvents: this.activityEvents.map((event) => ({
6159
5923
  ...event,