@velum-labs/routekit-daemon 1.3.2 → 1.5.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 (172) hide show
  1. package/dist/account-enroll-service.d.ts +1 -3
  2. package/dist/account-enroll-service.js +262 -262
  3. package/dist/account-mutation-service.d.ts +1 -3
  4. package/dist/account-mutation-service.js +302 -283
  5. package/dist/account-query-service.d.ts +1 -3
  6. package/dist/account-query-service.js +88 -86
  7. package/dist/call-attribution-store.js +544 -1
  8. package/dist/control-dispatch.js +9 -15
  9. package/dist/daemon-bootstrap-preflight.js +1 -1
  10. package/dist/daemon-control-handlers.d.ts +1 -1
  11. package/dist/daemon-control-handlers.js +24 -27
  12. package/dist/daemon-generations.d.ts +14 -28
  13. package/dist/daemon-generations.js +114 -53
  14. package/dist/daemon-lifecycle-service.d.ts +1 -3
  15. package/dist/daemon-lifecycle-service.js +88 -94
  16. package/dist/daemon-maintenance.d.ts +27 -49
  17. package/dist/daemon-maintenance.js +5 -1
  18. package/dist/daemon-options.d.ts +3 -2
  19. package/dist/daemon-policy-context.d.ts +1 -0
  20. package/dist/daemon-policy-context.js +1 -0
  21. package/dist/daemon-runtime-state.d.ts +1 -1
  22. package/dist/daemon-runtime-state.js +2 -3
  23. package/dist/daemon-state-context.d.ts +1 -1
  24. package/dist/daemon-state-context.js +1 -38
  25. package/dist/doctor-service.d.ts +1 -3
  26. package/dist/doctor-service.js +87 -91
  27. package/dist/effect/daemon-live.d.ts +7 -6
  28. package/dist/effect/daemon-live.js +57 -135
  29. package/dist/eval-routing-service.d.ts +1 -3
  30. package/dist/eval-routing-service.js +45 -69
  31. package/dist/eval-session-execution-store.d.ts +24 -0
  32. package/dist/eval-session-execution-store.js +253 -0
  33. package/dist/host-protocol.d.ts +1 -0
  34. package/dist/host.js +3 -0
  35. package/dist/internal-providers/provider-anthropic/index.d.ts +23 -0
  36. package/dist/internal-providers/provider-anthropic/index.js +42 -0
  37. package/dist/internal-providers/provider-anthropic/test/provider.test.js +33 -0
  38. package/dist/internal-providers/provider-azure/index.d.ts +25 -0
  39. package/dist/internal-providers/provider-azure/index.js +101 -0
  40. package/dist/internal-providers/provider-azure/test/provider.test.js +83 -0
  41. package/dist/internal-providers/provider-bedrock/codec.d.ts +11 -0
  42. package/dist/internal-providers/provider-bedrock/codec.js +484 -0
  43. package/dist/internal-providers/provider-bedrock/connection-settings.d.ts +6 -0
  44. package/dist/internal-providers/provider-bedrock/connection-settings.js +41 -0
  45. package/dist/internal-providers/provider-bedrock/connection.d.ts +17 -0
  46. package/dist/internal-providers/provider-bedrock/connection.js +143 -0
  47. package/dist/internal-providers/provider-bedrock/index.d.ts +27 -0
  48. package/dist/internal-providers/provider-bedrock/index.js +47 -0
  49. package/dist/internal-providers/provider-bedrock/source.d.ts +39 -0
  50. package/dist/internal-providers/provider-bedrock/source.js +454 -0
  51. package/dist/internal-providers/provider-bedrock/test/bedrock-source.test.d.ts +1 -0
  52. package/dist/internal-providers/provider-bedrock/test/bedrock-source.test.js +786 -0
  53. package/dist/internal-providers/provider-bedrock/test/connection.test.d.ts +1 -0
  54. package/dist/internal-providers/provider-bedrock/test/connection.test.js +249 -0
  55. package/dist/internal-providers/provider-bedrock/test/workload-credentials.test.d.ts +1 -0
  56. package/dist/internal-providers/provider-bedrock/test/workload-credentials.test.js +29 -0
  57. package/dist/internal-providers/provider-bedrock/workload-credentials.d.ts +5 -0
  58. package/dist/internal-providers/provider-bedrock/workload-credentials.js +14 -0
  59. package/dist/internal-providers/provider-claude-code/index.d.ts +6 -0
  60. package/dist/internal-providers/provider-claude-code/index.js +4 -0
  61. package/dist/internal-providers/provider-claude-code/module-api.d.ts +25 -0
  62. package/dist/internal-providers/provider-claude-code/module-api.js +31 -0
  63. package/dist/internal-providers/provider-claude-code/relay.d.ts +20 -0
  64. package/dist/internal-providers/provider-claude-code/relay.js +115 -0
  65. package/dist/internal-providers/provider-claude-code/subscription.d.ts +2 -0
  66. package/dist/internal-providers/provider-claude-code/subscription.js +194 -0
  67. package/dist/internal-providers/provider-claude-code/test/http-submission.test.d.ts +1 -0
  68. package/dist/internal-providers/provider-claude-code/test/http-submission.test.js +140 -0
  69. package/dist/internal-providers/provider-claude-code/test/relay.test.d.ts +1 -0
  70. package/dist/internal-providers/provider-claude-code/test/relay.test.js +379 -0
  71. package/dist/internal-providers/provider-claude-code/test/subscription.test.d.ts +1 -0
  72. package/dist/internal-providers/provider-claude-code/test/subscription.test.js +256 -0
  73. package/dist/internal-providers/provider-cliproxy/index.d.ts +9 -0
  74. package/dist/internal-providers/provider-cliproxy/index.js +15 -0
  75. package/dist/internal-providers/provider-codex/index.d.ts +6 -0
  76. package/dist/internal-providers/provider-codex/index.js +7 -0
  77. package/dist/internal-providers/provider-codex/module-api.d.ts +25 -0
  78. package/dist/internal-providers/provider-codex/module-api.js +31 -0
  79. package/dist/internal-providers/provider-codex/relay.d.ts +123 -0
  80. package/dist/internal-providers/provider-codex/relay.js +261 -0
  81. package/dist/internal-providers/provider-codex/subscription.d.ts +2 -0
  82. package/dist/internal-providers/provider-codex/subscription.js +555 -0
  83. package/dist/internal-providers/provider-codex/test/http-submission.test.d.ts +1 -0
  84. package/dist/internal-providers/provider-codex/test/http-submission.test.js +142 -0
  85. package/dist/internal-providers/provider-codex/test/relay.test.d.ts +1 -0
  86. package/dist/internal-providers/provider-codex/test/relay.test.js +600 -0
  87. package/dist/internal-providers/provider-codex/test/subscription.test.d.ts +1 -0
  88. package/dist/internal-providers/provider-codex/test/subscription.test.js +70 -0
  89. package/dist/internal-providers/provider-codex/test/translated-content.test.d.ts +1 -0
  90. package/dist/internal-providers/provider-codex/test/translated-content.test.js +91 -0
  91. package/dist/internal-providers/provider-custom/index.d.ts +9 -0
  92. package/dist/internal-providers/provider-custom/index.js +15 -0
  93. package/dist/internal-providers/provider-google/index.d.ts +23 -0
  94. package/dist/internal-providers/provider-google/index.js +43 -0
  95. package/dist/internal-providers/provider-google/test/provider.test.d.ts +1 -0
  96. package/dist/internal-providers/provider-google/test/provider.test.js +34 -0
  97. package/dist/internal-providers/provider-google-vertex/index.d.ts +28 -0
  98. package/dist/internal-providers/provider-google-vertex/index.js +137 -0
  99. package/dist/internal-providers/provider-google-vertex/test/provider.test.d.ts +1 -0
  100. package/dist/internal-providers/provider-google-vertex/test/provider.test.js +85 -0
  101. package/dist/internal-providers/provider-openai/documented-reasoning.d.ts +9 -0
  102. package/dist/internal-providers/provider-openai/documented-reasoning.js +26 -0
  103. package/dist/internal-providers/provider-openai/index.d.ts +23 -0
  104. package/dist/internal-providers/provider-openai/index.js +74 -0
  105. package/dist/internal-providers/provider-openai/test/provider.test.d.ts +1 -0
  106. package/dist/internal-providers/provider-openai/test/provider.test.js +268 -0
  107. package/dist/internal-providers/provider-openai-compatible/index.d.ts +9 -0
  108. package/dist/internal-providers/provider-openai-compatible/index.js +15 -0
  109. package/dist/internal-providers/provider-openai-compatible/test/provider.test.d.ts +1 -0
  110. package/dist/internal-providers/provider-openai-compatible/test/provider.test.js +40 -0
  111. package/dist/internal-providers/provider-openrouter/connection.d.ts +5 -0
  112. package/dist/internal-providers/provider-openrouter/connection.js +143 -0
  113. package/dist/internal-providers/provider-openrouter/index.d.ts +28 -0
  114. package/dist/internal-providers/provider-openrouter/index.js +42 -0
  115. package/dist/internal-providers/provider-openrouter/pricing.d.ts +4 -0
  116. package/dist/internal-providers/provider-openrouter/pricing.js +108 -0
  117. package/dist/internal-providers/provider-openrouter/test/connection.test.d.ts +1 -0
  118. package/dist/internal-providers/provider-openrouter/test/connection.test.js +71 -0
  119. package/dist/internal-providers/provider-openrouter/test/pricing.test.d.ts +1 -0
  120. package/dist/internal-providers/provider-openrouter/test/pricing.test.js +45 -0
  121. package/dist/internal-providers/provider-openrouter/test/provider.test.d.ts +1 -0
  122. package/dist/internal-providers/provider-openrouter/test/provider.test.js +141 -0
  123. package/dist/internal-providers/provider-openrouter/test/validation.test.d.ts +1 -0
  124. package/dist/internal-providers/provider-openrouter/test/validation.test.js +225 -0
  125. package/dist/launcher-service.d.ts +3 -7
  126. package/dist/launcher-service.js +144 -133
  127. package/dist/provider-modules.d.ts +6 -0
  128. package/dist/provider-modules.js +55 -0
  129. package/dist/provider-query-service.d.ts +1 -3
  130. package/dist/provider-query-service.js +140 -143
  131. package/dist/router-generation-service.d.ts +1 -3
  132. package/dist/router-generation-service.js +83 -78
  133. package/dist/services/eval-session/service.d.ts +20 -8
  134. package/dist/services/eval-session/service.js +410 -40
  135. package/dist/services/gateway-generation/service.d.ts +7 -3
  136. package/dist/services/gateway-generation/service.js +126 -63
  137. package/dist/services/generations/service.d.ts +3 -3
  138. package/dist/services/generations/service.js +5 -1
  139. package/dist/telemetry-application-service.d.ts +1 -3
  140. package/dist/telemetry-application-service.js +41 -45
  141. package/dist/test/call-attribution-store.test.js +186 -0
  142. package/dist/test/daemon-accounts.test.js +2 -2
  143. package/dist/test/daemon-data-plane.test.js +24 -45
  144. package/dist/test/daemon-fixtures.js +1 -1
  145. package/dist/test/daemon-generation-transaction.test.js +66 -2
  146. package/dist/test/daemon-runtime-state.test.js +28 -1
  147. package/dist/test/effect-daemon.test.js +38 -0
  148. package/dist/test/eval-routing-application-service.test.js +6 -6
  149. package/dist/test/eval-session-execution.test.d.ts +1 -0
  150. package/dist/test/eval-session-execution.test.js +356 -0
  151. package/dist/test/eval-session-service.test.js +70 -1
  152. package/dist/test/host-worker-session.test.js +1 -0
  153. package/dist/test/launcher-session.test.d.ts +1 -0
  154. package/dist/test/launcher-session.test.js +87 -0
  155. package/dist/test/leaderboard.test.js +25 -1
  156. package/dist/test/provider-modules.test.d.ts +1 -0
  157. package/dist/test/provider-modules.test.js +65 -0
  158. package/dist/test/routekit-upstream-sources.test.d.ts +1 -0
  159. package/dist/test/routekit-upstream-sources.test.js +40 -0
  160. package/dist/test/runtime-composition-types.test.js +11 -0
  161. package/dist/token-application-service.d.ts +1 -3
  162. package/dist/token-application-service.js +38 -44
  163. package/dist/worker.js +5 -3
  164. package/package.json +35 -11
  165. package/dist/application-services.d.ts +0 -10
  166. package/dist/application-services.js +0 -22
  167. package/dist/daemon-lifecycle.d.ts +0 -54
  168. package/dist/daemon-lifecycle.js +0 -177
  169. package/dist/test/application-services.test.js +0 -135
  170. package/dist/test/daemon-lifecycle.test.js +0 -182
  171. /package/dist/{test/application-services.test.d.ts → internal-providers/provider-anthropic/test/provider.test.d.ts} +0 -0
  172. /package/dist/{test/daemon-lifecycle.test.d.ts → internal-providers/provider-azure/test/provider.test.d.ts} +0 -0
