@opengeni/core 1.2.1-canary.37222965366001 → 1.3.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.
- package/dist/canonical-human-identities.js +1 -1
- package/dist/{chunk-MM6N7CTO.js → chunk-672TAJCH.js} +45 -5
- package/dist/chunk-672TAJCH.js.map +1 -0
- package/dist/domain/connector-tool-permissions.d.ts +2 -0
- package/dist/domain/knowledge-messages.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +176 -72
- package/dist/index.js.map +1 -1
- package/dist/managed-session.d.ts +4 -1
- package/package.json +12 -12
- package/src/application/api-integration-servers.ts +9 -0
- package/src/domain/connector-tool-permissions.ts +177 -67
- package/src/domain/sessions.ts +2 -2
- package/src/domain/slack-bot.ts +15 -3
- package/src/index.ts +2 -0
- package/src/managed-session.ts +59 -5
- package/dist/chunk-MM6N7CTO.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -8,9 +8,11 @@ import {
|
|
|
8
8
|
getManagedAuthRequestActorLeaseStamp,
|
|
9
9
|
getManagedSession,
|
|
10
10
|
markManagedAuthRequestActorTransitionApplied,
|
|
11
|
+
recordManagedAuthLoggedFailure,
|
|
11
12
|
releaseManagedAuthRequestActorLease,
|
|
12
|
-
validateManagedAuthRequestActorLease
|
|
13
|
-
|
|
13
|
+
validateManagedAuthRequestActorLease,
|
|
14
|
+
withManagedAuthSessionLookup
|
|
15
|
+
} from "./chunk-672TAJCH.js";
|
|
14
16
|
import "./chunk-QO5GVFFO.js";
|
|
15
17
|
import {
|
|
16
18
|
EDITABLE_ARTIFACT_HINT_MAX_BYTES,
|
|
@@ -835,7 +837,7 @@ function expandApiIntegrationAccountRoutes(input) {
|
|
|
835
837
|
}
|
|
836
838
|
|
|
837
839
|
// src/domain/session-connection-accounts.ts
|
|
838
|
-
import { requireSession as requireSession3, requireWorkspace as
|
|
840
|
+
import { requireSession as requireSession3, requireWorkspace as requireWorkspace6 } from "@opengeni/db";
|
|
839
841
|
|
|
840
842
|
// src/domain/capabilities.ts
|
|
841
843
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
@@ -4886,7 +4888,7 @@ import {
|
|
|
4886
4888
|
listDistinctRigVersionIdsInGroup,
|
|
4887
4889
|
listInstalledPortableSkills,
|
|
4888
4890
|
listEnabledMcpCapabilityServers as listEnabledMcpCapabilityServers2,
|
|
4889
|
-
|
|
4891
|
+
resolveMcpApprovalRecommendation,
|
|
4890
4892
|
getSandbox as getSandbox4,
|
|
4891
4893
|
getSession as getSession3,
|
|
4892
4894
|
getInitializedSessionCreateReplay,
|
|
@@ -4903,7 +4905,7 @@ import {
|
|
|
4903
4905
|
getSessionTurnXaiProviderAccountAuthoritySnapshot,
|
|
4904
4906
|
getSessionTurnClaudeProviderAccountAuthoritySnapshot,
|
|
4905
4907
|
getWorkspaceModelPolicy as getWorkspaceModelPolicy2,
|
|
4906
|
-
requireWorkspace as
|
|
4908
|
+
requireWorkspace as requireWorkspace5,
|
|
4907
4909
|
initializeSessionStartAtomically,
|
|
4908
4910
|
listSessionTurns,
|
|
4909
4911
|
listSessionMcpServersForChildInheritance,
|
|
@@ -8444,7 +8446,9 @@ import {
|
|
|
8444
8446
|
areOpenGeniSlackBotScopesAccepted
|
|
8445
8447
|
} from "@opengeni/contracts";
|
|
8446
8448
|
import {
|
|
8447
|
-
getConnectionMetadata as getConnectionMetadata3
|
|
8449
|
+
getConnectionMetadata as getConnectionMetadata3,
|
|
8450
|
+
availableSlackBotConnectionMetadata,
|
|
8451
|
+
requireWorkspace as requireWorkspace4
|
|
8448
8452
|
} from "@opengeni/db";
|
|
8449
8453
|
import { HTTPException as HTTPException16 } from "hono/http-exception";
|
|
8450
8454
|
function openGeniSlackBotMetadata(metadata) {
|
|
@@ -8463,7 +8467,9 @@ function hasReservedOpenGeniSlackBotSessionMetadata(metadata) {
|
|
|
8463
8467
|
);
|
|
8464
8468
|
}
|
|
8465
8469
|
async function requireOpenGeniSlackBotConnection(db, workspaceId, connectionId) {
|
|
8466
|
-
const
|
|
8470
|
+
const local = await getConnectionMetadata3(db, workspaceId, connectionId, null);
|
|
8471
|
+
const workspace = await requireWorkspace4(db, workspaceId);
|
|
8472
|
+
const connection = local ?? (await availableSlackBotConnectionMetadata(db, { accountId: workspace.accountId, workspaceId })).find((candidate) => candidate.id === connectionId) ?? null;
|
|
8467
8473
|
if (!connection || !isOpenGeniSlackBotConnection(connection)) {
|
|
8468
8474
|
throw new HTTPException16(422, {
|
|
8469
8475
|
message: "slackBotConnectionId must reference an Opengeni Slack bot connection"
|
|
@@ -8536,9 +8542,10 @@ async function validateScheduledTaskSlackChannel(input) {
|
|
|
8536
8542
|
});
|
|
8537
8543
|
}
|
|
8538
8544
|
function withScheduledSlackBotPostingTools(tools, agentConfig, allowedTools) {
|
|
8539
|
-
|
|
8545
|
+
const posting = new Set(SCHEDULED_SLACK_BOT_POSTING_TOOLS);
|
|
8546
|
+
const next = tools.filter((tool) => !posting.has(tool));
|
|
8547
|
+
if (!agentConfig.slackBotConnectionId || !agentConfig.slackBotChannelId) return next;
|
|
8540
8548
|
const allowed = new Set(allowedTools);
|
|
8541
|
-
const next = [...tools];
|
|
8542
8549
|
for (const tool of SCHEDULED_SLACK_BOT_POSTING_TOOLS) {
|
|
8543
8550
|
if (allowed.has(tool) && !next.includes(tool)) next.push(tool);
|
|
8544
8551
|
}
|
|
@@ -10212,7 +10219,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
|
|
|
10212
10219
|
const workspace = await measureSessionStartPhase(
|
|
10213
10220
|
unresolvedDeps.observability,
|
|
10214
10221
|
"workspace_read",
|
|
10215
|
-
() =>
|
|
10222
|
+
() => requireWorkspace5(db, workspaceId)
|
|
10216
10223
|
);
|
|
10217
10224
|
const workspaceSessionToolDefaults = resolveWorkspaceSessionToolDefaults2(workspace.settings);
|
|
10218
10225
|
const parentAuthority = parentSession ? await getSessionAuthorityProjection4(db, workspaceId, parentSession.id) : null;
|
|
@@ -10480,7 +10487,7 @@ async function createSessionForRequestInFileScope(unresolvedDeps, grant, workspa
|
|
|
10480
10487
|
message: `MCP approval policy must name an enabled inherited capability: ${id}${/^api_(openapi|graphql)_/.test(id) ? "; API Integration tool approval is set at install with autoApprovedTools" : ""}`
|
|
10481
10488
|
});
|
|
10482
10489
|
}
|
|
10483
|
-
mcpApprovalPolicies[id] =
|
|
10490
|
+
mcpApprovalPolicies[id] = resolveMcpApprovalRecommendation(policy, inherited.approvalFloor) ?? false;
|
|
10484
10491
|
}
|
|
10485
10492
|
}
|
|
10486
10493
|
const resources = normalizeResources(
|
|
@@ -11454,7 +11461,7 @@ async function acceptSessionUserMessageInFileScope(deps, grant, workspaceId, ses
|
|
|
11454
11461
|
runtimeMcpServers: runtimeSettings.mcpServers,
|
|
11455
11462
|
defaultMcpServerIds: workspaceSessionToolPolicyDefaultServerIdsFor(
|
|
11456
11463
|
capabilityRuntimeSettings.mcpServers,
|
|
11457
|
-
(await
|
|
11464
|
+
(await requireWorkspace5(db, workspaceId)).settings
|
|
11458
11465
|
)
|
|
11459
11466
|
});
|
|
11460
11467
|
const { personalConnectionDelegations, mcpAccountBindings } = await freezeConnectionAccounts({
|
|
@@ -11765,7 +11772,7 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
11765
11772
|
requirePermission(grant, "sessions:control");
|
|
11766
11773
|
const agentAttemptCaller = grantHasAgentAttemptAuthority(grant);
|
|
11767
11774
|
const existingSession = await requireSession2(deps.db, grant.workspaceId, sessionId);
|
|
11768
|
-
const workspace = await
|
|
11775
|
+
const workspace = await requireWorkspace5(deps.db, grant.workspaceId);
|
|
11769
11776
|
const workspaceSessionToolDefaults = resolveWorkspaceSessionToolDefaults2(workspace.settings);
|
|
11770
11777
|
const capabilityRuntimeSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
11771
11778
|
deps.db,
|
|
@@ -12032,7 +12039,7 @@ async function updateSessionAgent(deps, grant, sessionId, request) {
|
|
|
12032
12039
|
});
|
|
12033
12040
|
requirePermission(grant, "sessions:control");
|
|
12034
12041
|
const agentAttemptCaller = grantHasAgentAttemptAuthority(grant);
|
|
12035
|
-
const workspace = await
|
|
12042
|
+
const workspace = await requireWorkspace5(deps.db, grant.workspaceId);
|
|
12036
12043
|
const goal = await getSessionGoal(deps.db, grant.workspaceId, sessionId);
|
|
12037
12044
|
const goalOpen = goal !== null && goal.status !== "completed";
|
|
12038
12045
|
const deploymentPolicy = agentConfigDeploymentPolicy2(deps.settings);
|
|
@@ -12319,7 +12326,7 @@ async function freezeSessionRealtimeConnectionAccounts(input) {
|
|
|
12319
12326
|
runtimeMcpServers: runtimeSettings.mcpServers,
|
|
12320
12327
|
defaultMcpServerIds: workspaceSessionToolPolicyDefaultServerIdsFor(
|
|
12321
12328
|
capabilitySettings.mcpServers,
|
|
12322
|
-
(await
|
|
12329
|
+
(await requireWorkspace6(db, workspaceId)).settings
|
|
12323
12330
|
)
|
|
12324
12331
|
});
|
|
12325
12332
|
return await freezeConnectionAccounts({
|
|
@@ -13001,7 +13008,7 @@ import {
|
|
|
13001
13008
|
grantWorkspaceAccess,
|
|
13002
13009
|
listWorkspaceMembers,
|
|
13003
13010
|
lockExternalWorkspaceMembershipLifecycle as lockExternalWorkspaceMembershipLifecycle3,
|
|
13004
|
-
requireWorkspace as
|
|
13011
|
+
requireWorkspace as requireWorkspace7,
|
|
13005
13012
|
setRlsContext,
|
|
13006
13013
|
withWorkspaceSubjectRls as withWorkspaceSubjectRls3,
|
|
13007
13014
|
addExternalWorkspaceMemberOperation,
|
|
@@ -13061,7 +13068,7 @@ async function addExternalWorkspaceMemberForRequest(c, deps, workspaceId, input)
|
|
|
13061
13068
|
if (live.accountId !== grant.accountId || live.subjectId !== grant.subjectId || payload.permissions.some((permission) => !hasPermission(live.permissions, permission))) {
|
|
13062
13069
|
throw new HTTPException18(403, { message: "membership authority changed" });
|
|
13063
13070
|
}
|
|
13064
|
-
const workspace = await
|
|
13071
|
+
const workspace = await requireWorkspace7(tx, workspaceId);
|
|
13065
13072
|
if (workspace.kind !== "shared" || workspace.accountId !== authority.accountId)
|
|
13066
13073
|
throw new HTTPException18(403, {
|
|
13067
13074
|
message: "external onboarding requires a shared organization workspace"
|
|
@@ -15617,7 +15624,7 @@ import {
|
|
|
15617
15624
|
getWorkspaceDefaultRigId as getWorkspaceDefaultRigId2,
|
|
15618
15625
|
withSessionRlsActorContext as withSessionRlsActorContext5,
|
|
15619
15626
|
nestedPostgresSqlState as nestedPostgresSqlState6,
|
|
15620
|
-
requireWorkspace as
|
|
15627
|
+
requireWorkspace as requireWorkspace8,
|
|
15621
15628
|
scopedKnowledgeScopeKey,
|
|
15622
15629
|
updateScheduledTask,
|
|
15623
15630
|
ScheduledTaskHeadChangedError,
|
|
@@ -15793,7 +15800,7 @@ async function createValidatedScheduledTask(input) {
|
|
|
15793
15800
|
message: "Personal source tasks create a private session for each run"
|
|
15794
15801
|
});
|
|
15795
15802
|
if (learning) {
|
|
15796
|
-
const workspace = await
|
|
15803
|
+
const workspace = await requireWorkspace8(input.db, input.grant.workspaceId);
|
|
15797
15804
|
const destination = knowledgeAction?.destination.kind === "personal" || workspace.kind === "personal" || target?.tenancy?.visibility === "private" || target?.memoryScope === "user" ? "personal" : "workspace";
|
|
15798
15805
|
if (learning.scope !== destination)
|
|
15799
15806
|
throw new HTTPException26(422, {
|
|
@@ -17149,7 +17156,7 @@ async function validateScheduledTaskAgentConfig(input) {
|
|
|
17149
17156
|
);
|
|
17150
17157
|
const retainTools = unchangedCreationField("tools");
|
|
17151
17158
|
const requestedTools = retainTools ? input.payload.agentConfig.tools : validateToolRefs(input.payload.agentConfig.tools ?? [], runtimeSettings);
|
|
17152
|
-
const workspace = await
|
|
17159
|
+
const workspace = await requireWorkspace8(input.db, input.workspaceId);
|
|
17153
17160
|
if (parent?.tenancy?.visibility === "private" && workspace.kind !== "personal" && input.payload.runMode !== "existing_session" && !input.payload.targetSessionId) {
|
|
17154
17161
|
throw new HTTPException26(422, {
|
|
17155
17162
|
message: "Schedule this private chat as the existing-session target, or create the task in your Personal workspace."
|
|
@@ -17330,7 +17337,7 @@ import {
|
|
|
17330
17337
|
listScheduledTaskHumanWaitAttention,
|
|
17331
17338
|
listScheduledTaskCreatorPolicies,
|
|
17332
17339
|
listScheduledTaskRunAuthNeededEvents,
|
|
17333
|
-
requireWorkspace as
|
|
17340
|
+
requireWorkspace as requireWorkspace9,
|
|
17334
17341
|
ScheduledTaskHeadChangedError as ScheduledTaskHeadChangedError2
|
|
17335
17342
|
} from "@opengeni/db";
|
|
17336
17343
|
import { HTTPException as HTTPException27 } from "hono/http-exception";
|
|
@@ -17522,7 +17529,7 @@ async function computeScheduledTaskAccessPlan(input) {
|
|
|
17522
17529
|
const [callerRegistry, ownerRegistry, workspaceSettings] = await Promise.all([
|
|
17523
17530
|
runtimeRegistry(db, task.workspaceId, settings, input.grant.subjectId, cache),
|
|
17524
17531
|
runtimeRegistry(db, task.workspaceId, settings, ownerSubjectId, cache),
|
|
17525
|
-
input.workspaceSettings !== void 0 ? Promise.resolve(input.workspaceSettings) :
|
|
17532
|
+
input.workspaceSettings !== void 0 ? Promise.resolve(input.workspaceSettings) : requireWorkspace9(db, task.workspaceId).then((workspace) => workspace.settings)
|
|
17526
17533
|
]);
|
|
17527
17534
|
const followsTask = scheduledTaskToolsFollowTask(task);
|
|
17528
17535
|
const target = task.runMode === "existing_session" && task.targetSessionId ? await getSession6(db, task.workspaceId, task.targetSessionId) : null;
|
|
@@ -17628,7 +17635,7 @@ async function withScheduledTaskPolicyDrift(input) {
|
|
|
17628
17635
|
workspaceId,
|
|
17629
17636
|
actionable.map((task) => task.id)
|
|
17630
17637
|
),
|
|
17631
|
-
|
|
17638
|
+
requireWorkspace9(input.db, workspaceId).then((workspace) => workspace.settings)
|
|
17632
17639
|
]);
|
|
17633
17640
|
} catch (error) {
|
|
17634
17641
|
input.onError?.(error);
|
|
@@ -17790,7 +17797,7 @@ async function scheduledTasksWithUnavailableAccounts(input) {
|
|
|
17790
17797
|
if (actionable.length === 0) return [];
|
|
17791
17798
|
let workspaceSettings;
|
|
17792
17799
|
try {
|
|
17793
|
-
workspaceSettings = (await
|
|
17800
|
+
workspaceSettings = (await requireWorkspace9(input.db, input.grant.workspaceId)).settings;
|
|
17794
17801
|
} catch (error) {
|
|
17795
17802
|
input.onError?.(error);
|
|
17796
17803
|
return [];
|
|
@@ -17949,7 +17956,7 @@ import {
|
|
|
17949
17956
|
listScheduledTasks,
|
|
17950
17957
|
readWorkspaceInsightsModelBundle,
|
|
17951
17958
|
readWorkspaceInsightsUsageBundle,
|
|
17952
|
-
requireWorkspace as
|
|
17959
|
+
requireWorkspace as requireWorkspace10
|
|
17953
17960
|
} from "@opengeni/db";
|
|
17954
17961
|
|
|
17955
17962
|
// src/domain/insights-timing.ts
|
|
@@ -18189,7 +18196,7 @@ async function getWorkspaceInsights(db, settings, input, observePhase) {
|
|
|
18189
18196
|
await measureInsightsPhase(
|
|
18190
18197
|
observePhase,
|
|
18191
18198
|
"require_workspace",
|
|
18192
|
-
() =>
|
|
18199
|
+
() => requireWorkspace10(db, input.workspaceId)
|
|
18193
18200
|
);
|
|
18194
18201
|
const [visibleRootScope, visibleSessionScope] = await Promise.all([
|
|
18195
18202
|
rootSessionId ? getSessionAccessProjection(db, input.workspaceId, rootSessionId) : null,
|
|
@@ -21755,6 +21762,7 @@ import {
|
|
|
21755
21762
|
directIntegrationTransport,
|
|
21756
21763
|
IntegrationInvocationError
|
|
21757
21764
|
} from "@opengeni/capabilities";
|
|
21765
|
+
import { apiIntegrationToolEffect } from "@opengeni/db";
|
|
21758
21766
|
function buildApiIntegrationMcpServers(input) {
|
|
21759
21767
|
const transport = createPinnedIntegrationTransport({
|
|
21760
21768
|
network: input.settings,
|
|
@@ -21784,6 +21792,14 @@ function buildApiIntegrationMcpServers(input) {
|
|
|
21784
21792
|
return {
|
|
21785
21793
|
id: integration.serverId,
|
|
21786
21794
|
server,
|
|
21795
|
+
effectAuthority: (toolName) => ({
|
|
21796
|
+
kind: "api_integration",
|
|
21797
|
+
instanceId: integration.instanceId,
|
|
21798
|
+
baseUrl: integration.baseUrl,
|
|
21799
|
+
connectionRef: integration.connectionRef,
|
|
21800
|
+
connectionAuthorityGeneration: integration.connectionAuthorityGeneration,
|
|
21801
|
+
effect: apiIntegrationToolEffect(integration.revision, toolName)
|
|
21802
|
+
}),
|
|
21787
21803
|
approvalAuthority: {
|
|
21788
21804
|
kind: "api_integration",
|
|
21789
21805
|
capabilityId: integration.capabilityId,
|
|
@@ -22113,6 +22129,7 @@ async function retainKnowledgeMessage(db, context, messageId) {
|
|
|
22113
22129
|
|
|
22114
22130
|
// src/domain/connector-tool-permissions.ts
|
|
22115
22131
|
import { slackRestMcpToolsForScopes } from "@opengeni/contracts/slack-rest-mcp";
|
|
22132
|
+
import { connectionAccountIdentityLabel as connectionAccountIdentityLabel2 } from "@opengeni/contracts/connection-account-label";
|
|
22116
22133
|
import { createHash as createHash11 } from "crypto";
|
|
22117
22134
|
import { Client as Client2 } from "@modelcontextprotocol/sdk/client/index.js";
|
|
22118
22135
|
import { StreamableHTTPClientTransport as StreamableHTTPClientTransport2 } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
@@ -22128,8 +22145,12 @@ import {
|
|
|
22128
22145
|
listConnectionsMetadata as listConnectionsMetadata4,
|
|
22129
22146
|
listEnabledMcpCapabilityServers as listEnabledMcpCapabilityServers3,
|
|
22130
22147
|
listConnectorToolPermissionPolicies,
|
|
22148
|
+
listChangedConnectorToolPermissions,
|
|
22131
22149
|
updateConnectorToolPermissionPolicies,
|
|
22132
|
-
|
|
22150
|
+
projectConnectorToolPermission,
|
|
22151
|
+
connectorToolPolicyRevision,
|
|
22152
|
+
ConnectorToolPermissionConflictError,
|
|
22153
|
+
listInstalledApiIntegrations as listInstalledApiIntegrations2
|
|
22133
22154
|
} from "@opengeni/db";
|
|
22134
22155
|
import { HTTPException as HTTPException32 } from "hono/http-exception";
|
|
22135
22156
|
import {
|
|
@@ -22159,9 +22180,50 @@ function connectorToolPermissionReference(ref, connectionId) {
|
|
|
22159
22180
|
}
|
|
22160
22181
|
async function resolveTarget2(input) {
|
|
22161
22182
|
if (input.capabilityId.startsWith("api:")) {
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22183
|
+
const integrations = (await listInstalledApiIntegrations2(
|
|
22184
|
+
input.db,
|
|
22185
|
+
input.workspaceId,
|
|
22186
|
+
input.personalOwnerVerified ? input.grant.subjectId : void 0
|
|
22187
|
+
)).filter((integration2) => integration2.capabilityId === input.capabilityId);
|
|
22188
|
+
const accountId = (integration2) => integration2.connectionRef?.connectionId ?? `session-mcp:${integration2.serverId}:${createHash11("sha256").update(integration2.baseUrl, "utf8").digest("hex")}`;
|
|
22189
|
+
const integration = integrations.find(
|
|
22190
|
+
(candidate) => (!input.instanceKey || candidate.instanceKey === input.instanceKey) && (!input.connectionId || accountId(candidate) === input.connectionId)
|
|
22191
|
+
);
|
|
22192
|
+
if (!integration) throw new HTTPException32(404, { message: "Integration account unavailable" });
|
|
22193
|
+
const server2 = settingsWithApiIntegrationServers({ ...input.settings, mcpServers: [] }, [
|
|
22194
|
+
integration
|
|
22195
|
+
]).mcpServers[0];
|
|
22196
|
+
const connection2 = integration.connectionRef?.connectionId ? await getConnectionMetadata5(
|
|
22197
|
+
input.db,
|
|
22198
|
+
input.workspaceId,
|
|
22199
|
+
integration.connectionRef.connectionId,
|
|
22200
|
+
input.grant.subjectId
|
|
22201
|
+
) : null;
|
|
22202
|
+
const accounts = integrations.map((candidate) => ({
|
|
22203
|
+
connectionId: accountId(candidate),
|
|
22204
|
+
label: candidate.displayName,
|
|
22205
|
+
scope: candidate.connectionRef?.subjectScope === "subject" ? "personal" : candidate.connectionRef ? "workspace" : "none",
|
|
22206
|
+
instanceKey: candidate.instanceKey
|
|
22207
|
+
}));
|
|
22208
|
+
return {
|
|
22209
|
+
server: server2,
|
|
22210
|
+
connection: connection2,
|
|
22211
|
+
connectionId: accountId(integration),
|
|
22212
|
+
accountLabel: connection2 ? connectionAccountIdentityLabel2(connection2.metadata, integration.displayName) : integration.displayName,
|
|
22213
|
+
accounts,
|
|
22214
|
+
instanceKey: integration.instanceKey,
|
|
22215
|
+
listedTools: integration.revision.tools.filter((tool) => integration.allowedTools.includes(tool.id)).map(
|
|
22216
|
+
(tool) => ({
|
|
22217
|
+
name: tool.id,
|
|
22218
|
+
title: tool.name,
|
|
22219
|
+
description: tool.description,
|
|
22220
|
+
annotations: {
|
|
22221
|
+
readOnlyHint: tool.safety === "read",
|
|
22222
|
+
destructiveHint: tool.safety === "destructive"
|
|
22223
|
+
}
|
|
22224
|
+
})
|
|
22225
|
+
)
|
|
22226
|
+
};
|
|
22165
22227
|
}
|
|
22166
22228
|
const catalog = await buildCapabilityCatalog(input);
|
|
22167
22229
|
const item = catalog.items.find((candidate) => candidate.id === input.capabilityId);
|
|
@@ -22174,25 +22236,31 @@ async function resolveTarget2(input) {
|
|
|
22174
22236
|
if (!server || server.url !== item.endpointUrl)
|
|
22175
22237
|
throw new HTTPException32(409, { message: "Connector configuration is unavailable" });
|
|
22176
22238
|
const ref = server.connectionRef;
|
|
22177
|
-
if (ref?.
|
|
22178
|
-
throw new HTTPException32(
|
|
22179
|
-
message: "
|
|
22239
|
+
if (ref?.subjectScope === "subject" && ref.accountSelection !== "all_eligible" && !input.personalOwnerVerified)
|
|
22240
|
+
throw new HTTPException32(403, {
|
|
22241
|
+
message: "Only the authenticated connection owner may manage personal tool permissions"
|
|
22180
22242
|
});
|
|
22181
|
-
|
|
22243
|
+
const visible = ref ? await listConnectionsMetadata4(
|
|
22182
22244
|
input.db,
|
|
22183
22245
|
input.workspaceId,
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
|
|
22187
|
-
|
|
22188
|
-
|
|
22189
|
-
|
|
22190
|
-
|
|
22191
|
-
|
|
22192
|
-
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
|
|
22246
|
+
input.personalOwnerVerified ? input.grant.subjectId : null
|
|
22247
|
+
) : [];
|
|
22248
|
+
const bindings = mcpAccountBindingsFromVisibleConnections({
|
|
22249
|
+
accountId: input.grant.accountId,
|
|
22250
|
+
workspaceId: input.workspaceId,
|
|
22251
|
+
subjectId: input.personalOwnerVerified ? input.grant.subjectId : null,
|
|
22252
|
+
servers: [server],
|
|
22253
|
+
// Runtime admission can enumerate every eligible account. A permission
|
|
22254
|
+
// selector must also preserve the installation's explicit owner scope.
|
|
22255
|
+
connections: ref?.accountSelection === "all_eligible" ? visible : visible.filter(
|
|
22256
|
+
(candidate) => ref?.subjectScope === "subject" ? candidate.subjectId === input.grant.subjectId : candidate.subjectId === null
|
|
22257
|
+
)
|
|
22258
|
+
});
|
|
22259
|
+
const binding = bindings.find(
|
|
22260
|
+
(candidate) => !input.connectionId || candidate.connectionId === input.connectionId
|
|
22261
|
+
);
|
|
22262
|
+
const connection = visible.find((candidate) => candidate.id === binding?.connectionId) ?? null;
|
|
22263
|
+
if (ref && !connection) {
|
|
22196
22264
|
throw new HTTPException32(409, { message: "Reconnect this connector to manage its tools" });
|
|
22197
22265
|
}
|
|
22198
22266
|
if (connection?.subjectId && !input.personalOwnerVerified)
|
|
@@ -22200,13 +22268,30 @@ async function resolveTarget2(input) {
|
|
|
22200
22268
|
message: "Only the authenticated connection owner may manage personal tool permissions"
|
|
22201
22269
|
});
|
|
22202
22270
|
const connectionId = connection?.id ?? `session-mcp:${server.id}:${createHash11("sha256").update(server.url, "utf8").digest("hex")}`;
|
|
22203
|
-
|
|
22271
|
+
if (input.connectionId && input.connectionId !== connectionId)
|
|
22272
|
+
throw new HTTPException32(409, {
|
|
22273
|
+
message: "Connector account unavailable. Reload its permissions."
|
|
22274
|
+
});
|
|
22275
|
+
return {
|
|
22276
|
+
server: binding ? { ...server, connectionRef: binding.connectionRef } : server,
|
|
22277
|
+
connection,
|
|
22278
|
+
connectionId,
|
|
22279
|
+
accountLabel: binding?.accountLabel ?? server.name ?? server.id,
|
|
22280
|
+
accounts: bindings.map((candidate) => ({
|
|
22281
|
+
connectionId: candidate.connectionId,
|
|
22282
|
+
label: candidate.accountLabel,
|
|
22283
|
+
scope: candidate.subjectScope === "subject" ? "personal" : "workspace"
|
|
22284
|
+
})),
|
|
22285
|
+
instanceKey: void 0,
|
|
22286
|
+
listedTools: null
|
|
22287
|
+
};
|
|
22204
22288
|
}
|
|
22205
22289
|
function reviewedConnectorToolCatalog(server, grantedScopes) {
|
|
22206
22290
|
const tools = isOfficialGmailMcpConfig(server.url, server.connectionRef) ? GMAIL_REST_MCP_TOOLS.filter((tool) => gmailToolSupportsScopes(tool.name, grantedScopes)) : isOfficialSlackMcpConfig(server.url, server.connectionRef) ? slackRestMcpToolsForScopes(grantedScopes) : null;
|
|
22207
22291
|
return tools?.filter((tool) => !server.allowedTools || server.allowedTools.includes(tool.name)) ?? null;
|
|
22208
22292
|
}
|
|
22209
22293
|
async function listTools(input, target) {
|
|
22294
|
+
if (target.listedTools !== null) return target.listedTools;
|
|
22210
22295
|
const reviewed = reviewedConnectorToolCatalog(
|
|
22211
22296
|
target.server,
|
|
22212
22297
|
target.connection?.grantedScopes ?? []
|
|
@@ -22288,19 +22373,14 @@ async function getConnectorToolPermissions(input) {
|
|
|
22288
22373
|
workspaceId: input.workspaceId,
|
|
22289
22374
|
connectionId: target.connectionId
|
|
22290
22375
|
});
|
|
22291
|
-
const
|
|
22292
|
-
|
|
22376
|
+
const changedTools = new Set(
|
|
22377
|
+
await listChangedConnectorToolPermissions(input.db, {
|
|
22378
|
+
accountId: input.grant.accountId,
|
|
22379
|
+
workspaceId: input.workspaceId,
|
|
22293
22380
|
connectionId: target.connectionId,
|
|
22294
|
-
serverId: target.server.id
|
|
22295
|
-
|
|
22296
|
-
|
|
22297
|
-
});
|
|
22298
|
-
if (!resolved.managed) return { permission: "allow", inherited: true };
|
|
22299
|
-
return {
|
|
22300
|
-
permission: resolved.entry?.policy ?? "block",
|
|
22301
|
-
inherited: resolved.entry?.toolName !== name
|
|
22302
|
-
};
|
|
22303
|
-
};
|
|
22381
|
+
serverId: target.server.id
|
|
22382
|
+
})
|
|
22383
|
+
);
|
|
22304
22384
|
const defaultPolicy = policies.find(
|
|
22305
22385
|
(row) => row.serverId === target.server.id && row.toolName === "*" && row.actionName === "*"
|
|
22306
22386
|
);
|
|
@@ -22322,15 +22402,25 @@ async function getConnectorToolPermissions(input) {
|
|
|
22322
22402
|
tools: tools.map(
|
|
22323
22403
|
(tool) => ({
|
|
22324
22404
|
name: tool.name,
|
|
22405
|
+
...changedTools.has(tool.name) ? { resetReason: "operation_changed" } : {},
|
|
22325
22406
|
...tool.title ?? tool.annotations?.title ? { title: tool.title ?? tool.annotations?.title } : {},
|
|
22326
22407
|
...tool.description ? { description: tool.description } : {},
|
|
22327
22408
|
group: connectorToolGroup(tool),
|
|
22328
|
-
...
|
|
22329
|
-
|
|
22409
|
+
...projectConnectorToolPermission(policies, {
|
|
22410
|
+
connectionId: target.connectionId,
|
|
22411
|
+
serverId: target.server.id,
|
|
22412
|
+
toolName: tool.name,
|
|
22413
|
+
defaultDecision: target.server.requireApproval === true || Array.isArray(target.server.requireApproval) && target.server.requireApproval.includes(tool.name) ? "ask" : "allow"
|
|
22414
|
+
})
|
|
22330
22415
|
})
|
|
22331
22416
|
),
|
|
22332
22417
|
discoveryError,
|
|
22333
|
-
canManage: canManageConnectorPermissions(input.grant)
|
|
22418
|
+
canManage: canManageConnectorPermissions(input.grant),
|
|
22419
|
+
appliesTo: "next_attempt",
|
|
22420
|
+
revision: connectorToolPolicyRevision(policies, target.connectionId, target.server.id),
|
|
22421
|
+
accountLabel: target.accountLabel,
|
|
22422
|
+
accounts: target.accounts,
|
|
22423
|
+
...target.instanceKey ? { instanceKey: target.instanceKey } : {}
|
|
22334
22424
|
};
|
|
22335
22425
|
}
|
|
22336
22426
|
function canManageConnectorPermissions(grant) {
|
|
@@ -22343,20 +22433,32 @@ async function updateConnectorToolPermissions(input) {
|
|
|
22343
22433
|
throw new HTTPException32(400, {
|
|
22344
22434
|
message: "Tool names must be exact and cannot use the connector-default wildcard."
|
|
22345
22435
|
});
|
|
22346
|
-
const target = await resolveTarget2(
|
|
22436
|
+
const target = await resolveTarget2({
|
|
22437
|
+
...input,
|
|
22438
|
+
connectionId: input.payload.connectionId,
|
|
22439
|
+
...input.payload.instanceKey ? { instanceKey: input.payload.instanceKey } : {}
|
|
22440
|
+
});
|
|
22347
22441
|
if (target.connectionId !== input.payload.connectionId)
|
|
22348
22442
|
throw new HTTPException32(409, {
|
|
22349
22443
|
message: "The connector account changed. Reload its permissions."
|
|
22350
22444
|
});
|
|
22351
|
-
|
|
22352
|
-
|
|
22353
|
-
|
|
22354
|
-
|
|
22355
|
-
|
|
22356
|
-
|
|
22357
|
-
|
|
22358
|
-
|
|
22359
|
-
|
|
22445
|
+
try {
|
|
22446
|
+
await updateConnectorToolPermissionPolicies(input.db, {
|
|
22447
|
+
accountId: input.grant.accountId,
|
|
22448
|
+
workspaceId: input.workspaceId,
|
|
22449
|
+
subjectId: input.grant.subjectId,
|
|
22450
|
+
connectionId: target.connectionId,
|
|
22451
|
+
serverId: target.server.id,
|
|
22452
|
+
toolNames: input.payload.target === "default" ? ["*"] : input.payload.target === "action" ? [input.payload.toolName] : input.payload.toolNames,
|
|
22453
|
+
...input.payload.target === "action" ? { actionName: input.payload.actionName } : {},
|
|
22454
|
+
...input.payload.expectedRevision ? { expectedRevision: input.payload.expectedRevision } : {},
|
|
22455
|
+
policy: input.payload.permission
|
|
22456
|
+
});
|
|
22457
|
+
} catch (error) {
|
|
22458
|
+
if (error instanceof ConnectorToolPermissionConflictError)
|
|
22459
|
+
throw new HTTPException32(409, { message: error.message });
|
|
22460
|
+
throw error;
|
|
22461
|
+
}
|
|
22360
22462
|
}
|
|
22361
22463
|
export {
|
|
22362
22464
|
ArchivedSessionImportError2 as ArchivedSessionImportError,
|
|
@@ -22818,6 +22920,7 @@ export {
|
|
|
22818
22920
|
readSessionAttachmentFiles,
|
|
22819
22921
|
readSessionLineage,
|
|
22820
22922
|
readSkill,
|
|
22923
|
+
recordManagedAuthLoggedFailure,
|
|
22821
22924
|
recordRigAuditEvent,
|
|
22822
22925
|
recordSessionCreated,
|
|
22823
22926
|
recordUserMessageAccepted,
|
|
@@ -23013,6 +23116,7 @@ export {
|
|
|
23013
23116
|
withAgentConfigHttpErrors,
|
|
23014
23117
|
withDefaultEnabledCapabilityMcpTools,
|
|
23015
23118
|
withFrozenPersonalConnectionDelegations,
|
|
23119
|
+
withManagedAuthSessionLookup,
|
|
23016
23120
|
withResolvedSessionAuthorization,
|
|
23017
23121
|
withSameRequestSessionMcpServerTools,
|
|
23018
23122
|
withScheduledSlackBotPostingTools,
|