sneakoscope 8.1.2 → 8.2.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 (261) hide show
  1. package/README.md +96 -58
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +5 -51
  5. package/dist/cli/command-manifest-lite.js +2 -1
  6. package/dist/cli/command-registry.js +2 -1
  7. package/dist/cli/global-mode-router.js +1 -1
  8. package/dist/cli/install-helpers-codex-lb-config.js +112 -914
  9. package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
  10. package/dist/cli/install-helpers-install-support.js +4 -20
  11. package/dist/cli/install-helpers.js +36 -2716
  12. package/dist/cli/router.js +9 -9
  13. package/dist/commands/bridge-command-output.js +111 -0
  14. package/dist/commands/bridge.js +320 -0
  15. package/dist/commands/codex-app.js +39 -123
  16. package/dist/commands/doctor-helpers.js +380 -0
  17. package/dist/commands/doctor-profile.js +3 -0
  18. package/dist/commands/doctor.js +114 -873
  19. package/dist/commands/mad-sks.js +0 -4
  20. package/dist/config/skills-manifest.json +1 -1
  21. package/dist/core/agents/agent-effort-policy.js +11 -21
  22. package/dist/core/agents/agent-recursion-guard.js +26 -0
  23. package/dist/core/agents/agent-runner-codex-exec.js +7 -9
  24. package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
  25. package/dist/core/architecture-hardening/state/state-service.js +49 -13
  26. package/dist/core/auto-review.js +15 -9
  27. package/dist/core/codex/codex-config-guard.js +8 -0
  28. package/dist/core/codex-adapter.js +8 -10
  29. package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
  30. package/dist/core/codex-app/codex-app-launcher.js +10 -12
  31. package/dist/core/codex-app/codex-app-restart.js +10 -12
  32. package/dist/core/codex-app/menubar/constants.js +2 -5
  33. package/dist/core/codex-app/menubar/global-install.js +3 -2
  34. package/dist/core/codex-app/menubar/installer/result.js +23 -0
  35. package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
  36. package/dist/core/codex-app/menubar/installer.js +5 -96
  37. package/dist/core/codex-app/menubar/migration.js +1 -42
  38. package/dist/core/codex-app/openrouter-provider.js +0 -78
  39. package/dist/core/codex-app.js +97 -360
  40. package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
  41. package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
  42. package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
  43. package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
  44. package/dist/core/codex-control/codex-task-runner.js +16 -60
  45. package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
  46. package/dist/core/codex-exec-output-schema.js +11 -13
  47. package/dist/core/codex-lb/bridge-contracts.js +2 -0
  48. package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
  49. package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
  50. package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
  51. package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
  52. package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
  53. package/dist/core/codex-lb/capability-runner.js +505 -201
  54. package/dist/core/codex-lb/codex-lb-env.js +179 -12
  55. package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
  56. package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
  57. package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
  58. package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
  59. package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
  60. package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
  61. package/dist/core/codex-lb/combined-catalog.js +12 -0
  62. package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
  63. package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
  64. package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
  65. package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
  66. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
  67. package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
  68. package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
  69. package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
  70. package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
  71. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
  72. package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
  73. package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
  74. package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
  75. package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
  76. package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
  77. package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
  78. package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
  79. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
  80. package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
  81. package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
  82. package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
  83. package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
  84. package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
  85. package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
  86. package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
  87. package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
  88. package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
  89. package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
  90. package/dist/core/codex-lb/desktop-controller.js +2 -1730
  91. package/dist/core/codex-lb/desktop-service.js +462 -627
  92. package/dist/core/codex-lb/migration-receipt.js +560 -118
  93. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
  94. package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
  95. package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
  96. package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
  97. package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
  98. package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
  99. package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
  100. package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
  101. package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
  102. package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
  103. package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
  104. package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
  105. package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
  106. package/dist/core/codex-lb/provider-credentials/types.js +1 -0
  107. package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
  108. package/dist/core/codex-lb/provider-credentials.js +5 -0
  109. package/dist/core/codex-lb/provider-registry.js +323 -0
  110. package/dist/core/codex-lb/provider-route-policy.js +118 -0
  111. package/dist/core/codex-lb/request-route-resolver.js +172 -0
  112. package/dist/core/codex-lb/route-index.js +148 -0
  113. package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
  114. package/dist/core/commands/basic-cli.js +1 -1
  115. package/dist/core/commands/check-command.js +3 -10
  116. package/dist/core/commands/gate-result-contract.js +10 -14
  117. package/dist/core/commands/intent-normalization/normalizer.js +1 -1
  118. package/dist/core/commands/mad-sks-command.js +2 -6
  119. package/dist/core/commands/release-command.js +11 -1
  120. package/dist/core/commands/telegram-command.js +46 -6
  121. package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
  122. package/dist/core/doctor/skill-legacy-surface.js +5 -5
  123. package/dist/core/evidence/v2/evidence-key.js +30 -3
  124. package/dist/core/feature-fixtures.js +8 -1
  125. package/dist/core/feature-registry.js +3 -2
  126. package/dist/core/hooks-runtime/stop-finalization.js +11 -1
  127. package/dist/core/hooks-runtime/subagent-context.js +15 -1
  128. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
  129. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  130. package/dist/core/hooks-runtime.js +73 -87
  131. package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
  132. package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
  133. package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
  134. package/dist/core/imagegen/imagegen-capability.js +43 -151
  135. package/dist/core/init/skills/filesystem.js +89 -0
  136. package/dist/core/init/skills/inventory.js +97 -0
  137. package/dist/core/init/skills/manifest.js +151 -0
  138. package/dist/core/init/skills.js +5 -325
  139. package/dist/core/init.js +0 -63
  140. package/dist/core/install/installed-package-smoke.js +1 -1
  141. package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
  142. package/dist/core/policy/latest-version-guidance.js +15 -2
  143. package/dist/core/preflight/parallel-preflight-engine.js +27 -51
  144. package/dist/core/provider/provider-badge.js +9 -4
  145. package/dist/core/provider/provider-context.js +57 -107
  146. package/dist/core/providers/openrouter/openrouter-account.js +3 -1
  147. package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
  148. package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
  149. package/dist/core/release/gate-manifest.js +0 -1
  150. package/dist/core/release/main-push-guard.js +13 -0
  151. package/dist/core/release/main-push-receipt.js +11 -0
  152. package/dist/core/release/physical-release-gates.js +664 -61
  153. package/dist/core/release/publish-preflight.js +3 -3
  154. package/dist/core/release/release-gate-batch-runner.js +19 -6
  155. package/dist/core/release/release-gate-dag.js +33 -6
  156. package/dist/core/release/release-gate-node.js +1 -3
  157. package/dist/core/release/release-gate-output-contract.js +55 -0
  158. package/dist/core/release/release-pack-contract.js +1 -1
  159. package/dist/core/release/release-pack-receipt.js +209 -8
  160. package/dist/core/release/release-real-contract.js +1 -1
  161. package/dist/core/release/stage-publish.js +106 -28
  162. package/dist/core/retention/temp-lease.js +204 -0
  163. package/dist/core/retention.js +18 -195
  164. package/dist/core/routes.js +1 -2
  165. package/dist/core/safety/intent-contract/intent-contract.js +3 -3
  166. package/dist/core/subagents/naruto-host-credentials.js +6 -1
  167. package/dist/core/subagents/official-subagent-config.js +27 -9
  168. package/dist/core/subagents/official-subagent-runner.js +14 -31
  169. package/dist/core/subagents/wave-lifecycle.js +36 -8
  170. package/dist/core/subagents/wave-parent-guidance.js +2 -1
  171. package/dist/core/telegram/doctor.js +2 -2
  172. package/dist/core/telegram/liveness.js +10 -4
  173. package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
  174. package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
  175. package/dist/core/update/update-migration-state/session-state-split.js +247 -0
  176. package/dist/core/update/update-migration-state/simple-stages.js +46 -0
  177. package/dist/core/update/update-migration-state.js +4 -481
  178. package/dist/core/version.js +1 -1
  179. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
  180. package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
  181. package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
  182. package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
  183. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
  184. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
  185. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
  186. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
  187. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
  188. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
  189. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
  190. package/dist/scripts/canonical-test-runner.js +7 -1
  191. package/dist/scripts/check-runtime-schemas.js +7 -2
  192. package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
  193. package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
  194. package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
  195. package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
  196. package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
  197. package/dist/scripts/desktop-bridge-transport-client.js +116 -0
  198. package/dist/scripts/desktop-bridge-unification-check.js +276 -0
  199. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
  200. package/dist/scripts/gate-policy-audit-check.js +52 -2
  201. package/dist/scripts/provider-badge-context-check.js +55 -12
  202. package/dist/scripts/publish-preflight.js +1 -2
  203. package/dist/scripts/release-affected-selector-check.js +1 -2
  204. package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
  205. package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
  206. package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
  207. package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
  208. package/dist/scripts/release-gate-batch-runner-check.js +9 -0
  209. package/dist/scripts/release-gate-dag-runner-check.js +6 -0
  210. package/dist/scripts/release-gate-dag-runner.js +4 -2
  211. package/dist/scripts/release-metadata-check.js +16 -3
  212. package/dist/scripts/release-pack-receipt.js +29 -6
  213. package/dist/scripts/release-physical-gates-check.js +39 -0
  214. package/dist/scripts/release-real-check.js +7 -5
  215. package/package.json +6 -8
  216. package/release-gates.v2.json +156 -157
  217. package/runtime-required-scripts.json +11 -11
  218. package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
  219. package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
  220. package/schemas/release/release-gate-node.schema.json +2 -3
  221. package/dist/cli/codex-lb-setup-warning-output.js +0 -17
  222. package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
  223. package/dist/commands/codex-lb.js +0 -1232
  224. package/dist/core/architecture-hardening/migration/migration.js +0 -111
  225. package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
  226. package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
  227. package/dist/core/codex-app/child-policy/child-policy.js +0 -35
  228. package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
  229. package/dist/core/codex-app/glm-model-profile.js +0 -1
  230. package/dist/core/codex-app/glm-profile-installer.js +0 -191
  231. package/dist/core/codex-app/glm-profile-schema.js +0 -42
  232. package/dist/core/codex-app/multi-provider-router.js +0 -391
  233. package/dist/core/codex-app/openrouter-activate.js +0 -405
  234. package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
  235. package/dist/core/codex-app/provider-child-policy.js +0 -64
  236. package/dist/core/codex-app/provider-mode.js +0 -91
  237. package/dist/core/codex-app/provider-session-policy.js +0 -85
  238. package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
  239. package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
  240. package/dist/core/codex-lb/codex-lb-setup.js +0 -293
  241. package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
  242. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
  243. package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
  244. package/dist/core/codex-lb/desktop-mode.js +0 -32
  245. package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
  246. package/dist/core/codex-lb/legacy-migration.js +0 -576
  247. package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
  248. package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
  249. package/dist/core/codex-lb/routing-truth.js +0 -327
  250. package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
  251. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
  252. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
  253. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
  254. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
  255. package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
  256. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
  257. package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
  258. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
  259. package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
  260. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
  261. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
