@vellumai/credential-executor 0.10.7 → 0.10.8-dev.202607102228.5945895

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 (65) hide show
  1. package/Dockerfile +1 -1
  2. package/node_modules/@vellumai/service-contracts/package.json +1 -2
  3. package/node_modules/@vellumai/service-contracts/src/__tests__/attachment-naming.test.ts +104 -0
  4. package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +0 -2
  5. package/node_modules/@vellumai/service-contracts/src/attachment-naming.ts +118 -0
  6. package/node_modules/@vellumai/service-contracts/src/credential-rpc.ts +3 -5
  7. package/node_modules/@vellumai/service-contracts/src/index.ts +2 -4
  8. package/node_modules/@vellumai/service-contracts/src/rpc.ts +4 -447
  9. package/package.json +2 -3
  10. package/src/__tests__/bulk-set-credentials.test.ts +1 -1
  11. package/src/__tests__/local-standalone.test.ts +5 -36
  12. package/src/__tests__/managed-integration.test.ts +112 -91
  13. package/src/__tests__/managed-reconnect.test.ts +2 -2
  14. package/src/__tests__/transport.test.ts +23 -27
  15. package/src/cli.ts +1 -1
  16. package/src/index.ts +8 -88
  17. package/src/main.ts +228 -340
  18. package/src/paths.ts +4 -20
  19. package/src/server.ts +52 -469
  20. package/node_modules/@vellumai/service-contracts/src/__tests__/grants.test.ts +0 -686
  21. package/node_modules/@vellumai/service-contracts/src/grants.ts +0 -184
  22. package/node_modules/@vellumai/service-contracts/src/rendering.ts +0 -135
  23. package/src/__tests__/command-executor.test.ts +0 -1879
  24. package/src/__tests__/command-validator.test.ts +0 -1405
  25. package/src/__tests__/command-workspace.test.ts +0 -1050
  26. package/src/__tests__/grant-store.test.ts +0 -689
  27. package/src/__tests__/http-executor.test.ts +0 -1336
  28. package/src/__tests__/http-policy.test.ts +0 -1069
  29. package/src/__tests__/local-materializers.test.ts +0 -860
  30. package/src/__tests__/local-token-refresh.test.ts +0 -361
  31. package/src/__tests__/manage-secure-command-tool.test.ts +0 -134
  32. package/src/__tests__/managed-lazy-getters.test.ts +0 -359
  33. package/src/__tests__/managed-materializers.test.ts +0 -1028
  34. package/src/__tests__/managed-rejection.test.ts +0 -43
  35. package/src/__tests__/toolstore.test.ts +0 -773
  36. package/src/audit/store.ts +0 -188
  37. package/src/commands/auth-adapters.ts +0 -169
  38. package/src/commands/egress-hooks.ts +0 -203
  39. package/src/commands/executor.ts +0 -1155
  40. package/src/commands/output-scan.ts +0 -157
  41. package/src/commands/profiles.ts +0 -286
  42. package/src/commands/validator.ts +0 -702
  43. package/src/commands/workspace.ts +0 -550
  44. package/src/grants/index.ts +0 -17
  45. package/src/grants/persistent-store.ts +0 -309
  46. package/src/grants/rpc-handlers.ts +0 -293
  47. package/src/grants/temporary-store.ts +0 -289
  48. package/src/http/audit.ts +0 -84
  49. package/src/http/executor.ts +0 -684
  50. package/src/http/path-template.ts +0 -245
  51. package/src/http/policy.ts +0 -238
  52. package/src/http/response-filter.ts +0 -233
  53. package/src/managed-errors.ts +0 -9
  54. package/src/managed-lazy-getters.ts +0 -106
  55. package/src/managed-main.ts +0 -822
  56. package/src/materializers/local-oauth-lookup.ts +0 -98
  57. package/src/materializers/local-token-refresh.ts +0 -287
  58. package/src/materializers/local.ts +0 -316
  59. package/src/materializers/managed-platform.ts +0 -295
  60. package/src/subjects/local.ts +0 -177
  61. package/src/subjects/managed.ts +0 -311
  62. package/src/subjects/policy.ts +0 -79
  63. package/src/toolstore/integrity.ts +0 -94
  64. package/src/toolstore/manifest.ts +0 -154
  65. package/src/toolstore/publish.ts +0 -571
