@opengeni/core 2.10.0-canary.0 → 2.10.0-canary.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 (50) hide show
  1. package/dist/application/external-workspace-members.d.ts +16 -0
  2. package/dist/application/host-mcp-resolvers.d.ts +13 -0
  3. package/dist/application/new-session-drafts.d.ts +4 -2
  4. package/dist/chunk-5WZYFL45.js +266 -0
  5. package/dist/chunk-5WZYFL45.js.map +1 -0
  6. package/dist/domain/file-owner.d.ts +8 -0
  7. package/dist/domain/knowledge-files.d.ts +20 -0
  8. package/dist/domain/knowledge-messages.d.ts +39 -0
  9. package/dist/domain/knowledge-messages.test.d.ts +1 -0
  10. package/dist/domain/knowledge-search.d.ts +80 -0
  11. package/dist/domain/knowledge-search.test.d.ts +1 -0
  12. package/dist/domain/knowledge.d.ts +9 -0
  13. package/dist/domain/pr-review.d.ts +2 -2
  14. package/dist/domain/resources.d.ts +2 -2
  15. package/dist/domain/scheduled-tasks.d.ts +12 -2
  16. package/dist/domain/sessions.d.ts +6 -2
  17. package/dist/domain/skills.d.ts +16 -0
  18. package/dist/index.d.ts +6 -4
  19. package/dist/index.js +3948 -3939
  20. package/dist/index.js.map +1 -1
  21. package/dist/remote-mcp-credentials.d.ts +16 -1
  22. package/dist/remote-mcp-credentials.js +7 -215
  23. package/dist/remote-mcp-credentials.js.map +1 -1
  24. package/package.json +12 -12
  25. package/src/application/external-workspace-members.ts +89 -0
  26. package/src/application/host-mcp-resolvers.ts +85 -0
  27. package/src/application/new-session-drafts.ts +37 -3
  28. package/src/domain/file-owner.ts +52 -0
  29. package/src/domain/host-mcp-task-admission.ts +27 -17
  30. package/src/domain/knowledge-files.ts +39 -0
  31. package/src/domain/knowledge-messages.test.ts +91 -0
  32. package/src/domain/knowledge-messages.ts +105 -0
  33. package/src/domain/knowledge-search.test.ts +45 -0
  34. package/src/domain/knowledge-search.ts +55 -0
  35. package/src/domain/knowledge.ts +133 -0
  36. package/src/domain/product-integration-skill.gen.ts +7 -7
  37. package/src/domain/resources.ts +36 -25
  38. package/src/domain/scheduled-tasks.ts +362 -139
  39. package/src/domain/sessions.ts +117 -20
  40. package/src/domain/skills.ts +8 -0
  41. package/src/index.ts +9 -4
  42. package/src/remote-mcp-credentials.ts +76 -8
  43. package/dist/domain/company-brain-governed-writes.d.ts +0 -79
  44. package/dist/domain/governed-learning-activation.d.ts +0 -16
  45. package/dist/domain/governed-learning-evaluator.d.ts +0 -6
  46. package/dist/domain/remember.d.ts +0 -72
  47. package/src/domain/company-brain-governed-writes.ts +0 -346
  48. package/src/domain/governed-learning-activation.ts +0 -44
  49. package/src/domain/governed-learning-evaluator.ts +0 -49
  50. package/src/domain/remember.ts +0 -577
@@ -4,3 +4,19 @@ import { type AccessDeps } from "../access/index.js";
4
4
  /** Explicit host onboarding. Ordinary asUser reads never call this operation.
5
5
  * Existing memberships are not overwritten, including reduced permissions. */
6
6
  export declare function addExternalWorkspaceMemberForRequest(c: Context, deps: AccessDeps, workspaceId: string, input: unknown): Promise<ExternalIdentity>;
7
+ export declare function lookupExternalIdentityForRequest(c: Context, deps: AccessDeps, organizationId: string, input: unknown): Promise<{
8
+ found: false;
9
+ } | {
10
+ found: true;
11
+ subjectId: string;
12
+ organizationMembershipId: string;
13
+ identityStatus: "active" | "disabled" | "revoked";
14
+ identityAuthorizationRevision: number;
15
+ membershipStatus: "active" | "provisioning" | "revoked" | "suspended";
16
+ membershipAuthorizationRevision: number;
17
+ }>;
18
+ export declare function cancelExternalWorkspaceMemberGrantForRequest(c: Context, deps: AccessDeps, organizationId: string, workspaceId: string, membershipId: string, input: unknown): Promise<{
19
+ removed: boolean;
20
+ replay: boolean;
21
+ fencedGrantOperationId: string;
22
+ }>;
@@ -0,0 +1,13 @@
1
+ import type { Context } from "hono";
2
+ import { type AccessDeps } from "../access/index.js";
3
+ export declare function hostMcpResolverForRequest(context: Context, deps: AccessDeps, organizationId: string, source: string, method: "get" | "put" | "revoke", raw?: unknown): Promise<{
4
+ id: string;
5
+ organizationId: string;
6
+ externalSource: string;
7
+ url: string;
8
+ timeoutMs: number;
9
+ generation: number;
10
+ status: "active" | "revoked";
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ }>;
@@ -3,7 +3,7 @@ import type { AppDependencies } from "../dependencies.js";
3
3
  import { type AccessGrantAuthorization } from "../access/index.js";
4
4
  type NewSessionDraftDependencies = Pick<AppDependencies, "settings" | "db" | "objectStorage">;
5
5
  /** Read the authenticated actor's server-authoritative pre-session composer state. */
6
- export declare function getActorNewSessionDraft(deps: Pick<NewSessionDraftDependencies, "settings" | "db">, grant: AccessGrant, workspaceId: string): Promise<NewSessionDraftValue>;
6
+ declare function getActorNewSessionDraftInFileScope(deps: Pick<NewSessionDraftDependencies, "settings" | "db">, grant: AccessGrant, workspaceId: string): Promise<NewSessionDraftValue>;
7
7
  /**
8
8
  * Validate and save one exact actor-private draft revision. Create-time-only
9
9
  * checks (live machine target, rig/variable-set state, and permission
@@ -11,7 +11,7 @@ export declare function getActorNewSessionDraft(deps: Pick<NewSessionDraftDepend
11
11
  * draft may represent incomplete options, while no invalid option can become a
12
12
  * session without passing that single canonical create boundary.
13
13
  */
