@opengeni/core 3.0.1 → 3.1.2

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 (257) hide show
  1. package/README.md +4 -4
  2. package/dist/access/index.d.ts +131 -7
  3. package/dist/access/service-initiator.d.ts +3 -0
  4. package/dist/application/archived-session-imports.d.ts +6 -0
  5. package/dist/application/composer-submit.d.ts +1 -1
  6. package/dist/application/connect-operation.d.ts +6 -0
  7. package/dist/application/external-workspace-members.d.ts +13 -1
  8. package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
  9. package/dist/application/modal-native-original-configuration.d.ts +79 -0
  10. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  11. package/dist/application/new-session-drafts.d.ts +29 -2
  12. package/dist/application/organization-privacy.d.ts +57 -0
  13. package/dist/application/prepared-mcp-connection.d.ts +31 -0
  14. package/dist/application/sandbox-recovery.d.ts +58 -0
  15. package/dist/application/session-commands.d.ts +3 -0
  16. package/dist/application/session-tenancy.d.ts +13 -4
  17. package/dist/billing/agent-run-admission.d.ts +21 -0
  18. package/dist/billing/limits.d.ts +27 -1
  19. package/dist/billing/model-call-admission.d.ts +34 -0
  20. package/dist/billing/model-usage-settlement.d.ts +112 -0
  21. package/dist/canonical-human-identities.js +1 -1
  22. package/dist/{chunk-VCZFFEPB.js → chunk-7T2SZ7BI.js} +16 -2
  23. package/dist/chunk-7T2SZ7BI.js.map +1 -0
  24. package/dist/{chunk-ZYCNLYGH.js → chunk-OMJFIIWK.js} +178 -12
  25. package/dist/chunk-OMJFIIWK.js.map +1 -0
  26. package/dist/{chunk-H7X52RI2.js → chunk-QI2M2B2K.js} +83 -8
  27. package/dist/chunk-QI2M2B2K.js.map +1 -0
  28. package/dist/{chunk-OF65T3PM.js → chunk-TTWTXQB2.js} +94 -6
  29. package/dist/chunk-TTWTXQB2.js.map +1 -0
  30. package/dist/codex-model-availability.d.ts +55 -0
  31. package/dist/default-session-model.d.ts +192 -0
  32. package/dist/dependencies.d.ts +41 -7
  33. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  34. package/dist/domain/agent-config-resolution.d.ts +49 -0
  35. package/dist/domain/automations.d.ts +8 -1
  36. package/dist/domain/capabilities.d.ts +112 -8
  37. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  38. package/dist/domain/connector-tool-permissions.d.ts +62 -0
  39. package/dist/domain/direct-model-provider.d.ts +3 -0
  40. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  41. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  42. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  43. package/dist/domain/editable-artifacts/service.d.ts +3 -1
  44. package/dist/domain/editable-artifacts/types.d.ts +1 -1
  45. package/dist/domain/encryption-key.d.ts +12 -0
  46. package/dist/domain/insights-timing.d.ts +16 -0
  47. package/dist/domain/insights-usage.d.ts +27 -0
  48. package/dist/domain/insights.d.ts +21 -3
  49. package/dist/domain/knowledge-files.d.ts +1 -1
  50. package/dist/domain/knowledge-preparation.d.ts +10 -0
  51. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  52. package/dist/domain/knowledge-search.d.ts +15 -76
  53. package/dist/domain/mcp-account-bindings.d.ts +17 -0
  54. package/dist/domain/mcp-account-routes.d.ts +21 -0
  55. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  56. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  57. package/dist/domain/personal-connection-delegations.d.ts +73 -12
  58. package/dist/domain/pr-review.d.ts +121 -6
  59. package/dist/domain/realtime-voice-billing.d.ts +103 -0
  60. package/dist/domain/resources.d.ts +17 -1
  61. package/dist/domain/scheduled-task-access.d.ts +265 -0
  62. package/dist/domain/scheduled-task-account-audit.d.ts +27 -0
  63. package/dist/domain/scheduled-task-audience.d.ts +70 -0
  64. package/dist/domain/scheduled-tasks.d.ts +61 -18
  65. package/dist/domain/session-connection-accounts.d.ts +53 -0
  66. package/dist/domain/session-file-access.d.ts +4 -0
  67. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  68. package/dist/domain/session-start-timing.d.ts +7 -0
  69. package/dist/domain/session-tool-policy.d.ts +102 -4
  70. package/dist/domain/sessions.d.ts +179 -15
  71. package/dist/domain/site-audience.d.ts +52 -0
  72. package/dist/domain/skills.d.ts +29 -1
  73. package/dist/domain/slack-bot.d.ts +46 -1
  74. package/dist/domain/slack-publication-secret-safety.d.ts +1 -1
  75. package/dist/domain/vaults/index.d.ts +7 -0
  76. package/dist/domain/vaults/mapping.d.ts +25 -0
  77. package/dist/domain/vaults/provider-registry.d.ts +72 -0
  78. package/dist/domain/vaults/provider-sync.d.ts +176 -0
  79. package/dist/domain/vaults/provider-writes.d.ts +57 -0
  80. package/dist/domain/vaults/secret-resolver.d.ts +34 -0
  81. package/dist/domain/vaults/types.d.ts +24 -0
  82. package/dist/domain/vaults/vault-service.d.ts +35 -0
  83. package/dist/domain/voice-input-billing.d.ts +77 -0
  84. package/dist/domain/web-search-billing.d.ts +51 -0
  85. package/dist/domain/workspace-credits.d.ts +7 -0
  86. package/dist/editable-artifact-live/application.d.ts +2 -1
  87. package/dist/editable-artifact-live/server.d.ts +5 -1
  88. package/dist/editable-artifact-live/ticket.d.ts +2 -1
  89. package/dist/editable-artifact-live/types.d.ts +9 -0
  90. package/dist/editable-artifact-live.js +2 -2
  91. package/dist/editable-artifacts.js +10 -2
  92. package/dist/goal-admission.d.ts +627 -0
  93. package/dist/host-session-usage-limit.d.ts +15 -0
  94. package/dist/index.d.ts +43 -8
  95. package/dist/index.js +22682 -11743
  96. package/dist/index.js.map +1 -1
  97. package/dist/managed-session.d.ts +110 -7
  98. package/dist/model-call.d.ts +58 -0
  99. package/dist/model-catalog.d.ts +29 -3
  100. package/dist/model-provider-credentials.d.ts +43 -0
  101. package/dist/product-usage-metrics.d.ts +30 -0
  102. package/dist/rigs/index.d.ts +1 -13
  103. package/dist/sandbox/fleet.d.ts +58 -4
  104. package/dist/sandbox/routing.d.ts +42 -2
  105. package/dist/sandbox/runtime-settings.d.ts +27 -17
  106. package/dist/session-authorization.d.ts +10 -0
  107. package/dist/session-usage-limit-metrics.d.ts +60 -0
  108. package/dist/session-usage-limits.d.ts +89 -0
  109. package/dist/site-agent-clamp.d.ts +71 -0
  110. package/dist/site-session-origin.d.ts +39 -2
  111. package/dist/transcription.d.ts +120 -3
  112. package/dist/turn-surface.d.ts +20 -0
  113. package/dist/user-presence.d.ts +32 -0
  114. package/dist/workflow-wake-contract.d.ts +13 -1
  115. package/package.json +15 -22
  116. package/src/access/index.ts +961 -38
  117. package/src/access/service-initiator.ts +50 -0
  118. package/src/application/api-integration-servers.ts +9 -0
  119. package/src/application/archived-session-imports.ts +161 -0
  120. package/src/application/composer-submit.ts +3 -2
  121. package/src/application/connect-authority.ts +3 -3
  122. package/src/application/connect-operation.ts +37 -3
  123. package/src/application/external-continuation.ts +20 -3
  124. package/src/application/external-link-work-admission.ts +3 -0
  125. package/src/application/external-workspace-members.ts +51 -3
  126. package/src/application/modal-native-live-declaration-join.ts +196 -0
  127. package/src/application/modal-native-original-configuration.ts +261 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +172 -55
  130. package/src/application/organization-privacy.ts +161 -0
  131. package/src/application/prepared-mcp-connection.ts +133 -0
  132. package/src/application/sandbox-recovery.ts +78 -0
  133. package/src/application/session-commands.ts +73 -1
  134. package/src/application/session-mcp-credential-rotation.ts +61 -18
  135. package/src/application/session-tenancy.ts +262 -44
  136. package/src/application/user-resource-grants.ts +1 -29
  137. package/src/billing/agent-run-admission.ts +117 -0
  138. package/src/billing/limits.ts +138 -14
  139. package/src/billing/model-call-admission.ts +118 -0
  140. package/src/billing/model-usage-settlement.ts +472 -0
  141. package/src/codex-model-availability.ts +264 -0
  142. package/src/default-session-model.ts +692 -0
  143. package/src/dependencies.ts +48 -6
  144. package/src/developer-setup-credential-ceiling.ts +60 -0
  145. package/src/domain/agent-config-resolution.ts +148 -0
  146. package/src/domain/automations.ts +76 -2
  147. package/src/domain/capabilities.ts +830 -181
  148. package/src/domain/connection-account-selection-error.ts +19 -0
  149. package/src/domain/connector-tool-permissions.ts +572 -0
  150. package/src/domain/direct-model-provider.ts +62 -0
  151. package/src/domain/editable-artifacts/agent-application.ts +44 -6
  152. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  153. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  154. package/src/domain/editable-artifacts/ports.ts +11 -0
  155. package/src/domain/editable-artifacts/service.ts +20 -0
  156. package/src/domain/editable-artifacts/types.ts +1 -1
  157. package/src/domain/encryption-key.ts +26 -0
  158. package/src/domain/file-owner.ts +16 -1
  159. package/src/domain/github-action-policies.ts +1 -1
  160. package/src/domain/github-skill-source.ts +3 -1
  161. package/src/domain/insights-timing.ts +95 -0
  162. package/src/domain/insights-usage.ts +67 -0
  163. package/src/domain/insights.ts +167 -43
  164. package/src/domain/knowledge-files.ts +10 -3
  165. package/src/domain/knowledge-messages.ts +1 -0
  166. package/src/domain/knowledge-preparation.test.ts +276 -0
  167. package/src/domain/knowledge-preparation.ts +147 -0
  168. package/src/domain/knowledge-search.test.ts +617 -5
  169. package/src/domain/knowledge-search.ts +240 -23
  170. package/src/domain/mcp-account-bindings.ts +169 -0
  171. package/src/domain/mcp-account-routes.ts +152 -0
  172. package/src/domain/native-mcp-connection-admission.ts +14 -0
  173. package/src/domain/organization-integration-catalog.ts +88 -0
  174. package/src/domain/personal-connection-delegations.ts +399 -257
  175. package/src/domain/pr-review.ts +24 -8
  176. package/src/domain/realtime-voice-billing.ts +425 -0
  177. package/src/domain/resources.ts +50 -4
  178. package/src/domain/scheduled-task-access.ts +1089 -0
  179. package/src/domain/scheduled-task-account-audit.ts +90 -0
  180. package/src/domain/scheduled-task-audience.ts +249 -0
  181. package/src/domain/scheduled-tasks.ts +1313 -374
  182. package/src/domain/session-connection-accounts.ts +239 -0
  183. package/src/domain/session-file-access.ts +47 -0
  184. package/src/domain/session-native-connection-replacement.ts +64 -0
  185. package/src/domain/session-start-timing.ts +60 -0
  186. package/src/domain/session-tool-policy.ts +489 -14
  187. package/src/domain/sessions.ts +2254 -717
  188. package/src/domain/site-audience.ts +130 -0
  189. package/src/domain/skills.ts +9 -0
  190. package/src/domain/slack-bot.ts +141 -4
  191. package/src/domain/slack-publication-secret-safety.ts +1 -1
  192. package/src/domain/vaults/index.ts +19 -0
  193. package/src/domain/vaults/mapping.ts +190 -0
  194. package/src/domain/vaults/provider-registry.ts +201 -0
  195. package/src/domain/vaults/provider-sync.ts +531 -0
  196. package/src/domain/vaults/provider-writes.ts +288 -0
  197. package/src/domain/vaults/secret-resolver.ts +464 -0
  198. package/src/domain/vaults/types.ts +26 -0
  199. package/src/domain/vaults/vault-service.ts +1316 -0
  200. package/src/domain/voice-input-billing.ts +330 -0
  201. package/src/domain/web-search-billing.ts +169 -0
  202. package/src/domain/workspace-credits.ts +13 -0
  203. package/src/editable-artifact-live/application.ts +8 -1
  204. package/src/editable-artifact-live/server.ts +154 -6
  205. package/src/editable-artifact-live/ticket.ts +86 -1
  206. package/src/editable-artifact-live/types.ts +10 -0
  207. package/src/goal-admission.ts +220 -0
  208. package/src/host-session-usage-limit.ts +25 -0
  209. package/src/index.ts +75 -11
  210. package/src/managed-session.ts +137 -6
  211. package/src/model-call.ts +79 -0
  212. package/src/model-catalog.ts +345 -91
  213. package/src/model-provider-credentials.ts +394 -0
  214. package/src/product-usage-metrics.ts +101 -0
  215. package/src/rigs/index.ts +23 -111
  216. package/src/sandbox/fleet.ts +253 -28
  217. package/src/sandbox/routing.ts +204 -43
  218. package/src/sandbox/runtime-settings.ts +159 -85
  219. package/src/session-authorization.ts +172 -23
  220. package/src/session-usage-limit-metrics.ts +95 -0
  221. package/src/session-usage-limits.ts +415 -0
  222. package/src/site-agent-clamp.ts +226 -0
  223. package/src/site-session-origin.ts +84 -5
  224. package/src/transcription.ts +123 -4
  225. package/src/turn-surface.ts +47 -0
  226. package/src/user-presence.ts +134 -0
  227. package/src/workflow-wake-contract.ts +14 -1
  228. package/dist/application/host-mcp-owner.d.ts +0 -6
  229. package/dist/application/host-mcp-resolvers.d.ts +0 -13
  230. package/dist/chunk-5WZYFL45.js +0 -266
  231. package/dist/chunk-5WZYFL45.js.map +0 -1
  232. package/dist/chunk-H7X52RI2.js.map +0 -1
  233. package/dist/chunk-OF65T3PM.js.map +0 -1
  234. package/dist/chunk-VCZFFEPB.js.map +0 -1
  235. package/dist/chunk-ZYCNLYGH.js.map +0 -1
  236. package/dist/domain/connection-authority.d.ts +0 -97
  237. package/dist/domain/connection-authority.js +0 -169
  238. package/dist/domain/connection-authority.js.map +0 -1
  239. package/dist/domain/environments.d.ts +0 -33
  240. package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
  241. package/dist/domain/host-mcp-task-admission.d.ts +0 -18
  242. package/dist/domain/packs.d.ts +0 -59
  243. package/dist/domain/product-integration-pack.d.ts +0 -44
  244. package/dist/domain/product-integration-skill.gen.d.ts +0 -5
  245. package/dist/remote-mcp-credentials.d.ts +0 -23
  246. package/dist/remote-mcp-credentials.js +0 -11
  247. package/dist/remote-mcp-credentials.js.map +0 -1
  248. package/src/application/host-mcp-owner.ts +0 -41
  249. package/src/application/host-mcp-resolvers.ts +0 -84
  250. package/src/domain/connection-authority.ts +0 -329
  251. package/src/domain/environments.ts +0 -120
  252. package/src/domain/host-mcp-authority-source-admission.ts +0 -25
  253. package/src/domain/host-mcp-task-admission.ts +0 -121
  254. package/src/domain/packs.ts +0 -699
  255. package/src/domain/product-integration-pack.ts +0 -42
  256. package/src/domain/product-integration-skill.gen.ts +0 -52
  257. package/src/remote-mcp-credentials.ts +0 -361