@@ -0,0 +1,356 @@
1
+ import assert from "node:assert/strict";
2
+ import { createHash } from "node:crypto";
3
+ import { mkdtempSync, readdirSync, readFileSync, rmSync, statSync, symlinkSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import { join } from "node:path";
6
+ import test from "node:test";
7
+ import { HttpSubmissionError, runRouteKitEffect } from "@velum-labs/routekit-runtime/effect";
8
+ import { Effect, FileSystem, Path, PlatformError } from "effect";
9
+ import { makeEvalSessionExecutionStore } from "../eval-session-execution-store.js";
10
+ import { EvalSessionManager } from "../services/eval-session/service.js";
11
+ const sha = (value) => createHash("sha256").update(value).digest("hex");
12
+ const run = Effect.runPromise;
13
+ const executionDigest = sha("immutable-authoring-execution");
14
+ const request = {
15
+ method: "POST",
16
+ destination: "https://provider.invalid/v1/responses",
17
+ requestDigest: sha("actual native request"),
18
+ model: "native-model",
19
+ accountIdentity: sha("private account identity")
20
+ };
21
+ const completed = {
22
+ state: "completed",
23
+ httpStatus: 200,
24
+ responseDigest: sha("actual raw response"),
25
+ responseBytes: 19,
26
+ terminal: "eof"
27
+ };
28
+ function openInput(maximumProviderAttempts = 3) {
29
+ return {
30
+ purpose: "authoring",
31
+ operationId: "test-authoring",
32
+ allowedModels: ["openai/native-model"],
33
+ limits: {
34
+ calls: 32,
35
+ inputTokens: 10_000,
36
+ outputTokens: 1000,
37
+ perCallOutputTokens: 32,
38
+ wallTimeMs: 60_000
39
+ },
40
+ expiresInSeconds: 60,
41
+ gatewayUrl: "http://127.0.0.1:8080",
42
+ targetIdentity: "routekit-generation:1",
43
+ evidenceRequired: { executionDigest, maximumProviderAttempts, policy: "strict-http-v1" }
44
+ };
45
+ }
46
+ function identity(opened) {
47
+ assert.ok(opened.executionGrant);
48
+ return {
49
+ sessionId: opened.sessionId,
50
+ grantId: opened.executionGrant.grantId,
51
+ executionDigest: opened.executionGrant.executionDigest,
52
+ issuerIdentity: opened.executionGrant.issuerIdentity
53
+ };
54
+ }
55
+ async function fixture(t) {
56
+ const root = mkdtempSync(join(tmpdir(), "routekit-eval-execution-"));
57
+ let failedRenames = 0;
58
+ const store = await runRouteKitEffect(Effect.gen(function* () {
59
+ const fs = yield* FileSystem.FileSystem;
60
+ return yield* makeEvalSessionExecutionStore(join(root, "private")).pipe(Effect.provideService(FileSystem.FileSystem, {
61
+ ...fs,
62
+ rename: (from, to) => Effect.suspend(() => {
63
+ if (failedRenames > 0) {
64
+ failedRenames -= 1;
65
+ return Effect.fail(PlatformError.systemError({
66
+ _tag: "Unknown",
67
+ module: "FileSystem",
68
+ method: "rename",
69
+ description: "injected required evidence write failure"
70
+ }));
71
+ }
72
+ return fs.rename(from, to);
73
+ })
74
+ }));
75
+ }));
76
+ let now = 0;
77
+ const sessions = new EvalSessionManager({ store, now: () => now });
78
+ await run(sessions.initialize());
79
+ t.after(async () => {
80
+ failedRenames = 0;
81
+ await run(sessions.shutdown().pipe(Effect.ignore));
82
+ rmSync(root, { recursive: true, force: true });
83
+ });
84
+ return {
85
+ root,
86
+ store,
87
+ sessions,
88
+ failRenames: (count) => {
89
+ failedRenames = count;
90
+ },
91
+ setNow: (value) => {
92
+ now = value;
93
+ },
94
+ record: () => JSON.parse(readFileSync(join(store.directory, `${executionDigest}.json`), "utf8"))
95
+ };
96
+ }
97
+ async function authority(sessions, opened, suffix = "") {
98
+ const binding = await run(sessions.bindIngress(opened.sessionId, {
99
+ requestDigest: sha(`frontend request ${suffix}`),
100
+ model: "openai/native-model"
101
+ }));
102
+ return { binding, authority: await run(sessions.resolveSubmission(binding)) };
103
+ }
104
+ async function rejectsCode(effect, code) {
105
+ const result = await run(effect.pipe(Effect.map(() => ({ kind: "success" })), Effect.catch((error) => Effect.succeed({ kind: "error", error }))));
106
+ assert.equal(result.kind, "error");
107
+ if (result.kind === "error") {
108
+ assert.ok(result.error instanceof HttpSubmissionError);
109
+ assert.equal(result.error.code, code);
110
+ }
111
+ }
112
+ test("strict sessions require durable awaited authority while legacy sessions remain ephemeral", async () => {
113
+ const sessions = new EvalSessionManager({ now: () => 0 });
114
+ await rejectsCode(sessions.openEffect(openInput()), "execution-unavailable");
115
+ assert.throws(() => sessions.open(openInput()), /awaited openEffect/u);
116
+ const { evidenceRequired: _, ...legacy } = openInput();
117
+ const opened = sessions.open(legacy);
118
+ assert.equal(opened.executionGrant, undefined);
119
+ assert.equal(sessions.resolve(opened.bearerCredential)?.evalSession?.executionGrant, undefined);
120
+ assert.equal(sessions.close(opened.sessionId), true);
121
+ });
122
+ test("the real private store persists a permit before submission and seals only after revocation", async (t) => {
123
+ const { store, sessions, record } = await fixture(t);
124
+ const opened = await run(sessions.openEffect(openInput()));
125
+ assert.deepEqual(sessions.resolve(opened.bearerCredential)?.evalSession?.executionGrant, opened.executionGrant);
126
+ assert.equal(statSync(store.directory).mode & 0o777, 0o700);
127
+ assert.equal(statSync(join(store.directory, `${executionDigest}.json`)).mode & 0o777, 0o600);
128
+ assert.throws(() => sessions.close(opened.sessionId), /awaited closeEffect/u);
129
+ const bound = await authority(sessions, opened);
130
+ let submissions = 0;
131
+ const attempt = await run(bound.authority.begin(request).pipe(Effect.tap(() => Effect.sync(() => {
132
+ assert.equal(record().evidence.receipts.length, 1);
133
+ submissions += 1;
134
+ }))));
135
+ assert.equal(submissions, 1);
136
+ let evidence = await run(sessions.executionEvidence(identity(opened)));
137
+ assert.equal(evidence.receipts[0]?.state, "intent");
138
+ assert.equal(evidence.exposure, "unknown");
139
+ await run(bound.authority.settle(attempt.attemptId, completed));
140
+ evidence = await run(sessions.executionEvidence(identity(opened)));
141
+ assert.equal(evidence.state, "open");
142
+ assert.equal(evidence.exposure, "closed");
143
+ assert.equal(await run(sessions.closeEffect(opened.sessionId)), true);
144
+ evidence = await run(sessions.executionEvidence(identity(opened)));
145
+ assert.equal(evidence.state, "sealed");
146
+ assert.equal(evidence.exposure, "closed");
147
+ assert.equal(sessions.resolve(opened.bearerCredential), undefined);
148
+ await rejectsCode(sessions.openEffect(openInput()), "execution-consumed");
149
+ });
150
+ test("concurrent ingresses and retries share one non-resettable provider attempt allowance", async (t) => {
151
+ const { sessions } = await fixture(t);
152
+ const opened = await run(sessions.openEffect(openInput(3)));
153
+ const first = await authority(sessions, opened, "first");
154
+ const second = await authority(sessions, opened, "second");
155
+ const results = await Promise.all(Array.from({ length: 12 }, (_, index) => run((index % 2 === 0 ? first : second).authority.begin(request).pipe(Effect.map((attempt) => ({ kind: "attempt", attempt })), Effect.catch((error) => Effect.succeed({ kind: "error", code: error.code }))))));
156
+ assert.equal(results.filter((entry) => entry.kind === "attempt").length, 3);
157
+ assert.deepEqual(results.filter((entry) => entry.kind === "error").map((entry) => entry.code), Array(9).fill("provider-attempt-limit"));
158
+ const evidence = await run(sessions.executionEvidence(identity(opened)));
159
+ assert.equal(evidence.receipts.length, 3);
160
+ assert.equal(new Set(evidence.receipts.map((entry) => entry.attemptId)).size, 3);
161
+ await rejectsCode(sessions.openEffect(openInput(3)), "execution-consumed");
162
+ });
163
+ test("server ingresses reject mismatches and duplicate delivery without manufacturing attempts", async (t) => {
164
+ const { sessions } = await fixture(t);
165
+ const opened = await run(sessions.openEffect(openInput()));
166
+ const binding = await run(sessions.bindIngress(opened.sessionId, {
167
+ requestDigest: sha("bound frontend"),
168
+ model: "openai/native-model"
169
+ }));
170
+ await rejectsCode(sessions.resolveSubmission({ ...binding, requestDigest: sha("tampered") }), "ingress-identity");
171
+ await rejectsCode(sessions.resolveSubmission({ ...binding, issuerIdentity: "another-issuer" }), "execution-identity");
172
+ await rejectsCode(sessions.resolveSubmission({ ...binding, grantId: "another-grant" }), "execution-identity");
173
+ await run(sessions.resolveSubmission(binding));
174
+ await rejectsCode(sessions.resolveSubmission(binding), "ingress-consumed");
175
+ await run(sessions.closeEffect(opened.sessionId));
176
+ const evidence = await run(sessions.executionEvidence(identity(opened)));
177
+ assert.equal(evidence.state, "sealed");
178
+ assert.equal(evidence.exposure, "closed");
179
+ assert.equal(evidence.receipts.length, 0);
180
+ assert.equal(evidence.ingresses[0]?.status, "no-attempt");
181
+ await rejectsCode(sessions.openEffect(openInput()), "execution-consumed");
182
+ });
183
+ test("unknown is sticky across concurrent completion and forbids another strict submission", async (t) => {
184
+ const { sessions } = await fixture(t);
185
+ const opened = await run(sessions.openEffect(openInput()));
186
+ const bound = await authority(sessions, opened);
187
+ const first = await run(bound.authority.begin(request));
188
+ const second = await run(bound.authority.begin(request));
189
+ await run(bound.authority.settle(first.attemptId, { state: "unknown", reason: "transport-error" }));
190
+ let evidence = await run(sessions.executionEvidence(identity(opened)));
191
+ assert.equal(evidence.state, "draining");
192
+ assert.equal(sessions.resolve(opened.bearerCredential), undefined);
193
+ await rejectsCode(bound.authority.begin(request), "execution-closed");
194
+ await run(bound.authority.settle(second.attemptId, completed));
195
+ await run(bound.authority.settle(first.attemptId, completed));
196
+ evidence = await run(sessions.executionEvidence(identity(opened)));
197
+ assert.equal(evidence.state, "sealed");
198
+ assert.equal(evidence.exposure, "unknown");
199
+ assert.deepEqual(evidence.receipts.map((entry) => entry.state), ["unknown", "completed"]);
200
+ });
201
+ test("close revokes new work but existing provider owners settle a draining grant", async (t) => {
202
+ const { sessions } = await fixture(t);
203
+ const opened = await run(sessions.openEffect(openInput()));
204
+ const bound = await authority(sessions, opened);
205
+ const { attemptId } = await run(bound.authority.begin(request));
206
+ assert.equal(await run(sessions.closeEffect(opened.sessionId)), true);
207
+ assert.equal(await run(sessions.closeEffect(opened.sessionId)), false);
208
+ let evidence = await run(sessions.executionEvidence(identity(opened)));
209
+ assert.equal(evidence.state, "draining");
210
+ assert.equal(evidence.exposure, "unknown");
211
+ await rejectsCode(bound.authority.begin(request), "execution-closed");
212
+ await run(bound.authority.settle(attemptId, completed));
213
+ evidence = await run(sessions.executionEvidence(identity(opened)));
214
+ assert.equal(evidence.state, "sealed");
215
+ assert.equal(evidence.exposure, "closed");
216
+ });
217
+ test("restart recovers unmatched intents as unknown and a retiring manager cannot overwrite them", async (t) => {
218
+ const { sessions, store } = await fixture(t);
219
+ const opened = await run(sessions.openEffect(openInput()));
220
+ const bound = await authority(sessions, opened);
221
+ const { attemptId } = await run(bound.authority.begin(request));
222
+ const reopenedStore = await runRouteKitEffect(makeEvalSessionExecutionStore(store.directory));
223
+ const successor = new EvalSessionManager({ store: reopenedStore, now: () => 1_000 });
224
+ await run(successor.initialize());
225
+ assert.equal(successor.resolve(opened.bearerCredential), undefined);
226
+ let evidence = await run(successor.executionEvidence(identity(opened)));
227
+ assert.equal(evidence.state, "sealed");
228
+ assert.equal(evidence.exposure, "unknown");
229
+ assert.deepEqual(evidence.receipts[0]?.outcome, { state: "unknown", reason: "daemon-restart" });
230
+ await run(bound.authority.settle(attemptId, completed));
231
+ evidence = await run(successor.executionEvidence(identity(opened)));
232
+ assert.deepEqual(evidence.receipts[0]?.outcome, { state: "unknown", reason: "daemon-restart" });
233
+ await rejectsCode(bound.authority.begin(request), "execution-closed");
234
+ await rejectsCode(successor.openEffect(openInput()), "execution-consumed");
235
+ });
236
+ test("only explicitly closed untouched readiness grants can be reissued and their history remains bound", async (t) => {
237
+ const { sessions, store, record } = await fixture(t);
238
+ const first = await run(sessions.openEffect(openInput()));
239
+ await run(sessions.closeEffect(first.sessionId));
240
+ await rejectsCode(sessions.openEffect(openInput(4)), "execution-consumed");
241
+ const second = await run(sessions.openEffect(openInput()));
242
+ assert.notEqual(first.sessionId, second.sessionId);
243
+ assert.notEqual(first.executionGrant?.grantId, second.executionGrant?.grantId);
244
+ assert.equal(record().readinessHistory.length, 1);
245
+ assert.equal((await run(sessions.executionEvidence(identity(first)))).state, "sealed");
246
+ assert.equal((await run(sessions.executionEvidence(identity(second)))).state, "open");
247
+ await rejectsCode(sessions.executionEvidence({
248
+ ...identity(second),
249
+ grantId: first.executionGrant.grantId
250
+ }), "execution-identity");
251
+ const successor = new EvalSessionManager({ store, now: () => 1000 });
252
+ await run(successor.initialize());
253
+ assert.equal((await run(successor.executionEvidence(identity(second)))).exposure, "closed");
254
+ // Recovery revokes the unclosed grant, but does not turn unresolved readiness
255
+ // into proof that an explicit no-request close completed.
256
+ await rejectsCode(successor.openEffect(openInput()), "execution-consumed");
257
+ });
258
+ test("required intent write failure yields zero submissions and poisons even with repeated I/O failure", async (t) => {
259
+ for (const failures of [1, 2]) {
260
+ await t.test(`${failures} failed writes`, async (t) => {
261
+ const { sessions, failRenames, record } = await fixture(t);
262
+ const opened = await run(sessions.openEffect(openInput()));
263
+ const bound = await authority(sessions, opened);
264
+ let submissions = 0;
265
+ failRenames(failures);
266
+ await rejectsCode(bound.authority.begin(request).pipe(Effect.tap(() => Effect.sync(() => {
267
+ submissions += 1;
268
+ }))), "execution-store");
269
+ assert.equal(submissions, 0);
270
+ assert.equal(record().evidence.receipts.length, 0);
271
+ assert.equal(sessions.resolve(opened.bearerCredential), undefined);
272
+ await rejectsCode(bound.authority.begin(request), "execution-closed");
273
+ failRenames(0);
274
+ const evidence = await run(sessions.executionEvidence(identity(opened)));
275
+ assert.equal(evidence.poisoned, true);
276
+ assert.equal(evidence.state, "sealed");
277
+ assert.equal(evidence.exposure, "unknown");
278
+ assert.equal(evidence.receipts.length, 0);
279
+ });
280
+ }
281
+ });
282
+ test("required settlement I/O failure retains the durable intent and cannot report closed exposure", async (t) => {
283
+ const { sessions, store, failRenames } = await fixture(t);
284
+ const opened = await run(sessions.openEffect(openInput()));
285
+ const bound = await authority(sessions, opened);
286
+ const { attemptId } = await run(bound.authority.begin(request));
287
+ failRenames(2);
288
+ await rejectsCode(bound.authority.settle(attemptId, completed), "execution-store");
289
+ failRenames(0);
290
+ let evidence = await run(sessions.executionEvidence(identity(opened)));
291
+ assert.equal(evidence.poisoned, true);
292
+ assert.equal(evidence.receipts[0]?.state, "intent");
293
+ assert.equal(evidence.exposure, "unknown");
294
+ const successor = new EvalSessionManager({ store, now: () => 1000 });
295
+ await run(successor.initialize());
296
+ evidence = await run(successor.executionEvidence(identity(opened)));
297
+ assert.equal(evidence.state, "sealed");
298
+ assert.equal(evidence.exposure, "unknown");
299
+ assert.equal(evidence.receipts[0]?.state, "unknown");
300
+ });
301
+ test("two independent initialized store owners cannot mint two allowances for one execution", async (t) => {
302
+ const { sessions, store } = await fixture(t);
303
+ const otherStore = await runRouteKitEffect(makeEvalSessionExecutionStore(store.directory));
304
+ const other = new EvalSessionManager({ store: otherStore, now: () => 0 });
305
+ await run(other.initialize());
306
+ const results = await Promise.all([sessions, other].map((owner) => run(owner.openEffect(openInput()).pipe(Effect.map((opened) => ({ kind: "opened", opened })), Effect.catch((error) => Effect.succeed({ kind: "error", code: error.code }))))));
307
+ assert.equal(results.filter((entry) => entry.kind === "opened").length, 1);
308
+ assert.deepEqual(results.filter((entry) => entry.kind === "error").map((entry) => entry.code), ["execution-consumed"]);
309
+ await run(other.shutdown());
310
+ });
311
+ test("corrupt evidence is never treated as a missing or fresh execution", async (t) => {
312
+ const { sessions, store } = await fixture(t);
313
+ const opened = await run(sessions.openEffect(openInput()));
314
+ const path = join(store.directory, `${executionDigest}.json`);
315
+ writeFileSync(path, "{malformed private authority\n");
316
+ await rejectsCode(sessions.executionEvidence(identity(opened)), "execution-store");
317
+ assert.equal(readFileSync(path, "utf8"), "{malformed private authority\n");
318
+ await rejectsCode(sessions.openEffect(openInput()), "execution-store");
319
+ const successor = new EvalSessionManager({ store });
320
+ await rejectsCode(successor.initialize(), "execution-store");
321
+ assert.equal(sessions.resolve(opened.bearerCredential), undefined);
322
+ });
323
+ test("private authority rejects symlinks and persists no bearer, payload, headers or raw account identity", async (t) => {
324
+ const { root, sessions, store } = await fixture(t);
325
+ const alias = join(root, "alias");
326
+ symlinkSync(store.directory, alias);
327
+ await rejectsCode(makeEvalSessionExecutionStore(alias).pipe(Effect.provideService(FileSystem.FileSystem, await runRouteKitEffect(FileSystem.FileSystem)), Effect.provideService(Path.Path, await runRouteKitEffect(Path.Path))), "execution-store");
328
+ const opened = await run(sessions.openEffect(openInput()));
329
+ const bound = await authority(sessions, opened);
330
+ const { attemptId } = await run(bound.authority.begin(request));
331
+ await run(bound.authority.settle(attemptId, completed));
332
+ const text = readdirSync(store.directory)
333
+ .filter((file) => file.endsWith(".json"))
334
+ .map((file) => readFileSync(join(store.directory, file), "utf8"))
335
+ .join("\n");
336
+ for (const secret of [
337
+ opened.bearerCredential,
338
+ "actual native request",
339
+ "actual raw response",
340
+ "private account identity",
341
+ "authorization",
342
+ "headers"
343
+ ])
344
+ assert.equal(text.includes(secret), false);
345
+ });
346
+ test("expiry refuses another provider attempt and an authoritative read revokes the stale grant", async (t) => {
347
+ const { sessions, setNow } = await fixture(t);
348
+ const opened = await run(sessions.openEffect(openInput()));
349
+ const bound = await authority(sessions, opened);
350
+ setNow(60_000);
351
+ await rejectsCode(bound.authority.begin(request), "execution-closed");
352
+ const evidence = await run(sessions.executionEvidence(identity(opened)));
353
+ assert.equal(evidence.state, "sealed");
354
+ assert.equal(evidence.exposure, "closed");
355
+ assert.equal(evidence.receipts.length, 0);
356
+ });
@@ -1,6 +1,6 @@
1
1
  import assert from "node:assert/strict";
2
2
  import test from "node:test";
3
- import { ManagedRuntime } from "effect";
3
+ import { Deferred, Effect, ManagedRuntime } from "effect";
4
4
  import { EvalSessionManager, EvalSessions } from "../services/eval-session/service.js";
5
5
  const limits = {
6
6
  calls: 2,
@@ -76,6 +76,75 @@ test("eval session admission enforces call, input, output, and expiry limits", (
76
76
  now = 60_000;
77
77
  assert.equal(sessions.resolve(opened.bearerCredential), undefined);
78
78
  });
79
+ test("concurrent eval authoring admissions cannot oversubscribe any shared budget", async (t) => {
80
+ for (const scenario of [
81
+ { reason: "call_limit", calls: 2, inputTokens: 100, outputTokens: 100 },
82
+ { reason: "input_limit", calls: 10, inputTokens: 8, outputTokens: 100 },
83
+ { reason: "output_limit", calls: 10, inputTokens: 100, outputTokens: 8 }
84
+ ]) {
85
+ await t.test(scenario.reason, async () => {
86
+ const sessions = new EvalSessionManager({ now: () => 0 });
87
+ const opened = sessions.open({
88
+ purpose: "authoring",
89
+ operationId: `concurrent-${scenario.reason}`,
90
+ allowedModels: ["openai/gpt-6-astra"],
91
+ limits: {
92
+ ...limits,
93
+ calls: scenario.calls,
94
+ inputTokens: scenario.inputTokens,
95
+ outputTokens: scenario.outputTokens
96
+ },
97
+ expiresInSeconds: 60,
98
+ gatewayUrl: "http://127.0.0.1:8080",
99
+ targetIdentity: "routekit-generation:1"
100
+ });
101
+ const admit = sessions.resolve(opened.bearerCredential)?.evalSession?.admit;
102
+ assert.ok(admit !== undefined);
103
+ const results = await Promise.all(Array.from({ length: 8 }, async () => {
104
+ // Queue all requests before any reservation, as concurrent HTTP handlers do.
105
+ await Promise.resolve();
106
+ return admit("openai/gpt-6-astra", 4, 4);
107
+ }));
108
+ assert.equal(results.filter((result) => result.admitted).length, 2);
109
+ assert.deepEqual(results.filter((result) => !result.admitted), Array.from({ length: 6 }, () => ({ admitted: false, reason: scenario.reason })));
110
+ sessions.closeAll();
111
+ });
112
+ }
113
+ });
114
+ test("failed concurrent authoring interrupts siblings without releasing admitted reservations", async () => {
115
+ const sessions = new EvalSessionManager({ now: () => 0 });
116
+ const opened = sessions.open({
117
+ purpose: "authoring",
118
+ operationId: "concurrent-authoring-cancellation",
119
+ allowedModels: ["openai/gpt-6-astra"],
120
+ limits,
121
+ expiresInSeconds: 60,
122
+ gatewayUrl: "http://127.0.0.1:8080",
123
+ targetIdentity: "routekit-generation:1"
124
+ });
125
+ const admit = sessions.resolve(opened.bearerCredential)?.evalSession?.admit;
126
+ assert.ok(admit !== undefined);
127
+ const bothAdmitted = Deferred.makeUnsafe();
128
+ let admitted = 0;
129
+ let siblingInterrupted = false;
130
+ const result = await Effect.runPromiseExit(Effect.forEach([0, 1], (index) => Effect.gen(function* () {
131
+ assert.deepEqual(admit("openai/gpt-6-astra", 5_000, 6), { admitted: true });
132
+ admitted += 1;
133
+ if (admitted === 2)
134
+ yield* Deferred.succeed(bothAdmitted, undefined);
135
+ yield* Deferred.await(bothAdmitted);
136
+ if (index === 0)
137
+ return yield* Effect.fail({ _tag: "TestProviderFailure" });
138
+ return yield* Effect.never.pipe(Effect.onInterrupt(() => Effect.sync(() => {
139
+ siblingInterrupted = true;
140
+ })));
141
+ }), { concurrency: 2 }).pipe(Effect.timeout("2 seconds")));
142
+ assert.equal(result._tag, "Failure");
143
+ assert.equal(admitted, 2);
144
+ assert.equal(siblingInterrupted, true);
145
+ assert.deepEqual(admit("openai/gpt-6-astra", 0, 1), { admitted: false, reason: "call_limit" });
146
+ sessions.closeAll();
147
+ });
79
148
  test("eval sessions close when their Effect-owned daemon scope is disposed", async () => {
80
149
  let sequence = 20;
81
150
  const runtime = ManagedRuntime.make(EvalSessions.layer({
@@ -24,6 +24,7 @@ test("host worker coordinator consumes worker ready and response IPC", () => {
24
24
  workerPid: 1,
25
25
  workerStartedAt: "2026-01-01T00:00:00.000Z",
26
26
  packageVersion: "0.0.0",
27
+ sourceBuildId: "checkout-build",
27
28
  generation: 1,
28
29
  configRevision: 1,
29
30
  accountRevision: 1,
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,87 @@
1
+ import assert from "node:assert/strict";
2
+ import { dirname, join } from "node:path";
3
+ import test from "node:test";
4
+ import { fileURLToPath } from "node:url";
5
+ import { runRouteKitEffectWith } from "@velum-labs/routekit-runtime/effect";
6
+ import { Context, Effect, Ref } from "effect";
7
+ import { launcherHandlers } from "../launcher-service.js";
8
+ import { ActiveGateway } from "../services/active-gateway/service.js";
9
+ import { LauncherSessionManager } from "../services/launcher-session/service.js";
10
+ import { LauncherSessions } from "../services/launcher-session/service.js";
11
+ import { Tokens } from "../services/tokens/service.js";
12
+ test("launcher sessions bind repository context without durable token state", () => {
13
+ let byte = 0;
14
+ const sessions = new LauncherSessionManager({
15
+ random: (length) => Buffer.alloc(length, byte++)
16
+ });
17
+ const token = sessions.open({
18
+ repositoryRoot: "/workspace/repository",
19
+ profileName: "quality",
20
+ role: "owner"
21
+ });
22
+ assert.deepEqual(sessions.resolve(token), {
23
+ id: `launcher_${Buffer.alloc(16, 1).toString("base64url")}`,
24
+ label: "launcher:quality",
25
+ role: "owner",
26
+ routing: {
27
+ repositoryRoot: "/workspace/repository",
28
+ profileName: "quality"
29
+ }
30
+ });
31
+ assert.equal(sessions.resolve("wrong"), undefined);
32
+ sessions.closeAll();
33
+ assert.equal(sessions.resolve(token), undefined);
34
+ });
35
+ test("launcher preparation mints a session only after validation and response preparation", async () => {
36
+ const repositoryRoot = join(dirname(fileURLToPath(import.meta.url)), "../../../../test/fixtures/repository-routing-profiles");
37
+ let randomCalls = 0;
38
+ const sessions = new LauncherSessionManager({
39
+ random: (length) => Buffer.alloc(length, ++randomCalls)
40
+ });
41
+ const candidateToken = Buffer.alloc(32, 1).toString("base64url");
42
+ let failGatewayUrl = false;
43
+ const gateway = ActiveGateway.of({
44
+ state: await Effect.runPromise(Ref.make({})),
45
+ router: () => undefined,
46
+ proxy: () => undefined,
47
+ dataUrl: () => {
48
+ if (failGatewayUrl)
49
+ throw new Error("gateway URL unavailable");
50
+ return "http://127.0.0.1:8080";
51
+ },
52
+ control: () => undefined
53
+ });
54
+ const tokens = Tokens.of({
55
+ dataAuth: { token: "owner-token", path: "/unused" },
56
+ issue: () => Effect.die("unused"),
57
+ list: () => Effect.succeed([]),
58
+ revoke: () => Effect.die("unused"),
59
+ resolve: () => undefined,
60
+ dataTokenForPrincipal: () => Effect.succeed("owner-token")
61
+ });
62
+ const services = Context.empty().pipe(Context.add(ActiveGateway, gateway), Context.add(Tokens, tokens), Context.add(LauncherSessions, sessions));
63
+ const handler = launcherHandlers({
64
+ listModels: () => Effect.succeed({ models: [], revision: 0 })
65
+ })["launcher.prepare"];
66
+ const context = { requestId: "launcher-test", signal: new AbortController().signal };
67
+ const prepare = (input) => runRouteKitEffectWith(services, handler(input, context));
68
+ await assert.rejects(prepare({ tool: "claude", model: "unknown" }));
69
+ await assert.rejects(prepare({ tool: "codex", model: "unknown" }));
70
+ assert.equal(randomCalls, 0);
71
+ assert.equal(sessions.resolve(candidateToken), undefined);
72
+ failGatewayUrl = true;
73
+ await assert.rejects(prepare({ tool: "codex", model: "auto:quality", cwd: repositoryRoot }));
74
+ assert.equal(randomCalls, 0);
75
+ assert.equal(sessions.resolve(candidateToken), undefined);
76
+ failGatewayUrl = false;
77
+ const prepared = await prepare({
78
+ tool: "codex",
79
+ model: "auto:quality",
80
+ cwd: repositoryRoot
81
+ });
82
+ assert.equal(prepared.model, "auto:quality");
83
+ assert.equal(prepared.gatewayUrl, "http://127.0.0.1:8080");
84
+ assert.equal(prepared.authToken, candidateToken);
85
+ assert.equal(sessions.resolve(prepared.authToken)?.routing?.profileName, "quality");
86
+ assert.equal(randomCalls, 2);
87
+ });
@@ -9,6 +9,29 @@ import { aggregateInspections, defaultLeaderboardWindow, LeaderboardRollupStore
9
9
  function inspection(input) {
10
10
  return {
11
11
  callId: input.callId,
12
+ episodeId: input.callId,
13
+ hopIndex: 0,
14
+ role: "explicit",
15
+ cacheOutcome: "miss_cold",
16
+ episode: {
17
+ episodeId: input.callId,
18
+ hopCount: 1,
19
+ models: [input.model ?? "openai/gpt-5.5"],
20
+ cacheOutcomes: ["miss_cold"],
21
+ ...(input.cost === undefined ? {} : { cashUsd: input.cost }),
22
+ window: 0,
23
+ subscriptionUnitCalls: 0,
24
+ classifierUsd: 0,
25
+ classifierWindow: 0,
26
+ failoverUsd: 0,
27
+ failoverWindow: 0,
28
+ switchMissTokens: 0,
29
+ taxCashUsd: 0,
30
+ taxWindow: 0,
31
+ taxApiEquivalentUsd: 0,
32
+ switchMissPremiumUsd: 0,
33
+ stickyCounterfactuals: []
34
+ },
12
35
  status: input.status ?? "succeeded",
13
36
  effectiveModel: input.model ?? "openai/gpt-5.5",
14
37
  provider: input.provider ?? "openai",
@@ -23,7 +46,8 @@ function inspection(input) {
23
46
  cost: {
24
47
  ...(input.cost !== undefined ? { estimateUsd: input.cost } : {}),
25
48
  unknownUsage: false,
26
- unknownCost: input.unknownCost ?? false
49
+ unknownCost: input.unknownCost ?? false,
50
+ switchMissPremiumUsd: 0
27
51
  },
28
52
  timing: {
29
53
  startedAt: input.startedAt ?? "2026-07-27T10:00:00.000Z",
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,65 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import test from "node:test";
6
+ import { ProviderModuleRegistry } from "@velum-labs/routekit-provider-core";
7
+ import { fakeOpenAi } from "@velum-labs/routekit-provider-fake-openai";
8
+ import { startRouteKitDaemon } from "../index.js";
9
+ import { installProviderModulesForTest, providerModules } from "../provider-modules.js";
10
+ test("production daemon module catalog includes first-party clouds but no fixtures", () => {
11
+ const ids = providerModules.list().map((module) => module.id);
12
+ for (const id of [
13
+ "openai",
14
+ "anthropic",
15
+ "bedrock",
16
+ "google",
17
+ "openrouter",
18
+ "cliproxy",
19
+ "claude-code",
20
+ "codex",
21
+ "openai-compatible",
22
+ "custom",
23
+ "openai-azure",
24
+ "google-vertex"
25
+ ]) {
26
+ assert.ok(ids.includes(id), `missing provider module ${id}`);
27
+ }
28
+ assert.equal(ids.includes("fake-openai"), false);
29
+ });
30
+ test("fake provider chats through the daemon without config-core registration", async () => {
31
+ const root = mkdtempSync(join(tmpdir(), "routekit-fake-provider-"));
32
+ const restoreProviderModules = installProviderModulesForTest(new ProviderModuleRegistry([...providerModules.list(), fakeOpenAi]));
33
+ const configPath = join(root, "router.yaml");
34
+ writeFileSync(configPath, ["sources:", " fixture:", " use: fake-openai", "defaultModel: fixture/chat-model", ""].join("\n"));
35
+ const daemon = await startRouteKitDaemon({
36
+ packageVersion: "1.4.0-test",
37
+ stateHome: join(root, "state"),
38
+ configPath,
39
+ port: 0,
40
+ portless: false,
41
+ env: { HOME: root, ROUTEKIT_HOME: join(root, "state"), ROUTEKIT_PORTLESS: "0" }
42
+ });
43
+ try {
44
+ const dataToken = readFileSync(daemon.record.authTokenFile, "utf8").trim();
45
+ const response = await fetch(`${daemon.dataUrl}/v1/chat/completions`, {
46
+ method: "POST",
47
+ headers: {
48
+ authorization: `Bearer ${dataToken}`,
49
+ "content-type": "application/json"
50
+ },
51
+ body: JSON.stringify({
52
+ model: "fixture/chat-model",
53
+ messages: [{ role: "user", content: "hi" }]
54
+ })
55
+ });
56
+ assert.equal(response.status, 200);
57
+ const body = (await response.json());
58
+ assert.equal(body.choices[0]?.message.content, "fake-openai");
59
+ }
60
+ finally {
61
+ await daemon.close();
62
+ restoreProviderModules();
63
+ rmSync(root, { recursive: true, force: true });
64
+ }
65
+ });
@@ -0,0 +1 @@
1
+ export {};