@slashfi/agents-sdk 0.16.0 → 0.18.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 (96) hide show
  1. package/dist/agent-definitions/auth.d.ts.map +1 -1
  2. package/dist/agent-definitions/auth.js +44 -11
  3. package/dist/agent-definitions/auth.js.map +1 -1
  4. package/dist/agent-definitions/integrations.d.ts.map +1 -1
  5. package/dist/agent-definitions/integrations.js +106 -45
  6. package/dist/agent-definitions/integrations.js.map +1 -1
  7. package/dist/agent-definitions/remote-registry.d.ts.map +1 -1
  8. package/dist/agent-definitions/remote-registry.js +174 -45
  9. package/dist/agent-definitions/remote-registry.js.map +1 -1
  10. package/dist/agent-definitions/secrets.d.ts.map +1 -1
  11. package/dist/agent-definitions/secrets.js +1 -4
  12. package/dist/agent-definitions/secrets.js.map +1 -1
  13. package/dist/agent-definitions/users.d.ts.map +1 -1
  14. package/dist/agent-definitions/users.js +14 -3
  15. package/dist/agent-definitions/users.js.map +1 -1
  16. package/dist/define-config.d.ts +125 -0
  17. package/dist/define-config.d.ts.map +1 -0
  18. package/dist/define-config.js +75 -0
  19. package/dist/define-config.js.map +1 -0
  20. package/dist/define.d.ts +11 -2
  21. package/dist/define.d.ts.map +1 -1
  22. package/dist/define.js +57 -26
  23. package/dist/define.js.map +1 -1
  24. package/dist/events.d.ts +133 -0
  25. package/dist/events.d.ts.map +1 -0
  26. package/dist/events.js +57 -0
  27. package/dist/events.js.map +1 -0
  28. package/dist/index.d.ts +16 -8
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +21 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/integration-interface.d.ts +3 -3
  33. package/dist/integration-interface.d.ts.map +1 -1
  34. package/dist/integration-interface.js +29 -21
  35. package/dist/integration-interface.js.map +1 -1
  36. package/dist/integrations-store.d.ts +2 -2
  37. package/dist/integrations-store.d.ts.map +1 -1
  38. package/dist/integrations-store.js +3 -3
  39. package/dist/integrations-store.js.map +1 -1
  40. package/dist/jwt.d.ts.map +1 -1
  41. package/dist/jwt.js +7 -5
  42. package/dist/jwt.js.map +1 -1
  43. package/dist/key-manager.d.ts.map +1 -1
  44. package/dist/key-manager.js +5 -3
  45. package/dist/key-manager.js.map +1 -1
  46. package/dist/oidc-signin.d.ts +32 -0
  47. package/dist/oidc-signin.d.ts.map +1 -0
  48. package/dist/oidc-signin.js +138 -0
  49. package/dist/oidc-signin.js.map +1 -0
  50. package/dist/registry-consumer.d.ts +104 -0
  51. package/dist/registry-consumer.d.ts.map +1 -0
  52. package/dist/registry-consumer.js +230 -0
  53. package/dist/registry-consumer.js.map +1 -0
  54. package/dist/registry.d.ts +5 -0
  55. package/dist/registry.d.ts.map +1 -1
  56. package/dist/registry.js +76 -4
  57. package/dist/registry.js.map +1 -1
  58. package/dist/secret-collection.d.ts.map +1 -1
  59. package/dist/secret-collection.js.map +1 -1
  60. package/dist/server.d.ts +3 -0
  61. package/dist/server.d.ts.map +1 -1
  62. package/dist/server.js +222 -27
  63. package/dist/server.js.map +1 -1
  64. package/dist/test-utils/mock-oidc-server.d.ts +36 -0
  65. package/dist/test-utils/mock-oidc-server.d.ts.map +1 -0
  66. package/dist/test-utils/mock-oidc-server.js +96 -0
  67. package/dist/test-utils/mock-oidc-server.js.map +1 -0
  68. package/dist/types.d.ts +106 -0
  69. package/dist/types.d.ts.map +1 -1
  70. package/package.json +6 -1
  71. package/src/agent-definitions/auth.ts +106 -38
  72. package/src/agent-definitions/integrations.ts +201 -73
  73. package/src/agent-definitions/remote-registry.ts +262 -65
  74. package/src/agent-definitions/secrets.ts +22 -8
  75. package/src/agent-definitions/users.ts +16 -4
  76. package/src/cli.ts +293 -0
  77. package/src/codegen.test.ts +527 -0
  78. package/src/codegen.ts +1348 -0
  79. package/src/consumer.test.ts +536 -0
  80. package/src/define-config.ts +205 -0
  81. package/src/define.ts +134 -46
  82. package/src/events.ts +237 -0
  83. package/src/index.ts +107 -8
  84. package/src/integration-interface.ts +52 -28
  85. package/src/integrations-store.ts +9 -5
  86. package/src/jwt.ts +48 -19
  87. package/src/key-manager.test.ts +22 -13
  88. package/src/key-manager.ts +8 -10
  89. package/src/oidc-signin.ts +223 -0
  90. package/src/registry-consumer.ts +413 -0
  91. package/src/registry.ts +115 -9
  92. package/src/secret-collection.ts +2 -1
  93. package/src/server.test.ts +304 -238
  94. package/src/server.ts +371 -69
  95. package/src/test-utils/mock-oidc-server.ts +123 -0
  96. package/src/types.ts +172 -18
