@forestadmin/workflow-executor 1.12.0 → 1.14.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 (59) hide show
  1. package/README.md +4 -0
  2. package/dist/adapters/agent-client-agent-port.d.ts +1 -1
  3. package/dist/adapters/agent-client-agent-port.js +3 -3
  4. package/dist/adapters/ai-client-adapter.d.ts +5 -1
  5. package/dist/adapters/ai-client-adapter.js +4 -1
  6. package/dist/adapters/always-error-ai-model-port.d.ts +5 -1
  7. package/dist/adapters/always-error-ai-model-port.js +6 -1
  8. package/dist/adapters/server-ai-adapter.d.ts +5 -1
  9. package/dist/adapters/server-ai-adapter.js +4 -1
  10. package/dist/adapters/step-outcome-to-update-step-mapper.js +4 -1
  11. package/dist/build-workflow-executor.js +87 -2
  12. package/dist/crypto/credential-encryption.d.ts +10 -0
  13. package/dist/crypto/credential-encryption.js +75 -0
  14. package/dist/defaults.d.ts +1 -0
  15. package/dist/defaults.js +5 -2
  16. package/dist/errors.d.ts +18 -0
  17. package/dist/errors.js +50 -2
  18. package/dist/executors/mcp-step-executor.d.ts +7 -2
  19. package/dist/executors/mcp-step-executor.js +78 -14
  20. package/dist/executors/step-executor-factory.d.ts +1 -1
  21. package/dist/executors/step-executor-factory.js +24 -3
  22. package/dist/executors/trigger-record-action-step-executor.js +10 -4
  23. package/dist/http/executor-http-server.d.ts +12 -0
  24. package/dist/http/executor-http-server.js +90 -1
  25. package/dist/http/mcp-oauth-credentials.d.ts +24 -0
  26. package/dist/http/mcp-oauth-credentials.js +77 -0
  27. package/dist/index.d.ts +7 -1
  28. package/dist/index.js +10 -3
  29. package/dist/oauth/keyed-mutex.d.ts +5 -0
  30. package/dist/oauth/keyed-mutex.js +27 -0
  31. package/dist/oauth/refresh-grant.d.ts +15 -0
  32. package/dist/oauth/refresh-grant.js +112 -0
  33. package/dist/oauth/token-endpoint-url.d.ts +2 -0
  34. package/dist/oauth/token-endpoint-url.js +103 -0
  35. package/dist/oauth/token-service.d.ts +34 -0
  36. package/dist/oauth/token-service.js +172 -0
  37. package/dist/ports/agent-port.d.ts +1 -0
  38. package/dist/ports/ai-model-port.d.ts +5 -1
  39. package/dist/ports/mcp-oauth-credentials-store.d.ts +24 -0
  40. package/dist/ports/mcp-oauth-credentials-store.js +3 -0
  41. package/dist/ports/run-store.d.ts +1 -0
  42. package/dist/remote-tool-fetcher.d.ts +7 -2
  43. package/dist/remote-tool-fetcher.js +53 -6
  44. package/dist/runner.d.ts +2 -0
  45. package/dist/runner.js +3 -3
  46. package/dist/stores/database-mcp-oauth-credentials-store.d.ts +22 -0
  47. package/dist/stores/database-mcp-oauth-credentials-store.js +188 -0
  48. package/dist/stores/database-store.d.ts +1 -1
  49. package/dist/stores/database-store.js +17 -50
  50. package/dist/stores/in-memory-mcp-oauth-credentials-store.d.ts +13 -0
  51. package/dist/stores/in-memory-mcp-oauth-credentials-store.js +44 -0
  52. package/dist/stores/in-memory-store.d.ts +1 -0
  53. package/dist/stores/in-memory-store.js +6 -1
  54. package/dist/stores/schema-migrations.d.ts +19 -0
  55. package/dist/stores/schema-migrations.js +69 -0
  56. package/dist/types/validated/execution.d.ts +6 -0
  57. package/dist/types/validated/step-outcome.d.ts +10 -0
  58. package/dist/types/validated/step-outcome.js +7 -2
  59. package/package.json +4 -4
@@ -10,6 +10,7 @@ const koa_1 = __importDefault(require("koa"));
10
10
  const koa_jwt_1 = __importDefault(require("koa-jwt"));
11
11
  const bearer_claims_1 = require("./bearer-claims");
12
12
  const http_errors_1 = require("./http-errors");
13
+ const mcp_oauth_credentials_1 = require("./mcp-oauth-credentials");
13
14
  const step_serializer_1 = __importDefault(require("./step-serializer"));
14
15
  const console_logger_1 = __importDefault(require("../adapters/console-logger"));
15
16
  const errors_1 = require("../errors");
