@opengeni/core 0.28.0 → 1.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 (224) hide show
  1. package/README.md +1 -1
  2. package/dist/access/external-actor-authority.d.ts +47 -0
  3. package/dist/access/index.d.ts +182 -3
  4. package/dist/access/service-initiator.d.ts +3 -0
  5. package/dist/application/api-integration-servers.d.ts +20 -0
  6. package/dist/application/archived-session-imports.d.ts +6 -0
  7. package/dist/application/composer-submit.d.ts +24 -0
  8. package/dist/application/connect-authority.d.ts +13 -0
  9. package/dist/application/connect-operation.d.ts +31 -0
  10. package/dist/application/external-continuation.d.ts +15 -0
  11. package/dist/application/external-identity-lifecycle.d.ts +20 -0
  12. package/dist/application/external-link-work-admission.d.ts +12 -0
  13. package/dist/application/external-workspace-members.d.ts +34 -0
  14. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  15. package/dist/application/new-session-drafts.d.ts +39 -2
  16. package/dist/application/sandbox-recovery.d.ts +58 -0
  17. package/dist/application/session-commands.d.ts +26 -13
  18. package/dist/application/session-mcp-credential-rotation.d.ts +29 -0
  19. package/dist/application/session-tenancy.d.ts +19 -0
  20. package/dist/application/user-resource-grants.d.ts +20 -0
  21. package/dist/billing/limits.d.ts +11 -0
  22. package/dist/canonical-human-identities.d.ts +7 -2
  23. package/dist/canonical-human-identities.js +17 -4
  24. package/dist/canonical-human-identities.js.map +1 -1
  25. package/dist/{chunk-6WKPWE5S.js → chunk-2MKMRGSY.js} +108 -24
  26. package/dist/chunk-2MKMRGSY.js.map +1 -0
  27. package/dist/{chunk-NYPMQ7NO.js → chunk-GVO3N37G.js} +205 -37
  28. package/dist/chunk-GVO3N37G.js.map +1 -0
  29. package/dist/{chunk-JJU6I5XD.js → chunk-LCQXNR62.js} +36 -10
  30. package/dist/chunk-LCQXNR62.js.map +1 -0
  31. package/dist/chunk-MM6N7CTO.js +387 -0
  32. package/dist/chunk-MM6N7CTO.js.map +1 -0
  33. package/dist/chunk-QO5GVFFO.js +235 -0
  34. package/dist/chunk-QO5GVFFO.js.map +1 -0
  35. package/dist/codex-model-availability.d.ts +14 -0
  36. package/dist/default-session-model.d.ts +139 -0
  37. package/dist/dependencies.d.ts +87 -4
  38. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  39. package/dist/domain/agent-config-resolution.d.ts +49 -0
  40. package/dist/domain/automations.d.ts +58 -0
  41. package/dist/domain/capabilities.d.ts +22 -4
  42. package/dist/domain/company-profile-agent-admin.d.ts +25 -0
  43. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  44. package/dist/domain/connector-tool-permissions.d.ts +36 -0
  45. package/dist/domain/direct-model-provider.d.ts +3 -0
  46. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  47. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  48. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  49. package/dist/domain/editable-artifacts/service.d.ts +4 -3
  50. package/dist/domain/environments.d.ts +5 -9
  51. package/dist/domain/external-creation-attribution.d.ts +6 -0
  52. package/dist/domain/file-owner.d.ts +8 -0
  53. package/dist/domain/github-action-policies.d.ts +36 -0
  54. package/dist/domain/github-repository-bindings.d.ts +117 -0
  55. package/dist/domain/github-skill-source.d.ts +5 -0
  56. package/dist/domain/governed-learning-slack-publication.d.ts +45 -0
  57. package/dist/domain/insights-timing.d.ts +16 -0
  58. package/dist/domain/insights-usage.d.ts +27 -0
  59. package/dist/domain/insights.d.ts +28 -1
  60. package/dist/domain/knowledge-files.d.ts +20 -0
  61. package/dist/domain/knowledge-messages.d.ts +39 -0
  62. package/dist/domain/knowledge-messages.test.d.ts +1 -0
  63. package/dist/domain/knowledge-preparation.d.ts +10 -0
  64. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  65. package/dist/domain/knowledge-search.d.ts +15 -0
  66. package/dist/domain/knowledge-search.test.d.ts +1 -0
  67. package/dist/domain/knowledge.d.ts +9 -0
  68. package/dist/domain/mcp-account-bindings.d.ts +19 -0
  69. package/dist/domain/mcp-account-routes.d.ts +21 -0
  70. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  71. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  72. package/dist/domain/organization-membership-lifecycle.d.ts +1 -0
  73. package/dist/domain/personal-connection-delegations.d.ts +87 -4
  74. package/dist/domain/pr-review.d.ts +249 -0
  75. package/dist/domain/resources.d.ts +24 -3
  76. package/dist/domain/scheduled-task-access.d.ts +247 -0
  77. package/dist/domain/scheduled-tasks.d.ts +103 -6
  78. package/dist/domain/session-connection-accounts.d.ts +16 -0
  79. package/dist/domain/session-file-access.d.ts +4 -0
  80. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  81. package/dist/domain/session-start-timing.d.ts +7 -0
  82. package/dist/domain/session-tool-policy.d.ts +93 -4
  83. package/dist/domain/sessions.d.ts +275 -28
  84. package/dist/domain/skill-imports.d.ts +1 -0
  85. package/dist/domain/skill-search.d.ts +30 -0
  86. package/dist/domain/skills.d.ts +117 -0
  87. package/dist/domain/slack-bot.d.ts +46 -1
  88. package/dist/domain/workspace-members.d.ts +8 -1
  89. package/dist/editable-artifact-live/application.d.ts +12 -3
  90. package/dist/editable-artifact-live/ports.d.ts +0 -1
  91. package/dist/editable-artifact-live/server.d.ts +5 -2
  92. package/dist/editable-artifact-live/ticket.d.ts +2 -2
  93. package/dist/editable-artifact-live/types.d.ts +14 -2
  94. package/dist/editable-artifact-live.js +2 -2
  95. package/dist/editable-artifacts.js +10 -4
  96. package/dist/index.d.ts +49 -3
  97. package/dist/index.js +18826 -6847
  98. package/dist/index.js.map +1 -1
  99. package/dist/managed-auth-session-sets.d.ts +131 -0
  100. package/dist/managed-auth-session-sets.js +51 -0
  101. package/dist/managed-auth-session-sets.js.map +1 -0
  102. package/dist/managed-session.d.ts +98 -11
  103. package/dist/model-catalog.d.ts +117 -0
  104. package/dist/product-usage-metrics.d.ts +30 -0
  105. package/dist/rigs/index.d.ts +22 -5
  106. package/dist/rigs/provider-images.d.ts +1 -1
  107. package/dist/sandbox/fleet.d.ts +59 -10
  108. package/dist/sandbox/routing.d.ts +22 -2
  109. package/dist/sandbox/runtime-settings.d.ts +56 -0
  110. package/dist/session-authorization.d.ts +38 -1
  111. package/dist/site-session-origin.d.ts +9 -0
  112. package/dist/transcription.d.ts +12 -1
  113. package/dist/turn-surface.d.ts +18 -0
  114. package/dist/user-presence.d.ts +32 -0
  115. package/package.json +18 -11
  116. package/src/access/external-actor-authority.ts +94 -0
  117. package/src/access/index.ts +1386 -44
  118. package/src/access/service-initiator.ts +50 -0
  119. package/src/application/api-integration-servers.ts +215 -0
  120. package/src/application/archived-session-imports.ts +161 -0
  121. package/src/application/composer-submit.ts +77 -0
  122. package/src/application/connect-authority.ts +77 -0
  123. package/src/application/connect-operation.ts +80 -0
  124. package/src/application/external-continuation.ts +129 -0
  125. package/src/application/external-identity-lifecycle.ts +48 -0
  126. package/src/application/external-link-work-admission.ts +90 -0
  127. package/src/application/external-workspace-members.ts +232 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +222 -29
  130. package/src/application/sandbox-recovery.ts +78 -0
  131. package/src/application/session-commands.ts +430 -73
  132. package/src/application/session-mcp-credential-rotation.ts +217 -0
  133. package/src/application/session-tenancy.ts +445 -0
  134. package/src/application/user-resource-grants.ts +154 -0
  135. package/src/billing/limits.ts +103 -24
  136. package/src/canonical-human-identities.ts +22 -3
  137. package/src/codex-model-availability.ts +136 -0
  138. package/src/default-session-model.ts +656 -0
  139. package/src/dependencies.ts +97 -5
  140. package/src/developer-setup-credential-ceiling.ts +60 -0
  141. package/src/domain/agent-config-resolution.ts +148 -0
  142. package/src/domain/automations.ts +270 -0
  143. package/src/domain/capabilities.ts +244 -151
  144. package/src/domain/company-profile-agent-admin.ts +56 -0
  145. package/src/domain/connection-account-selection-error.ts +19 -0
  146. package/src/domain/connector-tool-permissions.ts +371 -0
  147. package/src/domain/direct-model-provider.ts +62 -0
  148. package/src/domain/editable-artifacts/agent-application.ts +61 -15
  149. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  150. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  151. package/src/domain/editable-artifacts/ports.ts +11 -0
  152. package/src/domain/editable-artifacts/service.ts +32 -1
  153. package/src/domain/editable-artifacts/snapshot-compaction.ts +9 -5
  154. package/src/domain/editable-artifacts/snapshot-verifier-genesis.ts +10 -8
  155. package/src/domain/editable-artifacts/snapshot-verifier.ts +10 -3
  156. package/src/domain/environments.ts +25 -45
  157. package/src/domain/external-creation-attribution.ts +22 -0
  158. package/src/domain/file-owner.ts +67 -0
  159. package/src/domain/github-action-policies.ts +169 -0
  160. package/src/domain/github-repository-bindings.ts +295 -0
  161. package/src/domain/github-skill-source.ts +233 -0
  162. package/src/domain/governed-learning-slack-publication.ts +157 -0
  163. package/src/domain/insights-timing.ts +95 -0
  164. package/src/domain/insights-usage.ts +67 -0
  165. package/src/domain/insights.ts +270 -169
  166. package/src/domain/knowledge-files.ts +46 -0
  167. package/src/domain/knowledge-messages.test.ts +91 -0
  168. package/src/domain/knowledge-messages.ts +106 -0
  169. package/src/domain/knowledge-preparation.test.ts +276 -0
  170. package/src/domain/knowledge-preparation.ts +147 -0
  171. package/src/domain/knowledge-search.test.ts +561 -0
  172. package/src/domain/knowledge-search.ts +256 -0
  173. package/src/domain/knowledge.ts +133 -0
  174. package/src/domain/mcp-account-bindings.ts +171 -0
  175. package/src/domain/mcp-account-routes.ts +121 -0
  176. package/src/domain/native-mcp-connection-admission.ts +14 -0
  177. package/src/domain/organization-integration-catalog.ts +88 -0
  178. package/src/domain/organization-membership-lifecycle.ts +10 -0
  179. package/src/domain/personal-connection-delegations.ts +758 -115
  180. package/src/domain/pr-review.ts +687 -0
  181. package/src/domain/resources.ts +182 -25
  182. package/src/domain/scheduled-task-access.ts +1052 -0
  183. package/src/domain/scheduled-tasks.ts +1952 -215
  184. package/src/domain/session-connection-accounts.ts +67 -0
  185. package/src/domain/session-file-access.ts +47 -0
  186. package/src/domain/session-native-connection-replacement.ts +64 -0
  187. package/src/domain/session-start-timing.ts +55 -0
  188. package/src/domain/session-tool-policy.ts +443 -19
  189. package/src/domain/sessions.ts +3417 -619
  190. package/src/domain/skill-imports.ts +137 -17
  191. package/src/domain/skill-search.ts +221 -0
  192. package/src/domain/skills.ts +104 -0
  193. package/src/domain/slack-bot.ts +128 -3
  194. package/src/domain/workspace-members.ts +34 -2
  195. package/src/editable-artifact-live/application.ts +29 -4
  196. package/src/editable-artifact-live/ports.ts +0 -1
  197. package/src/editable-artifact-live/server.ts +167 -13
  198. package/src/editable-artifact-live/ticket.ts +87 -6
  199. package/src/editable-artifact-live/types.ts +16 -2
  200. package/src/editable-artifact-live/wire.ts +0 -10
  201. package/src/index.ts +69 -4
  202. package/src/managed-auth-session-sets.ts +371 -0
  203. package/src/managed-session.ts +520 -2
  204. package/src/model-catalog.ts +873 -0
  205. package/src/product-usage-metrics.ts +101 -0
  206. package/src/rigs/index.ts +179 -63
  207. package/src/rigs/provider-images.ts +2 -3
  208. package/src/sandbox/fleet.ts +471 -59
  209. package/src/sandbox/routing.ts +160 -33
  210. package/src/sandbox/runtime-settings.ts +281 -0
  211. package/src/session-authorization.ts +262 -78
  212. package/src/site-session-origin.ts +22 -0
  213. package/src/transcription.ts +13 -1
  214. package/src/turn-surface.ts +45 -0
  215. package/src/user-presence.ts +134 -0
  216. package/dist/chunk-6WKPWE5S.js.map +0 -1
  217. package/dist/chunk-IBOEYG6N.js +0 -34
  218. package/dist/chunk-IBOEYG6N.js.map +0 -1
  219. package/dist/chunk-JJU6I5XD.js.map +0 -1
  220. package/dist/chunk-NYPMQ7NO.js.map +0 -1
  221. package/dist/domain/durable-learning-slack-publication.d.ts +0 -72
  222. package/dist/domain/packs.d.ts +0 -55
  223. package/src/domain/durable-learning-slack-publication.ts +0 -202
  224. package/src/domain/packs.ts +0 -556