package/src/index.ts CHANGED
@@ -83,6 +83,11 @@ export type {
83
83
  ToolSchema,
84
84
  ToolSelectionContext,
85
85
  IntegrationConfig,
86
+ ApiKeySecurityScheme,
87
+ HttpSecurityScheme,
88
+ NoneSecurityScheme,
89
+ OAuth2SecurityScheme,
90
+ SecurityScheme,
86
91
  IntegrationMethods,
87
92
  IntegrationMethodResult,
88
93
  IntegrationMethodContext,
@@ -92,15 +97,48 @@ export type {
92
97
 
93
98
  // Define functions
94
99
  export { defineAgent, defineTool } from "./define.js";
95
- export type { DefineAgentOptions, DefineToolOptions } from "./define.js";
100
+ export type { DefineAgentOptions, DefineToolOptions, AgentWithHooks, ToolWithHooks } from "./define.js";
96
101
 
97
102
  // Registry
98
103
  export { createAgentRegistry } from "./registry.js";
99
- export type { AgentRegistry, AgentRegistryOptions, RegistryMiddleware } from "./registry.js";
104
+ export type {
105
+ AgentRegistry,
106
+ AgentRegistryOptions,
107
+ RegistryMiddleware,
108
+ } from "./registry.js";
109
+
110
+ // Events
111
+ export { createEventBus } from "./events.js";
112
+ export type {
113
+ EventBus,
114
+ EventType,
115
+ EventCallback,
116
+ AgentEvent,
117
+ ToolCallEvent,
118
+ ToolResultEvent,
119
+ ToolErrorEvent,
120
+ StepEvent,
121
+ InvokeEvent,
122
+ EventMap,
123
+ } from "./events.js";
100
124
 
101
125
  // Server
102
- export { createAgentServer, detectAuth, resolveAuth, canSeeAgent } from "./server.js";
103
- export type { AgentServer, AgentServerOptions, AuthConfig, OAuthIdentityProvider, ResolvedAuth, TrustedIssuer } from "./server.js";
126
+ export {
127
+ createAgentServer,
128
+ detectAuth,
129
+ resolveAuth,
130
+ canSeeAgent,
131
+ } from "./server.js";
132
+ export type {
133
+ AgentServer,
134
+ AgentServerOptions,
135
+ AuthConfig,
136
+ OAuthIdentityProvider,
137
+ ResolvedAuth,
138
+ TrustedIssuer,
139
+ } from "./server.js";
140
+ export { createOIDCSignIn } from "./oidc-signin.js";
141
+ export type { OIDCProviderConfig, OIDCSignInHandler } from "./oidc-signin.js";
104
142
 
105
143
  // Secret Collection
106
144
  export {
@@ -147,8 +185,23 @@ export type {
147
185
  export { encryptSecret, decryptSecret } from "./crypto.js";
148
186
 
149
187
  // JWT
150
- export { signJwt, verifyJwt, signJwtES256, verifyJwtLocal, verifyJwtFromIssuer, generateSigningKey, exportSigningKey, importSigningKey, buildJwks } from "./jwt.js";
151
- export type { JwtPayload, AgentJwtPayload, SigningKey, ExportedKeyPair } from "./jwt.js";
188
+ export {
189
+ signJwt,
190
+ verifyJwt,
191
+ signJwtES256,
192
+ verifyJwtLocal,
193
+ verifyJwtFromIssuer,
194
+ generateSigningKey,
195
+ exportSigningKey,
196
+ importSigningKey,
197
+ buildJwks,
198
+ } from "./jwt.js";
199
+ export type {
200
+ JwtPayload,
201
+ AgentJwtPayload,
202
+ SigningKey,
203
+ ExportedKeyPair,
204
+ } from "./jwt.js";
152
205
 
153
206
  // Postgres Secret Store
154
207
 
@@ -177,7 +230,6 @@ export type {
177
230
  TokenExchangeResult,
178
231
  } from "./agent-definitions/integrations.js";
179
232
 
180
-
181
233
  // Remote Registry
182
234
  export { createRemoteRegistryAgent } from "./agent-definitions/remote-registry.js";
183
235
  export type { RemoteRegistryAgentOptions } from "./agent-definitions/remote-registry.js";
@@ -195,4 +247,51 @@ export type {
195
247
  export * from "./integrations-store.js";
196
248
  export * from "./integration-interface.js";
197
249
  export type { ContextFactory } from "./registry.js";
198
- export { createKeyManager, type KeyManager, type KeyStore, type KeyManagerOptions, type StoredKey, type KeyStatus } from "./key-manager.js";
250
+ export {
251
+ createKeyManager,
252
+ type KeyManager,
253
+ type KeyStore,
254
+ type KeyManagerOptions,
255
+ type StoredKey,
256
+ type KeyStatus,
257
+ } from "./key-manager.js";
258
+
259
+ // Config & Consumer
260
+ export {
261
+ normalizeRef,
262
+ normalizeRegistry,
263
+ isSecretUrl,
264
+ isSecretUri,
265
+ } from "./define-config.js";
266
+ export type {
267
+ RegistryAuth,
268
+ RegistryEntry,
269
+ RefConfig,
270
+ RefEntry,
271
+ ConsumerConfig,
272
+ ResolvedRegistry,
273
+ ResolvedRef,
274
+ ResolvedConfig,
275
+ } from "./define-config.js";
276
+
277
+ export { createRegistryConsumer } from "./registry-consumer.js";
278
+ export type {
279
+ RegistryConsumer,
280
+ RegistryConsumerOptions,
281
+ RegistryConfiguration,
282
+ AgentListing,
283
+ SecretResolver,
284
+ } from "./registry-consumer.js";
285
+
286
+ // Codegen (exported from separate entrypoint — see ./codegen.ts)
287
+ // TODO: Re-enable once codegen.ts type errors are fixed
288
+ // export { codegen, useAgent, listAgentTools } from "./codegen.js";
289
+ // export type {
290
+ // CodegenOptions,
291
+ // CodegenResult,
292
+ // CodegenManifest,
293
+ // McpToolDefinition,
294
+ // McpServerInfo,
295
+ // McpTransport,
296
+ // ServerSource,
297
+ // } from "./codegen.js";
@@ -5,16 +5,16 @@
5
5
  * They are all internal visibility and only callable by @integrations.
6
6
  */
7
7
 
8
- import { defineTool } from './define.js';
9
- import type { IntegrationsStore } from './integrations-store.js';
10
- import type { ToolDefinition, ToolContext } from './types.js';
8
+ import { defineTool } from "./define.js";
9
+ import type { IntegrationsStore } from "./integrations-store.js";
10
+ import type { ToolContext, ToolDefinition } from "./types.js";
11
11
 
12
12
  export interface IntegrationDefinition {
13
13
  id: string;
14
14
  agentPath: string;
15
15
  name: string;
16
16
  description: string;
17
- type: 'oauth' | 'credentials' | 'config';
17
+ type: "oauth" | "credentials" | "config";
18
18
  configSchema?: Record<string, unknown>;
19
19
  }
20
20
 
@@ -22,23 +22,36 @@ export interface IntegrationInterfaceConfig {
22
22
  agentPath: string;
23
23
  store: IntegrationsStore;
24
24
  discover: () => Promise<IntegrationDefinition[]>;
25
- setup: (config: Record<string, unknown>, ctx: ToolContext) => Promise<{ success: boolean; integrationId?: string; oauthUrl?: string; error?: string }>;
26
- connect?: (integrationId: string, ctx: ToolContext) => Promise<{ success: boolean; error?: string }>;
25
+ setup: (
26
+ config: Record<string, unknown>,
27
+ ctx: ToolContext,
28
+ ) => Promise<{
29
+ success: boolean;
30
+ integrationId?: string;
31
+ oauthUrl?: string;
32
+ error?: string;
33
+ }>;
34
+ connect?: (
35
+ integrationId: string,
36
+ ctx: ToolContext,
37
+ ) => Promise<{ success: boolean; error?: string }>;
27
38
  }
28
39
 
29
40
  /**
30
41
  * Create the standard _integration tools for an agent.
31
42
  * Returns an array of ToolDefinitions to include in the agent's tools.
32
43
  */
33
- export function createIntegrationTools(config: IntegrationInterfaceConfig): ToolDefinition<ToolContext>[] {
44
+ export function createIntegrationTools(
45
+ config: IntegrationInterfaceConfig,
46
+ ): ToolDefinition<ToolContext>[] {
34
47
  const { agentPath, store, discover, setup, connect } = config;
35
48
 
36
49
  const discoverTool = defineTool({
37
- name: 'discover_integrations',
50
+ name: "discover_integrations",
38
51
  description: `Discover available integrations for ${agentPath}.`,
39
- visibility: 'internal' as const,
52
+ visibility: "internal" as const,
40
53
  inputSchema: {
41
- type: 'object' as const,
54
+ type: "object" as const,
42
55
  properties: {},
43
56
  },
44
57
  execute: async () => {
@@ -48,17 +61,20 @@ export function createIntegrationTools(config: IntegrationInterfaceConfig): Tool
48
61
  });
49
62
 
50
63
  const setupTool = defineTool({
51
- name: 'setup_integration',
64
+ name: "setup_integration",
52
65
  description: `Set up a new integration for ${agentPath}.`,
53
- visibility: 'internal' as const,
66
+ visibility: "internal" as const,
54
67
  inputSchema: {
55
- type: 'object' as const,
68
+ type: "object" as const,
56
69
  properties: {
57
- config: { type: 'object', description: 'Integration configuration' },
70
+ config: { type: "object", description: "Integration configuration" },
58
71
  },
59
- required: ['config'],
72
+ required: ["config"],
60
73
  },
61
- execute: async (input: { config: Record<string, unknown> }, ctx: ToolContext) => {
74
+ execute: async (
75
+ input: { config: Record<string, unknown> },
76
+ ctx: ToolContext,
77
+ ) => {
62
78
  const result = await setup(input.config, ctx);
63
79
  if (result.success && !result.oauthUrl) {
64
80
  // Direct setup (no OAuth needed) — create integration row
@@ -74,23 +90,26 @@ export function createIntegrationTools(config: IntegrationInterfaceConfig): Tool
74
90
  });
75
91
 
76
92
  const connectTool = defineTool({
77
- name: 'connect_integration',
93
+ name: "connect_integration",
78
94
  description: `Test or authorize a ${agentPath} integration connection.`,
79
- visibility: 'internal' as const,
95
+ visibility: "internal" as const,
80
96
  inputSchema: {
81
- type: 'object' as const,
97
+ type: "object" as const,
82
98
  properties: {
83
- integration_id: { type: 'string', description: 'Integration ID to connect' },
99
+ integration_id: {
100
+ type: "string",
101
+ description: "Integration ID to connect",
102
+ },
84
103
  },
85
- required: ['integration_id'],
104
+ required: ["integration_id"],
86
105
  },
87
106
  execute: async (input: { integration_id: string }, ctx: ToolContext) => {
88
107
  if (connect) {
89
108
  const result = await connect(input.integration_id, ctx);
90
109
  if (result.success) {
91
- await store.update(input.integration_id, { status: 'active' });
110
+ await store.update(input.integration_id, { status: "active" });
92
111
  } else {
93
- await store.update(input.integration_id, { status: 'error' });
112
+ await store.update(input.integration_id, { status: "error" });
94
113
  }
95
114
  return result;
96
115
  }
@@ -99,13 +118,13 @@ export function createIntegrationTools(config: IntegrationInterfaceConfig): Tool
99
118
  });
100
119
 
101
120
  const listTool = defineTool({
102
- name: 'list_integrations',
121
+ name: "list_integrations",
103
122
  description: `List installed integrations for ${agentPath}.`,
104
- visibility: 'internal' as const,
123
+ visibility: "internal" as const,
105
124
  inputSchema: {
106
- type: 'object' as const,
125
+ type: "object" as const,
107
126
  properties: {
108
- tenant_id: { type: 'string', description: 'Filter by tenant' },
127
+ tenant_id: { type: "string", description: "Filter by tenant" },
109
128
  },
110
129
  },
111
130
  execute: async (input: { tenant_id?: string }) => {
@@ -114,5 +133,10 @@ export function createIntegrationTools(config: IntegrationInterfaceConfig): Tool
114
133
  },
115
134
  });
116
135
 
117
- return [discoverTool, setupTool, connectTool, listTool] as ToolDefinition<ToolContext>[];
136
+ return [
137
+ discoverTool,
138
+ setupTool,
139
+ connectTool,
140
+ listTool,
141
+ ] as ToolDefinition<ToolContext>[];
118
142
  }
@@ -9,7 +9,7 @@ export interface Integration {
9
9
  id: string;
10
10
  agentPath: string;
11
11
  tenantId?: string;
12
- status: 'active' | 'disabled' | 'error';
12
+ status: "active" | "disabled" | "error";
13
13
  config: Record<string, unknown>;
14
14
  installedBy?: string;
15
15
  installedAt: number;
@@ -28,7 +28,10 @@ export interface IntegrationsStore {
28
28
  get(id: string): Promise<Integration | null>;
29
29
  list(tenantId?: string): Promise<Integration[]>;
30
30
  listByAgent(agentPath: string, tenantId?: string): Promise<Integration[]>;
31
- update(id: string, updates: Partial<Pick<Integration, 'status' | 'config' | 'updatedAt'>>): Promise<Integration | null>;
31
+ update(
32
+ id: string,
33
+ updates: Partial<Pick<Integration, "status" | "config" | "updatedAt">>,
34
+ ): Promise<Integration | null>;
32
35
  delete(id: string): Promise<boolean>;
33
36
  }
34
37
 
@@ -44,7 +47,7 @@ export function createInMemoryIntegrationsStore(): IntegrationsStore {
44
47
  id,
45
48
  agentPath: input.agentPath,
46
49
  tenantId: input.tenantId,
47
- status: 'active',
50
+ status: "active",
48
51
  config: input.config,
49
52
  installedBy: input.installedBy,
50
53
  installedAt: now,
@@ -60,12 +63,13 @@ export function createInMemoryIntegrationsStore(): IntegrationsStore {
60
63
 
61
64
  async list(tenantId?) {
62
65
  const all = Array.from(integrations.values());
63
- return tenantId ? all.filter(i => i.tenantId === tenantId) : all;
66
+ return tenantId ? all.filter((i) => i.tenantId === tenantId) : all;
64
67
  },
65
68
 
66
69
  async listByAgent(agentPath, tenantId?) {
67
70
  return Array.from(integrations.values()).filter(
68
- i => i.agentPath === agentPath && (!tenantId || i.tenantId === tenantId)
71
+ (i) =>
72
+ i.agentPath === agentPath && (!tenantId || i.tenantId === tenantId),
69
73
  );
70
74
  },
71
75
 
package/src/jwt.ts CHANGED
@@ -9,15 +9,14 @@
9
9
  */
10
10
 
11
11
  import {
12
+ type JWK,
13
+ type JWTPayload,
12
14
  SignJWT,
13
- jwtVerify,
14
- generateKeyPair,
15
+ createRemoteJWKSet,
15
16
  exportJWK,
17
+ generateKeyPair,
16
18
  importJWK,
17
- createRemoteJWKSet,
18
- type JWTPayload,
19
-
20
- type JWK,
19
+ jwtVerify,
21
20
  } from "jose";
22
21
 
23
22
  // ============================================
@@ -80,7 +79,9 @@ export interface ExportedKeyPair {
80
79
  * Generate a new ES256 signing key pair.
81
80
  */
82
81
  export async function generateSigningKey(kid?: string): Promise<SigningKey> {
83
- const { privateKey, publicKey } = await generateKeyPair("ES256", { extractable: true });
82
+ const { privateKey, publicKey } = await generateKeyPair("ES256", {
83
+ extractable: true,
84
+ });
84
85
  return {
85
86
  kid: kid ?? `key-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
86
87
  privateKey,
@@ -94,7 +95,9 @@ export async function generateSigningKey(kid?: string): Promise<SigningKey> {
94
95
  /**
95
96
  * Export a signing key to JWK format (for storage).
96
97
  */
97
- export async function exportSigningKey(key: SigningKey): Promise<ExportedKeyPair> {
98
+ export async function exportSigningKey(
99
+ key: SigningKey,
100
+ ): Promise<ExportedKeyPair> {
98
101
  const privateKeyJwk = await exportJWK(key.privateKey);
99
102
  const publicKeyJwk = await exportJWK(key.publicKey);
100
103
  return {
@@ -110,9 +113,17 @@ export async function exportSigningKey(key: SigningKey): Promise<ExportedKeyPair
110
113
  /**
111
114
  * Import a signing key from stored JWK format.
112
115
  */
113
- export async function importSigningKey(exported: ExportedKeyPair): Promise<SigningKey> {
114
- const privateKey = await importJWK(exported.privateKeyJwk, exported.alg) as CryptoKey;
115
- const publicKey = await importJWK(exported.publicKeyJwk, exported.alg) as CryptoKey;
116
+ export async function importSigningKey(
117
+ exported: ExportedKeyPair,
118
+ ): Promise<SigningKey> {
119
+ const privateKey = (await importJWK(
120
+ exported.privateKeyJwk,
121
+ exported.alg,
122
+ )) as CryptoKey;
123
+ const publicKey = (await importJWK(
124
+ exported.publicKeyJwk,
125
+ exported.alg,
126
+ )) as CryptoKey;
116
127
  return {
117
128
  kid: exported.kid,
118
129
  privateKey,
@@ -148,7 +159,10 @@ export async function buildJwks(keys: SigningKey[]): Promise<{ keys: JWK[] }> {
148
159
  * Sign a JWT with ES256 using the server's private key.
149
160
  */
150
161
  export async function signJwtES256(
151
- payload: Omit<AgentJwtPayload, "iat" | "exp"> & { iat?: number; exp?: number },
162
+ payload: Omit<AgentJwtPayload, "iat" | "exp"> & {
163
+ iat?: number;
164
+ exp?: number;
165
+ },
152
166
  privateKey: CryptoKey,
153
167
  kid: string,
154
168
  issuer?: string,
@@ -202,7 +216,7 @@ export async function verifyJwtFromIssuer(
202
216
  issuerUrl: string,
203
217
  ): Promise<AgentJwtPayload | null> {
204
218
  try {
205
- const jwksUrl = issuerUrl.replace(/\/$/, "") + "/.well-known/jwks.json";
219
+ const jwksUrl = `${issuerUrl.replace(/\/$/, "")}/.well-known/jwks.json`;
206
220
  let jwks = jwksCache.get(jwksUrl);
207
221
  if (!jwks) {
208
222
  jwks = createRemoteJWKSet(new URL(jwksUrl));
@@ -234,19 +248,34 @@ function base64UrlDecode(str: string): Uint8Array {
234
248
 
235
249
  async function hmacSign(data: string, secret: string): Promise<Uint8Array> {
236
250
  const key = await crypto.subtle.importKey(
237
- "raw", encoder.encode(secret),
238
- { name: "HMAC", hash: "SHA-256" }, false, ["sign"],
251
+ "raw",
252
+ encoder.encode(secret),
253
+ { name: "HMAC", hash: "SHA-256" },
254
+ false,
255
+ ["sign"],
239
256
  );
240
257
  const sig = await crypto.subtle.sign("HMAC", key, encoder.encode(data));
241
258
  return new Uint8Array(sig);
242
259
  }
243
260
 
244
- async function hmacVerify(data: string, signature: Uint8Array, secret: string): Promise<boolean> {
261
+ async function hmacVerify(
262
+ data: string,
263
+ signature: Uint8Array,
264
+ secret: string,
265
+ ): Promise<boolean> {
245
266
  const key = await crypto.subtle.importKey(
246
- "raw", encoder.encode(secret),
247
- { name: "HMAC", hash: "SHA-256" }, false, ["verify"],
267
+ "raw",
268
+ encoder.encode(secret),
269
+ { name: "HMAC", hash: "SHA-256" },
270
+ false,
271
+ ["verify"],
272
+ );
273
+ return crypto.subtle.verify(
274
+ "HMAC",
275
+ key,
276
+ signature.buffer as ArrayBuffer,
277
+ encoder.encode(data),
248
278
  );
249
- return crypto.subtle.verify("HMAC", key, signature.buffer as ArrayBuffer, encoder.encode(data));
250
279
  }
251
280
 
252
281
  /** @deprecated Use AgentJwtPayload instead */
@@ -1,6 +1,11 @@
1
- import { describe, test, expect, afterEach } from "bun:test";
2
- import { createKeyManager, type KeyStore, type StoredKey, type KeyManager } from "./key-manager";
3
- import { jwtVerify, createLocalJWKSet } from "jose";
1
+ import { afterEach, describe, expect, test } from "bun:test";
2
+ import { createLocalJWKSet, jwtVerify } from "jose";
3
+ import {
4
+ type KeyManager,
5
+ type KeyStore,
6
+ type StoredKey,
7
+ createKeyManager,
8
+ } from "./key-manager";
4
9
 
5
10
  // In-memory KeyStore for testing (no DB needed)
6
11
  function createMemoryKeyStore(): KeyStore & { keys: StoredKey[] } {
@@ -76,9 +81,7 @@ describe("KeyManager", () => {
76
81
  const parts = token.split(".");
77
82
  expect(parts).toHaveLength(3);
78
83
 
79
- const payload = JSON.parse(
80
- Buffer.from(parts[1], "base64url").toString()
81
- );
84
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString());
82
85
  expect(payload.sub).toBe("test-service");
83
86
  expect(payload.iss).toBe("http://test:3000");
84
87
  expect(payload.exp - payload.iat).toBe(300); // default 5 min TTL
@@ -110,7 +113,7 @@ describe("KeyManager", () => {
110
113
 
111
114
  const token = await km.signJwt({ sub: "short-lived" });
112
115
  const payload = JSON.parse(
113
- Buffer.from(token.split(".")[1], "base64url").toString()
116
+ Buffer.from(token.split(".")[1], "base64url").toString(),
114
117
  );
115
118
  expect(payload.exp - payload.iat).toBe(60);
116
119
  });
@@ -126,9 +129,11 @@ describe("KeyManager", () => {
126
129
  checkIntervalMs: 60_000,
127
130
  });
128
131
 
129
- const initialKid = km.getJwks().keys.find(
130
- (k) => store.keys.find((sk) => sk.kid === k.kid)?.status === "active"
131
- )?.kid;
132
+ const initialKid = km
133
+ .getJwks()
134
+ .keys.find(
135
+ (k) => store.keys.find((sk) => sk.kid === k.kid)?.status === "active",
136
+ )?.kid;
132
137
 
133
138
  // Force rotation
134
139
  await km.rotate();
@@ -227,7 +232,7 @@ describe("KeyManager", () => {
227
232
  expect(failed).toBe(true);
228
233
  });
229
234
 
230
- // ---- Transaction tests ----
235
+ // ---- Transaction tests ----
231
236
 
232
237
  test("transaction: rotate is atomic (rollback on failure)", async () => {
233
238
  const store = createMemoryKeyStore();
@@ -241,10 +246,14 @@ describe("KeyManager", () => {
241
246
 
242
247
  // Monkey-patch insertKey to fail mid-transaction
243
248
  const origInsert = store.insertKey;
244
- store.insertKey = async () => { throw new Error("simulated failure"); };
249
+ store.insertKey = async () => {
250
+ throw new Error("simulated failure");
251
+ };
245
252
 
246
253
  // Rotation should fail, but state should be rolled back
247
- try { await km.rotate(); } catch {}
254
+ try {
255
+ await km.rotate();
256
+ } catch {}
248
257
 
249
258
  // Original key should still be active (not deprecated)
250
259
  const active = store.keys.filter((k) => k.status === "active");
@@ -13,13 +13,7 @@
13
13
  * - Signs JWTs with the active key
14
14
  */
15
15
 
16
- import {
17
- generateKeyPair,
18
- exportJWK,
19
- importJWK,
20
- SignJWT,
21
- type JWK,
22
- } from "jose";
16
+ import { type JWK, SignJWT, exportJWK, generateKeyPair, importJWK } from "jose";
23
17
 
24
18
  // ── Types ──
25
19
 
@@ -103,7 +97,9 @@ function generateKid(): string {
103
97
  }
104
98
 
105
99
  async function generateNewKey(keyLifetimeMs: number): Promise<StoredKey> {
106
- const { privateKey, publicKey } = await generateKeyPair(ALG, { extractable: true });
100
+ const { privateKey, publicKey } = await generateKeyPair(ALG, {
101
+ extractable: true,
102
+ });
107
103
  const kid = generateKid();
108
104
 
109
105
  const publicJwk = await exportJWK(publicKey);
@@ -127,13 +123,15 @@ async function generateNewKey(keyLifetimeMs: number): Promise<StoredKey> {
127
123
  }
128
124
 
129
125
  async function toCachedKey(stored: StoredKey): Promise<CachedKey> {
130
- const privateKey = await importJWK(stored.privateJwk, ALG) as CryptoKey;
126
+ const privateKey = (await importJWK(stored.privateJwk, ALG)) as CryptoKey;
131
127
  return { ...stored, privateKey };
132
128
  }
133
129
 
134
130
  // ── Key Manager ──
135
131
 
136
- export async function createKeyManager(opts: KeyManagerOptions): Promise<KeyManager> {
132
+ export async function createKeyManager(
133
+ opts: KeyManagerOptions,
134
+ ): Promise<KeyManager> {
137
135
  const {
138
136
  store,
139
137
  issuer,