@@ -2,14 +2,21 @@
2
2
  import { createHash } from 'node:crypto';
3
3
  import fs from 'node:fs/promises';
4
4
  import http, {} from 'node:http';
5
- import net, {} from 'node:net';
6
5
  import os from 'node:os';
7
6
  import path from 'node:path';
8
- import { DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES, desktopBridgeStatePath, selectAvailableDesktopBridgePort, startDesktopBridge, stopDesktopBridge } from '../core/codex-lb/desktop-bridge/index.js';
7
+ import { DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES, desktopBridgeClientPath, desktopBridgeStatePath, selectAvailableDesktopBridgePort, startDesktopBridge, stopDesktopBridge } from '../core/codex-lb/desktop-bridge/index.js';
8
+ import { closeServer, listen, request, websocketRoundTrip } from './desktop-bridge-transport-client.js';
9
9
  import { assertGate, emitGate } from './gate-lib.js';
10
- const gatewayKey = 'desktop-bridge-gateway-secret';
10
+ const providerSecret = 'desktop-bridge-provider-secret';
11
+ const publicModel = 'desktop-bridge-check-model';
12
+ const catalogGeneration = 'desktop-bridge-check-catalog';
13
+ const policyGeneration = 'desktop-bridge-check-policy';
14
+ const credentialGeneration = 'desktop-bridge-check-credential';
15
+ const credentialFingerprint = 'desktop-bridge-check-fingerprint';
11
16
  const desktopAuthorization = 'Bearer desktop-oauth-secret';