@@ -14,10 +14,18 @@ import {
14
14
  ResourceRefConflictError,
15
15
  ResourceMountPathError,
16
16
  stableJson,
17
+ type RepositoryResourceRef,
17
18
  type ResourceRef,
18
19
  type ToolRef,
20
+ type WorkspaceSessionToolDefaults,
19
21
  } from "@opengeni/contracts";
20
- import { areGitHubRepositoriesAllowedForWorkspace, requireFile, type Database } from "@opengeni/db";
22
+ import {
23
+ areGitHubRepositoriesAllowedForWorkspace,
24
+ requireFileForSubject,
25
+ withSessionRlsActorContext,
26
+ type SessionRlsActorContext,
27
+ type Database,
28
+ } from "@opengeni/db";
21
29
  import { HTTPException } from "hono/http-exception";
22
30
 
23
31
  export function validateToolRefs(tools: ToolRef[], settings: McpSettings): ToolRef[] {
@@ -36,17 +44,21 @@ export function validateToolRefs(tools: ToolRef[], settings: McpSettings): ToolR
36
44
  }
37
45
  throw new HTTPException(422, { message: `unknown MCP server id: ${tool.id}` });
38
46
  }
39
- // Tool refs are tri-state for pack portability across deployments:
47
+
40
48
  // - bare / optional:false is STRICT: the id must be configured here and
