@opengeni/core 3.0.1 → 4.0.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 (89) hide show
  1. package/README.md +1 -1
  2. package/dist/application/connect-operation.d.ts +3 -0
  3. package/dist/application/sandbox-recovery.d.ts +49 -0
  4. package/dist/{chunk-H7X52RI2.js → chunk-TFHSE7XR.js} +13 -2
  5. package/dist/chunk-TFHSE7XR.js.map +1 -0
  6. package/dist/dependencies.d.ts +1 -1
  7. package/dist/domain/capabilities.d.ts +2 -2
  8. package/dist/domain/connection-account-selection-error.d.ts +6 -0
  9. package/dist/domain/connector-tool-permissions.d.ts +27 -0
  10. package/dist/domain/editable-artifacts/agent-application.d.ts +8 -0
  11. package/dist/domain/environments.d.ts +3 -7
  12. package/dist/domain/insights-timing.d.ts +16 -0
  13. package/dist/domain/insights.d.ts +4 -1
  14. package/dist/domain/knowledge-files.d.ts +1 -1
  15. package/dist/domain/knowledge-preparation.d.ts +9 -0
  16. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  17. package/dist/domain/mcp-account-bindings.d.ts +19 -0
  18. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  19. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  20. package/dist/domain/personal-connection-delegations.d.ts +19 -10
  21. package/dist/domain/pr-review.d.ts +56 -4
  22. package/dist/domain/scheduled-tasks.d.ts +8 -5
  23. package/dist/domain/session-file-access.d.ts +4 -0
  24. package/dist/domain/sessions.d.ts +8 -6
  25. package/dist/domain/skills.d.ts +29 -1
  26. package/dist/editable-artifacts.js +1 -1
  27. package/dist/index.d.ts +7 -5
  28. package/dist/index.js +4868 -4803
  29. package/dist/index.js.map +1 -1
  30. package/dist/sandbox/routing.d.ts +2 -1
  31. package/dist/sandbox/runtime-settings.d.ts +1 -15
  32. package/package.json +11 -19
  33. package/src/application/composer-submit.ts +2 -1
  34. package/src/application/connect-operation.ts +32 -3
  35. package/src/application/sandbox-recovery.ts +55 -0
  36. package/src/application/user-resource-grants.ts +1 -16
  37. package/src/dependencies.ts +5 -1
  38. package/src/domain/capabilities.ts +169 -122
  39. package/src/domain/connection-account-selection-error.ts +9 -0
  40. package/src/domain/connector-tool-permissions.ts +305 -0
  41. package/src/domain/editable-artifacts/agent-application.ts +31 -2
  42. package/src/domain/environments.ts +4 -9
  43. package/src/domain/file-owner.ts +16 -1
  44. package/src/domain/insights-timing.ts +95 -0
  45. package/src/domain/insights.ts +59 -35
  46. package/src/domain/knowledge-files.ts +10 -3
  47. package/src/domain/knowledge-messages.ts +1 -0
  48. package/src/domain/knowledge-preparation.test.ts +251 -0
  49. package/src/domain/knowledge-preparation.ts +126 -0
  50. package/src/domain/mcp-account-bindings.ts +152 -0
  51. package/src/domain/native-mcp-connection-admission.ts +14 -0
  52. package/src/domain/organization-integration-catalog.ts +83 -0
  53. package/src/domain/personal-connection-delegations.ts +226 -177
  54. package/src/domain/pr-review.ts +22 -6
  55. package/src/domain/resources.ts +9 -2
  56. package/src/domain/scheduled-tasks.ts +200 -155
  57. package/src/domain/session-file-access.ts +47 -0
  58. package/src/domain/session-tool-policy.ts +12 -4
  59. package/src/domain/sessions.ts +390 -261
  60. package/src/domain/skills.ts +9 -0
  61. package/src/index.ts +10 -6
  62. package/src/rigs/index.ts +17 -17
  63. package/src/sandbox/routing.ts +18 -7
  64. package/src/sandbox/runtime-settings.ts +7 -91
  65. package/dist/application/host-mcp-owner.d.ts +0 -6
  66. package/dist/application/host-mcp-resolvers.d.ts +0 -13
  67. package/dist/chunk-5WZYFL45.js +0 -266
  68. package/dist/chunk-5WZYFL45.js.map +0 -1
  69. package/dist/chunk-H7X52RI2.js.map +0 -1
  70. package/dist/domain/connection-authority.d.ts +0 -97
  71. package/dist/domain/connection-authority.js +0 -169
  72. package/dist/domain/connection-authority.js.map +0 -1
  73. package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
  74. package/dist/domain/host-mcp-task-admission.d.ts +0 -18
  75. package/dist/domain/packs.d.ts +0 -59
  76. package/dist/domain/product-integration-pack.d.ts +0 -44
  77. package/dist/domain/product-integration-skill.gen.d.ts +0 -5
  78. package/dist/remote-mcp-credentials.d.ts +0 -23
  79. package/dist/remote-mcp-credentials.js +0 -11
  80. package/dist/remote-mcp-credentials.js.map +0 -1
  81. package/src/application/host-mcp-owner.ts +0 -41
  82. package/src/application/host-mcp-resolvers.ts +0 -84
  83. package/src/domain/connection-authority.ts +0 -329
  84. package/src/domain/host-mcp-authority-source-admission.ts +0 -25
  85. package/src/domain/host-mcp-task-admission.ts +0 -121
  86. package/src/domain/packs.ts +0 -699
  87. package/src/domain/product-integration-pack.ts +0 -42
  88. package/src/domain/product-integration-skill.gen.ts +0 -52
  89. package/src/remote-mcp-credentials.ts +0 -361