12
17
  const desktopCookie = 'desktop=session-secret';
18
+ const clientCapability = Buffer.alloc(32, 0x48).toString('base64url');
19
+ const clientCapabilitySha256 = createHash('sha256').update(clientCapability).digest('hex');
13
20
  const upstreamObservations = {};
14
21
  let sseRequestBody = Buffer.alloc(0);
15
22
  let multipartRequestBody = Buffer.alloc(0);
@@ -51,7 +58,7 @@ const upstream = http.createServer((request, response) => {
51
58
  });
52
59
  return;
53
60
  }
54
- if (request.url === '/v1/responses') {
61
+ if (request.url === '/backend-api/codex/responses') {
55
62
  upstreamObservations.http = request.headers;
56
63
  request.resume();
57
64
  request.once('end', () => {
@@ -61,7 +68,7 @@ const upstream = http.createServer((request, response) => {
61
68
  'set-cookie': 'remote=session-secret',
62
69
  'x-codex-lb-api-key': 'response-secret'
63
70
  });
64
- response.end('{"transport":"compat"}');
71
+ response.end('{"transport":"authorization-bearer"}');
65
72
  });
66
73
  return;
67
74
  }
@@ -101,11 +108,11 @@ upstream.on('upgrade', (request, socket, head) => {
101
108
  socket.on('data', consume);
102
109
  });
103
110
  const upstreamPort = await listen(upstream);
104
- const temporaryRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-lb-desktop-bridge-gate-'));
111
+ const temporaryRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-desktop-bridge-gate-'));
105
112
  const home = path.join(temporaryRoot, 'home');
106
113
  await fs.mkdir(path.join(home, '.codex'), { recursive: true });
107
114
  let preferredBridge = null;
108
- let compatBridge = null;
115
+ let bearerBridge = null;
109
116
  let preferredPort = 0;
110
117
  let stateSecretSafe = false;
111
118
  let stateRemovedOnStop = false;
@@ -119,18 +126,19 @@ try {
119
126
  const statePath = desktopBridgeStatePath(home);
120
127
  preferredBridge = await startDesktopBridge(bridgeConfig(preferredPort, upstreamPort, 'x-codex-lb-api-key'), { statePath });
121
128
  const stateText = await fs.readFile(statePath, 'utf8');
122
- stateSecretSafe = !stateText.includes(gatewayKey)
129
+ stateSecretSafe = !stateText.includes(providerSecret)
123
130
  && !stateText.includes(desktopAuthorization)
124
- && !stateText.includes(desktopCookie);
131
+ && !stateText.includes(desktopCookie)
132
+ && !stateText.includes(clientCapability);
125
133
  sseResult = await request({
126
134
  port: preferredPort,
127
- path: '/backend-api/codex/responses?stream=1',
135
+ path: desktopBridgeClientPath(clientCapability, '/backend-api/codex/responses?stream=1'),
128
136
  method: 'POST',
129
137
  headers: clientHeaders({
130
138
  'content-type': 'application/json',
131
139
  origin: 'app://codex'
132
140
  }),
133
- chunks: [Buffer.from('{"stream":true}')],
141
+ chunks: [Buffer.from(JSON.stringify({ model: publicModel, stream: true }))],
134
142
  onData: () => {
135
143
  if (!sseEnded)
136
144
  firstSseChunkBeforeEnd = true;
@@ -143,7 +151,7 @@ try {
143
151
  ]);
144
152
  multipartResult = await request({
145
153
  port: preferredPort,
146
- path: '/backend-api/files',
154
+ path: desktopBridgeClientPath(clientCapability, '/backend-api/files'),
147
155
  method: 'POST',
148
156
  headers: clientHeaders({
149
157
  'content-type': 'multipart/form-data; boundary=boundary',
@@ -155,29 +163,37 @@ try {
155
163
  multipartPayload.subarray(77_777)
156
164
  ]
157
165
  });
158
- webSocketResult = await websocketRoundTrip(preferredPort);
166
+ webSocketResult = await websocketRoundTrip({
167
+ port: preferredPort,
168
+ clientCapability,
169
+ publicModel,
170
+ desktopAuthorization,
171
+ desktopCookie,
172
+ maskedClientFrame,
173
+ expectedResponseFrameBytes: serverBinaryFrame.length + serverCloseFrame.length
174
+ });
159
175
  await stopDesktopBridge(preferredBridge);
160
176
  preferredBridge = null;
161
177
  stateRemovedOnStop = await fs.access(statePath).then(() => false, () => true);
162
- const compatPort = await selectAvailableDesktopBridgePort('127.0.0.1');
163
- compatBridge = await startDesktopBridge(bridgeConfig(compatPort, upstreamPort, 'authorization-bearer-compat'), { writeState: false });
178
+ const bearerPort = await selectAvailableDesktopBridgePort('127.0.0.1');
179
+ bearerBridge = await startDesktopBridge(bridgeConfig(bearerPort, upstreamPort, 'authorization-bearer'), { writeState: false });
164
180
  httpResult = await request({
165
- port: compatPort,
166
- path: '/v1/responses',
181
+ port: bearerPort,
182
+ path: desktopBridgeClientPath(clientCapability, '/backend-api/codex/responses'),
167
183
  method: 'POST',
168
184
  headers: clientHeaders({
169
185
  'content-type': 'application/json',
170
186
  origin: 'app://codex'
171
187
  }),
172
- chunks: [Buffer.from('{"input":"hello"}')]
188
+ chunks: [Buffer.from(JSON.stringify({ model: publicModel, input: 'hello' }))]
173
189
  });
174
190
  }
175
191
  finally {
176
192
  if (preferredBridge)
177
193
  await stopDesktopBridge(preferredBridge).catch(() => undefined);
178
- if (compatBridge)
179
- await stopDesktopBridge(compatBridge).catch(() => undefined);
180
- await close(upstream).catch(() => undefined);
194
+ if (bearerBridge)
195
+ await stopDesktopBridge(bearerBridge).catch(() => undefined);
196
+ await closeServer(upstream).catch(() => undefined);
181
197
  await fs.rm(temporaryRoot, { recursive: true, force: true });
182
198
  }
183
199
  const sseHeaders = upstreamObservations.sse || {};
@@ -187,8 +203,8 @@ const websocketHeaders = upstreamObservations.websocket || {};
187
203
  const sseVerified = sseResult?.status === 200
188
204
  && sseResult.body.toString('utf8') === 'data: first\n\ndata: second\n\n'
189
205
  && firstSseChunkBeforeEnd
190
- && sseRequestBody.toString('utf8') === '{"stream":true}'
191
- && sseResult.headers.location === `ws://127.0.0.1:${preferredPort}/backend-api/codex/call-1?token=opaque`;
206
+ && sseRequestBody.toString('utf8') === JSON.stringify({ model: publicModel, stream: true })
207
+ && sseResult.headers.location === `ws://127.0.0.1:${preferredPort}${desktopBridgeClientPath(clientCapability, '/backend-api/codex/call-1?token=opaque')}`;
192
208
  const multipartVerified = multipartResult?.status === 200
193
209
  && multipartResult.body.toString('utf8') === '{"ok":true}'
194
210
  && createHash('sha256').update(multipartRequestBody).digest('hex') === multipartResult.requestBodySha256;
@@ -198,18 +214,18 @@ const webSocketVerified = Boolean(webSocketResult
198
214
  && !/Set-Cookie|X-Codex-LB-Api-Key/i.test(webSocketResult.responseHead)
199
215
  && webSocketResult.frames.equals(Buffer.concat([serverBinaryFrame, serverCloseFrame]))
200
216
  && receivedClientFrame.subarray(0, maskedClientFrame.length).equals(maskedClientFrame));
201
- const preferredAuthVerified = sseHeaders['x-codex-lb-api-key'] === gatewayKey
217
+ const preferredAuthVerified = sseHeaders['x-codex-lb-api-key'] === providerSecret
202
218
  && sseHeaders.authorization === undefined
203
219
  && sseHeaders.cookie === undefined
204
- && multipartHeaders['x-codex-lb-api-key'] === gatewayKey
220
+ && multipartHeaders['x-codex-lb-api-key'] === providerSecret
205
221
  && multipartHeaders.authorization === undefined
206
222
  && multipartHeaders.cookie === undefined
207
- && websocketHeaders['x-codex-lb-api-key'] === gatewayKey
223
+ && websocketHeaders['x-codex-lb-api-key'] === providerSecret
208
224
  && websocketHeaders.authorization === undefined
209
225
  && websocketHeaders.cookie === undefined;
210
- const compatAuthVerified = httpResult?.status === 200
211
- && httpResult.body.toString('utf8') === '{"transport":"compat"}'
212
- && httpHeaders.authorization === `Bearer ${gatewayKey}`
226
+ const bearerAuthVerified = httpResult?.status === 200
227
+ && httpResult.body.toString('utf8') === '{"transport":"authorization-bearer"}'
228
+ && httpHeaders.authorization === `Bearer ${providerSecret}`
213
229
  && httpHeaders['x-codex-lb-api-key'] === undefined
214
230
  && httpHeaders.cookie === undefined;
215
231
  const responseHeadersRedacted = [sseResult, multipartResult, httpResult].every((result) => (result !== null
@@ -217,21 +233,21 @@ const responseHeadersRedacted = [sseResult, multipartResult, httpResult].every((
217
233
  && result.headers['set-cookie'] === undefined
218
234
  && result.headers['x-codex-lb-api-key'] === undefined));
219
235
  const report = {
220
- schema: 'sks.codex-lb-desktop-bridge-check.v1',
236
+ schema: 'sks.desktop-bridge-transport-check.v1',
221
237
  ok: sseVerified
222
238
  && multipartVerified
223
239
  && webSocketVerified
224
240
  && preferredAuthVerified
225
- && compatAuthVerified
241
+ && bearerAuthVerified
226
242
  && responseHeadersRedacted
227
243
  && stateSecretSafe
228
244
  && stateRemovedOnStop,
229
- http: compatAuthVerified,
245
+ http: bearerAuthVerified,
230
246
  sse: sseVerified,
231
247
  multipart: multipartVerified,
232
248
  websocket: webSocketVerified,
233
- preferred_gateway_auth_transport: preferredAuthVerified,
234
- explicit_legacy_gateway_auth_transport: compatAuthVerified,
249
+ x_codex_lb_api_key_transport: preferredAuthVerified,
250
+ authorization_bearer_transport: bearerAuthVerified,
235
251
  response_headers_redacted: responseHeadersRedacted,
236
252
  public_state_secret_safe: stateSecretSafe,
237
253
  public_state_removed_on_stop: stateRemovedOnStop,
@@ -240,32 +256,64 @@ const report = {
240
256
  ...(multipartVerified ? [] : ['desktop_bridge_multipart_round_trip_failed']),
241
257
  ...(webSocketVerified ? [] : ['desktop_bridge_websocket_round_trip_failed']),
242
258
  ...(preferredAuthVerified ? [] : ['desktop_bridge_preferred_auth_transport_failed']),
243
- ...(compatAuthVerified ? [] : ['desktop_bridge_compat_auth_transport_failed']),
259
+ ...(bearerAuthVerified ? [] : ['desktop_bridge_authorization_bearer_transport_failed']),
244
260
  ...(responseHeadersRedacted ? [] : ['desktop_bridge_response_secret_header_leaked']),
245
261
  ...(stateSecretSafe ? [] : ['desktop_bridge_public_state_contains_secret']),
246
262
  ...(stateRemovedOnStop ? [] : ['desktop_bridge_state_not_removed_on_stop'])
247
263
  ]
248
264
  };
249
- assertGate(report.ok, 'codex-lb Desktop bridge gate failed', report);
250
- emitGate('codex-lb:desktop-bridge', {
265
+ assertGate(report.ok, 'Desktop Bridge transport gate failed', report);
266
+ emitGate('desktop-bridge:transport', {
251
267
  http: report.http,
252
268
  sse: report.sse,
253
269
  multipart: report.multipart,
254
270
  websocket: report.websocket,
255
- gateway_auth_transports: [
271
+ provider_auth_transports: [
256
272
  'x-codex-lb-api-key',
257
- 'authorization-bearer-compat'
273
+ 'authorization-bearer'
258
274
  ],
259
275
  response_headers_redacted: report.response_headers_redacted,
260
276
  public_state_secret_safe: report.public_state_secret_safe
261
277
  });
262
- function bridgeConfig(listenPort, remotePort, gatewayAuthTransport) {
278
+ function bridgeConfig(listenPort, remotePort, authTransport) {
279
+ const baseUrl = `http://127.0.0.1:${remotePort}/backend-api/codex`;
263
280
  return {
264
281
  listenHost: '127.0.0.1',
265
282
  listenPort,
266
- remoteBaseUrl: `http://127.0.0.1:${remotePort}/backend-api/codex`,
267
- gatewayKey,
268
- gatewayAuthTransport,
283
+ providerRegistry: {
284
+ schema: 'sks.desktop-bridge-provider-registry.v1',
285
+ generation: 'desktop-bridge-check-registry',
286
+ created_at: '2026-08-05T00:00:00.000Z',
287
+ providers: {
288
+ 'codex-lb': {
289
+ provider_id: 'codex-lb', enabled: true, base_url: baseUrl,
290
+ allowed_origins: [new URL(baseUrl).origin], auth_transport: authTransport,
291
+ credential_state: 'ready', credential_fingerprint: credentialFingerprint,
292
+ credential_generation: credentialGeneration, source_catalog_generation: catalogGeneration
293
+ },
294
+ openrouter: {
295
+ provider_id: 'openrouter', enabled: false, base_url: 'https://openrouter.ai/api/v1',
296
+ allowed_origins: ['https://openrouter.ai'], auth_transport: 'openrouter-bearer',
297
+ credential_state: 'not_configured', credential_fingerprint: null,
298
+ credential_generation: 'desktop-bridge-check-openrouter-credential', source_catalog_generation: null
299
+ }
300
+ }
301
+ },
302
+ routePolicy: {
303
+ schema: 'sks.bridge-routing-policy.v1', default_provider_id: 'codex-lb', fallback: 'none',
304
+ model_routes: { [publicModel]: { provider_id: 'codex-lb', upstream_model: publicModel } },
305
+ catalog_generation: catalogGeneration, policy_generation: policyGeneration,
306
+ changed_at: '2026-08-05T00:00:00.000Z'
307
+ },
308
+ providerSessionPins: [],
309
+ resolveProviderCredential: async (providerId, expectedGeneration) => ({
310
+ provider_id: providerId,
311
+ value: providerId === 'codex-lb' ? providerSecret : 'unused-openrouter-secret',
312
+ source: 'release-check',
313
+ fingerprint: providerId === 'codex-lb' ? credentialFingerprint : 'unused-openrouter-fingerprint',
314
+ generation: expectedGeneration
315
+ }),
316
+ clientCapabilitySha256,
269
317
  allowedPathPrefixes: DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES,
270
318
  allowedOrigins: ['app://codex'],
271
319
  connectTimeoutMs: 2_000,
@@ -277,118 +325,7 @@ function clientHeaders(additional = {}) {
277
325
  authorization: desktopAuthorization,
278
326
  cookie: desktopCookie,
279
327
  'x-codex-lb-api-key': 'client-forged-key',
328
+ 'x-sks-model': publicModel,
280
329
  ...additional
281
330
  };
282
331
  }
283
- async function listen(server) {
284
- await new Promise((resolve, reject) => {
285
- server.once('error', reject);
286
- server.listen(0, '127.0.0.1', resolve);
287
- });
288
- return server.address().port;
289
- }
290
- async function close(server) {
291
- if (!server.listening)
292
- return;
293
- await new Promise((resolve, reject) => {
294
- server.close((error) => error ? reject(error) : resolve());
295
- });
296
- }
297
- async function request(input) {
298
- const requestBody = Buffer.concat([...(input.chunks || [])]);
299
- return new Promise((resolve, reject) => {
300
- const client = http.request({
301
- host: '127.0.0.1',
302
- port: input.port,
303
- path: input.path,
304
- method: input.method || 'GET',
305
- headers: input.headers
306
- }, (response) => {
307
- const chunks = [];
308
- response.on('data', (chunk) => {
309
- chunks.push(chunk);
310
- input.onData?.(chunk);
311
- });
312
- response.once('end', () => resolve({
313
- status: response.statusCode || 0,
314
- headers: response.headers,
315
- body: Buffer.concat(chunks),
316
- requestBodySha256: createHash('sha256').update(requestBody).digest('hex')
317
- }));
318
- });
319
- client.once('error', reject);
320
- for (const chunk of input.chunks || [])
321
- client.write(chunk);
322
- client.end();
323
- });
324
- }
325
- async function websocketRoundTrip(port) {
326
- const holder = { socket: null };
327
- try {
328
- return await new Promise((resolve, reject) => {
329
- const client = net.connect({ host: '127.0.0.1', port });
330
- holder.socket = client;
331
- const chunks = [];
332
- let sentFrame = false;
333
- let settled = false;
334
- const timer = setTimeout(() => {
335
- if (settled)
336
- return;
337
- settled = true;
338
- reject(new Error('desktop_bridge_websocket_timeout'));
339
- client?.destroy();
340
- }, 5_000);
341
- timer.unref();
342
- client.once('connect', () => {
343
- client?.write('GET /backend-api/codex/realtime/call-1?token=opaque HTTP/1.1\r\n'
344
- + `Host: 127.0.0.1:${port}\r\n`
345
- + 'Connection: Upgrade\r\n'
346
- + 'Upgrade: websocket\r\n'
347
- + 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n'
348
- + 'Sec-WebSocket-Version: 13\r\n'
349
- + 'Sec-WebSocket-Protocol: codex.realtime.v1\r\n'
350
- + 'Origin: app://codex\r\n'
351
- + `Authorization: ${desktopAuthorization}\r\n`
352
- + `Cookie: ${desktopCookie}\r\n`
353
- + 'X-Codex-LB-Api-Key: client-forged-key\r\n'
354
- + '\r\n');
355
- });
356
- client.on('data', (chunk) => {
357
- chunks.push(chunk);
358
- const all = Buffer.concat(chunks);
359
- const boundary = all.indexOf('\r\n\r\n');
360
- if (boundary >= 0 && !sentFrame) {
361
- sentFrame = true;
362
- client?.write(maskedClientFrame);
363
- }
364
- const expectedLength = boundary + 4 + serverBinaryFrame.length + serverCloseFrame.length;
365
- if (boundary < 0 || all.length < expectedLength || settled)
366
- return;
367
- settled = true;
368
- clearTimeout(timer);
369
- resolve({
370
- responseHead: all.subarray(0, boundary).toString('latin1'),
371
- frames: all.subarray(boundary + 4)
372
- });
373
- client?.destroy();
374
- });
375
- client.once('error', (error) => {
376
- if (settled)
377
- return;
378
- settled = true;
379
- clearTimeout(timer);
380
- reject(error);
381
- });
382
- client.once('close', () => {
383
- if (settled)
384
- return;
385
- settled = true;
386
- clearTimeout(timer);
387
- reject(new Error('desktop_bridge_websocket_closed_before_complete'));
388
- });
389
- });
390
- }
391
- finally {
392
- holder.socket?.destroy();
393
- }
394
- }
@@ -0,0 +1,116 @@
1
+ import { createHash } from 'node:crypto';
2
+ import http, {} from 'node:http';
3
+ import net, {} from 'node:net';
4
+ export async function listen(server) {
5
+ await new Promise((resolve, reject) => {
6
+ server.once('error', reject);
7
+ server.listen(0, '127.0.0.1', resolve);
8
+ });
9
+ return server.address().port;
10
+ }
11
+ export async function closeServer(server) {
12
+ if (!server.listening)
13
+ return;
14
+ await new Promise((resolve, reject) => {
15
+ server.close((error) => error ? reject(error) : resolve());
16
+ });
17
+ }
18
+ export async function request(input) {
19
+ const requestBody = Buffer.concat([...(input.chunks || [])]);
20
+ return new Promise((resolve, reject) => {
21
+ const client = http.request({
22
+ host: '127.0.0.1',
23
+ port: input.port,
24
+ path: input.path,
25
+ method: input.method || 'GET',
26
+ headers: input.headers
27
+ }, (response) => {
28
+ const chunks = [];
29
+ response.on('data', (chunk) => {
30
+ chunks.push(chunk);
31
+ input.onData?.(chunk);
32
+ });
33
+ response.once('end', () => resolve({
34
+ status: response.statusCode || 0,
35
+ headers: response.headers,
36
+ body: Buffer.concat(chunks),
37
+ requestBodySha256: createHash('sha256').update(requestBody).digest('hex')
38
+ }));
39
+ });
40
+ client.once('error', reject);
41
+ for (const chunk of input.chunks || [])
42
+ client.write(chunk);
43
+ client.end();
44
+ });
45
+ }
46
+ export async function websocketRoundTrip(input) {
47
+ const holder = { socket: null };
48
+ try {
49
+ return await new Promise((resolve, reject) => {
50
+ const client = net.connect({ host: '127.0.0.1', port: input.port });
51
+ holder.socket = client;
52
+ const chunks = [];
53
+ let sentFrame = false;
54
+ let settled = false;
55
+ const timer = setTimeout(() => {
56
+ if (settled)
57
+ return;
58
+ settled = true;
59
+ reject(new Error('desktop_bridge_websocket_timeout'));
60
+ client.destroy();
61
+ }, 5_000);
62
+ timer.unref();
63
+ client.once('connect', () => {
64
+ client.write(`GET /__sks/client/${input.clientCapability}/backend-api/codex/realtime/call-1?token=opaque HTTP/1.1\r\n`
65
+ + `Host: 127.0.0.1:${input.port}\r\n`
66
+ + 'Connection: Upgrade\r\n'
67
+ + 'Upgrade: websocket\r\n'
68
+ + 'Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n'
69
+ + 'Sec-WebSocket-Version: 13\r\n'
70
+ + 'Sec-WebSocket-Protocol: codex.realtime.v1\r\n'
71
+ + 'Origin: app://codex\r\n'
72
+ + `X-SKS-Model: ${input.publicModel}\r\n`
73
+ + `Authorization: ${input.desktopAuthorization}\r\n`
74
+ + `Cookie: ${input.desktopCookie}\r\n`
75
+ + 'X-Codex-LB-Api-Key: client-forged-key\r\n'
76
+ + '\r\n');
77
+ });
78
+ client.on('data', (chunk) => {
79
+ chunks.push(chunk);
80
+ const all = Buffer.concat(chunks);
81
+ const boundary = all.indexOf('\r\n\r\n');
82
+ if (boundary >= 0 && !sentFrame) {
83
+ sentFrame = true;
84
+ client.write(input.maskedClientFrame);
85
+ }
86
+ const expectedLength = boundary + 4 + input.expectedResponseFrameBytes;
87
+ if (boundary < 0 || all.length < expectedLength || settled)
88
+ return;
89
+ settled = true;
90
+ clearTimeout(timer);
91
+ resolve({
92
+ responseHead: all.subarray(0, boundary).toString('latin1'),
93
+ frames: all.subarray(boundary + 4)
94
+ });
95
+ client.destroy();
96
+ });
97
+ client.once('error', (error) => {
98
+ if (settled)
99
+ return;
100
+ settled = true;
101
+ clearTimeout(timer);
102
+ reject(error);
103
+ });
104
+ client.once('close', () => {
105
+ if (settled)
106
+ return;
107
+ settled = true;
108
+ clearTimeout(timer);
109
+ reject(new Error('desktop_bridge_websocket_closed_before_complete'));
110
+ });
111
+ });
112
+ }
113
+ finally {
114
+ holder.socket?.destroy();
115
+ }
116
+ }