41
- // runtime connection failure fails the turn.
49
+ // runtime connection failure fails closed when preparation is demanded.
50
+ // Only an independent eager:true marker makes that a startup barrier.
42
51
  // - optional:true + known id is preserved: runtime treats it like an
43
52
  // auto-attached capability MCP and skips connect/list failures.
44
53
  // - optional:true + unknown id is skipped above: the client explicitly
45
54
  // opted into graceful degradation for MCPs (for example docs servers
46
55
  // like context7) that only some deployments configure.
47
- out.push(
48
- optional ? { kind: "mcp", id: tool.id, optional: true } : { kind: "mcp", id: tool.id },
49
- );
56
+ out.push({
57
+ kind: "mcp",
58
+ id: tool.id,
59
+ ...(optional ? { optional: true } : {}),
60
+ ...(tool.eager === true ? { eager: true } : {}),
61
+ });
50
62
  }
51
63
  return mergeToolRefs([], out);
52
64
  }
@@ -77,6 +89,38 @@ export function withDefaultEnabledCapabilityMcpTools(
77
89
  return mergeToolRefs(tools, enabledCapabilityMcpToolRefs(settings, runtimeSettings));
78
90
  }
79
91
 
92
+ /**
93
+ * Apply the workspace's exact new-session MCP defaults when configured.
94
+ * Stale or currently unavailable ids are optional and disappear from the
95
+ * executable selection without making every new session fail during a rolling
96
+ * connector change. An absent workspace override preserves the legacy
97
+ * deployment + enabled-capability default.
98
+ */
99
+ export function withWorkspaceDefaultMcpTools(
100
+ tools: ToolRef[],
101
+ settings: McpSettings,
102
+ runtimeSettings: McpSettings,
103
+ defaults: WorkspaceSessionToolDefaults | null,
104
+ ): ToolRef[] {
105
+ if (!defaults?.mcpServerIds) {
106
+ return withDefaultEnabledCapabilityMcpTools(tools, settings, runtimeSettings);
107
+ }
108
+ return mergeToolRefs(
109
+ tools,
110
+ validateToolRefs(
111
+ [
112
+ ...defaults.mcpServerIds,
113
+ ...(defaults.inheritConnectedMcpServers
114
+ ? runtimeSettings.mcpServers
115
+ .filter((server) => !["opengeni", "files", "docs"].includes(server.id))
116
+ .map((server) => server.id)
117
+ : []),
118
+ ].map((id) => ({ kind: "mcp" as const, id, optional: true as const })),
119
+ runtimeSettings,
120
+ ),
121
+ );
122
+ }
123
+
80
124
  /** Drop stored refs that are no longer present in the current runtime registry. */
