@executor-js/sdk 1.5.20 → 1.5.22
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.
- package/dist/{chunk-EJKXSREX.js → chunk-DN5AKD4U.js} +3 -1
- package/dist/chunk-DN5AKD4U.js.map +1 -0
- package/dist/{chunk-MYRPYTSV.js → chunk-GUZHNTDQ.js} +197 -57
- package/dist/chunk-GUZHNTDQ.js.map +1 -0
- package/dist/{chunk-PCSRC6WP.js → chunk-SNWDGE3G.js} +47 -17
- package/dist/chunk-SNWDGE3G.js.map +1 -0
- package/dist/client.d.ts +9 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/core.js +11 -5
- package/dist/core.js.map +1 -1
- package/dist/executor.d.ts +2 -0
- package/dist/executor.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/integration.d.ts +4 -3
- package/dist/integration.d.ts.map +1 -1
- package/dist/oauth-callback-state.test.d.ts +2 -0
- package/dist/oauth-callback-state.test.d.ts.map +1 -0
- package/dist/oauth-service.d.ts +23 -13
- package/dist/oauth-service.d.ts.map +1 -1
- package/dist/oauth.d.ts +23 -0
- package/dist/oauth.d.ts.map +1 -1
- package/dist/plugin.d.ts +35 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/server-connection.d.ts +1 -0
- package/dist/server-connection.d.ts.map +1 -1
- package/dist/shared.d.ts +2 -1
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +8 -2
- package/dist/test-config.d.ts +1 -0
- package/dist/test-config.d.ts.map +1 -1
- package/dist/testing/oauth-test-server.d.ts +3 -0
- package/dist/testing/oauth-test-server.d.ts.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +9 -3
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-EJKXSREX.js.map +0 -1
- package/dist/chunk-MYRPYTSV.js.map +0 -1
- package/dist/chunk-PCSRC6WP.js.map +0 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Option, Schema } from "effect";
|
|
3
3
|
var DEFAULT_EXECUTOR_SERVER_ORIGIN = "http://127.0.0.1:4000";
|
|
4
4
|
var DEFAULT_EXECUTOR_SERVER_USERNAME = "executor";
|
|
5
|
+
var EXECUTOR_ORG_SELECTOR_HEADER = "x-executor-organization";
|
|
5
6
|
var stripTrailingSlash = (value) => value.replace(/\/+$/, "");
|
|
6
7
|
var displayNameFromOrigin = (origin) => origin.replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
7
8
|
var normalizeExecutorServerOrigin = (raw) => {
|
|
@@ -157,6 +158,7 @@ var InternalError = class extends Schema2.TaggedErrorClass()(
|
|
|
157
158
|
export {
|
|
158
159
|
DEFAULT_EXECUTOR_SERVER_ORIGIN,
|
|
159
160
|
DEFAULT_EXECUTOR_SERVER_USERNAME,
|
|
161
|
+
EXECUTOR_ORG_SELECTOR_HEADER,
|
|
160
162
|
normalizeExecutorServerOrigin,
|
|
161
163
|
apiBaseUrlForServerOrigin,
|
|
162
164
|
originFromApiBaseUrl,
|
|
@@ -168,4 +170,4 @@ export {
|
|
|
168
170
|
isOAuthPopupResult,
|
|
169
171
|
InternalError
|
|
170
172
|
};
|
|
171
|
-
//# sourceMappingURL=chunk-
|
|
173
|
+
//# sourceMappingURL=chunk-DN5AKD4U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server-connection.ts","../src/oauth-popup-types.ts","../src/api-errors.ts"],"sourcesContent":["import { Option, Schema } from \"effect\";\n\nexport const DEFAULT_EXECUTOR_SERVER_ORIGIN = \"http://127.0.0.1:4000\";\nexport const DEFAULT_EXECUTOR_SERVER_USERNAME = \"executor\";\nexport const EXECUTOR_ORG_SELECTOR_HEADER = \"x-executor-organization\";\n\nexport type ExecutorServerConnectionKind = \"http\" | \"desktop-sidecar\";\nexport type ExecutorLocalServerKind = \"cli-daemon\" | \"desktop-sidecar\" | \"foreground\";\n\nexport type ExecutorServerAuth =\n | {\n readonly kind: \"basic\";\n readonly username?: string;\n readonly password: string;\n }\n | {\n readonly kind: \"bearer\";\n readonly token: string;\n }\n | {\n // OAuth 2.0 device-flow credential from `executor login` against a hosted\n // server. The access token is sent as a Bearer; `refreshToken` +\n // `expiresAt` (epoch seconds) + `tokenEndpoint` + `clientId` let the CLI\n // refresh it before expiry without a fresh browser login.\n readonly kind: \"oauth\";\n readonly accessToken: string;\n readonly refreshToken?: string;\n readonly expiresAt?: number;\n readonly tokenEndpoint?: string;\n readonly clientId?: string;\n };\n\nexport interface ExecutorServerConnection {\n readonly kind: ExecutorServerConnectionKind;\n readonly key: string;\n readonly origin: string;\n readonly apiBaseUrl: string;\n readonly displayName: string;\n readonly auth?: ExecutorServerAuth;\n}\n\nexport interface ExecutorServerConnectionInput {\n readonly kind?: ExecutorServerConnectionKind;\n readonly key?: string;\n readonly origin?: string;\n readonly apiBaseUrl?: string;\n readonly displayName?: string;\n readonly auth?: ExecutorServerAuth;\n}\n\nexport interface ExecutorLocalServerManifest {\n readonly version: 1;\n readonly kind: ExecutorLocalServerKind;\n readonly pid: number;\n readonly startedAt: string;\n readonly dataDir: string;\n readonly scopeDir: string | null;\n readonly connection: ExecutorServerConnection;\n readonly owner: {\n readonly client: \"cli\" | \"desktop\";\n readonly version: string | null;\n readonly executablePath: string | null;\n };\n}\n\nconst stripTrailingSlash = (value: string): string => value.replace(/\\/+$/, \"\");\n\nconst displayNameFromOrigin = (origin: string): string =>\n origin.replace(/^https?:\\/\\//, \"\").replace(/\\/+$/, \"\");\n\nexport const normalizeExecutorServerOrigin = (raw: string): string => {\n const trimmed = stripTrailingSlash(raw.trim());\n if (!trimmed) return DEFAULT_EXECUTOR_SERVER_ORIGIN;\n\n const parsed = new URL(/^https?:\\/\\//.test(trimmed) ? trimmed : `http://${trimmed}`);\n if (parsed.pathname === \"/api\") {\n parsed.pathname = \"/\";\n }\n parsed.search = \"\";\n parsed.hash = \"\";\n return stripTrailingSlash(parsed.toString());\n};\n\nexport const apiBaseUrlForServerOrigin = (origin: string): string => `${origin}/api`;\n\nexport const originFromApiBaseUrl = (raw: string): string => {\n const parsed = new URL(raw);\n if (parsed.pathname.endsWith(\"/api\")) {\n parsed.pathname = parsed.pathname.slice(0, -\"/api\".length) || \"/\";\n }\n parsed.search = \"\";\n parsed.hash = \"\";\n return normalizeExecutorServerOrigin(parsed.toString());\n};\n\nexport const normalizeExecutorServerConnection = (\n input: ExecutorServerConnectionInput = {},\n): ExecutorServerConnection => {\n const origin = normalizeExecutorServerOrigin(\n input.origin ??\n (input.apiBaseUrl ? originFromApiBaseUrl(input.apiBaseUrl) : DEFAULT_EXECUTOR_SERVER_ORIGIN),\n );\n const apiBaseUrl = stripTrailingSlash(input.apiBaseUrl ?? apiBaseUrlForServerOrigin(origin));\n const kind = input.kind ?? \"http\";\n\n return {\n kind,\n key: input.key ?? `${kind}:${origin}`,\n origin,\n apiBaseUrl,\n displayName: input.displayName ?? displayNameFromOrigin(origin),\n ...(input.auth ? { auth: input.auth } : {}),\n };\n};\n\nconst encodeBasicCredentials = (credentials: string): string | null => {\n if (typeof globalThis.btoa === \"function\") {\n return globalThis.btoa(credentials);\n }\n\n const buffer = (\n globalThis as {\n readonly Buffer?: {\n readonly from: (value: string) => { readonly toString: (encoding: \"base64\") => string };\n };\n }\n ).Buffer;\n if (buffer) {\n return buffer.from(credentials).toString(\"base64\");\n }\n\n return null;\n};\n\nexport const getExecutorServerAuthorizationHeader = (\n connection: ExecutorServerConnection,\n): string | null => {\n const auth = connection.auth;\n if (!auth) return null;\n if (auth.kind === \"bearer\") return `Bearer ${auth.token}`;\n if (auth.kind === \"oauth\") return `Bearer ${auth.accessToken}`;\n const encoded = encodeBasicCredentials(\n `${auth.username ?? DEFAULT_EXECUTOR_SERVER_USERNAME}:${auth.password}`,\n );\n return encoded ? `Basic ${encoded}` : null;\n};\n\nconst ExecutorServerAuthJson = Schema.Union([\n Schema.Struct({\n kind: Schema.Literal(\"basic\"),\n username: Schema.optional(Schema.String),\n password: Schema.String,\n }),\n Schema.Struct({\n kind: Schema.Literal(\"bearer\"),\n token: Schema.String,\n }),\n Schema.Struct({\n kind: Schema.Literal(\"oauth\"),\n accessToken: Schema.String,\n refreshToken: Schema.optional(Schema.String),\n expiresAt: Schema.optional(Schema.Number),\n tokenEndpoint: Schema.optional(Schema.String),\n clientId: Schema.optional(Schema.String),\n }),\n]);\n\nconst ExecutorServerConnectionJson = Schema.Struct({\n kind: Schema.optional(Schema.Literals([\"http\", \"desktop-sidecar\"])),\n key: Schema.optional(Schema.String),\n origin: Schema.String,\n apiBaseUrl: Schema.optional(Schema.String),\n displayName: Schema.optional(Schema.String),\n auth: Schema.optional(ExecutorServerAuthJson),\n});\n\nconst ExecutorLocalServerManifestJson = Schema.Struct({\n version: Schema.Literal(1),\n kind: Schema.Literals([\"cli-daemon\", \"desktop-sidecar\", \"foreground\"]),\n pid: Schema.Number,\n startedAt: Schema.String,\n dataDir: Schema.String,\n scopeDir: Schema.NullOr(Schema.String),\n connection: ExecutorServerConnectionJson,\n owner: Schema.Struct({\n client: Schema.Literals([\"cli\", \"desktop\"]),\n version: Schema.NullOr(Schema.String),\n executablePath: Schema.NullOr(Schema.String),\n }),\n});\n\nconst decodeUnknownJsonOption = Schema.decodeUnknownOption(Schema.UnknownFromJsonString);\nconst decodeExecutorLocalServerManifestJson = Schema.decodeUnknownOption(\n ExecutorLocalServerManifestJson,\n);\n\nconst canNormalizeServerOrigin = (origin: string): boolean => {\n const trimmed = stripTrailingSlash(origin.trim());\n if (!trimmed) return true;\n return URL.canParse(/^https?:\\/\\//.test(trimmed) ? trimmed : `http://${trimmed}`);\n};\n\nexport const parseExecutorLocalServerManifest = (\n raw: string,\n): ExecutorLocalServerManifest | null => {\n const json = decodeUnknownJsonOption(raw);\n if (Option.isNone(json)) return null;\n const decoded = decodeExecutorLocalServerManifestJson(json.value);\n if (Option.isNone(decoded)) return null;\n const parsed = decoded.value;\n if (\n !Number.isInteger(parsed.pid) ||\n parsed.pid <= 0 ||\n !canNormalizeServerOrigin(parsed.connection.origin)\n ) {\n return null;\n }\n\n const connection = normalizeExecutorServerConnection(parsed.connection);\n return {\n version: 1,\n kind: parsed.kind,\n pid: parsed.pid,\n startedAt: parsed.startedAt,\n dataDir: parsed.dataDir,\n scopeDir: parsed.scopeDir,\n connection,\n owner: {\n client: parsed.owner.client,\n version: parsed.owner.version,\n executablePath: parsed.owner.executablePath,\n },\n };\n};\n\nexport const serializeExecutorLocalServerManifest = (\n manifest: ExecutorLocalServerManifest,\n): string => `${JSON.stringify(manifest, null, 2)}\\n`;\n","// ---------------------------------------------------------------------------\n// OAuth popup result — the message shape exchanged between the popup window\n// (opened during authorization) and the opener (the onboarding UI). Both the\n// server-side HTML generator and the client-side popup opener agree on this\n// shape so that success / failure can be communicated reliably via both\n// `postMessage` and `BroadcastChannel`.\n// ---------------------------------------------------------------------------\n\n/** Message type literal used to identify our popup results. */\nexport const OAUTH_POPUP_MESSAGE_TYPE = \"executor:oauth-result\" as const;\n\nexport type OAuthPopupResult<TAuth> =\n | ({\n readonly type: typeof OAUTH_POPUP_MESSAGE_TYPE;\n readonly ok: true;\n readonly sessionId: string;\n } & TAuth)\n | {\n readonly type: typeof OAUTH_POPUP_MESSAGE_TYPE;\n readonly ok: false;\n readonly sessionId: string | null;\n /** Short user-facing summary. */\n readonly error: string;\n /** Full technical detail. Omitted when identical to `error`. */\n readonly errorDetails?: string;\n };\n\nexport const isOAuthPopupResult = <TAuth>(value: unknown): value is OAuthPopupResult<TAuth> =>\n typeof value === \"object\" &&\n value !== null &&\n (value as { type?: unknown }).type === OAUTH_POPUP_MESSAGE_TYPE;\n","// ---------------------------------------------------------------------------\n// Wire-level HTTP errors. Lives in the SDK so plugin `HttpApiGroup`\n// definitions (which sit on the SDK side of the dependency graph and\n// must stay publishable) can declare them without dragging in the\n// server-only `@executor-js/api` package. The HTTP edge in\n// `@executor-js/api` re-exports these and pairs them with the\n// translation/capture helpers used by handlers.\n// ---------------------------------------------------------------------------\n\nimport { Schema } from \"effect\";\n\n/** Public 500 surface. Opaque by schema — only `traceId` crosses the wire. */\nexport class InternalError extends Schema.TaggedErrorClass<InternalError>()(\n \"InternalError\",\n {\n /** Opaque correlation id for backend lookup (Sentry event id, log line, etc.). */\n traceId: Schema.String,\n },\n { httpApiStatus: 500 },\n) {}\n"],"mappings":"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","names":["Schema"]}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
IntegrationRemovalNotAllowedError,
|
|
10
10
|
InvalidConnectionInputError,
|
|
11
11
|
NoHandlerError,
|
|
12
|
+
OAUTH2_SESSION_TTL_MS,
|
|
12
13
|
OAuthCompleteError,
|
|
13
14
|
OAuthProbeError,
|
|
14
15
|
OAuthRegisterDynamicError,
|
|
@@ -21,10 +22,12 @@ import {
|
|
|
21
22
|
ToolPolicyActionSchema,
|
|
22
23
|
ToolSchemaView,
|
|
23
24
|
comparePolicyRow,
|
|
25
|
+
encodeOAuthCallbackState,
|
|
24
26
|
isValidPattern,
|
|
27
|
+
matchPattern,
|
|
25
28
|
resolveEffectivePolicy,
|
|
26
29
|
rowToToolPolicy
|
|
27
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-SNWDGE3G.js";
|
|
28
31
|
import {
|
|
29
32
|
OAUTH2_DEFAULT_TIMEOUT_MS,
|
|
30
33
|
assertSupportedOAuthEndpointUrl,
|
|
@@ -695,10 +698,6 @@ var TOOL_POLICY_ACTIONS = [
|
|
|
695
698
|
];
|
|
696
699
|
var isToolPolicyAction = (value) => typeof value === "string" && TOOL_POLICY_ACTIONS.includes(value);
|
|
697
700
|
|
|
698
|
-
// src/oauth.ts
|
|
699
|
-
var OAUTH2_PROVIDER_KEY = "oauth2";
|
|
700
|
-
var OAUTH2_SESSION_TTL_MS = 15 * 60 * 1e3;
|
|
701
|
-
|
|
702
701
|
// src/plugin-storage.ts
|
|
703
702
|
var definePluginStorageCollection = (name, schema, options) => ({
|
|
704
703
|
name,
|
|
@@ -3848,7 +3847,7 @@ var coreToolsPlugin = definePlugin((options = {}) => ({
|
|
|
3848
3847
|
}));
|
|
3849
3848
|
|
|
3850
3849
|
// src/oauth-service.ts
|
|
3851
|
-
import { Effect as Effect7, Option as Option2, Schema as Schema4 } from "effect";
|
|
3850
|
+
import { Duration as Duration2, Effect as Effect7, Option as Option2, Schema as Schema4 } from "effect";
|
|
3852
3851
|
import { FetchHttpClient as FetchHttpClient2 } from "effect/unstable/http";
|
|
3853
3852
|
|
|
3854
3853
|
// src/oauth-discovery.ts
|
|
@@ -4278,6 +4277,48 @@ var makeOAuthService = (deps) => {
|
|
|
4278
4277
|
const httpClientLayer = deps.httpClientLayer ?? FetchHttpClient2.layer;
|
|
4279
4278
|
const fetch = deps.fetch;
|
|
4280
4279
|
const redirectUri = deps.redirectUri;
|
|
4280
|
+
const MAX_DISCOVERY_AUTH_SERVERS = 3;
|
|
4281
|
+
const MAX_DISCOVERED_SCOPES = 100;
|
|
4282
|
+
const capScopes = (scopes) => dedupeScopes(scopes).slice(0, MAX_DISCOVERED_SCOPES);
|
|
4283
|
+
const discoverScopesForResource = (resource) => Effect7.gen(function* () {
|
|
4284
|
+
if (resource == null) {
|
|
4285
|
+
return yield* new OAuthDiscoveryError({
|
|
4286
|
+
message: "Cannot discover OAuth scopes: the client has no resource configured"
|
|
4287
|
+
});
|
|
4288
|
+
}
|
|
4289
|
+
const discoveryOptions = { endpointUrlPolicy: deps.endpointUrlPolicy, httpClientLayer };
|
|
4290
|
+
const protectedResource = yield* discoverProtectedResourceMetadata(
|
|
4291
|
+
resource,
|
|
4292
|
+
discoveryOptions
|
|
4293
|
+
);
|
|
4294
|
+
const resourceScopes = protectedResource?.metadata.scopes_supported;
|
|
4295
|
+
if (resourceScopes !== void 0) return capScopes(resourceScopes);
|
|
4296
|
+
for (const issuer of (protectedResource?.metadata.authorization_servers ?? []).slice(
|
|
4297
|
+
0,
|
|
4298
|
+
MAX_DISCOVERY_AUTH_SERVERS
|
|
4299
|
+
)) {
|
|
4300
|
+
const authServer = yield* discoverAuthorizationServerMetadata(
|
|
4301
|
+
issuer,
|
|
4302
|
+
discoveryOptions
|
|
4303
|
+
).pipe(Effect7.catchTag("OAuthDiscoveryError", () => Effect7.succeed(null)));
|
|
4304
|
+
const scopes = authServer?.metadata.scopes_supported;
|
|
4305
|
+
if (scopes !== void 0) return capScopes(scopes);
|
|
4306
|
+
}
|
|
4307
|
+
return [];
|
|
4308
|
+
}).pipe(
|
|
4309
|
+
// Bound the whole sequence (PRM + up to MAX_DISCOVERY_AUTH_SERVERS AS
|
|
4310
|
+
// fetches, each with its own request timeout). 30s is larger than a single
|
|
4311
|
+
// request timeout so it bounds the sequence, not a slow-but-valid request.
|
|
4312
|
+
Effect7.timeoutOrElse({
|
|
4313
|
+
duration: Duration2.seconds(30),
|
|
4314
|
+
orElse: () => Effect7.fail(
|
|
4315
|
+
new OAuthDiscoveryError({
|
|
4316
|
+
message: "OAuth scope discovery timed out",
|
|
4317
|
+
cause: "timeout"
|
|
4318
|
+
})
|
|
4319
|
+
)
|
|
4320
|
+
})
|
|
4321
|
+
);
|
|
4281
4322
|
const createClient = (input) => Effect7.gen(function* () {
|
|
4282
4323
|
yield* validateClientEndpoints(input, deps.endpointUrlPolicy);
|
|
4283
4324
|
const keys = yield* Effect7.try({
|
|
@@ -4465,15 +4506,22 @@ var makeOAuthService = (deps) => {
|
|
|
4465
4506
|
message: `OAuth client not found: ${input.client}`
|
|
4466
4507
|
});
|
|
4467
4508
|
}
|
|
4468
|
-
const
|
|
4509
|
+
const scopePolicy = yield* deps.resolveOAuthScopePolicy(input.integration, input.template).pipe(
|
|
4469
4510
|
Effect7.mapError(
|
|
4470
4511
|
(cause) => new OAuthStartError({
|
|
4471
4512
|
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: StorageFailure carries a typed `message` field
|
|
4472
|
-
message: `Failed to resolve
|
|
4513
|
+
message: `Failed to resolve OAuth scope policy: ${cause.message}`
|
|
4473
4514
|
})
|
|
4474
4515
|
)
|
|
4475
4516
|
);
|
|
4476
|
-
const requestedScopes =
|
|
4517
|
+
const requestedScopes = scopePolicy.kind === "discover" ? yield* discoverScopesForResource(client.resource).pipe(
|
|
4518
|
+
Effect7.mapError(
|
|
4519
|
+
(cause) => new OAuthStartError({
|
|
4520
|
+
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: OAuthDiscoveryError carries a typed `message` field
|
|
4521
|
+
message: `Failed to discover OAuth scopes: ${cause.message}`
|
|
4522
|
+
})
|
|
4523
|
+
)
|
|
4524
|
+
) : dedupeScopes(scopePolicy.scopes);
|
|
4477
4525
|
if (client.grant === "client_credentials") {
|
|
4478
4526
|
const token = yield* exchangeClientCredentials({
|
|
4479
4527
|
tokenUrl: client.tokenUrl,
|
|
@@ -4518,6 +4566,10 @@ var makeOAuthService = (deps) => {
|
|
|
4518
4566
|
const verifier = createPkceCodeVerifier();
|
|
4519
4567
|
const challenge = yield* Effect7.promise(() => createPkceCodeChallenge(verifier));
|
|
4520
4568
|
const state = OAuthState.make(createOAuthState());
|
|
4569
|
+
const providerState = encodeOAuthCallbackState({
|
|
4570
|
+
state: String(state),
|
|
4571
|
+
orgSlug: deps.callbackStateOrgSlug
|
|
4572
|
+
});
|
|
4521
4573
|
const now = /* @__PURE__ */ new Date();
|
|
4522
4574
|
const expiresAt = Date.now() + OAUTH2_SESSION_TTL_MS;
|
|
4523
4575
|
yield* deps.fuma.use(
|
|
@@ -4534,10 +4586,10 @@ var makeOAuthService = (deps) => {
|
|
|
4534
4586
|
redirect_url: flowRedirectUri,
|
|
4535
4587
|
pkce_verifier: verifier,
|
|
4536
4588
|
identity_label: input.identityLabel ?? null,
|
|
4537
|
-
// Persist the requested scope set (
|
|
4538
|
-
// recorded-scope fallback reflects
|
|
4539
|
-
// AS omits `scope`, without
|
|
4540
|
-
//
|
|
4589
|
+
// Persist the requested scope set (the integration's declared or
|
|
4590
|
+
// discovered scopes) so `complete`'s recorded-scope fallback reflects
|
|
4591
|
+
// exactly what was requested when the AS omits `scope`, without
|
|
4592
|
+
// re-resolving it at completion.
|
|
4541
4593
|
payload: { owner: input.owner, clientOwner: input.clientOwner, requestedScopes },
|
|
4542
4594
|
expires_at: expiresAt,
|
|
4543
4595
|
created_at: now
|
|
@@ -4549,7 +4601,7 @@ var makeOAuthService = (deps) => {
|
|
|
4549
4601
|
clientId: client.clientId,
|
|
4550
4602
|
redirectUrl: flowRedirectUri,
|
|
4551
4603
|
scopes: requestedScopes,
|
|
4552
|
-
state:
|
|
4604
|
+
state: providerState,
|
|
4553
4605
|
codeChallenge: challenge,
|
|
4554
4606
|
resource: client.resource ?? void 0,
|
|
4555
4607
|
// Provider quirks (Google: access_type=offline + prompt=consent) —
|
|
@@ -4585,9 +4637,10 @@ var makeOAuthService = (deps) => {
|
|
|
4585
4637
|
pkceVerifier: sessionRow.pkce_verifier == null ? null : String(sessionRow.pkce_verifier),
|
|
4586
4638
|
identityLabel: sessionRow.identity_label == null ? null : String(sessionRow.identity_label),
|
|
4587
4639
|
expiresAt: Number(sessionRow.expires_at),
|
|
4588
|
-
// The scope set `start` requested (
|
|
4589
|
-
//
|
|
4590
|
-
//
|
|
4640
|
+
// The scope set `start` requested (the integration's declared or
|
|
4641
|
+
// discovered scopes), persisted on the session payload. Drives the
|
|
4642
|
+
// recorded-scope fallback when the AS omits `scope`. Missing/legacy
|
|
4643
|
+
// payloads fall back to the client's scopes below.
|
|
4591
4644
|
requestedScopes: requestedScopesFromPayload(sessionRow.payload),
|
|
4592
4645
|
// The app's owner, recorded by `start` — reload the SAME app at
|
|
4593
4646
|
// completion by explicit owner (no derivation). Defaults to the session
|
|
@@ -4728,7 +4781,13 @@ var makeOAuthService = (deps) => {
|
|
|
4728
4781
|
authorizationUrl: as.metadata.authorization_endpoint,
|
|
4729
4782
|
tokenUrl: as.metadata.token_endpoint,
|
|
4730
4783
|
resource: resource?.metadata.resource ?? null,
|
|
4731
|
-
|
|
4784
|
+
// Prefer the resource's own RFC 9728 scopes (authoritative, even when
|
|
4785
|
+
// empty); fall back to the authorization server's list only when PRM is
|
|
4786
|
+
// silent. For a spec-compliant MCP server (one that publishes PRM) this
|
|
4787
|
+
// matches what `oauth.start` discovers. The AS fallback is a best-effort
|
|
4788
|
+
// hint for the registration form on servers that omit PRM — where
|
|
4789
|
+
// `oauth.start` requests none — so the two can differ for those.
|
|
4790
|
+
scopesSupported: resource?.metadata.scopes_supported ?? as.metadata.scopes_supported,
|
|
4732
4791
|
registrationEndpoint: as.metadata.registration_endpoint ?? null,
|
|
4733
4792
|
tokenEndpointAuthMethodsSupported: as.metadata.token_endpoint_auth_methods_supported
|
|
4734
4793
|
};
|
|
@@ -5328,6 +5387,7 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
5328
5387
|
const transaction = (effect) => fuma.transaction(effect);
|
|
5329
5388
|
const staticTools = /* @__PURE__ */ new Map();
|
|
5330
5389
|
const runtimes = /* @__PURE__ */ new Map();
|
|
5390
|
+
let activeToolPolicyProvider = null;
|
|
5331
5391
|
const credentialProviders = /* @__PURE__ */ new Map();
|
|
5332
5392
|
const credentialProviderOrder = [];
|
|
5333
5393
|
const staticToolOwner = () => subject == null ? "org" : "user";
|
|
@@ -6055,12 +6115,25 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
6055
6115
|
updated_at: now
|
|
6056
6116
|
});
|
|
6057
6117
|
});
|
|
6058
|
-
const connectionsList = (filter) =>
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6118
|
+
const connectionsList = (filter) => Effect8.gen(function* () {
|
|
6119
|
+
const rows = yield* core.findMany("connection", {
|
|
6120
|
+
where: (b) => b.and(
|
|
6121
|
+
filter?.integration === void 0 ? true : b("integration", "=", String(filter.integration)),
|
|
6122
|
+
filter?.owner === void 0 ? true : b("owner", "=", filter.owner)
|
|
6123
|
+
)
|
|
6124
|
+
});
|
|
6125
|
+
const connections = rows.map(rowToConnection);
|
|
6126
|
+
if (!activeToolPolicyProvider) return connections;
|
|
6127
|
+
const visibleTools = yield* toolsList({ includeAnnotations: false });
|
|
6128
|
+
const visibleConnectionKeys = new Set(
|
|
6129
|
+
visibleTools.filter((tool2) => !tool2.static).map((tool2) => `${tool2.owner}:${tool2.integration}:${tool2.connection}`)
|
|
6130
|
+
);
|
|
6131
|
+
return connections.filter(
|
|
6132
|
+
(connection) => visibleConnectionKeys.has(
|
|
6133
|
+
`${connection.owner}:${connection.integration}:${connection.name}`
|
|
6134
|
+
)
|
|
6135
|
+
);
|
|
6136
|
+
});
|
|
6064
6137
|
const connectionsGet = (ref) => findConnectionRow(ref).pipe(Effect8.map((row) => row ? rowToConnection(row) : null));
|
|
6065
6138
|
const connectionsUpdate = (ref, input) => Effect8.gen(function* () {
|
|
6066
6139
|
const row = yield* findConnectionRow(ref);
|
|
@@ -6139,6 +6212,51 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
6139
6212
|
}
|
|
6140
6213
|
return yield* produceConnectionTools(integrationRow, ref);
|
|
6141
6214
|
});
|
|
6215
|
+
const compareProviderPolicyRule = (a, b) => {
|
|
6216
|
+
if (a.position < b.position) return -1;
|
|
6217
|
+
if (a.position > b.position) return 1;
|
|
6218
|
+
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
6219
|
+
};
|
|
6220
|
+
const resolveProviderPolicyFromRules = (toolId, rules3) => {
|
|
6221
|
+
for (const rule of [...rules3].sort(compareProviderPolicyRule)) {
|
|
6222
|
+
if (!matchPattern(rule.pattern, toolId)) continue;
|
|
6223
|
+
return {
|
|
6224
|
+
action: rule.action,
|
|
6225
|
+
source: "user",
|
|
6226
|
+
pattern: rule.pattern,
|
|
6227
|
+
policyId: rule.id
|
|
6228
|
+
};
|
|
6229
|
+
}
|
|
6230
|
+
return {
|
|
6231
|
+
action: "block",
|
|
6232
|
+
source: "user",
|
|
6233
|
+
pattern: "*"
|
|
6234
|
+
};
|
|
6235
|
+
};
|
|
6236
|
+
const listActivePolicyRuleSet = () => activeToolPolicyProvider ? (
|
|
6237
|
+
// Batched per-operation resolver: fetch all policy + connection state
|
|
6238
|
+
// once, then resolve every tool in this operation against that
|
|
6239
|
+
// snapshot. Avoids the per-tool resolve N+1 on the list surface.
|
|
6240
|
+
activeToolPolicyProvider.prepare ? activeToolPolicyProvider.prepare().pipe(Effect8.map((resolve) => ({ kind: "prepared", resolve }))) : activeToolPolicyProvider.resolve ? Effect8.succeed({
|
|
6241
|
+
kind: "provider",
|
|
6242
|
+
provider: activeToolPolicyProvider,
|
|
6243
|
+
rules: null
|
|
6244
|
+
}) : activeToolPolicyProvider.list().pipe(
|
|
6245
|
+
Effect8.map((rules3) => ({
|
|
6246
|
+
kind: "provider",
|
|
6247
|
+
provider: activeToolPolicyProvider,
|
|
6248
|
+
rules: rules3
|
|
6249
|
+
}))
|
|
6250
|
+
)
|
|
6251
|
+
) : core.findMany("tool_policy", {}).pipe(Effect8.map((rows) => ({ kind: "global", rows })));
|
|
6252
|
+
const resolvePolicyFromRuleSet = (toolId, ruleSet, defaultRequiresApproval) => ruleSet.kind === "prepared" ? Effect8.succeed(ruleSet.resolve({ toolId, defaultRequiresApproval })) : ruleSet.kind === "provider" ? ruleSet.provider.resolve ? ruleSet.provider.resolve({ toolId, defaultRequiresApproval }) : Effect8.succeed(resolveProviderPolicyFromRules(toolId, ruleSet.rules ?? [])) : Effect8.succeed(
|
|
6253
|
+
resolveEffectivePolicy(
|
|
6254
|
+
toolId,
|
|
6255
|
+
ruleSet.rows,
|
|
6256
|
+
ownerRankForRow,
|
|
6257
|
+
defaultRequiresApproval
|
|
6258
|
+
)
|
|
6259
|
+
);
|
|
6142
6260
|
const matchesToolFilter = (tool2, filter) => {
|
|
6143
6261
|
if (!filter) return true;
|
|
6144
6262
|
if (filter.integration !== void 0 && tool2.integration !== filter.integration) return false;
|
|
@@ -6195,16 +6313,15 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
6195
6313
|
select: TOOL_INVOCATION_COLUMNS
|
|
6196
6314
|
});
|
|
6197
6315
|
const includeBlocked = filter?.includeBlocked ?? false;
|
|
6198
|
-
const
|
|
6316
|
+
const policyRules = yield* listActivePolicyRuleSet();
|
|
6199
6317
|
const tools = [];
|
|
6200
6318
|
for (const row of rows) {
|
|
6201
6319
|
const tool2 = rowToTool(row);
|
|
6202
6320
|
if (!matchesToolFilter(tool2, filter)) continue;
|
|
6203
6321
|
if (!includeBlocked) {
|
|
6204
|
-
const effective =
|
|
6322
|
+
const effective = yield* resolvePolicyFromRuleSet(
|
|
6205
6323
|
normalizedPolicyId(tool2),
|
|
6206
|
-
|
|
6207
|
-
ownerRankForRow,
|
|
6324
|
+
policyRules,
|
|
6208
6325
|
tool2.annotations?.requiresApproval
|
|
6209
6326
|
);
|
|
6210
6327
|
if (effective.action === "block") continue;
|
|
@@ -6215,10 +6332,9 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
6215
6332
|
const tool2 = staticToolToTool(entry);
|
|
6216
6333
|
if (!matchesToolFilter(tool2, filter)) continue;
|
|
6217
6334
|
if (!includeBlocked) {
|
|
6218
|
-
const effective =
|
|
6335
|
+
const effective = yield* resolvePolicyFromRuleSet(
|
|
6219
6336
|
normalizedPolicyId(tool2),
|
|
6220
|
-
|
|
6221
|
-
ownerRankForRow,
|
|
6337
|
+
policyRules,
|
|
6222
6338
|
tool2.annotations?.requiresApproval
|
|
6223
6339
|
);
|
|
6224
6340
|
if (effective.action === "block") continue;
|
|
@@ -6228,9 +6344,16 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
6228
6344
|
return tools;
|
|
6229
6345
|
});
|
|
6230
6346
|
const toolSchema = (address) => Effect8.gen(function* () {
|
|
6347
|
+
const policyRules = yield* listActivePolicyRuleSet();
|
|
6231
6348
|
const staticEntry = staticTools.get(String(address));
|
|
6232
6349
|
if (staticEntry) {
|
|
6233
6350
|
const tool3 = staticToolToTool(staticEntry);
|
|
6351
|
+
const effective2 = yield* resolvePolicyFromRuleSet(
|
|
6352
|
+
normalizedPolicyId(tool3),
|
|
6353
|
+
policyRules,
|
|
6354
|
+
tool3.annotations?.requiresApproval
|
|
6355
|
+
);
|
|
6356
|
+
if (effective2.action === "block") return null;
|
|
6234
6357
|
const preview2 = yield* Effect8.tryPromise({
|
|
6235
6358
|
try: () => buildToolTypeScriptPreview({
|
|
6236
6359
|
inputSchema: tool3.inputSchema,
|
|
@@ -6262,6 +6385,12 @@ var createExecutor = (config) => Effect8.gen(function* () {
|
|
|
6262
6385
|
});
|
|
6263
6386
|
if (!row) return null;
|
|
6264
6387
|
const tool2 = rowToTool(row);
|
|
6388
|
+
const effective = yield* resolvePolicyFromRuleSet(
|
|
6389
|
+
normalizedPolicyId(tool2),
|
|
6390
|
+
policyRules,
|
|
6391
|
+
tool2.annotations?.requiresApproval
|
|
6392
|
+
);
|
|
6393
|
+
if (effective.action === "block") return null;
|
|
6265
6394
|
const definitionRows = yield* core.findMany("definition", {
|
|
6266
6395
|
where: (b) => b.and(
|
|
6267
6396
|
byOwner(parsed.owner)(b),
|
|
@@ -6482,11 +6611,10 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6482
6611
|
);
|
|
6483
6612
|
const staticEntry = staticTools.get(String(address));
|
|
6484
6613
|
if (staticEntry) {
|
|
6485
|
-
const
|
|
6486
|
-
const policy2 =
|
|
6614
|
+
const policyRules2 = yield* listActivePolicyRuleSet();
|
|
6615
|
+
const policy2 = yield* resolvePolicyFromRuleSet(
|
|
6487
6616
|
String(address),
|
|
6488
|
-
|
|
6489
|
-
ownerRankForRow,
|
|
6617
|
+
policyRules2,
|
|
6490
6618
|
staticEntry.tool.annotations?.requiresApproval
|
|
6491
6619
|
);
|
|
6492
6620
|
if (policy2.action === "block") {
|
|
@@ -6526,12 +6654,11 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6526
6654
|
});
|
|
6527
6655
|
}
|
|
6528
6656
|
const toolForPolicy = rowToTool(row);
|
|
6529
|
-
const
|
|
6657
|
+
const policyRules = yield* listActivePolicyRuleSet();
|
|
6530
6658
|
const annotations = decodeJsonColumn(row.annotations);
|
|
6531
|
-
const policy =
|
|
6659
|
+
const policy = yield* resolvePolicyFromRuleSet(
|
|
6532
6660
|
normalizedPolicyId(toolForPolicy),
|
|
6533
|
-
|
|
6534
|
-
ownerRankForRow,
|
|
6661
|
+
policyRules,
|
|
6535
6662
|
annotations?.requiresApproval
|
|
6536
6663
|
);
|
|
6537
6664
|
if (policy.action === "block") {
|
|
@@ -6620,21 +6747,22 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6620
6747
|
ownedKeys: (owner) => ownedKeys(owner),
|
|
6621
6748
|
defaultWritableProvider,
|
|
6622
6749
|
mintOAuthConnection: (input) => mintOAuthConnection(input),
|
|
6623
|
-
//
|
|
6624
|
-
// template
|
|
6625
|
-
//
|
|
6626
|
-
//
|
|
6627
|
-
//
|
|
6628
|
-
//
|
|
6629
|
-
//
|
|
6630
|
-
|
|
6750
|
+
// One integration-row read + one projector run. Resolve the method this
|
|
6751
|
+
// template selects exactly as the runtime's `selectAuthMethod` does —
|
|
6752
|
+
// exact slug match, else the sole declared method (single-method
|
|
6753
|
+
// integrations accept any slug); an ambiguous miss selects nothing rather
|
|
6754
|
+
// than guessing across methods. The discover-vs-scopes choice then reads
|
|
6755
|
+
// off that method (MCP exposes `discoveryUrl`), so core needs no plugin-id
|
|
6756
|
+
// knowledge.
|
|
6757
|
+
resolveOAuthScopePolicy: (integration, template) => findIntegrationRow(integration).pipe(
|
|
6631
6758
|
Effect8.map((row) => {
|
|
6632
|
-
|
|
6633
|
-
const
|
|
6634
|
-
const
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6759
|
+
const methods = row ? describeAuthMethodsForRow(row) : [];
|
|
6760
|
+
const selected = methods.find((m) => m.template === String(template)) ?? (methods.length === 1 ? methods[0] : void 0);
|
|
6761
|
+
const oauth2 = selected?.kind === "oauth" ? selected.oauth : void 0;
|
|
6762
|
+
if (oauth2?.scopes === void 0 && oauth2?.discoveryUrl !== void 0) {
|
|
6763
|
+
return { kind: "discover" };
|
|
6764
|
+
}
|
|
6765
|
+
return { kind: "scopes", scopes: oauth2?.scopes ?? [] };
|
|
6638
6766
|
})
|
|
6639
6767
|
),
|
|
6640
6768
|
httpClientLayer: config.httpClientLayer,
|
|
@@ -6644,7 +6772,8 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6644
6772
|
// OAuth service receives `null` and redirect-requiring flows fail loudly
|
|
6645
6773
|
// instead of silently using `http://127.0.0.1/callback`. Hosts that serve
|
|
6646
6774
|
// OAuth (cloud, self-host) derive a real `${webBaseUrl}/oauth/callback`.
|
|
6647
|
-
redirectUri: config.redirectUri ?? null
|
|
6775
|
+
redirectUri: config.redirectUri ?? null,
|
|
6776
|
+
callbackStateOrgSlug: config.oauthCallbackStateOrgSlug ?? null
|
|
6648
6777
|
});
|
|
6649
6778
|
const blobPartitions = {
|
|
6650
6779
|
org: `o:${tenant}`,
|
|
@@ -6718,6 +6847,19 @@ ${approvalArgumentPreview(args)}`,
|
|
|
6718
6847
|
oauth,
|
|
6719
6848
|
transaction: (effect) => transaction(effect)
|
|
6720
6849
|
};
|
|
6850
|
+
if (plugin.toolPolicyProvider) {
|
|
6851
|
+
const rawProvider = plugin.toolPolicyProvider(ctx);
|
|
6852
|
+
const provider = Effect8.isEffect(rawProvider) ? yield* rawProvider : rawProvider;
|
|
6853
|
+
if (provider) {
|
|
6854
|
+
if (activeToolPolicyProvider) {
|
|
6855
|
+
return yield* new StorageError({
|
|
6856
|
+
message: "Only one plugin can provide the active tool policy source.",
|
|
6857
|
+
cause: void 0
|
|
6858
|
+
});
|
|
6859
|
+
}
|
|
6860
|
+
activeToolPolicyProvider = provider;
|
|
6861
|
+
}
|
|
6862
|
+
}
|
|
6721
6863
|
const extension = plugin.extension ? plugin.extension(ctx) : {};
|
|
6722
6864
|
if (plugin.extension) {
|
|
6723
6865
|
extensions[plugin.id] = extension;
|
|
@@ -6845,8 +6987,6 @@ export {
|
|
|
6845
6987
|
coreSchema,
|
|
6846
6988
|
TOOL_POLICY_ACTIONS,
|
|
6847
6989
|
isToolPolicyAction,
|
|
6848
|
-
OAUTH2_PROVIDER_KEY,
|
|
6849
|
-
OAUTH2_SESSION_TTL_MS,
|
|
6850
6990
|
definePluginStorageCollection,
|
|
6851
6991
|
pluginStorageId,
|
|
6852
6992
|
buildToolTypeScriptPreview,
|
|
@@ -6862,4 +7002,4 @@ export {
|
|
|
6862
7002
|
collectTables,
|
|
6863
7003
|
createExecutor
|
|
6864
7004
|
};
|
|
6865
|
-
//# sourceMappingURL=chunk-
|
|
7005
|
+
//# sourceMappingURL=chunk-GUZHNTDQ.js.map
|