@opengeni/api-router 2.13.0-canary.2 → 3.0.0-canary.1

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.
@@ -3557,7 +3557,7 @@ import { bodyLimit } from "hono/body-limit";
3557
3557
  import { compress } from "hono/compress";
3558
3558
  import { cors } from "hono/cors";
3559
3559
  import { getCookie as getCookie2 } from "hono/cookie";
3560
- import { HTTPException as HTTPException95 } from "hono/http-exception";
3560
+ import { HTTPException as HTTPException97 } from "hono/http-exception";
3561
3561
 
3562
3562
  // src/http/api-error.ts
3563
3563
  import { WorkspaceControlBusyError } from "@opengeni/db";
@@ -3592,17 +3592,17 @@ function workspaceControlBusyHttpError(error) {
3592
3592
  import {
3593
3593
  CodexCompactionV2ProviderLockedError,
3594
3594
  ManagedAuthActorLeaseOutcomeUnknownError,
3595
- hasPermission as hasPermission24,
3595
+ hasPermission as hasPermission25,
3596
3596
  requireAccessGrant as requireAccessGrant47,
3597
- requireAccessGrantAuthorization as requireAccessGrantAuthorization36,
3597
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization37,
3598
3598
  requirePermission as requirePermission9,
3599
3599
  releaseManagedAuthRequestActorLease,
3600
3600
  resolveCatalogSettings,
3601
3601
  resolveWorkspaceCatalogSettings as resolveWorkspaceCatalogSettings10,
3602
3602
  validateManagedAuthRequestActorLease,
3603
- requireSessionAuthorization as requireSessionAuthorization15,
3604
- SessionAuthorizationDeniedError as SessionAuthorizationDeniedError16,
3605
- SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError14
3603
+ requireSessionAuthorization as requireSessionAuthorization16,
3604
+ SessionAuthorizationDeniedError as SessionAuthorizationDeniedError17,
3605
+ SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError15
3606
3606
  } from "@opengeni/core";
3607
3607
 
3608
3608
  // src/auth/managed-auth.ts
@@ -6221,7 +6221,7 @@ function registerKnowledgeEntryTools(server, deps, grant, sessionId) {
6221
6221
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
6222
6222
  } catch (error) {
6223
6223
  const state = nestedPostgresSqlState2(error);
6224
- const message = surface === "instruction" ? state === "40001" ? "This instruction changed. Read its current content and baseline, then retry the same intended edit against that exact state." : state === "23505" ? "This instruction operation ID was already used with different input. Reuse it only for an exact retry." : state === "42501" ? "The instruction change is unavailable in this task's scope or Agent learning policy. Off disables authoring, not the task. Do not ask for approval to continue." : state === "22023" || state === "23514" ? "Invalid instruction change. Read the current instruction, use append for a new rule, edit with one exact oldText match to update or remove text, and replace only when the user explicitly wants the complete instruction replaced. The resulting instruction must stay within 600 characters." : "Workspace instructions are temporarily unavailable. Retry the same operation ID only if the prior change may have succeeded." : state === "40001" ? "This entry changed. Read its current revision and retry your correction with the current version." : state === "23505" ? "This operation ID was already used with different input. Reuse it only for an exact retry." : state === "42501" ? "The entry, reference, or write is unavailable in this task's scope and Agent learning policy. Off disables saving, not your task. Do not ask for an approval to continue." : state === "22023" || state === "23514" ? "Invalid Knowledge entry or relationship. Check the referenced IDs and revision before retrying." : "Knowledge is temporarily unavailable. Your task can continue; retry the same operation ID if saving may have succeeded.";
6224
+ const message = surface === "instruction" ? state === "40001" ? "This instruction changed. Read its current content and baseline, then retry the same intended edit against that exact state." : state === "23505" ? "This instruction operation ID was already used with different input. Reuse it only for an exact retry." : state === "42501" ? "The instruction change is unavailable in this task's scope or Agent learning policy. Off disables authoring, not the task. Do not ask for approval to continue." : state === "22023" || state === "23514" ? "Invalid instruction change. Read the current instruction, use append for a new rule, or edit with one localized exact oldText match to update or remove text. Agents cannot replace the complete instruction. The resulting instruction must stay within 600 characters." : "Workspace instructions are temporarily unavailable. Retry the same operation ID only if the prior change may have succeeded." : state === "40001" ? "This entry changed. Read its current revision and retry your correction with the current version." : state === "23505" ? "This operation ID was already used with different input. Reuse it only for an exact retry." : state === "42501" ? "The entry, reference, or write is unavailable in this task's scope and Agent learning policy. Off disables saving, not your task. Do not ask for an approval to continue." : state === "22023" || state === "23514" ? "Invalid Knowledge entry or relationship. Check the referenced IDs and revision before retrying." : "Knowledge is temporarily unavailable. Your task can continue; retry the same operation ID if saving may have succeeded.";
6225
6225
  return {
6226
6226
  isError: true,
6227
6227
  content: [
@@ -6380,7 +6380,7 @@ function registerKnowledgeEntryTools(server, deps, grant, sessionId) {
6380
6380
  server.registerTool(
6381
6381
  "instruction_policy_save",
6382
6382
  {
6383
- description: "Change a concise standing workspace instruction through this task's Agent learning policy. Read the current policy first and submit its exact baseline. Use editMode=append by default for a new rule; it preserves the current content and adds one blank-line separator. Use edit with oldText that occurs exactly once and newText to update or remove existing text. Use replace only when the user explicitly asks to replace the complete instruction; never reconstruct or summarize unrelated rules. Each supplied text and the resulting instruction are limited to 600 characters. Facts and incidents belong in knowledge_save and reusable procedures in skill_save. Review first saves an inactive revision and returns pending; continue the task without an approval question.",
6383
+ description: "Change a concise standing workspace instruction through this task's Agent learning policy. Read the current policy first and submit its exact baseline. Use editMode=append by default for a new rule; it preserves the current content and adds one blank-line separator. Use edit with a localized oldText that occurs exactly once and newText to update or remove only that passage. Agents cannot replace the complete instruction; direct the user to the manual workspace-instruction editor for a whole-policy rewrite. Each supplied text and the resulting instruction are limited to 600 characters. Facts and incidents belong in knowledge_save and reusable procedures in skill_save. Review first saves an inactive revision and returns pending; continue the task without an approval question.",
6384
6384
  inputSchema: AgentInstructionSaveRequest.shape
6385
6385
  },
6386
6386
  (input) => run((context) => saveAgentInstruction(deps.db, context, input), "instruction")
@@ -6664,6 +6664,7 @@ import {
6664
6664
  prepareGeneratedWorkspaceFile,
6665
6665
  getSessionAuthorityProjection,
6666
6666
  requireWorkspace as requireWorkspace2,
6667
+ recordSandboxFilePublication,
6667
6668
  withSessionRlsActorContext as withSessionRlsActorContext5
6668
6669
  } from "@opengeni/db";
6669
6670
  import { retryWhileMissing as retryWhileMissing3 } from "@opengeni/storage";
@@ -10343,6 +10344,12 @@ async function publishSandboxFileArtifactInScope(deps, input) {
10343
10344
  if (!artifact) {
10344
10345
  throw new HTTPException12(502, { message: "published sandbox artifact is not ready" });
10345
10346
  }
10347
+ await recordSandboxFilePublication(deps.db, {
10348
+ accountId: input.grant.accountId,
10349
+ workspaceId: input.grant.workspaceId,
10350
+ fileId: file.id,
10351
+ sourceSessionId: input.session.id
10352
+ });
10346
10353
  return SandboxFileArtifactReceipt.parse({
10347
10354
  type: "sandbox_file",
10348
10355
  sandboxPath: `/workspace/${path}`,
@@ -17864,7 +17871,7 @@ function parseSlackReactionContextCheckpoint(value, expectedBinding, key, nowMs
17864
17871
  (message) => seenMessageTimestamps.indexOf(message.timestamp)
17865
17872
  );
17866
17873
  if (seenMessageTimestamps.length > 0 && messages.length === 0 || messages.length > 0 && threadTimestamp === null || messages.length > 0 && messages[0].timestamp !== seenMessageTimestamps[0] || seenTimestampIndexes.some(
17867
- (index, position) => index < 0 || position > 0 && index <= seenTimestampIndexes[position - 1]
17874
+ (index, position2) => index < 0 || position2 > 0 && index <= seenTimestampIndexes[position2 - 1]
17868
17875
  )) {
17869
17876
  throw new SlackBotProviderError("reaction_checkpoint_invalid");
17870
17877
  }
@@ -62833,12 +62840,12 @@ import {
62833
62840
  filterOpenApiDocumentForDefinition,
62834
62841
  googleDiscoveryToOpenApi,
62835
62842
  integrationDefinitionById as integrationDefinitionById2,
62836
- parseOpenApiDocument
62843
+ parseOpenApiDocument,
62844
+ MAX_CURATED_INTEGRATION_SPEC_BYTES
62837
62845
  } from "@opengeni/capabilities";
62838
62846
  import {
62839
62847
  ApiIntegrationPreview
62840
62848
  } from "@opengeni/contracts";
62841
- var MAX_CURATED_DEFINITION_SOURCE_BYTES = 64 * 1024 * 1024;
62842
62849
  async function resolveApiIntegrationPreview(input) {
62843
62850
  if (input.source.kind === "definition") {
62844
62851
  return await resolveDefinition(input);
@@ -62876,20 +62883,26 @@ async function resolveDefinition(input) {
62876
62883
  const bytes = await fetchIntegrationSourceDocument(
62877
62884
  input.transport,
62878
62885
  definition.source.url,
62879
- MAX_CURATED_DEFINITION_SOURCE_BYTES
62886
+ MAX_CURATED_INTEGRATION_SPEC_BYTES
62880
62887
  );
62881
62888
  let document;
62882
62889
  if (definition.source.kind === "google_discovery") {
62883
62890
  document = googleDiscoveryToOpenApi(JSON.parse(new TextDecoder().decode(bytes)));
62884
62891
  } else {
62885
- document = filterOpenApiDocumentForDefinition(parseOpenApiDocument(bytes), definition);
62892
+ document = filterOpenApiDocumentForDefinition(
62893
+ parseOpenApiDocument(bytes, {
62894
+ maxBytes: MAX_CURATED_INTEGRATION_SPEC_BYTES
62895
+ }),
62896
+ definition
62897
+ );
62886
62898
  }
62887
62899
  const identity = integrationInstallationIdentity("openapi", definition.id, definition.source.url);
62888
62900
  const revision = compileOpenApiRevision(document, {
62889
62901
  definitionId: definition.id,
62890
62902
  sourceUrl: definition.source.url,
62891
62903
  baseUrl: definition.baseUrl,
62892
- provider: definition.provider.id
62904
+ provider: definition.provider.id,
62905
+ ...definition.source.kind === "openapi" && definition.source.schemaMode ? { schemaMode: definition.source.schemaMode } : {}
62893
62906
  });
62894
62907
  const baseUrl = firstOpenApiServerUrl(revision);
62895
62908
  const providerDomain = definition.provider.domain;
@@ -62990,6 +63003,9 @@ async function resolveGraphql(input, endpoint, name) {
62990
63003
  });
62991
63004
  }
62992
63005
  function resolvedPreview(input) {
63006
+ if (Buffer.byteLength(JSON.stringify(input.revision, null, 2), "utf8") > 4 * 1024 * 1024) {
63007
+ throw new Error("Compiled integration exceeds the supported 4 MiB storage limit");
63008
+ }
62993
63009
  const deprecated = input.revision.tools.filter((tool) => tool.deprecated).length;
62994
63010
  const warnings = [
62995
63011
  ...deprecated > 0 ? [`${deprecated} deprecated operation${deprecated === 1 ? "" : "s"} will not be enabled.`] : [],
@@ -63487,6 +63503,14 @@ function registerConnectRoutes(app, deps) {
63487
63503
  ownership: ["workspace"],
63488
63504
  setup: ["oauth"]
63489
63505
  }),
63506
+ ConnectProvider.parse({
63507
+ id: "gmail",
63508
+ label: "Gmail",
63509
+ family: "google",
63510
+ readiness: !external || !canWrite2 || !personal ? "unsupported" : mcpConfigured ? "available" : "needs_configuration",
63511
+ ownership: personal ? ["personal"] : [],
63512
+ setup: ["oauth"]
63513
+ }),
63490
63514
  ConnectProvider.parse({
63491
63515
  id: "slack-personal",
63492
63516
  label: "My Slack account",
@@ -63690,7 +63714,7 @@ function registerConnectRoutes(app, deps) {
63690
63714
  ConnectAccount.parse({
63691
63715
  id: connection.id,
63692
63716
  version: connection.version,
63693
- providerId: connection.metadata.mcpUrl === OPENGENI_PERSONAL_SLACK_MCP_URL2 ? "slack-personal" : "mcp-oauth",
63717
+ providerId: connection.metadata.mcpUrl === OPENGENI_PERSONAL_SLACK_MCP_URL2 ? "slack-personal" : connection.metadata.mcpUrl === OFFICIAL_GMAIL_MCP_URL ? "gmail" : "mcp-oauth",
63694
63718
  label: connection.providerDomain,
63695
63719
  ownership: connection.subjectId === null ? "workspace" : "personal",
63696
63720
  status: connection.status === "revoked" ? "disabled" : connection.status === "active" ? "connected" : "auth_needed"
@@ -64046,10 +64070,10 @@ function registerConnectRoutes(app, deps) {
64046
64070
  })
64047
64071
  );
64048
64072
  }
64049
- if (["mcp-oauth", "slack-personal"].includes(before.providerId)) {
64073
+ if (["mcp-oauth", "slack-personal", "gmail"].includes(before.providerId)) {
64050
64074
  if (action.type !== "credentials")
64051
64075
  throw new HTTPException38(422, { message: "MCP OAuth requires a server URL" });
64052
- const values = before.providerId === "slack-personal" ? { mcpUrl: OPENGENI_PERSONAL_SLACK_MCP_URL2 } : z18.object({ mcpUrl: z18.string().url().max(4096) }).strict().parse(action.values);
64076
+ const values = before.providerId === "slack-personal" ? { mcpUrl: OPENGENI_PERSONAL_SLACK_MCP_URL2 } : before.providerId === "gmail" ? { mcpUrl: OFFICIAL_GMAIL_MCP_URL } : z18.object({ mcpUrl: z18.string().url().max(4096) }).strict().parse(action.values);
64053
64077
  return c.json(
64054
64078
  await executeConnectOperation({
64055
64079
  db: deps.db,
@@ -64485,6 +64509,7 @@ function registerConnectRoutes(app, deps) {
64485
64509
  if (input.installationTarget && [
64486
64510
  "mcp-oauth",
64487
64511
  "slack-personal",
64512
+ "gmail",
64488
64513
  "mcp-bearer",
64489
64514
  "mcp-headers",
64490
64515
  "fiken-token",
@@ -64498,17 +64523,26 @@ function registerConnectRoutes(app, deps) {
64498
64523
  throw new HTTPException38(422, {
64499
64524
  message: "MCP credential setup does not install an API integration instance"
64500
64525
  });
64501
- if (["mcp-oauth", "slack-personal", "mcp-bearer", "mcp-headers", "fiken-token"].includes(
64502
- input.providerId
64503
- )) {
64526
+ if ([
64527
+ "mcp-oauth",
64528
+ "slack-personal",
64529
+ "gmail",
64530
+ "mcp-bearer",
64531
+ "mcp-headers",
64532
+ "fiken-token"
64533
+ ].includes(input.providerId)) {
64504
64534
  if (input.providerId === "slack-personal" && input.ownership !== "personal")
64505
64535
  throw new HTTPException38(422, {
64506
64536
  message: "Hosted Slack MCP requires personal ownership"
64507
64537
  });
64538
+ if (input.providerId === "gmail" && input.ownership !== "personal")
64539
+ throw new HTTPException38(422, {
64540
+ message: "Gmail requires personal ownership; each user connects their own account"
64541
+ });
64508
64542
  if (input.providerId === "fiken-token" && input.ownership !== "workspace")
64509
64543
  throw new HTTPException38(422, { message: "Fiken is workspace-owned" });
64510
64544
  requireEnvironmentEncryption11(deps.settings);
64511
- if (["mcp-oauth", "slack-personal"].includes(input.providerId))
64545
+ if (["mcp-oauth", "slack-personal", "gmail"].includes(input.providerId))
64512
64546
  requireIntegrationsStateSecret(deps.settings);
64513
64547
  const existing = input.reconnectAccountId ? await getConnectionMetadata10(
64514
64548
  tx,
@@ -64516,7 +64550,7 @@ function registerConnectRoutes(app, deps) {
64516
64550
  input.reconnectAccountId,
64517
64551
  scope.subjectId
64518
64552
  ) : null;
64519
- if (input.reconnectAccountId && (!existing || (input.providerId === "fiken-token" ? !isFikenConnection2(existing) : ["mcp-oauth", "slack-personal"].includes(input.providerId) ? existing.kind !== "oauth2" || !existing.metadata.oauthDiscovery || input.providerId === "slack-personal" && existing.metadata.mcpUrl !== OPENGENI_PERSONAL_SLACK_MCP_URL2 : existing.kind !== "api_key" || existing.metadata.connectAdapter !== input.providerId) || (existing.subjectId === null ? "workspace" : "personal") !== input.ownership))
64553
+ if (input.reconnectAccountId && (!existing || (input.providerId === "fiken-token" ? !isFikenConnection2(existing) : ["mcp-oauth", "slack-personal", "gmail"].includes(input.providerId) ? existing.kind !== "oauth2" || !existing.metadata.oauthDiscovery || input.providerId === "slack-personal" && existing.metadata.mcpUrl !== OPENGENI_PERSONAL_SLACK_MCP_URL2 || input.providerId === "gmail" && existing.metadata.mcpUrl !== OFFICIAL_GMAIL_MCP_URL : existing.kind !== "api_key" || existing.metadata.connectAdapter !== input.providerId) || (existing.subjectId === null ? "workspace" : "personal") !== input.ownership))
64520
64554
  throw new HTTPException38(404, { message: "MCP account not found for this ownership" });
64521
64555
  if (input.ownership === "personal" && !isPersonalConnectionOwnerPrincipal(authorization))
64522
64556
  throw new HTTPException38(403, { message: "personal ownership unavailable" });
@@ -64547,7 +64581,7 @@ function registerConnectRoutes(app, deps) {
64547
64581
  } : {},
64548
64582
  nextAction: {
64549
64583
  type: "credentials",
64550
- fields: input.providerId === "slack-personal" ? [] : input.providerId === "fiken-token" ? [
64584
+ fields: ["slack-personal", "gmail"].includes(input.providerId) ? [] : input.providerId === "fiken-token" ? [
64551
64585
  {
64552
64586
  name: "apiToken",
64553
64587
  label: "Fiken API token",
@@ -93981,6 +94015,287 @@ function registerWorkspaceArtifactRoutes(app, deps) {
93981
94015
  });
93982
94016
  }
93983
94017
 
94018
+ // src/routes/artifact-catalog.ts
94019
+ import { resolveFirstPartyDelegationSecret as resolveFirstPartyDelegationSecret5 } from "@opengeni/config";
94020
+ import {
94021
+ ArtifactCatalogItem,
94022
+ ArtifactCatalogKind as ArtifactCatalogKind2,
94023
+ ArtifactCatalogListQuery,
94024
+ ArtifactCatalogListResponse,
94025
+ retainedArtifactReferenceFromFile as retainedArtifactReferenceFromFile3,
94026
+ retainedGeneratedImageReferenceFromFile as retainedGeneratedImageReferenceFromFile2
94027
+ } from "@opengeni/contracts";
94028
+ import {
94029
+ editableArtifactId as editableArtifactId3,
94030
+ editableArtifactScope as editableArtifactScope2,
94031
+ fileOwnerContextForAccess as fileOwnerContextForAccess5,
94032
+ grantHasAgentAttemptAuthority as grantHasAgentAttemptAuthority4,
94033
+ hasPermission as hasPermission21,
94034
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization32,
94035
+ requireLiveAgentAttemptAuthorization as requireLiveAgentAttemptAuthorization5,
94036
+ requireSessionAuthorization as requireSessionAuthorization14,
94037
+ SessionAuthorizationDeniedError as SessionAuthorizationDeniedError13,
94038
+ SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError11
94039
+ } from "@opengeni/core";
94040
+ import {
94041
+ getFilesForSubject as getFilesForSubject3,
94042
+ getGeneratedImageArtifact as getGeneratedImageArtifact2,
94043
+ getSessionAuthorityProjection as getSessionAuthorityProjection3,
94044
+ listArtifactCatalogCandidates,
94045
+ withSessionRlsActorContext as withSessionRlsActorContext7
94046
+ } from "@opengeni/db";
94047
+ import { HTTPException as HTTPException84 } from "hono/http-exception";
94048
+
94049
+ // src/artifact-catalog-cursor.ts
94050
+ import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, createHash as createHash27, randomBytes as randomBytes11 } from "crypto";
94051
+ import { ArtifactCatalogKind } from "@opengeni/contracts";
94052
+ import { HTTPException as HTTPException83 } from "hono/http-exception";
94053
+ import { z as z33 } from "zod";
94054
+ var Cursor = z33.object({
94055
+ version: z33.literal(1),
94056
+ snapshotAt: z33.string().datetime(),
94057
+ expiresAt: z33.number().int().positive(),
94058
+ after: z33.object({
94059
+ key: z33.string().max(4096),
94060
+ kind: ArtifactCatalogKind,
94061
+ id: z33.string().min(1).max(128)
94062
+ }).strict()
94063
+ }).strict();
94064
+ function artifactCatalogCursorCodec(secret, binding) {
94065
+ const key = createHash27("sha256").update("opengeni:artifact-catalog:v1\0").update(secret).digest();
94066
+ const aad = createHash27("sha256").update(binding).digest();
94067
+ return {
94068
+ encode(value) {
94069
+ const iv = randomBytes11(12);
94070
+ const cipher = createCipheriv3("aes-256-gcm", key, iv);
94071
+ cipher.setAAD(aad);
94072
+ const bytes = Buffer.concat([
94073
+ cipher.update(JSON.stringify(Cursor.parse(value)), "utf8"),
94074
+ cipher.final()
94075
+ ]);
94076
+ return Buffer.concat([iv, cipher.getAuthTag(), bytes]).toString("base64url");
94077
+ },
94078
+ decode(value) {
94079
+ try {
94080
+ if (value.length > 8192 || !/^[A-Za-z0-9_-]+$/.test(value)) throw new Error();
94081
+ const bytes = Buffer.from(value, "base64url");
94082
+ if (bytes.length < 29 || bytes.toString("base64url") !== value) throw new Error();
94083
+ const decipher = createDecipheriv3("aes-256-gcm", key, bytes.subarray(0, 12));
94084
+ decipher.setAAD(aad);
94085
+ decipher.setAuthTag(bytes.subarray(12, 28));
94086
+ const parsed = Cursor.parse(
94087
+ JSON.parse(
94088
+ Buffer.concat([decipher.update(bytes.subarray(28)), decipher.final()]).toString("utf8")
94089
+ )
94090
+ );
94091
+ if (parsed.expiresAt <= Date.now() || Date.parse(parsed.snapshotAt) > Date.now() + 6e4)
94092
+ throw new Error();
94093
+ return parsed;
94094
+ } catch {
94095
+ throw new HTTPException83(422, { message: "Invalid or expired artifact catalog cursor" });
94096
+ }
94097
+ }
94098
+ };
94099
+ }
94100
+
94101
+ // src/routes/artifact-catalog.ts
94102
+ var editableKinds = /* @__PURE__ */ new Set(["document", "spreadsheet", "presentation"]);
94103
+ var CANDIDATE_BATCH = 200;
94104
+ var MAX_BATCHES = 10;
94105
+ var iso = (value) => new Date(value).toISOString();
94106
+ var position = (row) => ({
94107
+ key: row.sort_key,
94108
+ kind: row.kind,
94109
+ id: row.id
94110
+ });
94111
+ function registerArtifactCatalogRoutes(app, deps) {
94112
+ app.get("/v1/workspaces/:workspaceId/artifact-catalog", async (context) => {
94113
+ const workspaceId = context.req.param("workspaceId");
94114
+ const authorization = await requireAccessGrantAuthorization32(context, deps, workspaceId);
94115
+ const grant = authorization.grant;
94116
+ const parsed = ArtifactCatalogListQuery.safeParse(context.req.query());
94117
+ if (!parsed.success)
94118
+ throw new HTTPException84(422, { message: "Invalid artifact catalog query" });
94119
+ const query = parsed.data;
94120
+ const artifactsAllowed = hasPermission21(grant.permissions, "artifacts:read");
94121
+ const filesAllowed = hasPermission21(grant.permissions, "files:read");
94122
+ if (!artifactsAllowed && !filesAllowed)
94123
+ throw new HTTPException84(403, { message: "Artifact catalog read access required" });
94124
+ let kinds = ArtifactCatalogKind2.options.filter(
94125
+ (kind) => (kind === "image" || kind === "file" ? filesAllowed : artifactsAllowed) && (!query.kind || kind === query.kind)
94126
+ );
94127
+ if (!deps.editableArtifacts) {
94128
+ if (query.kind && editableKinds.has(query.kind) && artifactsAllowed)
94129
+ throw new HTTPException84(503, { message: "Editable artifacts are unavailable" });
94130
+ kinds = kinds.filter((kind) => !editableKinds.has(kind));
94131
+ }
94132
+ const includesFiles = kinds.includes("file") || kinds.includes("image");
94133
+ const actor = includesFiles ? await fileOwnerContextForAccess5(deps, authorization, "files:read") : { subjectId: grant.subjectId, privateFileOwnerSubjectId: null };
94134
+ if (grantHasAgentAttemptAuthority4(grant) && actor.initiatingHumanSubjectId === void 0) {
94135
+ const callerSessionId = grant.metadata?.["sessionId"];
94136
+ try {
94137
+ if (typeof callerSessionId !== "string")
94138
+ throw new SessionAuthorizationDeniedError13("caller_stale");
94139
+ const attempt = await requireLiveAgentAttemptAuthorization5(deps.db, grant, callerSessionId);
94140
+ actor.initiatingHumanSubjectId = attempt.initiatingHumanSubjectId;
94141
+ } catch (error) {
94142
+ if (error instanceof SessionAuthorizationDeniedError13)
94143
+ throw new HTTPException84(404, { message: "Session not found", cause: error });
94144
+ throw error;
94145
+ }
94146
+ }
94147
+ const sourceDecisions = /* @__PURE__ */ new Map();
94148
+ const canReadSession = async (sessionId) => {
94149
+ if (!hasPermission21(grant.permissions, "sessions:read")) return false;
94150
+ if (sourceDecisions.has(sessionId)) return sourceDecisions.get(sessionId);
94151
+ try {
94152
+ await requireSessionAuthorization14(deps, grant, {
94153
+ sessionId,
94154
+ operation: "session.read",
94155
+ surface: "http"
94156
+ });
94157
+ if (!await getSessionAuthorityProjection3(deps.db, workspaceId, sessionId)) {
94158
+ sourceDecisions.set(sessionId, false);
94159
+ return false;
94160
+ }
94161
+ sourceDecisions.set(sessionId, true);
94162
+ return true;
94163
+ } catch (error) {
94164
+ if (error instanceof SessionAuthorizationDeniedError13) {
94165
+ sourceDecisions.set(sessionId, false);
94166
+ return false;
94167
+ }
94168
+ if (error instanceof SessionAuthorizationUnavailableError11)
94169
+ throw new HTTPException84(503, { message: "Session authorization is unavailable" });
94170
+ throw error;
94171
+ }
94172
+ };
94173
+ context.header("cache-control", "private, no-store");
94174
+ return withSessionRlsActorContext7(actor, async () => {
94175
+ if (query.sourceSessionId && !await canReadSession(query.sourceSessionId))
94176
+ throw new HTTPException84(404, { message: "Session not found" });
94177
+ const secret = resolveFirstPartyDelegationSecret5(deps.settings);
94178
+ if (!secret)
94179
+ throw new HTTPException84(503, { message: "Artifact catalog cursor signing is unavailable" });
94180
+ const filters = { ...query, cursor: void 0 };
94181
+ const codec = artifactCatalogCursorCodec(
94182
+ secret,
94183
+ JSON.stringify({
94184
+ accountId: grant.accountId,
94185
+ workspaceId,
94186
+ subjectId: grant.subjectId,
94187
+ principalKind: grant.principalKind,
94188
+ metadata: grant.metadata,
94189
+ permissions: [...grant.permissions].sort(),
94190
+ initiatingHumanSubjectId: actor.initiatingHumanSubjectId ?? null,
94191
+ owner: actor.privateFileOwnerSubjectId ?? null,
94192
+ kinds,
94193
+ filters
94194
+ })
94195
+ );
94196
+ const prior = query.cursor ? codec.decode(query.cursor) : void 0;
94197
+ const snapshotAt = prior?.snapshotAt ?? (/* @__PURE__ */ new Date()).toISOString();
94198
+ const expiresAt = prior?.expiresAt ?? Date.now() + 60 * 6e4;
94199
+ let after = prior?.after;
94200
+ const items = [];
94201
+ let lastReturned;
94202
+ let nextCursor = null;
94203
+ const fileSubject = includesFiles ? await fileAuthoritySubjectIdForGrant(deps, grant) : null;
94204
+ for (let batch = 0; batch < MAX_BATCHES; batch++) {
94205
+ const candidates = await listArtifactCatalogCandidates(
94206
+ deps.db,
94207
+ { accountId: grant.accountId, workspaceId },
94208
+ {
94209
+ query,
94210
+ kinds,
94211
+ snapshotAt,
94212
+ ...after ? { after } : {},
94213
+ limit: CANDIDATE_BATCH
94214
+ }
94215
+ );
94216
+ for (const candidate of candidates) {
94217
+ after = position(candidate);
94218
+ const item = await projectCandidate(deps, grant, candidate, fileSubject);
94219
+ if (!item || item.status !== query.status || query.q && !item.title.toLowerCase().includes(query.q.toLowerCase()))
94220
+ continue;
94221
+ if (items.length === query.limit) {
94222
+ nextCursor = codec.encode({ version: 1, snapshotAt, expiresAt, after: lastReturned });
94223
+ return context.json(ArtifactCatalogListResponse.parse({ items, nextCursor }));
94224
+ }
94225
+ if (candidate.source_session_id && await canReadSession(candidate.source_session_id))
94226
+ item.sourceSessionId = candidate.source_session_id;
94227
+ items.push(ArtifactCatalogItem.parse(item));
94228
+ lastReturned = after;
94229
+ }
94230
+ if (candidates.length < CANDIDATE_BATCH) break;
94231
+ if (batch === MAX_BATCHES - 1 && after)
94232
+ nextCursor = codec.encode({ version: 1, snapshotAt, expiresAt, after });
94233
+ }
94234
+ return context.json(ArtifactCatalogListResponse.parse({ items, nextCursor }));
94235
+ });
94236
+ });
94237
+ }
94238
+ async function projectCandidate(deps, grant, row, fileSubject) {
94239
+ const item = {
94240
+ id: row.id,
94241
+ kind: row.kind,
94242
+ title: row.title,
94243
+ status: row.status,
94244
+ createdAt: iso(row.created_at),
94245
+ updatedAt: iso(row.updated_at)
94246
+ };
94247
+ if (row.version_id) item.versionId = row.version_id;
94248
+ if (editableKinds.has(row.kind)) {
94249
+ const scope = editableArtifactScope2({
94250
+ accountId: grant.accountId,
94251
+ workspaceId: grant.workspaceId
94252
+ });
94253
+ try {
94254
+ const artifact = await deps.editableArtifacts.readArtifact({
94255
+ scope,
94256
+ actor: editableArtifactActorForGrant(grant, "0000000000000001"),
94257
+ artifactId: editableArtifactId3(row.id)
94258
+ });
94259
+ if (artifact.scope.accountId !== scope.accountId || artifact.scope.workspaceId !== scope.workspaceId || artifact.id !== row.id || artifact.modality !== row.kind)
94260
+ throw new Error("Artifact application returned mismatched catalog metadata");
94261
+ return {
94262
+ ...item,
94263
+ title: artifact.title,
94264
+ status: artifact.lifecycle,
94265
+ createdAt: artifact.createdAt,
94266
+ updatedAt: artifact.updatedAt
94267
+ };
94268
+ } catch (error) {
94269
+ if (isInvisibleListCandidate(error)) return null;
94270
+ throw editableArtifactHttpError(error);
94271
+ }
94272
+ }
94273
+ if (row.kind === "file" || row.kind === "image") {
94274
+ const [file] = await getFilesForSubject3(deps.db, {
94275
+ accountId: grant.accountId,
94276
+ workspaceId: grant.workspaceId,
94277
+ subjectId: fileSubject,
94278
+ fileIds: [row.id]
94279
+ });
94280
+ if (!file || file.status !== "ready") return null;
94281
+ const generated = row.origin === "generated_image" ? await getGeneratedImageArtifact2(deps.db, grant.workspaceId, row.id) : null;
94282
+ const reference = row.origin === "generated_image" ? generated?.status === "ready" ? retainedGeneratedImageReferenceFromFile2({
94283
+ ...file,
94284
+ width: generated.width,
94285
+ height: generated.height
94286
+ }) : null : retainedArtifactReferenceFromFile3(file, "file");
94287
+ if (!reference) return null;
94288
+ return {
94289
+ ...item,
94290
+ file: reference,
94291
+ filename: file.filename,
94292
+ contentType: reference.contentType,
94293
+ sizeBytes: file.sizeBytes
94294
+ };
94295
+ }
94296
+ return item;
94297
+ }
94298
+
93984
94299
  // src/routes/insights.ts
93985
94300
  import { InsightsRange, WorkspaceInsightsResponse } from "@opengeni/contracts";
93986
94301
  import {
@@ -93990,13 +94305,13 @@ import {
93990
94305
  WorkspaceInsightsFilterValidationError
93991
94306
  } from "@opengeni/core";
93992
94307
  import { workspaceInsightsMetricObserver } from "@opengeni/observability";
93993
- import { HTTPException as HTTPException83 } from "hono/http-exception";
94308
+ import { HTTPException as HTTPException85 } from "hono/http-exception";
93994
94309
  function normalizeWorkspaceInsightsQueryFilter(value, field) {
93995
94310
  try {
93996
94311
  return normalizeWorkspaceInsightsFilter(value, field);
93997
94312
  } catch (error) {
93998
94313
  if (error instanceof WorkspaceInsightsFilterValidationError) {
93999
- throw new HTTPException83(400, { message: error.message });
94314
+ throw new HTTPException85(400, { message: error.message });
94000
94315
  }
94001
94316
  throw error;
94002
94317
  }
@@ -94016,7 +94331,7 @@ function registerInsightsRoutes(app, deps) {
94016
94331
  await requireAccessGrant42(c, deps, workspaceId, "workspace:admin");
94017
94332
  const rangeParsed = InsightsRange.safeParse(rangeRaw);
94018
94333
  if (!rangeParsed.success) {
94019
- throw new HTTPException83(400, {
94334
+ throw new HTTPException85(400, {
94020
94335
  message: "range must be one of today|week|month|ytd"
94021
94336
  });
94022
94337
  }
@@ -94053,7 +94368,7 @@ import { requireAccessGrant as requireAccessGrant44, TranscriptionServiceError a
94053
94368
  import { getWorkspace as getWorkspace5 } from "@opengeni/db";
94054
94369
 
94055
94370
  // src/routes/transcription-recordings.ts
94056
- import { createHash as createHash27 } from "crypto";
94371
+ import { createHash as createHash28 } from "crypto";
94057
94372
  import {
94058
94373
  CreateTranscriptionRecordingRequest,
94059
94374
  FinalizeTranscriptionRecordingRequest,
@@ -94898,7 +95213,7 @@ function valueAsUuid(value) {
94898
95213
  if (/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
94899
95214
  return value;
94900
95215
  }
94901
- const hex2 = createHash27("sha256").update(value).digest("hex").slice(0, 32);
95216
+ const hex2 = createHash28("sha256").update(value).digest("hex").slice(0, 32);
94902
95217
  return `${hex2.slice(0, 8)}-${hex2.slice(8, 12)}-4${hex2.slice(13, 16)}-a${hex2.slice(17, 20)}-${hex2.slice(20, 32)}`;
94903
95218
  }
94904
95219
  function nonnegativeInteger(value) {
@@ -94962,7 +95277,7 @@ async function readBoundedBody(request, maxBytes) {
94962
95277
  return body4;
94963
95278
  }
94964
95279
  function sha256Hex3(bytes) {
94965
- return createHash27("sha256").update(bytes).digest("hex");
95280
+ return createHash28("sha256").update(bytes).digest("hex");
94966
95281
  }
94967
95282
 
94968
95283
  // src/routes/transcriptions.ts
@@ -95116,7 +95431,7 @@ import {
95116
95431
  } from "@opengeni/contracts";
95117
95432
  import {
95118
95433
  getVideoGenerationOperationSummary,
95119
- withSessionRlsActorContext as withSessionRlsActorContext7,
95434
+ withSessionRlsActorContext as withSessionRlsActorContext8,
95120
95435
  getWorkspaceVercelAiGatewayConnectionMetadata as getWorkspaceVercelAiGatewayConnectionMetadata2,
95121
95436
  getWorkspaceVideoGenerationPolicy,
95122
95437
  updateWorkspaceVideoGenerationPolicy,
@@ -95125,14 +95440,14 @@ import {
95125
95440
  } from "@opengeni/db";
95126
95441
  import {
95127
95442
  requireAccessGrant as requireAccessGrant45,
95128
- requireAccessGrantAuthorization as requireAccessGrantAuthorization32,
95129
- fileOwnerContextForAccess as fileOwnerContextForAccess5,
95443
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization33,
95444
+ fileOwnerContextForAccess as fileOwnerContextForAccess6,
95130
95445
  requireWorkspaceSettingsGrant as requireWorkspaceSettingsGrant4,
95131
95446
  VIDEO_GENERATION_MODEL_CATALOG,
95132
95447
  videoGenerationModelSupportsFundingSource,
95133
95448
  videoGenerationCapabilitiesForPolicy
95134
95449
  } from "@opengeni/core";
95135
- import { HTTPException as HTTPException84 } from "hono/http-exception";
95450
+ import { HTTPException as HTTPException86 } from "hono/http-exception";
95136
95451
  function registerVideoGenerationRoutes(app, deps) {
95137
95452
  app.get("/v1/workspaces/:workspaceId/video-generation", async (c) => {
95138
95453
  const workspaceId = c.req.param("workspaceId");
@@ -95179,14 +95494,14 @@ function registerVideoGenerationRoutes(app, deps) {
95179
95494
  (option) => option.source === payload.fundingSource
95180
95495
  );
95181
95496
  if (payload.enabledModelIds.length > 0 && !selectedFunding?.available) {
95182
- throw new HTTPException84(422, {
95497
+ throw new HTTPException86(422, {
95183
95498
  message: selectedFunding?.unavailableReason ?? "Video generation funding is unavailable"
95184
95499
  });
95185
95500
  }
95186
95501
  if (payload.enabledModelIds.some(
95187
95502
  (modelId) => !videoGenerationModelSupportsFundingSource(modelId, payload.fundingSource)
95188
95503
  )) {
95189
- throw new HTTPException84(422, {
95504
+ throw new HTTPException86(422, {
95190
95505
  message: "The selected video model is unavailable for this funding source"
95191
95506
  });
95192
95507
  }
@@ -95200,24 +95515,24 @@ function registerVideoGenerationRoutes(app, deps) {
95200
95515
  return c.json(VideoGenerationPolicy.parse(policy));
95201
95516
  } catch (error) {
95202
95517
  if (error instanceof VideoGenerationConflictError) {
95203
- throw new HTTPException84(409, { message: error.message });
95518
+ throw new HTTPException86(409, { message: error.message });
95204
95519
  }
95205
95520
  if (error instanceof Error && error.message.startsWith("Unknown video generation model:")) {
95206
- throw new HTTPException84(422, { message: error.message });
95521
+ throw new HTTPException86(422, { message: error.message });
95207
95522
  }
95208
95523
  throw error;
95209
95524
  }
95210
95525
  });
95211
95526
  app.get("/v1/workspaces/:workspaceId/video-generation/operations/:operationId", async (c) => {
95212
95527
  const workspaceId = c.req.param("workspaceId");
95213
- const access = await requireAccessGrantAuthorization32(c, deps, workspaceId, "workspace:read");
95214
- const actor = await fileOwnerContextForAccess5(deps, access, "workspace:read");
95215
- const summary = await withSessionRlsActorContext7(
95528
+ const access = await requireAccessGrantAuthorization33(c, deps, workspaceId, "workspace:read");
95529
+ const actor = await fileOwnerContextForAccess6(deps, access, "workspace:read");
95530
+ const summary = await withSessionRlsActorContext8(
95216
95531
  actor,
95217
95532
  () => getVideoGenerationOperationSummary(deps.db, workspaceId, c.req.param("operationId"))
95218
95533
  );
95219
95534
  if (!summary)
95220
- throw new HTTPException84(404, {
95535
+ throw new HTTPException86(404, {
95221
95536
  message: "video generation operation not found"
95222
95537
  });
95223
95538
  return c.json(VideoGenerationOperationSummary.parse(summary));
@@ -95274,9 +95589,9 @@ import {
95274
95589
  CanonicalHumanIdentityMutationInFlightError,
95275
95590
  getCanonicalHumanIdentityProjection as getCanonicalHumanIdentityProjection2
95276
95591
  } from "@opengeni/db/canonical-human-identities";
95277
- import { HTTPException as HTTPException85 } from "hono/http-exception";
95278
- import { z as z33 } from "zod";
95279
- var BindingId = z33.string().uuid();
95592
+ import { HTTPException as HTTPException87 } from "hono/http-exception";
95593
+ import { z as z34 } from "zod";
95594
+ var BindingId = z34.string().uuid();
95280
95595
  async function requestIdentity(context, deps) {
95281
95596
  return await requireCanonicalHumanRequestIdentity(context, {
95282
95597
  db: deps.db,
@@ -95289,13 +95604,13 @@ async function requestIdentity(context, deps) {
95289
95604
  async function parseBody5(context, schema) {
95290
95605
  const parsed = schema.safeParse(await context.req.json().catch(() => null));
95291
95606
  if (!parsed.success) {
95292
- throw new HTTPException85(422, { message: "Invalid canonical human identity request" });
95607
+ throw new HTTPException87(422, { message: "Invalid canonical human identity request" });
95293
95608
  }
95294
95609
  return parsed.data;
95295
95610
  }
95296
95611
  function bindingId(context) {
95297
95612
  const parsed = BindingId.safeParse(context.req.param("bindingId"));
95298
- if (!parsed.success) throw new HTTPException85(422, { message: "Invalid login binding id" });
95613
+ if (!parsed.success) throw new HTTPException87(422, { message: "Invalid login binding id" });
95299
95614
  return parsed.data;
95300
95615
  }
95301
95616
  function identityError(context, error) {
@@ -95326,7 +95641,7 @@ async function mutate(context, deps, input) {
95326
95641
  const identity = await requestIdentity(context, deps);
95327
95642
  const actorFence = getManagedAuthRequestActorLeaseStamp(context.req.raw);
95328
95643
  if (deps.settings.managedAuthSessionSetMode !== "legacy" && !actorFence) {
95329
- throw new HTTPException85(409, { message: "Managed actor mutation fence is unavailable" });
95644
+ throw new HTTPException87(409, { message: "Managed actor mutation fence is unavailable" });
95330
95645
  }
95331
95646
  try {
95332
95647
  const response = CanonicalHumanIdentityMutationResponse.parse(
@@ -95474,15 +95789,15 @@ import {
95474
95789
  updateOrganizationPrivateSessionSettings,
95475
95790
  updateOrganizationRetentionPolicy
95476
95791
  } from "@opengeni/db";
95477
- import { HTTPException as HTTPException86 } from "hono/http-exception";
95478
- import { z as z34 } from "zod";
95479
- var OrganizationId2 = z34.string().uuid();
95480
- var WorkspaceId = z34.string().uuid();
95481
- var MembershipId = z34.string().uuid();
95482
- var InvitationId = z34.string().uuid();
95792
+ import { HTTPException as HTTPException88 } from "hono/http-exception";
95793
+ import { z as z35 } from "zod";
95794
+ var OrganizationId2 = z35.string().uuid();
95795
+ var WorkspaceId = z35.string().uuid();
95796
+ var MembershipId = z35.string().uuid();
95797
+ var InvitationId = z35.string().uuid();
95483
95798
  async function requireManagedHuman(context, deps) {
95484
95799
  if (deps.settings.productAccessMode !== "managed" || !deps.managedAuth || !context.req.header("cookie") || context.req.header("authorization")) {
95485
- throw new HTTPException86(401, { message: "managed human session required" });
95800
+ throw new HTTPException88(401, { message: "managed human session required" });
95486
95801
  }
95487
95802
  const session = await getManagedSession3(context, deps.managedAuth, {
95488
95803
  db: deps.db,
@@ -95490,7 +95805,7 @@ async function requireManagedHuman(context, deps) {
95490
95805
  sessionSetMode: deps.settings.managedAuthSessionSetMode
95491
95806
  });
95492
95807
  if (!session?.user) {
95493
- throw new HTTPException86(401, { message: "managed human session required" });
95808
+ throw new HTTPException88(401, { message: "managed human session required" });
95494
95809
  }
95495
95810
  return { session, subjectId: `user:${session.user.id}` };
95496
95811
  }
@@ -95506,14 +95821,14 @@ async function requireOrganizationAdministrator(context, deps, organizationId2)
95506
95821
  );
95507
95822
  return { subjectId };
95508
95823
  }
95509
- throw new HTTPException86(401, {
95824
+ throw new HTTPException88(401, {
95510
95825
  message: "organization administrator session required"
95511
95826
  });
95512
95827
  }
95513
95828
  async function parseBody6(context, schema) {
95514
95829
  const parsed = schema.safeParse(await context.req.json().catch(() => null));
95515
95830
  if (!parsed.success) {
95516
- throw new HTTPException86(422, {
95831
+ throw new HTTPException88(422, {
95517
95832
  message: "invalid organization membership request"
95518
95833
  });
95519
95834
  }
@@ -95521,19 +95836,19 @@ async function parseBody6(context, schema) {
95521
95836
  }
95522
95837
  function parseId(schema, value, label) {
95523
95838
  const parsed = schema.safeParse(value);
95524
- if (!parsed.success) throw new HTTPException86(422, { message: `invalid ${label}` });
95839
+ if (!parsed.success) throw new HTTPException88(422, { message: `invalid ${label}` });
95525
95840
  return parsed.data;
95526
95841
  }
95527
95842
  function rethrowMembershipError(error, resourceLimitMessage) {
95528
95843
  const sqlState = nestedPostgresSqlState9(error);
95529
95844
  if (sqlState === "54000" && resourceLimitMessage) {
95530
- throw new HTTPException86(409, {
95845
+ throw new HTTPException88(409, {
95531
95846
  message: resourceLimitMessage
95532
95847
  });
95533
95848
  }
95534
95849
  const status = organizationMembershipHttpStatus(sqlState);
95535
95850
  if (status !== null) {
95536
- throw new HTTPException86(status, {
95851
+ throw new HTTPException88(status, {
95537
95852
  message: status === 403 ? "organization administration is not authorized" : status === 404 ? "organization resource not found" : status === 409 ? "organization membership state changed; refresh and retry" : "invalid organization membership operation"
95538
95853
  });
95539
95854
  }
@@ -95573,7 +95888,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95573
95888
  )
95574
95889
  );
95575
95890
  } catch (error) {
95576
- if (error instanceof HTTPException86) throw error;
95891
+ if (error instanceof HTTPException88) throw error;
95577
95892
  rethrowMembershipError(error);
95578
95893
  }
95579
95894
  });
@@ -95630,7 +95945,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95630
95945
  );
95631
95946
  } catch (error) {
95632
95947
  if (nestedPostgresSqlState9(error) === "42501") {
95633
- throw new HTTPException86(403, {
95948
+ throw new HTTPException88(403, {
95634
95949
  message: "organization membership is not active"
95635
95950
  });
95636
95951
  }
@@ -95641,7 +95956,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95641
95956
  const { session, subjectId } = await requireManagedHuman(context, deps);
95642
95957
  const query = ListOrganizationInvitationsPageQuery.safeParse(context.req.query());
95643
95958
  if (!query.success) {
95644
- throw new HTTPException86(422, {
95959
+ throw new HTTPException88(422, {
95645
95960
  message: "invalid organization invitation page"
95646
95961
  });
95647
95962
  }
@@ -95919,7 +96234,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95919
96234
  );
95920
96235
  } catch (error) {
95921
96236
  if (nestedPostgresSqlState9(error) === "55000") {
95922
- throw new HTTPException86(409, {
96237
+ throw new HTTPException88(409, {
95923
96238
  message: "private-session readiness is not activated for this organization"
95924
96239
  });
95925
96240
  }
@@ -95937,7 +96252,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95937
96252
  try {
95938
96253
  assertOrganizationUserSetupDeliveryConfigured(deps.settings, deps.managedEmailTransport);
95939
96254
  } catch {
95940
- throw new HTTPException86(503, {
96255
+ throw new HTTPException88(503, {
95941
96256
  message: "invited-user account setup delivery is not configured on this deployment"
95942
96257
  });
95943
96258
  }
@@ -95973,7 +96288,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95973
96288
  201
95974
96289
  );
95975
96290
  } catch (error) {
95976
- if (error instanceof HTTPException86) throw error;
96291
+ if (error instanceof HTTPException88) throw error;
95977
96292
  rethrowMembershipError(error);
95978
96293
  }
95979
96294
  });
@@ -95986,7 +96301,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
95986
96301
  );
95987
96302
  const query = ListOrganizationInvitationsPageQuery.safeParse(context.req.query());
95988
96303
  if (!query.success) {
95989
- throw new HTTPException86(422, {
96304
+ throw new HTTPException88(422, {
95990
96305
  message: "invalid organization invitation page"
95991
96306
  });
95992
96307
  }
@@ -96023,7 +96338,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
96023
96338
  try {
96024
96339
  assertOrganizationUserSetupDeliveryConfigured(deps.settings, deps.managedEmailTransport);
96025
96340
  } catch {
96026
- throw new HTTPException86(503, {
96341
+ throw new HTTPException88(503, {
96027
96342
  message: "invited-user account setup delivery is not configured on this deployment"
96028
96343
  });
96029
96344
  }
@@ -96070,7 +96385,7 @@ function registerOrganizationMembershipRoutes(app, deps) {
96070
96385
  membership: OrganizationMember.parse(result.membership)
96071
96386
  });
96072
96387
  } catch (error) {
96073
- if (error instanceof HTTPException86) throw error;
96388
+ if (error instanceof HTTPException88) throw error;
96074
96389
  rethrowMembershipError(error);
96075
96390
  }
96076
96391
  });
@@ -96252,12 +96567,12 @@ import {
96252
96567
  } from "@opengeni/contracts";
96253
96568
  import {
96254
96569
  accountScopedApiKeyWorkspaceAuthority as accountScopedApiKeyWorkspaceAuthority3,
96255
- hasPermission as hasPermission21,
96570
+ hasPermission as hasPermission22,
96256
96571
  requireAccessContext as requireAccessContext4,
96257
- requireAccessGrantAuthorization as requireAccessGrantAuthorization33,
96572
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization34,
96258
96573
  requireSessionAuthorizationListScope as requireSessionAuthorizationListScope3,
96259
- SessionAuthorizationDeniedError as SessionAuthorizationDeniedError13,
96260
- SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError11
96574
+ SessionAuthorizationDeniedError as SessionAuthorizationDeniedError14,
96575
+ SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError12
96261
96576
  } from "@opengeni/core";
96262
96577
  import {
96263
96578
  decodeSessionListCursor as decodeSessionListCursor2,
@@ -96267,14 +96582,14 @@ import {
96267
96582
  SessionListCursorError as SessionListCursorError2,
96268
96583
  SessionListCursorExpiredError as SessionListCursorExpiredError2
96269
96584
  } from "@opengeni/db";
96270
- import { HTTPException as HTTPException87 } from "hono/http-exception";
96271
- import { z as z35 } from "zod";
96585
+ import { HTTPException as HTTPException89 } from "hono/http-exception";
96586
+ import { z as z36 } from "zod";
96272
96587
  var ORGANIZATION_SESSION_LIST_MAX_WORKSPACE_READS = 25;
96273
- var OrganizationId3 = z35.string().uuid();
96274
- var OrganizationSessionListCursorEnvelope = z35.object({
96275
- workspaceId: z35.string().uuid(),
96276
- cursor: z35.string().min(1).nullable(),
96277
- pinnedOffset: z35.number().int().nonnegative().max(1e4).optional()
96588
+ var OrganizationId3 = z36.string().uuid();
96589
+ var OrganizationSessionListCursorEnvelope = z36.object({
96590
+ workspaceId: z36.string().uuid(),
96591
+ cursor: z36.string().min(1).nullable(),
96592
+ pinnedOffset: z36.number().int().nonnegative().max(1e4).optional()
96278
96593
  }).strict();
96279
96594
  function encodeOrganizationSessionListCursor(cursor) {
96280
96595
  return Buffer.from(JSON.stringify(cursor)).toString("base64url");
@@ -96296,10 +96611,10 @@ function decodeOrganizationSessionListCursor(value) {
96296
96611
  function requireOrganizationSessionReadAuthority(context, organizationId2) {
96297
96612
  const authority = accountScopedApiKeyWorkspaceAuthority3(context);
96298
96613
  if (authority) {
96299
- if (authority.accountId === organizationId2 && hasPermission21(authority.permissions, "sessions:read")) {
96614
+ if (authority.accountId === organizationId2 && hasPermission22(authority.permissions, "sessions:read")) {
96300
96615
  return "organization_api_key";
96301
96616
  }
96302
- throw new HTTPException87(403, { message: "organization session read authority required" });
96617
+ throw new HTTPException89(403, { message: "organization session read authority required" });
96303
96618
  }
96304
96619
  const accountGrant = context.accountGrants.find(
96305
96620
  (candidate) => candidate.accountId === organizationId2
@@ -96307,16 +96622,16 @@ function requireOrganizationSessionReadAuthority(context, organizationId2) {
96307
96622
  if (accountGrant?.permissions.includes("account:admin")) {
96308
96623
  return "account_admin";
96309
96624
  }
96310
- throw new HTTPException87(403, { message: "organization session read authority required" });
96625
+ throw new HTTPException89(403, { message: "organization session read authority required" });
96311
96626
  }
96312
96627
  function sessionAuthorizationHttpError2(error) {
96313
- if (error instanceof SessionAuthorizationDeniedError13) {
96314
- return new HTTPException87(404, { message: "session not found" });
96628
+ if (error instanceof SessionAuthorizationDeniedError14) {
96629
+ return new HTTPException89(404, { message: "session not found" });
96315
96630
  }
96316
- if (error instanceof SessionAuthorizationUnavailableError11) {
96317
- return new HTTPException87(503, { message: "session authorization is unavailable" });
96631
+ if (error instanceof SessionAuthorizationUnavailableError12) {
96632
+ return new HTTPException89(503, { message: "session authorization is unavailable" });
96318
96633
  }
96319
- if (error instanceof HTTPException87) return error;
96634
+ if (error instanceof HTTPException89) return error;
96320
96635
  throw error;
96321
96636
  }
96322
96637
  function compareWorkspaceIds(left, right) {
@@ -96326,7 +96641,7 @@ function registerOrganizationSessionRoutes(app, deps) {
96326
96641
  app.get("/v1/organizations/:organizationId/sessions", async (c) => {
96327
96642
  const organizationIdResult = OrganizationId3.safeParse(c.req.param("organizationId"));
96328
96643
  if (!organizationIdResult.success) {
96329
- throw new HTTPException87(422, { message: "invalid organization id" });
96644
+ throw new HTTPException89(422, { message: "invalid organization id" });
96330
96645
  }
96331
96646
  const organizationId2 = organizationIdResult.data;
96332
96647
  const context = await requireAccessContext4(c, deps);
@@ -96334,14 +96649,14 @@ function registerOrganizationSessionRoutes(app, deps) {
96334
96649
  const queryResult = ListOrganizationSessionsQuery.safeParse(c.req.query());
96335
96650
  if (!queryResult.success) {
96336
96651
  const issue = queryResult.error.issues[0];
96337
- throw new HTTPException87(400, {
96652
+ throw new HTTPException89(400, {
96338
96653
  message: issue ? `${issue.path.length > 0 ? `${issue.path.join(".")}: ` : ""}${issue.message}` : "invalid organization session list query"
96339
96654
  });
96340
96655
  }
96341
96656
  const query = queryResult.data;
96342
96657
  const cursor = query.cursor ? decodeOrganizationSessionListCursor(query.cursor) : null;
96343
96658
  if (query.cursor && !cursor) {
96344
- throw new HTTPException87(400, { message: "cursor is invalid" });
96659
+ throw new HTTPException89(400, { message: "cursor is invalid" });
96345
96660
  }
96346
96661
  const workspaces = (await listSharedWorkspacesForAccount2(deps.db, organizationId2)).sort(
96347
96662
  compareWorkspaceIds
@@ -96405,14 +96720,14 @@ function registerOrganizationSessionRoutes(app, deps) {
96405
96720
  async function listWorkspaceSessionPage(c, deps, input) {
96406
96721
  let authorization;
96407
96722
  try {
96408
- authorization = await requireAccessGrantAuthorization33(
96723
+ authorization = await requireAccessGrantAuthorization34(
96409
96724
  c,
96410
96725
  deps,
96411
96726
  input.workspace.id,
96412
96727
  "sessions:read"
96413
96728
  );
96414
96729
  } catch (error) {
96415
- if (input.readAuthority === "account_admin" && error instanceof HTTPException87 && error.status === 403) {
96730
+ if (input.readAuthority === "account_admin" && error instanceof HTTPException89 && error.status === 403) {
96416
96731
  return null;
96417
96732
  }
96418
96733
  throw error;
@@ -96426,7 +96741,7 @@ async function listWorkspaceSessionPage(c, deps, input) {
96426
96741
  }
96427
96742
  const cursor = input.innerCursor ? decodeSessionListCursor2(input.innerCursor) : null;
96428
96743
  if (input.innerCursor && !cursor) {
96429
- throw new HTTPException87(400, { message: "cursor is invalid" });
96744
+ throw new HTTPException89(400, { message: "cursor is invalid" });
96430
96745
  }
96431
96746
  try {
96432
96747
  const list = async (limit) => await listSessionsForSubject2(deps.db, input.workspace.id, {
@@ -96459,13 +96774,13 @@ async function listWorkspaceSessionPage(c, deps, input) {
96459
96774
  return { sessions: withStatus(rows), nextCursor: page.nextCursor, nextPinnedOffset };
96460
96775
  } catch (error) {
96461
96776
  if (error instanceof SessionListAccessError2) {
96462
- throw new HTTPException87(403, { message: error.message });
96777
+ throw new HTTPException89(403, { message: error.message });
96463
96778
  }
96464
96779
  if (error instanceof SessionListCursorExpiredError2) {
96465
- throw new HTTPException87(410, { message: error.message });
96780
+ throw new HTTPException89(410, { message: error.message });
96466
96781
  }
96467
96782
  if (error instanceof SessionListCursorError2) {
96468
- throw new HTTPException87(400, { message: error.message });
96783
+ throw new HTTPException89(400, { message: error.message });
96469
96784
  }
96470
96785
  throw error;
96471
96786
  }
@@ -96500,10 +96815,10 @@ import {
96500
96815
  OrganizationRecoveryUnavailableError,
96501
96816
  startOrganizationRecoveryOperation
96502
96817
  } from "@opengeni/db";
96503
- import { HTTPException as HTTPException88 } from "hono/http-exception";
96504
- import { z as z36 } from "zod";
96505
- var OrganizationId4 = z36.string().uuid();
96506
- var RecoveryOperationId = z36.string().uuid();
96818
+ import { HTTPException as HTTPException90 } from "hono/http-exception";
96819
+ import { z as z37 } from "zod";
96820
+ var OrganizationId4 = z37.string().uuid();
96821
+ var RecoveryOperationId = z37.string().uuid();
96507
96822
  var productionServices = {
96508
96823
  requireCanonicalHumanRequestIdentity: requireCanonicalHumanRequestIdentity2,
96509
96824
  getManagedAuthRequestActorAdmissionStamp,
@@ -96519,7 +96834,7 @@ var productionServices = {
96519
96834
  };
96520
96835
  async function requireRecoveryIdentity(context, deps, services) {
96521
96836
  if (deps.settings.productAccessMode !== "managed" || !deps.managedAuth || !context.req.header("cookie") || context.req.header("authorization")) {
96522
- throw new HTTPException88(401, {
96837
+ throw new HTTPException90(401, {
96523
96838
  message: "Managed human authentication required"
96524
96839
  });
96525
96840
  }
@@ -96535,7 +96850,7 @@ async function requireRecoveryIdentity(context, deps, services) {
96535
96850
  async function parseBody7(context, schema) {
96536
96851
  const parsed = schema.safeParse(await context.req.json().catch(() => null));
96537
96852
  if (!parsed.success) {
96538
- throw new HTTPException88(422, {
96853
+ throw new HTTPException90(422, {
96539
96854
  message: "Invalid organization recovery request"
96540
96855
  });
96541
96856
  }
@@ -96543,7 +96858,7 @@ async function parseBody7(context, schema) {
96543
96858
  }
96544
96859
  function parseId2(schema, value, label) {
96545
96860
  const parsed = schema.safeParse(value);
96546
- if (!parsed.success) throw new HTTPException88(422, { message: `Invalid ${label}` });
96861
+ if (!parsed.success) throw new HTTPException90(422, { message: `Invalid ${label}` });
96547
96862
  return parsed.data;
96548
96863
  }
96549
96864
  function organizationId(context) {
@@ -96598,12 +96913,12 @@ function organizationRecoveryHttpError(error) {
96598
96913
  function requireActorFence(context, deps, services) {
96599
96914
  const actorFence = services.getManagedAuthRequestActorLeaseStamp(context.req.raw);
96600
96915
  if (deps.settings.managedAuthSessionSetMode !== "legacy" && !actorFence) {
96601
- throw new HTTPException88(409, {
96916
+ throw new HTTPException90(409, {
96602
96917
  message: "Managed actor mutation fence is unavailable"
96603
96918
  });
96604
96919
  }
96605
96920
  if (!actorFence) {
96606
- throw new HTTPException88(409, {
96921
+ throw new HTTPException90(409, {
96607
96922
  message: "Organization recovery requires provider-neutral browser login slots"
96608
96923
  });
96609
96924
  }
@@ -96758,7 +97073,7 @@ import {
96758
97073
  preflightOrganizationUserSetup,
96759
97074
  previewOrganizationUserSetup
96760
97075
  } from "@opengeni/db";
96761
- import { HTTPException as HTTPException89 } from "hono/http-exception";
97076
+ import { HTTPException as HTTPException91 } from "hono/http-exception";
96762
97077
  var completedSetupReplayPasswordHash = `completed-replay:${"0".repeat(64)}`;
96763
97078
  function registerManagedOnboardingRoutes(app, deps, options = {}) {
96764
97079
  const accountSetupLimiter = options.accountSetupLimiter ?? new PublicSetupRateLimiter();
@@ -96781,7 +97096,7 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
96781
97096
  await context.req.json().catch(() => null)
96782
97097
  );
96783
97098
  if (!parsed.success) {
96784
- throw new HTTPException89(422, {
97099
+ throw new HTTPException91(422, {
96785
97100
  message: "invalid organization setup request"
96786
97101
  });
96787
97102
  }
@@ -96805,17 +97120,17 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
96805
97120
  } catch (error) {
96806
97121
  const sqlState = nestedPostgresSqlState10(error);
96807
97122
  if (sqlState === "22023") {
96808
- throw new HTTPException89(422, {
97123
+ throw new HTTPException91(422, {
96809
97124
  message: "invalid organization setup request"
96810
97125
  });
96811
97126
  }
96812
97127
  if (sqlState === "42501") {
96813
- throw new HTTPException89(403, {
97128
+ throw new HTTPException91(403, {
96814
97129
  message: "verified managed user required"
96815
97130
  });
96816
97131
  }
96817
97132
  if (sqlState === "23505" || sqlState === "55000") {
96818
- throw new HTTPException89(409, {
97133
+ throw new HTTPException91(409, {
96819
97134
  message: "organization setup is no longer available; refresh to continue"
96820
97135
  });
96821
97136
  }
@@ -96824,14 +97139,14 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
96824
97139
  });
96825
97140
  app.post("/v1/auth/organization-setup/preview", async (context) => {
96826
97141
  if (deps.settings.productAccessMode !== "managed" || !deps.managedAuth) {
96827
- throw new HTTPException89(404, { message: "account setup is unavailable" });
97142
+ throw new HTTPException91(404, { message: "account setup is unavailable" });
96828
97143
  }
96829
97144
  enforceAccountSetupRateLimit(context, accountSetupLimiter);
96830
97145
  const parsed = PreviewOrganizationUserSetupRequest.safeParse(
96831
97146
  await context.req.json().catch(() => null)
96832
97147
  );
96833
97148
  if (!parsed.success) {
96834
- throw new HTTPException89(422, { message: "invalid account setup preview request" });
97149
+ throw new HTTPException91(422, { message: "invalid account setup preview request" });
96835
97150
  }
96836
97151
  return context.json(
96837
97152
  OrganizationUserSetupPreview.parse(
@@ -96844,14 +97159,14 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
96844
97159
  });
96845
97160
  app.post("/v1/auth/organization-setup", async (context) => {
96846
97161
  if (deps.settings.productAccessMode !== "managed" || !deps.managedAuth) {
96847
- throw new HTTPException89(404, { message: "account setup is unavailable" });
97162
+ throw new HTTPException91(404, { message: "account setup is unavailable" });
96848
97163
  }
96849
97164
  enforceAccountSetupRateLimit(context, accountSetupLimiter);
96850
97165
  const parsed = CompleteOrganizationUserSetupRequest.safeParse(
96851
97166
  await context.req.json().catch(() => null)
96852
97167
  );
96853
97168
  if (!parsed.success) {
96854
- throw new HTTPException89(422, {
97169
+ throw new HTTPException91(422, {
96855
97170
  message: "invalid account setup request"
96856
97171
  });
96857
97172
  }
@@ -96859,7 +97174,7 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
96859
97174
  const tokenDigest = await organizationUserSetupTokenDigest(parsed.data.token);
96860
97175
  const preflight = await preflightOrganizationUserSetup(deps.db, tokenDigest);
96861
97176
  if (preflight === "unavailable") {
96862
- throw new HTTPException89(404, {
97177
+ throw new HTTPException91(404, {
96863
97178
  message: "account setup link is invalid, expired, or already belongs to an account"
96864
97179
  });
96865
97180
  }
@@ -96885,17 +97200,17 @@ function registerManagedOnboardingRoutes(app, deps, options = {}) {
96885
97200
  } catch (error) {
96886
97201
  const sqlState = nestedPostgresSqlState10(error);
96887
97202
  if (sqlState === "22023") {
96888
- throw new HTTPException89(422, {
97203
+ throw new HTTPException91(422, {
96889
97204
  message: "invalid account setup request"
96890
97205
  });
96891
97206
  }
96892
97207
  if (sqlState === "23505") {
96893
- throw new HTTPException89(409, {
97208
+ throw new HTTPException91(409, {
96894
97209
  message: "account setup request changed; reopen the original link and try again"
96895
97210
  });
96896
97211
  }
96897
97212
  if (sqlState === "P0002" || sqlState === "42501" || sqlState === "55000") {
96898
- throw new HTTPException89(404, {
97213
+ throw new HTTPException91(404, {
96899
97214
  message: "account setup link is invalid, expired, or already belongs to an account"
96900
97215
  });
96901
97216
  }
@@ -96910,7 +97225,7 @@ function enforceAccountSetupRateLimit(context, limiter) {
96910
97225
  } catch {
96911
97226
  }
96912
97227
  if (!allowed2) {
96913
- throw new HTTPException89(429, { message: "too many account setup requests; slow down" });
97228
+ throw new HTTPException91(429, { message: "too many account setup requests; slow down" });
96914
97229
  }
96915
97230
  }
96916
97231
  function accountSetupClientKey(context) {
@@ -96978,7 +97293,7 @@ function refillSetupRateLimitBucket(bucket, capacity, refillPerSecond, now) {
96978
97293
  }
96979
97294
  async function requireManagedHuman2(context, deps) {
96980
97295
  if (deps.settings.productAccessMode !== "managed" || !deps.managedAuth || !context.req.header("cookie") || context.req.header("authorization")) {
96981
- throw new HTTPException89(401, { message: "managed human session required" });
97296
+ throw new HTTPException91(401, { message: "managed human session required" });
96982
97297
  }
96983
97298
  const session = await getManagedSession4(context, deps.managedAuth, {
96984
97299
  db: deps.db,
@@ -96986,7 +97301,7 @@ async function requireManagedHuman2(context, deps) {
96986
97301
  sessionSetMode: deps.settings.managedAuthSessionSetMode
96987
97302
  });
96988
97303
  if (!session?.user) {
96989
- throw new HTTPException89(401, { message: "managed human session required" });
97304
+ throw new HTTPException91(401, { message: "managed human session required" });
96990
97305
  }
96991
97306
  return session;
96992
97307
  }
@@ -97013,7 +97328,7 @@ import {
97013
97328
  StartManagedAuthSocialTransactionRequest,
97014
97329
  StartManagedAuthSocialTransactionResponse
97015
97330
  } from "@opengeni/contracts/managed-auth-session-sets";
97016
- import { hasPermission as hasPermission22, requireSessionAuthorization as requireSessionAuthorization14 } from "@opengeni/core";
97331
+ import { hasPermission as hasPermission23, requireSessionAuthorization as requireSessionAuthorization15 } from "@opengeni/core";
97017
97332
  import {
97018
97333
  authenticateAndAdoptManagedAuthSession,
97019
97334
  isolatedManagedAuthHeaders,
@@ -97053,13 +97368,13 @@ import {
97053
97368
  } from "@opengeni/db/managed-auth-session-sets";
97054
97369
  import { ensureManagedAccessForUser as ensureManagedAccessForUser2, getSession as getSession10 } from "@opengeni/db";
97055
97370
  import { deleteCookie as deleteCookie3, getCookie, setCookie as setCookie3 } from "hono/cookie";
97056
- import { HTTPException as HTTPException90 } from "hono/http-exception";
97057
- import { z as z37 } from "zod";
97058
- var ManagedAuthSocialStartReceipt = z37.object({
97059
- version: z37.literal(1),
97060
- requestDigest: z37.string().regex(/^[0-9a-f]{64}$/u),
97061
- url: z37.string().url().max(4096),
97062
- stateCookie: z37.string().min(1).max(4096)
97371
+ import { HTTPException as HTTPException92 } from "hono/http-exception";
97372
+ import { z as z38 } from "zod";
97373
+ var ManagedAuthSocialStartReceipt = z38.object({
97374
+ version: z38.literal(1),
97375
+ requestDigest: z38.string().regex(/^[0-9a-f]{64}$/u),
97376
+ url: z38.string().url().max(4096),
97377
+ stateCookie: z38.string().min(1).max(4096)
97063
97378
  }).strict();
97064
97379
  function registerManagedAuthSessionSetRoutes(app, deps) {
97065
97380
  const noStore = async (context, next) => {
@@ -97080,7 +97395,7 @@ function registerManagedAuthSessionSetRoutes(app, deps) {
97080
97395
  app.use("/v1/auth/session-set/*", noStore);
97081
97396
  app.get("/v1/auth/get-session", async (context) => {
97082
97397
  if (deps.settings.managedAuthSessionSetMode === "legacy") {
97083
- if (!deps.managedAuth) throw new HTTPException90(404);
97398
+ if (!deps.managedAuth) throw new HTTPException92(404);
97084
97399
  return await deps.managedAuth.handler(context.req.raw);
97085
97400
  }
97086
97401
  context.header("cache-control", "no-store");
@@ -97685,14 +98000,14 @@ async function resolveCanonicalDeepLink(deps, authority, path, expectedActorEpoc
97685
98000
  const grants = target.workspaceId ? access.workspaceGrants.filter((grant) => grant.workspaceId === target.workspaceId) : access.workspaceGrants;
97686
98001
  let authorized = false;
97687
98002
  for (const grant of grants) {
97688
- if (!hasPermission22(grant.permissions, target.sessionId ? "sessions:read" : target.permission)) {
98003
+ if (!hasPermission23(grant.permissions, target.sessionId ? "sessions:read" : target.permission)) {
97689
98004
  continue;
97690
98005
  }
97691
98006
  if (target.sessionId) {
97692
98007
  const session = await getSession10(deps.db, grant.workspaceId, target.sessionId);
97693
98008
  if (!session) continue;
97694
98009
  try {
97695
- await requireSessionAuthorization14(deps, grant, {
98010
+ await requireSessionAuthorization15(deps, grant, {
97696
98011
  sessionId: target.sessionId,
97697
98012
  operation: "session.read",
97698
98013
  surface: "http"
@@ -97919,7 +98234,7 @@ function appendCookies(context, cookies) {
97919
98234
  for (const cookie of cookies) context.header("set-cookie", cookie, { append: true });
97920
98235
  }
97921
98236
  function throwHttp(error) {
97922
- if (error instanceof HTTPException90) throw error;
98237
+ if (error instanceof HTTPException92) throw error;
97923
98238
  if (error instanceof ManagedAuthSessionSetGenerationConflictError) {
97924
98239
  throw managedAuthApiError(409, "generation_conflict", { cause: error, retryable: true });
97925
98240
  }
@@ -97988,32 +98303,32 @@ import {
97988
98303
  import {
97989
98304
  issueManagedHumanUserResourceGrant,
97990
98305
  listManagedHumanUserResourceAuthorities,
97991
- requireAccessGrantAuthorization as requireAccessGrantAuthorization34,
98306
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization35,
97992
98307
  revokeManagedHumanUserResourceGrant,
97993
- SessionAuthorizationDeniedError as SessionAuthorizationDeniedError14,
97994
- SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError12,
98308
+ SessionAuthorizationDeniedError as SessionAuthorizationDeniedError15,
98309
+ SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError13,
97995
98310
  SessionTenancyManagedHumanRequiredError as SessionTenancyManagedHumanRequiredError2
97996
98311
  } from "@opengeni/core";
97997
98312
  import { nestedPostgresSqlState as nestedPostgresSqlState11, SessionTenancyNotActivatedError as SessionTenancyNotActivatedError2 } from "@opengeni/db";
97998
- import { HTTPException as HTTPException91 } from "hono/http-exception";
97999
- import { z as z38 } from "zod";
98313
+ import { HTTPException as HTTPException93 } from "hono/http-exception";
98314
+ import { z as z39 } from "zod";
98000
98315
  async function body2(context, schema) {
98001
98316
  const parsed = schema.safeParse(await context.req.json().catch(() => null));
98002
- if (!parsed.success) throw new HTTPException91(422, { message: "invalid user-resource request" });
98317
+ if (!parsed.success) throw new HTTPException93(422, { message: "invalid user-resource request" });
98003
98318
  return parsed.data;
98004
98319
  }
98005
98320
  function lifecycleError(error) {
98006
- if (error instanceof SessionAuthorizationDeniedError14 || error instanceof SessionTenancyManagedHumanRequiredError2 || error instanceof SessionTenancyNotActivatedError2) {
98007
- throw new HTTPException91(403, { message: "user-resource authority denied" });
98321
+ if (error instanceof SessionAuthorizationDeniedError15 || error instanceof SessionTenancyManagedHumanRequiredError2 || error instanceof SessionTenancyNotActivatedError2) {
98322
+ throw new HTTPException93(403, { message: "user-resource authority denied" });
98008
98323
  }
98009
- if (error instanceof SessionAuthorizationUnavailableError12) {
98010
- throw new HTTPException91(503, { message: "session authorization unavailable" });
98324
+ if (error instanceof SessionAuthorizationUnavailableError13) {
98325
+ throw new HTTPException93(503, { message: "session authorization unavailable" });
98011
98326
  }
98012
98327
  if (nestedPostgresSqlState11(error) === "42501") {
98013
- throw new HTTPException91(403, { message: "user-resource authority denied" });
98328
+ throw new HTTPException93(403, { message: "user-resource authority denied" });
98014
98329
  }
98015
98330
  if (nestedPostgresSqlState11(error) === "22023") {
98016
- throw new HTTPException91(422, { message: "invalid user-resource request" });
98331
+ throw new HTTPException93(422, { message: "invalid user-resource request" });
98017
98332
  }
98018
98333
  throw error;
98019
98334
  }
@@ -98026,9 +98341,9 @@ function registerUserResourceAuthorityRoutes(app, deps) {
98026
98341
  cursor: context.req.query("cursor"),
98027
98342
  limit: context.req.query("limit")
98028
98343
  });
98029
- if (!query.success) throw new HTTPException91(422, { message: "explicit scope=user required" });
98344
+ if (!query.success) throw new HTTPException93(422, { message: "explicit scope=user required" });
98030
98345
  const workspaceId = context.req.param("workspaceId");
98031
- const access = await requireAccessGrantAuthorization34(
98346
+ const access = await requireAccessGrantAuthorization35(
98032
98347
  context,
98033
98348
  deps,
98034
98349
  workspaceId,
@@ -98053,10 +98368,10 @@ function registerUserResourceAuthorityRoutes(app, deps) {
98053
98368
  });
98054
98369
  app.post(`${base}/:authorityId/grants`, async (context) => {
98055
98370
  const workspaceId = context.req.param("workspaceId");
98056
- const authorityId = z38.string().uuid().safeParse(context.req.param("authorityId"));
98057
- if (!authorityId.success) throw new HTTPException91(422, { message: "invalid authority id" });
98371
+ const authorityId = z39.string().uuid().safeParse(context.req.param("authorityId"));
98372
+ if (!authorityId.success) throw new HTTPException93(422, { message: "invalid authority id" });
98058
98373
  const request = await body2(context, IssueUserResourceGrantRequest);
98059
- const access = await requireAccessGrantAuthorization34(
98374
+ const access = await requireAccessGrantAuthorization35(
98060
98375
  context,
98061
98376
  deps,
98062
98377
  workspaceId,
@@ -98082,11 +98397,11 @@ function registerUserResourceAuthorityRoutes(app, deps) {
98082
98397
  });
98083
98398
  app.delete(`${base}/grants/:grantId`, async (context) => {
98084
98399
  const query = RevokeUserResourceGrantQuery.safeParse({ scope: context.req.query("scope") });
98085
- if (!query.success) throw new HTTPException91(422, { message: "explicit scope=user required" });
98086
- const grantId = z38.string().uuid().safeParse(context.req.param("grantId"));
98087
- if (!grantId.success) throw new HTTPException91(422, { message: "invalid grant id" });
98400
+ if (!query.success) throw new HTTPException93(422, { message: "explicit scope=user required" });
98401
+ const grantId = z39.string().uuid().safeParse(context.req.param("grantId"));
98402
+ if (!grantId.success) throw new HTTPException93(422, { message: "invalid grant id" });
98088
98403
  const workspaceId = context.req.param("workspaceId");
98089
- const access = await requireAccessGrantAuthorization34(
98404
+ const access = await requireAccessGrantAuthorization35(
98090
98405
  context,
98091
98406
  deps,
98092
98407
  workspaceId,
@@ -98116,22 +98431,22 @@ import {
98116
98431
  import {
98117
98432
  issueManagedHumanUserResourceGrant as issueManagedHumanUserResourceGrant2,
98118
98433
  listManagedHumanUserResourceAuthorities as listManagedHumanUserResourceAuthorities2,
98119
- requireAccessGrantAuthorization as requireAccessGrantAuthorization35,
98434
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization36,
98120
98435
  revokeManagedHumanUserResourceGrant as revokeManagedHumanUserResourceGrant2,
98121
- SessionAuthorizationDeniedError as SessionAuthorizationDeniedError15,
98122
- SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError13,
98436
+ SessionAuthorizationDeniedError as SessionAuthorizationDeniedError16,
98437
+ SessionAuthorizationUnavailableError as SessionAuthorizationUnavailableError14,
98123
98438
  SessionTenancyManagedHumanRequiredError as SessionTenancyManagedHumanRequiredError3
98124
98439
  } from "@opengeni/core";
98125
98440
  import { nestedPostgresSqlState as nestedPostgresSqlState12, SessionTenancyNotActivatedError as SessionTenancyNotActivatedError3 } from "@opengeni/db";
98126
- import { HTTPException as HTTPException93 } from "hono/http-exception";
98127
- import { z as z39 } from "zod";
98441
+ import { HTTPException as HTTPException95 } from "hono/http-exception";
98442
+ import { z as z40 } from "zod";
98128
98443
 
98129
98444
  // src/connection-authority-owner.ts
98130
98445
  import {
98131
98446
  IssueConnectionUseGrantRequest,
98132
98447
  ListConnectionAuthoritiesResponse
98133
98448
  } from "@opengeni/contracts/connection-authority";
98134
- import { HTTPException as HTTPException92 } from "hono/http-exception";
98449
+ import { HTTPException as HTTPException94 } from "hono/http-exception";
98135
98450
  function projectSelfConnectionAuthorities(page) {
98136
98451
  return ListConnectionAuthoritiesResponse.parse({
98137
98452
  scope: "user",
@@ -98154,21 +98469,21 @@ function connectionUseGrantLifecycleInput(input) {
98154
98469
  // src/routes/connection-authorities.ts
98155
98470
  async function body3(context, schema) {
98156
98471
  const parsed = schema.safeParse(await context.req.json().catch(() => null));
98157
- if (!parsed.success) throw new HTTPException93(422, { message: "invalid connection authority" });
98472
+ if (!parsed.success) throw new HTTPException95(422, { message: "invalid connection authority" });
98158
98473
  return parsed.data;
98159
98474
  }
98160
98475
  function lifecycleError2(error) {
98161
- if (error instanceof SessionAuthorizationDeniedError15 || error instanceof SessionTenancyManagedHumanRequiredError3 || error instanceof SessionTenancyNotActivatedError3) {
98162
- throw new HTTPException93(403, { message: "connection authority denied" });
98476
+ if (error instanceof SessionAuthorizationDeniedError16 || error instanceof SessionTenancyManagedHumanRequiredError3 || error instanceof SessionTenancyNotActivatedError3) {
98477
+ throw new HTTPException95(403, { message: "connection authority denied" });
98163
98478
  }
98164
- if (error instanceof SessionAuthorizationUnavailableError13) {
98165
- throw new HTTPException93(503, { message: "session authorization unavailable" });
98479
+ if (error instanceof SessionAuthorizationUnavailableError14) {
98480
+ throw new HTTPException95(503, { message: "session authorization unavailable" });
98166
98481
  }
98167
98482
  if (nestedPostgresSqlState12(error) === "42501") {
98168
- throw new HTTPException93(403, { message: "connection authority denied" });
98483
+ throw new HTTPException95(403, { message: "connection authority denied" });
98169
98484
  }
98170
98485
  if (nestedPostgresSqlState12(error) === "22023") {
98171
- throw new HTTPException93(422, { message: "invalid connection authority" });
98486
+ throw new HTTPException95(422, { message: "invalid connection authority" });
98172
98487
  }
98173
98488
  throw error;
98174
98489
  }
@@ -98180,9 +98495,9 @@ function registerConnectionAuthorityRoutes(app, deps) {
98180
98495
  cursor: context.req.query("cursor"),
98181
98496
  limit: context.req.query("limit")
98182
98497
  });
98183
- if (!query.success) throw new HTTPException93(422, { message: "explicit scope=user required" });
98498
+ if (!query.success) throw new HTTPException95(422, { message: "explicit scope=user required" });
98184
98499
  const workspaceId = context.req.param("workspaceId");
98185
- const access = await requireAccessGrantAuthorization35(
98500
+ const access = await requireAccessGrantAuthorization36(
98186
98501
  context,
98187
98502
  deps,
98188
98503
  workspaceId,
@@ -98204,10 +98519,10 @@ function registerConnectionAuthorityRoutes(app, deps) {
98204
98519
  });
98205
98520
  app.post(`${base}/:authorityId/grants`, async (context) => {
98206
98521
  const workspaceId = context.req.param("workspaceId");
98207
- const authorityId = z39.string().uuid().safeParse(context.req.param("authorityId"));
98208
- if (!authorityId.success) throw new HTTPException93(422, { message: "invalid authority id" });
98522
+ const authorityId = z40.string().uuid().safeParse(context.req.param("authorityId"));
98523
+ if (!authorityId.success) throw new HTTPException95(422, { message: "invalid authority id" });
98209
98524
  const request = await body3(context, IssueConnectionUseGrantRequest2);
98210
- const access = await requireAccessGrantAuthorization35(
98525
+ const access = await requireAccessGrantAuthorization36(
98211
98526
  context,
98212
98527
  deps,
98213
98528
  workspaceId,
@@ -98234,11 +98549,11 @@ function registerConnectionAuthorityRoutes(app, deps) {
98234
98549
  });
98235
98550
  app.delete(`${base}/grants/:grantId`, async (context) => {
98236
98551
  const query = RevokeConnectionUseGrantQuery.safeParse({ scope: context.req.query("scope") });
98237
- if (!query.success) throw new HTTPException93(422, { message: "explicit scope=user required" });
98238
- const grantId = z39.string().uuid().safeParse(context.req.param("grantId"));
98239
- if (!grantId.success) throw new HTTPException93(422, { message: "invalid grant id" });
98552
+ if (!query.success) throw new HTTPException95(422, { message: "explicit scope=user required" });
98553
+ const grantId = z40.string().uuid().safeParse(context.req.param("grantId"));
98554
+ if (!grantId.success) throw new HTTPException95(422, { message: "invalid grant id" });
98240
98555
  const workspaceId = context.req.param("workspaceId");
98241
- const access = await requireAccessGrantAuthorization35(
98556
+ const access = await requireAccessGrantAuthorization36(
98242
98557
  context,
98243
98558
  deps,
98244
98559
  workspaceId,
@@ -98825,7 +99140,7 @@ async function exactAvailable(providers, providerId, context) {
98825
99140
  }
98826
99141
 
98827
99142
  // src/integrations/slack-interactions.ts
98828
- import { createHash as createHash29, createHmac as createHmac10, timingSafeEqual as timingSafeEqual3 } from "crypto";
99143
+ import { createHash as createHash30, createHmac as createHmac10, timingSafeEqual as timingSafeEqual3 } from "crypto";
98829
99144
  import {
98830
99145
  approvalIdentifier,
98831
99146
  ApproveSlackUserLinkAccessRequest,
@@ -98928,14 +99243,14 @@ import {
98928
99243
  acceptSessionUserMessage as acceptSessionUserMessage2,
98929
99244
  controlHumanSessionWorkstream as controlHumanSessionWorkstream2,
98930
99245
  createSessionForRequest as createSessionForRequest2,
98931
- hasPermission as hasPermission23,
99246
+ hasPermission as hasPermission24,
98932
99247
  requireAccessContext as requireAccessContext5,
98933
99248
  requireAccessGrant as requireAccessGrant46,
98934
99249
  requireSessionAuthorizationListScope as requireSessionAuthorizationListScope4,
98935
99250
  resolveWorkspaceCatalogSettings as resolveWorkspaceCatalogSettings9
98936
99251
  } from "@opengeni/core";
98937
99252
  import { publishDurableSessionEvents as publishDurableSessionEvents4 } from "@opengeni/events";
98938
- import { HTTPException as HTTPException94 } from "hono/http-exception";
99253
+ import { HTTPException as HTTPException96 } from "hono/http-exception";
98939
99254
 
98940
99255
  // src/integrations/slack-routing.ts
98941
99256
  function isSlackDirectMessageConversation(entry2) {
@@ -99303,7 +99618,7 @@ function record4(value) {
99303
99618
  }
99304
99619
 
99305
99620
  // src/slack-reaction-files.ts
99306
- import { createHash as createHash28 } from "crypto";
99621
+ import { createHash as createHash29 } from "crypto";
99307
99622
  import { completeFileUpload as completeFileUpload5, prepareGeneratedWorkspaceFile as prepareGeneratedWorkspaceFile2 } from "@opengeni/db";
99308
99623
  import { retryWhileMissing as retryWhileMissing7 } from "@opengeni/storage";
99309
99624
  var IMPORT_IDENTITY_VERSION = "slack-reaction-image-v1";
@@ -99320,7 +99635,7 @@ async function importSlackReactionImage(dependencies, source, image, ordinal) {
99320
99635
  if (image.bytes.byteLength < 1 || image.bytes.byteLength > 4 * 1024 * 1024) {
99321
99636
  throw new Error("Slack reaction image size is invalid");
99322
99637
  }
99323
- const sha2564 = createHash28("sha256").update(image.bytes).digest("hex");
99638
+ const sha2564 = createHash29("sha256").update(image.bytes).digest("hex");
99324
99639
  const identity = slackReactionImageIdentity(source, image.fileId);
99325
99640
  const fileId = deterministicUuid(`${identity}:file`);
99326
99641
  const uploadId = deterministicUuid(`${identity}:upload`);
@@ -99414,7 +99729,7 @@ function assertStoredSlackImage(head, image, sha2564) {
99414
99729
  }
99415
99730
  }
99416
99731
  function deterministicUuid(seed) {
99417
- const bytes = createHash28("sha256").update(seed, "utf8").digest().subarray(0, 16);
99732
+ const bytes = createHash29("sha256").update(seed, "utf8").digest().subarray(0, 16);
99418
99733
  bytes[6] = (bytes[6] ?? 0) & 15 | 80;
99419
99734
  bytes[8] = (bytes[8] ?? 0) & 63 | 128;
99420
99735
  const hex2 = bytes.toString("hex");
@@ -99573,7 +99888,7 @@ function slackReactionInboxEntry(payload, bot, settings) {
99573
99888
  if (!settings.enabled || !event || event.type !== "reaction_added" || item?.type !== "message" || !teamId || !eventId || !userId || userId === bot.botUserId || !reaction || reaction !== settings.emoji || !channelId || !workspaceSlackReactionChannelAllowed(settings, channelId) || !timestamp) {
99574
99889
  return null;
99575
99890
  }
99576
- const stableReactionIdentity = createHash29("sha256").update([teamId, userId, channelId, timestamp, reaction].join("\n")).digest("hex");
99891
+ const stableReactionIdentity = createHash30("sha256").update([teamId, userId, channelId, timestamp, reaction].join("\n")).digest("hex");
99577
99892
  return {
99578
99893
  providerEventId: eventId,
99579
99894
  providerMessageId: `reaction:${stableReactionIdentity}`,
@@ -99609,14 +99924,14 @@ function registerSlackInteractionRoutes(app, deps) {
99609
99924
  const payload = parseJsonObject(signed.rawBody);
99610
99925
  if (payload.type === "url_verification") {
99611
99926
  const challenge = boundedString(payload.challenge, 512);
99612
- if (!challenge) throw new HTTPException94(400, { message: "invalid Slack challenge" });
99927
+ if (!challenge) throw new HTTPException96(400, { message: "invalid Slack challenge" });
99613
99928
  return c.json({ challenge });
99614
99929
  }
99615
99930
  const teamId = boundedString(payload.team_id, 64);
99616
- if (!teamId) throw new HTTPException94(400, { message: "invalid Slack event" });
99931
+ if (!teamId) throw new HTTPException96(400, { message: "invalid Slack event" });
99617
99932
  const installation = await resolveSlackInstallationRoute(deps.db, teamId);
99618
99933
  if (!installation)
99619
- throw new HTTPException94(403, {
99934
+ throw new HTTPException96(403, {
99620
99935
  message: "Slack installation unavailable"
99621
99936
  });
99622
99937
  const event = record5(payload.event);
@@ -99659,12 +99974,12 @@ function registerSlackInteractionRoutes(app, deps) {
99659
99974
  const signed = await readSignedSlackRequest(c, deps);
99660
99975
  const form = new URLSearchParams(signed.rawBody);
99661
99976
  if (form.get("command") !== deps.settings.slackCommand) {
99662
- throw new HTTPException94(400, { message: "invalid Slack command" });
99977
+ throw new HTTPException96(400, { message: "invalid Slack command" });
99663
99978
  }
99664
99979
  const entry2 = normalizedFormInteraction(form, "slash_command");
99665
99980
  const installation = await resolveSlackInstallationRoute(deps.db, entry2.slackTeamId);
99666
99981
  if (!installation)
99667
- throw new HTTPException94(403, {
99982
+ throw new HTTPException96(403, {
99668
99983
  message: "Slack installation unavailable"
99669
99984
  });
99670
99985
  if (isSlackInfoCommand(entry2.text)) {
@@ -99701,13 +100016,13 @@ function registerSlackInteractionRoutes(app, deps) {
99701
100016
  const entry2 = normalizedBlockActionInteraction(payload);
99702
100017
  const installation2 = await resolveSlackInstallationRoute(deps.db, entry2.slackTeamId);
99703
100018
  if (!installation2) {
99704
- throw new HTTPException94(403, { message: "Slack installation unavailable" });
100019
+ throw new HTTPException96(403, { message: "Slack installation unavailable" });
99705
100020
  }
99706
100021
  await enqueueNormalizedSlackInteraction(deps, installation2, entry2);
99707
100022
  return c.json({ ok: true });
99708
100023
  }
99709
100024
  if (payload.type !== "message_action") {
99710
- throw new HTTPException94(400, {
100025
+ throw new HTTPException96(400, {
99711
100026
  message: "unsupported Slack interaction"
99712
100027
  });
99713
100028
  }
@@ -99723,13 +100038,13 @@ function registerSlackInteractionRoutes(app, deps) {
99723
100038
  const threadTs = boundedString(message?.thread_ts, 64);
99724
100039
  const text = boundedText(message?.text);
99725
100040
  if (!triggerId || !teamId || !userId || !channelId || !messageTs || !text) {
99726
- throw new HTTPException94(400, {
100041
+ throw new HTTPException96(400, {
99727
100042
  message: "invalid Slack message shortcut"
99728
100043
  });
99729
100044
  }
99730
100045
  const installation = await resolveSlackInstallationRoute(deps.db, teamId);
99731
100046
  if (!installation)
99732
- throw new HTTPException94(403, {
100047
+ throw new HTTPException96(403, {
99733
100048
  message: "Slack installation unavailable"
99734
100049
  });
99735
100050
  await enqueueNormalizedSlackInteraction(deps, installation, {
@@ -99763,7 +100078,7 @@ function registerSlackInteractionRoutes(app, deps) {
99763
100078
  const prepared = await prepareSlackUserLinkAccessRequest(deps.db, {
99764
100079
  accountId: installation.accountId,
99765
100080
  workspaceId,
99766
- tokenDigest: createHash29("sha256").update(payload.linkToken).digest("hex"),
100081
+ tokenDigest: createHash30("sha256").update(payload.linkToken).digest("hex"),
99767
100082
  connectionId: link.connectionId,
99768
100083
  slackTeamId: link.slackTeamId,
99769
100084
  slackUserId: link.slackUserId,
@@ -99950,19 +100265,19 @@ function registerSlackInteractionRoutes(app, deps) {
99950
100265
  const linkToken = boundedString(body4?.linkToken, 2048);
99951
100266
  const signingSecret = deps.settings.slackSigningSecret;
99952
100267
  if (!linkToken || !signingSecret) {
99953
- throw new HTTPException94(400, {
100268
+ throw new HTTPException96(400, {
99954
100269
  message: "invalid or expired Slack identity link"
99955
100270
  });
99956
100271
  }
99957
100272
  const link = verifySlackUserLinkToken(signingSecret, linkToken);
99958
100273
  if (!link || link.workspaceId !== workspaceId) {
99959
- throw new HTTPException94(400, {
100274
+ throw new HTTPException96(400, {
99960
100275
  message: "invalid or expired Slack identity link"
99961
100276
  });
99962
100277
  }
99963
100278
  const installation = await resolveSlackLinkTargetInstallation(deps, link, workspaceId);
99964
100279
  if (!installation) {
99965
- throw new HTTPException94(404, {
100280
+ throw new HTTPException96(404, {
99966
100281
  message: "Slack installation not found"
99967
100282
  });
99968
100283
  }
@@ -99970,7 +100285,7 @@ function registerSlackInteractionRoutes(app, deps) {
99970
100285
  const prepared = await prepareSlackUserLinkAccessRequest(deps.db, {
99971
100286
  accountId: grant.accountId,
99972
100287
  workspaceId,
99973
- tokenDigest: createHash29("sha256").update(linkToken).digest("hex"),
100288
+ tokenDigest: createHash30("sha256").update(linkToken).digest("hex"),
99974
100289
  connectionId: link.connectionId,
99975
100290
  slackTeamId: link.slackTeamId,
99976
100291
  slackUserId: link.slackUserId,
@@ -100003,7 +100318,7 @@ function registerSlackInteractionRoutes(app, deps) {
100003
100318
  const workspaceId = c.req.param("workspaceId");
100004
100319
  await requireAccessGrant46(c, deps, workspaceId, "connections:write");
100005
100320
  const connectionId = boundedString(c.req.query("connectionId"), 64);
100006
- if (!connectionId) throw new HTTPException94(400, { message: "connectionId is required" });
100321
+ if (!connectionId) throw new HTTPException96(400, { message: "connectionId is required" });
100007
100322
  return c.json({
100008
100323
  deleted: await deleteSlackBotUserLink(
100009
100324
  deps.db,
@@ -100018,7 +100333,7 @@ function registerSlackInteractionRoutes(app, deps) {
100018
100333
  const workspaceId = c.req.param("workspaceId");
100019
100334
  const grant = await requireAccessGrant46(c, deps, workspaceId, "workspace:admin");
100020
100335
  const connectionId = boundedString(c.req.query("connectionId"), 64);
100021
- if (!connectionId) throw new HTTPException94(400, { message: "connectionId is required" });
100336
+ if (!connectionId) throw new HTTPException96(400, { message: "connectionId is required" });
100022
100337
  const routes = await listSlackChannelRoutes(
100023
100338
  deps.db,
100024
100339
  { accountId: grant.accountId, workspaceId },
@@ -100055,7 +100370,7 @@ function registerSlackInteractionRoutes(app, deps) {
100055
100370
  (candidate) => candidate.connectionId === payload.connectionId
100056
100371
  );
100057
100372
  if (!binding) {
100058
- throw new HTTPException94(404, { message: "Slack installation not found" });
100373
+ throw new HTTPException96(404, { message: "Slack installation not found" });
100059
100374
  }
100060
100375
  const callerPersonalWorkspaceId = await namedSubjectPersonalWorkspaceId2(deps.db, {
100061
100376
  accountId: grant.accountId,
@@ -100068,13 +100383,13 @@ function registerSlackInteractionRoutes(app, deps) {
100068
100383
  targetAccountId: grant.accountId,
100069
100384
  targetWorkspaceId: route.targetWorkspaceId
100070
100385
  });
100071
- if (!authorized || !hasPermission23(authorized.permissions, "sessions:create")) {
100072
- throw new HTTPException94(403, {
100386
+ if (!authorized || !hasPermission24(authorized.permissions, "sessions:create")) {
100387
+ throw new HTTPException96(403, {
100073
100388
  message: `you cannot start work in the workspace chosen for ${route.slackChannelId}`
100074
100389
  });
100075
100390
  }
100076
100391
  if (callerPersonalWorkspaceId !== null && route.targetWorkspaceId === callerPersonalWorkspaceId) {
100077
- throw new HTTPException94(422, {
100392
+ throw new HTTPException96(422, {
100078
100393
  message: `a channel cannot be routed to a personal workspace: work started in ${route.slackChannelId} would be invisible to everyone else in it`
100079
100394
  });
100080
100395
  }
@@ -100104,7 +100419,7 @@ function registerSlackInteractionRoutes(app, deps) {
100104
100419
  const workspaceId = c.req.param("workspaceId");
100105
100420
  const grant = await requireAccessGrant46(c, deps, workspaceId, "workspace:admin");
100106
100421
  const connectionId = boundedString(c.req.query("connectionId"), 64);
100107
- if (!connectionId) throw new HTTPException94(400, { message: "connectionId is required" });
100422
+ if (!connectionId) throw new HTTPException96(400, { message: "connectionId is required" });
100108
100423
  const cursor = boundedString(c.req.query("cursor"), 1024);
100109
100424
  const client = await createOpenGeniSlackBotInteractionClient(deps, {
100110
100425
  accountId: grant.accountId,
@@ -100151,7 +100466,7 @@ async function publishSlackAppHome(deps, installation, refresh, renewLease) {
100151
100466
  const grant = link ? await getWorkspaceGrant4(deps.db, link.subjectId, installation.workspaceId, {
100152
100467
  principalKind: "human_session"
100153
100468
  }) : null;
100154
- if (!grant || grant.accountId !== installation.accountId || !hasPermission23(grant.permissions, "sessions:read")) {
100469
+ if (!grant || grant.accountId !== installation.accountId || !hasPermission24(grant.permissions, "sessions:read")) {
100155
100470
  const client2 = await createOpenGeniSlackBotInteractionClient(deps, {
100156
100471
  accountId: installation.accountId,
100157
100472
  workspaceId: installation.workspaceId,
@@ -100229,7 +100544,7 @@ async function publishSlackAppHome(deps, installation, refresh, renewLease) {
100229
100544
  const currentGrant = currentLink ? await getWorkspaceGrant4(deps.db, currentLink.subjectId, installation.workspaceId, {
100230
100545
  principalKind: "human_session"
100231
100546
  }) : null;
100232
- if (!currentLink || currentLink.subjectId !== grant.subjectId || !currentGrant || currentGrant.accountId !== installation.accountId || !hasPermission23(currentGrant.permissions, "sessions:read")) {
100547
+ if (!currentLink || currentLink.subjectId !== grant.subjectId || !currentGrant || currentGrant.accountId !== installation.accountId || !hasPermission24(currentGrant.permissions, "sessions:read")) {
100233
100548
  await publishSlackAppHomeAccessView(
100234
100549
  client,
100235
100550
  refresh,
@@ -100694,7 +101009,7 @@ async function handleSlackRouteChoice(deps, home, entry2, actionId, optionId) {
100694
101009
  targetAccountId: chosen.candidateAccountId,
100695
101010
  targetWorkspaceId: chosen.candidateWorkspaceId
100696
101011
  }) : null;
100697
- if (!grant || !hasPermission23(grant.permissions, "sessions:create")) {
101012
+ if (!grant || !hasPermission24(grant.permissions, "sessions:create")) {
100698
101013
  await client.postMessage({
100699
101014
  operationId: deterministicUuid2(`slack-route-denied:${prompt.id}:${chosen.id}`),
100700
101015
  userId: entry2.slackUserId,
@@ -100892,7 +101207,7 @@ async function processSlackInboxEntry(deps, entry2) {
100892
101207
  });
100893
101208
  return;
100894
101209
  }
100895
- if (!hasPermission23(grant.permissions, "sessions:create")) {
101210
+ if (!hasPermission24(grant.permissions, "sessions:create")) {
100896
101211
  throw new SlackInteractionPermanentError("sessions_create_denied");
100897
101212
  }
100898
101213
  const { interaction } = await getOrCreateSlackInteraction(deps.db, {
@@ -100955,7 +101270,7 @@ async function processSlackInboxEntry(deps, entry2) {
100955
101270
  }
100956
101271
  );
100957
101272
  } catch (error) {
100958
- if (error instanceof HTTPException94) {
101273
+ if (error instanceof HTTPException96) {
100959
101274
  await client.postMessage({
100960
101275
  operationId: deterministicUuid2(`slack-admission-failed:${interaction.id}`),
100961
101276
  ...routePolicy.directMessageShortcut ? { userId: entry2.slackUserId } : {
@@ -101222,7 +101537,7 @@ async function processSlackReactionInboxEntry(deps, entry2) {
101222
101537
  if (!resolved) {
101223
101538
  throw new SlackInteractionPermanentError("identity_access_revoked");
101224
101539
  }
101225
- if (!hasPermission23(resolved.permissions, "sessions:create") || !hasPermission23(resolved.permissions, "sessions:control")) {
101540
+ if (!hasPermission24(resolved.permissions, "sessions:create") || !hasPermission24(resolved.permissions, "sessions:control")) {
101226
101541
  throw new SlackInteractionPermanentError("reaction_session_permissions_denied");
101227
101542
  }
101228
101543
  return resolved;
@@ -101392,7 +101707,7 @@ async function processSlackReactionInboxEntry(deps, entry2) {
101392
101707
  );
101393
101708
  await acceptSlackReactionTask(deps, grant, session.id, preparedEntry, preparedTask.resources);
101394
101709
  } catch (error) {
101395
- if (error instanceof HTTPException94) {
101710
+ if (error instanceof HTTPException96) {
101396
101711
  await client.postMessage({
101397
101712
  operationId: deterministicUuid2(`slack-reaction-admission-failed:${interaction.id}`),
101398
101713
  channelId: entry2.slackChannelId,
@@ -101692,7 +102007,7 @@ async function continueSlackSession(deps, grant, interaction, entry2, resources
101692
102007
  }
101693
102008
  await reopenSlackInteractionDelivery(deps.db, interaction);
101694
102009
  if (entry2.text.trim().toLowerCase() === "stop") {
101695
- if (!hasPermission23(grant.permissions, "sessions:control")) {
102010
+ if (!hasPermission24(grant.permissions, "sessions:control")) {
101696
102011
  throw new SlackInteractionPermanentError("sessions_control_denied");
101697
102012
  }
101698
102013
  await controlHumanSessionWorkstream2(
@@ -101753,7 +102068,7 @@ async function continueSlackSession(deps, grant, interaction, entry2, resources
101753
102068
  }
101754
102069
  }
101755
102070
  }
101756
- if (!hasPermission23(grant.permissions, "sessions:control")) {
102071
+ if (!hasPermission24(grant.permissions, "sessions:control")) {
101757
102072
  throw new SlackInteractionPermanentError("sessions_control_denied");
101758
102073
  }
101759
102074
  await acceptSessionUserMessage2(
@@ -101841,7 +102156,7 @@ async function processSlackBlockAction(deps, entry2) {
101841
102156
  targetAccountId: target.accountId,
101842
102157
  targetWorkspaceId: target.workspaceId
101843
102158
  });
101844
- if (!grant || !hasPermission23(grant.permissions, "sessions:control")) {
102159
+ if (!grant || !hasPermission24(grant.permissions, "sessions:control")) {
101845
102160
  throw new SlackInteractionPermanentError("sessions_control_denied");
101846
102161
  }
101847
102162
  const client = await createOpenGeniSlackBotInteractionClient(deps, {
@@ -102032,7 +102347,7 @@ async function executeSlackAction(deps, grant, interaction, handle) {
102032
102347
  }
102033
102348
  const session = await getSession11(deps.db, grant.workspaceId, handle.sessionId);
102034
102349
  if (!session) throw new SlackInteractionPermanentError("slack_action_session_missing");
102035
- const recurring = hasPermission23(grant.permissions, "sessions:read") && hasPermission23(grant.permissions, "scheduled_tasks:manage") ? makeRecurringText(deps, grant.workspaceId, handle.sessionId) : null;
102350
+ const recurring = hasPermission24(grant.permissions, "sessions:read") && hasPermission24(grant.permissions, "scheduled_tasks:manage") ? makeRecurringText(deps, grant.workspaceId, handle.sessionId) : null;
102036
102351
  return {
102037
102352
  result: "status",
102038
102353
  text: `${mention}OpenGeni task status: *${session.status.replaceAll("_", " ")}*.${recurring ? `
@@ -102789,12 +103104,12 @@ async function enqueueNormalizedSlackInteraction(deps, route, entry2) {
102789
103104
  async function readSignedSlackRequest(c, deps) {
102790
103105
  const signingSecret = deps.settings.slackSigningSecret;
102791
103106
  if (!signingSecret)
102792
- throw new HTTPException94(503, {
103107
+ throw new HTTPException96(503, {
102793
103108
  message: "Slack interactions are disabled"
102794
103109
  });
102795
103110
  const rawBytes = new Uint8Array(await c.req.raw.arrayBuffer());
102796
103111
  if (rawBytes.byteLength === 0 || rawBytes.byteLength > SLACK_INTERACTION_MAX_BODY_BYTES) {
102797
- throw new HTTPException94(rawBytes.byteLength > SLACK_INTERACTION_MAX_BODY_BYTES ? 413 : 400, {
103112
+ throw new HTTPException96(rawBytes.byteLength > SLACK_INTERACTION_MAX_BODY_BYTES ? 413 : 400, {
102798
103113
  message: "invalid Slack request body"
102799
103114
  });
102800
103115
  }
@@ -102807,7 +103122,7 @@ async function readSignedSlackRequest(c, deps) {
102807
103122
  },
102808
103123
  signingSecret
102809
103124
  )) {
102810
- throw new HTTPException94(401, { message: "invalid Slack signature" });
103125
+ throw new HTTPException96(401, { message: "invalid Slack signature" });
102811
103126
  }
102812
103127
  return { rawBody };
102813
103128
  }
@@ -102818,7 +103133,7 @@ function normalizedFormInteraction(form, triggerKind) {
102818
103133
  const triggerId = boundedString(form.get("trigger_id"), 256);
102819
103134
  const text = boundedText(form.get("text"));
102820
103135
  if (!teamId || !userId || !channelId || !triggerId || !text) {
102821
- throw new HTTPException94(400, { message: "invalid Slack command payload" });
103136
+ throw new HTTPException96(400, { message: "invalid Slack command payload" });
102822
103137
  }
102823
103138
  return {
102824
103139
  providerEventId: `command:${triggerId}`,
@@ -102861,9 +103176,9 @@ function normalizedBlockActionInteraction(payload) {
102861
103176
  const actionId = boundedString(action?.action_id, 128);
102862
103177
  const handleId = boundedString(action?.value, 64);
102863
103178
  if (!teamId || !userId || !channelId || !messageTs || !actionTs || !actionId || !SLACK_BLOCK_ACTION_IDS.has(actionId) || !handleId || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(handleId) || !Array.isArray(payload.actions) || payload.actions.length !== 1) {
102864
- throw new HTTPException94(400, { message: "invalid Slack block action" });
103179
+ throw new HTTPException96(400, { message: "invalid Slack block action" });
102865
103180
  }
102866
- const identity = createHash29("sha256").update([teamId, userId, channelId, messageTs, actionTs, actionId, handleId].join("\n")).digest("hex");
103181
+ const identity = createHash30("sha256").update([teamId, userId, channelId, messageTs, actionTs, actionId, handleId].join("\n")).digest("hex");
102867
103182
  return {
102868
103183
  providerEventId: `block:${identity}`,
102869
103184
  providerMessageId: `block:${identity}`,
@@ -102928,7 +103243,7 @@ async function slackInfoCommandResponse(deps, installation, entry2) {
102928
103243
  const grant = link ? await getWorkspaceGrant4(deps.db, link.subjectId, installation.workspaceId, {
102929
103244
  principalKind: "human_session"
102930
103245
  }) : null;
102931
- if (!grant || grant.accountId !== installation.accountId || !hasPermission23(grant.permissions, "sessions:read")) {
103246
+ if (!grant || grant.accountId !== installation.accountId || !hasPermission24(grant.permissions, "sessions:read")) {
102932
103247
  return ephemeralSlackResponse(
102933
103248
  link ? `Your Slack identity is linked, but it does not currently have access to this OpenGeni workspace. Request access: ${linkUrl(deps, identity)}. No session was created.` : `Link your Slack identity to OpenGeni before starting work: ${linkUrl(deps, identity)}. No session was created.`
102934
103249
  );
@@ -102936,9 +103251,9 @@ async function slackInfoCommandResponse(deps, installation, entry2) {
102936
103251
  const workspace = await getWorkspace6(deps.db, installation.workspaceId);
102937
103252
  const command = deps.settings.slackCommand;
102938
103253
  const botMention = slackBotMention(installation.botUserId);
102939
- const canControl = hasPermission23(grant.permissions, "sessions:control");
102940
- const canCreate = hasPermission23(grant.permissions, "sessions:create");
102941
- const schedules = hasPermission23(grant.permissions, "scheduled_tasks:manage") ? slackSchedulesUrl(deps, installation.workspaceId) : null;
103254
+ const canControl = hasPermission24(grant.permissions, "sessions:control");
103255
+ const canCreate = hasPermission24(grant.permissions, "sessions:create");
103256
+ const schedules = hasPermission24(grant.permissions, "scheduled_tasks:manage") ? slackSchedulesUrl(deps, installation.workspaceId) : null;
102942
103257
  const workspaceUrl = slackWorkspaceUrl(deps, installation.workspaceId);
102943
103258
  const workspaceName = (workspace?.name ?? "").trim().slice(0, 120);
102944
103259
  const destination = workspaceName ? `the *${escapeSlackMrkdwn(workspaceName)}* workspace` : "your OpenGeni workspace";
@@ -103051,29 +103366,29 @@ function linkUrl(deps, entry2, mintedAtMs) {
103051
103366
  }
103052
103367
  async function requireManagedSlackLinkHuman(c, deps) {
103053
103368
  if (c.req.header("authorization")) {
103054
- throw new HTTPException94(401, { message: "managed browser sign-in required" });
103369
+ throw new HTTPException96(401, { message: "managed browser sign-in required" });
103055
103370
  }
103056
103371
  const context = await requireAccessContext5(c, deps);
103057
103372
  if (context.mode !== "managed" || !context.subjectId.startsWith("user:")) {
103058
- throw new HTTPException94(403, { message: "managed browser sign-in required" });
103373
+ throw new HTTPException96(403, { message: "managed browser sign-in required" });
103059
103374
  }
103060
103375
  return context;
103061
103376
  }
103062
103377
  function freshSlackLinkRequired() {
103063
- return new HTTPException94(400, {
103378
+ return new HTTPException96(400, {
103064
103379
  message: "This Slack link is invalid or expired. Request a fresh link from Slack."
103065
103380
  });
103066
103381
  }
103067
103382
  function slackLinkAccessHttpError(error) {
103068
- if (error instanceof HTTPException94) return error;
103383
+ if (error instanceof HTTPException96) return error;
103069
103384
  if (!(error instanceof SlackUserLinkAccessPersistenceError)) throw error;
103070
103385
  if (error.code === "version_conflict" || error.code === "idempotency_conflict") {
103071
- return new HTTPException94(409, {
103386
+ return new HTTPException96(409, {
103072
103387
  message: "The Slack access request changed. Refresh and try again."
103073
103388
  });
103074
103389
  }
103075
103390
  if (error.code === "state_conflict") {
103076
- return new HTTPException94(409, {
103391
+ return new HTTPException96(409, {
103077
103392
  message: "This Slack link is no longer pending. Request a fresh link from Slack."
103078
103393
  });
103079
103394
  }
@@ -103128,7 +103443,7 @@ function usesPrivateBotDm(interaction, entry2) {
103128
103443
  return isDirectMessageShortcut(entry2) || interaction.visibility === "private" && entry2.triggerKind !== "dm";
103129
103444
  }
103130
103445
  function deterministicUuid2(value) {
103131
- const bytes = createHash29("sha256").update(value).digest().subarray(0, 16);
103446
+ const bytes = createHash30("sha256").update(value).digest().subarray(0, 16);
103132
103447
  bytes[6] = bytes[6] & 15 | 80;
103133
103448
  bytes[8] = bytes[8] & 63 | 128;
103134
103449
  const hex2 = bytes.toString("hex");
@@ -103141,7 +103456,7 @@ function parseJsonObject(value) {
103141
103456
  if (result) return result;
103142
103457
  } catch {
103143
103458
  }
103144
- throw new HTTPException94(400, { message: "invalid Slack JSON payload" });
103459
+ throw new HTTPException96(400, { message: "invalid Slack JSON payload" });
103145
103460
  }
103146
103461
  function record5(value) {
103147
103462
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -103171,7 +103486,7 @@ function safeErrorCode(error) {
103171
103486
  if (error instanceof SlackBotProviderError) return error.code.slice(0, 128);
103172
103487
  if (error instanceof SlackInteractionPermanentError) return error.code.slice(0, 128);
103173
103488
  if (error instanceof SlackInteractionRetryableError) return error.code.slice(0, 128);
103174
- if (error instanceof HTTPException94) return `http_${error.status}`;
103489
+ if (error instanceof HTTPException96) return `http_${error.status}`;
103175
103490
  const raw = error instanceof Error ? error.name : "slack_interaction_error";
103176
103491
  return raw.toLowerCase().replace(/[^a-z0-9_-]/g, "_").slice(0, 128) || "error";
103177
103492
  }
@@ -103199,7 +103514,7 @@ var SlackInteractionRetryableError = class extends Error {
103199
103514
  }
103200
103515
  };
103201
103516
  function permanentSlackInteractionError(error) {
103202
- return error instanceof SlackInteractionPermanentError || error instanceof HTTPException94;
103517
+ return error instanceof SlackInteractionPermanentError || error instanceof HTTPException96;
103203
103518
  }
103204
103519
  var PERMANENT_SLACK_DELIVERY_CODES = /* @__PURE__ */ new Set([
103205
103520
  "account_inactive",
@@ -103299,7 +103614,7 @@ function createAppComposition(deps) {
103299
103614
  authoritySubjectId
103300
103615
  }) => {
103301
103616
  if (!objectStorage) {
103302
- throw new HTTPException95(503, {
103617
+ throw new HTTPException97(503, {
103303
103618
  message: "object storage is not configured"
103304
103619
  });
103305
103620
  }
@@ -103557,7 +103872,7 @@ function createAppComposition(deps) {
103557
103872
  } catch (error) {
103558
103873
  if (error instanceof ManagedAuthActorChangeError2) {
103559
103874
  c.header("x-opengeni-actor-state", "changed");
103560
- throw new HTTPException95(409, { message: error.code, cause: error });
103875
+ throw new HTTPException97(409, { message: error.code, cause: error });
103561
103876
  }
103562
103877
  if (error instanceof ManagedAuthActorLeaseOutcomeUnknownError) {
103563
103878
  throw new ApiHttpError(503, {
@@ -103602,7 +103917,7 @@ function createAppComposition(deps) {
103602
103917
  deps.settings.publicBaseUrl
103603
103918
  );
103604
103919
  if (!attempt || !authority || attempt.authorityHash !== managedAuthSha2562(authority)) {
103605
- throw new HTTPException95(409, { message: "provider_route_blocked" });
103920
+ throw new HTTPException97(409, { message: "provider_route_blocked" });
103606
103921
  }
103607
103922
  const isolated = await isolatedManagedAuthOAuthCallbackRequest(managedAuth, c.req.raw);
103608
103923
  preserveCookieNames = [isolated.stateCookieName];
@@ -103816,7 +104131,7 @@ function createAppComposition(deps) {
103816
104131
  boundedRequest = await boundedMcpRequest(c.req.raw);
103817
104132
  } catch (error) {
103818
104133
  if (error instanceof McpPayloadTooLargeError) {
103819
- throw new HTTPException95(413, {
104134
+ throw new HTTPException97(413, {
103820
104135
  message: "MCP request body exceeds the safety limit"
103821
104136
  });
103822
104137
  }
@@ -103826,7 +104141,7 @@ function createAppComposition(deps) {
103826
104141
  try {
103827
104142
  oauthAccess = await resolveMcpOAuthRouteAccess(routeDeps, c.req.raw, workspaceId);
103828
104143
  } catch (error) {
103829
- if (error instanceof HTTPException95 && error.status === 401) {
104144
+ if (error instanceof HTTPException97 && error.status === 401) {
103830
104145
  c.header(
103831
104146
  "www-authenticate",
103832
104147
  mcpOAuthAuthenticateHeader(routeDeps, new URL(c.req.url).pathname)
@@ -103861,7 +104176,7 @@ function createAppComposition(deps) {
103861
104176
  try {
103862
104177
  authorization = await requireMcpAccessGrantAuthorization(c, routeDeps, workspaceId);
103863
104178
  } catch (error) {
103864
- if (deps.settings.mcpOauthEnabled && error instanceof HTTPException95 && error.status === 401) {
104179
+ if (deps.settings.mcpOauthEnabled && error instanceof HTTPException97 && error.status === 401) {
103865
104180
  c.header(
103866
104181
  "www-authenticate",
103867
104182
  mcpOAuthAuthenticateHeader(routeDeps, new URL(c.req.url).pathname)
@@ -103874,17 +104189,17 @@ function createAppComposition(deps) {
103874
104189
  const boundSessionId = grant.metadata?.sessionId;
103875
104190
  if (typeof boundSessionId === "string") {
103876
104191
  try {
103877
- await requireSessionAuthorization15(routeDeps, grant, {
104192
+ await requireSessionAuthorization16(routeDeps, grant, {
103878
104193
  sessionId: boundSessionId,
103879
104194
  operation: "session.first_party_mcp.call",
103880
104195
  surface: "first_party_mcp"
103881
104196
  });
103882
104197
  } catch (error) {
103883
- if (error instanceof SessionAuthorizationDeniedError16) {
103884
- throw new HTTPException95(404, { message: "session not found" });
104198
+ if (error instanceof SessionAuthorizationDeniedError17) {
104199
+ throw new HTTPException97(404, { message: "session not found" });
103885
104200
  }
103886
- if (error instanceof SessionAuthorizationUnavailableError14) {
103887
- throw new HTTPException95(503, {
104201
+ if (error instanceof SessionAuthorizationUnavailableError15) {
104202
+ throw new HTTPException97(503, {
103888
104203
  message: "session authorization is unavailable"
103889
104204
  });
103890
104205
  }
@@ -103930,7 +104245,7 @@ function createAppComposition(deps) {
103930
104245
  });
103931
104246
  app.get("/v1/workspaces/:workspaceId/tools/catalog", async (c) => {
103932
104247
  const workspaceId = c.req.param("workspaceId");
103933
- const authorization = await requireAccessGrantAuthorization36(
104248
+ const authorization = await requireAccessGrantAuthorization37(
103934
104249
  c,
103935
104250
  routeDeps,
103936
104251
  workspaceId,
@@ -103946,7 +104261,7 @@ function createAppComposition(deps) {
103946
104261
  });
103947
104262
  app.post("/v1/workspaces/:workspaceId/tools/calls", async (c) => {
103948
104263
  const workspaceId = c.req.param("workspaceId");
103949
- const authorization = await requireAccessGrantAuthorization36(
104264
+ const authorization = await requireAccessGrantAuthorization37(
103950
104265
  c,
103951
104266
  routeDeps,
103952
104267
  workspaceId,
@@ -103955,7 +104270,7 @@ function createAppComposition(deps) {
103955
104270
  const grant = authorization.grant;
103956
104271
  const parsed = ToolGatewayCallRequest2.safeParse(await c.req.json().catch(() => null));
103957
104272
  if (!parsed.success) {
103958
- throw new HTTPException95(400, { message: "Invalid tool gateway call" });
104273
+ throw new HTTPException97(400, { message: "Invalid tool gateway call" });
103959
104274
  }
103960
104275
  const prepared = await prepareWorkspaceToolGateway(routeDeps, authorization);
103961
104276
  try {
@@ -103975,7 +104290,7 @@ function createAppComposition(deps) {
103975
104290
  });
103976
104291
  app.post("/v1/workspaces/:workspaceId/tools/approvals", async (c) => {
103977
104292
  const workspaceId = c.req.param("workspaceId");
103978
- const authorization = await requireAccessGrantAuthorization36(
104293
+ const authorization = await requireAccessGrantAuthorization37(
103979
104294
  c,
103980
104295
  routeDeps,
103981
104296
  workspaceId,
@@ -103983,7 +104298,7 @@ function createAppComposition(deps) {
103983
104298
  );
103984
104299
  const parsed = ToolGatewayApprovalRequest2.safeParse(await c.req.json().catch(() => null));
103985
104300
  if (!parsed.success) {
103986
- throw new HTTPException95(400, { message: "Invalid tool gateway approval" });
104301
+ throw new HTTPException97(400, { message: "Invalid tool gateway approval" });
103987
104302
  }
103988
104303
  const prepared = await prepareWorkspaceToolGateway(routeDeps, authorization);
103989
104304
  try {
@@ -104004,7 +104319,7 @@ function createAppComposition(deps) {
104004
104319
  });
104005
104320
  app.get("/v1/workspaces/:workspaceId/tools/declarations", async (c) => {
104006
104321
  const workspaceId = c.req.param("workspaceId");
104007
- const authorization = await requireAccessGrantAuthorization36(
104322
+ const authorization = await requireAccessGrantAuthorization37(
104008
104323
  c,
104009
104324
  routeDeps,
104010
104325
  workspaceId,
@@ -104040,7 +104355,7 @@ function createAppComposition(deps) {
104040
104355
  const workspaceId = c.req.param("workspaceId");
104041
104356
  const grant = await requireAccessGrant47(c, routeDeps, workspaceId);
104042
104357
  if (!isCodemodeGrant(grant)) {
104043
- throw new HTTPException95(403, { message: "Codemode access denied" });
104358
+ throw new HTTPException97(403, { message: "Codemode access denied" });
104044
104359
  }
104045
104360
  try {
104046
104361
  return c.json((await requireActiveCodemodeCatalog(routeDeps, grant)).catalog);
@@ -104052,11 +104367,11 @@ function createAppComposition(deps) {
104052
104367
  const workspaceId = c.req.param("workspaceId");
104053
104368
  const grant = await requireAccessGrant47(c, routeDeps, workspaceId);
104054
104369
  if (!isCodemodeGrant(grant)) {
104055
- throw new HTTPException95(403, { message: "Codemode access denied" });
104370
+ throw new HTTPException97(403, { message: "Codemode access denied" });
104056
104371
  }
104057
104372
  const parsed = CodemodeCallRequest2.safeParse(await c.req.json().catch(() => null));
104058
104373
  if (!parsed.success) {
104059
- throw new HTTPException95(400, { message: "Invalid Codemode call" });
104374
+ throw new HTTPException97(400, { message: "Invalid Codemode call" });
104060
104375
  }
104061
104376
  try {
104062
104377
  const submission = await submitAndDispatchCodemodeCall(routeDeps, grant, parsed.data);
@@ -104072,17 +104387,17 @@ function createAppComposition(deps) {
104072
104387
  const workspaceId = c.req.param("workspaceId");
104073
104388
  const grant = await requireAccessGrant47(c, routeDeps, workspaceId);
104074
104389
  if (!isCodemodeGrant(grant)) {
104075
- throw new HTTPException95(403, { message: "Codemode access denied" });
104390
+ throw new HTTPException97(403, { message: "Codemode access denied" });
104076
104391
  }
104077
104392
  try {
104078
104393
  const operation = await readCodemodeOperation(routeDeps, grant, c.req.param("operationId"));
104079
104394
  if (!operation)
104080
- throw new HTTPException95(404, {
104395
+ throw new HTTPException97(404, {
104081
104396
  message: "Codemode operation not found"
104082
104397
  });
104083
104398
  return c.json(operation);
104084
104399
  } catch (error) {
104085
- if (error instanceof HTTPException95) throw error;
104400
+ if (error instanceof HTTPException97) throw error;
104086
104401
  throw codemodeHttpError(error);
104087
104402
  }
104088
104403
  });
@@ -104108,6 +104423,7 @@ function createAppComposition(deps) {
104108
104423
  registerWorkspaceStateRoutes(app, routeDeps);
104109
104424
  registerMemorySlackPublicationRoutes(app, routeDeps);
104110
104425
  registerWorkspaceArtifactRoutes(app, routeDeps);
104426
+ registerArtifactCatalogRoutes(app, routeDeps);
104111
104427
  registerPreferenceRegistryRoutes(app, routeDeps);
104112
104428
  registerSocialRoutes(app, routeDeps);
104113
104429
  registerPersonalGitHubRoutes(app, routeDeps);
@@ -104196,7 +104512,7 @@ function managedAuthOAuthCallbackProvider(pathname) {
104196
104512
  }
104197
104513
  function mutationOutcomeUnknown(error, method) {
104198
104514
  if (method === "GET" || method === "HEAD" || method === "OPTIONS") return false;
104199
- const cause = error instanceof HTTPException95 ? error.cause : error;
104515
+ const cause = error instanceof HTTPException97 ? error.cause : error;
104200
104516
  return cause instanceof BrowserControlTransportError5 || cause instanceof BrowserControlProtocolError3;
104201
104517
  }
104202
104518
  function appendVary(current, value) {
@@ -104225,15 +104541,15 @@ function workspaceRequestRequiresCodexAccountPrevalidation(request) {
104225
104541
  async function validateCodexAccountTarget(request) {
104226
104542
  const body4 = await request.clone().json().catch(() => null);
104227
104543
  if (typeof body4?.target !== "string" || body4.target.length === 0) {
104228
- throw new HTTPException95(400, {
104544
+ throw new HTTPException97(400, {
104229
104545
  message: 'target is required ("auto" or an account id)'
104230
104546
  });
104231
104547
  }
104232
104548
  }
104233
104549
  async function requireMcpAccessGrantAuthorization(c, deps, workspaceId) {
104234
- const authorization = await requireAccessGrantAuthorization36(c, deps, workspaceId);
104550
+ const authorization = await requireAccessGrantAuthorization37(c, deps, workspaceId);
104235
104551
  const grant = authorization.grant;
104236
- if (hasPermission24(grant.permissions, "workspace:read")) {
104552
+ if (hasPermission25(grant.permissions, "workspace:read")) {
104237
104553
  return authorization;
104238
104554
  }
104239
104555
  if (isCodemodeGrant(grant)) {
@@ -104274,16 +104590,16 @@ function clientAuthConfig(settings) {
104274
104590
  }
104275
104591
  function codemodeHttpError(error) {
104276
104592
  if (error instanceof SiteSessionPathError) {
104277
- return new HTTPException95(404, { message: error.message, cause: error });
104593
+ return new HTTPException97(404, { message: error.message, cause: error });
104278
104594
  }
104279
- if (error instanceof SessionAuthorizationDeniedError16) {
104280
- return new HTTPException95(404, {
104595
+ if (error instanceof SessionAuthorizationDeniedError17) {
104596
+ return new HTTPException97(404, {
104281
104597
  message: "session not found",
104282
104598
  cause: error
104283
104599
  });
104284
104600
  }
104285
- if (error instanceof SessionAuthorizationUnavailableError14) {
104286
- return new HTTPException95(503, {
104601
+ if (error instanceof SessionAuthorizationUnavailableError15) {
104602
+ return new HTTPException97(503, {
104287
104603
  message: "session authorization is unavailable",
104288
104604
  cause: error
104289
104605
  });
@@ -104316,21 +104632,21 @@ function codemodeHttpError(error) {
104316
104632
  });
104317
104633
  }
104318
104634
  if (error instanceof CodemodeOperationNotExecutableError) {
104319
- return new HTTPException95(409, { message: error.message, cause: error });
104635
+ return new HTTPException97(409, { message: error.message, cause: error });
104320
104636
  }
104321
104637
  if (error instanceof CodemodeOperationConflictError) {
104322
- return new HTTPException95(409, { message: error.message, cause: error });
104638
+ return new HTTPException97(409, { message: error.message, cause: error });
104323
104639
  }
104324
104640
  if (error instanceof CodemodeToolNotInCatalogError) {
104325
- return new HTTPException95(404, { message: error.message, cause: error });
104641
+ return new HTTPException97(404, { message: error.message, cause: error });
104326
104642
  }
104327
104643
  if (error instanceof CodemodeToolApprovalRequiredError) {
104328
- return new HTTPException95(409, { message: error.message, cause: error });
104644
+ return new HTTPException97(409, { message: error.message, cause: error });
104329
104645
  }
104330
104646
  if (error instanceof CodemodePayloadTooLargeError) {
104331
- return new HTTPException95(413, { message: error.message, cause: error });
104647
+ return new HTTPException97(413, { message: error.message, cause: error });
104332
104648
  }
104333
- return error instanceof HTTPException95 ? error : new HTTPException95(500, {
104649
+ return error instanceof HTTPException97 ? error : new HTTPException97(500, {
104334
104650
  message: "Codemode request failed",
104335
104651
  cause: error
104336
104652
  });
@@ -104359,7 +104675,7 @@ function structuredServicesHint(backend) {
104359
104675
  }
104360
104676
  function codexCompactionV2ProviderLockedError(error) {
104361
104677
  if (error instanceof CodexCompactionV2ProviderLockedError) return error;
104362
- if (error instanceof HTTPException95 && error.cause instanceof CodexCompactionV2ProviderLockedError) {
104678
+ if (error instanceof HTTPException97 && error.cause instanceof CodexCompactionV2ProviderLockedError) {
104363
104679
  return error.cause;
104364
104680
  }
104365
104681
  return null;
@@ -104373,7 +104689,7 @@ function httpStatusForError(error) {
104373
104689
  if (workspaceControlBusyHttpError(error)) {
104374
104690
  return 503;
104375
104691
  }
104376
- if (error instanceof HTTPException95) {
104692
+ if (error instanceof HTTPException97) {
104377
104693
  return error.status;
104378
104694
  }
104379
104695
  if (error instanceof McpPayloadTooLargeError) {
@@ -104405,7 +104721,7 @@ function publicErrorMessage(error, status) {
104405
104721
  if (status >= 500) {
104406
104722
  return "OpenGeni could not complete the request.";
104407
104723
  }
104408
- if (error instanceof HTTPException95) {
104724
+ if (error instanceof HTTPException97) {
104409
104725
  return boundedPublicMessage(error.message) ?? "Request failed.";
104410
104726
  }
104411
104727
  if (error instanceof McpPayloadTooLargeError) {
@@ -105379,4 +105695,4 @@ export {
105379
105695
  withDefaultEnabledCapabilityMcpTools,
105380
105696
  workflowIdForSession4 as workflowIdForSession
105381
105697
  };
105382
- //# sourceMappingURL=chunk-K2NU4KRK.js.map
105698
+ //# sourceMappingURL=chunk-AJ62T5QN.js.map