81
125
  export function availableToolRefs(tools: ToolRef[], settings: McpSettings): ToolRef[] {
82
126
  const available = new Set(settings.mcpServers.map((server) => server.id));
@@ -161,6 +205,7 @@ export function normalizeResources(resources: ResourceRef[]): ResourceRef[] {
161
205
  mountPath,
162
206
  ...(resource.subpath ? { subpath: normalizeRepositorySubpath(resource.subpath) } : {}),
163
207
  ...(resource.provider ? { provider: resource.provider } : {}),
208
+ ...(resource.connectionType ? { connectionType: resource.connectionType } : {}),
164
209
  ...(resource.credentialBindingId
165
210
  ? { credentialBindingId: resource.credentialBindingId }
166
211
  : {}),
@@ -175,6 +220,7 @@ export function normalizeResources(resources: ResourceRef[]): ResourceRef[] {
175
220
  ? { githubInstallationId: resource.githubInstallationId }
176
221
  : {}),
177
222
  ...(resource.githubRepositoryId ? { githubRepositoryId: resource.githubRepositoryId } : {}),
223
+ ...(resource.optional === true ? { optional: true } : {}),
178
224
  };
179
225
  }
180
226
  const key = stableJson(normalized);
@@ -228,6 +274,97 @@ export function validateGitHubRepositorySelectionShapes(resources: ResourceRef[]
228
274
  return [...new Set(selected.map((item) => item.installationId))];
229
275
  }