@@ -1,359 +0,0 @@
1
- /**
2
- * Tests for the managed CES lazy API key getter pattern.
3
- *
4
- * Exercises the production `buildLazyGetters` from `managed-lazy-getters.ts`
5
- * directly, ensuring regressions in key precedence, lazy resolution, or
6
- * graceful degradation are caught by these tests.
7
- */
8
-
9
- import { describe, expect, test } from "bun:test";
10
-
11
- import {
12
- applyManagedCredentialRefs,
13
- buildLazyGetters,
14
- type ApiKeyRef,
15
- type AssistantIdRef,
16
- } from "../managed-lazy-getters.js";
17
-
18
- // ---------------------------------------------------------------------------
19
- // applyManagedCredentialRefs — fail-closed overwrite across sessions
20
- // ---------------------------------------------------------------------------
21
-
22
- describe("applyManagedCredentialRefs", () => {
23
- test("overwrites both refs with the provided values", () => {
24
- const apiKeyRef: ApiKeyRef = { current: "old-key" };
25
- const assistantIdRef: AssistantIdRef = { current: "ast_old" };
26
-
27
- applyManagedCredentialRefs(apiKeyRef, assistantIdRef, "new-key", "ast_new");
28
-
29
- expect(apiKeyRef.current).toBe("new-key");
30
- expect(assistantIdRef.current).toBe("ast_new");
31
- });
32
-
33
- test("clears a stale assistant ID when the new value is omitted", () => {
34
- // A new session (or an API-key-only update) that does not carry an
35
- // assistant ID must not inherit the previous session's ID.
36
- const apiKeyRef: ApiKeyRef = { current: "prev-key" };
37
- const assistantIdRef: AssistantIdRef = { current: "ast_prev" };
38
-
39
- applyManagedCredentialRefs(
40
- apiKeyRef,
41
- assistantIdRef,
42
- "rotated-key",
43
- undefined,
44
- );
45
-
46
- expect(apiKeyRef.current).toBe("rotated-key");
47
- expect(assistantIdRef.current).toBe("");
48
- });
49
-
50
- test("clears a stale API key when the new value is omitted", () => {
51
- const apiKeyRef: ApiKeyRef = { current: "prev-key" };
52
- const assistantIdRef: AssistantIdRef = { current: "ast_prev" };
53
-
54
- applyManagedCredentialRefs(apiKeyRef, assistantIdRef, undefined, undefined);
55
-
56
- expect(apiKeyRef.current).toBe("");
57
- expect(assistantIdRef.current).toBe("");
58
- });
59
-
60
- test("lazy getters fail closed after a reconnect that omits the ID", () => {
61
- const apiKeyRef: ApiKeyRef = { current: "session1-key" };
62
- const assistantIdRef: AssistantIdRef = { current: "ast_session1" };
63
- const { getManagedMaterializerOptions } = buildLazyGetters({
64
- platformBaseUrl: "https://api.vellum.ai",
65
- assistantIdRef,
66
- apiKeyRef,
67
- });
68
-
69
- // A reconnecting session provides a key but no assistant ID.
70
- applyManagedCredentialRefs(
71
- apiKeyRef,
72
- assistantIdRef,
73
- "session2-key",
74
- undefined,
75
- );
76
-
77
- // Materialization must not proceed with the prior session's assistant ID.
78
- expect(getManagedMaterializerOptions()).toBeUndefined();
79
- });
80
- });
81
-
82
- // ---------------------------------------------------------------------------
83
- // Before API key arrives
84
- // ---------------------------------------------------------------------------
85
-
86
- describe("managed lazy getters — before API key arrives", () => {
87
- test("apiKeyRef starts empty and managed subject options are undefined", () => {
88
- const apiKeyRef: ApiKeyRef = { current: "" };
89
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
90
- const { getManagedSubjectOptions } = buildLazyGetters({
91
- platformBaseUrl: "https://api.vellum.ai",
92
- assistantIdRef,
93
- apiKeyRef,
94
- });
95
-
96
- expect(apiKeyRef.current).toBe("");
97
- expect(getManagedSubjectOptions()).toBeUndefined();
98
- });
99
-
100
- test("apiKeyRef starts empty and managed materializer options are undefined", () => {
101
- const apiKeyRef: ApiKeyRef = { current: "" };
102
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
103
- const { getManagedMaterializerOptions } = buildLazyGetters({
104
- platformBaseUrl: "https://api.vellum.ai",
105
- assistantIdRef,
106
- apiKeyRef,
107
- });
108
-
109
- expect(getManagedMaterializerOptions()).toBeUndefined();
110
- });
111
-
112
- test("getAssistantApiKey returns empty string when ref is empty and no env var", () => {
113
- const apiKeyRef: ApiKeyRef = { current: "" };
114
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
115
- const { getAssistantApiKey } = buildLazyGetters({
116
- platformBaseUrl: "https://api.vellum.ai",
117
- assistantIdRef,
118
- apiKeyRef,
119
- });
120
-
121
- expect(getAssistantApiKey()).toBe("");
122
- });
123
- });
124
-
125
- // ---------------------------------------------------------------------------
126
- // After API key arrives via handshake
127
- // ---------------------------------------------------------------------------
128
-
129
- describe("managed lazy getters — after API key arrives via handshake", () => {
130
- test("setting apiKeyRef.current enables managed subject options", () => {
131
- const apiKeyRef: ApiKeyRef = { current: "" };
132
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
133
- const { getManagedSubjectOptions } = buildLazyGetters({
134
- platformBaseUrl: "https://api.vellum.ai",
135
- assistantIdRef,
136
- apiKeyRef,
137
- });
138
-
139
- expect(getManagedSubjectOptions()).toBeUndefined();
140
-
141
- apiKeyRef.current = "vak_test_key_12345";
142
-
143
- const opts = getManagedSubjectOptions();
144
- expect(opts).toBeDefined();
145
- expect(opts!.platformBaseUrl).toBe("https://api.vellum.ai");
146
- expect(opts!.assistantApiKey).toBe("vak_test_key_12345");
147
- expect(opts!.assistantId).toBe("ast_abc123");
148
- });
149
-
150
- test("setting apiKeyRef.current enables managed materializer options", () => {
151
- const apiKeyRef: ApiKeyRef = { current: "" };
152
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
153
- const { getManagedMaterializerOptions } = buildLazyGetters({
154
- platformBaseUrl: "https://api.vellum.ai",
155
- assistantIdRef,
156
- apiKeyRef,
157
- });
158
-
159
- expect(getManagedMaterializerOptions()).toBeUndefined();
160
-
161
- apiKeyRef.current = "vak_test_key_12345";
162
-
163
- const opts = getManagedMaterializerOptions();
164
- expect(opts).toBeDefined();
165
- expect(opts!.platformBaseUrl).toBe("https://api.vellum.ai");
166
- expect(opts!.assistantApiKey).toBe("vak_test_key_12345");
167
- expect(opts!.assistantId).toBe("ast_abc123");
168
- });
169
-
170
- test("returned options contain the exact key from the ref (not a stale copy)", () => {
171
- const apiKeyRef: ApiKeyRef = { current: "" };
172
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
173
- const { getManagedSubjectOptions, getManagedMaterializerOptions } =
174
- buildLazyGetters({
175
- platformBaseUrl: "https://api.vellum.ai",
176
- assistantIdRef,
177
- apiKeyRef,
178
- });
179
-
180
- apiKeyRef.current = "vak_key_v1";
181
- expect(getManagedSubjectOptions()!.assistantApiKey).toBe("vak_key_v1");
182
- expect(getManagedMaterializerOptions()!.assistantApiKey).toBe("vak_key_v1");
183
-
184
- apiKeyRef.current = "vak_key_v2";
185
- expect(getManagedSubjectOptions()!.assistantApiKey).toBe("vak_key_v2");
186
- expect(getManagedMaterializerOptions()!.assistantApiKey).toBe("vak_key_v2");
187
- });
188
- });
189
-
190
- // ---------------------------------------------------------------------------
191
- // Lazy resolution timing
192
- // ---------------------------------------------------------------------------
193
-
194
- describe("managed lazy getters — lazy resolution timing", () => {
195
- test("handlers built before key arrives resolve the key at call time", () => {
196
- const apiKeyRef: ApiKeyRef = { current: "" };
197
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
198
-
199
- const { getManagedSubjectOptions, getManagedMaterializerOptions } =
200
- buildLazyGetters({
201
- platformBaseUrl: "https://api.vellum.ai",
202
- assistantIdRef,
203
- apiKeyRef,
204
- });
205
-
206
- // At registration time: no key yet
207
- expect(getManagedSubjectOptions()).toBeUndefined();
208
- expect(getManagedMaterializerOptions()).toBeUndefined();
209
-
210
- // Later: handshake delivers the key
211
- apiKeyRef.current = "vak_late_arriving_key";
212
-
213
- // Same getter functions now return valid options
214
- expect(getManagedSubjectOptions()).toBeDefined();
215
- expect(getManagedMaterializerOptions()).toBeDefined();
216
- expect(getManagedSubjectOptions()!.assistantApiKey).toBe(
217
- "vak_late_arriving_key",
218
- );
219
- });
220
-
221
- test("deps object with getter properties resolves lazily (mirrors httpDeps pattern)", () => {
222
- const apiKeyRef: ApiKeyRef = { current: "" };
223
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
224
- const { getManagedSubjectOptions, getManagedMaterializerOptions } =
225
- buildLazyGetters({
226
- platformBaseUrl: "https://api.vellum.ai",
227
- assistantIdRef,
228
- apiKeyRef,
229
- });
230
-
231
- // Build a deps object with getters, mirroring managed-main.ts httpDeps
232
- const httpDeps = {
233
- get managedSubjectOptions() {
234
- return getManagedSubjectOptions();
235
- },
236
- get managedMaterializerOptions() {
237
- return getManagedMaterializerOptions();
238
- },
239
- };
240
-
241
- // Before key: both undefined
242
- expect(httpDeps.managedSubjectOptions).toBeUndefined();
243
- expect(httpDeps.managedMaterializerOptions).toBeUndefined();
244
-
245
- // After key: both resolved
246
- apiKeyRef.current = "vak_lazy_key";
247
- expect(httpDeps.managedSubjectOptions).toBeDefined();
248
- expect(httpDeps.managedSubjectOptions!.assistantApiKey).toBe(
249
- "vak_lazy_key",
250
- );
251
- expect(httpDeps.managedMaterializerOptions).toBeDefined();
252
- expect(httpDeps.managedMaterializerOptions!.assistantApiKey).toBe(
253
- "vak_lazy_key",
254
- );
255
- });
256
-
257
- test("env var fallback is used when ref is empty", () => {
258
- const apiKeyRef: ApiKeyRef = { current: "" };
259
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
260
- const { getAssistantApiKey, getManagedSubjectOptions } = buildLazyGetters({
261
- platformBaseUrl: "https://api.vellum.ai",
262
- assistantIdRef,
263
- apiKeyRef,
264
- envApiKey: "vak_env_fallback",
265
- });
266
-
267
- expect(getAssistantApiKey()).toBe("vak_env_fallback");
268
- expect(getManagedSubjectOptions()).toBeDefined();
269
- expect(getManagedSubjectOptions()!.assistantApiKey).toBe(
270
- "vak_env_fallback",
271
- );
272
- });
273
-
274
- test("handshake-provided key takes precedence over env var", () => {
275
- const apiKeyRef: ApiKeyRef = { current: "" };
276
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
277
- const { getAssistantApiKey } = buildLazyGetters({
278
- platformBaseUrl: "https://api.vellum.ai",
279
- assistantIdRef,
280
- apiKeyRef,
281
- envApiKey: "vak_env_key",
282
- });
283
-
284
- expect(getAssistantApiKey()).toBe("vak_env_key");
285
-
286
- apiKeyRef.current = "vak_handshake_key";
287
- expect(getAssistantApiKey()).toBe("vak_handshake_key");
288
- });
289
- });
290
-
291
- // ---------------------------------------------------------------------------
292
- // Missing required fields -> undefined (graceful degradation)
293
- // ---------------------------------------------------------------------------
294
-
295
- describe("managed lazy getters — missing platform config fields", () => {
296
- test("missing platformBaseUrl returns undefined even with API key", () => {
297
- const apiKeyRef: ApiKeyRef = { current: "vak_test_key" };
298
- const assistantIdRef: AssistantIdRef = { current: "ast_abc123" };
299
- const { getManagedSubjectOptions, getManagedMaterializerOptions } =
300
- buildLazyGetters({
301
- platformBaseUrl: "",
302
- assistantIdRef,
303
- apiKeyRef,
304
- });
305
-
306
- expect(getManagedSubjectOptions()).toBeUndefined();
307
- expect(getManagedMaterializerOptions()).toBeUndefined();
308
- });
309
-
310
- test("missing assistantId returns undefined even with API key", () => {
311
- const apiKeyRef: ApiKeyRef = { current: "vak_test_key" };
312
- const assistantIdRef: AssistantIdRef = { current: "" };
313
- const { getManagedSubjectOptions, getManagedMaterializerOptions } =
314
- buildLazyGetters({
315
- platformBaseUrl: "https://api.vellum.ai",
316
- assistantIdRef,
317
- apiKeyRef,
318
- });
319
-
320
- expect(getManagedSubjectOptions()).toBeUndefined();
321
- expect(getManagedMaterializerOptions()).toBeUndefined();
322
- });
323
-
324
- test("assistantIdRef updated after build enables options (warm-pool scenario)", () => {
325
- /**
326
- * Verifies that updating assistantIdRef.current after buildLazyGetters
327
- * makes previously-undefined options become defined — the core fix for
328
- * warm-pool pods where the assistant ID is empty at CES startup.
329
- */
330
-
331
- // GIVEN an API key is available but assistant ID is empty (warm-pool startup)
332
- const apiKeyRef: ApiKeyRef = { current: "vak_test_key" };
333
- const assistantIdRef: AssistantIdRef = { current: "" };
334
- const { getManagedSubjectOptions, getManagedMaterializerOptions } =
335
- buildLazyGetters({
336
- platformBaseUrl: "https://api.vellum.ai",
337
- assistantIdRef,
338
- apiKeyRef,
339
- });
340
-
341
- // WHEN options are checked before assistant ID arrives
342
- // THEN they are undefined
343
- expect(getManagedSubjectOptions()).toBeUndefined();
344
- expect(getManagedMaterializerOptions()).toBeUndefined();
345
-
346
- // WHEN the assistant ID arrives via handshake/RPC
347
- assistantIdRef.current = "ast_provisioned_123";
348
-
349
- // THEN the same getter functions now return valid options
350
- const subOpts = getManagedSubjectOptions();
351
- expect(subOpts).toBeDefined();
352
- expect(subOpts!.assistantId).toBe("ast_provisioned_123");
353
- expect(subOpts!.assistantApiKey).toBe("vak_test_key");
354
-
355
- const matOpts = getManagedMaterializerOptions();
356
- expect(matOpts).toBeDefined();
357
- expect(matOpts!.assistantId).toBe("ast_provisioned_123");
358
- });
359
- });