@@ -1,169 +0,0 @@
1
- // src/domain/connection-authority.ts
2
- import {
3
- ConnectionAuthorityEnvelope,
4
- ConnectionUseAttribution,
5
- ConnectionUseAuthoritySnapshot
6
- } from "@opengeni/contracts/connection-authority";
7
- var ConnectionAuthorityInvariantError = class extends Error {
8
- constructor(code) {
9
- super(`connection authority invariant failed: ${code}`);
10
- this.code = code;
11
- this.name = "ConnectionAuthorityInvariantError";
12
- }
13
- };
14
- function captureConnectionUseAuthority(input) {
15
- const authority = ConnectionAuthorityEnvelope.parse(input.authority ?? {});
16
- const connection = input.connection;
17
- if (connection.organizationId !== input.organizationId) {
18
- throw new ConnectionAuthorityInvariantError("tenant_mismatch");
19
- }
20
- if (connection.status !== "active") {
21
- throw new ConnectionAuthorityInvariantError("connection_status_inactive");
22
- }
23
- let authoritySource;
24
- let userDelegation = null;
25
- if (authority.scope === "workspace") {
26
- if (connection.subjectId !== null || connection.ownerOrganizationMembershipId !== null) {
27
- throw new ConnectionAuthorityInvariantError("workspace_borrowed_personal_connection");
28
- }
29
- if (connection.workspaceId !== input.targetWorkspaceId) {
30
- throw new ConnectionAuthorityInvariantError("workspace_connection_scope_mismatch");
31
- }
32
- authoritySource = input.authorityWasOmitted ? "legacy_workspace_omission" : "explicit_workspace";
33
- } else {
34
- const delegation = authority.userDelegation;
35
- const resourceAuthority = input.userAuthority;
36
- if (!delegation || !resourceAuthority) {
37
- throw new ConnectionAuthorityInvariantError("user_authority_missing");
38
- }
39
- if (!connection.subjectId || !connection.ownerOrganizationMembershipId) {
40
- throw new ConnectionAuthorityInvariantError("personal_owner_missing");
41
- }
42
- if (resourceAuthority.id !== delegation.authorityId || resourceAuthority.organizationId !== input.organizationId || resourceAuthority.resourceKind !== "connection" || resourceAuthority.resourceId !== connection.id || resourceAuthority.originWorkspaceId !== connection.workspaceId || resourceAuthority.ownerSubjectId !== connection.subjectId || resourceAuthority.ownerOrganizationMembershipId !== connection.ownerOrganizationMembershipId || resourceAuthority.generation !== delegation.authorityGeneration || resourceAuthority.status !== "active") {
43
- throw new ConnectionAuthorityInvariantError("user_authority_mismatch");
44
- }
45
- userDelegation = delegation;
46
- authoritySource = "user_delegation";
47
- }
48
- return ConnectionUseAuthoritySnapshot.parse({
49
- organizationId: input.organizationId,
50
- originWorkspaceId: connection.workspaceId,
51
- targetWorkspaceId: input.targetWorkspaceId,
52
- targetSessionId: input.targetSessionId,
53
- targetSessionVisibility: input.targetSessionVisibility,
54
- targetSessionAuthorityEpoch: input.targetSessionAuthorityEpoch,
55
- acceptedWork: input.acceptedWork,
56
- connectionId: connection.id,
57
- connectionGeneration: connection.generation,
58
- connectionStatus: "active",
59
- providerDomain: connection.providerDomain.toLowerCase(),
60
- connectionKind: connection.kind,
61
- scope: authority.scope,
62
- ownerSubjectId: connection.subjectId,
63
- ownerOrganizationMembershipId: connection.ownerOrganizationMembershipId,
64
- ownerMembershipAuthorizationRevision: authority.scope === "user" ? input.userAuthority.ownerMembershipAuthorizationRevision : null,
65
- authoritySource,
66
- selectionSources: input.selectionSources,
67
- userDelegation
68
- });
69
- }
70
- function denied(reason) {
71
- return { status: "denied", reason };
72
- }
73
- function revalidateConnectionUseAuthority(input) {
74
- const snapshot = ConnectionUseAuthoritySnapshot.parse(input.snapshot);
75
- const live = input.live;
76
- const now = input.now ?? /* @__PURE__ */ new Date();
77
- if (live.organizationId !== snapshot.organizationId || live.targetWorkspaceId !== snapshot.targetWorkspaceId) {
78
- return denied("tenant_mismatch");
79
- }
80
- if (!live.targetWorkspaceAccessActive) return denied("workspace_access_inactive");
81
- if (!live.session.active) return denied("session_inactive");
82
- if (live.session.id !== snapshot.targetSessionId || live.session.organizationId !== snapshot.organizationId || live.session.workspaceId !== snapshot.targetWorkspaceId) {
83
- return denied("session_identity_changed");
84
- }
85
- if (live.session.visibility !== snapshot.targetSessionVisibility) {
86
- return denied("session_visibility_changed");
87
- }
88
- if (live.session.authorityEpoch !== snapshot.targetSessionAuthorityEpoch) {
89
- return denied("session_authority_epoch_changed");
90
- }
91
- const connection = live.connection;
92
- if (!connection) return denied("connection_missing");
93
- if (connection.id !== snapshot.connectionId || connection.organizationId !== snapshot.organizationId || connection.workspaceId !== snapshot.originWorkspaceId || connection.providerDomain.toLowerCase() !== snapshot.providerDomain || connection.kind !== snapshot.connectionKind) {
94
- return denied("connection_identity_changed");
95
- }
96
- if (connection.generation !== snapshot.connectionGeneration) {
97
- return denied("connection_generation_changed");
98
- }
99
- if (connection.status !== "active") return denied("connection_status_inactive");
100
- if (connection.subjectId !== snapshot.ownerSubjectId || connection.ownerOrganizationMembershipId !== snapshot.ownerOrganizationMembershipId) {
101
- return denied("connection_owner_changed");
102
- }
103
- if (snapshot.scope === "workspace") {
104
- if (connection.subjectId !== null || connection.workspaceId !== snapshot.targetWorkspaceId) {
105
- return denied("connection_owner_changed");
106
- }
107
- return {
108
- status: "authorized",
109
- attribution: ConnectionUseAttribution.parse({
110
- organizationId: snapshot.organizationId,
111
- workspaceId: snapshot.targetWorkspaceId,
112
- sessionId: snapshot.targetSessionId,
113
- connectionId: snapshot.connectionId,
114
- connectionGeneration: snapshot.connectionGeneration,
115
- scope: "workspace",
116
- ownerSubjectId: null,
117
- authorityId: null,
118
- grantId: null
119
- })
120
- };
121
- }
122
- const delegation = snapshot.userDelegation;
123
- const membership = live.ownerMembership;
124
- if (!membership || membership.status !== "active" || membership.id !== snapshot.ownerOrganizationMembershipId || membership.organizationId !== snapshot.organizationId || membership.subjectId !== snapshot.ownerSubjectId || membership.authorizationRevision !== snapshot.ownerMembershipAuthorizationRevision) {
125
- return denied("owner_membership_inactive");
126
- }
127
- const authority = live.userAuthority;
128
- if (!authority) return denied("authority_missing");
129
- if (authority.id !== delegation.authorityId || authority.organizationId !== snapshot.organizationId || authority.resourceKind !== "connection" || authority.resourceId !== snapshot.connectionId || authority.originWorkspaceId !== snapshot.originWorkspaceId || authority.ownerSubjectId !== snapshot.ownerSubjectId || authority.ownerOrganizationMembershipId !== snapshot.ownerOrganizationMembershipId) {
130
- return denied("authority_identity_changed");
131
- }
132
- if (authority.generation !== delegation.authorityGeneration) {
133
- return denied("authority_generation_changed");
134
- }
135
- if (authority.status !== "active") return denied("authority_status_inactive");
136
- const grant = live.grant;
137
- if (!grant) return denied("grant_missing");
138
- if (grant.id !== delegation.grantId || grant.authorityId !== delegation.authorityId || grant.organizationId !== snapshot.organizationId || grant.workspaceId !== snapshot.targetWorkspaceId || grant.sessionId !== delegation.sessionId || grant.action !== "connection.use" || grant.mode !== delegation.mode || grant.context !== snapshot.targetSessionVisibility || grant.authorityEpoch !== delegation.authorityEpoch) {
139
- return denied("grant_identity_changed");
140
- }
141
- if (grant.generation !== delegation.grantGeneration) {
142
- return denied("grant_generation_changed");
143
- }
144
- if (grant.status !== "active") return denied("grant_status_inactive");
145
- if (grant.expiresAt !== null && Date.parse(grant.expiresAt) <= now.getTime()) {
146
- return denied("grant_expired");
147
- }
148
- if (grant.mode === "once" && grant.consumed) return denied("grant_already_consumed");
149
- return {
150
- status: "authorized",
151
- attribution: ConnectionUseAttribution.parse({
152
- organizationId: snapshot.organizationId,
153
- workspaceId: snapshot.targetWorkspaceId,
154
- sessionId: snapshot.targetSessionId,
155
- connectionId: snapshot.connectionId,
156
- connectionGeneration: snapshot.connectionGeneration,
157
- scope: "user",
158
- ownerSubjectId: snapshot.ownerSubjectId,
159
- authorityId: delegation.authorityId,
160
- grantId: delegation.grantId
161
- })
162
- };
163
- }
164
- export {
165
- ConnectionAuthorityInvariantError,
166
- captureConnectionUseAuthority,
167
- revalidateConnectionUseAuthority
168
- };
169
- //# sourceMappingURL=connection-authority.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/domain/connection-authority.ts"],"sourcesContent":["import type {\n ConnectionKind,\n ConnectionStatus,\n SessionTenancyVisibility,\n UserResourceDelegation,\n UserResourceGrantMode,\n UserResourceGrantStatus,\n} from \"@opengeni/contracts\";\nimport {\n ConnectionAuthorityEnvelope,\n ConnectionUseAttribution,\n ConnectionUseAuthoritySnapshot,\n type ConnectionUseAuthorizationResult,\n type ConnectionAuthoritySelectionSource,\n type ConnectionUseDenialReason,\n type ConnectionUseSelectionSource,\n} from \"@opengeni/contracts/connection-authority\";\n\nexport type ConnectionAuthorityCandidate = {\n id: string;\n organizationId: string;\n workspaceId: string;\n generation: number;\n status: ConnectionStatus;\n providerDomain: string;\n kind: ConnectionKind;\n subjectId: string | null;\n ownerOrganizationMembershipId: string | null;\n};\n\nexport type UserConnectionAuthorityCandidate = {\n id: string;\n organizationId: string;\n resourceKind: \"connection\";\n resourceId: string;\n originWorkspaceId: string;\n ownerSubjectId: string;\n ownerOrganizationMembershipId: string;\n ownerMembershipAuthorizationRevision: number;\n generation: number;\n status: \"active\" | \"retained\" | \"revoked\";\n};\n\nexport class ConnectionAuthorityInvariantError extends Error {\n constructor(readonly code: string) {\n super(`connection authority invariant failed: ${code}`);\n this.name = \"ConnectionAuthorityInvariantError\";\n }\n}\n\nexport function captureConnectionUseAuthority(input: {\n organizationId: string;\n targetWorkspaceId: string;\n targetSessionId: string;\n targetSessionVisibility: SessionTenancyVisibility;\n targetSessionAuthorityEpoch: number;\n acceptedWork:\n | { kind: \"turn\"; turnId: string }\n | {\n kind: \"scheduled_task\";\n taskId: string;\n taskAuthorityRevision: number;\n runId: string;\n };\n connection: ConnectionAuthorityCandidate;\n authority?: unknown;\n authorityWasOmitted?: boolean;\n userAuthority?: UserConnectionAuthorityCandidate | null;\n selectionSources: ConnectionUseSelectionSource[];\n}): ConnectionUseAuthoritySnapshot {\n const authority = ConnectionAuthorityEnvelope.parse(input.authority ?? {});\n const connection = input.connection;\n if (connection.organizationId !== input.organizationId) {\n throw new ConnectionAuthorityInvariantError(\"tenant_mismatch\");\n }\n if (connection.status !== \"active\") {\n throw new ConnectionAuthorityInvariantError(\"connection_status_inactive\");\n }\n\n let authoritySource: ConnectionAuthoritySelectionSource;\n let userDelegation: UserResourceDelegation | null = null;\n if (authority.scope === \"workspace\") {\n if (connection.subjectId !== null || connection.ownerOrganizationMembershipId !== null) {\n throw new ConnectionAuthorityInvariantError(\"workspace_borrowed_personal_connection\");\n }\n if (connection.workspaceId !== input.targetWorkspaceId) {\n throw new ConnectionAuthorityInvariantError(\"workspace_connection_scope_mismatch\");\n }\n authoritySource = input.authorityWasOmitted\n ? \"legacy_workspace_omission\"\n : \"explicit_workspace\";\n } else {\n const delegation = authority.userDelegation;\n const resourceAuthority = input.userAuthority;\n if (!delegation || !resourceAuthority) {\n throw new ConnectionAuthorityInvariantError(\"user_authority_missing\");\n }\n if (!connection.subjectId || !connection.ownerOrganizationMembershipId) {\n throw new ConnectionAuthorityInvariantError(\"personal_owner_missing\");\n }\n if (\n resourceAuthority.id !== delegation.authorityId ||\n resourceAuthority.organizationId !== input.organizationId ||\n resourceAuthority.resourceKind !== \"connection\" ||\n resourceAuthority.resourceId !== connection.id ||\n resourceAuthority.originWorkspaceId !== connection.workspaceId ||\n resourceAuthority.ownerSubjectId !== connection.subjectId ||\n resourceAuthority.ownerOrganizationMembershipId !==\n connection.ownerOrganizationMembershipId ||\n resourceAuthority.generation !== delegation.authorityGeneration ||\n resourceAuthority.status !== \"active\"\n ) {\n throw new ConnectionAuthorityInvariantError(\"user_authority_mismatch\");\n }\n userDelegation = delegation;\n authoritySource = \"user_delegation\";\n }\n\n return ConnectionUseAuthoritySnapshot.parse({\n organizationId: input.organizationId,\n originWorkspaceId: connection.workspaceId,\n targetWorkspaceId: input.targetWorkspaceId,\n targetSessionId: input.targetSessionId,\n targetSessionVisibility: input.targetSessionVisibility,\n targetSessionAuthorityEpoch: input.targetSessionAuthorityEpoch,\n acceptedWork: input.acceptedWork,\n connectionId: connection.id,\n connectionGeneration: connection.generation,\n connectionStatus: \"active\",\n providerDomain: connection.providerDomain.toLowerCase(),\n connectionKind: connection.kind,\n scope: authority.scope,\n ownerSubjectId: connection.subjectId,\n ownerOrganizationMembershipId: connection.ownerOrganizationMembershipId,\n ownerMembershipAuthorizationRevision:\n authority.scope === \"user\" ? input.userAuthority!.ownerMembershipAuthorizationRevision : null,\n authoritySource,\n selectionSources: input.selectionSources,\n userDelegation,\n });\n}\n\nexport type LiveConnectionUseState = {\n organizationId: string;\n targetWorkspaceId: string;\n targetWorkspaceAccessActive: boolean;\n session: {\n id: string;\n organizationId: string;\n workspaceId: string;\n visibility: SessionTenancyVisibility;\n authorityEpoch: number;\n active: boolean;\n };\n connection: ConnectionAuthorityCandidate | null;\n ownerMembership: {\n id: string;\n organizationId: string;\n subjectId: string;\n status: \"provisioning\" | \"active\" | \"suspended\" | \"revoked\";\n authorizationRevision: number;\n } | null;\n userAuthority: UserConnectionAuthorityCandidate | null;\n grant: {\n id: string;\n authorityId: string;\n organizationId: string;\n workspaceId: string;\n sessionId: string | null;\n action: string;\n mode: UserResourceGrantMode;\n context: SessionTenancyVisibility;\n authorityEpoch: number | null;\n generation: number;\n status: UserResourceGrantStatus;\n expiresAt: string | null;\n consumed: boolean;\n } | null;\n};\n\nfunction denied(reason: ConnectionUseDenialReason): ConnectionUseAuthorizationResult {\n return { status: \"denied\", reason };\n}\n\n/**\n * Revalidates every mutable fence immediately before provider use. Callers must\n * resolve the live state in one DB authority boundary; this pure function does\n * not cache, refresh, decrypt, or invoke a provider.\n */\nexport function revalidateConnectionUseAuthority(input: {\n snapshot: ConnectionUseAuthoritySnapshot;\n live: LiveConnectionUseState;\n now?: Date;\n}): ConnectionUseAuthorizationResult {\n const snapshot = ConnectionUseAuthoritySnapshot.parse(input.snapshot);\n const live = input.live;\n const now = input.now ?? new Date();\n if (\n live.organizationId !== snapshot.organizationId ||\n live.targetWorkspaceId !== snapshot.targetWorkspaceId\n ) {\n return denied(\"tenant_mismatch\");\n }\n if (!live.targetWorkspaceAccessActive) return denied(\"workspace_access_inactive\");\n if (!live.session.active) return denied(\"session_inactive\");\n if (\n live.session.id !== snapshot.targetSessionId ||\n live.session.organizationId !== snapshot.organizationId ||\n live.session.workspaceId !== snapshot.targetWorkspaceId\n ) {\n return denied(\"session_identity_changed\");\n }\n if (live.session.visibility !== snapshot.targetSessionVisibility) {\n return denied(\"session_visibility_changed\");\n }\n if (live.session.authorityEpoch !== snapshot.targetSessionAuthorityEpoch) {\n return denied(\"session_authority_epoch_changed\");\n }\n const connection = live.connection;\n if (!connection) return denied(\"connection_missing\");\n if (\n connection.id !== snapshot.connectionId ||\n connection.organizationId !== snapshot.organizationId ||\n connection.workspaceId !== snapshot.originWorkspaceId ||\n connection.providerDomain.toLowerCase() !== snapshot.providerDomain ||\n connection.kind !== snapshot.connectionKind\n ) {\n return denied(\"connection_identity_changed\");\n }\n if (connection.generation !== snapshot.connectionGeneration) {\n return denied(\"connection_generation_changed\");\n }\n if (connection.status !== \"active\") return denied(\"connection_status_inactive\");\n if (\n connection.subjectId !== snapshot.ownerSubjectId ||\n connection.ownerOrganizationMembershipId !== snapshot.ownerOrganizationMembershipId\n ) {\n return denied(\"connection_owner_changed\");\n }\n\n if (snapshot.scope === \"workspace\") {\n if (connection.subjectId !== null || connection.workspaceId !== snapshot.targetWorkspaceId) {\n return denied(\"connection_owner_changed\");\n }\n return {\n status: \"authorized\",\n attribution: ConnectionUseAttribution.parse({\n organizationId: snapshot.organizationId,\n workspaceId: snapshot.targetWorkspaceId,\n sessionId: snapshot.targetSessionId,\n connectionId: snapshot.connectionId,\n connectionGeneration: snapshot.connectionGeneration,\n scope: \"workspace\",\n ownerSubjectId: null,\n authorityId: null,\n grantId: null,\n }),\n };\n }\n\n const delegation = snapshot.userDelegation!;\n const membership = live.ownerMembership;\n if (\n !membership ||\n membership.status !== \"active\" ||\n membership.id !== snapshot.ownerOrganizationMembershipId ||\n membership.organizationId !== snapshot.organizationId ||\n membership.subjectId !== snapshot.ownerSubjectId ||\n membership.authorizationRevision !== snapshot.ownerMembershipAuthorizationRevision\n ) {\n return denied(\"owner_membership_inactive\");\n }\n const authority = live.userAuthority;\n if (!authority) return denied(\"authority_missing\");\n if (\n authority.id !== delegation.authorityId ||\n authority.organizationId !== snapshot.organizationId ||\n authority.resourceKind !== \"connection\" ||\n authority.resourceId !== snapshot.connectionId ||\n authority.originWorkspaceId !== snapshot.originWorkspaceId ||\n authority.ownerSubjectId !== snapshot.ownerSubjectId ||\n authority.ownerOrganizationMembershipId !== snapshot.ownerOrganizationMembershipId\n ) {\n return denied(\"authority_identity_changed\");\n }\n if (authority.generation !== delegation.authorityGeneration) {\n return denied(\"authority_generation_changed\");\n }\n if (authority.status !== \"active\") return denied(\"authority_status_inactive\");\n\n const grant = live.grant;\n if (!grant) return denied(\"grant_missing\");\n if (\n grant.id !== delegation.grantId ||\n grant.authorityId !== delegation.authorityId ||\n grant.organizationId !== snapshot.organizationId ||\n grant.workspaceId !== snapshot.targetWorkspaceId ||\n grant.sessionId !== delegation.sessionId ||\n grant.action !== \"connection.use\" ||\n grant.mode !== delegation.mode ||\n grant.context !== snapshot.targetSessionVisibility ||\n grant.authorityEpoch !== delegation.authorityEpoch\n ) {\n return denied(\"grant_identity_changed\");\n }\n if (grant.generation !== delegation.grantGeneration) {\n return denied(\"grant_generation_changed\");\n }\n if (grant.status !== \"active\") return denied(\"grant_status_inactive\");\n if (grant.expiresAt !== null && Date.parse(grant.expiresAt) <= now.getTime()) {\n return denied(\"grant_expired\");\n }\n if (grant.mode === \"once\" && grant.consumed) return denied(\"grant_already_consumed\");\n\n return {\n status: \"authorized\",\n attribution: ConnectionUseAttribution.parse({\n organizationId: snapshot.organizationId,\n workspaceId: snapshot.targetWorkspaceId,\n sessionId: snapshot.targetSessionId,\n connectionId: snapshot.connectionId,\n connectionGeneration: snapshot.connectionGeneration,\n scope: \"user\",\n ownerSubjectId: snapshot.ownerSubjectId,\n authorityId: delegation.authorityId,\n grantId: delegation.grantId,\n }),\n };\n}\n"],"mappings":";AAQA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AA2BA,IAAM,oCAAN,cAAgD,MAAM;AAAA,EAC3D,YAAqB,MAAc;AACjC,UAAM,0CAA0C,IAAI,EAAE;AADnC;AAEnB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,8BAA8B,OAmBX;AACjC,QAAM,YAAY,4BAA4B,MAAM,MAAM,aAAa,CAAC,CAAC;AACzE,QAAM,aAAa,MAAM;AACzB,MAAI,WAAW,mBAAmB,MAAM,gBAAgB;AACtD,UAAM,IAAI,kCAAkC,iBAAiB;AAAA,EAC/D;AACA,MAAI,WAAW,WAAW,UAAU;AAClC,UAAM,IAAI,kCAAkC,4BAA4B;AAAA,EAC1E;AAEA,MAAI;AACJ,MAAI,iBAAgD;AACpD,MAAI,UAAU,UAAU,aAAa;AACnC,QAAI,WAAW,cAAc,QAAQ,WAAW,kCAAkC,MAAM;AACtF,YAAM,IAAI,kCAAkC,wCAAwC;AAAA,IACtF;AACA,QAAI,WAAW,gBAAgB,MAAM,mBAAmB;AACtD,YAAM,IAAI,kCAAkC,qCAAqC;AAAA,IACnF;AACA,sBAAkB,MAAM,sBACpB,8BACA;AAAA,EACN,OAAO;AACL,UAAM,aAAa,UAAU;AAC7B,UAAM,oBAAoB,MAAM;AAChC,QAAI,CAAC,cAAc,CAAC,mBAAmB;AACrC,YAAM,IAAI,kCAAkC,wBAAwB;AAAA,IACtE;AACA,QAAI,CAAC,WAAW,aAAa,CAAC,WAAW,+BAA+B;AACtE,YAAM,IAAI,kCAAkC,wBAAwB;AAAA,IACtE;AACA,QACE,kBAAkB,OAAO,WAAW,eACpC,kBAAkB,mBAAmB,MAAM,kBAC3C,kBAAkB,iBAAiB,gBACnC,kBAAkB,eAAe,WAAW,MAC5C,kBAAkB,sBAAsB,WAAW,eACnD,kBAAkB,mBAAmB,WAAW,aAChD,kBAAkB,kCAChB,WAAW,iCACb,kBAAkB,eAAe,WAAW,uBAC5C,kBAAkB,WAAW,UAC7B;AACA,YAAM,IAAI,kCAAkC,yBAAyB;AAAA,IACvE;AACA,qBAAiB;AACjB,sBAAkB;AAAA,EACpB;AAEA,SAAO,+BAA+B,MAAM;AAAA,IAC1C,gBAAgB,MAAM;AAAA,IACtB,mBAAmB,WAAW;AAAA,IAC9B,mBAAmB,MAAM;AAAA,IACzB,iBAAiB,MAAM;AAAA,IACvB,yBAAyB,MAAM;AAAA,IAC/B,6BAA6B,MAAM;AAAA,IACnC,cAAc,MAAM;AAAA,IACpB,cAAc,WAAW;AAAA,IACzB,sBAAsB,WAAW;AAAA,IACjC,kBAAkB;AAAA,IAClB,gBAAgB,WAAW,eAAe,YAAY;AAAA,IACtD,gBAAgB,WAAW;AAAA,IAC3B,OAAO,UAAU;AAAA,IACjB,gBAAgB,WAAW;AAAA,IAC3B,+BAA+B,WAAW;AAAA,IAC1C,sCACE,UAAU,UAAU,SAAS,MAAM,cAAe,uCAAuC;AAAA,IAC3F;AAAA,IACA,kBAAkB,MAAM;AAAA,IACxB;AAAA,EACF,CAAC;AACH;AAwCA,SAAS,OAAO,QAAqE;AACnF,SAAO,EAAE,QAAQ,UAAU,OAAO;AACpC;AAOO,SAAS,iCAAiC,OAIZ;AACnC,QAAM,WAAW,+BAA+B,MAAM,MAAM,QAAQ;AACpE,QAAM,OAAO,MAAM;AACnB,QAAM,MAAM,MAAM,OAAO,oBAAI,KAAK;AAClC,MACE,KAAK,mBAAmB,SAAS,kBACjC,KAAK,sBAAsB,SAAS,mBACpC;AACA,WAAO,OAAO,iBAAiB;AAAA,EACjC;AACA,MAAI,CAAC,KAAK,4BAA6B,QAAO,OAAO,2BAA2B;AAChF,MAAI,CAAC,KAAK,QAAQ,OAAQ,QAAO,OAAO,kBAAkB;AAC1D,MACE,KAAK,QAAQ,OAAO,SAAS,mBAC7B,KAAK,QAAQ,mBAAmB,SAAS,kBACzC,KAAK,QAAQ,gBAAgB,SAAS,mBACtC;AACA,WAAO,OAAO,0BAA0B;AAAA,EAC1C;AACA,MAAI,KAAK,QAAQ,eAAe,SAAS,yBAAyB;AAChE,WAAO,OAAO,4BAA4B;AAAA,EAC5C;AACA,MAAI,KAAK,QAAQ,mBAAmB,SAAS,6BAA6B;AACxE,WAAO,OAAO,iCAAiC;AAAA,EACjD;AACA,QAAM,aAAa,KAAK;AACxB,MAAI,CAAC,WAAY,QAAO,OAAO,oBAAoB;AACnD,MACE,WAAW,OAAO,SAAS,gBAC3B,WAAW,mBAAmB,SAAS,kBACvC,WAAW,gBAAgB,SAAS,qBACpC,WAAW,eAAe,YAAY,MAAM,SAAS,kBACrD,WAAW,SAAS,SAAS,gBAC7B;AACA,WAAO,OAAO,6BAA6B;AAAA,EAC7C;AACA,MAAI,WAAW,eAAe,SAAS,sBAAsB;AAC3D,WAAO,OAAO,+BAA+B;AAAA,EAC/C;AACA,MAAI,WAAW,WAAW,SAAU,QAAO,OAAO,4BAA4B;AAC9E,MACE,WAAW,cAAc,SAAS,kBAClC,WAAW,kCAAkC,SAAS,+BACtD;AACA,WAAO,OAAO,0BAA0B;AAAA,EAC1C;AAEA,MAAI,SAAS,UAAU,aAAa;AAClC,QAAI,WAAW,cAAc,QAAQ,WAAW,gBAAgB,SAAS,mBAAmB;AAC1F,aAAO,OAAO,0BAA0B;AAAA,IAC1C;AACA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa,yBAAyB,MAAM;AAAA,QAC1C,gBAAgB,SAAS;AAAA,QACzB,aAAa,SAAS;AAAA,QACtB,WAAW,SAAS;AAAA,QACpB,cAAc,SAAS;AAAA,QACvB,sBAAsB,SAAS;AAAA,QAC/B,OAAO;AAAA,QACP,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,aAAa,SAAS;AAC5B,QAAM,aAAa,KAAK;AACxB,MACE,CAAC,cACD,WAAW,WAAW,YACtB,WAAW,OAAO,SAAS,iCAC3B,WAAW,mBAAmB,SAAS,kBACvC,WAAW,cAAc,SAAS,kBAClC,WAAW,0BAA0B,SAAS,sCAC9C;AACA,WAAO,OAAO,2BAA2B;AAAA,EAC3C;AACA,QAAM,YAAY,KAAK;AACvB,MAAI,CAAC,UAAW,QAAO,OAAO,mBAAmB;AACjD,MACE,UAAU,OAAO,WAAW,eAC5B,UAAU,mBAAmB,SAAS,kBACtC,UAAU,iBAAiB,gBAC3B,UAAU,eAAe,SAAS,gBAClC,UAAU,sBAAsB,SAAS,qBACzC,UAAU,mBAAmB,SAAS,kBACtC,UAAU,kCAAkC,SAAS,+BACrD;AACA,WAAO,OAAO,4BAA4B;AAAA,EAC5C;AACA,MAAI,UAAU,eAAe,WAAW,qBAAqB;AAC3D,WAAO,OAAO,8BAA8B;AAAA,EAC9C;AACA,MAAI,UAAU,WAAW,SAAU,QAAO,OAAO,2BAA2B;AAE5E,QAAM,QAAQ,KAAK;AACnB,MAAI,CAAC,MAAO,QAAO,OAAO,eAAe;AACzC,MACE,MAAM,OAAO,WAAW,WACxB,MAAM,gBAAgB,WAAW,eACjC,MAAM,mBAAmB,SAAS,kBAClC,MAAM,gBAAgB,SAAS,qBAC/B,MAAM,cAAc,WAAW,aAC/B,MAAM,WAAW,oBACjB,MAAM,SAAS,WAAW,QAC1B,MAAM,YAAY,SAAS,2BAC3B,MAAM,mBAAmB,WAAW,gBACpC;AACA,WAAO,OAAO,wBAAwB;AAAA,EACxC;AACA,MAAI,MAAM,eAAe,WAAW,iBAAiB;AACnD,WAAO,OAAO,0BAA0B;AAAA,EAC1C;AACA,MAAI,MAAM,WAAW,SAAU,QAAO,OAAO,uBAAuB;AACpE,MAAI,MAAM,cAAc,QAAQ,KAAK,MAAM,MAAM,SAAS,KAAK,IAAI,QAAQ,GAAG;AAC5E,WAAO,OAAO,eAAe;AAAA,EAC/B;AACA,MAAI,MAAM,SAAS,UAAU,MAAM,SAAU,QAAO,OAAO,wBAAwB;AAEnF,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,aAAa,yBAAyB,MAAM;AAAA,MAC1C,gBAAgB,SAAS;AAAA,MACzB,aAAa,SAAS;AAAA,MACtB,WAAW,SAAS;AAAA,MACpB,cAAc,SAAS;AAAA,MACvB,sBAAsB,SAAS;AAAA,MAC/B,OAAO;AAAA,MACP,gBAAgB,SAAS;AAAA,MACzB,aAAa,WAAW;AAAA,MACxB,SAAS,WAAW;AAAA,IACtB,CAAC;AAAA,EACH;AACF;","names":[]}
@@ -1,10 +0,0 @@
1
- import type { Settings } from "@opengeni/config";
2
- import type { McpServerConnectionRef } from "@opengeni/contracts";
3
- /**
4
- * Explicit host-owned MCP refs change which credential authority executes an
5
- * opaque connection id. Admit new external refs only after the operator has
6
- * completed the two-phase fleet rollout. Readers and inheritance remain
7
- * tolerant regardless of this switch, and markerless legacy refs retain their
8
- * bounded non-UUID compatibility path.
9
- */
10
- export declare function assertHostMcpAuthoritySourceAdmissionEnabled(settings: Pick<Settings, "hostMcpAuthoritySourceAdmissionEnabled">, connectionRef: McpServerConnectionRef | null | undefined): void;
@@ -1,18 +0,0 @@
1
- import type { Settings } from "@opengeni/config";
2
- import type { ToolRef, ScheduledTask, AccessGrant } from "@opengeni/contracts";
3
- import { type Database } from "@opengeni/db";
4
- import { type AccessGrantAuthorization } from "../access/index.js";
5
- /** Internal closure, not a caller-provided callback or durable key dependency. */
6
- export declare function prepareHostMcpTaskAdmission(input: {
7
- settings: Settings;
8
- tools: ToolRef[];
9
- grant: AccessGrant;
10
- authorization?: AccessGrantAuthorization;
11
- selections: unknown;
12
- }): (tx: Database, task: ScheduledTask) => Promise<void>;
13
- export declare function prepareInheritedHostMcpTaskAdmission(settings: Settings, tools: ToolRef[], source: {
14
- sessionId: string;
15
- turnId: string;
16
- attemptId: string;
17
- executionGeneration: number;
18
- }): (tx: Database, task: ScheduledTask) => Promise<void>;
@@ -1,59 +0,0 @@
1
- import { CapabilityPack, type CapabilityPackSkill, type PackInstallationPreview, type ScheduledTaskAgentConfig, type SocialConnection } from "@opengeni/contracts";
2
- import { type Database } from "@opengeni/db";
3
- export declare const MARKETING_SOCIAL_PACK_ID = "marketing-social-daily-analysis";
4
- export declare function listCapabilityPacks(): CapabilityPack[];
5
- export declare function getCapabilityPack(packId: string): CapabilityPack | null;
6
- export declare function isBuiltInCapabilityPack(packId: string): boolean;
7
- /**
8
- * Built-in packs plus the manifests registered for this workspace. Stored
9
- * manifests retain exact historical bytes. Execution views derive Skill labels
10
- * from their files, but malformed content needs explicit repair, not omission.
11
- */
12
- export declare function listWorkspaceCapabilityPacks(db: Database, workspaceId: string): Promise<CapabilityPack[]>;
13
- export declare function resolveCapabilityPack(db: Database, workspaceId: string, packId: string): Promise<CapabilityPack | null>;
14
- export declare function capabilityPackManifestDigest(pack: CapabilityPack): string;
15
- /** True when the Pack must use the owner-aware V2 preview/install lifecycle. */
16
- export declare function capabilityPackRequiresInstallationPlan(pack: CapabilityPack): boolean;
17
- export type InlinePackSkillInstall = {
18
- componentKey: string;
19
- capabilityId: string;
20
- pluginKey: string;
21
- sourceUrl: string;
22
- repositoryUrl: string;
23
- sourceCommit: string;
24
- sourcePath: string;
25
- name: string;
26
- description: string;
27
- activationMode: "workspace_managed" | "session_selected";
28
- contentSha256: string;
29
- totalBytes: number;
30
- files: Array<{
31
- path: string;
32
- content: string;
33
- byteSize: number;
34
- contentSha256: string;
35
- }>;
36
- };
37
- /** Convert a legacy inline Pack Skill into the ordinary immutable Skill model. */
38
- export declare function inlinePackSkillInstall(pack: CapabilityPack, skill: CapabilityPackSkill): InlinePackSkillInstall;
39
- export declare function previewCapabilityPackInstallation(db: Database, access: {
40
- accountId: string;
41
- workspaceId: string;
42
- subjectId: string;
43
- }, pack: CapabilityPack, options?: {
44
- rigId?: string;
45
- variableSetId?: string;
46
- }): Promise<PackInstallationPreview>;
47
- /**
48
- * v1 pack-scoped runtime rule: at most one enabled pack per workspace may
49
- * declare a `sandboxImage` — there is deliberately no image composition or
50
- * layering. Enforced when a pack is enabled (both the packs endpoint and the
51
- * generic capability enable path) and re-checked at session start by the
52
- * worker, which also covers manifests re-registered after enablement.
53
- */
54
- export declare function assertPackSandboxImageCompatible(db: Database, workspaceId: string, pack: CapabilityPack): Promise<void>;
55
- export declare function buildMarketingDailyAnalysisAgentConfig(input: {
56
- connections: SocialConnection[];
57
- documentBaseIds: string[];
58
- promptInstructions?: string;
59
- }): ScheduledTaskAgentConfig;
@@ -1,44 +0,0 @@
1
- export declare const OPENGENI_PRODUCT_INTEGRATION_PACK_ID = "opengeni-product-integration";
2
- /** Generated from the canonical external coding-agent guide, with an explicit
3
- * session-selected wrapper. Installation grants no executable capabilities. */
4
- export declare const OPENGENI_PRODUCT_INTEGRATION_SKILL: {
5
- name: string;
6
- description: string;
7
- activationMode: "session_selected";
8
- files: {
9
- path: string;
10
- content: string;
11
- }[];
12
- };
13
- export declare const OPENGENI_PRODUCT_INTEGRATION_PACK: {
14
- id: string;
15
- name: string;
16
- description: string;
17
- role: string;
18
- category: string;
19
- version: string;
20
- skills: {
21
- name: string;
22
- description: string;
23
- activationMode: "session_selected";
24
- files: {
25
- path: string;
26
- content: string;
27
- }[];
28
- }[];
29
- components: never[];
30
- tools: never[];
31
- connectors: never[];
32
- knowledge: never[];
33
- scheduledTaskTemplates: never[];
34
- automationTemplates: never[];
35
- metadata: {
36
- audience: string;
37
- purpose: string;
38
- implementationOnly: boolean;
39
- skillActivation: string;
40
- installationExposure: string;
41
- grantsExecutableCapabilities: boolean;
42
- canonicalSource: string;
43
- };
44
- };
@@ -1,5 +0,0 @@
1
- export declare const productIntegrationSkillDescription = "Design, implement, verify, and hand off a tenant-safe OpenGeni product integration while adapting to the customer's architecture, UI, data APIs, and desired delivery autonomy. Select only for an implementation session; installation alone does not expose it to other agents.";
2
- export declare const productIntegrationSkillFiles: {
3
- path: string;
4
- content: string;
5
- }[];
@@ -1,23 +0,0 @@
1
- import type { Settings } from "@opengeni/config";
2
- import { type Database, type HostMcpResolverRoute } from "@opengeni/db";
3
- import { type ConnectionCredentialsPort } from "@opengeni/contracts";
4
- import { pinnedFetch } from "@opengeni/network";
5
- /** Optional standalone transport for the existing request-time host port.
6
- * No successful credential is cached or persisted. The host must authorize
7
- * every immutable request context, including revocation and binding generation.
8
- */
9
- export declare function createRemoteMcpCredentialsPort(settings: Pick<Settings, "hostMcpCredentialResolversJson" | "environment" | "integrationsAllowPrivateNetworkTargets">, transport?: typeof pinnedFetch, routes?: {
10
- resolve: (input: {
11
- accountId: string;
12
- workspaceId: string;
13
- }) => Promise<HostMcpResolverRoute>;
14
- isCurrent: (input: {
15
- accountId: string;
16
- workspaceId: string;
17
- }, route: HostMcpResolverRoute) => Promise<boolean>;
18
- }): ConnectionCredentialsPort;
19
- /** Native standalone transport; the database remains authoritative on every
20
- * resolution/use. Embedded in-process ports retain their existing precedence. */
21
- export declare function createNativeRemoteMcpCredentialsPort(settings: Settings, db: Database, transport?: typeof pinnedFetch): ConnectionCredentialsPort;
22
- /** Parses only server configuration; never return parser errors containing secrets. */
23
- export declare function hasLegacyHostMcpResolver(settings: Pick<Settings, "hostMcpCredentialResolversJson">, accountId: string): boolean;
@@ -1,11 +0,0 @@
1
- import {
2
- createNativeRemoteMcpCredentialsPort,
3
- createRemoteMcpCredentialsPort,
4
- hasLegacyHostMcpResolver
5
- } from "./chunk-5WZYFL45.js";
6
- export {
7
- createNativeRemoteMcpCredentialsPort,
8
- createRemoteMcpCredentialsPort,
9
- hasLegacyHostMcpResolver
10
- };
11
- //# sourceMappingURL=remote-mcp-credentials.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,41 +0,0 @@
1
- import { HTTPException } from "hono/http-exception";
2
- import { resolveHostMcpBindingOwner, type Database } from "@opengeni/db";
3
- import {
4
- externalActorContinuationForAuthorization,
5
- hasPermission,
6
- hasVerifiedOwningUserAuthorization,
7
- requireResolvedAccessGrantAuthorization,
8
- type AccessGrantAuthorization,
9
- } from "../access";
10
- import { requireConnectOwnerAuthority } from "./connect-authority";
11
-
12
- /** Direct user admission only. Agents inherit exact accepted snapshots instead.
13
- * Native and externally represented users share owner semantics; service keys
14
- * cannot impersonate a human owner merely by naming a subject. */
15
- export function prepareHostMcpOwnerAuthorization(
16
- authorization: AccessGrantAuthorization,
17
- workspaceId: string,
18
- permission: "connections:read" | "connections:write",
19
- ) {
20
- const grant = requireResolvedAccessGrantAuthorization(authorization, workspaceId);
21
- if (
22
- !hasVerifiedOwningUserAuthorization(authorization) ||
23
- grant.metadata?.sessionId ||
24
- !hasPermission(grant.permissions, permission)
25
- )
26
- throw new HTTPException(403, {
27
- message: "Host binding requires verified owning-user authority",
28
- });
29
- const continuation = externalActorContinuationForAuthorization(authorization);
30
- const scope = {
31
- accountId: grant.accountId,
32
- workspaceId,
33
- subjectId: grant.subjectId,
34
- personalOwnerVerified: authorization.canonicalManagedHumanSession,
35
- ...(continuation ? { externalContinuation: continuation } : {}),
36
- };
37
- return async (tx: Database) => {
38
- await requireConnectOwnerAuthority(tx, scope, permission);
39
- return resolveHostMcpBindingOwner(tx, scope);
40
- };
41
- }
@@ -1,84 +0,0 @@
1
- import type { Context } from "hono";
2
- import { HTTPException } from "hono/http-exception";
3
- import { z } from "zod";
4
- import {
5
- HostMcpResolverSource,
6
- PutHostMcpResolverRequest,
7
- RevokeHostMcpResolverRequest,
8
- } from "@opengeni/contracts/host-mcp-resolvers";
9
- import { getHostMcpResolver, mutateHostMcpResolver, HostMcpResolverError } from "@opengeni/db";
10
- import { isLocalTestEnvironment, validateHttpUrl } from "@opengeni/network";
11
- import {
12
- accountScopedApiKeyWorkspaceAuthority,
13
- requireAccessContext,
14
- type AccessDeps,
15
- } from "../access";
16
- import { requireVariableSetEncryption } from "../domain/environments";
17
- import { hasLegacyHostMcpResolver } from "../remote-mcp-credentials";
18
-
19
- export async function hostMcpResolverForRequest(
20
- context: Context,
21
- deps: AccessDeps,
22
- organizationId: string,
23
- source: string,
24
- method: "get" | "put" | "revoke",
25
- raw?: unknown,
26
- ) {
27
- const id = z.string().uuid().safeParse(organizationId);
28
- const externalSource = HostMcpResolverSource.safeParse(source);
29
- if (!id.success || !externalSource.success)
30
- throw new HTTPException(422, { message: "invalid resolver identity" });
31
- const access = await requireAccessContext(context, deps);
32
- const service = accountScopedApiKeyWorkspaceAuthority(access);
33
- // Full organization keys carry workspace:admin, not human account:admin.
34
- // The stamped authority proves the exact organization service-key lane.
35
- if (!service || service.accountId !== id.data || !service.permissions.includes("workspace:admin"))
36
- throw new HTTPException(403, {
37
- message: "resolver administration requires an organization service key",
38
- });
39
- const actor = { accountId: id.data, subjectId: access.subjectId };
40
- try {
41
- if (method === "get") return await getHostMcpResolver(deps.db, actor, externalSource.data);
42
- const common = {
43
- externalSource: externalSource.data,
44
- encryptionKey: requireVariableSetEncryption(deps.settings),
45
- legacyConfigured: hasLegacyHostMcpResolver(deps.settings, id.data),
46
- };
47
- if (method === "put") {
48
- const parsed = PutHostMcpResolverRequest.safeParse(raw);
49
- if (!parsed.success) throw new HTTPException(422, { message: "invalid resolver operation" });
50
- let url: string;
51
- try {
52
- url = validateHttpUrl(parsed.data.url, {
53
- allowLoopbackHttp: isLocalTestEnvironment(deps.settings.environment),
54
- });
55
- if (
56
- new URL(url).protocol !== "https:" &&
57
- !isLocalTestEnvironment(deps.settings.environment)
58
- )
59
- throw new Error();
60
- } catch {
61
- throw new HTTPException(422, { message: "invalid resolver URL" });
62
- }
63
- return await mutateHostMcpResolver(deps.db, actor, {
64
- ...common,
65
- kind: "put",
66
- request: { ...parsed.data, url },
67
- });
68
- }
69
- const parsed = RevokeHostMcpResolverRequest.safeParse(raw);
70
- if (!parsed.success) throw new HTTPException(422, { message: "invalid resolver operation" });
71
- return await mutateHostMcpResolver(deps.db, actor, {
72
- ...common,
73
- kind: "revoke",
74
- request: parsed.data,
75
- });
76
- } catch (error) {
77
- if (error instanceof HostMcpResolverError)
78
- throw new HTTPException(error.status, { message: error.message });
79
- if (error instanceof HTTPException) throw error;
80
- // Database/encryption errors can carry SQL parameters. Never expose or log
81
- // the underlying credential-bearing cause at the public route boundary.
82
- throw new HTTPException(503, { message: "resolver administration unavailable" });
83
- }
84
- }