230
276
 
277
+ export type PersonalGitHubRepositoryResource = RepositoryResourceRef & {
278
+ provider: "github";
279
+ connectionType: "github_personal";
280
+ credentialBindingId: string;
281
+ access: "read" | "write";
282
+ repositoryId: string;
283
+ };
284
+
285
+ const PERSONAL_GITHUB_BINDING_ID_PATTERN =
286
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
287
+
288
+ function isPersonalGitHubRepositoryCandidate(
289
+ resource: ResourceRef,
290
+ ): resource is RepositoryResourceRef & { provider: "github"; credentialBindingId: string } {
291
+ if (resource.kind !== "repository" || resource.connectionType !== "github_personal") {
292
+ return false;
293
+ }
294
+ return resource.provider === "github" && resource.credentialBindingId !== undefined;
295
+ }
296
+
297
+ /**
298
+ * Validate and return the dedicated personal-GitHub repository resource lane.
299
+ * A host-opaque binding is only a selector for the server-side authority
300
+ * snapshot; it never authorizes a repository on its own.
301
+ */
302
+ export function personalGitHubRepositoryResources(
303
+ resources: ResourceRef[],
304
+ ): PersonalGitHubRepositoryResource[] {
305
+ const selected: PersonalGitHubRepositoryResource[] = [];
306
+ for (const resource of resources) {
307
+ if (!isPersonalGitHubRepositoryCandidate(resource)) {
308
+ if (resource.kind === "repository" && resource.connectionType === "github_personal") {
309
+ throw new HTTPException(422, {
310
+ message: "personal GitHub repository resources require the dedicated GitHub provider",
311
+ });
312
+ }
313
+ continue;
314
+ }
315
+ if (
316
+ !PERSONAL_GITHUB_BINDING_ID_PATTERN.test(resource.credentialBindingId) ||
317
+ typeof resource.repositoryId !== "string" ||
318
+ !/^[1-9]\d*$/u.test(resource.repositoryId) ||
319
+ (resource.access !== "read" && resource.access !== "write") ||
320
+ resource.installationId !== undefined ||
321
+ resource.githubInstallationId !== undefined ||
322
+ resource.githubRepositoryId !== undefined ||
323
+ resource.connectionId !== undefined ||
324
+ resource.projectId !== undefined
325
+ ) {
326
+ throw new HTTPException(422, {
327
+ message:
328
+ "personal GitHub repository resources require one opaque binding, provider repository id, and explicit read or write access",
329
+ });
330
+ }
331
+ let uri: URL;
332
+ try {
333
+ uri = new URL(resource.uri);
334
+ } catch {
335
+ throw new HTTPException(422, { message: "personal GitHub repository URI is invalid" });
336
+ }
337
+ if (
338
+ uri.protocol !== "https:" ||
339
+ uri.hostname !== "github.com" ||
340
+ uri.port !== "" ||
341
+ uri.username !== "" ||
342
+ uri.password !== "" ||
343
+ uri.search !== "" ||
344
+ uri.hash !== "" ||
345
+ uri.pathname.endsWith(".git") ||
346
+ uri.pathname.split("/").filter(Boolean).length !== 2 ||
347
+ resource.uri !== `${uri.origin}${uri.pathname.replace(/\/$/u, "")}`
348
+ ) {
349
+ throw new HTTPException(422, {
350
+ message: "personal GitHub repository resources require a canonical GitHub HTTPS URI",
351
+ });
352
+ }
353
+ selected.push(resource as PersonalGitHubRepositoryResource);
354
+ }
355
+ const identities = new Set<string>();
356
+ for (const resource of selected) {
357
+ const key = `${resource.credentialBindingId}\0${resource.repositoryId}`;
358
+ if (identities.has(key)) {
359
+ throw new HTTPException(422, {
360
+ message: "personal GitHub repository resources must not contain duplicates",
361
+ });
362
+ }
363
+ identities.add(key);
364
+ }
365
+ return selected;
366
+ }
367
+
231
368
  /** @deprecated Use validateGitHubRepositorySelectionShapes for multi-installation sessions. */
