@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.
- package/dist/app.js +1 -1
- package/dist/artifact-catalog-cursor.d.ts +27 -0
- package/dist/{chunk-K2NU4KRK.js → chunk-AJ62T5QN.js} +594 -278
- package/dist/{chunk-K2NU4KRK.js.map → chunk-AJ62T5QN.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/routes/artifact-catalog.d.ts +6 -0
- package/dist/routes/editable-artifacts.d.ts +2 -0
- package/dist/sandbox-file-artifacts.d.ts +19 -0
- package/package.json +19 -19
- package/src/app.ts +2 -0
- package/src/artifact-catalog-cursor.ts +60 -0
- package/src/integrations/api-integrations.ts +17 -4
- package/src/mcp/knowledge-entries.ts +2 -2
- package/src/routes/artifact-catalog.ts +279 -0
- package/src/routes/connect.ts +80 -51
- package/src/routes/editable-artifacts.ts +2 -2
- package/src/sandbox-file-artifacts.ts +9 -2
|
@@ -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
|
|
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
|
|
3595
|
+
hasPermission as hasPermission25,
|
|
3596
3596
|
requireAccessGrant as requireAccessGrant47,
|
|
3597
|
-
requireAccessGrantAuthorization as
|
|
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
|
|
3604
|
-
SessionAuthorizationDeniedError as
|
|
3605
|
-
SessionAuthorizationUnavailableError as
|
|
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
|
|
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
|
|
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,
|
|
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
|
-
|
|
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(
|
|
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 ([
|
|
64502
|
-
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
95129
|
-
fileOwnerContextForAccess as
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
95214
|
-
const actor = await
|
|
95215
|
-
const summary = await
|
|
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
|
|
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
|
|
95278
|
-
import { z as
|
|
95279
|
-
var BindingId =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
95478
|
-
import { z as
|
|
95479
|
-
var OrganizationId2 =
|
|
95480
|
-
var WorkspaceId =
|
|
95481
|
-
var MembershipId =
|
|
95482
|
-
var InvitationId =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
96570
|
+
hasPermission as hasPermission22,
|
|
96256
96571
|
requireAccessContext as requireAccessContext4,
|
|
96257
|
-
requireAccessGrantAuthorization as
|
|
96572
|
+
requireAccessGrantAuthorization as requireAccessGrantAuthorization34,
|
|
96258
96573
|
requireSessionAuthorizationListScope as requireSessionAuthorizationListScope3,
|
|
96259
|
-
SessionAuthorizationDeniedError as
|
|
96260
|
-
SessionAuthorizationUnavailableError as
|
|
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
|
|
96271
|
-
import { z as
|
|
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 =
|
|
96274
|
-
var OrganizationSessionListCursorEnvelope =
|
|
96275
|
-
workspaceId:
|
|
96276
|
-
cursor:
|
|
96277
|
-
pinnedOffset:
|
|
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 &&
|
|
96614
|
+
if (authority.accountId === organizationId2 && hasPermission22(authority.permissions, "sessions:read")) {
|
|
96300
96615
|
return "organization_api_key";
|
|
96301
96616
|
}
|
|
96302
|
-
throw new
|
|
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
|
|
96625
|
+
throw new HTTPException89(403, { message: "organization session read authority required" });
|
|
96311
96626
|
}
|
|
96312
96627
|
function sessionAuthorizationHttpError2(error) {
|
|
96313
|
-
if (error instanceof
|
|
96314
|
-
return new
|
|
96628
|
+
if (error instanceof SessionAuthorizationDeniedError14) {
|
|
96629
|
+
return new HTTPException89(404, { message: "session not found" });
|
|
96315
96630
|
}
|
|
96316
|
-
if (error instanceof
|
|
96317
|
-
return new
|
|
96631
|
+
if (error instanceof SessionAuthorizationUnavailableError12) {
|
|
96632
|
+
return new HTTPException89(503, { message: "session authorization is unavailable" });
|
|
96318
96633
|
}
|
|
96319
|
-
if (error instanceof
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
96777
|
+
throw new HTTPException89(403, { message: error.message });
|
|
96463
96778
|
}
|
|
96464
96779
|
if (error instanceof SessionListCursorExpiredError2) {
|
|
96465
|
-
throw new
|
|
96780
|
+
throw new HTTPException89(410, { message: error.message });
|
|
96466
96781
|
}
|
|
96467
96782
|
if (error instanceof SessionListCursorError2) {
|
|
96468
|
-
throw new
|
|
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
|
|
96504
|
-
import { z as
|
|
96505
|
-
var OrganizationId4 =
|
|
96506
|
-
var RecoveryOperationId =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
97123
|
+
throw new HTTPException91(422, {
|
|
96809
97124
|
message: "invalid organization setup request"
|
|
96810
97125
|
});
|
|
96811
97126
|
}
|
|
96812
97127
|
if (sqlState === "42501") {
|
|
96813
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
97203
|
+
throw new HTTPException91(422, {
|
|
96889
97204
|
message: "invalid account setup request"
|
|
96890
97205
|
});
|
|
96891
97206
|
}
|
|
96892
97207
|
if (sqlState === "23505") {
|
|
96893
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
97057
|
-
import { z as
|
|
97058
|
-
var ManagedAuthSocialStartReceipt =
|
|
97059
|
-
version:
|
|
97060
|
-
requestDigest:
|
|
97061
|
-
url:
|
|
97062
|
-
stateCookie:
|
|
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
|
|
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 (!
|
|
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
|
|
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
|
|
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
|
|
98306
|
+
requireAccessGrantAuthorization as requireAccessGrantAuthorization35,
|
|
97992
98307
|
revokeManagedHumanUserResourceGrant,
|
|
97993
|
-
SessionAuthorizationDeniedError as
|
|
97994
|
-
SessionAuthorizationUnavailableError as
|
|
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
|
|
97999
|
-
import { z as
|
|
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
|
|
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
|
|
98007
|
-
throw new
|
|
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
|
|
98010
|
-
throw new
|
|
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
|
|
98328
|
+
throw new HTTPException93(403, { message: "user-resource authority denied" });
|
|
98014
98329
|
}
|
|
98015
98330
|
if (nestedPostgresSqlState11(error) === "22023") {
|
|
98016
|
-
throw new
|
|
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
|
|
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
|
|
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 =
|
|
98057
|
-
if (!authorityId.success) throw new
|
|
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
|
|
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
|
|
98086
|
-
const grantId =
|
|
98087
|
-
if (!grantId.success) throw new
|
|
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
|
|
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
|
|
98434
|
+
requireAccessGrantAuthorization as requireAccessGrantAuthorization36,
|
|
98120
98435
|
revokeManagedHumanUserResourceGrant as revokeManagedHumanUserResourceGrant2,
|
|
98121
|
-
SessionAuthorizationDeniedError as
|
|
98122
|
-
SessionAuthorizationUnavailableError as
|
|
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
|
|
98127
|
-
import { z as
|
|
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
|
|
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
|
|
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
|
|
98162
|
-
throw new
|
|
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
|
|
98165
|
-
throw new
|
|
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
|
|
98483
|
+
throw new HTTPException95(403, { message: "connection authority denied" });
|
|
98169
98484
|
}
|
|
98170
98485
|
if (nestedPostgresSqlState12(error) === "22023") {
|
|
98171
|
-
throw new
|
|
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
|
|
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
|
|
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 =
|
|
98208
|
-
if (!authorityId.success) throw new
|
|
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
|
|
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
|
|
98238
|
-
const grantId =
|
|
98239
|
-
if (!grantId.success) throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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 || !
|
|
100072
|
-
throw new
|
|
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
|
|
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
|
|
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 || !
|
|
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 || !
|
|
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 || !
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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 || !
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
103179
|
+
throw new HTTPException96(400, { message: "invalid Slack block action" });
|
|
102865
103180
|
}
|
|
102866
|
-
const identity =
|
|
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 || !
|
|
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 =
|
|
102940
|
-
const canCreate =
|
|
102941
|
-
const schedules =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
103884
|
-
throw new
|
|
104198
|
+
if (error instanceof SessionAuthorizationDeniedError17) {
|
|
104199
|
+
throw new HTTPException97(404, { message: "session not found" });
|
|
103885
104200
|
}
|
|
103886
|
-
if (error instanceof
|
|
103887
|
-
throw new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
104550
|
+
const authorization = await requireAccessGrantAuthorization37(c, deps, workspaceId);
|
|
104235
104551
|
const grant = authorization.grant;
|
|
104236
|
-
if (
|
|
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
|
|
104593
|
+
return new HTTPException97(404, { message: error.message, cause: error });
|
|
104278
104594
|
}
|
|
104279
|
-
if (error instanceof
|
|
104280
|
-
return new
|
|
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
|
|
104286
|
-
return new
|
|
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
|
|
104635
|
+
return new HTTPException97(409, { message: error.message, cause: error });
|
|
104320
104636
|
}
|
|
104321
104637
|
if (error instanceof CodemodeOperationConflictError) {
|
|
104322
|
-
return new
|
|
104638
|
+
return new HTTPException97(409, { message: error.message, cause: error });
|
|
104323
104639
|
}
|
|
104324
104640
|
if (error instanceof CodemodeToolNotInCatalogError) {
|
|
104325
|
-
return new
|
|
104641
|
+
return new HTTPException97(404, { message: error.message, cause: error });
|
|
104326
104642
|
}
|
|
104327
104643
|
if (error instanceof CodemodeToolApprovalRequiredError) {
|
|
104328
|
-
return new
|
|
104644
|
+
return new HTTPException97(409, { message: error.message, cause: error });
|
|
104329
104645
|
}
|
|
104330
104646
|
if (error instanceof CodemodePayloadTooLargeError) {
|
|
104331
|
-
return new
|
|
104647
|
+
return new HTTPException97(413, { message: error.message, cause: error });
|
|
104332
104648
|
}
|
|
104333
|
-
return error instanceof
|
|
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
|
|
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
|
|
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
|
|
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-
|
|
105698
|
+
//# sourceMappingURL=chunk-AJ62T5QN.js.map
|