@@ -20,6 +21,7 @@ class ExecutorHttpServer {
20
21
  this.server = null;
21
22
  this.options = options;
22
23
  this.logger = options.logger ?? (0, console_logger_1.default)();
24
+ this.mcpOAuthCredentialsStore = options.mcpOAuthCredentialsStore;
23
25
  this.app = new koa_1.default();
24
26
  this.app.use(async (ctx, next) => {
25
27
  ctx.set('X-Executor-Version', version);
@@ -97,10 +99,17 @@ class ExecutorHttpServer {
97
99
  // Trigger handles its own authz by comparing bearer user with step.user.
98
100
  router.get('/runs/:runId', this.hasRunAccessMiddleware.bind(this), this.handleGetRun.bind(this));
99
101
  router.post('/runs/:runId/trigger', this.handleTrigger.bind(this));
102
+ const { mcpOAuthCredentialsStore: credentialsStore, credentialEncryption, remoteToolFetcher, } = this.options;
103
+ // Design-time tool listing for the MCP-server details page: resolve the caller's vault
104
+ // credential, refresh, and list the oauth2 server's tools — no workflow run involved.
105
+ router.get('/list-mcp-tools', ctx => this.handleListMcpTools(ctx, remoteToolFetcher));
106
+ router.post('/mcp-oauth-credentials', ctx => this.handleDepositCredentials(ctx, credentialsStore, credentialEncryption));
107
+ router.delete('/mcp-oauth-credentials/:mcpServerId', ctx => this.handleDeleteCredentials(ctx, credentialsStore));
100
108
  this.app.use(router.routes());
101
109
  this.app.use(router.allowedMethods());
102
110
  }
103
111
  async start() {
112
+ await this.mcpOAuthCredentialsStore.init(this.logger);
104
113
  return new Promise((resolve, reject) => {
105
114
  this.server = http_1.default.createServer(this.app.callback());
106
115
  this.server.once('error', reject);
@@ -161,6 +170,86 @@ class ExecutorHttpServer {
161
170
  ctx.status = 200;
162
171
  ctx.body = { triggered: true };
163
172
  }
173
+ async handleDepositCredentials(ctx, store, encryption) {
174
+ const userId = ctx.state.user.id;
175
+ const parsed = mcp_oauth_credentials_1.depositCredentialsBodySchema.safeParse(ctx.request.body ?? {});
176
+ if (!parsed.success) {
177
+ const details = parsed.error.issues
178
+ .map(issue => `${issue.path.join('.') || 'body'}: ${issue.message}`)
179
+ .join('; ');
180
+ throw new http_errors_1.BadRequestHttpError(`Invalid request body — ${details}`);
181
+ }
182
+ try {
183
+ await store.upsert((0, mcp_oauth_credentials_1.buildMcpOAuthCredentialInput)({ body: parsed.data, userId, encryption }));
184
+ }
185
+ catch (err) {
186
+ // The frontend must tell this missing-key config error apart from a generic failure (to route
187
+ // the user to an admin rather than retry), so it returns a typed { code } the middleware won't.
188
+ if (err instanceof errors_1.ExecutorEncryptionKeyMissingError) {
189
+ ctx.status = 503;
190
+ ctx.body = { code: err.code };
191
+ return;
192
+ }
193
+ throw err;
194
+ }
195
+ // Evict any cached access token so a reconnect/re-deposit takes effect immediately, instead of
196
+ // serving the token minted from the previous credential until it expires (mirrors delete).
197
+ this.options.oauthTokenService?.evict(userId, parsed.data.mcpServerId);
198
+ ctx.status = 200;
199
+ ctx.body = { stored: true };
200
+ }
201
+ async handleDeleteCredentials(ctx, store) {
202
+ const userId = ctx.state.user.id;
203
+ await store.delete(userId, ctx.params.mcpServerId);
204
+ // Evict any in-process cached access token so the disconnect is immediate, not deferred until
205
+ // the cached token expires (the row is gone, but the runtime would otherwise still serve it).
206
+ this.options.oauthTokenService?.evict(userId, ctx.params.mcpServerId);
207
+ ctx.status = 204;
208
+ }
209
+ // Design-time tool listing: resolve the caller's vault credential for the target oauth2 server,
210
+ // refresh + inject the Bearer, and return the server's tool definitions. user_id comes from the
211
+ // validated JWT, so a caller only ever lists with their own stored credential. A missing/dead
212
+ // credential surfaces as a typed needs-oauth-reauth response (not a generic error or empty list)
213
+ // so the details page can prompt a reconnect — mirroring the run path's awaiting-input reason.
214
+ async handleListMcpTools(ctx, fetcher) {
215
+ const userId = ctx.state.user.id;
216
+ const { mcpServerId } = ctx.query;
217
+ if (typeof mcpServerId !== 'string' || mcpServerId.length === 0) {
218
+ throw new http_errors_1.BadRequestHttpError('Missing required query parameter "mcpServerId"');
219
+ }
220
+ try {
221
+ const { tools, mcpServerName, loadFailed } = await fetcher.fetch(mcpServerId, userId);
222
+ // A dead or misrouted server otherwise renders as an (indistinguishable) empty tool list, so
223
+ // surface it — mirroring the run path, which errors rather than executing against no tools.
224
+ if (!mcpServerName) {
225
+ throw new http_errors_1.NotFoundHttpError(`No MCP server is configured for id "${mcpServerId}"`);
226
+ }
227
+ if (loadFailed) {
228
+ throw new http_errors_1.ServiceUnavailableHttpError('The MCP server could not be reached to list its tools');
229
+ }
230
+ ctx.status = 200;
231
+ ctx.body = {
232
+ tools: tools.map(tool => ({ name: tool.base.name, description: tool.base.description })),
233
+ };
234
+ }
235
+ catch (err) {
236
+ // Set the body directly so the error middleware (which would map this to a generic 400 and
237
+ // drop the typed reason) doesn't touch it — the frontend needs the reason to prompt reconnect.
238
+ if (err instanceof errors_1.OAuthReauthRequiredError) {
239
+ ctx.status = 409;
240
+ ctx.body = { awaitingInputReason: err.awaitingInputReason, mcpServerId };
241
+ return;
242
+ }
243
+ // Key-missing is an operator misconfig, not re-consent-resolvable: return the same typed 503
244
+ // the deposit endpoint uses so the details page shows the admin message, not a generic error.
245
+ if (err instanceof errors_1.ExecutorEncryptionKeyMissingError) {
246
+ ctx.status = 503;
247
+ ctx.body = { code: err.code };
248
+ return;
249
+ }
250
+ throw err;
251
+ }
252
+ }
164
253
  }
165
254
  exports.default = ExecutorHttpServer;
166
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlY3V0b3ItaHR0cC1zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaHR0cC9leGVjdXRvci1odHRwLXNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUtBLGlFQUF5QztBQUN6Qyx5REFBaUM7QUFDakMsZ0RBQXdCO0FBQ3hCLDhDQUFzQjtBQUN0QixzREFBNkI7QUFFN0IsbURBQXdFO0FBQ3hFLCtDQUt1QjtBQUN2Qix3RUFBcUQ7QUFDckQsZ0ZBQTZEO0FBQzdELHNDQUFnRDtBQUVoRCx5R0FBeUc7QUFDekcsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBd0IsQ0FBQztBQVV6RSxNQUFxQixrQkFBa0I7SUFNckMsWUFBWSxPQUFrQztRQUZ0QyxXQUFNLEdBQWtCLElBQUksQ0FBQztRQUduQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLElBQUksSUFBQSx3QkFBbUIsR0FBRSxDQUFDO1FBQ3RELElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxhQUFHLEVBQUUsQ0FBQztRQUVyQixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1lBQy9CLEdBQUcsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDdkMsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUNmLENBQUMsQ0FBQyxDQUFDO1FBRUgsdUZBQXVGO1FBQ3ZGLDRGQUE0RjtRQUM1RixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFO1lBQy9CLElBQUksQ0FBQztnQkFDSCxNQUFNLElBQUksRUFBRSxDQUFDO1lBQ2YsQ0FBQztZQUFDLE9BQU8sR0FBWSxFQUFFLENBQUM7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
255
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhlY3V0b3ItaHR0cC1zZXJ2ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaHR0cC9leGVjdXRvci1odHRwLXNlcnZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVNBLGlFQUF5QztBQUN6Qyx5REFBaUM7QUFDakMsZ0RBQXdCO0FBQ3hCLDhDQUFzQjtBQUN0QixzREFBNkI7QUFFN0IsbURBQXdFO0FBQ3hFLCtDQU91QjtBQUN2QixtRUFHaUM7QUFDakMsd0VBQXFEO0FBQ3JELGdGQUE2RDtBQUM3RCxzQ0FJbUI7QUFFbkIseUdBQXlHO0FBQ3pHLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQXdCLENBQUM7QUFnQnpFLE1BQXFCLGtCQUFrQjtJQU9yQyxZQUFZLE9BQWtDO1FBRnRDLFdBQU0sR0FBa0IsSUFBSSxDQUFDO1FBR25DLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxJQUFBLHdCQUFtQixHQUFFLENBQUM7UUFDdEQsSUFBSSxDQUFDLHdCQUF3QixHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQztRQUNqRSxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksYUFBRyxFQUFFLENBQUM7UUFFckIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUMvQixHQUFHLENBQUMsR0FBRyxDQUFDLG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDZixDQUFDLENBQUMsQ0FBQztRQUVILHVGQUF1RjtRQUN2Riw0RkFBNEY7UUFDNUYsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUMvQixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxJQUFJLEVBQUUsQ0FBQztZQUNmLENBQUM7WUFBQyxPQUFPLEdBQVksRUFBRSxDQUFDO2dCQUN0QixNQUFNLFNBQVMsR0FBRyxJQUFBLHlCQUFXLEVBQUMsR0FBRyxDQUFDLENBQUM7Z0JBRW5DLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDZixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRTt3QkFDM0MsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO3dCQUNsQixJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUk7d0JBQ2QsS0FBSyxFQUFFLElBQUEsNEJBQW1CLEVBQUMsR0FBRyxDQUFDO3dCQUMvQixLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUztxQkFDcEQsQ0FBQyxDQUFDO29CQUNILEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO29CQUNqQixHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLHVCQUF1QixFQUFFLENBQUM7b0JBRTlDLE9BQU87Z0JBQ1QsQ0FBQztnQkFFRCxJQUFJLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztvQkFDbEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUscUJBQXFCLEVBQUU7d0JBQzFDLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTTt3QkFDbEIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO3dCQUNkLE1BQU0sRUFBRSxTQUFTLENBQUMsTUFBTTt3QkFDeEIsS0FBSyxFQUFFLElBQUEsNEJBQW1CLEVBQUMsU0FBUyxDQUFDLEtBQUssSUFBSSxTQUFTLENBQUM7d0JBQ3hELGtGQUFrRjt3QkFDbEYsbUZBQW1GO3dCQUNuRixLQUFLLEVBQ0gsQ0FBQyxTQUFTLENBQUMsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQzs0QkFDdEUsU0FBUyxDQUFDLEtBQUs7cUJBQ2xCLENBQUMsQ0FBQztnQkFDTCxDQUFDO2dCQUVELEdBQUcsQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQztnQkFDOUIsR0FBRyxDQUFDLElBQUksR0FBRyxFQUFFLEtBQUssRUFBRSxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDOUMsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBRUgsNEZBQTRGO1FBQzVGLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDL0IsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNuRCxNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7Z0JBQ3RDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztnQkFDckUsR0FBRyxDQUFDLElBQUksR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDO2dCQUVyQixPQUFPO1lBQ1QsQ0FBQztZQUVELE1BQU0sSUFBSSxFQUFFLENBQUM7UUFDZixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUEsb0JBQVUsR0FBRSxDQUFDLENBQUM7UUFFM0IsMkRBQTJEO1FBQzNELDZGQUE2RjtRQUM3RixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FDVixJQUFBLGlCQUFNLEVBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUUsc0JBQXNCLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQzdGLENBQUM7UUFFRiwyRkFBMkY7UUFDM0YsMkZBQTJGO1FBQzNGLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDL0IsTUFBTSxNQUFNLEdBQUcsa0NBQWtCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFNUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDcEIsd0ZBQXdGO2dCQUN4RiwwRkFBMEY7Z0JBQzFGLHFGQUFxRjtnQkFDckYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsaUNBQWlDLEVBQUU7b0JBQ3JELE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTTtvQkFDbEIsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJO29CQUNkLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO2lCQUNuRixDQUFDLENBQUM7Z0JBRUgsTUFBTSxJQUFJLG1DQUFxQixFQUFFLENBQUM7WUFDcEMsQ0FBQztZQUVELEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxHQUFHLEVBQUUsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUV2RCxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ2YsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLE1BQU0sR0FBRyxJQUFJLGdCQUFNLEVBQUUsQ0FBQztRQUU1Qiw4REFBOEQ7UUFDOUQseUVBQXlFO1FBQ3pFLE1BQU0sQ0FBQyxHQUFHLENBQ1IsY0FBYyxFQUNkLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQ3RDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUM3QixDQUFDO1FBQ0YsTUFBTSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRW5FLE1BQU0sRUFDSix3QkFBd0IsRUFBRSxnQkFBZ0IsRUFDMUMsb0JBQW9CLEVBQ3BCLGlCQUFpQixHQUNsQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFFakIsdUZBQXVGO1FBQ3ZGLHNGQUFzRjtRQUN0RixNQUFNLENBQUMsR0FBRyxDQUFDLGlCQUFpQixFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFFdEYsTUFBTSxDQUFDLElBQUksQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUMxQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsR0FBRyxFQUFFLGdCQUFnQixFQUFFLG9CQUFvQixDQUFDLENBQzNFLENBQUM7UUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLHFDQUFxQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQ3pELElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxHQUFHLEVBQUUsZ0JBQWdCLENBQUMsQ0FDcEQsQ0FBQztRQUVGLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzlCLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFFRCxLQUFLLENBQUMsS0FBSztRQUNULE1BQU0sSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFdEQsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsTUFBTSxHQUFHLGNBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNqRCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsSUFBSTtRQUNSLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDakIsT0FBTyxFQUFFLENBQUM7Z0JBRVYsT0FBTztZQUNULENBQUM7WUFFRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRTtnQkFDdEIsSUFBSSxHQUFHLEVBQUUsQ0FBQztvQkFDUixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2QsQ0FBQztxQkFBTSxDQUFDO29CQUNOLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO29CQUNuQixPQUFPLEVBQUUsQ0FBQztnQkFDWixDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUVPLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxHQUFnQixFQUFFLElBQWM7UUFDbkUsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFvQixDQUFDO1FBQzVDLElBQUksT0FBZ0IsQ0FBQztRQUVyQixJQUFJLENBQUM7WUFDSCxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDakYsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSw0QkFBNEIsRUFBRTtnQkFDakQsS0FBSyxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSztnQkFDdkIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO2dCQUNsQixJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUk7Z0JBQ2QsS0FBSyxFQUFFLElBQUEsNEJBQW1CLEVBQUMsR0FBRyxDQUFDO2dCQUMvQixLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUzthQUNwRCxDQUFDLENBQUM7WUFFSCxrRUFBa0U7WUFDbEUsTUFBTSxJQUFJLHlDQUEyQixDQUFDLHFCQUFxQixFQUFFLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDL0UsQ0FBQztRQUVELElBQUksQ0FBQyxPQUFPO1lBQUUsTUFBTSxJQUFJLGdDQUFrQixFQUFFLENBQUM7UUFFN0MsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUNmLENBQUM7SUFFTyxLQUFLLENBQUMsWUFBWSxDQUFDLEdBQWdCO1FBQ3pDLE1BQU0sS0FBSyxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvRSxHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMseUJBQW9CLENBQUMsRUFBRSxDQUFDO0lBQ3hELENBQUM7SUFFTyxLQUFLLENBQUMsYUFBYSxDQUFDLEdBQWdCO1FBQzFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO1FBQzdCLHVEQUF1RDtRQUN2RCxNQUFNLFlBQVksR0FBSSxHQUFHLENBQUMsS0FBSyxDQUFDLElBQXFCLENBQUMsRUFBRSxDQUFDO1FBRXpELE1BQU0sV0FBVyxHQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBa0MsRUFBRSxXQUFXLENBQUM7UUFFakYsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7UUFFNUUsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7UUFDakIsR0FBRyxDQUFDLElBQUksR0FBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0lBRU8sS0FBSyxDQUFDLHdCQUF3QixDQUNwQyxHQUFnQixFQUNoQixLQUErQixFQUMvQixVQUFnQztRQUVoQyxNQUFNLE1BQU0sR0FBSSxHQUFHLENBQUMsS0FBSyxDQUFDLElBQXFCLENBQUMsRUFBRSxDQUFDO1FBQ25ELE1BQU0sTUFBTSxHQUFHLG9EQUE0QixDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztRQUU5RSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3BCLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTTtpQkFDaEMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxNQUFNLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO2lCQUNuRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFFZCxNQUFNLElBQUksaUNBQW1CLENBQUMsMEJBQTBCLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztRQUVELElBQUksQ0FBQztZQUNILE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFBLG9EQUE0QixFQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM5RixDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLDhGQUE4RjtZQUM5RixnR0FBZ0c7WUFDaEcsSUFBSSxHQUFHLFlBQVksMENBQWlDLEVBQUUsQ0FBQztnQkFDckQsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7Z0JBQ2pCLEdBQUcsQ0FBQyxJQUFJLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUU5QixPQUFPO1lBQ1QsQ0FBQztZQUVELE1BQU0sR0FBRyxDQUFDO1FBQ1osQ0FBQztRQUVELCtGQUErRjtRQUMvRiwyRkFBMkY7UUFDM0YsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDdkUsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7UUFDakIsR0FBRyxDQUFDLElBQUksR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRU8sS0FBSyxDQUFDLHVCQUF1QixDQUNuQyxHQUFnQixFQUNoQixLQUErQjtRQUUvQixNQUFNLE1BQU0sR0FBSSxHQUFHLENBQUMsS0FBSyxDQUFDLElBQXFCLENBQUMsRUFBRSxDQUFDO1FBRW5ELE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuRCw4RkFBOEY7UUFDOUYsOEZBQThGO1FBQzlGLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3RFLEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO0lBQ25CLENBQUM7SUFFRCxnR0FBZ0c7SUFDaEcsZ0dBQWdHO0lBQ2hHLDhGQUE4RjtJQUM5RixpR0FBaUc7SUFDakcsK0ZBQStGO0lBQ3ZGLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxHQUFnQixFQUFFLE9BQTBCO1FBQzNFLE1BQU0sTUFBTSxHQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBcUIsQ0FBQyxFQUFFLENBQUM7UUFDbkQsTUFBTSxFQUFFLFdBQVcsRUFBRSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUM7UUFFbEMsSUFBSSxPQUFPLFdBQVcsS0FBSyxRQUFRLElBQUksV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNoRSxNQUFNLElBQUksaUNBQW1CLENBQUMsZ0RBQWdELENBQUMsQ0FBQztRQUNsRixDQUFDO1FBRUQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLEtBQUssRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLEdBQUcsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUV0Riw2RkFBNkY7WUFDN0YsNEZBQTRGO1lBQzVGLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztnQkFDbkIsTUFBTSxJQUFJLCtCQUFpQixDQUFDLHVDQUF1QyxXQUFXLEdBQUcsQ0FBQyxDQUFDO1lBQ3JGLENBQUM7WUFFRCxJQUFJLFVBQVUsRUFBRSxDQUFDO2dCQUNmLE1BQU0sSUFBSSx5Q0FBMkIsQ0FDbkMsdURBQXVELENBQ3hELENBQUM7WUFDSixDQUFDO1lBRUQsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7WUFDakIsR0FBRyxDQUFDLElBQUksR0FBRztnQkFDVCxLQUFLLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQzthQUN6RixDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYiwyRkFBMkY7WUFDM0YsK0ZBQStGO1lBQy9GLElBQUksR0FBRyxZQUFZLGlDQUF3QixFQUFFLENBQUM7Z0JBQzVDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsR0FBRyxDQUFDO2dCQUNqQixHQUFHLENBQUMsSUFBSSxHQUFHLEVBQUUsbUJBQW1CLEVBQUUsR0FBRyxDQUFDLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDO2dCQUV6RSxPQUFPO1lBQ1QsQ0FBQztZQUVELDZGQUE2RjtZQUM3Riw4RkFBOEY7WUFDOUYsSUFBSSxHQUFHLFlBQVksMENBQWlDLEVBQUUsQ0FBQztnQkFDckQsR0FBRyxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUM7Z0JBQ2pCLEdBQUcsQ0FBQyxJQUFJLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUU5QixPQUFPO1lBQ1QsQ0FBQztZQUVELE1BQU0sR0FBRyxDQUFDO1FBQ1osQ0FBQztJQUNILENBQUM7Q0FDRjtBQTFURCxxQ0EwVEMifQ==
@@ -0,0 +1,24 @@
1
+ import type CredentialEncryption from '../crypto/credential-encryption';
2
+ import type { McpOAuthCredentialInput } from '../ports/mcp-oauth-credentials-store';
3
+ import { z } from 'zod';
4
+ export declare const depositCredentialsBodySchema: z.ZodObject<{
5
+ mcpServerId: z.ZodString;
6
+ refreshToken: z.ZodString;
7
+ clientId: z.ZodOptional<z.ZodString>;
8
+ clientSecret: z.ZodOptional<z.ZodString>;
9
+ clientSecretExpiresAt: z.ZodOptional<z.ZodString>;
10
+ tokenEndpoint: z.ZodString;
11
+ tokenEndpointAuthMethod: z.ZodOptional<z.ZodEnum<{
12
+ client_secret_post: "client_secret_post";
13
+ client_secret_basic: "client_secret_basic";
14
+ none: "none";
15
+ }>>;
16
+ scopes: z.ZodOptional<z.ZodString>;
17
+ }, z.core.$strict>;
18
+ export type DepositCredentialsBody = z.infer<typeof depositCredentialsBodySchema>;
19
+ export declare function buildMcpOAuthCredentialInput({ body, userId, encryption, }: {
20
+ body: DepositCredentialsBody;
21
+ userId: number;
22
+ encryption: CredentialEncryption;
23
+ }): McpOAuthCredentialInput;
24
+ //# sourceMappingURL=mcp-oauth-credentials.d.ts.map
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.depositCredentialsBodySchema = void 0;
7
+ exports.buildMcpOAuthCredentialInput = buildMcpOAuthCredentialInput;
8
+ const zod_1 = require("zod");
9
+ const token_endpoint_url_1 = __importDefault(require("../oauth/token-endpoint-url"));
10
+ // String lengths mirror the DB column limits, so oversized values are rejected here at the boundary
11
+ // rather than at insert. .strict() matters for security: it blocks a body-supplied user id, since
12
+ // identity comes only from the JWT.
13
+ exports.depositCredentialsBodySchema = zod_1.z
14
+ .object({
15
+ mcpServerId: zod_1.z.string().min(1).max(255),
16
+ refreshToken: zod_1.z.string().min(1),
17
+ clientId: zod_1.z.string().min(1).max(255).optional(),
18
+ clientSecret: zod_1.z.string().min(1).optional(),
19
+ clientSecretExpiresAt: zod_1.z
20
+ .string()
21
+ .refine(value => !Number.isNaN(Date.parse(value)), { message: 'must be a parseable date' })
22
+ .optional(),
23
+ tokenEndpoint: zod_1.z
24
+ .string()
25
+ .min(1)
26
+ .max(2048)
27
+ .superRefine((value, ctx) => {
28
+ // The executor POSTs the refresh grant here, so reject SSRF-prone endpoints at deposit
29
+ // rather than discovering them at refresh time.
30
+ try {
31
+ (0, token_endpoint_url_1.default)(value);
32
+ }
33
+ catch (error) {
34
+ ctx.addIssue({
35
+ code: zod_1.z.ZodIssueCode.custom,
36
+ message: error instanceof Error ? error.message : 'invalid token endpoint',
37
+ });
38
+ }
39
+ }),
40
+ // Restrict to the methods the refresh grant implements, so an unsupported/typo'd one is rejected
41
+ // here rather than silently mis-authenticating at refresh time ('none' = public client).
42
+ tokenEndpointAuthMethod: zod_1.z
43
+ .enum(['client_secret_basic', 'client_secret_post', 'none'])
44
+ .optional(),
45
+ scopes: zod_1.z.string().max(2048).optional(),
46
+ })
47
+ .strict()
48
+ .superRefine((body, ctx) => {
49
+ // RFC 6749 requires client_id alongside client_secret; a secret with no id can never
50
+ // authenticate, so reject it here instead of persisting an unusable credential.
51
+ if (body.clientSecret && !body.clientId) {
52
+ ctx.addIssue({
53
+ code: zod_1.z.ZodIssueCode.custom,
54
+ path: ['clientId'],
55
+ message: 'clientId is required when clientSecret is provided',
56
+ });
57
+ }
58
+ });
59
+ // Translates a validated deposit body into the at-rest record: encrypts the refresh token (and
60
+ // client secret when present) and maps optional fields to their nullable columns. encrypt() throws
61
+ // ExecutorEncryptionKeyMissingError when the key is unset; the caller maps that to a 503.
62
+ function buildMcpOAuthCredentialInput({ body, userId, encryption, }) {
63
+ const refreshToken = encryption.encrypt(body.refreshToken);
64
+ const clientSecret = body.clientSecret ? encryption.encrypt(body.clientSecret) : null;
65
+ return {
66
+ userId,
67
+ mcpServerId: body.mcpServerId,
68
+ refreshTokenEnc: refreshToken.ciphertext,
69
+ clientId: body.clientId ?? null,
70
+ clientSecretEnc: clientSecret?.ciphertext ?? null,
71
+ clientSecretExpiresAt: body.clientSecretExpiresAt ? new Date(body.clientSecretExpiresAt) : null,
72
+ tokenEndpoint: body.tokenEndpoint,
73
+ tokenEndpointAuthMethod: body.tokenEndpointAuthMethod ?? null,
74
+ scopes: body.scopes ?? null,
75
+ };
76
+ }
77
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWNwLW9hdXRoLWNyZWRlbnRpYWxzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2h0dHAvbWNwLW9hdXRoLWNyZWRlbnRpYWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQTZEQSxvRUF1QkM7QUFqRkQsNkJBQXdCO0FBRXhCLHFGQUFrRTtBQUVsRSxvR0FBb0c7QUFDcEcsa0dBQWtHO0FBQ2xHLG9DQUFvQztBQUN2QixRQUFBLDRCQUE0QixHQUFHLE9BQUM7S0FDMUMsTUFBTSxDQUFDO0lBQ04sV0FBVyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQztJQUN2QyxZQUFZLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0IsUUFBUSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRTtJQUMvQyxZQUFZLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUU7SUFDMUMscUJBQXFCLEVBQUUsT0FBQztTQUNyQixNQUFNLEVBQUU7U0FDUixNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLENBQUM7U0FDMUYsUUFBUSxFQUFFO0lBQ2IsYUFBYSxFQUFFLE9BQUM7U0FDYixNQUFNLEVBQUU7U0FDUixHQUFHLENBQUMsQ0FBQyxDQUFDO1NBQ04sR0FBRyxDQUFDLElBQUksQ0FBQztTQUNULFdBQVcsQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLEVB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
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export type { WorkflowPort } from './ports/workflow-port';
9
9
  export type { RunStore } from './ports/run-store';
10
10
  export type { Logger } from './ports/logger-port';
11
11
  export { default as ConsoleLogger } from './adapters/console-logger';
12
- export { WorkflowExecutorError, MissingToolCallError, MalformedToolCallError, RecordNotFoundError, NoRecordsError, NoReadableFieldsError, NoResolvedFieldsError, NoWritableFieldsError, NoActionsError, NoRelationshipFieldsError, RelatedRecordNotFoundError, InvalidAIResponseError, InvalidAiRequestError, RelationNotFoundError, FieldNotFoundError, ActionNotFoundError, StepStateError, NoMcpToolsError, McpToolNotFoundError, McpToolInvocationError, AgentPortError, WorkflowPortError, RunStorePortError, AiModelPortError, AgentProbeError, ConfigurationError, InvalidPreRecordedArgsError, UnsupportedStepTypeError, UnsupportedActionFormError, InvalidStepDefinitionError, DomainValidationError, } from './errors';
12
+ export { WorkflowExecutorError, MissingToolCallError, MalformedToolCallError, RecordNotFoundError, NoRecordsError, NoReadableFieldsError, NoResolvedFieldsError, NoWritableFieldsError, NoActionsError, NoRelationshipFieldsError, RelatedRecordNotFoundError, InvalidAIResponseError, InvalidAiRequestError, RelationNotFoundError, FieldNotFoundError, ActionNotFoundError, StepStateError, NoMcpToolsError, McpToolNotFoundError, McpToolInvocationError, AgentPortError, WorkflowPortError, RunStorePortError, AiModelPortError, AgentProbeError, ConfigurationError, ExecutorEncryptionKeyMissingError, InvalidPreRecordedArgsError, UnsupportedStepTypeError, UnsupportedActionFormError, InvalidStepDefinitionError, DomainValidationError, } from './errors';
13
13
  export { default as BaseStepExecutor } from './executors/base-step-executor';
14
14
  export { default as ConditionStepExecutor } from './executors/condition-step-executor';
15
15
  export { default as ReadRecordStepExecutor } from './executors/read-record-step-executor';
@@ -30,6 +30,12 @@ export { default as SchemaResolver } from './schema-resolver';
30
30
  export { default as InMemoryStore } from './stores/in-memory-store';
31
31
  export { default as DatabaseStore } from './stores/database-store';
32
32
  export type { DatabaseStoreOptions } from './stores/database-store';
33
+ export { default as DatabaseMcpOAuthCredentialsStore } from './stores/database-mcp-oauth-credentials-store';
34
+ export type { DatabaseMcpOAuthCredentialsStoreOptions } from './stores/database-mcp-oauth-credentials-store';
35
+ export { default as InMemoryMcpOAuthCredentialsStore } from './stores/in-memory-mcp-oauth-credentials-store';
36
+ export type { McpOAuthCredentialsStore, McpOAuthCredentialInput, StoredMcpOAuthCredential, } from './ports/mcp-oauth-credentials-store';
37
+ export { default as CredentialEncryption } from './crypto/credential-encryption';
38
+ export type { EncryptedValue } from './crypto/credential-encryption';
33
39
  export { buildDatabaseRunStore, buildInMemoryRunStore } from './stores/build-run-store';
34
40
  export { buildInMemoryExecutor, buildDatabaseExecutor } from './build-workflow-executor';
35
41
  export { runCli } from './cli-core';
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.DatabaseStore = exports.InMemoryStore = exports.SchemaResolver = exports.SchemaCache = exports.validateSecrets = exports.Runner = exports.ExecutorHttpServer = exports.ForestServerWorkflowPort = exports.AgentClientAgentPort = exports.GuidanceStepExecutor = exports.McpStepExecutor = exports.LoadRelatedRecordStepExecutor = exports.TriggerRecordActionStepExecutor = exports.UpdateRecordStepExecutor = exports.ReadRecordStepExecutor = exports.ConditionStepExecutor = exports.BaseStepExecutor = exports.DomainValidationError = exports.InvalidStepDefinitionError = exports.UnsupportedActionFormError = exports.UnsupportedStepTypeError = exports.InvalidPreRecordedArgsError = exports.ConfigurationError = exports.AgentProbeError = exports.AiModelPortError = exports.RunStorePortError = exports.WorkflowPortError = exports.AgentPortError = exports.McpToolInvocationError = exports.McpToolNotFoundError = exports.NoMcpToolsError = exports.StepStateError = exports.ActionNotFoundError = exports.FieldNotFoundError = exports.RelationNotFoundError = exports.InvalidAiRequestError = exports.InvalidAIResponseError = exports.RelatedRecordNotFoundError = exports.NoRelationshipFieldsError = exports.NoActionsError = exports.NoWritableFieldsError = exports.NoResolvedFieldsError = exports.NoReadableFieldsError = exports.NoRecordsError = exports.RecordNotFoundError = exports.MalformedToolCallError = exports.MissingToolCallError = exports.WorkflowExecutorError = exports.ConsoleLogger = exports.StepType = void 0;
7
- exports.PrettyLogger = exports.runCli = exports.buildDatabaseExecutor = exports.buildInMemoryExecutor = exports.buildInMemoryRunStore = exports.buildDatabaseRunStore = void 0;
6
+ exports.InMemoryStore = exports.SchemaResolver = exports.SchemaCache = exports.validateSecrets = exports.Runner = exports.ExecutorHttpServer = exports.ForestServerWorkflowPort = exports.AgentClientAgentPort = exports.GuidanceStepExecutor = exports.McpStepExecutor = exports.LoadRelatedRecordStepExecutor = exports.TriggerRecordActionStepExecutor = exports.UpdateRecordStepExecutor = exports.ReadRecordStepExecutor = exports.ConditionStepExecutor = exports.BaseStepExecutor = exports.DomainValidationError = exports.InvalidStepDefinitionError = exports.UnsupportedActionFormError = exports.UnsupportedStepTypeError = exports.InvalidPreRecordedArgsError = exports.ExecutorEncryptionKeyMissingError = exports.ConfigurationError = exports.AgentProbeError = exports.AiModelPortError = exports.RunStorePortError = exports.WorkflowPortError = exports.AgentPortError = exports.McpToolInvocationError = exports.McpToolNotFoundError = exports.NoMcpToolsError = exports.StepStateError = exports.ActionNotFoundError = exports.FieldNotFoundError = exports.RelationNotFoundError = exports.InvalidAiRequestError = exports.InvalidAIResponseError = exports.RelatedRecordNotFoundError = exports.NoRelationshipFieldsError = exports.NoActionsError = exports.NoWritableFieldsError = exports.NoResolvedFieldsError = exports.NoReadableFieldsError = exports.NoRecordsError = exports.RecordNotFoundError = exports.MalformedToolCallError = exports.MissingToolCallError = exports.WorkflowExecutorError = exports.ConsoleLogger = exports.StepType = void 0;
7
+ exports.PrettyLogger = exports.runCli = exports.buildDatabaseExecutor = exports.buildInMemoryExecutor = exports.buildInMemoryRunStore = exports.buildDatabaseRunStore = exports.CredentialEncryption = exports.InMemoryMcpOAuthCredentialsStore = exports.DatabaseMcpOAuthCredentialsStore = exports.DatabaseStore = void 0;
8
8
  var step_definition_1 = require("./types/validated/step-definition");
9
9
  Object.defineProperty(exports, "StepType", { enumerable: true, get: function () { return step_definition_1.StepType; } });
10
10
  var console_logger_1 = require("./adapters/console-logger");
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "RunStorePortError", { enumerable: true, get: fun
36
36
  Object.defineProperty(exports, "AiModelPortError", { enumerable: true, get: function () { return errors_1.AiModelPortError; } });
37
37
  Object.defineProperty(exports, "AgentProbeError", { enumerable: true, get: function () { return errors_1.AgentProbeError; } });
38
38
  Object.defineProperty(exports, "ConfigurationError", { enumerable: true, get: function () { return errors_1.ConfigurationError; } });
39
+ Object.defineProperty(exports, "ExecutorEncryptionKeyMissingError", { enumerable: true, get: function () { return errors_1.ExecutorEncryptionKeyMissingError; } });
39
40
  Object.defineProperty(exports, "InvalidPreRecordedArgsError", { enumerable: true, get: function () { return errors_1.InvalidPreRecordedArgsError; } });
40
41
  Object.defineProperty(exports, "UnsupportedStepTypeError", { enumerable: true, get: function () { return errors_1.UnsupportedStepTypeError; } });
41
42
  Object.defineProperty(exports, "UnsupportedActionFormError", { enumerable: true, get: function () { return errors_1.UnsupportedActionFormError; } });
@@ -75,6 +76,12 @@ var in_memory_store_1 = require("./stores/in-memory-store");
75
76
  Object.defineProperty(exports, "InMemoryStore", { enumerable: true, get: function () { return __importDefault(in_memory_store_1).default; } });
76
77
  var database_store_1 = require("./stores/database-store");
77
78
  Object.defineProperty(exports, "DatabaseStore", { enumerable: true, get: function () { return __importDefault(database_store_1).default; } });
79
+ var database_mcp_oauth_credentials_store_1 = require("./stores/database-mcp-oauth-credentials-store");
80
+ Object.defineProperty(exports, "DatabaseMcpOAuthCredentialsStore", { enumerable: true, get: function () { return __importDefault(database_mcp_oauth_credentials_store_1).default; } });
81
+ var in_memory_mcp_oauth_credentials_store_1 = require("./stores/in-memory-mcp-oauth-credentials-store");
82
+ Object.defineProperty(exports, "InMemoryMcpOAuthCredentialsStore", { enumerable: true, get: function () { return __importDefault(in_memory_mcp_oauth_credentials_store_1).default; } });
83
+ var credential_encryption_1 = require("./crypto/credential-encryption");
84
+ Object.defineProperty(exports, "CredentialEncryption", { enumerable: true, get: function () { return __importDefault(credential_encryption_1).default; } });
78
85
  var build_run_store_1 = require("./stores/build-run-store");
79
86
  Object.defineProperty(exports, "buildDatabaseRunStore", { enumerable: true, get: function () { return build_run_store_1.buildDatabaseRunStore; } });
80
87
  Object.defineProperty(exports, "buildInMemoryRunStore", { enumerable: true, get: function () { return build_run_store_1.buildInMemoryRunStore; } });
@@ -85,4 +92,4 @@ var cli_core_1 = require("./cli-core");
85
92
  Object.defineProperty(exports, "runCli", { enumerable: true, get: function () { return cli_core_1.runCli; } });
86
93
  var pretty_logger_1 = require("./adapters/pretty-logger");
87
94
  Object.defineProperty(exports, "PrettyLogger", { enumerable: true, get: function () { return __importDefault(pretty_logger_1).default; } });
88
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBLHFFQUE2RDtBQUFwRCwyR0FBQSxRQUFRLE9BQUE7QUF5RWpCLDREQUFxRTtBQUE1RCxnSUFBQSxPQUFPLE9BQWlCO0FBRWpDLG1DQWdDa0I7QUEvQmhCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLDhHQUFBLG9CQUFvQixPQUFBO0FBQ3BCLGdIQUFBLHNCQUFzQixPQUFBO0FBQ3RCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLHdHQUFBLGNBQWMsT0FBQTtBQUNkLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLHdHQUFBLGNBQWMsT0FBQTtBQUNkLG1IQUFBLHlCQUF5QixPQUFBO0FBQ3pCLG9IQUFBLDBCQUEwQixPQUFBO0FBQzFCLGdIQUFBLHNCQUFzQixPQUFBO0FBQ3RCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLHdHQUFBLGNBQWMsT0FBQTtBQUNkLHlHQUFBLGVBQWUsT0FBQTtBQUNmLDhHQUFBLG9CQUFvQixPQUFBO0FBQ3BCLGdIQUFBLHNCQUFzQixPQUFBO0FBQ3RCLHdHQUFBLGNBQWMsT0FBQTtBQUNkLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDBHQUFBLGdCQUFnQixPQUFBO0FBQ2hCLHlHQUFBLGVBQWUsT0FBQTtBQUNmLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLHFIQUFBLDJCQUEyQixPQUFBO0FBQzNCLGtIQUFBLHdCQUF3QixPQUFBO0FBQ3hCLG9IQUFBLDBCQUEwQixPQUFBO0FBQzFCLG9IQUFBLDBCQUEwQixPQUFBO0FBQzFCLCtHQUFBLHFCQUFxQixPQUFBO0FBRXZCLHFFQUE2RTtBQUFwRSx1SUFBQSxPQUFPLE9BQW9CO0FBQ3BDLCtFQUF1RjtBQUE5RSxpSkFBQSxPQUFPLE9BQXlCO0FBQ3pDLG1GQUEwRjtBQUFqRixvSkFBQSxPQUFPLE9BQTBCO0FBQzFDLHVGQUE4RjtBQUFyRix3SkFBQSxPQUFPLE9BQTRCO0FBQzVDLHVHQUE2RztBQUFwRyx1S0FBQSxPQUFPLE9BQW1DO0FBQ25ELG1HQUF5RztBQUFoRyxtS0FBQSxPQUFPLE9BQWlDO0FBQ2pELG1FQUEyRTtBQUFsRSxxSUFBQSxPQUFPLE9BQW1CO0FBQ25DLDZFQUFxRjtBQUE1RSwrSUFBQSxPQUFPLE9BQXdCO0FBQ3hDLDhFQUFxRjtBQUE1RSxnSkFBQSxPQUFPLE9BQXdCO0FBQ3hDLHNGQUE2RjtBQUFwRix3SkFBQSxPQUFPLE9BQTRCO0FBQzVDLG9FQUE0RTtBQUFuRSwySUFBQSxPQUFPLE9BQXNCO0FBRXRDLG1DQUE2QztBQUFwQyxpSEFBQSxPQUFPLE9BQVU7QUFFMUIsdURBQWdFO0FBQXZELG9JQUFBLE9BQU8sT0FBbUI7QUFDbkMsK0NBQXdEO0FBQS9DLDRIQUFBLE9BQU8sT0FBZTtBQUMvQixxREFBOEQ7QUFBckQsa0lBQUEsT0FBTyxPQUFrQjtBQUNsQyw0REFBb0U7QUFBM0QsaUlBQUEsT0FBTyxPQUFpQjtBQUNqQywwREFBbUU7QUFBMUQsZ0lBQUEsT0FBTyxPQUFpQjtBQUVqQyw0REFBd0Y7QUFBL0Usd0hBQUEscUJBQXFCLE9BQUE7QUFBRSx3SEFBQSxxQkFBcUIsT0FBQTtBQUNyRCxxRUFBeUY7QUFBaEYsZ0lBQUEscUJBQXFCLE9BQUE7QUFBRSxnSUFBQSxxQkFBcUIsT0FBQTtBQUNyRCx1Q0FBb0M7QUFBM0Isa0dBQUEsTUFBTSxPQUFBO0FBQ2YsMERBQW1FO0FBQTFELDhIQUFBLE9BQU8sT0FBZ0IifQ==
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7OztBQUFBLHFFQUE2RDtBQUFwRCwyR0FBQSxRQUFRLE9BQUE7QUF5RWpCLDREQUFxRTtBQUE1RCxnSUFBQSxPQUFPLE9BQWlCO0FBRWpDLG1DQWlDa0I7QUFoQ2hCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLDhHQUFBLG9CQUFvQixPQUFBO0FBQ3BCLGdIQUFBLHNCQUFzQixPQUFBO0FBQ3RCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLHdHQUFBLGNBQWMsT0FBQTtBQUNkLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLHdHQUFBLGNBQWMsT0FBQTtBQUNkLG1IQUFBLHlCQUF5QixPQUFBO0FBQ3pCLG9IQUFBLDBCQUEwQixPQUFBO0FBQzFCLGdIQUFBLHNCQUFzQixPQUFBO0FBQ3RCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLHdHQUFBLGNBQWMsT0FBQTtBQUNkLHlHQUFBLGVBQWUsT0FBQTtBQUNmLDhHQUFBLG9CQUFvQixPQUFBO0FBQ3BCLGdIQUFBLHNCQUFzQixPQUFBO0FBQ3RCLHdHQUFBLGNBQWMsT0FBQTtBQUNkLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDBHQUFBLGdCQUFnQixPQUFBO0FBQ2hCLHlHQUFBLGVBQWUsT0FBQTtBQUNmLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDJIQUFBLGlDQUFpQyxPQUFBO0FBQ2pDLHFIQUFBLDJCQUEyQixPQUFBO0FBQzNCLGtIQUFBLHdCQUF3QixPQUFBO0FBQ3hCLG9IQUFBLDBCQUEwQixPQUFBO0FBQzFCLG9IQUFBLDBCQUEwQixPQUFBO0FBQzFCLCtHQUFBLHFCQUFxQixPQUFBO0FBRXZCLHFFQUE2RTtBQUFwRSx1SUFBQSxPQUFPLE9BQW9CO0FBQ3BDLCtFQUF1RjtBQUE5RSxpSkFBQSxPQUFPLE9BQXlCO0FBQ3pDLG1GQUEwRjtBQUFqRixvSkFBQSxPQUFPLE9BQTBCO0FBQzFDLHVGQUE4RjtBQUFyRix3SkFBQSxPQUFPLE9BQTRCO0FBQzVDLHVHQUE2RztBQUFwRyx1S0FBQSxPQUFPLE9BQW1DO0FBQ25ELG1HQUF5RztBQUFoRyxtS0FBQSxPQUFPLE9BQWlDO0FBQ2pELG1FQUEyRTtBQUFsRSxxSUFBQSxPQUFPLE9BQW1CO0FBQ25DLDZFQUFxRjtBQUE1RSwrSUFBQSxPQUFPLE9BQXdCO0FBQ3hDLDhFQUFxRjtBQUE1RSxnSkFBQSxPQUFPLE9BQXdCO0FBQ3hDLHNGQUE2RjtBQUFwRix3SkFBQSxPQUFPLE9BQTRCO0FBQzVDLG9FQUE0RTtBQUFuRSwySUFBQSxPQUFPLE9BQXNCO0FBRXRDLG1DQUE2QztBQUFwQyxpSEFBQSxPQUFPLE9BQVU7QUFFMUIsdURBQWdFO0FBQXZELG9JQUFBLE9BQU8sT0FBbUI7QUFDbkMsK0NBQXdEO0FBQS9DLDRIQUFBLE9BQU8sT0FBZTtBQUMvQixxREFBOEQ7QUFBckQsa0lBQUEsT0FBTyxPQUFrQjtBQUNsQyw0REFBb0U7QUFBM0QsaUlBQUEsT0FBTyxPQUFpQjtBQUNqQywwREFBbUU7QUFBMUQsZ0lBQUEsT0FBTyxPQUFpQjtBQUVqQyxzR0FBNEc7QUFBbkcseUtBQUEsT0FBTyxPQUFvQztBQUVwRCx3R0FBNkc7QUFBcEcsMEtBQUEsT0FBTyxPQUFvQztBQU1wRCx3RUFBaUY7QUFBeEUsOElBQUEsT0FBTyxPQUF3QjtBQUV4Qyw0REFBd0Y7QUFBL0Usd0hBQUEscUJBQXFCLE9BQUE7QUFBRSx3SEFBQSxxQkFBcUIsT0FBQTtBQUNyRCxxRUFBeUY7QUFBaEYsZ0lBQUEscUJBQXFCLE9BQUE7QUFBRSxnSUFBQSxxQkFBcUIsT0FBQTtBQUNyRCx1Q0FBb0M7QUFBM0Isa0dBQUEsTUFBTSxPQUFBO0FBQ2YsMERBQW1FO0FBQTFELDhIQUFBLE9BQU8sT0FBZ0IifQ==
@@ -0,0 +1,5 @@
1
+ export default class KeyedMutex {
2
+ private readonly tails;
3
+ runExclusive<T>(key: string, task: () => Promise<T>): Promise<T>;
4
+ }
5
+ //# sourceMappingURL=keyed-mutex.d.ts.map
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // Serializes async work per key: callers sharing a key run one at a time (FIFO), while different
4
+ // keys proceed in parallel. Used to collapse concurrent token refreshes for the same (user, server)
5
+ // into a single in-flight refresh within one process.
6
+ class KeyedMutex {
7
+ constructor() {
8
+ this.tails = new Map();
9
+ }
10
+ async runExclusive(key, task) {
11
+ const previous = this.tails.get(key) ?? Promise.resolve();
12
+ const result = previous.then(() => task());
13
+ // Store a non-rejecting tail so the next caller chains regardless of this task's outcome.
14
+ const tail = result.then(() => undefined, () => undefined);
15
+ this.tails.set(key, tail);
16
+ try {
17
+ return await result;
18
+ }
19
+ finally {
20
+ // Drop the entry once this was the last queued task for the key, so the map can't grow.
21
+ if (this.tails.get(key) === tail)
22
+ this.tails.delete(key);
23
+ }
24
+ }
25
+ }
26
+ exports.default = KeyedMutex;
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoia2V5ZWQtbXV0ZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb2F1dGgva2V5ZWQtbXV0ZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxpR0FBaUc7QUFDakcsb0dBQW9HO0FBQ3BHLHNEQUFzRDtBQUN0RCxNQUFxQixVQUFVO0lBQS9CO1FBQ21CLFVBQUssR0FBRyxJQUFJLEdBQUcsRUFBNEIsQ0FBQztJQW1CL0QsQ0FBQztJQWpCQyxLQUFLLENBQUMsWUFBWSxDQUFJLEdBQVcsRUFBRSxJQUFzQjtRQUN2RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDMUQsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzNDLDBGQUEwRjtRQUMxRixNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUN0QixHQUFHLEVBQUUsQ0FBQyxTQUFTLEVBQ2YsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUNoQixDQUFDO1FBQ0YsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRTFCLElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxNQUFNLENBQUM7UUFDdEIsQ0FBQztnQkFBUyxDQUFDO1lBQ1Qsd0ZBQXdGO1lBQ3hGLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSTtnQkFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMzRCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBcEJELDZCQW9CQyJ9
@@ -0,0 +1,15 @@
1
+ export interface RefreshGrantParams {
2
+ tokenEndpoint: string;
3
+ refreshToken: string;
4
+ clientId?: string | null;
5
+ clientSecret?: string | null;
6
+ tokenEndpointAuthMethod?: string | null;
7
+ scopes?: string | null;
8
+ }
9
+ export interface RefreshGrantResult {
10
+ accessToken: string;
11
+ expiresInS?: number;
12
+ refreshToken?: string;
13
+ }
14
+ export default function refreshAccessToken(params: RefreshGrantParams): Promise<RefreshGrantResult>;
15
+ //# sourceMappingURL=refresh-grant.d.ts.map
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = refreshAccessToken;
7
+ const errors_1 = require("../errors");
8
+ const token_endpoint_url_1 = __importDefault(require("./token-endpoint-url"));
9
+ // RFC 6749 §2.3.1 form-url-encodes the client id/secret before base64 (space → '+', unlike
10
+ // encodeURIComponent's '%20'); identical for the base64url/hex credentials providers actually issue.
11
+ function formUrlEncode(value) {
12
+ const params = new URLSearchParams();
13
+ params.set('v', value);
14
+ return params.toString().slice('v='.length);
15
+ }
16
+ // Some providers return expires_in as a numeric string; coerce it so the token is still cached
17
+ // (an unusable value leaves it uncached, forcing a full refresh — and rotation — on every call).
18
+ function coerceExpiresInS(value) {
19
+ if (typeof value === 'number')
20
+ return value;
21
+ if (typeof value === 'string' && /^\d+$/.test(value))
22
+ return Number(value);
23
+ return undefined;
24
+ }
25
+ function buildRequest(params) {
26
+ const headers = {
27
+ 'content-type': 'application/x-www-form-urlencoded',
28
+ accept: 'application/json',
29
+ };
30
+ const body = new URLSearchParams({
31
+ grant_type: 'refresh_token',
32
+ refresh_token: params.refreshToken,
33
+ });
34
+ if (params.scopes)
35
+ body.set('scope', params.scopes);
36
+ const { clientId, clientSecret, tokenEndpointAuthMethod } = params;
37
+ if (clientSecret) {
38
+ if (tokenEndpointAuthMethod === 'client_secret_post') {
39
+ if (clientId)
40
+ body.set('client_id', clientId);
41
+ body.set('client_secret', clientSecret);
42
+ }
43
+ else {
44
+ const credentials = `${formUrlEncode(clientId ?? '')}:${formUrlEncode(clientSecret)}`;
45
+ headers.authorization = `Basic ${Buffer.from(credentials).toString('base64')}`;
46
+ }
47
+ }
48
+ else if (clientId) {
49
+ body.set('client_id', clientId);
50
+ }
51
+ return { headers, body };
52
+ }
53
+ // Runs the OAuth2 refresh-token grant (RFC 6749 §6) against the stored token endpoint. Distinguishes
54
+ // a non-retryable invalid_grant (revoked / rotated) from a transient failure so the caller can decide
55
+ // between forcing re-auth and retrying.
56
+ async function refreshAccessToken(params) {
57
+ // Defense in depth: deposit validation rejects SSRF-prone endpoints, but a row predating that
58
+ // validation could still carry one — re-check before the outbound POST. Throws (terminal) rather
59
+ // than reaching the network.
60
+ (0, token_endpoint_url_1.default)(params.tokenEndpoint);
61
+ const { headers, body } = buildRequest(params);
62
+ let response;
63
+ try {
64
+ // Never follow redirects: a 3xx to an internal host would re-send the grant body (refresh
65
+ // token, plus the client secret in client_secret_post) there and parse its reply as a token —
66
+ // bypassing the endpoint validation above. Any redirect is treated as a failure.
67
+ response = await fetch(params.tokenEndpoint, {
68
+ method: 'POST',
69
+ headers,
70
+ body,
71
+ redirect: 'manual',
72
+ });
73
+ }
74
+ catch (cause) {
75
+ throw new errors_1.OAuthRefreshError('the token endpoint could not be reached', cause);
76
+ }
77
+ if (response.type === 'opaqueredirect' || (response.status >= 300 && response.status < 400)) {
78
+ throw new errors_1.OAuthRefreshError('the token endpoint attempted a redirect');
79
+ }
80
+ let payload = {};
81
+ try {
82
+ const parsed = await response.json();
83
+ // Ignore a non-object body (e.g. literal null), keeping the {} default so the status checks
84
+ // below still surface a typed OAuthRefreshError.
85
+ if (parsed && typeof parsed === 'object')
86
+ payload = parsed;
87
+ }
88
+ catch {
89
+ // Non-JSON body — handled by the status checks below.
90
+ }
91
+ if (!response.ok) {
92
+ // invalid_client / unauthorized_client mean the client credential itself is dead (e.g. an expired
93
+ // secret) — non-retryable like invalid_grant, so route to re-consent instead of a doomed retry.
94
+ if (payload.error === 'invalid_grant' ||
95
+ payload.error === 'invalid_client' ||
96
+ payload.error === 'unauthorized_client') {
97
+ throw new errors_1.OAuthInvalidGrantError(typeof payload.error_description === 'string' ? payload.error_description : undefined);
98
+ }
99
+ throw new errors_1.OAuthRefreshError(typeof payload.error === 'string'
100
+ ? payload.error
101
+ : `the token endpoint returned ${response.status}`);
102
+ }
103
+ if (typeof payload.access_token !== 'string' || !payload.access_token) {
104
+ throw new errors_1.OAuthRefreshError('the token endpoint response had no access_token');
105
+ }
106
+ return {
107
+ accessToken: payload.access_token,
108
+ expiresInS: coerceExpiresInS(payload.expires_in),
109
+ refreshToken: typeof payload.refresh_token === 'string' ? payload.refresh_token : undefined,
110
+ };
111
+ }
112
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVmcmVzaC1ncmFudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vYXV0aC9yZWZyZXNoLWdyYW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBZ0ZBLHFDQXNFQztBQXRKRCxzQ0FBc0U7QUFDdEUsOEVBQTJEO0FBMEIzRCwyRkFBMkY7QUFDM0YscUdBQXFHO0FBQ3JHLFNBQVMsYUFBYSxDQUFDLEtBQWE7SUFDbEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztJQUNyQyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUV2QixPQUFPLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzlDLENBQUM7QUFFRCwrRkFBK0Y7QUFDL0YsaUdBQWlHO0FBQ2pHLFNBQVMsZ0JBQWdCLENBQUMsS0FBYztJQUN0QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVE7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUM1QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTNFLE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRCxTQUFTLFlBQVksQ0FBQyxNQUEwQjtJQUk5QyxNQUFNLE9BQU8sR0FBMkI7UUFDdEMsY0FBYyxFQUFFLG1DQUFtQztRQUNuRCxNQUFNLEVBQUUsa0JBQWtCO0tBQzNCLENBQUM7SUFDRixNQUFNLElBQUksR0FBRyxJQUFJLGVBQWUsQ0FBQztRQUMvQixVQUFVLEVBQUUsZUFBZTtRQUMzQixhQUFhLEVBQUUsTUFBTSxDQUFDLFlBQVk7S0FDbkMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxNQUFNLENBQUMsTUFBTTtRQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFF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
@@ -0,0 +1,2 @@
1
+ export default function assertSafeTokenEndpoint(raw: string): void;
2
+ //# sourceMappingURL=token-endpoint-url.d.ts.map