@@ -1,329 +0,0 @@
1
- import type {
2
- ConnectionKind,
3
- ConnectionStatus,
4
- SessionTenancyVisibility,
5
- UserResourceDelegation,
6
- UserResourceGrantMode,
7
- UserResourceGrantStatus,
8
- } from "@opengeni/contracts";
9
- import {
10
- ConnectionAuthorityEnvelope,
11
- ConnectionUseAttribution,
12
- ConnectionUseAuthoritySnapshot,
13
- type ConnectionUseAuthorizationResult,
14
- type ConnectionAuthoritySelectionSource,
15
- type ConnectionUseDenialReason,
16
- type ConnectionUseSelectionSource,
17
- } from "@opengeni/contracts/connection-authority";
18
-
19
- export type ConnectionAuthorityCandidate = {
20
- id: string;
21
- organizationId: string;
22
- workspaceId: string;
23
- generation: number;
24
- status: ConnectionStatus;
25
- providerDomain: string;
26
- kind: ConnectionKind;
27
- subjectId: string | null;
28
- ownerOrganizationMembershipId: string | null;
29
- };
30
-
31
- export type UserConnectionAuthorityCandidate = {
32
- id: string;
33
- organizationId: string;
34
- resourceKind: "connection";
35
- resourceId: string;
36
- originWorkspaceId: string;
37
- ownerSubjectId: string;
38
- ownerOrganizationMembershipId: string;
39
- ownerMembershipAuthorizationRevision: number;
40
- generation: number;
41
- status: "active" | "retained" | "revoked";
42
- };
43
-
44
- export class ConnectionAuthorityInvariantError extends Error {
45
- constructor(readonly code: string) {
46
- super(`connection authority invariant failed: ${code}`);
47
- this.name = "ConnectionAuthorityInvariantError";
48
- }
49
- }
50
-
51
- export function captureConnectionUseAuthority(input: {
52
- organizationId: string;
53
- targetWorkspaceId: string;
54
- targetSessionId: string;
55
- targetSessionVisibility: SessionTenancyVisibility;
56
- targetSessionAuthorityEpoch: number;
57
- acceptedWork:
58
- | { kind: "turn"; turnId: string }
59
- | {
60
- kind: "scheduled_task";
61
- taskId: string;
62
- taskAuthorityRevision: number;
63
- runId: string;
64
- };
65
- connection: ConnectionAuthorityCandidate;
66
- authority?: unknown;
67
- authorityWasOmitted?: boolean;
68
- userAuthority?: UserConnectionAuthorityCandidate | null;
69
- selectionSources: ConnectionUseSelectionSource[];
70
- }): ConnectionUseAuthoritySnapshot {
71
- const authority = ConnectionAuthorityEnvelope.parse(input.authority ?? {});
72
- const connection = input.connection;
73
- if (connection.organizationId !== input.organizationId) {
74
- throw new ConnectionAuthorityInvariantError("tenant_mismatch");
75
- }
76
- if (connection.status !== "active") {
77
- throw new ConnectionAuthorityInvariantError("connection_status_inactive");
78
- }
79
-
80
- let authoritySource: ConnectionAuthoritySelectionSource;
81
- let userDelegation: UserResourceDelegation | null = null;
82
- if (authority.scope === "workspace") {
83
- if (connection.subjectId !== null || connection.ownerOrganizationMembershipId !== null) {
84
- throw new ConnectionAuthorityInvariantError("workspace_borrowed_personal_connection");
85
- }
86
- if (connection.workspaceId !== input.targetWorkspaceId) {
87
- throw new ConnectionAuthorityInvariantError("workspace_connection_scope_mismatch");
88
- }
89
- authoritySource = input.authorityWasOmitted
90
- ? "legacy_workspace_omission"
91
- : "explicit_workspace";
92
- } else {
93
- const delegation = authority.userDelegation;
94
- const resourceAuthority = input.userAuthority;
95
- if (!delegation || !resourceAuthority) {
96
- throw new ConnectionAuthorityInvariantError("user_authority_missing");
97
- }
98
- if (!connection.subjectId || !connection.ownerOrganizationMembershipId) {
99
- throw new ConnectionAuthorityInvariantError("personal_owner_missing");
100
- }
101
- if (
102
- resourceAuthority.id !== delegation.authorityId ||
103
- resourceAuthority.organizationId !== input.organizationId ||
104
- resourceAuthority.resourceKind !== "connection" ||
105
- resourceAuthority.resourceId !== connection.id ||
106
- resourceAuthority.originWorkspaceId !== connection.workspaceId ||
107
- resourceAuthority.ownerSubjectId !== connection.subjectId ||
108
- resourceAuthority.ownerOrganizationMembershipId !==
109
- connection.ownerOrganizationMembershipId ||
110
- resourceAuthority.generation !== delegation.authorityGeneration ||
111
- resourceAuthority.status !== "active"
112
- ) {
113
- throw new ConnectionAuthorityInvariantError("user_authority_mismatch");
114
- }
115
- userDelegation = delegation;
116
- authoritySource = "user_delegation";
117
- }
118
-
119
- return ConnectionUseAuthoritySnapshot.parse({
120
- organizationId: input.organizationId,
121
- originWorkspaceId: connection.workspaceId,
122
- targetWorkspaceId: input.targetWorkspaceId,
123
- targetSessionId: input.targetSessionId,
124
- targetSessionVisibility: input.targetSessionVisibility,
125
- targetSessionAuthorityEpoch: input.targetSessionAuthorityEpoch,
126
- acceptedWork: input.acceptedWork,
127
- connectionId: connection.id,
128
- connectionGeneration: connection.generation,
129
- connectionStatus: "active",
130
- providerDomain: connection.providerDomain.toLowerCase(),
131
- connectionKind: connection.kind,
132
- scope: authority.scope,
133
- ownerSubjectId: connection.subjectId,
134
- ownerOrganizationMembershipId: connection.ownerOrganizationMembershipId,
135
- ownerMembershipAuthorizationRevision:
136
- authority.scope === "user" ? input.userAuthority!.ownerMembershipAuthorizationRevision : null,
137
- authoritySource,
138
- selectionSources: input.selectionSources,
139
- userDelegation,
140
- });
141
- }
142
-
143
- export type LiveConnectionUseState = {
144
- organizationId: string;
145
- targetWorkspaceId: string;
146
- targetWorkspaceAccessActive: boolean;
147
- session: {
148
- id: string;
149
- organizationId: string;
150
- workspaceId: string;
151
- visibility: SessionTenancyVisibility;
152
- authorityEpoch: number;
153
- active: boolean;
154
- };
155
- connection: ConnectionAuthorityCandidate | null;
156
- ownerMembership: {
157
- id: string;
158
- organizationId: string;
159
- subjectId: string;
160
- status: "provisioning" | "active" | "suspended" | "revoked";
161
- authorizationRevision: number;
162
- } | null;
163
- userAuthority: UserConnectionAuthorityCandidate | null;
164
- grant: {
165
- id: string;
166
- authorityId: string;
167
- organizationId: string;
168
- workspaceId: string;
169
- sessionId: string | null;
170
- action: string;
171
- mode: UserResourceGrantMode;
172
- context: SessionTenancyVisibility;
173
- authorityEpoch: number | null;
174
- generation: number;
175
- status: UserResourceGrantStatus;
176
- expiresAt: string | null;
177
- consumed: boolean;
178
- } | null;
179
- };
180
-
181
- function denied(reason: ConnectionUseDenialReason): ConnectionUseAuthorizationResult {
182
- return { status: "denied", reason };
183
- }
184
-
185
- /**
186
- * Revalidates every mutable fence immediately before provider use. Callers must
187
- * resolve the live state in one DB authority boundary; this pure function does
188
- * not cache, refresh, decrypt, or invoke a provider.
189
- */
190
- export function revalidateConnectionUseAuthority(input: {
191
- snapshot: ConnectionUseAuthoritySnapshot;
192
- live: LiveConnectionUseState;
193
- now?: Date;
194
- }): ConnectionUseAuthorizationResult {
195
- const snapshot = ConnectionUseAuthoritySnapshot.parse(input.snapshot);
196
- const live = input.live;
197
- const now = input.now ?? new Date();
198
- if (
199
- live.organizationId !== snapshot.organizationId ||
200
- live.targetWorkspaceId !== snapshot.targetWorkspaceId
201
- ) {
202
- return denied("tenant_mismatch");
203
- }
204
- if (!live.targetWorkspaceAccessActive) return denied("workspace_access_inactive");
205
- if (!live.session.active) return denied("session_inactive");
206
- if (
207
- live.session.id !== snapshot.targetSessionId ||
208
- live.session.organizationId !== snapshot.organizationId ||
209
- live.session.workspaceId !== snapshot.targetWorkspaceId
210
- ) {
211
- return denied("session_identity_changed");
212
- }
213
- if (live.session.visibility !== snapshot.targetSessionVisibility) {
214
- return denied("session_visibility_changed");
215
- }
216
- if (live.session.authorityEpoch !== snapshot.targetSessionAuthorityEpoch) {
217
- return denied("session_authority_epoch_changed");
218
- }
219
- const connection = live.connection;
220
- if (!connection) return denied("connection_missing");
221
- if (
222
- connection.id !== snapshot.connectionId ||
223
- connection.organizationId !== snapshot.organizationId ||
224
- connection.workspaceId !== snapshot.originWorkspaceId ||
225
- connection.providerDomain.toLowerCase() !== snapshot.providerDomain ||
226
- connection.kind !== snapshot.connectionKind
227
- ) {
228
- return denied("connection_identity_changed");
229
- }
230
- if (connection.generation !== snapshot.connectionGeneration) {
231
- return denied("connection_generation_changed");
232
- }
233
- if (connection.status !== "active") return denied("connection_status_inactive");
234
- if (
235
- connection.subjectId !== snapshot.ownerSubjectId ||
236
- connection.ownerOrganizationMembershipId !== snapshot.ownerOrganizationMembershipId
237
- ) {
238
- return denied("connection_owner_changed");
239
- }
240
-
241
- if (snapshot.scope === "workspace") {
242
- if (connection.subjectId !== null || connection.workspaceId !== snapshot.targetWorkspaceId) {
243
- return denied("connection_owner_changed");
244
- }
245
- return {
246
- status: "authorized",
247
- attribution: ConnectionUseAttribution.parse({
248
- organizationId: snapshot.organizationId,
249
- workspaceId: snapshot.targetWorkspaceId,
250
- sessionId: snapshot.targetSessionId,
251
- connectionId: snapshot.connectionId,
252
- connectionGeneration: snapshot.connectionGeneration,
253
- scope: "workspace",
254
- ownerSubjectId: null,
255
- authorityId: null,
256
- grantId: null,
257
- }),
258
- };
259
- }
260
-
261
- const delegation = snapshot.userDelegation!;
262
- const membership = live.ownerMembership;
263
- if (
264
- !membership ||
265
- membership.status !== "active" ||
266
- membership.id !== snapshot.ownerOrganizationMembershipId ||
267
- membership.organizationId !== snapshot.organizationId ||
268
- membership.subjectId !== snapshot.ownerSubjectId ||
269
- membership.authorizationRevision !== snapshot.ownerMembershipAuthorizationRevision
270
- ) {
271
- return denied("owner_membership_inactive");
272
- }
273
- const authority = live.userAuthority;
274
- if (!authority) return denied("authority_missing");
275
- if (
276
- authority.id !== delegation.authorityId ||
277
- authority.organizationId !== snapshot.organizationId ||
278
- authority.resourceKind !== "connection" ||
279
- authority.resourceId !== snapshot.connectionId ||
280
- authority.originWorkspaceId !== snapshot.originWorkspaceId ||
281
- authority.ownerSubjectId !== snapshot.ownerSubjectId ||
282
- authority.ownerOrganizationMembershipId !== snapshot.ownerOrganizationMembershipId
283
- ) {
284
- return denied("authority_identity_changed");
285
- }
286
- if (authority.generation !== delegation.authorityGeneration) {
287
- return denied("authority_generation_changed");
288
- }
289
- if (authority.status !== "active") return denied("authority_status_inactive");
290
-
291
- const grant = live.grant;
292
- if (!grant) return denied("grant_missing");
293
- if (
294
- grant.id !== delegation.grantId ||
295
- grant.authorityId !== delegation.authorityId ||
296
- grant.organizationId !== snapshot.organizationId ||
297
- grant.workspaceId !== snapshot.targetWorkspaceId ||
298
- grant.sessionId !== delegation.sessionId ||
299
- grant.action !== "connection.use" ||
300
- grant.mode !== delegation.mode ||
301
- grant.context !== snapshot.targetSessionVisibility ||
302
- grant.authorityEpoch !== delegation.authorityEpoch
303
- ) {
304
- return denied("grant_identity_changed");
305
- }
306
- if (grant.generation !== delegation.grantGeneration) {
307
- return denied("grant_generation_changed");
308
- }
309
- if (grant.status !== "active") return denied("grant_status_inactive");
310
- if (grant.expiresAt !== null && Date.parse(grant.expiresAt) <= now.getTime()) {
311
- return denied("grant_expired");
312
- }
313
- if (grant.mode === "once" && grant.consumed) return denied("grant_already_consumed");
314
-
315
- return {
316
- status: "authorized",
317
- attribution: ConnectionUseAttribution.parse({
318
- organizationId: snapshot.organizationId,
319
- workspaceId: snapshot.targetWorkspaceId,
320
- sessionId: snapshot.targetSessionId,
321
- connectionId: snapshot.connectionId,
322
- connectionGeneration: snapshot.connectionGeneration,
323
- scope: "user",
324
- ownerSubjectId: snapshot.ownerSubjectId,
325
- authorityId: delegation.authorityId,
326
- grantId: delegation.grantId,
327
- }),
328
- };
329
- }
@@ -1,120 +0,0 @@
1
- import { environmentsEncryptionKeyBytes, type Settings } from "@opengeni/config";
2
- import {
3
- variableSetVariableNameReservation,
4
- type AccessGrant,
5
- type VariableSet,
6
- } from "@opengeni/contracts";
7
- import { getVariableSet, recordAuditEvent, type Database } from "@opengeni/db";
8
- import { HTTPException } from "hono/http-exception";
9
- import { requirePermission } from "../access";
10
-
11
- export const MAX_ENVIRONMENTS_PER_WORKSPACE = 25;
12
- export const MAX_VARIABLES_PER_ENVIRONMENT = 100;
13
-
14
- // Names the platform itself injects into sandboxes (sandboxEnvironmentForRun,
15
- // collectGitIdentityEnvironment) plus loader/startup-injection vectors. These
16
- // can never be set as variable set variables, so the run-scoped
17
- // git auth block and git identity always win without silent collisions.
18
- export function assertAllowedVariableSetVariableName(name: string): void {
19
- if (variableSetVariableNameReservation(name)) {
20
- throw new HTTPException(422, {
21
- message: `reserved variable set variable name / reserved environment variable name: ${name}`,
22
- });
23
- }
24
- }
25
-
26
- /** @deprecated use assertAllowedVariableSetVariableName */
27
- export const assertAllowedEnvironmentVariableName = assertAllowedVariableSetVariableName;
28
-
29
- export function requireVariableSetEncryption(settings: Settings): Uint8Array {
30
- const key = environmentsEncryptionKeyBytes(settings);
31
- if (!key) {
32
- throw new HTTPException(503, {
33
- message: "variable sets require OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY",
34
- });
35
- }
36
- return key;
37
- }
38
-
39
- /** @deprecated use requireVariableSetEncryption */
40
- export const requireEnvironmentEncryption = requireVariableSetEncryption;
41
-
42
- export async function requireVariableSetForApi(
43
- db: Database,
44
- grant: AccessGrant,
45
- variableSetId: string,
46
- ): Promise<VariableSet> {
47
- const variableSet = await getVariableSet(
48
- db,
49
- {
50
- accountId: grant.accountId,
51
- workspaceId: grant.workspaceId,
52
- subjectId: grant.subjectId,
53
- },
54
- variableSetId,
55
- );
56
- if (!variableSet) {
57
- throw new HTTPException(404, { message: "variableSet not found" });
58
- }
59
- return variableSet;
60
- }
61
-
62
- /**
63
- * Validates an variableSet attachment supplied in a request payload (session
64
- * create, scheduled task create/update, pack enable). Requires the
65
- * `variable-sets:use` permission unless the attachment was already authorized
66
- * (pack-installation-inherited attachments), and maps a missing or
67
- * cross-variable set to 422 because the id is payload, not the route
68
- * target. RLS plus the workspace_id clause make cross-workspace ids
69
- * indistinguishable from missing ones.
70
- */
71
- export async function validateVariableSetAttachment(
72
- deps: { settings: Settings; db: Database },
73
- grant: AccessGrant,
74
- workspaceId: string,
75
- variableSetId: string,
76
- options: { preauthorized?: boolean } = {},
77
- ): Promise<VariableSet> {
78
- requireVariableSetEncryption(deps.settings);
79
- if (!options.preauthorized) {
80
- requirePermission(grant, "variable-sets:attach");
81
- requirePermission(grant, "variable-sets:use");
82
- }
83
- const variableSet = await getVariableSet(
84
- deps.db,
85
- { accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
86
- variableSetId,
87
- );
88
- if (!variableSet) {
89
- throw new HTTPException(422, { message: "unknown variableSetId" });
90
- }
91
- return variableSet;
92
- }
93
-
94
- export async function recordVariableSetAuditEvent(
95
- db: Database,
96
- input: {
97
- grant: AccessGrant;
98
- action:
99
- | "variable_set.created"
100
- | "variable_set.updated"
101
- | "variable_set.deleted"
102
- | "variable_set.variable.set"
103
- | "variable_set.variable.deleted";
104
- variableSetId: string;
105
- variableName?: string;
106
- },
107
- ): Promise<void> {
108
- await recordAuditEvent(db, {
109
- accountId: input.grant.accountId,
110
- workspaceId: input.grant.workspaceId,
111
- subjectId: input.grant.subjectId,
112
- action: input.action,
113
- targetType: "workspace_variable_set",
114
- targetId: input.variableSetId,
115
- metadata: {
116
- variableSetId: input.variableSetId,
117
- ...(input.variableName ? { name: input.variableName } : {}),
118
- },
119
- });
120
- }
@@ -1,25 +0,0 @@
1
- import type { Settings } from "@opengeni/config";
2
- import type { McpServerConnectionRef } from "@opengeni/contracts";
3
- import { HTTPException } from "hono/http-exception";
4
-
5
- /**
6
- * Explicit host-owned MCP refs change which credential authority executes an
7
- * opaque connection id. Admit new external refs only after the operator has
8
- * completed the two-phase fleet rollout. Readers and inheritance remain
9
- * tolerant regardless of this switch, and markerless legacy refs retain their
10
- * bounded non-UUID compatibility path.
11
- */
12
- export function assertHostMcpAuthoritySourceAdmissionEnabled(
13
- settings: Pick<Settings, "hostMcpAuthoritySourceAdmissionEnabled">,
14
- connectionRef: McpServerConnectionRef | null | undefined,
15
- ): void {
16
- if (
17
- connectionRef?.authoritySource === "host" &&
18
- !settings.hostMcpAuthoritySourceAdmissionEnabled
19
- ) {
20
- throw new HTTPException(422, {
21
- message:
22
- "new host-owned MCP connection refs are not admitted; upgrade the complete API/worker/web fleet, then set OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED=true",
23
- });
24
- }
25
- }
@@ -1,121 +0,0 @@
1
- import { HTTPException } from "hono/http-exception";
2
- import type { Settings } from "@opengeni/config";
3
- import type { ToolRef, ScheduledTask, AccessGrant } from "@opengeni/contracts";
4
- import {
5
- hostMcpBindingMatchesSelection,
6
- HostMcpCreateSelections,
7
- } from "@opengeni/contracts/host-mcp-bindings";
8
- import {
9
- captureHostMcpTaskAuthorities,
10
- getHostMcpBinding,
11
- getHostMcpDelegation,
12
- HostMcpDelegationAuthorityError,
13
- inheritHostMcpTaskAuthoritiesFromAttempt,
14
- type Database,
15
- } from "@opengeni/db";
16
- import { hasPermission, type AccessGrantAuthorization } from "../access";
17
- import { prepareHostMcpOwnerAuthorization } from "../application/host-mcp-owner";
18
- import { assertHostMcpAuthoritySourceAdmissionEnabled } from "./host-mcp-authority-source-admission";
19
-
20
- /** Internal closure, not a caller-provided callback or durable key dependency. */
21
- export function prepareHostMcpTaskAdmission(input: {
22
- settings: Settings;
23
- tools: ToolRef[];
24
- grant: AccessGrant;
25
- authorization?: AccessGrantAuthorization;
26
- selections: unknown;
27
- }): (tx: Database, task: ScheduledTask) => Promise<void> {
28
- const selections = HostMcpCreateSelections.parse(input.selections);
29
- if (
30
- !input.authorization ||
31
- input.authorization.grant.accountId !== input.grant.accountId ||
32
- input.authorization.grant.subjectId !== input.grant.subjectId ||
33
- input.authorization?.grant.workspaceId !== input.grant.workspaceId ||
34
- input.grant.metadata?.["sessionId"] ||
35
- !hasPermission(input.authorization?.grant.permissions ?? [], "connections:read") ||
36
- !hasPermission(input.grant.permissions, "connections:read")
37
- )
38
- throw new HTTPException(403, {
39
- message: "Host task selection requires a verified owner",
40
- });
41
- const reauthorize = prepareHostMcpOwnerAuthorization(
42
- input.authorization,
43
- input.grant.workspaceId,
44
- "connections:read",
45
- );
46
- const prepared = selections.map((selection) => {
47
- const server = input.settings.mcpServers.find(
48
- (candidate) => candidate.id === selection.serverId,
49
- );
50
- if (
51
- !server?.url ||
52
- server.connectionRef?.authoritySource !== "host" ||
53
- !server.connectionRef.hostBinding ||
54
- !input.tools.some((tool) => tool.kind === "mcp" && tool.id === selection.serverId)
55
- )
56
- throw new HTTPException(422, {
57
- message: "Host task selection must match a selected configured server",
58
- });
59
- assertHostMcpAuthoritySourceAdmissionEnabled(input.settings, server.connectionRef);
60
- return {
61
- delegationId: selection.delegationId,
62
- generation: selection.generation,
63
- configured: structuredClone({
64
- serverId: selection.serverId,
65
- destinationUrl: server.url,
66
- connectionRef: server.connectionRef,
67
- }),
68
- };
69
- });
70
- return async (tx, task) => {
71
- const owner = await reauthorize(tx);
72
- try {
73
- const selected = [];
74
- for (const selection of prepared) {
75
- const delegation = await getHostMcpDelegation(tx, owner, selection.delegationId);
76
- const binding = delegation
77
- ? await getHostMcpBinding(tx, owner, delegation.bindingId)
78
- : null;
79
- if (!binding || !hostMcpBindingMatchesSelection(binding, selection.configured))
80
- throw new HostMcpDelegationAuthorityError("Host task selection changed");
81
- selected.push({
82
- delegationId: selection.delegationId,
83
- generation: selection.generation,
84
- bindingId: binding.id,
85
- bindingGeneration: binding.generation,
86
- definition: binding.definition,
87
- });
88
- }
89
- if (selected.length) await captureHostMcpTaskAuthorities(tx, owner, task, selected);
90
- } catch (error) {
91
- if (error instanceof HostMcpDelegationAuthorityError)
92
- throw new HTTPException(403, { message: error.message });
93
- throw error;
94
- }
95
- };
96
- }
97
-
98
- export function prepareInheritedHostMcpTaskAdmission(
99
- settings: Settings,
100
- tools: ToolRef[],
101
- source: { sessionId: string; turnId: string; attemptId: string; executionGeneration: number },
102
- ): (tx: Database, task: ScheduledTask) => Promise<void> {
103
- const configured = settings.mcpServers.flatMap((server) => {
104
- if (
105
- !tools.some((tool) => tool.kind === "mcp" && tool.id === server.id) ||
106
- server.connectionRef?.authoritySource !== "host" ||
107
- !server.connectionRef.hostBinding ||
108
- !server.url
109
- )
110
- return [];
111
- assertHostMcpAuthoritySourceAdmissionEnabled(settings, server.connectionRef);
112
- return [
113
- structuredClone({
114
- serverId: server.id,
115
- destinationUrl: server.url,
116
- connectionRef: server.connectionRef,
117
- }),
118
- ];
119
- });
120
- return (tx, task) => inheritHostMcpTaskAuthoritiesFromAttempt(tx, task, source, configured);
121
- }