14
- export declare function saveActorNewSessionDraft(deps: NewSessionDraftDependencies, grant: AccessGrant, workspaceId: string, rawInput: unknown,
14
+ declare function saveActorNewSessionDraftInFileScope(deps: NewSessionDraftDependencies, grant: AccessGrant, workspaceId: string, rawInput: unknown,
15
15
  /**
16
16
  * `AccessGrantAuthorization.canonicalManagedHumanSession` — did this request
17
17
  * authenticate as the canonical managed cookie that owns `grant.subjectId`?
@@ -19,4 +19,6 @@ export declare function saveActorNewSessionDraft(deps: NewSessionDraftDependenci
19
19
  * the historical bare-membership fence.
20
20
  */
21
21
  canonicalManagedHumanSession?: boolean, externalAuthorization?: AccessGrantAuthorization): Promise<NewSessionDraftValue>;
22
+ export declare function getActorNewSessionDraft(deps: Parameters<typeof getActorNewSessionDraftInFileScope>[0], grant: AccessGrant, workspaceId: string, authorization?: AccessGrantAuthorization): Promise<NewSessionDraftValue>;
23
+ export declare function saveActorNewSessionDraft(...args: Parameters<typeof saveActorNewSessionDraftInFileScope>): Promise<NewSessionDraftValue>;
22
24
  export {};
@@ -0,0 +1,266 @@
1
+ // src/remote-mcp-credentials.ts
2
+ import { environmentsEncryptionKeyBytes } from "@opengeni/config";
3
+ import {
4
+ resolveHostMcpResolverRoute,
5
+ hostMcpResolverRouteIsCurrent
6
+ } from "@opengeni/db";
7
+ import {
8
+ McpConnectionResourceScope,
9
+ hostMcpCredentialUseGuard
10
+ } from "@opengeni/contracts";
11
+ import { pinnedFetch, readResponseJsonBounded, validateHttpUrl } from "@opengeni/network";
12
+ import { z } from "zod";
13
+ var configuration = z.array(
14
+ z.object({
15
+ accountId: z.string().uuid(),
16
+ url: z.string().max(2048),
17
+ bearerToken: z.string().min(1).max(8192).regex(/^[^\r\n]+$/),
18
+ timeoutMs: z.number().int().min(100).max(3e4).default(1e4)
19
+ }).strict()
20
+ ).max(128);
21
+ var scope = {
22
+ accountId: z.string(),
23
+ workspaceId: z.string(),
24
+ sessionId: z.string(),
25
+ providerDomain: z.string(),
26
+ provider: z.string().optional(),
27
+ scopes: z.array(z.string()).max(256).optional(),
28
+ resource: z.string().optional(),
29
+ selectedResources: z.array(McpConnectionResourceScope).max(256).optional()
30
+ };
31
+ var resolution = z.discriminatedUnion("status", [
32
+ z.object({
33
+ ...scope,
34
+ status: z.literal("ok"),
35
+ connectionId: z.string().min(1),
36
+ headers: z.record(z.string(), z.string()),
37
+ placements: z.array(
38
+ z.object({
39
+ carrier: z.enum(["header", "query", "cookie"]),
40
+ name: z.string(),
41
+ value: z.string(),
42
+ prefix: z.string().optional()
43
+ }).strict()
44
+ ).max(64).optional(),
45
+ expiresAt: z.string().datetime({ offset: true })
46
+ }).strict(),
47
+ z.object({
48
+ ...scope,
49
+ status: z.literal("auth_needed"),
50
+ connectionId: z.string().optional(),
51
+ reason: z.enum([
52
+ "missing_connection",
53
+ "expired",
54
+ "insufficient_scope",
55
+ "refresh_failed",
56
+ "personal_authority_unavailable",
57
+ "unsupported_auth",
58
+ "resource_scope_unavailable"
59
+ ]),
60
+ authorizationUrl: z.string().optional()
61
+ }).strict()
62
+ ]);
63
+ var gatewayResolution = z.discriminatedUnion("status", [
64
+ resolution.options[0].omit({ sessionId: true }).extend({ requestId: z.string().uuid() }),
65
+ resolution.options[1].omit({ sessionId: true }).extend({ requestId: z.string().uuid() })
66
+ ]);
67
+ var responseEnvelope = z.object({
68
+ version: z.literal(1),
69
+ requestId: z.string().uuid(),
70
+ destinationUrl: z.string(),
71
+ resolution: z.union([resolution, gatewayResolution])
72
+ }).strict();
73
+ function normalizeResolution(value) {
74
+ const common = {
75
+ accountId: value.accountId,
76
+ workspaceId: value.workspaceId,
77
+ ..."sessionId" in value ? { sessionId: value.sessionId } : { requestId: value.requestId },
78
+ providerDomain: value.providerDomain,
79
+ ...value.provider !== void 0 ? { provider: value.provider } : {},
80
+ ...value.scopes !== void 0 ? { scopes: value.scopes } : {},
81
+ ...value.resource !== void 0 ? { resource: value.resource } : {},
82
+ ...value.selectedResources !== void 0 ? { selectedResources: value.selectedResources } : {}
83
+ };
84
+ if (value.status === "auth_needed")
85
+ return {
86
+ ...common,
87
+ status: "auth_needed",
88
+ reason: value.reason,
89
+ ...value.connectionId !== void 0 ? { connectionId: value.connectionId } : {},
90
+ ...value.authorizationUrl !== void 0 ? { authorizationUrl: value.authorizationUrl } : {}
91
+ };
92
+ return {
93
+ ...common,
94
+ status: "ok",
95
+ connectionId: value.connectionId,
96
+ headers: value.headers,
97
+ expiresAt: value.expiresAt,
98
+ ...value.placements !== void 0 ? {
99
+ placements: value.placements.map((placement) => ({
100
+ carrier: placement.carrier,
101
+ name: placement.name,
102
+ value: placement.value,
103
+ ...placement.prefix !== void 0 ? { prefix: placement.prefix } : {}
104
+ }))
105
+ } : {}
106
+ };
107
+ }
108
+ function createRemoteMcpCredentialsPort(settings, transport = pinnedFetch, routes) {
109
+ if (!settings.hostMcpCredentialResolversJson && !routes) return {};
110
+ let entries;
111
+ try {
112
+ entries = configuration.parse(JSON.parse(settings.hostMcpCredentialResolversJson || "[]"));
113
+ for (const entry of entries) validateHttpUrl(entry.url);
114
+ if (new Set(entries.map((entry) => entry.accountId)).size !== entries.length) throw new Error();
115
+ } catch {
116
+ throw new Error("Invalid host MCP credential resolver configuration");
117
+ }
118
+ const byAccount = new Map(entries.map((entry) => [entry.accountId, entry]));
119
+ const active = /* @__PURE__ */ new Map();
120
+ let physicalRequests = 0;
121
+ const resolveRemote = async (input) => {
122
+ const serialized = JSON.stringify(input);
123
+ const request = JSON.parse(serialized);
124
+ const unavailable = (reason) => ({
125
+ status: "auth_needed",
126
+ accountId: request.accountId,
127
+ workspaceId: request.workspaceId,
128
+ ..."sessionId" in request ? { sessionId: request.sessionId } : { requestId: request.requestId },
129
+ providerDomain: request.connectionRef.providerDomain,
130
+ ...request.connectionRef.provider !== void 0 ? { provider: request.connectionRef.provider } : {},
131
+ ...request.connectionRef.connectionId !== void 0 ? { connectionId: request.connectionRef.connectionId } : {},
132
+ ...request.connectionRef.scopes !== void 0 ? { scopes: request.connectionRef.scopes } : {},
133
+ ...request.connectionRef.resource !== void 0 ? { resource: request.connectionRef.resource } : {},
134
+ ...request.connectionRef.selectedResources !== void 0 ? { selectedResources: request.connectionRef.selectedResources } : {},
135
+ reason
136
+ });
137
+ let route = { mode: "legacy" };
138
+ try {
139
+ if (routes) route = await routes.resolve(request);
140
+ } catch {
141
+ return unavailable("refresh_failed");
142
+ }
143
+ if (route.mode === "denied") return unavailable("unsupported_auth");
144
+ const config = route.mode === "namespace" ? route : byAccount.get(request.accountId);
145
+ if (!config || request.connectionRef.authoritySource !== "host")
146
+ return unavailable("unsupported_auth");
147
+ const current = async () => {
148
+ try {
149
+ return routes ? await routes.isCurrent(request, route) : true;
150
+ } catch {
151
+ return false;
152
+ }
153
+ };
154
+ const finish = async (value) => {
155
+ if (!await current()) return unavailable("refresh_failed");
156
+ const result = structuredClone(value);
157
+ if (result.status === "ok" && routes) result[hostMcpCredentialUseGuard] = current;
158
+ return result;
159
+ };
160
+ if (new TextEncoder().encode(serialized).byteLength > 65536)
161
+ return unavailable("refresh_failed");
162
+ const activeKey = JSON.stringify([
163
+ route.mode === "namespace" ? [route.id, route.generation] : "legacy",
164
+ serialized
165
+ ]);
166
+ const pending = active.get(activeKey);
167
+ if (pending) return finish(await pending);
168
+ if (physicalRequests >= 128) return unavailable("refresh_failed");
169
+ const run = async () => {
170
+ const requestId = crypto.randomUUID();
171
+ const controller = new AbortController();
172
+ let timer;
173
+ const deadline = new Promise((_, reject) => {
174
+ timer = setTimeout(() => {
175
+ controller.abort();
176
+ reject(new Error("Host resolver deadline"));
177
+ }, config.timeoutMs);
178
+ });
179
+ try {
180
+ physicalRequests++;
181
+ return await Promise.race([
182
+ deadline,
183
+ (async () => {
184
+ if (!await current()) return unavailable("refresh_failed");
185
+ const response = await transport(
186
+ config.url,
187
+ {
188
+ method: "POST",
189
+ redirect: "manual",
190
+ signal: controller.signal,
191
+ headers: {
192
+ Authorization: `Bearer ${config.bearerToken}`,
193
+ "Content-Type": "application/json"
194
+ },
195
+ body: JSON.stringify({ version: 1, requestId, request })
196
+ },
197
+ settings,
198
+ { requireHttpsOutsideLocalTest: true, label: "Host MCP credential resolver" }
199
+ );
200
+ if (!response.ok) {
201
+ await response.body?.cancel();
202
+ return unavailable("refresh_failed");
203
+ }
204
+ const parsed = responseEnvelope.parse(
205
+ await readResponseJsonBounded(response, 65536, "Host MCP credential resolver", {
206
+ signal: controller.signal
207
+ })
208
+ );
209
+ if (parsed.requestId !== requestId || parsed.destinationUrl !== request.destinationUrl || parsed.resolution.accountId !== request.accountId || parsed.resolution.workspaceId !== request.workspaceId || ("sessionId" in request ? !("sessionId" in parsed.resolution) || parsed.resolution.sessionId !== request.sessionId : !("requestId" in parsed.resolution) || parsed.resolution.requestId !== request.requestId))
210
+ return unavailable("refresh_failed");
211
+ if (parsed.resolution.status === "ok" && (Date.parse(parsed.resolution.expiresAt) <= Date.now() + 5e3 || Date.parse(parsed.resolution.expiresAt) > Date.now() + 9e5)) {
212
+ return unavailable("refresh_failed");
213
+ }
214
+ return normalizeResolution(parsed.resolution);
215
+ })().finally(() => {
216
+ physicalRequests--;
217
+ })
218
+ ]);
219
+ } catch {
220
+ return unavailable("refresh_failed");
221
+ } finally {
222
+ clearTimeout(timer);
223
+ }
224
+ };
225
+ const task = run();
226
+ active.set(activeKey, task);
227
+ try {
228
+ return finish(await task);
229
+ } finally {
230
+ if (active.get(activeKey) === task) active.delete(activeKey);
231
+ }
232
+ };
233
+ return {
234
+ mcpAuthoritySource: "host",
235
+ async mcpCredentials(input) {
236
+ const result = await resolveRemote(input);
237
+ if (!("sessionId" in result)) throw new Error("Invalid host turn credential scope");
238
+ return result;
239
+ },
240
+ async mcpGatewayCredentials(input) {
241
+ const result = await resolveRemote(input);
242
+ if (!("requestId" in result)) throw new Error("Invalid host gateway credential scope");
243
+ return result;
244
+ }
245
+ };
246
+ }
247
+ function createNativeRemoteMcpCredentialsPort(settings, db, transport = pinnedFetch) {
248
+ return createRemoteMcpCredentialsPort(settings, transport, {
249
+ resolve: (request) => resolveHostMcpResolverRoute(db, request, environmentsEncryptionKeyBytes(settings)),
250
+ isCurrent: (request, route) => hostMcpResolverRouteIsCurrent(db, request, route)
251
+ });
252
+ }
253
+ function hasLegacyHostMcpResolver(settings, accountId) {
254
+ try {
255
+ return configuration.parse(JSON.parse(settings.hostMcpCredentialResolversJson || "[]")).some((entry) => entry.accountId === accountId);
256
+ } catch {
257
+ throw new Error("Invalid host MCP credential resolver configuration");
258
+ }
259
+ }
260
+
261
+ export {
262
+ createRemoteMcpCredentialsPort,
263
+ createNativeRemoteMcpCredentialsPort,
264
+ hasLegacyHostMcpResolver
265
+ };
266
+ //# sourceMappingURL=chunk-5WZYFL45.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/remote-mcp-credentials.ts"],"sourcesContent":["import type { Settings } from \"@opengeni/config\";\nimport { environmentsEncryptionKeyBytes } from \"@opengeni/config\";\nimport {\n resolveHostMcpResolverRoute,\n hostMcpResolverRouteIsCurrent,\n type Database,\n type HostMcpResolverRoute,\n} from \"@opengeni/db\";\nimport {\n McpConnectionResourceScope,\n hostMcpCredentialUseGuard,\n type ConnectionCredentialsPort,\n type McpCredentialsRequest,\n type McpCredentialResolution,\n type McpGatewayCredentialsRequest,\n type McpGatewayCredentialResolution,\n} from \"@opengeni/contracts\";\nimport { pinnedFetch, readResponseJsonBounded, validateHttpUrl } from \"@opengeni/network\";\nimport { z } from \"zod\";\n\nconst configuration = z\n .array(\n z\n .object({\n accountId: z.string().uuid(),\n url: z.string().max(2048),\n bearerToken: z\n .string()\n .min(1)\n .max(8192)\n .regex(/^[^\\r\\n]+$/),\n timeoutMs: z.number().int().min(100).max(30_000).default(10_000),\n })\n .strict(),\n )\n .max(128);\n\nconst scope = {\n accountId: z.string(),\n workspaceId: z.string(),\n sessionId: z.string(),\n providerDomain: z.string(),\n provider: z.string().optional(),\n scopes: z.array(z.string()).max(256).optional(),\n resource: z.string().optional(),\n selectedResources: z.array(McpConnectionResourceScope).max(256).optional(),\n};\nconst resolution = z.discriminatedUnion(\"status\", [\n z\n .object({\n ...scope,\n status: z.literal(\"ok\"),\n connectionId: z.string().min(1),\n headers: z.record(z.string(), z.string()),\n placements: z\n .array(\n z\n .object({\n carrier: z.enum([\"header\", \"query\", \"cookie\"]),\n name: z.string(),\n value: z.string(),\n prefix: z.string().optional(),\n })\n .strict(),\n )\n .max(64)\n .optional(),\n expiresAt: z.string().datetime({ offset: true }),\n })\n .strict(),\n z\n .object({\n ...scope,\n status: z.literal(\"auth_needed\"),\n connectionId: z.string().optional(),\n reason: z.enum([\n \"missing_connection\",\n \"expired\",\n \"insufficient_scope\",\n \"refresh_failed\",\n \"personal_authority_unavailable\",\n \"unsupported_auth\",\n \"resource_scope_unavailable\",\n ]),\n authorizationUrl: z.string().optional(),\n })\n .strict(),\n]);\nconst gatewayResolution = z.discriminatedUnion(\"status\", [\n resolution.options[0].omit({ sessionId: true }).extend({ requestId: z.string().uuid() }),\n resolution.options[1].omit({ sessionId: true }).extend({ requestId: z.string().uuid() }),\n]);\nconst responseEnvelope = z\n .object({\n version: z.literal(1),\n requestId: z.string().uuid(),\n destinationUrl: z.string(),\n resolution: z.union([resolution, gatewayResolution]),\n })\n .strict();\n\ntype RemoteResolution = McpCredentialResolution | McpGatewayCredentialResolution;\nfunction normalizeResolution(\n value: z.infer<typeof resolution> | z.infer<typeof gatewayResolution>,\n): RemoteResolution {\n const common = {\n accountId: value.accountId,\n workspaceId: value.workspaceId,\n ...(\"sessionId\" in value ? { sessionId: value.sessionId } : { requestId: value.requestId }),\n providerDomain: value.providerDomain,\n ...(value.provider !== undefined ? { provider: value.provider } : {}),\n ...(value.scopes !== undefined ? { scopes: value.scopes } : {}),\n ...(value.resource !== undefined ? { resource: value.resource } : {}),\n ...(value.selectedResources !== undefined\n ? { selectedResources: value.selectedResources }\n : {}),\n };\n if (value.status === \"auth_needed\")\n return {\n ...common,\n status: \"auth_needed\",\n reason: value.reason,\n ...(value.connectionId !== undefined ? { connectionId: value.connectionId } : {}),\n ...(value.authorizationUrl !== undefined ? { authorizationUrl: value.authorizationUrl } : {}),\n };\n return {\n ...common,\n status: \"ok\",\n connectionId: value.connectionId,\n headers: value.headers,\n expiresAt: value.expiresAt,\n ...(value.placements !== undefined\n ? {\n placements: value.placements.map((placement) => ({\n carrier: placement.carrier,\n name: placement.name,\n value: placement.value,\n ...(placement.prefix !== undefined ? { prefix: placement.prefix } : {}),\n })),\n }\n : {}),\n };\n}\n\n/** Optional standalone transport for the existing request-time host port.\n * No successful credential is cached or persisted. The host must authorize\n * every immutable request context, including revocation and binding generation.\n */\nexport function createRemoteMcpCredentialsPort(\n settings: Pick<\n Settings,\n \"hostMcpCredentialResolversJson\" | \"environment\" | \"integrationsAllowPrivateNetworkTargets\"\n >,\n transport: typeof pinnedFetch = pinnedFetch,\n routes?: {\n resolve: (input: { accountId: string; workspaceId: string }) => Promise<HostMcpResolverRoute>;\n isCurrent: (\n input: { accountId: string; workspaceId: string },\n route: HostMcpResolverRoute,\n ) => Promise<boolean>;\n },\n): ConnectionCredentialsPort {\n if (!settings.hostMcpCredentialResolversJson && !routes) return {};\n let entries: z.infer<typeof configuration>;\n try {\n entries = configuration.parse(JSON.parse(settings.hostMcpCredentialResolversJson || \"[]\"));\n for (const entry of entries) validateHttpUrl(entry.url);\n if (new Set(entries.map((entry) => entry.accountId)).size !== entries.length) throw new Error();\n } catch {\n // Configuration includes credentials: never return parser input or causes.\n throw new Error(\"Invalid host MCP credential resolver configuration\");\n }\n const byAccount = new Map(entries.map((entry) => [entry.accountId, entry]));\n const active = new Map<string, Promise<RemoteResolution>>();\n let physicalRequests = 0;\n const resolveRemote = async (\n input: McpCredentialsRequest | McpGatewayCredentialsRequest,\n ): Promise<RemoteResolution> => {\n const serialized = JSON.stringify(input);\n const request: McpCredentialsRequest | McpGatewayCredentialsRequest = JSON.parse(serialized);\n const unavailable = (reason: \"unsupported_auth\" | \"refresh_failed\"): RemoteResolution => ({\n status: \"auth_needed\",\n accountId: request.accountId,\n workspaceId: request.workspaceId,\n ...(\"sessionId\" in request\n ? { sessionId: request.sessionId }\n : { requestId: request.requestId }),\n providerDomain: request.connectionRef.providerDomain,\n ...(request.connectionRef.provider !== undefined\n ? { provider: request.connectionRef.provider }\n : {}),\n ...(request.connectionRef.connectionId !== undefined\n ? { connectionId: request.connectionRef.connectionId }\n : {}),\n ...(request.connectionRef.scopes !== undefined\n ? { scopes: request.connectionRef.scopes }\n : {}),\n ...(request.connectionRef.resource !== undefined\n ? { resource: request.connectionRef.resource }\n : {}),\n ...(request.connectionRef.selectedResources !== undefined\n ? { selectedResources: request.connectionRef.selectedResources }\n : {}),\n reason,\n });\n let route: HostMcpResolverRoute = { mode: \"legacy\" };\n try {\n if (routes) route = await routes.resolve(request);\n } catch {\n return unavailable(\"refresh_failed\");\n }\n if (route.mode === \"denied\") return unavailable(\"unsupported_auth\");\n const config = route.mode === \"namespace\" ? route : byAccount.get(request.accountId);\n if (!config || request.connectionRef.authoritySource !== \"host\")\n return unavailable(\"unsupported_auth\");\n const current = async () => {\n try {\n return routes ? await routes.isCurrent(request, route) : true;\n } catch {\n return false;\n }\n };\n const finish = async (value: RemoteResolution): Promise<RemoteResolution> => {\n if (!(await current())) return unavailable(\"refresh_failed\");\n const result = structuredClone(value);\n if (result.status === \"ok\" && routes) result[hostMcpCredentialUseGuard] = current;\n return result;\n };\n // Snapshot before any asynchronous operation; never retain mutable caller\n // objects as the authority for a delayed response.\n if (new TextEncoder().encode(serialized).byteLength > 65_536)\n return unavailable(\"refresh_failed\");\n const activeKey = JSON.stringify([\n route.mode === \"namespace\" ? [route.id, route.generation] : \"legacy\",\n serialized,\n ]);\n const pending = active.get(activeKey);\n if (pending) return finish(await pending);\n if (physicalRequests >= 128) return unavailable(\"refresh_failed\");\n const run = async (): Promise<RemoteResolution> => {\n const requestId = crypto.randomUUID();\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const deadline = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n controller.abort();\n reject(new Error(\"Host resolver deadline\"));\n }, config.timeoutMs);\n });\n try {\n physicalRequests++;\n return await Promise.race([\n deadline,\n (async () => {\n if (!(await current())) return unavailable(\"refresh_failed\");\n const response = await transport(\n config.url,\n {\n method: \"POST\",\n redirect: \"manual\",\n signal: controller.signal,\n headers: {\n Authorization: `Bearer ${config.bearerToken}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({ version: 1, requestId, request }),\n },\n settings,\n { requireHttpsOutsideLocalTest: true, label: \"Host MCP credential resolver\" },\n );\n if (!response.ok) {\n await response.body?.cancel();\n return unavailable(\"refresh_failed\");\n }\n const parsed = responseEnvelope.parse(\n await readResponseJsonBounded(response, 65_536, \"Host MCP credential resolver\", {\n signal: controller.signal,\n }),\n );\n if (\n parsed.requestId !== requestId ||\n parsed.destinationUrl !== request.destinationUrl ||\n parsed.resolution.accountId !== request.accountId ||\n parsed.resolution.workspaceId !== request.workspaceId ||\n (\"sessionId\" in request\n ? !(\"sessionId\" in parsed.resolution) ||\n parsed.resolution.sessionId !== request.sessionId\n : !(\"requestId\" in parsed.resolution) ||\n parsed.resolution.requestId !== request.requestId)\n )\n return unavailable(\"refresh_failed\");\n if (\n parsed.resolution.status === \"ok\" &&\n (Date.parse(parsed.resolution.expiresAt) <= Date.now() + 5_000 ||\n Date.parse(parsed.resolution.expiresAt) > Date.now() + 900_000)\n ) {\n return unavailable(\"refresh_failed\");\n }\n // Existing buildHostConnectionTokenResolver validates the precise\n // connection, provider, scopes, resources and credential placements.\n return normalizeResolution(parsed.resolution);\n })().finally(() => {\n physicalRequests--;\n }),\n ]);\n } catch {\n return unavailable(\"refresh_failed\");\n } finally {\n clearTimeout(timer);\n }\n };\n const task = run();\n active.set(activeKey, task);\n try {\n return finish(await task);\n } finally {\n if (active.get(activeKey) === task) active.delete(activeKey);\n }\n };\n return {\n mcpAuthoritySource: \"host\",\n async mcpCredentials(input) {\n const result = await resolveRemote(input);\n if (!(\"sessionId\" in result)) throw new Error(\"Invalid host turn credential scope\");\n return result;\n },\n async mcpGatewayCredentials(input) {\n const result = await resolveRemote(input);\n if (!(\"requestId\" in result)) throw new Error(\"Invalid host gateway credential scope\");\n return result;\n },\n };\n}\n\n/** Native standalone transport; the database remains authoritative on every\n * resolution/use. Embedded in-process ports retain their existing precedence. */\nexport function createNativeRemoteMcpCredentialsPort(\n settings: Settings,\n db: Database,\n transport: typeof pinnedFetch = pinnedFetch,\n): ConnectionCredentialsPort {\n return createRemoteMcpCredentialsPort(settings, transport, {\n resolve: (request) =>\n resolveHostMcpResolverRoute(db, request, environmentsEncryptionKeyBytes(settings)),\n isCurrent: (request, route) => hostMcpResolverRouteIsCurrent(db, request, route),\n });\n}\n\n/** Parses only server configuration; never return parser errors containing secrets. */\nexport function hasLegacyHostMcpResolver(\n settings: Pick<Settings, \"hostMcpCredentialResolversJson\">,\n accountId: string,\n): boolean {\n try {\n return configuration\n .parse(JSON.parse(settings.hostMcpCredentialResolversJson || \"[]\"))\n .some((entry) => entry.accountId === accountId);\n } catch {\n throw new Error(\"Invalid host MCP credential resolver configuration\");\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import { type SessionRlsActorContext } from "@opengeni/db";
2
+ import type { AccessGrant, Permission } from "@opengeni/contracts";
3
+ import { type AccessGrantAuthorization } from "../access/index.js";
4
+ import type { ApiRouteDeps } from "../dependencies.js";
5
+ /** Personal original-file access follows verified ownership, never a subject-shaped bearer. */
6
+ export declare function fileOwnerContextForAccess(deps: Pick<ApiRouteDeps, "db">, access: AccessGrantAuthorization, permission: Permission): Promise<SessionRlsActorContext>;
7
+ /** Internal MCP/core callers can prove an agent attempt without inventing a human authorization. */
8
+ export declare function fileOwnerContextForAgent(deps: Pick<ApiRouteDeps, "db">, grant: AccessGrant, permission: Permission): Promise<SessionRlsActorContext>;
@@ -0,0 +1,20 @@
1
+ import { type KnowledgeContext } from "@opengeni/db";
2
+ import type { ApiRouteDeps } from "../dependencies.js";
3
+ /** Existing original -> one source revision, through the ordinary task policy. */
4
+ export declare function prepareKnowledgeFile(deps: Pick<ApiRouteDeps, "db" | "objectStorage" | "getDocumentServices">, context: KnowledgeContext, fileId: string): Promise<{
5
+ status: "retained";
6
+ fileId: string;
7
+ filename: string;
8
+ receipt: {
9
+ operationId: string;
10
+ entryId: string;
11
+ revisionId: string;
12
+ version: number;
13
+ outcome: "archived" | "pending" | "published" | "rejected";
14
+ reviewBatchId: string | null;
15
+ replayed: boolean;
16
+ };
17
+ } | {
18
+ status: "disabled";
19
+ fileId: string;
20
+ }>;
@@ -0,0 +1,39 @@
1
+ import { type Database, type KnowledgeContext } from "@opengeni/db";
2
+ /** Retain actual message bytes, never a model-authored reconstruction of a confirmation. */
3
+ export declare function retainKnowledgeMessage(db: Database, context: KnowledgeContext, messageId?: string): Promise<{
4
+ retained: boolean;
5
+ reason: string;
6
+ entryId?: never;
7
+ revisionId?: never;
8
+ outcome?: never;
9
+ messageId?: never;
10
+ reused?: never;
11
+ } | {
12
+ retained: boolean;
13
+ reason: string;
14
+ entryId: string;
15
+ revisionId?: never;
16
+ outcome?: never;
17
+ messageId?: never;
18
+ reused?: never;
19
+ } | {
20
+ reason?: never;
21
+ retained: boolean;
22
+ entryId: string;
23
+ revisionId: string;
24
+ outcome: "pending" | "published" | "superseded";
25
+ messageId: string;
26
+ reused: boolean;
27
+ } | {
28
+ operationId: string;
29
+ entryId: string;
30
+ revisionId: string;
31
+ version: number;
32
+ outcome: "archived" | "pending" | "published" | "rejected";
33
+ reviewBatchId: string | null;
34
+ replayed: boolean;
35
+ reason?: never;
36
+ reused?: never;
37
+ retained: boolean;
38
+ messageId: string;
39
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import { KnowledgeEntryListRequest } from "@opengeni/contracts";
2
+ import { type Database, type KnowledgeContext } from "@opengeni/db";
3
+ import type { DocumentEmbedder } from "@opengeni/documents";
4
+ import type { z } from "zod";
5
+ /** Shared search path for HTTP and both first-party retrieval servers. */
6
+ export declare function searchKnowledgeEntries(db: Database, context: KnowledgeContext, input: z.input<typeof KnowledgeEntryListRequest>, embedder: () => DocumentEmbedder): Promise<{
7
+ entries: {
8
+ id: string;
9
+ scope: "organization" | "personal" | "workspace";
10
+ version: number;
11
+ publishedRevisionId: string | null;
12
+ latestRevisionId: string;
13
+ archived: boolean;
14
+ createdAt: string;
15
+ updatedAt: string;
16
+ score?: number | undefined;
17
+ excerpts: {
18
+ field: "content" | "title";
19
+ start: number;
20
+ end: number;
21
+ text: string;
22
+ }[];
23
+ revision: {
24
+ id: string;
25
+ entryId: string;
26
+ number: number;
27
+ change: "archive" | "upsert";
28
+ previousRevisionId: string | null;
29
+ restoredFromRevisionId: string | null;
30
+ createdAt: string;
31
+ createdBySessionId: string | null;
32
+ reviewBatchId: string | null;
33
+ outcome: "pending" | "published" | "rejected" | "superseded";
34
+ title: string;
35
+ kind: "decision" | "fact" | "group" | "incident" | "note" | "requirement" | "source";
36
+ preview: string;
37
+ groupIds: string[];
38
+ sourceKind: "connector" | "conversation" | "file" | "manual" | "repository" | "slack" | "task_note" | "web" | null;
39
+ };
40
+ }[];
41
+ nextCursor: string | null;
42
+ searchMode: "keyword";
43
+ } | {
44
+ entries: {
45
+ id: string;
46
+ scope: "organization" | "personal" | "workspace";
47
+ version: number;
48
+ publishedRevisionId: string | null;
49
+ latestRevisionId: string;
50
+ archived: boolean;
51
+ createdAt: string;
52
+ updatedAt: string;
53
+ score?: number | undefined;
54
+ excerpts: {
55
+ field: "content" | "title";
56
+ start: number;
57
+ end: number;
58
+ text: string;
59
+ }[];
60
+ revision: {
61
+ id: string;
62
+ entryId: string;
63
+ number: number;
64
+ change: "archive" | "upsert";
65
+ previousRevisionId: string | null;
66
+ restoredFromRevisionId: string | null;
67
+ createdAt: string;
68
+ createdBySessionId: string | null;
69
+ reviewBatchId: string | null;
70
+ outcome: "pending" | "published" | "rejected" | "superseded";
71
+ title: string;
72
+ kind: "decision" | "fact" | "group" | "incident" | "note" | "requirement" | "source";
73
+ preview: string;
74
+ groupIds: string[];
75
+ sourceKind: "connector" | "conversation" | "file" | "manual" | "repository" | "slack" | "task_note" | "web" | null;
76
+ };
77
+ }[];
78
+ nextCursor: string | null;
79
+ searchMode: "hybrid" | "vector";
80
+ }>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { AccessGrant, Permission } from "@opengeni/contracts";
2
+ import type { KnowledgeContext } from "@opengeni/db";
3
+ import { type AccessGrantAuthorization } from "../access/index.js";
4
+ import type { ApiRouteDeps } from "../dependencies.js";
5
+ /** A delegated MCP gateway can retrieve shared Knowledge. Its subject label
6
+ * does not establish personal ownership or human review authority. */
7
+ export declare function knowledgeContextForGateway(deps: Pick<ApiRouteDeps, "db">, grant: AccessGrant): Promise<KnowledgeContext>;
8
+ /** One host boundary for HTTP, SDK-through-HTTP and first-party Knowledge tools. */
9
+ export declare function knowledgeContextForAccess(deps: Pick<ApiRouteDeps, "db">, access: AccessGrantAuthorization, permission: Permission): Promise<KnowledgeContext>;
@@ -42,7 +42,7 @@ export declare const prReviewAutomationAdapter: {
42
42
  }) => {
43
43
  initialMessage: string;
44
44
  sessionTemplate: {
45
- bundledSkillIds?: ("builtin:opengeni-documents" | "builtin:opengeni-presentations" | "builtin:opengeni-projects" | "builtin:opengeni-sites" | "builtin:opengeni-skills" | "builtin:opengeni-spreadsheets" | "builtin:opengeni-video-generation")[] | undefined;
45
+ bundledSkillIds?: ("builtin:document-parsing" | "builtin:opengeni-documents" | "builtin:opengeni-presentations" | "builtin:opengeni-projects" | "builtin:opengeni-sites" | "builtin:opengeni-skills" | "builtin:opengeni-spreadsheets" | "builtin:opengeni-video-generation" | "builtin:opengeni-visualize")[] | undefined;
46
46
  prompt: string;
47
47
  instructions: string | null;
48
48
  resources: ({
@@ -81,7 +81,7 @@ export declare const prReviewAutomationAdapter: {
81
81
  eager?: boolean | undefined;
82
82
  optional?: boolean | undefined;
83
83
  }[];
84
- firstPartyMcpTools: ("artifacts_archive" | "artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_prepare_upload" | "artifacts_publish" | "artifacts_restore" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "command_read" | "command_wait" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_resume" | "goal_set" | "goal_update" | "instruction_policy_propose" | "interaction_discover" | "interaction_request_human" | "knowledge_correct" | "knowledge_propose" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "project_create" | "project_delete" | "project_get" | "project_list" | "project_reorder" | "project_update" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_set_project" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "wait_for_input" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
84
+ firstPartyMcpTools: ("artifacts_archive" | "artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_prepare_upload" | "artifacts_publish" | "artifacts_restore" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "command_read" | "command_wait" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_resume" | "goal_set" | "goal_update" | "instruction_policy_get" | "instruction_policy_propose" | "instruction_policy_save" | "interaction_discover" | "interaction_request_human" | "knowledge_archive" | "knowledge_browse" | "knowledge_correct" | "knowledge_get" | "knowledge_propose" | "knowledge_retain_file" | "knowledge_retain_message" | "knowledge_save" | "knowledge_search" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "project_create" | "project_delete" | "project_get" | "project_list" | "project_reorder" | "project_update" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_set_project" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "wait_for_input" | "work_claim_release" | "work_claim_upsert" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
85
85
  firstPartyMcpPermissions: ("account:admin" | "account:read" | "api_keys:manage" | "artifacts:publish" | "artifacts:read" | "billing:manage" | "billing:read" | "capabilities:manage" | "codemode:call" | "connections:read" | "connections:write" | "documents:manage" | "documents:search" | "enrollments:manage" | "enrollments:read" | "environments:manage" | "environments:use" | "files:read" | "files:upload" | "files:write" | "github:manage" | "github:use" | "goals:manage" | "mcp_servers:attach" | "members:manage" | "rigs:manage" | "rigs:use" | "scheduled_tasks:manage" | "scheduled_tasks:run" | "secrets:list" | "secrets:read" | "secrets:write" | "sessions:control" | "sessions:create" | "sessions:read" | "stream:acknowledge" | "stream:control" | "stream:view" | "terminal:attach" | "variable-sets:attach" | "variable-sets:list" | "variable-sets:manage" | "variable-sets:read" | "variable-sets:use" | "variable-sets:write" | "workspace:admin" | "workspace:create" | "workspace:read")[];
86
86
  model: string | null;
87
87
  reasoningEffort: "high" | "low" | "max" | "medium" | "minimal" | "none" | "xhigh" | null;
@@ -1,6 +1,6 @@
1
1
  import type { Settings } from "@opengeni/config";
2
2
  import { mergeToolRefs, stableJson, type RepositoryResourceRef, type ResourceRef, type ToolRef, type WorkspaceSessionToolDefaults } from "@opengeni/contracts";
3
- import { type Database } from "@opengeni/db";
3
+ import { type SessionRlsActorContext, type Database } from "@opengeni/db";
4
4
  export declare function validateToolRefs(tools: ToolRef[], settings: McpSettings): ToolRef[];
5
5
  type McpSettings = Pick<Settings, "mcpServers">;
6
6
  export declare function enabledCapabilityMcpToolRefs(settings: McpSettings, runtimeSettings: McpSettings): ToolRef[];
@@ -49,5 +49,5 @@ export declare function validateGitHubRepositorySelection(db: Database, workspac
49
49
  * leave the result unknown and must not cause draft hydration to delete it.
50
50
  */
51
51
  export declare function isAuthoritativeGitHubRepositorySelectionError(error: unknown): boolean;
52
- export declare function validateFileResources(db: Database, accountId: string, workspaceId: string, subjectId: string, resources: ResourceRef[]): Promise<void>;
52
+ export declare function validateFileResources(db: Database, accountId: string, workspaceId: string, subjectId: string | null, resources: ResourceRef[], privateFileContext?: SessionRlsActorContext): Promise<void>;
53
53
  export { mergeToolRefs, stableJson };
@@ -1,6 +1,6 @@
1
1
  import { type Settings } from "@opengeni/config";
2
2
  import type { AccessGrant, McpPersonalConnectionDelegation, ScheduledTask, ScheduledTaskAgentConfig, Session, SessionAuthorizationPort, SessionAuthorizationSurface, CreateScheduledTaskRequest as CreateScheduledTaskPayload, UpdateScheduledTaskRequest as UpdateScheduledTaskPayload } from "@opengeni/contracts";
3
- import { type Database, type TemporalScheduleCleanupClaim, type UpdateScheduledTaskInput } from "@opengeni/db";
3
+ import { type KnowledgeContext, type Database, type TemporalScheduleCleanupClaim, type UpdateScheduledTaskInput } from "@opengeni/db";
4
4
  import { type AccessGrantAuthorization } from "../access/index.js";
5
5
  import type { SessionWorkflowClient } from "../dependencies.js";
6
6
  import type { ObjectStorageDependency } from "../dependencies.js";
@@ -37,7 +37,11 @@ export declare function createValidatedScheduledTask(input: {
37
37
  */
38
38
  export declare function withScheduledTaskAuthorityWriteErrors<T>(run: () => Promise<T>): Promise<T>;
39
39
  /** API/MCP-facing update that maps authority-write denials to 409. */
40
- export declare function updateScheduledTaskForApi(db: Database, workspaceId: string, taskId: string, update: UpdateScheduledTaskInput): Promise<ScheduledTask>;
40
+ export declare function updateScheduledTaskForApi(db: Database, workspaceId: string, taskId: string, update: UpdateScheduledTaskInput, learning?: {
41
+ authorization: AccessGrantAuthorization;
42
+ request: NonNullable<UpdateScheduledTaskPayload["agentLearning"]>;
43
+ restoreState: ScheduledTaskRestoreState;
44
+ }): Promise<ScheduledTask>;
41
45
  export declare function validateScheduledTaskTarget(input: {
42
46
  db: Database;
43
47
  sessionAuthorization?: SessionAuthorizationPort | null | undefined;
@@ -84,6 +88,12 @@ export declare function requireScheduledTaskForApi(db: Database, workspaceId: st
84
88
  export type ScheduledTaskRestoreState = {
85
89
  task: ScheduledTask;
86
90
  personalConnectionDelegations: McpPersonalConnectionDelegation[];
91
+ learning?: {
92
+ context: KnowledgeContext;
93
+ scope: "workspace" | "personal";
94
+ settings: import("@opengeni/contracts").AgentLearningOverridePatch;
95
+ expectedVersion: number;
96
+ };
87
97
  };
88
98
  export declare function captureScheduledTaskRestoreState(db: Database, task: ScheduledTask): Promise<ScheduledTaskRestoreState>;
89
99
  export declare function restoreScheduledTask(db: Database, previous: ScheduledTaskRestoreState): Promise<ScheduledTask>;