@opengeni/api-router 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-OGQDXVXY.js";
4
4
 
5
5
  // src/app.ts
6
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
6
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
7
7
 
8
8
  // src/routes/claude-subscription-accounts.ts
9
9
  import { createHmac as createHmac2 } from "crypto";
@@ -4435,7 +4435,7 @@ import {
4435
4435
  setMcpOAuthRequestOrganizationAccess
4436
4436
  } from "@opengeni/db";
4437
4437
  import {
4438
- hasPermission as hasPermission14,
4438
+ hasPermission as hasPermission15,
4439
4439
  requireAccessContext as requireAccessContext2,
4440
4440
  requireAccessGrantAuthorization as requireAccessGrantAuthorization6
4441
4441
  } from "@opengeni/core";
@@ -4631,7 +4631,7 @@ import {
4631
4631
  buildApiIntegrationMcpServers,
4632
4632
  expandApiIntegrationAccountRoutes,
4633
4633
  expandMcpAccountRoutes,
4634
- hasPermission as hasPermission13,
4634
+ hasPermission as hasPermission14,
4635
4635
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization5,
4636
4636
  isVerifiedOrganizationServiceAuthorization as isVerifiedOrganizationServiceAuthorization2,
4637
4637
  externalContinuationCommitAuthorizer,
@@ -7916,9 +7916,11 @@ async function deleteSiteDataFile(deps, grant, siteId3, fileId, surface3 = {}) {
7916
7916
 
7917
7917
  // src/site-publishing/agent-data-tools.ts
7918
7918
  import {
7919
- siteHostname as siteHostname3
7919
+ siteHostname as siteHostname3,
7920
+ permissionsRequiredByFirstPartyTools
7920
7921
  } from "@opengeni/contracts";
7921
7922
  import { resolveFirstPartyMcpToolPolicy } from "@opengeni/config";
7923
+ import { hasPermission as hasPermission5 } from "@opengeni/core";
7922
7924
  import {
7923
7925
  consumeSiteRuntimeRate as consumeSiteRuntimeRate2,
7924
7926
  findSiteRuntimeAgentConversation,
@@ -8033,7 +8035,10 @@ import {
8033
8035
  siteHostname as siteHostname2,
8034
8036
  SITE_NOT_AVAILABLE_FOR_VIEWER_ERROR_CODE
8035
8037
  } from "@opengeni/contracts";
8036
- import { sessionUsageLimitsProducerEnabled } from "@opengeni/core";
8038
+ import {
8039
+ sessionUsageLimitsProducerEnabled,
8040
+ stampSiteViewerSessionAuthorization
8041
+ } from "@opengeni/core";
8037
8042
  import {
8038
8043
  consumeSiteRuntimeRate,
8039
8044
  findSiteHostname,
@@ -8056,6 +8061,15 @@ import {
8056
8061
  withWorkspaceSessionActivityRls
8057
8062
  } from "@opengeni/db";
8058
8063
 
8064
+ // src/site-publishing/session-request-authority.ts
8065
+ var authorities = /* @__PURE__ */ new WeakMap();
8066
+ function bindSiteSessionRequestAuthority(request, reauthorize) {
8067
+ authorities.set(request, reauthorize);
8068
+ }
8069
+ async function reauthorizeSiteSessionRequest(request) {
8070
+ await authorities.get(request)?.();
8071
+ }
8072
+
8059
8073
  // src/site-publishing/limits.ts
8060
8074
  import {
8061
8075
  DEFAULT_SITE_LIMITS,
@@ -8251,6 +8265,7 @@ function storedSiteLimitProfileKind(kind) {
8251
8265
 
8252
8266
  // src/site-publishing/service.ts
8253
8267
  import { randomBytes as randomBytes2 } from "crypto";
8268
+ import { AsyncLocalStorage } from "async_hooks";
8254
8269
  import {
8255
8270
  normalizeSitesDomain,
8256
8271
  OPENGENI_API_CONTRACT_HEADER,
@@ -8282,7 +8297,7 @@ import {
8282
8297
  readSiteRuntimeUsage,
8283
8298
  recordSitePublicationScan,
8284
8299
  getPublishedSite as getPublishedSite2,
8285
- listActiveSiteRuntimeConversations,
8300
+ listSiteRuntimeCancellationCandidates,
8286
8301
  revokeSiteViewerSessions,
8287
8302
  SitePublishingError,
8288
8303
  SITE_RUNTIME_SITE_PRINCIPAL,
@@ -10014,12 +10029,9 @@ async function runSitePublishing(fn) {
10014
10029
  var SITE_EFFECT_CONCURRENCY = 4;
10015
10030
  var SITE_EFFECT_QUEUE_LIMIT = 2e3;
10016
10031
  var effectsBySettings = /* @__PURE__ */ new WeakMap();
10017
- var dispatchBySettings = /* @__PURE__ */ new WeakMap();
10018
- function setSitePublishingDispatch(settings, dispatch) {
10019
- dispatchBySettings.set(settings, dispatch);
10020
- }
10021
- function sitePublishingDispatch(settings) {
10022
- return dispatchBySettings.get(settings) ?? null;
10032
+ var cancellationBySettings = /* @__PURE__ */ new WeakMap();
10033
+ function setSitePublishingCancellation(settings, cancel) {
10034
+ cancellationBySettings.set(settings, cancel);
10023
10035
  }
10024
10036
  function createEffects(settings, options = {}) {
10025
10037
  const queueLimit = options.queueLimit ?? SITE_EFFECT_QUEUE_LIMIT;
@@ -10297,14 +10309,18 @@ async function siteServiceSessionRequest(deps, scope, site, input) {
10297
10309
  "x-opengeni-site-id": site.id
10298
10310
  });
10299
10311
  if (site.versionId) headers.set("x-opengeni-site-version", site.versionId);
10300
- if (input.body !== void 0) headers.set("content-type", "application/json");
10312
+ const body5 = input.body === void 0 ? void 0 : JSON.stringify(input.body);
10313
+ if (body5 !== void 0) {
10314
+ headers.set("content-type", "application/json");
10315
+ headers.set("content-length", String(Buffer.byteLength(body5)));
10316
+ }
10301
10317
  return new Request(new URL(input.path, input.origin), {
10302
10318
  method: input.method,
10303
10319
  headers,
10304
- ...input.body === void 0 ? {} : { body: JSON.stringify(input.body) }
10320
+ ...body5 === void 0 ? {} : { body: body5 }
10305
10321
  });
10306
10322
  }
10307
- var STOP_CONVERSATIONS_LIMIT = 200;
10323
+ var STOP_CONVERSATIONS_PAGE_SIZE = 200;
10308
10324
  async function stopSiteViewers(deps, scope, siteId3, options) {
10309
10325
  let revokedSessions = 0;
10310
10326
  if (options.revokeSessions !== false) {
@@ -10318,67 +10334,53 @@ async function stopSiteViewers(deps, scope, siteId3, options) {
10318
10334
  }
10319
10335
  }
10320
10336
  if (options.cancelConversations === false) return { revokedSessions };
10321
- const dispatch = sitePublishingDispatch(deps.settings);
10322
- if (!dispatch) {
10323
- console.warn("[site-publishing] conversation cancel skipped: no in-process dispatch", {
10337
+ const cancel = cancellationBySettings.get(deps.settings);
10338
+ if (!cancel) {
10339
+ console.warn("[site-publishing] conversation cancel unavailable: no lifecycle adapter", {
10324
10340
  siteId: siteId3
10325
10341
  });
10326
10342
  return { revokedSessions };
10327
10343
  }
10328
10344
  const effects = sitePublishingEffects(deps.settings);
10329
- const origin = deps.settings.publicBaseUrl ?? "http://localhost";
10330
- effects.schedule("cancel conversations", async () => {
10331
- const sessionIds = await listActiveSiteRuntimeConversations(deps.db, scope, {
10332
- siteId: siteId3,
10333
- limit: STOP_CONVERSATIONS_LIMIT,
10334
- ...options.toolsNarrowedTo ? { toolsNarrowedTo: options.toolsNarrowedTo } : {}
10335
- });
10336
- if (sessionIds.length === 0) return;
10337
- const versionId = (await getPublishedSite2(deps.db, scope, siteId3))?.currentVersionId ?? null;
10338
- if (!versionId) {
10339
- console.warn("[site-publishing] conversation cancel skipped: the Site has no version", {
10340
- siteId: siteId3
10345
+ const runInContext = AsyncLocalStorage.snapshot();
10346
+ const operation = crypto.randomUUID();
10347
+ const startedBefore = /* @__PURE__ */ new Date();
10348
+ const run2 = () => runInContext(async () => {
10349
+ let after;
10350
+ let failed = 0;
10351
+ for (; ; ) {
10352
+ const sessionIds = await listSiteRuntimeCancellationCandidates(deps.db, scope, {
10353
+ siteId: siteId3,
10354
+ limit: STOP_CONVERSATIONS_PAGE_SIZE,
10355
+ startedBefore,
10356
+ ...after ? { after } : {},
10357
+ ...options.toolsNarrowedTo ? { toolsNarrowedTo: options.toolsNarrowedTo } : {}
10341
10358
  });
10342
- return;
10343
- }
10344
- const operation = crypto.randomUUID();
10345
- for (const sessionId of sessionIds) {
10346
- try {
10347
- const response = await dispatch(
10348
- await siteServiceSessionRequest(
10349
- deps,
10350
- scope,
10351
- { id: siteId3, versionId },
10352
- {
10353
- origin,
10354
- method: "POST",
10355
- path: `/v1/workspaces/${scope.workspaceId}/sessions/${sessionId}/control`,
10356
- body: {
10357
- action: "cancel",
10358
- clientEventId: `site-stop:${operation}:${sessionId}`.slice(0, 200),
10359
- reason: options.reason.slice(0, 500)
10360
- },
10361
- label: "Published Site"
10362
- }
10363
- )
10364
- );
10365
- if (!response.ok)
10359
+ if (sessionIds.length === 0) break;
10360
+ for (const sessionId of sessionIds) {
10361
+ try {
10362
+ await cancel({
10363
+ ...scope,
10364
+ siteId: siteId3,
10365
+ sessionId,
10366
+ operationKey: `site-stop:${operation}:${sessionId}`,
10367
+ reason: options.reason.slice(0, 500)
10368
+ });
10369
+ } catch (error) {
10370
+ failed += 1;
10366
10371
  console.warn("[site-publishing] could not cancel a Site conversation", {
10367
10372
  siteId: siteId3,
10368
10373
  sessionId,
10369
- status: response.status,
10370
- body: (await response.text().catch(() => "")).slice(0, 300)
10374
+ error: error instanceof Error ? error.message : String(error)
10371
10375
  });
10372
- else await response.body?.cancel().catch(() => void 0);
10373
- } catch (error) {
10374
- console.warn("[site-publishing] could not cancel a Site conversation", {
10375
- siteId: siteId3,
10376
- sessionId,
10377
- error: error instanceof Error ? error.message : String(error)
10378
- });
10376
+ }
10379
10377
  }
10378
+ after = sessionIds.at(-1);
10380
10379
  }
10380
+ if (failed > 0)
10381
+ throw new Error(`Site lifecycle cancellation failed for ${failed} conversations`);
10381
10382
  });
10383
+ if (!effects.schedule("cancel conversations", run2)) await run2();
10382
10384
  return { revokedSessions };
10383
10385
  }
10384
10386
  var abuseNoticeHours = /* @__PURE__ */ new Map();
@@ -11192,12 +11194,24 @@ async function meterSiteRuntime(deps, host, event) {
11192
11194
  }
11193
11195
  }
11194
11196
  async function siteRuntimeSessionRequest(deps, host, viewer, input) {
11195
- return await siteServiceSessionRequest(
11197
+ const request = await siteServiceSessionRequest(
11196
11198
  deps,
11197
11199
  host.scope,
11198
11200
  { id: host.site.id, versionId: host.versionId },
11199
11201
  { ...input, label: `${siteRuntimeViewerLabel(viewer)} on ${host.hostname}` }
11200
11202
  );
11203
+ bindSiteSessionRequestAuthority(request, input.reauthorize);
11204
+ if (viewer.kind === "member" && viewer.subjectId && viewer.sessionId) {
11205
+ stampSiteViewerSessionAuthorization(request, {
11206
+ organizationId: host.scope.accountId,
11207
+ subjectId: viewer.subjectId,
11208
+ permissions: [
11209
+ .../* @__PURE__ */ new Set([...SITE_RUNTIME_AGENT_PERMISSIONS, ...input.extraPermissions ?? []])
11210
+ ],
11211
+ workspaceId: host.scope.workspaceId
11212
+ });
11213
+ }
11214
+ return request;
11201
11215
  }
11202
11216
  function siteRuntimeForwardedResponse(response) {
11203
11217
  const headers = new Headers(response.headers);
@@ -11217,10 +11231,6 @@ var SITE_AGENT_SQL_TOOLS = Object.freeze([
11217
11231
  var SITE_AGENT_MEMBER_SQL_TOOLS = Object.freeze([
11218
11232
  "site_sql_query"
11219
11233
  ]);
11220
- var SITE_AGENT_DATA_TOOL_PERMISSIONS = Object.freeze([
11221
- "artifacts:read",
11222
- "artifacts:publish"
11223
- ]);
11224
11234
  var SITE_AGENT_OTHER_SITE_MESSAGE2 = "This Site's assistant can only use this Site's data";
11225
11235
  var SITE_AGENT_MANAGEMENT_MESSAGE = "This Site's assistant can use the Site's data, not manage the Site";
11226
11236
  function siteAgentDataToolNames(input) {
@@ -11229,18 +11239,23 @@ function siteAgentDataToolNames(input) {
11229
11239
  ...input.siteSql ? SITE_AGENT_SQL_TOOLS : [],
11230
11240
  ...input.siteSql && input.viewerKind === "member" ? SITE_AGENT_MEMBER_SQL_TOOLS : []
11231
11241
  ];
11232
- return names.filter((name) => input.allowed.includes(name));
11242
+ return names.filter(
11243
+ (name) => input.allowed.includes(name) && (input.viewerKind !== "member" || input.memberPermissions === void 0 || permissionsRequiredByFirstPartyTools([name]).every(
11244
+ (permission) => hasPermission5(input.memberPermissions, permission)
11245
+ ))
11246
+ );
11233
11247
  }
11234
11248
  async function siteAgentSiteSqlOn(deps, scope, siteId3) {
11235
11249
  if (!siteSqlOffered(deps.settings)) return false;
11236
11250
  const database = await getSiteSqlDatabase2(deps.db, { ...scope, siteId: siteId3 }).catch(() => null);
11237
11251
  return database?.enabled === true;
11238
11252
  }
11239
- async function siteAgentDataToolsForStart(deps, scope, siteId3, viewerKind) {
11253
+ async function siteAgentDataToolsForStart(deps, scope, siteId3, viewerKind, memberPermissions) {
11240
11254
  return siteAgentDataToolNames({
11241
11255
  viewerKind,
11242
11256
  siteSql: await siteAgentSiteSqlOn(deps, scope, siteId3),
11243
- allowed: resolveFirstPartyMcpToolPolicy(deps.settings).allowed
11257
+ allowed: resolveFirstPartyMcpToolPolicy(deps.settings).allowed,
11258
+ ...memberPermissions === void 0 ? {} : { memberPermissions }
11244
11259
  });
11245
11260
  }
11246
11261
  function sitePublishedDataViewer(host, principal, guest) {
@@ -12533,7 +12548,7 @@ import {
12533
12548
  editableArtifactId,
12534
12549
  editableArtifactReplicaId,
12535
12550
  editableArtifactScope,
12536
- hasPermission as hasPermission5,
12551
+ hasPermission as hasPermission6,
12537
12552
  requireAccessGrant as requireAccessGrant10,
12538
12553
  requireAccessGrantAuthorization as requireAccessGrantAuthorization2,
12539
12554
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization2,
@@ -12606,6 +12621,7 @@ async function withAccessGrantSessionRlsContext(deps, grant, fn) {
12606
12621
  {
12607
12622
  subjectId: actor.subjectId,
12608
12623
  initiatingHumanSubjectId: actor.initiatingHumanSubjectId,
12624
+ agentRootSessionId: actor.callerRootSessionId,
12609
12625
  privateFileOwnerSubjectId: learning.defaultScope === "personal" ? learning.subjectId : null
12610
12626
  },
12611
12627
  fn
@@ -12846,7 +12862,7 @@ function registerEditableArtifactRoutes(app, deps) {
12846
12862
  app.post(`${collection}/imports`, async (context) => {
12847
12863
  const workspaceId = context.req.param("workspaceId");
12848
12864
  const grant = await requireAccessGrant10(context, deps, workspaceId, "artifacts:publish");
12849
- if (!hasPermission5(grant.permissions, "files:read")) {
12865
+ if (!hasPermission6(grant.permissions, "files:read")) {
12850
12866
  throw applicationHttpError("forbidden");
12851
12867
  }
12852
12868
  const body5 = await parseBoundedImportRequest(context);
@@ -12943,7 +12959,7 @@ function registerEditableArtifactRoutes(app, deps) {
12943
12959
  snapshotVersion: body5.snapshotVersion,
12944
12960
  commandProtocolVersion: body5.commandProtocolVersion,
12945
12961
  committedTransactionProtocolVersion: body5.committedTransactionProtocolVersion,
12946
- allowEdit: hasPermission5(grant.permissions, "artifacts:publish"),
12962
+ allowEdit: hasPermission6(grant.permissions, "artifacts:publish"),
12947
12963
  ...body5.sourceSessionId ? {
12948
12964
  sourceSessionAuthority: {
12949
12965
  sessionId: body5.sourceSessionId,
@@ -12970,7 +12986,7 @@ function registerEditableArtifactRoutes(app, deps) {
12970
12986
  permissions: [
12971
12987
  "sessions:read",
12972
12988
  "artifacts:read",
12973
- ...hasPermission5(grant.permissions, "artifacts:publish") ? ["artifacts:publish"] : []
12989
+ ...hasPermission6(grant.permissions, "artifacts:publish") ? ["artifacts:publish"] : []
12974
12990
  ]
12975
12991
  },
12976
12992
  ...externalContinuation ? { externalContinuation } : {}
@@ -13896,7 +13912,7 @@ import {
13896
13912
  createWorkspaceVaultProviderRegistry,
13897
13913
  createRemoteExternalVaultFactories,
13898
13914
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization4,
13899
- hasPermission as hasPermission6,
13915
+ hasPermission as hasPermission7,
13900
13916
  isVaultError,
13901
13917
  VaultError,
13902
13918
  providerSecretName,
@@ -14223,8 +14239,8 @@ function isAccountAdmin(authorization) {
14223
14239
  }
14224
14240
  function canManageOnePasswordConnection(authorization, connection, metadata) {
14225
14241
  const { grant } = authorization;
14226
- if (!hasPermission6(grant.permissions, "connections:write", grant.permissionMode)) return false;
14227
- if (!hasPermission6(grant.permissions, "secrets:write", grant.permissionMode)) return false;
14242
+ if (!hasPermission7(grant.permissions, "connections:write", grant.permissionMode)) return false;
14243
+ if (!hasPermission7(grant.permissions, "secrets:write", grant.permissionMode)) return false;
14228
14244
  if (connection.subjectId !== null) return connection.subjectId === grant.subjectId;
14229
14245
  if (metadata.ownership === "organization") return isAccountAdmin(authorization);
14230
14246
  return true;
@@ -15075,7 +15091,7 @@ function registerVaultProviderRoutes(app, deps, options = {}) {
15075
15091
  }
15076
15092
  function canManageExternal(authorization, connection, details) {
15077
15093
  const grant = authorization.grant;
15078
- return hasPermission6(grant.permissions, "connections:write", grant.permissionMode) && hasPermission6(grant.permissions, "secrets:write", grant.permissionMode) && (connection.subjectId !== null ? connection.subjectId === grant.subjectId && isPersonalConnectionOwnerPrincipal(authorization) : details.ownership !== "organization" || isAccountAdmin(authorization));
15094
+ return hasPermission7(grant.permissions, "connections:write", grant.permissionMode) && hasPermission7(grant.permissions, "secrets:write", grant.permissionMode) && (connection.subjectId !== null ? connection.subjectId === grant.subjectId && isPersonalConnectionOwnerPrincipal(authorization) : details.ownership !== "organization" || isAccountAdmin(authorization));
15079
15095
  }
15080
15096
  function catalogVault(provider, vault, linkedVaultId) {
15081
15097
  return {
@@ -15803,12 +15819,12 @@ import { isVaultError as isVaultError3, vaultErrorFromDatabase as vaultErrorFrom
15803
15819
  // src/mcp/first-party-tool-permissions.ts
15804
15820
  import {
15805
15821
  FIRST_PARTY_TOOL_AUTHORIZATION,
15806
- permissionsRequiredByFirstPartyTools
15822
+ permissionsRequiredByFirstPartyTools as permissionsRequiredByFirstPartyTools2
15807
15823
  } from "@opengeni/contracts";
15808
15824
 
15809
15825
  // src/mcp/server.ts
15810
15826
  import {
15811
- hasPermission as hasPermission10,
15827
+ hasPermission as hasPermission11,
15812
15828
  authorizedSocialConnectionsForGrant,
15813
15829
  buildCapabilityCatalog,
15814
15830
  CONNECTED_MACHINE_CAPABILITY_ID,
@@ -16032,10 +16048,10 @@ async function listWorkspaceGitHubRepositoryBranches(deps, input, services = wor
16032
16048
  }
16033
16049
 
16034
16050
  // src/github-browser-flow.ts
16035
- import { hasPermission as hasPermission7 } from "@opengeni/core";
16051
+ import { hasPermission as hasPermission8 } from "@opengeni/core";
16036
16052
  var githubBrowserGrantMaxAgeSeconds = 10 * 60;
16037
16053
  function githubBrowserGrantClaims(settings, grant, nowSeconds = Math.floor(Date.now() / 1e3)) {
16038
- if (settings.productAccessMode !== "configured" || !hasPermission7(grant.permissions, "github:manage")) {
16054
+ if (settings.productAccessMode !== "configured" || !hasPermission8(grant.permissions, "github:manage")) {
16039
16055
  return {};
16040
16056
  }
16041
16057
  return {
@@ -16773,7 +16789,7 @@ async function withChannelAOperation(services, ctx, readOnly, fn) {
16773
16789
  hasGitHubRepositorySelection(session.resources) ? githubAppBotIdentity(settings) : null
16774
16790
  );
16775
16791
  }
16776
- const runEstablished = async (routed, lease, homeSession) => {
16792
+ const runEstablished = async (routed, lease, homeSession, pinnedMachine = null) => {
16777
16793
  const emit = async (events) => {
16778
16794
  await appendAndPublishEvents2(
16779
16795
  db,
@@ -16804,6 +16820,7 @@ async function withChannelAOperation(services, ctx, readOnly, fn) {
16804
16820
  homeSession,
16805
16821
  routingSession,
16806
16822
  machineAuthority,
16823
+ pinnedMachine,
16807
16824
  requestId
16808
16825
  });
16809
16826
  await routingSession.finalizeOpStreamOps().catch(() => void 0);
@@ -16892,6 +16909,7 @@ async function withChannelAOperation(services, ctx, readOnly, fn) {
16892
16909
  operationResourcePolicySupported: enrollment.agentCapabilities.operationResourcePolicy === true,
16893
16910
  operationCpuQuotaSupported: enrollment.agentCapabilities.operationCpuQuota === true,
16894
16911
  transactionalFsWriteSupported: enrollment.agentCapabilities.transactionalFsWrite === true,
16912
+ browserControlHttpSupported: enrollment.agentCapabilities.browserControlHttp === true,
16895
16913
  ...settings.agentOpStreamEnabled === true && enrollment?.opStream === true && bus.getOpStreamConnection ? {
16896
16914
  opStream: {
16897
16915
  transport: new NatsOpStreamTransport(
@@ -16930,7 +16948,11 @@ async function withChannelAOperation(services, ctx, readOnly, fn) {
16930
16948
  },
16931
16949
  established2
16932
16950
  );
16933
- return await runEstablished(routed, null, established2.session);
16951
+ return await runEstablished(routed, null, established2.session, {
16952
+ sandboxId: sandbox.id,
16953
+ sandboxWorkspaceId: originWorkspaceId,
16954
+ enrollment
16955
+ });
16934
16956
  } catch (error) {
16935
16957
  observeChannelAOperationFailure(services, {
16936
16958
  workspaceId,
@@ -21275,7 +21297,7 @@ import { parseSocialOauthClientsJson } from "@opengeni/config";
21275
21297
  import {
21276
21298
  OAuthStartResponse as OAuthStartResponse2
21277
21299
  } from "@opengeni/contracts";
21278
- import { hasPermission as hasPermission8, requireEnvironmentEncryption as requireEnvironmentEncryption5 } from "@opengeni/core";
21300
+ import { hasPermission as hasPermission9, requireEnvironmentEncryption as requireEnvironmentEncryption5 } from "@opengeni/core";
21279
21301
  import {
21280
21302
  consumeIntegrationOAuthStateNonce as consumeIntegrationOAuthStateNonce2,
21281
21303
  decryptEnvironmentValue as decryptEnvironmentValue2,
@@ -21445,7 +21467,7 @@ async function completeSocialOAuthCallback(deps, input) {
21445
21467
  throw new HTTPException28(422, { message: PERSONAL_CONNECTION_PRINCIPAL_MESSAGE });
21446
21468
  }
21447
21469
  const grant = await getWorkspaceGrant2(db, state.subjectId, state.workspaceId);
21448
- if (!grant || grant.accountId !== state.accountId || state.ownership === "workspace" && !hasPermission8(grant.permissions, "workspace:admin")) {
21470
+ if (!grant || grant.accountId !== state.accountId || state.ownership === "workspace" && !hasPermission9(grant.permissions, "workspace:admin")) {
21449
21471
  throw new HTTPException28(403, {
21450
21472
  message: "OAuth subject no longer has permission to connect social accounts"
21451
21473
  });
@@ -27708,7 +27730,7 @@ import {
27708
27730
  } from "@opengeni/contracts";
27709
27731
  import {
27710
27732
  fileOwnerContextForAgent as fileOwnerContextForAgent3,
27711
- hasPermission as hasPermission9,
27733
+ hasPermission as hasPermission10,
27712
27734
  requireOpenGeniSlackBotConnection as requireOpenGeniSlackBotConnection2,
27713
27735
  requirePermission as requirePermission3
27714
27736
  } from "@opengeni/core";
@@ -28007,7 +28029,7 @@ async function uploadSlackTaskFile(deps, input) {
28007
28029
  });
28008
28030
  }
28009
28031
  function slackTaskRequesterCanReceiveFile(permissions) {
28010
- return hasPermission9(permissions, "files:read") && hasPermission9(permissions, "sessions:read");
28032
+ return hasPermission10(permissions, "files:read") && hasPermission10(permissions, "sessions:read");
28011
28033
  }
28012
28034
  function assertSlackTaskUploadTarget(interaction) {
28013
28035
  if (interaction.visibility === "private" && (!interaction.slackChannelId.startsWith("D") || interaction.routeKey !== `${interaction.slackChannelId}:${interaction.slackThreadTs}` || interaction.ackSlackMessageTs !== null && interaction.ackSlackMessageTs !== interaction.slackThreadTs)) {
@@ -43299,7 +43321,7 @@ var PolicyMcpServer = class extends McpServer3 {
43299
43321
  holdsSelectableTool(toolName) {
43300
43322
  const policy = FIRST_PARTY_TOOL_AUTHORIZATION[toolName];
43301
43323
  if (policy.adminAccessRequired) return false;
43302
- const authorized = (policy.allOf?.every((permission) => hasPermission10(this.grant.permissions, permission)) ?? true) && (policy.anyOf?.some((permission) => hasPermission10(this.grant.permissions, permission)) ?? true);
43324
+ const authorized = (policy.allOf?.every((permission) => hasPermission11(this.grant.permissions, permission)) ?? true) && (policy.anyOf?.some((permission) => hasPermission11(this.grant.permissions, permission)) ?? true);
43303
43325
  return authorized && (this.selectedTools === null || this.selectedTools.has(toolName));
43304
43326
  }
43305
43327
  registerTool(name, config, cb) {
@@ -43407,7 +43429,7 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
43407
43429
  const json2 = (value) => ({
43408
43430
  content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
43409
43431
  });
43410
- const can = (permission) => hasPermission10(grant.permissions, permission);
43432
+ const can = (permission) => hasPermission11(grant.permissions, permission);
43411
43433
  let socialConnectionsPromise;
43412
43434
  const authorizedSocialConnections = () => socialConnectionsPromise ??= authorizedSocialConnectionsForGrant({
43413
43435
  db: deps.db,
@@ -48524,7 +48546,7 @@ function registerGitHubConnectTool(server, deps, grant, options, json2) {
48524
48546
  const installations = await listWorkspaceGitHubInstallationBindings(deps, grant.workspaceId);
48525
48547
  const status = githubBindingStatus(true, installations);
48526
48548
  const baseUrl = githubBrowserBaseUrl(settings, options.requestOrigin);
48527
- const state = baseUrl && hasPermission10(grant.permissions, "github:manage") ? createSignedState7(deps.githubStateSecret, {
48549
+ const state = baseUrl && hasPermission11(grant.permissions, "github:manage") ? createSignedState7(deps.githubStateSecret, {
48528
48550
  accountId: grant.accountId,
48529
48551
  workspaceId: grant.workspaceId,
48530
48552
  intent: "installation_authority",
@@ -49065,18 +49087,18 @@ function startWorkspaceToolGatewayObservation(observability, input) {
49065
49087
  }
49066
49088
 
49067
49089
  // src/workspace-tool-gateway-secrets.ts
49068
- import { AsyncLocalStorage } from "async_hooks";
49090
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
49069
49091
  import { environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes5 } from "@opengeni/config";
49070
49092
  import {
49071
49093
  SecretReferenceError,
49072
49094
  collectReferencesDeep
49073
49095
  } from "@opengeni/contracts";
49074
- import { createSecretResolver, hasPermission as hasPermission11 } from "@opengeni/core";
49096
+ import { createSecretResolver, hasPermission as hasPermission12 } from "@opengeni/core";
49075
49097
  import {
49076
49098
  createSecretArgumentResolver,
49077
49099
  secretArgumentMode
49078
49100
  } from "@opengeni/runtime/workspace-tool-gateway";
49079
- var siteSecretContexts = new AsyncLocalStorage();
49101
+ var siteSecretContexts = new AsyncLocalStorage2();
49080
49102
  function withSiteSecretContext(context, run2) {
49081
49103
  return siteSecretContexts.run(context, run2);
49082
49104
  }
@@ -49107,7 +49129,7 @@ function workspaceGatewaySecretArguments(input) {
49107
49129
  if (secretArgumentMode(call.entry) !== "literal") return call.arguments;
49108
49130
  const site = siteSecretContexts.getStore() ?? null;
49109
49131
  const references = collectReferencesDeep(call.arguments);
49110
- if (!site && references.length > 0 && !hasPermission11(input.grant.permissions, "secrets:use", input.grant.permissionMode)) {
49132
+ if (!site && references.length > 0 && !hasPermission12(input.grant.permissions, "secrets:use", input.grant.permissionMode)) {
49111
49133
  throw new SecretReferenceError(
49112
49134
  references.map((reference) => ({
49113
49135
  raw: reference.raw,
@@ -49217,7 +49239,7 @@ function workspaceToolGatewayIdentityKey(identity2) {
49217
49239
  }
49218
49240
 
49219
49241
  // src/site-publishing/page-tool-authority.ts
49220
- import { hasPermission as hasPermission12 } from "@opengeni/core";
49242
+ import { hasPermission as hasPermission13 } from "@opengeni/core";
49221
49243
  import {
49222
49244
  getPublishedSiteVersion as getPublishedSiteVersion4,
49223
49245
  getWorkspaceGrant as getWorkspaceGrant3,
@@ -49225,12 +49247,12 @@ import {
49225
49247
  withWorkspaceSubjectRls as withWorkspaceSubjectRls3
49226
49248
  } from "@opengeni/db";
49227
49249
  import { HTTPException as HTTPException37 } from "hono/http-exception";
49228
- var authorities = /* @__PURE__ */ new WeakMap();
49250
+ var authorities2 = /* @__PURE__ */ new WeakMap();
49229
49251
  function isPublishedSiteToolAuthorization(value) {
49230
- return authorities.has(value);
49252
+ return authorities2.has(value);
49231
49253
  }
49232
49254
  function publishedSiteToolAuthority(value) {
49233
- const authority = authorities.get(value);
49255
+ const authority = authorities2.get(value);
49234
49256
  if (!authority) throw new HTTPException37(403, { message: "site_tool_not_authorized" });
49235
49257
  return authority;
49236
49258
  }
@@ -49252,7 +49274,7 @@ async function authorizePublishedSiteTools(deps, domain, fields2) {
49252
49274
  });
49253
49275
  }
49254
49276
  );
49255
- if (!grant2 || !hasPermission12(grant2.permissions, "workspace:read")) throw denied2();
49277
+ if (!grant2 || !hasPermission13(grant2.permissions, "workspace:read")) throw denied2();
49256
49278
  return { host: host2, viewer, grant: grant2 };
49257
49279
  };
49258
49280
  const initial = await read();
@@ -49261,7 +49283,7 @@ async function authorizePublishedSiteTools(deps, domain, fields2) {
49261
49283
  if (!version2) throw new HTTPException37(403, { message: "site_tool_not_authorized" });
49262
49284
  const reauthorize = async () => {
49263
49285
  const live = await read();
49264
- if (live.host.site.id !== host.site.id || live.host.versionId !== version2.id || live.grant.accountId !== grant.accountId || live.grant.workspaceId !== grant.workspaceId || live.grant.subjectId !== grant.subjectId || live.viewer.sessionId !== initial.viewer.sessionId || grant.permissions.some((permission) => !hasPermission12(live.grant.permissions, permission)))
49286
+ if (live.host.site.id !== host.site.id || live.host.versionId !== version2.id || live.grant.accountId !== grant.accountId || live.grant.workspaceId !== grant.workspaceId || live.grant.subjectId !== grant.subjectId || live.viewer.sessionId !== initial.viewer.sessionId || grant.permissions.some((permission) => !hasPermission13(live.grant.permissions, permission)))
49265
49287
  throw new HTTPException37(403, { message: "site_tool_access_changed" });
49266
49288
  };
49267
49289
  Object.freeze(grant.permissions);
@@ -49270,7 +49292,7 @@ async function authorizePublishedSiteTools(deps, domain, fields2) {
49270
49292
  kind: "published_site_tools",
49271
49293
  grant
49272
49294
  });
49273
- authorities.set(authorization, {
49295
+ authorities2.set(authorization, {
49274
49296
  requestedTools: version2.requestedTools,
49275
49297
  origin: { siteId: host.site.id, versionId: version2.id, title: host.site.title },
49276
49298
  reauthorize,
@@ -49372,7 +49394,7 @@ async function prepareWorkspaceToolGateway(routeDeps, authorization, options = {
49372
49394
  );
49373
49395
  const workspace = await requireWorkspace2(tx, scope.workspaceId);
49374
49396
  if (!live || permissions.some(
49375
- (permission) => !hasPermission13(live.permissions, permission, live.permissionMode)
49397
+ (permission) => !hasPermission14(live.permissions, permission, live.permissionMode)
49376
49398
  ) || workspace.accountId !== scope.accountId || workspace.kind !== "shared")
49377
49399
  throw new HTTPException38(403, { message: "service gateway authority changed" });
49378
49400
  }
@@ -49761,7 +49783,7 @@ async function prepareWorkspaceToolGatewayForGrantInternal(routeDeps, grant, all
49761
49783
  const firstPartyServers = await Promise.all([
49762
49784
  ...gatewayServerIds.has("opengeni") ? [inMemoryMcpRegistration("opengeni", buildOpenGeniMcpServer(deps, grant))] : [],
49763
49785
  ...gatewayServerIds.has("files") ? [inMemoryMcpRegistration("files", buildFilesMcpServer(deps, grant))] : [],
49764
- ...gatewayServerIds.has("docs") && hasPermission13(grant.permissions, "documents:search") ? [
49786
+ ...gatewayServerIds.has("docs") && hasPermission14(grant.permissions, "documents:search") ? [
49765
49787
  inMemoryMcpRegistration(
49766
49788
  "docs",
49767
49789
  buildDocumentsMcpServer(
@@ -49986,10 +50008,10 @@ function workspaceToolGatewaySettingsForGrant(settings, grant, allowedIdentities
49986
50008
  ...settings,
49987
50009
  mcpServers: settings.mcpServers.filter((server) => {
49988
50010
  if (allowedServerIds && !allowedServerIds.has(server.id)) return false;
49989
- if (server.id === "docs" && !hasPermission13(grant.permissions, "documents:search")) {
50011
+ if (server.id === "docs" && !hasPermission14(grant.permissions, "documents:search")) {
49990
50012
  return false;
49991
50013
  }
49992
- if (server.id === "files" && !hasPermission13(grant.permissions, "files:read")) return false;
50014
+ if (server.id === "files" && !hasPermission14(grant.permissions, "files:read")) return false;
49993
50015
  return true;
49994
50016
  })
49995
50017
  };
@@ -51044,10 +51066,10 @@ function renderMcpOAuthExpiredPage(message) {
51044
51066
  async function listConsentWorkspaces(deps, context) {
51045
51067
  const readableWorkspaceIds = [
51046
51068
  ...new Set(
51047
- context.workspaceGrants.filter((grant) => hasPermission14(grant.permissions, "workspace:read")).map((grant) => grant.workspaceId)
51069
+ context.workspaceGrants.filter((grant) => hasPermission15(grant.permissions, "workspace:read")).map((grant) => grant.workspaceId)
51048
51070
  )
51049
51071
  ];
51050
- const readableAccountIds = context.accountGrants.filter((grant) => hasPermission14(grant.permissions, "workspace:read")).map((grant) => grant.accountId);
51072
+ const readableAccountIds = context.accountGrants.filter((grant) => hasPermission15(grant.permissions, "workspace:read")).map((grant) => grant.accountId);
51051
51073
  const [fromGrants, memberships, shared] = await Promise.all([
51052
51074
  Promise.all(readableWorkspaceIds.map((workspaceId) => getWorkspace2(deps.db, workspaceId))),
51053
51075
  listWorkspacesForSubject(deps.db, context.subjectId),
@@ -51154,7 +51176,7 @@ async function consentOrganizations(deps, context) {
51154
51176
  personal: workspace.kind === "personal"
51155
51177
  })),
51156
51178
  grantable: canonical.filter(
51157
- (permission) => accountGrant !== void 0 && hasPermission14(accountGrant.permissions, permission) || workspaceGrants.some((grant) => hasPermission14(grant.permissions, permission))
51179
+ (permission) => accountGrant !== void 0 && hasPermission15(accountGrant.permissions, permission) || workspaceGrants.some((grant) => hasPermission15(grant.permissions, permission))
51158
51180
  )
51159
51181
  };
51160
51182
  });
@@ -53019,7 +53041,7 @@ import { HTTPException as HTTPException45 } from "hono/http-exception";
53019
53041
  import {
53020
53042
  accountScopedApiKeyWorkspaceAuthority as accountScopedApiKeyWorkspaceAuthority2,
53021
53043
  organizationApiKeyAccess,
53022
- hasPermission as hasPermission15,
53044
+ hasPermission as hasPermission16,
53023
53045
  organizationWorkspaceInScope,
53024
53046
  requireAccessContext as requireAccessContext4,
53025
53047
  requireAccessGrantAuthorization as requireAccessGrantAuthorization7,
@@ -53254,7 +53276,7 @@ function ensureOrganizationPolicyDelegable(context, policy, legacy = false) {
53254
53276
  const authority = accountScopedApiKeyWorkspaceAuthority2(context);
53255
53277
  const source = context.credential?.policy;
53256
53278
  if (!authority || authority.permissionMode !== "explicit" || !source) return;
53257
- const requested = legacy ? Permission2.options.filter((permission) => hasPermission15(policy.permissions, permission)) : policy.permissions;
53279
+ const requested = legacy ? Permission2.options.filter((permission) => hasPermission16(policy.permissions, permission)) : policy.permissions;
53258
53280
  if (requested.some((permission) => !source.permissions.includes(permission)))
53259
53281
  throw new HTTPException45(403, {
53260
53282
  message: "cannot delegate permissions beyond organization key policy"
@@ -53572,7 +53594,7 @@ import { HTTPException as HTTPException48 } from "hono/http-exception";
53572
53594
  // src/workspace-tool-target-fence.ts
53573
53595
  import {
53574
53596
  externalContinuationCommitAuthorizer as externalContinuationCommitAuthorizer2,
53575
- hasPermission as hasPermission16,
53597
+ hasPermission as hasPermission17,
53576
53598
  isVerifiedOrganizationServiceAuthorization as isVerifiedOrganizationServiceAuthorization3
53577
53599
  } from "@opengeni/core";
53578
53600
  import {
@@ -53627,7 +53649,7 @@ function targetFenceCaller(deps, authorization, reauthorize) {
53627
53649
  grant.workspaceId
53628
53650
  );
53629
53651
  if (!live || permissions.some(
53630
- (permission) => !hasPermission16(live.permissions, permission, live.permissionMode)
53652
+ (permission) => !hasPermission17(live.permissions, permission, live.permissionMode)
53631
53653
  ))
53632
53654
  throw new HTTPException47(403, { message: "service gateway authority changed" });
53633
53655
  }
@@ -54182,7 +54204,7 @@ import {
54182
54204
  CodemodeCallRequest,
54183
54205
  CodemodeCallSubmission
54184
54206
  } from "@opengeni/contracts";
54185
- import { hasPermission as hasPermission17, isDeveloperSetupGrant, requireSessionAuthorization as requireSessionAuthorization6 } from "@opengeni/core";
54207
+ import { hasPermission as hasPermission18, isDeveloperSetupGrant, requireSessionAuthorization as requireSessionAuthorization6 } from "@opengeni/core";
54186
54208
  import {
54187
54209
  CodemodeToolApprovalRequiredError,
54188
54210
  getActiveSessionTurnForExecution,
@@ -54226,7 +54248,7 @@ function codemodeSessionProxyPermissions(settings, session) {
54226
54248
  const selection = allowedFirstPartyMcpToolsForSession2(settings, session.firstPartyMcpTools);
54227
54249
  const requiredBySelection = /* @__PURE__ */ new Set([
54228
54250
  "workspace:read",
54229
- ...permissionsRequiredByFirstPartyTools(selection)
54251
+ ...permissionsRequiredByFirstPartyTools2(selection)
54230
54252
  ]);
54231
54253
  return CODEMODE_SESSION_PROXY_PERMISSION_CEILING.filter(
54232
54254
  (permission) => requiredBySelection.has(permission) && sessionPermissions.includes(permission)
@@ -54347,7 +54369,7 @@ function codemodeAuthorityForGrant(grant) {
54347
54369
  };
54348
54370
  }
54349
54371
  function isCodemodeGrant(grant) {
54350
- return hasPermission17(grant.permissions, "codemode:call") && codemodeAuthorityForGrant(grant) !== null;
54372
+ return hasPermission18(grant.permissions, "codemode:call") && codemodeAuthorityForGrant(grant) !== null;
54351
54373
  }
54352
54374
  function requireMatchingCodemodeCatalog(authority, catalog) {
54353
54375
  if (!catalog) throw new CodemodeCatalogNotReadyError();
@@ -54718,7 +54740,7 @@ import {
54718
54740
  siteSessionOriginFromMetadata,
54719
54741
  withSiteSessionOrigin as withSiteSessionOrigin4
54720
54742
  } from "@opengeni/core";
54721
- import { getSession as getSession7 } from "@opengeni/db";
54743
+ import { getSession as getSession7, getSessionAuthorityProjection as getSessionAuthorityProjection2 } from "@opengeni/db";
54722
54744
  import { HTTPException as HTTPException50 } from "hono/http-exception";
54723
54745
  var CODEMODE_SDK_PROXY = /^\/v1\/workspaces\/[^/]+\/codemode\/sdk(?:\/|$)/u;
54724
54746
  var SITE_DATA = /^\/v1\/workspaces\/[^/]+\/published-artifacts\/([^/]+)\/(?:data|files)(?:\/|$)/u;
@@ -54750,10 +54772,15 @@ function siteFrameGuard(deps) {
54750
54772
  throw new HTTPException50(404, { message: "Unsupported Site session API path" });
54751
54773
  }
54752
54774
  if (match.sessionId !== null) {
54775
+ const authority = await getSessionAuthorityProjection2(
54776
+ deps.db,
54777
+ grant.workspaceId,
54778
+ match.sessionId
54779
+ );
54753
54780
  const session = await getSession7(deps.db, grant.workspaceId, match.sessionId).catch(
54754
54781
  () => null
54755
54782
  );
54756
- if (!session || !siteOriginsMatch(origin, siteSessionOriginFromMetadata(session.metadata)))
54783
+ if (!authority?.siteAccessRootId || !session || !siteOriginsMatch(origin, siteSessionOriginFromMetadata(session.metadata)))
54757
54784
  throw new HTTPException50(404, { message: "session not found" });
54758
54785
  }
54759
54786
  if (c.req.method !== "GET" && match.operation.id !== "sessions.create") {
@@ -55587,7 +55614,7 @@ import { sessionUsageLimitsProducerEnabled as sessionUsageLimitsProducerEnabled2
55587
55614
  import {
55588
55615
  CodexCompactionV2ProviderLockedError,
55589
55616
  ManagedAuthActorLeaseOutcomeUnknownError,
55590
- hasPermission as hasPermission43,
55617
+ hasPermission as hasPermission44,
55591
55618
  requireAccessGrant as requireAccessGrant64,
55592
55619
  requireAccessGrantAuthorization as requireAccessGrantAuthorization42,
55593
55620
  requireFreshAccessGrant as requireFreshAccessGrant5,
@@ -55605,7 +55632,7 @@ import {
55605
55632
  validateManagedAuthRequestActorLease,
55606
55633
  requireSessionAuthorization as requireSessionAuthorization21,
55607
55634
  SessionAuthorizationDeniedError as SessionAuthorizationDeniedError21,
55608
- withSessionAuthorizationReadReuse,
55635
+ withSessionAuthorizationReadReuse as withSessionAuthorizationReadReuse3,
55609
55636
  SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError19,
55610
55637
  createUserPresenceRecorder,
55611
55638
  registerProductUsageMetricBaselines,
@@ -57060,9 +57087,9 @@ import {
57060
57087
  import { getOAuthState } from "better-auth/api";
57061
57088
 
57062
57089
  // src/auth/managed-auth-attempt-context.ts
57063
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
57064
- var managedAuthAttemptStorage = new AsyncLocalStorage2();
57065
- var managedLinkIntentStorage = new AsyncLocalStorage2();
57090
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
57091
+ var managedAuthAttemptStorage = new AsyncLocalStorage3();
57092
+ var managedLinkIntentStorage = new AsyncLocalStorage3();
57066
57093
  function runManagedSignInConnect(intentId, action) {
57067
57094
  return managedLinkIntentStorage.run(intentId, action);
57068
57095
  }
@@ -89503,7 +89530,7 @@ import {
89503
89530
  isPersonalGitHubConnection as isPersonalGitHubConnection2
89504
89531
  } from "@opengeni/contracts/personal-github";
89505
89532
  import {
89506
- hasPermission as hasPermission18,
89533
+ hasPermission as hasPermission19,
89507
89534
  listOwnConnectionAccountsForGrant,
89508
89535
  hasReservedFikenMetadata,
89509
89536
  ONEPASSWORD_CREDENTIAL_ROLE as ONEPASSWORD_CREDENTIAL_ROLE2,
@@ -91488,7 +91515,7 @@ function registerConnectionRoutes(app, deps) {
91488
91515
  connectionId: c.req.param("connectionId"),
91489
91516
  payload: await c.req.json(),
91490
91517
  canManageOrganizationDestination: authorization.accountGrant?.permissions.includes("account:admin") === true,
91491
- canManageWorkspaceDestination: hasPermission18(grant.permissions, "workspace:admin"),
91518
+ canManageWorkspaceDestination: hasPermission19(grant.permissions, "workspace:admin"),
91492
91519
  canManagePersonalDestination: authorization.contextIntegrity && authorization.authenticatedSubjectId === grant.subjectId
91493
91520
  });
91494
91521
  return c.json(ConnectionResponse.parse({ connection }));
@@ -91566,7 +91593,7 @@ function registerConnectionRoutes(app, deps) {
91566
91593
  connectionId: c.req.param("connectionId"),
91567
91594
  payload: await c.req.json(),
91568
91595
  canManageOrganizationDestination: authorization.accountGrant?.permissions.includes("account:admin") === true,
91569
- canManageWorkspaceDestination: hasPermission18(grant.permissions, "workspace:admin"),
91596
+ canManageWorkspaceDestination: hasPermission19(grant.permissions, "workspace:admin"),
91570
91597
  canManagePersonalDestination: authorization.contextIntegrity && authorization.authenticatedSubjectId === grant.subjectId
91571
91598
  });
91572
91599
  return c.json(ConnectionResponse.parse({ connection }));
@@ -91644,7 +91671,7 @@ function registerConnectionRoutes(app, deps) {
91644
91671
  if (destinationSelection.authorityKind === "organization" && authorization.accountGrant?.permissions.includes("account:admin") !== true) {
91645
91672
  throw new HTTPException64(403, { message: "missing permission: account:admin" });
91646
91673
  }
91647
- if (destinationSelection.authorityKind === "workspace" && !hasPermission18(grant.permissions, "workspace:admin")) {
91674
+ if (destinationSelection.authorityKind === "workspace" && !hasPermission19(grant.permissions, "workspace:admin")) {
91648
91675
  throw new HTTPException64(403, { message: "missing permission: workspace:admin" });
91649
91676
  }
91650
91677
  if (destinationSelection.authorityKind === "personal" && (!authorization.contextIntegrity || authorization.authenticatedSubjectId !== grant.subjectId)) {
@@ -92422,7 +92449,7 @@ import {
92422
92449
  import {
92423
92450
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization10,
92424
92451
  requireAccessGrantAuthorization as requireAccessGrantAuthorization11,
92425
- hasPermission as hasPermission20,
92452
+ hasPermission as hasPermission21,
92426
92453
  requireEnvironmentEncryption as requireEnvironmentEncryption15,
92427
92454
  isFikenConnection as isFikenConnection2,
92428
92455
  isOpenGeniSlackBotConnection as isOpenGeniSlackBotConnection4,
@@ -93931,7 +93958,7 @@ import {
93931
93958
  import { withOrganizationIntegrationPolicyFence as withOrganizationIntegrationPolicyFence6 } from "@opengeni/db/organization-integration-policy";
93932
93959
  import {
93933
93960
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization9,
93934
- hasPermission as hasPermission19,
93961
+ hasPermission as hasPermission20,
93935
93962
  isDeveloperSetupGrant as isDeveloperSetupGrant2,
93936
93963
  requireSessionAuthorization as requireSessionAuthorization8
93937
93964
  } from "@opengeni/core";
@@ -93957,7 +93984,7 @@ async function connectRequestActor(deps, authorization) {
93957
93984
  preparedOnly: false
93958
93985
  };
93959
93986
  const authority = codemodeAuthorityForGrant(grant);
93960
- if (!authority || isDeveloperSetupGrant2(grant) || PREPARED_MCP_PERMISSIONS.some((permission) => !hasPermission19(grant.permissions, permission)))
93987
+ if (!authority || isDeveloperSetupGrant2(grant) || PREPARED_MCP_PERMISSIONS.some((permission) => !hasPermission20(grant.permissions, permission)))
93961
93988
  throw new HTTPException68(403, { message: "Prepared MCP setup authority required" });
93962
93989
  await requireSessionAuthorization8(deps, grant, {
93963
93990
  sessionId: authority.sessionId,
@@ -94019,7 +94046,7 @@ function assertAgentPreparedConnect(actor, attempt) {
94019
94046
 
94020
94047
  // src/routes/connect.ts
94021
94048
  function registerConnectRoutes(app, deps) {
94022
- const canReadAttempt = (permissions, providerId) => ["x", "reddit", "mcp-install"].includes(providerId) ? hasPermission20(permissions, "workspace:read") : providerId === "github-app" ? hasPermission20(permissions, "github:use") || hasPermission20(permissions, "github:manage") : providerId === "github-lens" ? hasPermission20(permissions, "workspace:read") : hasPermission20(permissions, "connections:read");
94049
+ const canReadAttempt = (permissions, providerId) => ["x", "reddit", "mcp-install"].includes(providerId) ? hasPermission21(permissions, "workspace:read") : providerId === "github-app" ? hasPermission21(permissions, "github:use") || hasPermission21(permissions, "github:manage") : providerId === "github-lens" ? hasPermission21(permissions, "workspace:read") : hasPermission21(permissions, "connections:read");
94023
94050
  app.get("/v1/workspaces/:workspaceId/connect/catalog", async (c) => {
94024
94051
  const authorization = await requireAccessGrantAuthorization11(
94025
94052
  c,
@@ -94033,7 +94060,7 @@ function registerConnectRoutes(app, deps) {
94033
94060
  authorization.grant,
94034
94061
  async (_tx, current) => current
94035
94062
  );
94036
- const canWrite2 = hasPermission20(authorization.grant.permissions, "connections:write");
94063
+ const canWrite2 = hasPermission21(authorization.grant.permissions, "connections:write");
94037
94064
  const personal = isPersonalConnectionOwnerPrincipal(authorization);
94038
94065
  let mcpConfigured = false;
94039
94066
  let credentialConfigured = false;
@@ -94053,7 +94080,7 @@ function registerConnectRoutes(app, deps) {
94053
94080
  configured2 = false;
94054
94081
  }
94055
94082
  const ownership = [
94056
- ...hasPermission20(authorization.grant.permissions, "workspace:admin") ? ["workspace"] : [],
94083
+ ...hasPermission21(authorization.grant.permissions, "workspace:admin") ? ["workspace"] : [],
94057
94084
  ...personal ? ["personal"] : []
94058
94085
  ];
94059
94086
  return ConnectProvider.parse({
@@ -94069,7 +94096,7 @@ function registerConnectRoutes(app, deps) {
94069
94096
  id: "mcp-install",
94070
94097
  label: "Install MCP capability",
94071
94098
  family: "mcp",
94072
- readiness: !external || !hasPermission20(authorization.grant.permissions, "capabilities:manage") ? "unsupported" : deps.settings.integrationsEnabled ? "available" : "needs_configuration",
94099
+ readiness: !external || !hasPermission21(authorization.grant.permissions, "capabilities:manage") ? "unsupported" : deps.settings.integrationsEnabled ? "available" : "needs_configuration",
94073
94100
  ownership: ["workspace"],
94074
94101
  setup: ["installation"]
94075
94102
  }),
@@ -94131,7 +94158,7 @@ function registerConnectRoutes(app, deps) {
94131
94158
  id: "github-app",
94132
94159
  label: "GitHub App installation",
94133
94160
  family: "github",
94134
- readiness: !external || !hasPermission20(authorization.grant.permissions, "github:manage") ? "unsupported" : githubAppMissingSettings3(deps.settings).length === 0 && deps.settings.githubAppSlug?.trim() ? "available" : "needs_configuration",
94161
+ readiness: !external || !hasPermission21(authorization.grant.permissions, "github:manage") ? "unsupported" : githubAppMissingSettings3(deps.settings).length === 0 && deps.settings.githubAppSlug?.trim() ? "available" : "needs_configuration",
94135
94162
  ownership: ["workspace"],
94136
94163
  setup: ["oauth", "installation"]
94137
94164
  }),
@@ -94139,7 +94166,7 @@ function registerConnectRoutes(app, deps) {
94139
94166
  id: "github-lens",
94140
94167
  label: "Opengeni Lens PR review",
94141
94168
  family: "github-lens",
94142
- readiness: !external || !hasPermission20(authorization.grant.permissions, "workspace:admin") || !hasPermission20(authorization.grant.permissions, "secrets:write") ? "unsupported" : credentialConfigured && deps.settings.sandboxBackend !== "selfhosted" && prReviewGitHubAppMissingSettings2(deps.settings).length === 0 ? "available" : "needs_configuration",
94169
+ readiness: !external || !hasPermission21(authorization.grant.permissions, "workspace:admin") || !hasPermission21(authorization.grant.permissions, "secrets:write") ? "unsupported" : credentialConfigured && deps.settings.sandboxBackend !== "selfhosted" && prReviewGitHubAppMissingSettings2(deps.settings).length === 0 ? "available" : "needs_configuration",
94143
94170
  ownership: ["workspace"],
94144
94171
  setup: ["oauth", "installation"]
94145
94172
  }),
@@ -94205,8 +94232,8 @@ function registerConnectRoutes(app, deps) {
94205
94232
  app.get("/v1/workspaces/:workspaceId/connect/accounts", async (c) => {
94206
94233
  const workspaceId = c.req.param("workspaceId");
94207
94234
  const { grant } = await requireAccessGrantAuthorization11(c, deps, workspaceId, "workspace:read");
94208
- const connections = hasPermission20(grant.permissions, "connections:read") ? await listConnectionsMetadata6(deps.db, workspaceId, grant.subjectId) : [];
94209
- const githubInstallations = hasPermission20(grant.permissions, "github:use") || hasPermission20(grant.permissions, "github:manage") ? await listGitHubInstallationAccessForWorkspace2(deps.db, workspaceId) : [];
94235
+ const connections = hasPermission21(grant.permissions, "connections:read") ? await listConnectionsMetadata6(deps.db, workspaceId, grant.subjectId) : [];
94236
+ const githubInstallations = hasPermission21(grant.permissions, "github:use") || hasPermission21(grant.permissions, "github:manage") ? await listGitHubInstallationAccessForWorkspace2(deps.db, workspaceId) : [];
94210
94237
  const lensRegistrations = await listPrReviewAppRegistrations(
94211
94238
  deps.db,
94212
94239
  grant.accountId,
@@ -94355,9 +94382,9 @@ function registerConnectRoutes(app, deps) {
94355
94382
  const before = stored.attempt;
94356
94383
  assertAgentPreparedConnect(actor, before);
94357
94384
  const advancePermission = before.providerId === "mcp-install" ? "capabilities:manage" : permission;
94358
- if (!hasPermission20(authorization.grant.permissions, advancePermission))
94385
+ if (!hasPermission21(authorization.grant.permissions, advancePermission))
94359
94386
  throw new HTTPException69(403, { message: `${advancePermission} required` });
94360
- if (before.mcpSetup && !hasPermission20(authorization.grant.permissions, "capabilities:manage"))
94387
+ if (before.mcpSetup && !hasPermission21(authorization.grant.permissions, "capabilities:manage"))
94361
94388
  throw new HTTPException69(403, { message: "capabilities:manage required" });
94362
94389
  if (before.providerId === "mcp-install") {
94363
94390
  if (action.type !== "credentials")
@@ -94403,7 +94430,7 @@ function registerConnectRoutes(app, deps) {
94403
94430
  }
94404
94431
  if (["github-app", "github-lens"].includes(before.providerId)) {
94405
94432
  const installationPermission = before.providerId === "github-lens" ? "workspace:admin" : "github:manage";
94406
- if (!hasPermission20(authorization.grant.permissions, installationPermission) || before.providerId === "github-lens" && !hasPermission20(authorization.grant.permissions, "secrets:write"))
94433
+ if (!hasPermission21(authorization.grant.permissions, installationPermission) || before.providerId === "github-lens" && !hasPermission21(authorization.grant.permissions, "secrets:write"))
94407
94434
  throw new HTTPException69(403, { message: "Installation management permission required" });
94408
94435
  return c.json(
94409
94436
  await executeConnectOperation({
@@ -94894,7 +94921,7 @@ function registerConnectRoutes(app, deps) {
94894
94921
  authorize: async (tx, attempt, origin) => {
94895
94922
  assertAgentPreparedConnect(actor, attempt);
94896
94923
  const permission = attempt.providerId === "mcp-install" ? "capabilities:manage" : ["x", "reddit"].includes(attempt.providerId) ? attempt.ownership === "workspace" ? "workspace:admin" : "workspace:read" : attempt.providerId === "github-app" ? "github:manage" : attempt.providerId === "github-lens" ? "workspace:admin" : "connections:write";
94897
- if (!hasPermission20(authorization.grant.permissions, permission) || attempt.providerId === "github-lens" && !hasPermission20(authorization.grant.permissions, "secrets:write"))
94924
+ if (!hasPermission21(authorization.grant.permissions, permission) || attempt.providerId === "github-lens" && !hasPermission21(authorization.grant.permissions, "secrets:write"))
94898
94925
  throw new HTTPException69(403, { message: "Connect management permission required" });
94899
94926
  await requireConnectOwnerAuthority(tx, scope, permission, origin);
94900
94927
  if (attempt.providerId === "github-lens")
@@ -94928,7 +94955,7 @@ function registerConnectRoutes(app, deps) {
94928
94955
  throw new HTTPException69(403, {
94929
94956
  message: "Verified Connect authority required"
94930
94957
  });
94931
- if (input.mcpSetup && !hasPermission20(authorization.grant.permissions, "capabilities:manage"))
94958
+ if (input.mcpSetup && !hasPermission21(authorization.grant.permissions, "capabilities:manage"))
94932
94959
  throw new HTTPException69(403, { message: "capabilities:manage required" });
94933
94960
  if (input.providerId === "atlassian")
94934
94961
  throw new HTTPException69(410, { message: ATLASSIAN_NATIVE_RETIRED_MESSAGE2 });
@@ -95110,7 +95137,7 @@ function registerConnectRoutes(app, deps) {
95110
95137
  message: "GitHub App setup requires workspace ownership and explicit installation selection"
95111
95138
  });
95112
95139
  if (input.providerId === "github-lens") {
95113
- if (!hasPermission20(authorization.grant.permissions, "secrets:write"))
95140
+ if (!hasPermission21(authorization.grant.permissions, "secrets:write"))
95114
95141
  throw new HTTPException69(403, { message: "secrets:write required" });
95115
95142
  await requireConnectOwnerAuthority(tx, scope, "secrets:write");
95116
95143
  await requireGitHubLensConnect({ ...deps, db: tx });
@@ -95149,7 +95176,7 @@ function registerConnectRoutes(app, deps) {
95149
95176
  throw new HTTPException69(422, { message: "Select the service connection during setup" });
95150
95177
  if (input.ownership === "personal" && !scope.personalOwnerVerified)
95151
95178
  throw new HTTPException69(403, { message: "personal ownership unavailable" });
95152
- const choices = hasPermission20(authorization.grant.permissions, "connections:read") ? (await listConnectionsMetadata6(tx, workspaceId, scope.subjectId)).filter(
95179
+ const choices = hasPermission21(authorization.grant.permissions, "connections:read") ? (await listConnectionsMetadata6(tx, workspaceId, scope.subjectId)).filter(
95153
95180
  (connection) => connection.status === "active" && (input.ownership === "workspace" ? connection.subjectId === null : connection.subjectId === scope.subjectId)
95154
95181
  ).map((connection) => ({
95155
95182
  value: connection.id,
@@ -95486,7 +95513,7 @@ import {
95486
95513
  requireAccessGrantAuthorization as requireAccessGrantAuthorization12,
95487
95514
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization11,
95488
95515
  externalContinuationCommitAuthorizer as externalContinuationCommitAuthorizer4,
95489
- hasPermission as hasPermission21
95516
+ hasPermission as hasPermission22
95490
95517
  } from "@opengeni/core";
95491
95518
  function nativeConfirmation(authorization) {
95492
95519
  if (!authorization.contextIntegrity || !authorization.canonicalManagedHumanSession || authorization.authenticatedSubjectId !== authorization.grant.subjectId || !authorization.grant.subjectId.startsWith("user:"))
@@ -95600,7 +95627,7 @@ function registerExternalIdentityLinkRoutes(app, deps) {
95600
95627
  principalKind: "human_session"
95601
95628
  });
95602
95629
  if (!current || current.accountId !== grant.accountId || request.permissions.some(
95603
- (permission) => !hasPermission21(grant.permissions, permission) || !hasPermission21(current.permissions, permission)
95630
+ (permission) => !hasPermission22(grant.permissions, permission) || !hasPermission22(current.permissions, permission)
95604
95631
  ))
95605
95632
  throw new HTTPException70(403, {
95606
95633
  message: "Link permissions exceed your authority in this workspace"
@@ -96475,7 +96502,7 @@ import {
96475
96502
  KnowledgeVectorCreditsDisabledError,
96476
96503
  KnowledgeVectorFundingError,
96477
96504
  KnowledgeVectorQueryRejectedError,
96478
- hasPermission as hasPermission22,
96505
+ hasPermission as hasPermission23,
96479
96506
  knowledgeContextForAccess as knowledgeContextForAccess2,
96480
96507
  requireAccessGrantAuthorization as requireAccessGrantAuthorization14,
96481
96508
  requireSessionAuthorization as requireSessionAuthorization9,
@@ -96571,7 +96598,7 @@ function registerKnowledgeRoutes(app, deps) {
96571
96598
  c.req.param("workspaceId"),
96572
96599
  write ? "documents:manage" : readPermission === "workspace:read" ? void 0 : readPermission
96573
96600
  );
96574
- const permission = write ? "documents:manage" : readPermission === "workspace:read" && hasPermission22(access.grant.permissions, "documents:search") ? "documents:search" : readPermission;
96601
+ const permission = write ? "documents:manage" : readPermission === "workspace:read" && hasPermission23(access.grant.permissions, "documents:search") ? "documents:search" : readPermission;
96575
96602
  return await withAccessGrantSessionRlsContext(deps, access.grant, async () => {
96576
96603
  const context = await knowledgeContextForAccess2(deps, access, permission);
96577
96604
  c.header("cache-control", "private, no-store");
@@ -96901,7 +96928,7 @@ function registerKnowledgeRoutes(app, deps) {
96901
96928
  throw new HTTPException72(403, { message: "Agents cannot change learning settings" });
96902
96929
  const access = await requireAccessGrantAuthorization14(c, deps, context.workspaceId);
96903
96930
  if (request.source?.kind === "chat") {
96904
- if (!hasPermission22(access.grant.permissions, "sessions:control"))
96931
+ if (!hasPermission23(access.grant.permissions, "sessions:control"))
96905
96932
  throw new HTTPException72(403, { message: "Chat settings require session control" });
96906
96933
  await requireSessionAuthorization9(deps, access.grant, {
96907
96934
  sessionId: request.source.id,
@@ -96910,7 +96937,7 @@ function registerKnowledgeRoutes(app, deps) {
96910
96937
  });
96911
96938
  context.actor.settingsScopes = [request.scope];
96912
96939
  } else if (request.source?.kind === "scheduled_task") {
96913
- if (!hasPermission22(access.grant.permissions, "scheduled_tasks:manage"))
96940
+ if (!hasPermission23(access.grant.permissions, "scheduled_tasks:manage"))
96914
96941
  throw new HTTPException72(403, {
96915
96942
  message: "Scheduled task settings require task management"
96916
96943
  });
@@ -99032,7 +99059,7 @@ import {
99032
99059
  revokeOrganizationMcpConnection,
99033
99060
  updateOrganizationMcpConnectionAccess
99034
99061
  } from "@opengeni/db";
99035
- import { hasPermission as hasPermission23, requireAccessContext as requireAccessContext8 } from "@opengeni/core";
99062
+ import { hasPermission as hasPermission24, requireAccessContext as requireAccessContext8 } from "@opengeni/core";
99036
99063
  import { HTTPException as HTTPException77 } from "hono/http-exception";
99037
99064
  import { z as z49 } from "zod";
99038
99065
  function registerOrganizationMcpConnectionRoutes(app, deps) {
@@ -99117,7 +99144,7 @@ async function requireOrganizationPerson2(c, deps) {
99117
99144
  if (context.mode !== "managed" || !context.subjectId.startsWith("user:") || !grant) {
99118
99145
  throw new HTTPException77(404, { message: "organization not found" });
99119
99146
  }
99120
- return { context, organizationId: organizationId2, admin: hasPermission23(grant.permissions, "account:admin") };
99147
+ return { context, organizationId: organizationId2, admin: hasPermission24(grant.permissions, "account:admin") };
99121
99148
  }
99122
99149
  async function requireConnection(deps, organizationId2, connectionId) {
99123
99150
  if (!z49.string().uuid().safeParse(connectionId).success) {
@@ -99185,7 +99212,7 @@ import {
99185
99212
  revokePersonalApiKey
99186
99213
  } from "@opengeni/db";
99187
99214
  import {
99188
- hasPermission as hasPermission24,
99215
+ hasPermission as hasPermission25,
99189
99216
  PERSONAL_API_KEY_TOKEN_PREFIX,
99190
99217
  requireAccessContext as requireAccessContext9
99191
99218
  } from "@opengeni/core";
@@ -99275,7 +99302,7 @@ async function requireOrganizationPerson3(c, deps, mutation) {
99275
99302
  if (context.mode !== "managed" || !context.subjectId.startsWith("user:") || !grant) {
99276
99303
  throw new HTTPException78(404, { message: "organization not found" });
99277
99304
  }
99278
- return { context, organizationId: organizationId2, admin: hasPermission24(grant.permissions, "account:admin") };
99305
+ return { context, organizationId: organizationId2, admin: hasPermission25(grant.permissions, "account:admin") };
99279
99306
  }
99280
99307
  async function projectKeys(deps, keys2) {
99281
99308
  const userIds = [...new Set(keys2.map((key2) => key2.ownerSubjectId.slice("user:".length)))];
@@ -100633,6 +100660,7 @@ import {
100633
100660
  import {
100634
100661
  requireAccessGrant as requireAccessGrant31,
100635
100662
  requireSessionAuthorization as requireSessionAuthorization13,
100663
+ withSessionAuthorizationReadReuse,
100636
100664
  recordWorkspaceUsage as recordWorkspaceUsage5,
100637
100665
  requireLimit as requireLimit6,
100638
100666
  relayConfigFromSettings as relayConfigFromSettings3,
@@ -102643,7 +102671,7 @@ function registerBrowserSessionRoutes(app, deps, options = {}) {
102643
102671
  fileIds: workspaceFileIds
102644
102672
  });
102645
102673
  const ordered = requireAuthorizedBrowserUploadFiles(workspaceFileIds, files);
102646
- const authorities2 = await Promise.all(
102674
+ const authorities3 = await Promise.all(
102647
102675
  ordered.map(async (file) => {
102648
102676
  const signed = await deps.objectStorage.createGetUrl({
102649
102677
  key: file.objectKey,
@@ -102664,7 +102692,7 @@ function registerBrowserSessionRoutes(app, deps, options = {}) {
102664
102692
  );
102665
102693
  await sessionClient.stageWorkspaceFiles({
102666
102694
  operationId: request.operationId,
102667
- files: authorities2
102695
+ files: authorities3
102668
102696
  });
102669
102697
  }
102670
102698
  }
@@ -104137,6 +104165,7 @@ function registerBrowserSessionRoutes(app, deps, options = {}) {
104137
104165
  operationResourcePolicySupported: enrollment.agentCapabilities.operationResourcePolicy === true,
104138
104166
  operationCpuQuotaSupported: enrollment.agentCapabilities.operationCpuQuota === true,
104139
104167
  transactionalFsWriteSupported: enrollment.agentCapabilities.transactionalFsWrite === true,
104168
+ browserControlHttpSupported: enrollment.agentCapabilities.browserControlHttp === true,
104140
104169
  ...deps.settings.agentOpStreamEnabled === true && enrollment.opStream === true && deps.bus.getOpStreamConnection ? {
104141
104170
  opStream: {
104142
104171
  transport: new NatsOpStreamTransport2(
@@ -104380,6 +104409,22 @@ function registerBrowserSessionRoutes(app, deps, options = {}) {
104380
104409
  });
104381
104410
  }
104382
104411
  async function withActiveBrowserController(context, grant, workspaceId, browserSessionId, authorizationOperation, channelOperation, callback, recoverMissing = true, stages) {
104412
+ return await withSessionAuthorizationReadReuse(
104413
+ (authorizationReads) => withActiveBrowserControllerReads(
104414
+ context,
104415
+ grant,
104416
+ workspaceId,
104417
+ browserSessionId,
104418
+ authorizationOperation,
104419
+ channelOperation,
104420
+ callback,
104421
+ recoverMissing,
104422
+ stages,
104423
+ authorizationReads
104424
+ )
104425
+ );
104426
+ }
104427
+ async function withActiveBrowserControllerReads(context, grant, workspaceId, browserSessionId, authorizationOperation, channelOperation, callback, recoverMissing, stages, authorizationReads) {
104383
104428
  try {
104384
104429
  const record8 = await getBrowserSessionControlRecord(deps.db, {
104385
104430
  accountId: grant.accountId,
@@ -104387,17 +104432,18 @@ function registerBrowserSessionRoutes(app, deps, options = {}) {
104387
104432
  browserSessionId
104388
104433
  });
104389
104434
  stages?.mark("record");
104390
- const sourceAuthorization = await authorizeSourceSession2(
104391
- deps,
104392
- grant,
104393
- record8.sourceSessionId,
104394
- authorizationOperation
104395
- );
104435
+ const sourceSessionNeeded = record8.session.placement?.kind === "connected_machine" || !record8.controllerHostSandboxGroupId;
104436
+ const [authorized, sourceRead] = await Promise.allSettled([
104437
+ authorizeSourceSession2(deps, grant, record8.sourceSessionId, authorizationOperation),
104438
+ sourceSessionNeeded ? requireSourceSession(deps, workspaceId, record8.sourceSessionId) : Promise.resolve(null)
104439
+ ]);
104440
+ if (authorized.status === "rejected") throw authorized.reason;
104441
+ if (sourceRead.status === "rejected") throw sourceRead.reason;
104442
+ const sourceAuthorization = authorized.value;
104396
104443
  stages?.mark("authorize");
104397
- let sourceSession = null;
104444
+ let sourceSession = sourceRead.value;
104398
104445
  if (record8.session.placement?.kind === "connected_machine") {
104399
- sourceSession = await requireSourceSession(deps, workspaceId, record8.sourceSessionId);
104400
- if (sourceSession.activeSandboxId !== record8.session.placement.sandboxId) {
104446
+ if (sourceSession?.activeSandboxId !== record8.session.placement.sandboxId) {
104401
104447
  return await throwBrowserSourcePlacementChanged(
104402
104448
  grant,
104403
104449
  record8.sourceSessionId,
@@ -104424,6 +104470,7 @@ function registerBrowserSessionRoutes(app, deps, options = {}) {
104424
104470
  let controllerTransportFailed = false;
104425
104471
  const controllerRecoveryState = { attempted: false };
104426
104472
  const run2 = async (placement, provisionedClient) => {
104473
+ authorizationReads.handOffToToolDispatch();
104427
104474
  const client = provisionedClient ?? connectController(deps, grant, record8, placement);
104428
104475
  const tokens = (0, browser_controller_authority_exports.deriveBrowserSessionControllerTokens)({
104429
104476
  rootSecret: browserAuthorityRoot(deps),
@@ -106098,9 +106145,10 @@ import {
106098
106145
  touchComputerSessionController
106099
106146
  } from "@opengeni/db";
106100
106147
  import {
106101
- hasPermission as hasPermission25,
106148
+ hasPermission as hasPermission26,
106102
106149
  requireAccessGrant as requireAccessGrant32,
106103
106150
  requireSessionAuthorization as requireSessionAuthorization14,
106151
+ withSessionAuthorizationReadReuse as withSessionAuthorizationReadReuse2,
106104
106152
  relayConfigFromSettings as relayConfigFromSettings4,
106105
106153
  resolveChannelAMachineConnection as resolveChannelAMachineConnection2,
106106
106154
  resolveSessionSandboxRuntime as resolveSessionSandboxRuntime4,
@@ -106823,7 +106871,7 @@ function registerComputerSessionRoutes(app, deps, options = {}) {
106823
106871
  }
106824
106872
  );
106825
106873
  async function authorizeHumanFrameInput(grant, record8, placement) {
106826
- if ((record8.session.placement.kind === "connected_machine" || record8.session.placement.kind === "attached_device") && placement.screenControlAllowed !== true || record8.session.placement.kind === "sandbox_group" && deps.settings.sandboxDesktopInteractive === false || grant.principalKind === "agent_attempt" || !hasPermission25(grant.permissions, "sessions:control"))
106874
+ if ((record8.session.placement.kind === "connected_machine" || record8.session.placement.kind === "attached_device") && placement.screenControlAllowed !== true || record8.session.placement.kind === "sandbox_group" && deps.settings.sandboxDesktopInteractive === false || grant.principalKind === "agent_attempt" || !hasPermission26(grant.permissions, "sessions:control"))
106827
106875
  return false;
106828
106876
  try {
106829
106877
  await requireSessionAuthorization14(deps, grant, {
@@ -106994,6 +107042,32 @@ function registerComputerSessionRoutes(app, deps, options = {}) {
106994
107042
  }
106995
107043
  }
106996
107044
  );
107045
+ async function routedMachineConnection(handle, grant, sourceSession, sandboxId) {
107046
+ const machineAuthority = await handle.machineAuthority();
107047
+ const sandbox = await getSandbox5(
107048
+ deps.db,
107049
+ {
107050
+ accountId: grant.accountId,
107051
+ workspaceId: sourceSession.workspaceId,
107052
+ subjectId: machineAuthority.subjectId
107053
+ },
107054
+ sandboxId
107055
+ );
107056
+ if (sandbox?.kind !== "selfhosted" || !sandbox.enrollmentId) {
107057
+ throw new ComputerSessionStateError("Connected Machine placement is unavailable");
107058
+ }
107059
+ return await resolveChannelAMachineConnection2(
107060
+ deps.db,
107061
+ {
107062
+ accountId: grant.accountId,
107063
+ workspaceId: sourceSession.workspaceId,
107064
+ sessionId: sourceSession.id,
107065
+ machineWorkspaceId: sandbox.workspaceId,
107066
+ enrollmentId: sandbox.enrollmentId
107067
+ },
107068
+ machineAuthority
107069
+ );
107070
+ }
106997
107071
  async function withComputerPlacement(sourceSession, grant, expectedPlacement, expectedPlacementInstanceId, operation, waitSignal, callback) {
106998
107072
  if (expectedPlacement?.kind === "external_provider") {
106999
107073
  throw new BrowserControlUnsupportedError3(
@@ -107041,6 +107115,7 @@ function registerComputerSessionRoutes(app, deps, options = {}) {
107041
107115
  operationResourcePolicySupported: enrollment.agentCapabilities.operationResourcePolicy === true,
107042
107116
  operationCpuQuotaSupported: enrollment.agentCapabilities.operationCpuQuota === true,
107043
107117
  transactionalFsWriteSupported: enrollment.agentCapabilities.transactionalFsWrite === true,
107118
+ browserControlHttpSupported: enrollment.agentCapabilities.browserControlHttp === true,
107044
107119
  ...deps.settings.agentOpStreamEnabled === true && enrollment.opStream === true && deps.bus.getOpStreamConnection ? {
107045
107120
  opStream: {
107046
107121
  transport: new NatsOpStreamTransport3(
@@ -107088,30 +107163,7 @@ function registerComputerSessionRoutes(app, deps, options = {}) {
107088
107163
  const resolved = await handle.routingSession.prime();
107089
107164
  let screenControlAllowed = false;
107090
107165
  if (operation !== "computer.end" && resolved.kind === "selfhosted" && resolved.sandboxId) {
107091
- const machineAuthority = await handle.machineAuthority();
107092
- const sandbox = await getSandbox5(
107093
- deps.db,
107094
- {
107095
- accountId: grant.accountId,
107096
- workspaceId: sourceSession.workspaceId,
107097
- subjectId: machineAuthority.subjectId
107098
- },
107099
- resolved.sandboxId
107100
- );
107101
- if (sandbox?.kind !== "selfhosted" || !sandbox.enrollmentId) {
107102
- throw new ComputerSessionStateError("Connected Machine placement is unavailable");
107103
- }
107104
- const enrollment = await resolveChannelAMachineConnection2(
107105
- deps.db,
107106
- {
107107
- accountId: grant.accountId,
107108
- workspaceId: sourceSession.workspaceId,
107109
- sessionId: sourceSession.id,
107110
- machineWorkspaceId: sandbox.workspaceId,
107111
- enrollmentId: sandbox.enrollmentId
107112
- },
107113
- machineAuthority
107114
- );
107166
+ const enrollment = handle.pinnedMachine?.sandboxId === resolved.sandboxId ? handle.pinnedMachine.enrollment : await routedMachineConnection(handle, grant, sourceSession, resolved.sandboxId);
107115
107167
  if (!enrollment?.connectionInstanceId) {
107116
107168
  throw new ComputerSessionStateError("Connected Machine is unavailable");
107117
107169
  }
@@ -107273,17 +107325,37 @@ function registerComputerSessionRoutes(app, deps, options = {}) {
107273
107325
  });
107274
107326
  }
107275
107327
  async function withActiveComputerController(context, grant, workspaceId, computerSessionId, authorizationOperation, channelOperation, callback, recoverMissing = true) {
107328
+ return await withSessionAuthorizationReadReuse2(
107329
+ (authorizationReads) => withActiveComputerControllerReads(
107330
+ context,
107331
+ grant,
107332
+ workspaceId,
107333
+ computerSessionId,
107334
+ authorizationOperation,
107335
+ channelOperation,
107336
+ callback,
107337
+ recoverMissing,
107338
+ authorizationReads
107339
+ )
107340
+ );
107341
+ }
107342
+ async function withActiveComputerControllerReads(context, grant, workspaceId, computerSessionId, authorizationOperation, channelOperation, callback, recoverMissing, authorizationReads) {
107276
107343
  try {
107277
107344
  const record8 = await getComputerSessionControlRecord2(deps.db, {
107278
107345
  accountId: grant.accountId,
107279
107346
  workspaceId,
107280
107347
  computerSessionId
107281
107348
  });
107282
- await authorizeSourceSession3(deps, grant, record8.sourceSessionId, authorizationOperation);
107283
- let sourceSession = null;
107349
+ const sourceSessionNeeded = record8.session.placement?.kind !== "sandbox_group";
107350
+ const [authorized, sourceRead] = await Promise.allSettled([
107351
+ authorizeSourceSession3(deps, grant, record8.sourceSessionId, authorizationOperation),
107352
+ sourceSessionNeeded ? requireSourceSession2(deps, workspaceId, record8.sourceSessionId) : Promise.resolve(null)
107353
+ ]);
107354
+ if (authorized.status === "rejected") throw authorized.reason;
107355
+ if (sourceRead.status === "rejected") throw sourceRead.reason;
107356
+ let sourceSession = sourceRead.value;
107284
107357
  if (record8.session.placement?.kind === "connected_machine") {
107285
- sourceSession = await requireSourceSession2(deps, workspaceId, record8.sourceSessionId);
107286
- if (sourceSession.activeSandboxId !== record8.session.placement.sandboxId) {
107358
+ if (sourceSession?.activeSandboxId !== record8.session.placement.sandboxId) {
107287
107359
  return await throwComputerSourcePlacementChanged(
107288
107360
  grant,
107289
107361
  record8.sourceSessionId,
@@ -107305,6 +107377,7 @@ function registerComputerSessionRoutes(app, deps, options = {}) {
107305
107377
  throw new ComputerSessionStateError("ComputerSession controller authority changed");
107306
107378
  }
107307
107379
  const run2 = async (placement) => {
107380
+ authorizationReads.handOffToToolDispatch();
107308
107381
  const client = connectController2(grant, record8, placement);
107309
107382
  const tokens = (0, browser_controller_authority_exports.deriveComputerSessionControllerTokens)({
107310
107383
  rootSecret: controllerAuthorityRoot(deps),
@@ -107994,7 +108067,7 @@ import { deleteCookie, setCookie } from "hono/cookie";
107994
108067
  import { HTTPException as HTTPException87 } from "hono/http-exception";
107995
108068
  import {
107996
108069
  githubAppActionPolicyActor,
107997
- hasPermission as hasPermission27,
108070
+ hasPermission as hasPermission28,
107998
108071
  listGitHubActionPolicyActors,
107999
108072
  personalGitHubActionPolicyActor,
108000
108073
  requireAccessGrant as requireAccessGrant33,
@@ -108010,7 +108083,7 @@ import { HTTPException as HTTPException86 } from "hono/http-exception";
108010
108083
  import {
108011
108084
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization12,
108012
108085
  requireConnectOwnerAuthority as requireConnectOwnerAuthority3,
108013
- hasPermission as hasPermission26
108086
+ hasPermission as hasPermission27
108014
108087
  } from "@opengeni/core";
108015
108088
  async function integrationCommitGrant(authorization, permissions, request) {
108016
108089
  const grant = structuredClone(authorization.grant);
@@ -108027,7 +108100,7 @@ async function integrationCommitGrant(authorization, permissions, request) {
108027
108100
  const secret = resolveFirstPartyDelegationSecret6(request.settings);
108028
108101
  const signed = token && secret ? await verifyDelegatedAccessToken2(secret, token) : null;
108029
108102
  if (signed) {
108030
- const matches = (value) => value.accountId === state.accountId && value.workspaceId === state.workspaceId && value.subjectId === state.subjectId && required.every((permission) => hasPermission26(value.permissions, permission));
108103
+ const matches = (value) => value.accountId === state.accountId && value.workspaceId === state.workspaceId && value.subjectId === state.subjectId && required.every((permission) => hasPermission27(value.permissions, permission));
108031
108104
  if (!matches(signed))
108032
108105
  throw new HTTPException86(403, { message: "Integration bearer authority mismatch" });
108033
108106
  return {
@@ -108105,7 +108178,7 @@ function registerGitHubRoutes(app, deps) {
108105
108178
  const installations = missing.length === 0 ? await listWorkspaceGitHubInstallationBindings(deps, grant.workspaceId) : [];
108106
108179
  const status = githubBindingStatus(missing.length === 0, installations);
108107
108180
  const setupMode = settings.productAccessMode === "managed" ? "platform" : "operator";
108108
- const canManage = !externalActorContinuationForAuthorization13(access) && hasPermission27(grant.permissions, "github:manage");
108181
+ const canManage = !externalActorContinuationForAuthorization13(access) && hasPermission28(grant.permissions, "github:manage");
108109
108182
  const returnPath = githubSessionReturnPath(c.req.query("returnPath"), grant.workspaceId);
108110
108183
  const connectState = missing.length === 0 && slug && canManage ? createSignedState13(githubStateSecret, {
108111
108184
  accountId: grant.accountId,
@@ -108899,7 +108972,7 @@ function githubRepositoryBranchesRouteError(error) {
108899
108972
  return new HTTPException87(502, { message: "GitHub branch discovery is unavailable" });
108900
108973
  }
108901
108974
  function requirePublicGitHubRepositoryVerificationPermission(grant) {
108902
- if (hasPermission27(grant.permissions, "sessions:create") || hasPermission27(grant.permissions, "sessions:control")) {
108975
+ if (hasPermission28(grant.permissions, "sessions:create") || hasPermission28(grant.permissions, "sessions:control")) {
108903
108976
  return;
108904
108977
  }
108905
108978
  throw new HTTPException87(403, {
@@ -109774,7 +109847,7 @@ import {
109774
109847
  buildConnectionTokenResolver as buildConnectionTokenResolver8,
109775
109848
  getConnectionMetadata as getConnectionMetadata13,
109776
109849
  getPersonalGitHubRepositorySelectionState as getPersonalGitHubRepositorySelectionState3,
109777
- getSessionAuthorityProjection as getSessionAuthorityProjection2,
109850
+ getSessionAuthorityProjection as getSessionAuthorityProjection3,
109778
109851
  getSessionTurnForAttempt,
109779
109852
  resolveAcceptedConnectionUse
109780
109853
  } from "@opengeni/db";
@@ -109957,7 +110030,7 @@ async function resolveBrokerAuthority(deps, secret, claims, routeId) {
109957
110030
  claims.sessionId,
109958
110031
  claims.attemptId
109959
110032
  );
109960
- const session = await getSessionAuthorityProjection2(
110033
+ const session = await getSessionAuthorityProjection3(
109961
110034
  deps.db,
109962
110035
  claims.workspaceId,
109963
110036
  claims.sessionId
@@ -110297,7 +110370,7 @@ import {
110297
110370
  import { withOrganizationIntegrationPolicyFence as withOrganizationIntegrationPolicyFence8 } from "@opengeni/db/organization-integration-policy";
110298
110371
  import { CORE_INTEGRATION_DEFINITIONS as CORE_INTEGRATION_DEFINITIONS5 } from "@opengeni/capabilities";
110299
110372
  import {
110300
- hasPermission as hasPermission28,
110373
+ hasPermission as hasPermission29,
110301
110374
  requireAccessGrant as requireAccessGrant35,
110302
110375
  requireAccessGrantAuthorization as requireAccessGrantAuthorization20
110303
110376
  } from "@opengeni/core";
@@ -110363,7 +110436,7 @@ function registerIntegrationFacetRoutes(app, deps) {
110363
110436
  facetKey: decoded(c.req.param("facetKey")),
110364
110437
  payload: await c.req.json(),
110365
110438
  canManageOrganizationDestination: authorization.accountGrant?.permissions.includes("account:admin") === true,
110366
- canManageWorkspaceDestination: hasPermission28(
110439
+ canManageWorkspaceDestination: hasPermission29(
110367
110440
  grant.permissions,
110368
110441
  "capabilities:manage"
110369
110442
  ),
@@ -110634,6 +110707,7 @@ import {
110634
110707
  getWorkspaceInteractionRevisionState,
110635
110708
  listSessionEventPage as listSessionEventPage2,
110636
110709
  listWorkspaceControlEvents,
110710
+ getWorkspaceControlEvent,
110637
110711
  readSessionEventStorageGapEnd
110638
110712
  } from "@opengeni/db";
110639
110713
  import {
@@ -111163,7 +111237,8 @@ async function sseWorkspaceControlStream(db, bus, workspaceId, after, signal, op
111163
111237
  }
111164
111238
  }
111165
111239
  }
111166
- await writeFrame(formatWorkspaceControlEventSse(event));
111240
+ const visible = await getWorkspaceControlEvent(db, workspaceId, event.id);
111241
+ if (visible) await writeFrame(formatWorkspaceControlEventSse(visible));
111167
111242
  lastSent = event.sequence;
111168
111243
  };
111169
111244
  delivery = createLatestWinsDelivery(send, fail);
@@ -112384,7 +112459,7 @@ import {
112384
112459
  } from "@opengeni/contracts";
112385
112460
  import {
112386
112461
  automationRequestDigest as automationRequestDigest2,
112387
- hasPermission as hasPermission29,
112462
+ hasPermission as hasPermission30,
112388
112463
  requireAutomationAdapter as requireAutomationAdapter2,
112389
112464
  requireAccessGrantAuthorization as requireAccessGrantAuthorization21,
112390
112465
  externalActorContinuationForAuthorization as externalActorContinuationForAuthorization14,
@@ -113189,7 +113264,7 @@ function registerPrReviewGitHubRoutes(app, deps) {
113189
113264
  grant.accountId,
113190
113265
  workspaceId
113191
113266
  );
113192
- const canManage = !externalActorContinuationForAuthorization14(access) && hasPermission29(grant.permissions, "workspace:admin") && hasPermission29(grant.permissions, "secrets:write");
113267
+ const canManage = !externalActorContinuationForAuthorization14(access) && hasPermission30(grant.permissions, "workspace:admin") && hasPermission30(grant.permissions, "secrets:write");
113193
113268
  const connectState = configured2 && canManage ? createSignedState14(deps.githubStateSecret, {
113194
113269
  accountId: grant.accountId,
113195
113270
  workspaceId,
@@ -113555,7 +113630,7 @@ async function requirePrReviewManageGrant(c, deps, workspaceId, state) {
113555
113630
  return grant;
113556
113631
  }
113557
113632
  function prReviewBrowserGrantClaims(deps, grant) {
113558
- if (deps.settings.productAccessMode !== "configured" || !hasPermission29(grant.permissions, "workspace:admin") || !hasPermission29(grant.permissions, "secrets:write")) {
113633
+ if (deps.settings.productAccessMode !== "configured" || !hasPermission30(grant.permissions, "workspace:admin") || !hasPermission30(grant.permissions, "secrets:write")) {
113559
113634
  return {};
113560
113635
  }
113561
113636
  return {
@@ -115196,7 +115271,7 @@ import {
115196
115271
  SupersedePreferenceRegistryRequest as SupersedePreferenceRegistryRequest2
115197
115272
  } from "@opengeni/contracts";
115198
115273
  import {
115199
- hasPermission as hasPermission30,
115274
+ hasPermission as hasPermission31,
115200
115275
  requireAccessGrant as requireAccessGrant40,
115201
115276
  requireAccessGrantAuthorization as requireAccessGrantAuthorization24
115202
115277
  } from "@opengeni/core";
@@ -115276,7 +115351,7 @@ function authorizePreferenceRegistryScopeMutation(access, scope) {
115276
115351
  }
115277
115352
  return;
115278
115353
  }
115279
- if (scope === "workspace" && !hasPermission30(grant.permissions, "workspace:admin")) {
115354
+ if (scope === "workspace" && !hasPermission31(grant.permissions, "workspace:admin")) {
115280
115355
  throw new HTTPException98(403, { message: "missing permission: workspace:admin" });
115281
115356
  }
115282
115357
  }
@@ -116543,7 +116618,7 @@ function registerScheduledTaskRoutes(app, deps) {
116543
116618
  settings: catalogSettings,
116544
116619
  authorization,
116545
116620
  tasks,
116546
- permissionsRequiredByTools: permissionsRequiredByFirstPartyTools,
116621
+ permissionsRequiredByTools: permissionsRequiredByFirstPartyTools2,
116547
116622
  onError: (error) => {
116548
116623
  deps.observability?.warn("Scheduled task access drift could not be computed", {
116549
116624
  errorClass: error instanceof Error ? error.name : "ScheduledTaskPolicyDriftError",
@@ -116729,7 +116804,7 @@ function registerScheduledTaskRoutes(app, deps) {
116729
116804
  authorization,
116730
116805
  taskId: c.req.param("taskId"),
116731
116806
  request: parsed.data,
116732
- permissionsRequiredByTools: permissionsRequiredByFirstPartyTools,
116807
+ permissionsRequiredByTools: permissionsRequiredByFirstPartyTools2,
116733
116808
  sessionAuthorization: deps.sessionAuthorization,
116734
116809
  authorizationSurface: "http"
116735
116810
  });
@@ -117496,7 +117571,12 @@ import {
117496
117571
  SITE_FRAME_SESSION_CREATE_FIELDS,
117497
117572
  siteFrameBodyRefusal as siteFrameBodyRefusal2
117498
117573
  } from "@opengeni/contracts/site-session-http";
117499
- import { requireWorkspace as requireWorkspace5, scheduledSessionIds } from "@opengeni/db";
117574
+ import {
117575
+ requireWorkspace as requireWorkspace5,
117576
+ scheduledSessionIds,
117577
+ currentSiteViewerRlsContext,
117578
+ nestedPostgresSqlState as nestedPostgresSqlState12
117579
+ } from "@opengeni/db";
117500
117580
  import {
117501
117581
  currentSiteSessionOrigin as currentSiteSessionOrigin4,
117502
117582
  isVerifiedDelegatedHumanAuthorization as isVerifiedDelegatedHumanAuthorization4,
@@ -117988,7 +118068,7 @@ import {
117988
118068
  import { HTTPException as HTTPException105 } from "hono/http-exception";
117989
118069
  import {
117990
118070
  getManagedAuthRequestActorEpoch as getManagedAuthRequestActorEpoch2,
117991
- hasPermission as hasPermission31,
118071
+ hasPermission as hasPermission32,
117992
118072
  requireAccessGrant as requireAccessGrant46,
117993
118073
  requireAccessGrantAuthorization as requireAccessGrantAuthorization29,
117994
118074
  requireFreshAccessGrant as requireFreshAccessGrant3,
@@ -118330,7 +118410,7 @@ function childRequiresActionRespondedByKindForGrant(grant) {
118330
118410
  return "human";
118331
118411
  }
118332
118412
  function requireViewerLifecyclePermission(grant) {
118333
- if (VIEWER_LIFECYCLE_PERMISSIONS.some((permission) => hasPermission31(grant.permissions, permission))) {
118413
+ if (VIEWER_LIFECYCLE_PERMISSIONS.some((permission) => hasPermission32(grant.permissions, permission))) {
118334
118414
  return;
118335
118415
  }
118336
118416
  throw new HTTPException105(403, {
@@ -118596,7 +118676,7 @@ function registerSessionRoutes(app, deps) {
118596
118676
  )
118597
118677
  );
118598
118678
  const siteOrigin = origin ?? currentSiteSessionOrigin4();
118599
- if (siteOrigin && grant.subjectId !== `site:${siteOrigin.siteId}`) {
118679
+ if (siteOrigin && currentSiteViewerRlsContext()?.siteId !== siteOrigin.siteId) {
118600
118680
  const refused4 = siteFrameBodyRefusal2("sessions.create", "/sessions", payload);
118601
118681
  if (refused4)
118602
118682
  return c.json(
@@ -118612,6 +118692,8 @@ function registerSessionRoutes(app, deps) {
118612
118692
  siteId: siteOrigin.siteId,
118613
118693
  versionId: siteOrigin.versionId ?? null
118614
118694
  });
118695
+ if (grant.principalKind !== "agent_attempt")
118696
+ payload.visibility = "private";
118615
118697
  }
118616
118698
  const create = () => createSessionForRequest(deps, grant, workspaceId, payload, authorization);
118617
118699
  session = await measureSessionCreatePhase(
@@ -118849,7 +118931,7 @@ function registerSessionRoutes(app, deps) {
118849
118931
  workspaceId,
118850
118932
  sessionIds: [...page2.pinned, ...page2.sessions].map((session) => session.id)
118851
118933
  });
118852
- const scheduleTargets = hasPermission31(grant.permissions, "scheduled_tasks:run") && hasPermission31(grant.permissions, "sessions:control") ? await scheduledSessionIds(
118934
+ const scheduleTargets = hasPermission32(grant.permissions, "scheduled_tasks:run") && hasPermission32(grant.permissions, "sessions:control") ? await scheduledSessionIds(
118853
118935
  db,
118854
118936
  workspaceId,
118855
118937
  [...page2.pinned, ...page2.sessions].map((session) => session.id)
@@ -119085,7 +119167,7 @@ function registerSessionRoutes(app, deps) {
119085
119167
  workspaceId,
119086
119168
  sessionIds: [sessionId]
119087
119169
  }),
119088
- hasPermission31(grant.permissions, "scheduled_tasks:run") && hasPermission31(grant.permissions, "sessions:control") ? scheduledSessionIds(db, workspaceId, [sessionId]) : Promise.resolve(/* @__PURE__ */ new Set()),
119170
+ hasPermission32(grant.permissions, "scheduled_tasks:run") && hasPermission32(grant.permissions, "sessions:control") ? scheduledSessionIds(db, workspaceId, [sessionId]) : Promise.resolve(/* @__PURE__ */ new Set()),
119089
119171
  loadEffectivePolicyContext(deps, workspaceId, grant.subjectId, [session])
119090
119172
  ]);
119091
119173
  const usageLimit = await sessionUsageLimitForRead(db, session, {
@@ -120156,7 +120238,7 @@ function registerSessionRoutes(app, deps) {
120156
120238
  }
120157
120239
  };
120158
120240
  collect(lineage.children);
120159
- const targets = hasPermission31(grant.permissions, "scheduled_tasks:run") && hasPermission31(grant.permissions, "sessions:control") ? await scheduledSessionIds(db, workspaceId, sessionIds) : /* @__PURE__ */ new Set();
120241
+ const targets = hasPermission32(grant.permissions, "scheduled_tasks:run") && hasPermission32(grant.permissions, "sessions:control") ? await scheduledSessionIds(db, workspaceId, sessionIds) : /* @__PURE__ */ new Set();
120160
120242
  const decorateNodes = (nodes) => nodes.map((node) => ({
120161
120243
  ...node,
120162
120244
  session: { ...node.session, hasSchedules: targets.has(node.session.id) },
@@ -121159,6 +121241,7 @@ function registerSessionRoutes(app, deps) {
121159
121241
  actorEpoch: getManagedAuthRequestActorEpoch2(c.req.raw) ?? void 0,
121160
121242
  reauthorizeAfterMs: authorization?.reauthorizeAfterMs ?? SESSION_AUTHORIZATION_DEFAULT_REAUTHORIZE_MS,
121161
121243
  reauthorize: async () => {
121244
+ await reauthorizeSiteSessionRequest(c.req.raw);
121162
121245
  const freshGrant = await requireFreshAccessGrant3(c, deps, workspaceId, "sessions:read");
121163
121246
  await requireSessionAuthorization16(deps, freshGrant, {
121164
121247
  sessionId,
@@ -122879,7 +122962,7 @@ function sessionTenancyHttpError(error) {
122879
122962
  retryable: false
122880
122963
  });
122881
122964
  }
122882
- if (error instanceof SessionTenancyNotActivatedError2) {
122965
+ if (error instanceof SessionTenancyNotActivatedError2 || nestedPostgresSqlState12(error) === "P0793") {
122883
122966
  return new ApiHttpError(409, {
122884
122967
  code: "conflict",
122885
122968
  message: "Only-me chats are not enabled for this organization.",
@@ -123505,7 +123588,7 @@ function sessionCreateErrorResponse(c, error) {
123505
123588
  403
123506
123589
  );
123507
123590
  }
123508
- if (error instanceof SessionTenancyNotActivatedError2) {
123591
+ if (error instanceof SessionTenancyNotActivatedError2 || nestedPostgresSqlState12(error) === "P0793") {
123509
123592
  return c.json(
123510
123593
  {
123511
123594
  code: "SESSION_TENANCY_NOT_ACTIVATED",
@@ -123622,7 +123705,7 @@ var ARCHIVE_LIVE_WORK_STATUSES = /* @__PURE__ */ new Set([
123622
123705
  async function pauseOwnArchivedWork(deps, grant, workspaceId, session) {
123623
123706
  if (session.createdBy.kind !== "subject" || session.createdBy.subjectId !== grant.subjectId)
123624
123707
  return session;
123625
- if (!hasPermission31(grant.permissions, "sessions:control")) return session;
123708
+ if (!hasPermission32(grant.permissions, "sessions:control")) return session;
123626
123709
  if (session.effectiveControl.directState === "paused") return session;
123627
123710
  const liveWork = ARCHIVE_LIVE_WORK_STATUSES.has(session.status) || session.activeTurnId !== null || Boolean(session.inputWait) || (await getSessionGoal2(deps.db, workspaceId, session.id))?.status === "active";
123628
123711
  if (!liveWork) return session;
@@ -123982,7 +124065,7 @@ import {
123982
124065
  replayWorkspaceGatewayCustomModelCreate,
123983
124066
  replayWorkspaceOpenRouterCustomModelCreate,
123984
124067
  listWorkspacesForSubject as listWorkspacesForSubject3,
123985
- nestedPostgresSqlState as nestedPostgresSqlState13,
124068
+ nestedPostgresSqlState as nestedPostgresSqlState14,
123986
124069
  removeWorkspaceMember,
123987
124070
  requireWorkspace as requireWorkspace6,
123988
124071
  updateWorkspaceSettings,
@@ -124014,7 +124097,7 @@ import {
124014
124097
  getManagedAuthRequestActorEpoch as getManagedAuthRequestActorEpoch3,
124015
124098
  accountScopedApiKeyWorkspaceAuthority as accountScopedApiKeyWorkspaceAuthority5,
124016
124099
  organizationWorkspaceInScope as organizationWorkspaceInScope2,
124017
- hasPermission as hasPermission32,
124100
+ hasPermission as hasPermission33,
124018
124101
  requireAccessContext as requireAccessContext12,
124019
124102
  requireApiKeyDelegationContext,
124020
124103
  requireExplicitPermissionDelegation as requireExplicitPermissionDelegation2,
@@ -124045,7 +124128,7 @@ import {
124045
124128
  // src/workspace-deletion.ts
124046
124129
  import {
124047
124130
  deleteWorkspaceIfQuiescent,
124048
- nestedPostgresSqlState as nestedPostgresSqlState12,
124131
+ nestedPostgresSqlState as nestedPostgresSqlState13,
124049
124132
  safeDatabaseErrorFacts
124050
124133
  } from "@opengeni/db";
124051
124134
  import { HTTPException as HTTPException107 } from "hono/http-exception";
@@ -124138,7 +124221,7 @@ async function deleteWorkspaceForRequest(deps, input) {
124138
124221
  ...observer ? { observer } : {}
124139
124222
  });
124140
124223
  } catch (error) {
124141
- const state = nestedPostgresSqlState12(error);
124224
+ const state = nestedPostgresSqlState13(error);
124142
124225
  if (state === "42501") {
124143
124226
  throw new HTTPException107(403, { message: "organization administration is not authorized" });
124144
124227
  }
@@ -124295,7 +124378,7 @@ function registerWorkspaceRoutes(app, deps) {
124295
124378
  return c.json(externalWorkspaces.map((workspace) => Workspace.parse(workspace)));
124296
124379
  const accountScopedAuthority = accountScopedApiKeyWorkspaceAuthority5(context);
124297
124380
  if (accountScopedAuthority) {
124298
- if (!hasPermission32(accountScopedAuthority.permissions, "workspace:read")) return c.json([]);
124381
+ if (!hasPermission33(accountScopedAuthority.permissions, "workspace:read")) return c.json([]);
124299
124382
  return c.json(
124300
124383
  (await listSharedWorkspacesForAccount2(deps.db, accountScopedAuthority.accountId)).filter(
124301
124384
  (workspace) => organizationWorkspaceInScope2(accountScopedAuthority.workspaceScope, workspace.id)
@@ -124304,7 +124387,7 @@ function registerWorkspaceRoutes(app, deps) {
124304
124387
  }
124305
124388
  const readableWorkspaceIds = [
124306
124389
  ...new Set(
124307
- context.workspaceGrants.filter((grant) => hasPermission32(grant.permissions, "workspace:read")).map((grant) => grant.workspaceId)
124390
+ context.workspaceGrants.filter((grant) => hasPermission33(grant.permissions, "workspace:read")).map((grant) => grant.workspaceId)
124308
124391
  )
124309
124392
  ];
124310
124393
  if (readableWorkspaceIds.length > 0) {
@@ -124495,7 +124578,7 @@ function registerWorkspaceRoutes(app, deps) {
124495
124578
  );
124496
124579
  return c.json(Workspace.parse(workspace));
124497
124580
  } catch (error) {
124498
- if (nestedPostgresSqlState13(error) === "0A000") {
124581
+ if (nestedPostgresSqlState14(error) === "0A000") {
124499
124582
  throw new HTTPException108(409, {
124500
124583
  message: "Memory settings moved to Settings > Agent learning. Refresh the app to change them."
124501
124584
  });
@@ -124745,7 +124828,7 @@ function registerWorkspaceRoutes(app, deps) {
124745
124828
  if (error instanceof WorkspaceGatewayCustomModelLimitError || error instanceof WorkspaceGatewayCustomModelHistoryLimitError) {
124746
124829
  throw new HTTPException108(422, { message: error.message });
124747
124830
  }
124748
- if (nestedPostgresSqlState13(error) === "23505") {
124831
+ if (nestedPostgresSqlState14(error) === "23505") {
124749
124832
  throw new HTTPException108(422, {
124750
124833
  message: "Gateway custom model already exists"
124751
124834
  });
@@ -124874,7 +124957,7 @@ function registerWorkspaceRoutes(app, deps) {
124874
124957
  if (error instanceof WorkspaceOpenRouterCustomModelLimitError || error instanceof WorkspaceOpenRouterCustomModelHistoryLimitError) {
124875
124958
  throw new HTTPException108(422, { message: error.message });
124876
124959
  }
124877
- if (nestedPostgresSqlState13(error) === "23505") {
124960
+ if (nestedPostgresSqlState14(error) === "23505") {
124878
124961
  throw new HTTPException108(422, {
124879
124962
  message: "OpenRouter custom model already exists"
124880
124963
  });
@@ -125006,7 +125089,7 @@ function registerWorkspaceRoutes(app, deps) {
125006
125089
  if (error instanceof WorkspaceOpperCustomModelLimitError || error instanceof WorkspaceOpperCustomModelHistoryLimitError) {
125007
125090
  throw new HTTPException108(422, { message: error.message });
125008
125091
  }
125009
- if (nestedPostgresSqlState13(error) === "23505") {
125092
+ if (nestedPostgresSqlState14(error) === "23505") {
125010
125093
  throw new HTTPException108(422, {
125011
125094
  message: "Opper custom model already exists"
125012
125095
  });
@@ -125494,7 +125577,7 @@ function rethrowWorkspaceMemberCandidateError(error) {
125494
125577
  message: "the workspace must keep at least one administrator"
125495
125578
  });
125496
125579
  }
125497
- const sqlState = nestedPostgresSqlState13(error);
125580
+ const sqlState = nestedPostgresSqlState14(error);
125498
125581
  if (sqlState === "P0002") {
125499
125582
  throw new HTTPException108(404, { message: "workspace not found" });
125500
125583
  }
@@ -125559,7 +125642,7 @@ import {
125559
125642
  getWorkspace as getWorkspace7,
125560
125643
  getWorkspaceUsage,
125561
125644
  grantWorkspaceCredits,
125562
- nestedPostgresSqlState as nestedPostgresSqlState14,
125645
+ nestedPostgresSqlState as nestedPostgresSqlState15,
125563
125646
  setMemberAllowance,
125564
125647
  setWorkspaceAllowance,
125565
125648
  withAccountRls as withAccountRls4,
@@ -125694,7 +125777,7 @@ async function lifecycle2(operation) {
125694
125777
  } catch (error) {
125695
125778
  if (error instanceof UsageAllowanceVersionConflictError)
125696
125779
  throw new HTTPException109(409, { message: error.message });
125697
- const state = nestedPostgresSqlState14(error);
125780
+ const state = nestedPostgresSqlState15(error);
125698
125781
  if (state === "40001" || state === "23505")
125699
125782
  throw new HTTPException109(409, { message: "Allowance version or operation conflicts" });
125700
125783
  if (state === "42501")
@@ -126617,7 +126700,7 @@ import {
126617
126700
  WORKSPACE_STATE_KNOWLEDGE_SAMPLE_LIMIT as WORKSPACE_STATE_KNOWLEDGE_SAMPLE_LIMIT2
126618
126701
  } from "@opengeni/contracts";
126619
126702
  import {
126620
- hasPermission as hasPermission33,
126703
+ hasPermission as hasPermission34,
126621
126704
  requireAccessGrant as requireAccessGrant52,
126622
126705
  requireAccessGrantAuthorization as requireAccessGrantAuthorization33,
126623
126706
  knowledgeContextForAccess as knowledgeContextForAccess3
@@ -127234,7 +127317,7 @@ function registerCompanyBrainRoutes(app, deps) {
127234
127317
  workspaceId,
127235
127318
  accountId: grant.accountId,
127236
127319
  subjectId: grant.subjectId,
127237
- canInspectKnowledge: hasPermission33(grant.permissions, "documents:search"),
127320
+ canInspectKnowledge: hasPermission34(grant.permissions, "documents:search"),
127238
127321
  access
127239
127322
  });
127240
127323
  context.header("cache-control", "private, no-store");
@@ -127253,7 +127336,7 @@ function registerCompanyBrainRoutes(app, deps) {
127253
127336
  workspaceId,
127254
127337
  accountId: grant.accountId,
127255
127338
  subjectId: grant.subjectId,
127256
- canInspectKnowledge: hasPermission33(grant.permissions, "documents:search"),
127339
+ canInspectKnowledge: hasPermission34(grant.permissions, "documents:search"),
127257
127340
  access
127258
127341
  });
127259
127342
  context.header("cache-control", "private, no-store");
@@ -127446,7 +127529,7 @@ import {
127446
127529
  } from "@opengeni/core";
127447
127530
  import {
127448
127531
  availableSlackBotConnectionMetadata as availableSlackBotConnectionMetadata2,
127449
- nestedPostgresSqlState as nestedPostgresSqlState15,
127532
+ nestedPostgresSqlState as nestedPostgresSqlState16,
127450
127533
  readOrganizationSlackBotAccess,
127451
127534
  setOrganizationSlackBotAccess,
127452
127535
  sharedOrganizationSlackBots as sharedOrganizationSlackBots2
@@ -127476,7 +127559,7 @@ function registerSlackBotAccessRoutes(app, deps) {
127476
127559
  )
127477
127560
  );
127478
127561
  } catch (error) {
127479
- if (nestedPostgresSqlState15(error) === "42501")
127562
+ if (nestedPostgresSqlState16(error) === "42501")
127480
127563
  throw new HTTPException115(404, { message: "Local bot installation unavailable" });
127481
127564
  throw error;
127482
127565
  }
@@ -127530,7 +127613,7 @@ function registerSlackBotAccessRoutes(app, deps) {
127530
127613
  return context.json(OpenGeniSlackBotOrganizationAccess.parse(result2));
127531
127614
  } catch (error) {
127532
127615
  if (error instanceof HTTPException115) throw error;
127533
- if (nestedPostgresSqlState15(error) === "42501")
127616
+ if (nestedPostgresSqlState16(error) === "42501")
127534
127617
  throw new HTTPException115(403, {
127535
127618
  message: "Organization administrator and a verified local bot installation required"
127536
127619
  });
@@ -127546,7 +127629,7 @@ import {
127546
127629
  WorkspaceStateResponse as WorkspaceStateResponse2
127547
127630
  } from "@opengeni/contracts";
127548
127631
  import {
127549
- hasPermission as hasPermission34,
127632
+ hasPermission as hasPermission35,
127550
127633
  requireAccessGrantAuthorization as requireAccessGrantAuthorization35,
127551
127634
  knowledgeContextForAccess as knowledgeContextForAccess4
127552
127635
  } from "@opengeni/core";
@@ -127605,7 +127688,7 @@ async function readWorkspaceState(deps, input) {
127605
127688
  const { workspaceId, query, access } = input;
127606
127689
  const { grant } = access;
127607
127690
  const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
127608
- const canInspectKnowledge = hasPermission34(grant.permissions, "documents:search");
127691
+ const canInspectKnowledge = hasPermission35(grant.permissions, "documents:search");
127609
127692
  const [workspace, policies, knowledge, currentPreferences, acceptedAttempt] = await Promise.all([
127610
127693
  getWorkspace9(deps.db, workspaceId),
127611
127694
  listWorkspaceInstructionPolicyRevisions3(deps.db, workspaceId, { limit: 1 }),
@@ -127732,7 +127815,7 @@ import {
127732
127815
  getWorkspaceArtifact as getWorkspaceArtifact3,
127733
127816
  getWorkspaceArtifactContentRef as getWorkspaceArtifactContentRef4,
127734
127817
  listWorkspaceArtifacts as listWorkspaceArtifacts2,
127735
- nestedPostgresSqlState as nestedPostgresSqlState16,
127818
+ nestedPostgresSqlState as nestedPostgresSqlState17,
127736
127819
  publishWorkspaceArtifactVersion as publishWorkspaceArtifactVersion2,
127737
127820
  rollbackWorkspaceArtifact as rollbackWorkspaceArtifact2,
127738
127821
  setWorkspaceArtifactStatus as setWorkspaceArtifactStatus2,
@@ -127784,7 +127867,7 @@ function workspaceArtifactErrorResponse(context, error) {
127784
127867
  422
127785
127868
  );
127786
127869
  }
127787
- if (nestedPostgresSqlState16(error) === "23505") {
127870
+ if (nestedPostgresSqlState17(error) === "23505") {
127788
127871
  return context.json(
127789
127872
  {
127790
127873
  code: "WORKSPACE_ARTIFACT_CONFLICT",
@@ -128685,6 +128768,9 @@ function registerSitePublishingRoutes(app, deps) {
128685
128768
  // src/routes/site-runtime.ts
128686
128769
  import { createHash as createHash37, randomBytes as randomBytes15, randomUUID as randomUUID16, timingSafeEqual as timingSafeEqual5 } from "crypto";
128687
128770
  import {
128771
+ ReasoningEffort,
128772
+ LatencyMode,
128773
+ permissionsRequiredByFirstPartyTools as permissionsRequiredByFirstPartyTools4,
128688
128774
  DeleteSessionQueueItemRequest as DeleteSessionQueueItemRequest3,
128689
128775
  EditSessionQueueItemRequest as EditSessionQueueItemRequest3,
128690
128776
  matchSiteOperation,
@@ -128709,17 +128795,19 @@ import {
128709
128795
  ToolGatewayInvokeRequest
128710
128796
  } from "@opengeni/contracts";
128711
128797
  import {
128798
+ cancelPublishedSiteSession,
128712
128799
  withHostSessionUsageLimit,
128713
128800
  withSiteSessionOrigin as withSiteSessionOrigin6,
128714
128801
  admissibleWorkspaceModel as admissibleWorkspaceModel2,
128715
128802
  loadWorkspaceModelSelectionInput as loadWorkspaceModelSelectionInput2,
128716
128803
  resolveWorkspaceModelSelection as resolveWorkspaceModelSelection4,
128717
- hasPermission as hasPermission35
128804
+ hasPermission as hasPermission36
128718
128805
  } from "@opengeni/core";
128719
128806
  import {
128720
128807
  consumeSiteAuthCode,
128721
128808
  finishSiteRuntimeAdmission,
128722
128809
  withSiteRuntimeAdmission,
128810
+ withSiteViewerRlsContext,
128723
128811
  createSiteAbuseReport,
128724
128812
  getSiteWorkspaceMemberPermissions,
128725
128813
  readSitePlatformUsage as readSitePlatformUsage2,
@@ -128742,13 +128830,16 @@ import {
128742
128830
  } from "@opengeni/db";
128743
128831
 
128744
128832
  // src/site-publishing/agent-session.ts
128745
- import { resolveAgentConfig } from "@opengeni/contracts";
128833
+ import {
128834
+ permissionsRequiredByFirstPartyTools as permissionsRequiredByFirstPartyTools3,
128835
+ resolveAgentConfig
128836
+ } from "@opengeni/contracts";
128746
128837
  import { agentConfigDeploymentPolicy as agentConfigDeploymentPolicy2, resolveFirstPartyMcpToolPolicy as resolveFirstPartyMcpToolPolicy3 } from "@opengeni/config";
128747
128838
  import { siteSessionOriginFromMetadata as siteSessionOriginFromMetadata2 } from "@opengeni/core";
128748
128839
  import { appendSessionEventsWithLockedSessionUpdate, getSiteSqlDatabase as getSiteSqlDatabase3 } from "@opengeni/db";
128749
128840
  import { publishDurableSessionEvents as publishDurableSessionEvents5 } from "@opengeni/events";
128750
- var SITE_AGENT_DEFAULTS_VERSION = 1;
128751
- async function normalizeSiteAgentSession(deps, host, viewer, sessionId, retainedToolIds) {
128841
+ var SITE_AGENT_DEFAULTS_VERSION = 2;
128842
+ async function normalizeSiteAgentSession(deps, host, viewer, sessionId, retainedToolIds, memberPermissions) {
128752
128843
  const data = await resolveSiteAgentDataContext(deps, host.scope, sessionId);
128753
128844
  if (data.kind !== "site" || data.siteId !== host.site.id || data.viewer.principal !== viewer.principal)
128754
128845
  throw sitePublishingError(
@@ -128761,8 +128852,10 @@ async function normalizeSiteAgentSession(deps, host, viewer, sessionId, retained
128761
128852
  const dataTools = siteAgentDataToolNames({
128762
128853
  viewerKind: viewer.kind,
128763
128854
  siteSql: sqlEnabled,
128764
- allowed: resolveFirstPartyMcpToolPolicy3(deps.settings).allowed
128855
+ allowed: resolveFirstPartyMcpToolPolicy3(deps.settings).allowed,
128856
+ ...memberPermissions === void 0 ? {} : { memberPermissions }
128765
128857
  });
128858
+ const dataToolPermissions = permissionsRequiredByFirstPartyTools3(dataTools);
128766
128859
  const config = resolveAgentConfig({
128767
128860
  creator: "api",
128768
128861
  request: {
@@ -128788,7 +128881,7 @@ async function normalizeSiteAgentSession(deps, host, viewer, sessionId, retained
128788
128881
  host.scope.workspaceId,
128789
128882
  sessionId,
128790
128883
  (session) => {
128791
- if (session.parentSessionId || session.createdBy.subjectId !== `site:${host.site.id}` || siteSessionOriginFromMetadata2(session.metadata)?.siteId !== host.site.id)
128884
+ if (session.parentSessionId || session.createdBy.subjectId !== `site:${host.site.id}` && !(viewer.kind === "member" && session.createdBy.kind === "subject" && session.createdBy.subjectId === viewer.subjectId) || siteSessionOriginFromMetadata2(session.metadata)?.siteId !== host.site.id)
128792
128885
  throw sitePublishingError(
128793
128886
  403,
128794
128887
  "forbidden",
@@ -128797,7 +128890,8 @@ async function normalizeSiteAgentSession(deps, host, viewer, sessionId, retained
128797
128890
  );
128798
128891
  const raw = session.metadata.opengeniPublishedSite;
128799
128892
  const stamp = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
128800
- if (stamp.agentDefaultsVersion === SITE_AGENT_DEFAULTS_VERSION) return { events: [] };
128893
+ if (stamp.agentDefaultsVersion === SITE_AGENT_DEFAULTS_VERSION && session.firstPartyMcpTools.join(",") === dataTools.join(",") && session.firstPartyMcpPermissions?.join(",") === dataToolPermissions.join(","))
128894
+ return { events: [] };
128801
128895
  const allowed2 = /* @__PURE__ */ new Set(["opengeni", ...retainedToolIds]);
128802
128896
  const tools = session.tools.filter((tool) => allowed2.has(tool.id));
128803
128897
  const toolPolicy = {
@@ -128824,7 +128918,7 @@ async function normalizeSiteAgentSession(deps, host, viewer, sessionId, retained
128824
128918
  ],
128825
128919
  update: {
128826
128920
  firstPartyMcpTools: dataTools,
128827
- firstPartyMcpPermissions: [...SITE_AGENT_DATA_TOOL_PERMISSIONS],
128921
+ firstPartyMcpPermissions: dataToolPermissions,
128828
128922
  agentConfig: config,
128829
128923
  instructions,
128830
128924
  tools,
@@ -129342,7 +129436,10 @@ var VersionId = z66.string().uuid();
129342
129436
  var ClientEventId = z66.string().min(1).max(200).optional();
129343
129437
  var CreateConversationRequest = z66.object({
129344
129438
  initialMessage: z66.string().trim().min(1).max(MESSAGE_MAX_CHARS),
129345
- idempotencyKey: z66.string().min(1).max(200).optional()
129439
+ idempotencyKey: z66.string().min(1).max(200).optional(),
129440
+ model: z66.string().min(1).optional(),
129441
+ reasoningEffort: ReasoningEffort.optional(),
129442
+ latencyMode: LatencyMode.optional()
129346
129443
  }).passthrough();
129347
129444
  var SendMessageRequest = z66.object({
129348
129445
  type: z66.literal("user.message"),
@@ -129531,7 +129628,7 @@ function idempotentSessionId(seed) {
129531
129628
  }
129532
129629
  function registerSiteRuntimeRoutes(app, deps) {
129533
129630
  const dispatch = async (request) => await app.fetch(markLocalInternalDispatch(request));
129534
- setSitePublishingDispatch(deps.settings, dispatch);
129631
+ setSitePublishingCancellation(deps.settings, (input) => cancelPublishedSiteSession(deps, input));
129535
129632
  const handler = async (context) => {
129536
129633
  const domain = configuredSitesDomain(deps.settings);
129537
129634
  if (!domain || !deps.settings.sitesGatewaySecret)
@@ -129919,7 +130016,7 @@ function registerSiteRuntimeRoutes(app, deps) {
129919
130016
  agent = choice !== null && choice.kind !== "unavailable";
129920
130017
  }
129921
130018
  const version2 = host.site.currentVersionId ? await getPublishedSiteVersion6(deps.db, host.scope, host.site.id, host.site.currentVersionId) : null;
129922
- const workspaceTools = base.workspaceTools && (version2?.requestedTools.length ?? 0) > 0 && viewer.subjectId !== null && viewer.subjectId !== void 0 && hasPermission35(
130019
+ const workspaceTools = base.workspaceTools && (version2?.requestedTools.length ?? 0) > 0 && viewer.subjectId !== null && viewer.subjectId !== void 0 && hasPermission36(
129923
130020
  await getSiteWorkspaceMemberPermissions(deps.db, host.scope, viewer.subjectId) ?? [],
129924
130021
  "workspace:read"
129925
130022
  );
@@ -130125,18 +130222,32 @@ function registerSiteRuntimeRoutes(app, deps) {
130125
130222
  const { context, url } = request;
130126
130223
  const base = `/v1/workspaces/${host.scope.workspaceId}/sessions`;
130127
130224
  const siteOrigin = { siteId: host.site.id, title: host.site.title, versionId: host.versionId };
130225
+ const reauthorizeViewer = async () => {
130226
+ const liveHost = await requireServedSiteRuntimeHost(deps, host.domain, request.fields.host);
130227
+ const liveViewer = await resolveSiteRuntimeViewer(deps, liveHost, request.fields);
130228
+ if (liveHost.site.id !== host.site.id || liveViewer.principal !== viewer.principal || liveViewer.kind !== viewer.kind || liveViewer.sessionId !== viewer.sessionId)
130229
+ throw siteNotAvailableForViewer(
130230
+ "agent",
130231
+ "This conversation is no longer available to this viewer"
130232
+ );
130233
+ };
130128
130234
  let pendingAdmission;
130129
130235
  const send = async (method, path, body5, extraPermissions) => {
130130
- const execute = () => withSiteSessionOrigin6(
130131
- siteOrigin,
130132
- async () => dispatch(
130133
- await siteRuntimeSessionRequest(deps, host, viewer, {
130134
- origin: url.origin,
130135
- method,
130136
- path,
130137
- ...body5 === void 0 ? {} : { body: body5 },
130138
- ...extraPermissions ? { extraPermissions } : {}
130139
- })
130236
+ await reauthorizeViewer();
130237
+ const execute = () => withSiteViewerRlsContext(
130238
+ { siteId: host.site.id, principal: viewer.principal },
130239
+ () => withSiteSessionOrigin6(
130240
+ siteOrigin,
130241
+ async () => dispatch(
130242
+ await siteRuntimeSessionRequest(deps, host, viewer, {
130243
+ origin: url.origin,
130244
+ method,
130245
+ path,
130246
+ reauthorize: reauthorizeViewer,
130247
+ ...body5 === void 0 ? {} : { body: body5 },
130248
+ ...extraPermissions ? { extraPermissions } : {}
130249
+ })
130250
+ )
130140
130251
  )
130141
130252
  );
130142
130253
  const pending2 = pendingAdmission;
@@ -130200,6 +130311,11 @@ function registerSiteRuntimeRoutes(app, deps) {
130200
130311
  if (viewer.kind === "guest" || viewer.kind === "user")
130201
130312
  await requireSitePlatformOpen(deps, "guest_agent");
130202
130313
  const models = await siteViewerModels(host, viewer, limits);
130314
+ if (input.model && !models.allowed.includes(input.model))
130315
+ throw siteNotAvailableForViewer(
130316
+ "agent_model",
130317
+ "This model is not available to you on this Site"
130318
+ );
130203
130319
  if (models.unavailable)
130204
130320
  throw siteNotAvailableForViewer(
130205
130321
  "agent_model",
@@ -130248,6 +130364,11 @@ ${input.idempotencyKey}`) : randomUUID16();
130248
130364
  }
130249
130365
  }
130250
130366
  }
130367
+ if (!repair && viewer.kind !== "member" && deps.settings.privacyOnlyMeAllowed === false)
130368
+ throw siteNotAvailableForViewer(
130369
+ "private_conversations",
130370
+ "Private Site conversations are disabled by this deployment"
130371
+ );
130251
130372
  for (const conversation2 of await listOwnedSiteRuntimeConversations(deps.db, host.scope, {
130252
130373
  siteId: host.site.id,
130253
130374
  viewerPrincipal: viewer.principal,
@@ -130286,8 +130407,10 @@ ${input.idempotencyKey}`) : randomUUID16();
130286
130407
  deps,
130287
130408
  host.scope,
130288
130409
  host.site.id,
130289
- viewer.kind
130410
+ viewer.kind,
130411
+ viewer.kind === "member" ? memberPermissions ?? [] : void 0
130290
130412
  );
130413
+ const dataToolPermissions = permissionsRequiredByFirstPartyTools4(dataTools);
130291
130414
  const admissionId = randomUUID16();
130292
130415
  const reservation = await reserve(
130293
130416
  () => repair ? reserveSiteRuntimeConversationWork(deps.db, host.scope, {
@@ -130316,13 +130439,14 @@ ${input.idempotencyKey}`) : randomUUID16();
130316
130439
  const body5 = {
130317
130440
  initialMessage: input.initialMessage,
130318
130441
  requestedSessionId,
130442
+ ...viewer.kind === "member" ? { visibility: "private" } : {},
130319
130443
  startMode: "standard",
130320
130444
  agentAccess: "session",
130321
130445
  memoryScope: "off",
130322
130446
  rigId: null,
130323
130447
  // Only this Site's data tools; never management or workspace tools.
130324
130448
  firstPartyMcpTools: dataTools,
130325
- ...dataTools.length > 0 ? { firstPartyMcpPermissions: [...SITE_AGENT_DATA_TOOL_PERMISSIONS] } : {},
130449
+ ...dataTools.length > 0 ? { firstPartyMcpPermissions: dataToolPermissions } : {},
130326
130450
  agent: {
130327
130451
  capabilities: {
130328
130452
  from: "none",
@@ -130334,7 +130458,9 @@ ${input.idempotencyKey}`) : randomUUID16();
130334
130458
  // No sandbox: a Site's agent answers from the page and the Site's
130335
130459
  // data, with no shell or workspace files.
130336
130460
  sandboxBackend: "none",
130337
- ...repair ? { model: repair.model } : models.default ? { model: models.default } : {},
130461
+ ...repair ? { model: repair.model } : input.model || models.default ? { model: input.model ?? models.default } : {},
130462
+ ...input.reasoningEffort === void 0 ? {} : { reasoningEffort: input.reasoningEffort },
130463
+ ...input.latencyMode === void 0 ? {} : { latencyMode: input.latencyMode },
130338
130464
  instructions: siteAgentInstructions(host, viewer, dataTools, agent.instructions),
130339
130465
  // Always explicit: an empty list means no workspace tools at all.
130340
130466
  tools: mcpTools,
@@ -130348,7 +130474,7 @@ ${input.idempotencyKey}`) : randomUUID16();
130348
130474
  },
130349
130475
  ...input.idempotencyKey ? { idempotencyKey: `site-runtime:${requestedSessionId}` } : {}
130350
130476
  };
130351
- const start = () => send("POST", base, body5, dataTools.length > 0 ? SITE_AGENT_DATA_TOOL_PERMISSIONS : []);
130477
+ const start = () => send("POST", base, body5, dataToolPermissions);
130352
130478
  const usageLimitMicros = viewer.kind === "member" || repair ? null : reservation.executionLimitMicros;
130353
130479
  let created;
130354
130480
  try {
@@ -130462,7 +130588,8 @@ ${input.idempotencyKey}`) : randomUUID16();
130462
130588
  host,
130463
130589
  viewer,
130464
130590
  conversation.sessionId,
130465
- conversation.toolIds
130591
+ conversation.toolIds,
130592
+ viewer.kind === "member" ? memberPermissions ?? [] : void 0
130466
130593
  );
130467
130594
  const usage = await settleSiteRuntimeSpend(deps, host, conversation);
130468
130595
  if (viewer.kind === "member" && conversation.limitMicros !== null)
@@ -130687,7 +130814,7 @@ import {
130687
130814
  editableArtifactScope as editableArtifactScope2,
130688
130815
  fileOwnerContextForAccess as fileOwnerContextForAccess5,
130689
130816
  grantHasAgentAttemptAuthority as grantHasAgentAttemptAuthority5,
130690
- hasPermission as hasPermission36,
130817
+ hasPermission as hasPermission37,
130691
130818
  requireAccessGrantAuthorization as requireAccessGrantAuthorization37,
130692
130819
  requireLiveAgentAttemptAuthorization as requireLiveAgentAttemptAuthorization8,
130693
130820
  requireSessionAuthorization as requireSessionAuthorization18,
@@ -130698,10 +130825,10 @@ import {
130698
130825
  import {
130699
130826
  getFilesForSubject as getFilesForSubject3,
130700
130827
  getGeneratedImageArtifact as getGeneratedImageArtifact2,
130701
- getSessionAuthorityProjection as getSessionAuthorityProjection3,
130828
+ getSessionAuthorityProjection as getSessionAuthorityProjection4,
130702
130829
  isWorkspaceArtifactVisible,
130703
130830
  listArtifactCatalogCandidates,
130704
- nestedPostgresSqlState as nestedPostgresSqlState17,
130831
+ nestedPostgresSqlState as nestedPostgresSqlState18,
130705
130832
  updateArtifactPin,
130706
130833
  withSessionRlsActorContext as withSessionRlsActorContext10
130707
130834
  } from "@opengeni/db";
@@ -130782,7 +130909,7 @@ function registerArtifactCatalogRoutes(app, deps) {
130782
130909
  "artifacts:publish"
130783
130910
  );
130784
130911
  const grant = authorization.grant;
130785
- if (!hasPermission36(grant.permissions, "artifacts:publish"))
130912
+ if (!hasPermission37(grant.permissions, "artifacts:publish"))
130786
130913
  throw new HTTPException119(403, { message: "Artifact publish access required" });
130787
130914
  const kind = ArtifactCatalogKind3.safeParse(context.req.param("kind"));
130788
130915
  const body5 = UpdateArtifactPinRequest.safeParse(await context.req.json().catch(() => null));
@@ -130791,7 +130918,7 @@ function registerArtifactCatalogRoutes(app, deps) {
130791
130918
  throw new HTTPException119(422, { message: "Invalid artifact pin request" });
130792
130919
  const artifactId2 = editableKinds.has(kind.data) ? requestedId : requestedId.toLowerCase();
130793
130920
  const fileKind = kind.data === "file" || kind.data === "image";
130794
- if (!hasPermission36(grant.permissions, fileKind ? "files:read" : "artifacts:read"))
130921
+ if (!hasPermission37(grant.permissions, fileKind ? "files:read" : "artifacts:read"))
130795
130922
  throw new HTTPException119(403, { message: "Artifact read access required" });
130796
130923
  const actor = fileKind ? await fileOwnerContextForAccess5(deps, authorization, "files:read") : { subjectId: grant.subjectId, privateFileOwnerSubjectId: null };
130797
130924
  context.header("cache-control", "private, no-store");
@@ -130843,7 +130970,7 @@ function registerArtifactCatalogRoutes(app, deps) {
130843
130970
  }
130844
130971
  );
130845
130972
  } catch (error) {
130846
- if (nestedPostgresSqlState17(error) === "42501")
130973
+ if (nestedPostgresSqlState18(error) === "42501")
130847
130974
  throw new HTTPException119(404, { message: "Artifact not found" });
130848
130975
  throw error;
130849
130976
  }
@@ -130860,8 +130987,8 @@ function registerArtifactCatalogRoutes(app, deps) {
130860
130987
  if (!parsed.success)
130861
130988
  throw new HTTPException119(422, { message: "Invalid artifact catalog query" });
130862
130989
  const query = parsed.data;
130863
- const artifactsAllowed = hasPermission36(grant.permissions, "artifacts:read");
130864
- const filesAllowed = hasPermission36(grant.permissions, "files:read");
130990
+ const artifactsAllowed = hasPermission37(grant.permissions, "artifacts:read");
130991
+ const filesAllowed = hasPermission37(grant.permissions, "files:read");
130865
130992
  if (!artifactsAllowed && !filesAllowed)
130866
130993
  throw new HTTPException119(403, { message: "Artifact catalog read access required" });
130867
130994
  let kinds = ArtifactCatalogKind3.options.filter(
@@ -130889,7 +131016,7 @@ function registerArtifactCatalogRoutes(app, deps) {
130889
131016
  }
130890
131017
  const sourceDecisions = /* @__PURE__ */ new Map();
130891
131018
  const canReadSession = async (sessionId) => {
130892
- if (!hasPermission36(grant.permissions, "sessions:read")) return false;
131019
+ if (!hasPermission37(grant.permissions, "sessions:read")) return false;
130893
131020
  if (sourceDecisions.has(sessionId)) return sourceDecisions.get(sessionId);
130894
131021
  try {
130895
131022
  await requireSessionAuthorization18(deps, grant, {
@@ -130897,7 +131024,7 @@ function registerArtifactCatalogRoutes(app, deps) {
130897
131024
  operation: "session.read",
130898
131025
  surface: "http"
130899
131026
  });
130900
- if (!await getSessionAuthorityProjection3(deps.db, workspaceId, sessionId)) {
131027
+ if (!await getSessionAuthorityProjection4(deps.db, workspaceId, sessionId)) {
130901
131028
  sourceDecisions.set(sessionId, false);
130902
131029
  return false;
130903
131030
  }
@@ -131176,6 +131303,8 @@ function registerInsightsRoutes(app, deps) {
131176
131303
  import {
131177
131304
  InsightsCallsResponse,
131178
131305
  InsightsUsageResponse,
131306
+ InsightsSiteUsageQuery,
131307
+ InsightsSiteUsageResponse,
131179
131308
  OrganizationInsightsCallsQuery,
131180
131309
  OrganizationInsightsUsageQuery,
131181
131310
  WorkspaceInsightsCallsQuery,
@@ -131184,10 +131313,12 @@ import {
131184
131313
  import {
131185
131314
  accountScopedApiKeyWorkspaceAuthority as accountScopedApiKeyWorkspaceAuthority7,
131186
131315
  getInsightsUsage,
131187
- hasPermission as hasPermission37,
131316
+ getInsightsSiteUsage,
131317
+ hasPermission as hasPermission38,
131188
131318
  listInsightsCalls,
131189
131319
  requireAccessContext as requireAccessContext15,
131190
- requireAccessGrant as requireAccessGrant58
131320
+ requireAccessGrant as requireAccessGrant58,
131321
+ siteViewerForGrant as siteViewerForGrant10
131191
131322
  } from "@opengeni/core";
131192
131323
  import {
131193
131324
  currentSessionRlsActorIdentityKey as currentSessionRlsActorIdentityKey2,
@@ -131325,7 +131456,7 @@ function insightsUsageCoalesceKey(scope, query, actor) {
131325
131456
  function organizationInsightsScope(context, accountId) {
131326
131457
  const authority = accountScopedApiKeyWorkspaceAuthority7(context);
131327
131458
  if (authority?.accountId === accountId) {
131328
- const readable = hasPermission37(
131459
+ const readable = hasPermission38(
131329
131460
  authority.permissions,
131330
131461
  "sessions:read",
131331
131462
  authority.permissionMode
@@ -131343,7 +131474,7 @@ function organizationInsightsScope(context, accountId) {
131343
131474
  detailsWorkspaceIds: [
131344
131475
  ...new Set(
131345
131476
  context.workspaceGrants.filter(
131346
- (grant) => grant.accountId === accountId && grant.subjectId === context.subjectId && hasPermission37(grant.permissions, "sessions:read", grant.permissionMode)
131477
+ (grant) => grant.accountId === accountId && grant.subjectId === context.subjectId && hasPermission38(grant.permissions, "sessions:read", grant.permissionMode)
131347
131478
  ).map((grant) => grant.workspaceId)
131348
131479
  )
131349
131480
  ].sort(),
@@ -131389,6 +131520,23 @@ function registerInsightsUsageRoutes(app, deps) {
131389
131520
  return response;
131390
131521
  });
131391
131522
  }
131523
+ app.get("/v1/workspaces/:workspaceId/insights/sites", async (c) => {
131524
+ const workspaceId = c.req.param("workspaceId");
131525
+ const grant = await requireAccessGrant58(c, deps, workspaceId, "workspace:admin");
131526
+ const query = InsightsSiteUsageQuery.safeParse(insightsQueryParameters(c.req.queries()));
131527
+ if (!query.success) throw new HTTPException122(400, { message: "invalid Site Insights query" });
131528
+ const viewer = await siteViewerForGrant10(deps.db, grant);
131529
+ const response = await insightsWithFriendlyTimeout(
131530
+ () => getInsightsSiteUsage(deps.db, {
131531
+ accountId: grant.accountId,
131532
+ workspaceId,
131533
+ query: query.data,
131534
+ viewerSubjectId: viewer.subjectId
131535
+ })
131536
+ );
131537
+ c.header("cache-control", "private, no-store");
131538
+ return c.json(InsightsSiteUsageResponse.parse(response));
131539
+ });
131392
131540
  app.get("/v1/workspaces/:workspaceId/insights/usage", async (c) => {
131393
131541
  const workspaceId = c.req.param("workspaceId");
131394
131542
  const grant = await requireAccessGrant58(c, deps, workspaceId, "workspace:admin");
@@ -131400,7 +131548,7 @@ function registerInsightsUsageRoutes(app, deps) {
131400
131548
  const scope = {
131401
131549
  accountId: grant.accountId,
131402
131550
  workspaceId,
131403
- detailsWorkspaceIds: hasPermission37(grant.permissions, "sessions:read", grant.permissionMode) ? [workspaceId] : []
131551
+ detailsWorkspaceIds: hasPermission38(grant.permissions, "sessions:read", grant.permissionMode) ? [workspaceId] : []
131404
131552
  };
131405
131553
  const response = await cached(
131406
131554
  c,
@@ -131426,7 +131574,7 @@ function registerInsightsUsageRoutes(app, deps) {
131426
131574
  const scope = {
131427
131575
  accountId: grant.accountId,
131428
131576
  workspaceId,
131429
- detailsWorkspaceIds: hasPermission37(grant.permissions, "sessions:read", grant.permissionMode) ? [workspaceId] : []
131577
+ detailsWorkspaceIds: hasPermission38(grant.permissions, "sessions:read", grant.permissionMode) ? [workspaceId] : []
131430
131578
  };
131431
131579
  const response = await cached(
131432
131580
  c,
@@ -132674,7 +132822,7 @@ import {
132674
132822
  } from "@opengeni/core";
132675
132823
 
132676
132824
  // src/model-calls/chat-completions.ts
132677
- import { ReasoningEffort } from "@opengeni/contracts";
132825
+ import { ReasoningEffort as ReasoningEffort2 } from "@opengeni/contracts";
132678
132826
  import { ModelCallError } from "@opengeni/core";
132679
132827
  import {
132680
132828
  normalizeModelCallUsage
@@ -132715,7 +132863,7 @@ var ChatCompletionRequest = z69.object({
132715
132863
  temperature: z69.number().min(0).max(2).nullish(),
132716
132864
  top_p: z69.number().min(0).max(1).nullish(),
132717
132865
  stop: z69.union([z69.string(), z69.array(z69.string()).max(4)]).nullish(),
132718
- reasoning_effort: ReasoningEffort.nullish(),
132866
+ reasoning_effort: ReasoningEffort2.nullish(),
132719
132867
  verbosity: z69.enum(["low", "medium", "high"]).nullish(),
132720
132868
  response_format: z69.object({ type: z69.string() }).passthrough().nullish(),
132721
132869
  stream: z69.boolean().nullish(),
@@ -133784,7 +133932,7 @@ import {
133784
133932
  requireSessionAuthorization as requireSessionAuthorization19,
133785
133933
  SessionAuthorizationDeniedError as SessionAuthorizationDeniedError18,
133786
133934
  SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError16,
133787
- siteViewerForGrant as siteViewerForGrant10
133935
+ siteViewerForGrant as siteViewerForGrant11
133788
133936
  } from "@opengeni/core";
133789
133937
  import {
133790
133938
  getGeneratedImageArtifact as getGeneratedImageArtifact3,
@@ -133838,7 +133986,7 @@ function registerSessionArtifactAssociationRoutes(app, deps) {
133838
133986
  ) : await hasWorkspaceArtifactSessionLink(
133839
133987
  deps.db,
133840
133988
  workspaceId,
133841
- await siteViewerForGrant10(deps.db, grant),
133989
+ await siteViewerForGrant11(deps.db, grant),
133842
133990
  sessionId,
133843
133991
  artifactId2
133844
133992
  );
@@ -134140,7 +134288,7 @@ import {
134140
134288
  StartManagedAuthSocialTransactionRequest,
134141
134289
  StartManagedAuthSocialTransactionResponse
134142
134290
  } from "@opengeni/contracts/managed-auth-session-sets";
134143
- import { hasPermission as hasPermission38, requireSessionAuthorization as requireSessionAuthorization20 } from "@opengeni/core";
134291
+ import { hasPermission as hasPermission39, requireSessionAuthorization as requireSessionAuthorization20 } from "@opengeni/core";
134144
134292
  import {
134145
134293
  authenticateAndAdoptManagedAuthSession,
134146
134294
  isolatedManagedAuthHeaders,
@@ -134823,7 +134971,7 @@ async function resolveCanonicalDeepLink(deps, authority, path, expectedActorEpoc
134823
134971
  const grants = target.workspaceId ? access.workspaceGrants.filter((grant) => grant.workspaceId === target.workspaceId) : access.workspaceGrants;
134824
134972
  let authorized = false;
134825
134973
  for (const grant of grants) {
134826
- if (!hasPermission38(grant.permissions, target.sessionId ? "sessions:read" : target.permission)) {
134974
+ if (!hasPermission39(grant.permissions, target.sessionId ? "sessions:read" : target.permission)) {
134827
134975
  continue;
134828
134976
  }
134829
134977
  if (target.sessionId) {
@@ -135679,7 +135827,7 @@ import {
135679
135827
  getManagedSession as getManagedSession5,
135680
135828
  accountScopedApiKeyWorkspaceAuthority as accountScopedApiKeyWorkspaceAuthority8,
135681
135829
  organizationWorkspaceInScope as organizationWorkspaceInScope3,
135682
- hasPermission as hasPermission39,
135830
+ hasPermission as hasPermission40,
135683
135831
  requireAccessContext as requireAccessContext16,
135684
135832
  organizationMembershipHttpStatus,
135685
135833
  requireCanonicalLocalAccountAdministrator as requireCanonicalLocalAccountAdministrator4,
@@ -135703,7 +135851,7 @@ import {
135703
135851
  listOrganizationAdministrationMembers as listOrganizationAdministrationMembers2,
135704
135852
  listOrganizationInvitations,
135705
135853
  listSelfOrganizationInvitations,
135706
- nestedPostgresSqlState as nestedPostgresSqlState18,
135854
+ nestedPostgresSqlState as nestedPostgresSqlState19,
135707
135855
  prepareOrganizationUserSetupDelivery,
135708
135856
  revokeOrganizationInvitation,
135709
135857
  settleOrganizationUserSetupDelivery,
@@ -135747,7 +135895,7 @@ async function requirePrivateSessionAdministrator(context, deps, organizationId2
135747
135895
  async function requireOrganizationKeyWorkspaceDeletion(context, deps, organizationId2, workspaceId) {
135748
135896
  const access = await requireAccessContext16(context, deps);
135749
135897
  const key2 = accountScopedApiKeyWorkspaceAuthority8(access);
135750
- if (!key2 || key2.accountId !== organizationId2 || !hasPermission39(key2.permissions, "workspace:admin")) {
135898
+ if (!key2 || key2.accountId !== organizationId2 || !hasPermission40(key2.permissions, "workspace:admin")) {
135751
135899
  throw new HTTPException128(403, {
135752
135900
  message: "deleting an organization workspace requires an organization owner session or an organization API key with workspace:admin"
135753
135901
  });
@@ -135820,7 +135968,7 @@ function parseId3(schema, value, label) {
135820
135968
  return parsed.data;
135821
135969
  }
135822
135970
  function rethrowMembershipError(error, resourceLimitMessage) {
135823
- const sqlState = nestedPostgresSqlState18(error);
135971
+ const sqlState = nestedPostgresSqlState19(error);
135824
135972
  if (sqlState === "54000" && resourceLimitMessage) {
135825
135973
  throw new HTTPException128(409, {
135826
135974
  message: resourceLimitMessage
@@ -135926,7 +136074,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
135926
136074
  })
135927
136075
  );
135928
136076
  } catch (error) {
135929
- if (nestedPostgresSqlState18(error) === "42501") {
136077
+ if (nestedPostgresSqlState19(error) === "42501") {
135930
136078
  throw new HTTPException128(403, {
135931
136079
  message: "organization membership is not active"
135932
136080
  });
@@ -136615,7 +136763,7 @@ import {
136615
136763
  import {
136616
136764
  accountScopedApiKeyWorkspaceAuthority as accountScopedApiKeyWorkspaceAuthority9,
136617
136765
  organizationWorkspaceInScope as organizationWorkspaceInScope4,
136618
- hasPermission as hasPermission40,
136766
+ hasPermission as hasPermission41,
136619
136767
  requireAccessContext as requireAccessContext17,
136620
136768
  requireAccessGrantAuthorization as requireAccessGrantAuthorization40,
136621
136769
  requireSessionAuthorizationListScope as requireSessionAuthorizationListScope3,
@@ -136660,7 +136808,7 @@ function decodeOrganizationSessionListCursor(value) {
136660
136808
  function requireOrganizationSessionReadAuthority(context, organizationId2) {
136661
136809
  const authority = accountScopedApiKeyWorkspaceAuthority9(context);
136662
136810
  if (authority) {
136663
- if (authority.accountId === organizationId2 && hasPermission40(authority.permissions, "sessions:read")) {
136811
+ if (authority.accountId === organizationId2 && hasPermission41(authority.permissions, "sessions:read")) {
136664
136812
  return "organization_api_key";
136665
136813
  }
136666
136814
  throw new HTTPException129(403, { message: "organization session read authority required" });
@@ -137125,7 +137273,7 @@ import {
137125
137273
  completeSelfServiceOrganizationSetup,
137126
137274
  completeOrganizationUserSetup,
137127
137275
  getSelfServiceOrganizationOnboardingState,
137128
- nestedPostgresSqlState as nestedPostgresSqlState19,
137276
+ nestedPostgresSqlState as nestedPostgresSqlState20,
137129
137277
  preflightOrganizationUserSetup,
137130
137278
  previewOrganizationUserSetup,
137131
137279
  recordOrganizationSignupUseCase
@@ -137183,14 +137331,14 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
137183
137331
  useCase: parsed.data.useCase
137184
137332
  }).catch((error) => {
137185
137333
  console.warn("[api] could not record the signup use case", {
137186
- sqlState: nestedPostgresSqlState19(error) ?? null
137334
+ sqlState: nestedPostgresSqlState20(error) ?? null
137187
137335
  });
137188
137336
  });
137189
137337
  }
137190
137338
  return context.json(completed);
137191
137339
  } catch (error) {
137192
137340
  recordOrganizationSetupOutcome(deps.observability, "failed");
137193
- const sqlState = nestedPostgresSqlState19(error);
137341
+ const sqlState = nestedPostgresSqlState20(error);
137194
137342
  if (sqlState === "22023") {
137195
137343
  throw new HTTPException131(422, {
137196
137344
  message: "invalid organization setup request"
@@ -137270,7 +137418,7 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
137270
137418
  )
137271
137419
  );
137272
137420
  } catch (error) {
137273
- const sqlState = nestedPostgresSqlState19(error);
137421
+ const sqlState = nestedPostgresSqlState20(error);
137274
137422
  if (sqlState === "22023") {
137275
137423
  throw new HTTPException131(422, {
137276
137424
  message: "invalid account setup request"
@@ -137635,7 +137783,7 @@ import {
137635
137783
  SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError18,
137636
137784
  SessionTenancyManagedHumanRequiredError as SessionTenancyManagedHumanRequiredError3
137637
137785
  } from "@opengeni/core";
137638
- import { nestedPostgresSqlState as nestedPostgresSqlState20, SessionTenancyNotActivatedError as SessionTenancyNotActivatedError3 } from "@opengeni/db";
137786
+ import { nestedPostgresSqlState as nestedPostgresSqlState21, SessionTenancyNotActivatedError as SessionTenancyNotActivatedError3 } from "@opengeni/db";
137639
137787
  import { HTTPException as HTTPException133 } from "hono/http-exception";
137640
137788
  import { z as z78 } from "zod";
137641
137789
  async function body4(context, schema) {
@@ -137650,10 +137798,10 @@ function lifecycleError(error) {
137650
137798
  if (error instanceof SessionAuthorizationUnavailableError18) {
137651
137799
  throw new HTTPException133(503, { message: "session authorization unavailable" });
137652
137800
  }
137653
- if (nestedPostgresSqlState20(error) === "42501") {
137801
+ if (nestedPostgresSqlState21(error) === "42501") {
137654
137802
  throw new HTTPException133(403, { message: "user-resource authority denied" });
137655
137803
  }
137656
- if (nestedPostgresSqlState20(error) === "22023") {
137804
+ if (nestedPostgresSqlState21(error) === "22023") {
137657
137805
  throw new HTTPException133(422, { message: "invalid user-resource request" });
137658
137806
  }
137659
137807
  throw error;
@@ -138964,7 +139112,7 @@ import {
138964
139112
  controlHumanSessionWorkstream as controlHumanSessionWorkstream2,
138965
139113
  createSessionForRequest as createSessionForRequest2,
138966
139114
  getActorNewSessionModelChoice,
138967
- hasPermission as hasPermission42,
139115
+ hasPermission as hasPermission43,
138968
139116
  requireAccessContext as requireAccessContext18,
138969
139117
  requireAccessGrant as requireAccessGrant63,
138970
139118
  requireSessionAuthorizationListScope as requireSessionAuthorizationListScope4,
@@ -138978,7 +139126,7 @@ import {
138978
139126
  resourceMountPathCollisionKey
138979
139127
  } from "@opengeni/contracts";
138980
139128
  import { listRecentSessionRepositoryResources } from "@opengeni/db";
138981
- import { hasPermission as hasPermission41 } from "@opengeni/core";
139129
+ import { hasPermission as hasPermission42 } from "@opengeni/core";
138982
139130
  var SLACK_SESSION_RECENT_REPOSITORY_LIMIT = 5;
138983
139131
  var SLACK_SESSION_RECENT_REPOSITORY_WINDOW_MS = 30 * 24 * 60 * 60 * 1e3;
138984
139132
  function githubUriKey(uri) {
@@ -139043,7 +139191,7 @@ function selectRecentRepositoryResources(recent, catalog, limit = SLACK_SESSION_
139043
139191
  return resources;
139044
139192
  }
139045
139193
  async function slackRecentRepositoryResources(deps, grant, workspaceId, now = /* @__PURE__ */ new Date()) {
139046
- if (!hasPermission41(grant.permissions, "github:use")) return [];
139194
+ if (!hasPermission42(grant.permissions, "github:use")) return [];
139047
139195
  const recent = await listRecentSessionRepositoryResources(deps.db, {
139048
139196
  workspaceId,
139049
139197
  subjectId: grant.subjectId,
@@ -140346,7 +140494,7 @@ function registerSlackInteractionRoutes(app, deps) {
140346
140494
  targetAccountId: grant.accountId,
140347
140495
  targetWorkspaceId: route2.targetWorkspaceId
140348
140496
  });
140349
- if (!authorized || !hasPermission42(authorized.permissions, "sessions:create")) {
140497
+ if (!authorized || !hasPermission43(authorized.permissions, "sessions:create")) {
140350
140498
  throw new HTTPException134(403, {
140351
140499
  message: `you cannot start work in the workspace chosen for ${route2.slackChannelId}`
140352
140500
  });
@@ -140429,7 +140577,7 @@ async function publishSlackAppHome(deps, installation, refresh, renewLease) {
140429
140577
  const grant = link ? await getWorkspaceGrant5(deps.db, link.subjectId, installation.workspaceId, {
140430
140578
  principalKind: "human_session"
140431
140579
  }) : null;
140432
- if (!grant || grant.accountId !== installation.accountId || !hasPermission42(grant.permissions, "sessions:read")) {
140580
+ if (!grant || grant.accountId !== installation.accountId || !hasPermission43(grant.permissions, "sessions:read")) {
140433
140581
  const client2 = await createOpenGeniSlackBotInteractionClient(deps, {
140434
140582
  accountId: installation.accountId,
140435
140583
  workspaceId: installation.workspaceId,
@@ -140507,7 +140655,7 @@ async function publishSlackAppHome(deps, installation, refresh, renewLease) {
140507
140655
  const currentGrant = currentLink ? await getWorkspaceGrant5(deps.db, currentLink.subjectId, installation.workspaceId, {
140508
140656
  principalKind: "human_session"
140509
140657
  }) : null;
140510
- if (!currentLink || currentLink.subjectId !== grant.subjectId || !currentGrant || currentGrant.accountId !== installation.accountId || !hasPermission42(currentGrant.permissions, "sessions:read")) {
140658
+ if (!currentLink || currentLink.subjectId !== grant.subjectId || !currentGrant || currentGrant.accountId !== installation.accountId || !hasPermission43(currentGrant.permissions, "sessions:read")) {
140511
140659
  await publishSlackAppHomeAccessView(
140512
140660
  client,
140513
140661
  refresh,
@@ -141060,7 +141208,7 @@ async function handleSlackRouteChoice(deps, home, entry2, actionId, optionId) {
141060
141208
  targetAccountId: chosen.candidateAccountId,
141061
141209
  targetWorkspaceId: chosen.candidateWorkspaceId
141062
141210
  }) : null;
141063
- if (!grant || !hasPermission42(grant.permissions, "sessions:create")) {
141211
+ if (!grant || !hasPermission43(grant.permissions, "sessions:create")) {
141064
141212
  await client.postMessage({
141065
141213
  operationId: deterministicUuid2(`slack-route-denied:${prompt.id}:${chosen.id}`),
141066
141214
  userId: entry2.slackUserId,
@@ -141269,7 +141417,7 @@ async function processSlackInboxEntry(deps, entry2) {
141269
141417
  });
141270
141418
  return;
141271
141419
  }
141272
- if (!hasPermission42(grant.permissions, "sessions:create")) {
141420
+ if (!hasPermission43(grant.permissions, "sessions:create")) {
141273
141421
  throw new SlackInteractionPermanentError("sessions_create_denied");
141274
141422
  }
141275
141423
  const { interaction } = await getOrCreateSlackInteraction(deps.db, {
@@ -141719,7 +141867,7 @@ async function processSlackReactionInboxEntry(deps, entry2) {
141719
141867
  if (!resolved) {
141720
141868
  throw new SlackInteractionPermanentError("identity_access_revoked");
141721
141869
  }
141722
- if (!hasPermission42(resolved.permissions, "sessions:create") || !hasPermission42(resolved.permissions, "sessions:control")) {
141870
+ if (!hasPermission43(resolved.permissions, "sessions:create") || !hasPermission43(resolved.permissions, "sessions:control")) {
141723
141871
  throw new SlackInteractionPermanentError("reaction_session_permissions_denied");
141724
141872
  }
141725
141873
  return resolved;
@@ -142264,7 +142412,7 @@ async function continueSlackSession(deps, grant, interaction, entry2, resources
142264
142412
  const sessionId = interaction.sessionId;
142265
142413
  await reopenSlackInteractionDelivery(deps.db, interaction);
142266
142414
  if (entry2.text.trim().toLowerCase() === "stop") {
142267
- if (!hasPermission42(grant.permissions, "sessions:control")) {
142415
+ if (!hasPermission43(grant.permissions, "sessions:control")) {
142268
142416
  throw new SlackInteractionPermanentError("sessions_control_denied");
142269
142417
  }
142270
142418
  await controlHumanSessionWorkstream2(
@@ -142343,7 +142491,7 @@ async function continueSlackSession(deps, grant, interaction, entry2, resources
142343
142491
  }
142344
142492
  }
142345
142493
  }
142346
- if (!hasPermission42(grant.permissions, "sessions:control")) {
142494
+ if (!hasPermission43(grant.permissions, "sessions:control")) {
142347
142495
  throw new SlackInteractionPermanentError("sessions_control_denied");
142348
142496
  }
142349
142497
  await withSlackAllowanceAdmissionNotice(deps, entry2, interaction, async () => {
@@ -142455,7 +142603,7 @@ async function processSlackBlockAction(deps, entry2) {
142455
142603
  targetAccountId: target.accountId,
142456
142604
  targetWorkspaceId: target.workspaceId
142457
142605
  });
142458
- if (!grant || !hasPermission42(grant.permissions, "sessions:control")) {
142606
+ if (!grant || !hasPermission43(grant.permissions, "sessions:control")) {
142459
142607
  throw new SlackInteractionPermanentError("sessions_control_denied");
142460
142608
  }
142461
142609
  const client = await createOpenGeniSlackBotInteractionClient(deps, {
@@ -142815,7 +142963,7 @@ async function executeSlackAction(deps, grant, interaction, handle) {
142815
142963
  }
142816
142964
  const session = await getSession18(deps.db, grant.workspaceId, handle.sessionId);
142817
142965
  if (!session) throw new SlackInteractionPermanentError("slack_action_session_missing");
142818
- const recurring = hasPermission42(grant.permissions, "sessions:read") && hasPermission42(grant.permissions, "scheduled_tasks:manage") ? makeRecurringText(deps, grant.workspaceId, handle.sessionId) : null;
142966
+ const recurring = hasPermission43(grant.permissions, "sessions:read") && hasPermission43(grant.permissions, "scheduled_tasks:manage") ? makeRecurringText(deps, grant.workspaceId, handle.sessionId) : null;
142819
142967
  return {
142820
142968
  result: "status",
142821
142969
  text: `${mention}Opengeni task status: *${session.status.replaceAll("_", " ")}*.${recurring ? `
@@ -143902,7 +144050,7 @@ async function slackInfoCommandResponse(deps, installation, entry2) {
143902
144050
  const grant = link ? await getWorkspaceGrant5(deps.db, link.subjectId, installation.workspaceId, {
143903
144051
  principalKind: "human_session"
143904
144052
  }) : null;
143905
- if (!grant || grant.accountId !== installation.accountId || !hasPermission42(grant.permissions, "sessions:read")) {
144053
+ if (!grant || grant.accountId !== installation.accountId || !hasPermission43(grant.permissions, "sessions:read")) {
143906
144054
  return ephemeralSlackResponse(
143907
144055
  link ? `Your Slack identity is linked, but it does not currently have access to this Opengeni workspace. Request access: ${linkUrl(deps, identity2)}. No session was created.` : `Link your Slack identity to Opengeni before starting work: ${linkUrl(deps, identity2)}. No session was created.`
143908
144056
  );
@@ -143910,9 +144058,9 @@ async function slackInfoCommandResponse(deps, installation, entry2) {
143910
144058
  const workspace = await getWorkspace15(deps.db, installation.workspaceId);
143911
144059
  const command = deps.settings.slackCommand;
143912
144060
  const botMention = slackBotMention(installation.botUserId);
143913
- const canControl = hasPermission42(grant.permissions, "sessions:control");
143914
- const canCreate = hasPermission42(grant.permissions, "sessions:create");
143915
- const canSchedule = hasPermission42(grant.permissions, "scheduled_tasks:manage");
144061
+ const canControl = hasPermission43(grant.permissions, "sessions:control");
144062
+ const canCreate = hasPermission43(grant.permissions, "sessions:create");
144063
+ const canSchedule = hasPermission43(grant.permissions, "scheduled_tasks:manage");
143916
144064
  const schedules = canSchedule ? slackSchedulesUrl(deps, installation.workspaceId) : null;
143917
144065
  const agentSchedules = canSchedule && canControl && slackTaskFirstPartyMcpTools(deps.settings, workspace?.settings).includes(
143918
144066
  "scheduled_tasks_create"
@@ -145058,7 +145206,7 @@ function createAppComposition(deps) {
145058
145206
  { accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
145059
145207
  { observeAvailability: true }
145060
145208
  );
145061
- if (!hasPermission43(grant.permissions, "sessions:create")) {
145209
+ if (!hasPermission44(grant.permissions, "sessions:create")) {
145062
145210
  modelSelectionForbidden = true;
145063
145211
  selections = [];
145064
145212
  }
@@ -145072,7 +145220,7 @@ function createAppComposition(deps) {
145072
145220
  preferredProvider: voicePreferences?.preferredProvider,
145073
145221
  fallbackEnabled: voicePreferences?.fallbackEnabled
145074
145222
  };
145075
- if (hasPermission43(grant.permissions, "sessions:create") && transcription) {
145223
+ if (hasPermission44(grant.permissions, "sessions:create") && transcription) {
145076
145224
  voiceInputProviders = await transcription.availableProviderIds?.(voiceContext) ?? [];
145077
145225
  voiceInputAvailable = voiceInputProviders.length > 0 && await Promise.resolve(transcription.available(voiceContext)).catch(() => false);
145078
145226
  }
@@ -145367,8 +145515,8 @@ function createAppComposition(deps) {
145367
145515
  throw error;
145368
145516
  }
145369
145517
  const grant = authorization.grant;
145370
- const outsideAgentContext = AsyncLocalStorage3.snapshot();
145371
- return await withSessionAuthorizationReadReuse(
145518
+ const outsideAgentContext = AsyncLocalStorage4.snapshot();
145519
+ return await withSessionAuthorizationReadReuse3(
145372
145520
  (reads) => withAccessGrantSessionRlsContext(routeDeps, grant, async () => {
145373
145521
  const boundSessionId = grant.metadata?.sessionId;
145374
145522
  if (typeof boundSessionId === "string") {
@@ -145465,7 +145613,7 @@ function createAppComposition(deps) {
145465
145613
  reauthorize: async () => {
145466
145614
  const live = await requireFreshAccessGrant5(c, routeDeps, workspaceId, "workspace:read");
145467
145615
  const original = authorization.grant;
145468
- if (live.accountId !== original.accountId || live.subjectId !== original.subjectId || live.principalKind !== original.principalKind || original.permissions.some((permission) => !hasPermission43(live.permissions, permission)))
145616
+ if (live.accountId !== original.accountId || live.subjectId !== original.subjectId || live.principalKind !== original.principalKind || original.permissions.some((permission) => !hasPermission44(live.permissions, permission)))
145469
145617
  throw new HTTPException135(403, { message: "tool_access_changed" });
145470
145618
  },
145471
145619
  onFence: (created) => {
@@ -145919,7 +146067,7 @@ async function validateCodexAccountTarget(request) {
145919
146067
  async function requireMcpAccessGrantAuthorization(c, deps, workspaceId) {
145920
146068
  const authorization = await requireAccessGrantAuthorization42(c, deps, workspaceId);
145921
146069
  const grant = authorization.grant;
145922
- if (hasPermission43(grant.permissions, "workspace:read")) {
146070
+ if (hasPermission44(grant.permissions, "workspace:read")) {
145923
146071
  return authorization;
145924
146072
  }
145925
146073
  if (isCodemodeGrant(grant)) {
@@ -147351,4 +147499,4 @@ export {
147351
147499
  withDefaultEnabledCapabilityMcpTools,
147352
147500
  workflowIdForSession4 as workflowIdForSession
147353
147501
  };
147354
- //# sourceMappingURL=chunk-PQBHZ2YH.js.map
147502
+ //# sourceMappingURL=chunk-6CECHDZP.js.map