232
369
  export function validateGitHubRepositorySelectionShape(resources: ResourceRef[]): number | null {
233
370
  const installationIds = validateGitHubRepositorySelectionShapes(resources);
@@ -246,6 +383,9 @@ function gitHubRepositorySelections(
246
383
  if (resource.kind !== "repository") {
247
384
  return [];
248
385
  }
386
+ if (isPersonalGitHubRepositoryCandidate(resource)) {
387
+ return [];
388
+ }
249
389
  const installationRaw =
250
390
  resource.githubInstallationId ??
251
391
  (resource.provider === "github" ? resource.installationId : undefined);
@@ -275,6 +415,7 @@ export async function validateGitHubRepositorySelection(
275
415
  workspaceId: string,
276
416
  resources: ResourceRef[],
277
417
  ): Promise<void> {
418
+ personalGitHubRepositoryResources(resources);
278
419
  const installationIds = validateGitHubRepositorySelectionShapes(resources);
279
420
  if (installationIds.length === 0) {
280
421
  return;
@@ -311,28 +452,44 @@ export function isAuthoritativeGitHubRepositorySelectionError(error: unknown): b
311
452
 
312
453
  export async function validateFileResources(
313
454
  db: Database,
455
+ accountId: string,
314
456
  workspaceId: string,
457
+ subjectId: string | null,
315
458
  resources: ResourceRef[],
459
+ privateFileContext?: SessionRlsActorContext,
316
460
  ): Promise<void> {
317
- const fileIds = new Set<string>();
318
- for (const resource of resources) {
319
- if (resource.kind !== "file") {
320
- continue;
321
- }
322
- if (fileIds.has(resource.fileId)) {
323
- throw new HTTPException(422, { message: `duplicate file resource: ${resource.fileId}` });
324
- }
325
- fileIds.add(resource.fileId);
326
- const file = await requireFile(db, workspaceId, resource.fileId).catch(() => null);
327
- if (!file) {
328
- throw new HTTPException(422, { message: `unknown file resource: ${resource.fileId}` });
329
- }
330
- if (file.status !== "ready") {
331
- throw new HTTPException(422, {
332
- message: `file resource ${resource.fileId} is ${file.status}`,
333
- });
334
- }
335
- }
461
+ return withSessionRlsActorContext(
462
+ privateFileContext ?? {
463
+ subjectId: subjectId ?? "service:file-resource-validation",
464
+ privateFileOwnerSubjectId: null,
465
+ },
466
+ async () => {
467
+ const fileIds = new Set<string>();
468
+ for (const resource of resources) {
469
+ if (resource.kind !== "file") {
470
+ continue;
471
+ }
472
+ if (fileIds.has(resource.fileId)) {
473
+ throw new HTTPException(422, { message: `duplicate file resource: ${resource.fileId}` });
474
+ }
475
+ fileIds.add(resource.fileId);
476
+ const file = await requireFileForSubject(db, {
477
+ accountId,
478
+ workspaceId,
479
+ subjectId: privateFileContext?.initiatingHumanSubjectId ?? subjectId,
480
+ fileId: resource.fileId,
481
+ }).catch(() => null);
482
+ if (!file) {
483
+ throw new HTTPException(422, { message: `unknown file resource: ${resource.fileId}` });
484
+ }
485
+ if (file.status !== "ready") {
486
+ throw new HTTPException(422, {
487
+ message: `file resource ${resource.fileId} is ${file.status}`,
488
+ });
489
+ }
490
+ }
491
+ },
492
+ );
336
493
  }
337
494
 
338
495
  function normalizeMountPath(path: string): string {