@opengeni/api-router 0.20.0 → 0.21.3

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 CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  validateToolRefs,
23
23
  withDefaultEnabledCapabilityMcpTools,
24
24
  workflowIdForSession
25
- } from "./chunk-AEVD7E2F.js";
25
+ } from "./chunk-AMMQI2D3.js";
26
26
  export {
27
27
  API_MAX_REQUEST_BODY_BYTES,
28
28
  allowedCorsOrigin,
@@ -10960,6 +10960,7 @@ import {
10960
10960
  isOpenGeniSlackBotConnection as isOpenGeniSlackBotConnection2,
10961
10961
  openGeniSlackBotMetadata as openGeniSlackBotMetadata2,
10962
10962
  requireAccessGrant as requireAccessGrant3,
10963
+ requireAccessGrantAuthorization,
10963
10964
  requireEnvironmentEncryption as requireEnvironmentEncryption4
10964
10965
  } from "@opengeni/core";
10965
10966
  import {
@@ -10981,6 +10982,9 @@ import { HTTPException as HTTPException11 } from "hono/http-exception";
10981
10982
 
10982
10983
  // src/integrations/google-drive.ts
10983
10984
  import { createHash as createHash6, randomBytes as randomBytes3 } from "crypto";
10985
+ import {
10986
+ bindConnectorDocumentDestination
10987
+ } from "@opengeni/contracts/connector-destinations";
10984
10988
  import {
10985
10989
  GOOGLE_DRIVE_CREDENTIAL_LABEL,
10986
10990
  GOOGLE_DRIVE_CREDENTIAL_ROLE,
@@ -11171,6 +11175,7 @@ async function completeGoogleDriveOAuthCallback(deps, input) {
11171
11175
  verifiedAt: (/* @__PURE__ */ new Date()).toISOString(),
11172
11176
  accessMode: scopeDecision.accessMode,
11173
11177
  lifecycle: googleDriveLifecycle("active"),
11178
+ ...previousMetadata?.documentDestination ? { documentDestination: previousMetadata.documentDestination } : {},
11174
11179
  ...previousMetadata?.selectedSources ? { selectedSources: previousMetadata.selectedSources } : previousMetadata?.selectedSource ? { selectedSources: [previousMetadata.selectedSource] } : {}
11175
11180
  });
11176
11181
  const connection = existing ? await updateConnection2(deps.db, {
@@ -11382,7 +11387,28 @@ async function saveGoogleDriveSource(deps, input) {
11382
11387
  if (!existing) {
11383
11388
  throw new HTTPException10(404, { message: "Google Drive connection not found" });
11384
11389
  }
11390
+ if (existing.accountId !== input.accountId || existing.workspaceId !== input.workspaceId) {
11391
+ throw new HTTPException10(403, { message: "Google Drive connection authority mismatch" });
11392
+ }
11385
11393
  await requireGoogleDriveSourceConnection(deps, existing, input.subjectId);
11394
+ const destinationSelection = payload.destination ?? {
11395
+ authorityKind: "workspace",
11396
+ collectionId: null
11397
+ };
11398
+ if (destinationSelection.authorityKind === "organization" && !input.canManageOrganizationDestination) {
11399
+ throw new HTTPException10(403, { message: "missing permission: account:admin" });
11400
+ }
11401
+ if (destinationSelection.authorityKind === "workspace" && !input.canManageWorkspaceDestination) {
11402
+ throw new HTTPException10(403, { message: "missing permission: workspace:admin" });
11403
+ }
11404
+ if (destinationSelection.authorityKind === "personal" && !input.canManagePersonalDestination) {
11405
+ throw new HTTPException10(403, { message: "personal destination requires the exact actor" });
11406
+ }
11407
+ const documentDestination = bindConnectorDocumentDestination(destinationSelection, {
11408
+ accountId: input.accountId,
11409
+ workspaceId: input.workspaceId,
11410
+ initiatingSubjectId: input.subjectId
11411
+ });
11386
11412
  const verifiedSources = [];
11387
11413
  for (const source of payload.sources) {
11388
11414
  const sourceId = validDriveId(source.id, "source.id");
@@ -11413,13 +11439,14 @@ async function saveGoogleDriveSource(deps, input) {
11413
11439
  expectedVersion: latest.version,
11414
11440
  metadata: GoogleDriveConnectionMetadata.parse({
11415
11441
  ...latestMetadata,
11442
+ documentDestination,
11416
11443
  selectedSource: null,
11417
11444
  selectedSources: verifiedSources.map((verified) => ({
11418
11445
  id: verified.id,
11419
11446
  name: verified.name,
11420
11447
  mimeType: verified.mimeType,
11421
11448
  driveId: verified.driveId,
11422
- targetScope: payload.targetScope,
11449
+ destination: documentDestination,
11423
11450
  syncCadence: payload.syncCadence,
11424
11451
  readPolicy: payload.readPolicy,
11425
11452
  selectedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -12205,12 +12232,22 @@ function registerConnectionRoutes(app, deps) {
12205
12232
  async (c) => {
12206
12233
  assertIntegrationsEnabled();
12207
12234
  const workspaceId = c.req.param("workspaceId");
12208
- const grant = await requireAccessGrant3(c, deps, workspaceId, "connections:write");
12235
+ const authorization = await requireAccessGrantAuthorization(
12236
+ c,
12237
+ deps,
12238
+ workspaceId,
12239
+ "connections:write"
12240
+ );
12241
+ const { grant } = authorization;
12209
12242
  const connection = await saveGoogleDriveSource(deps, {
12243
+ accountId: grant.accountId,
12210
12244
  workspaceId,
12211
12245
  subjectId: grant.subjectId,
12212
12246
  connectionId: c.req.param("connectionId"),
12213
- payload: await c.req.json()
12247
+ payload: await c.req.json(),
12248
+ canManageOrganizationDestination: authorization.accountGrant?.permissions.includes("account:admin") === true,
12249
+ canManageWorkspaceDestination: hasPermission8(grant.permissions, "workspace:admin"),
12250
+ canManagePersonalDestination: authorization.contextIntegrity && authorization.authenticatedSubjectId === grant.subjectId
12214
12251
  });
12215
12252
  return c.json(ConnectionResponse.parse({ connection }));
12216
12253
  }
@@ -12693,7 +12730,7 @@ import {
12693
12730
  } from "@opengeni/documents";
12694
12731
  import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
12695
12732
  import { HTTPException as HTTPException13 } from "hono/http-exception";
12696
- import { requireAccessGrant as requireAccessGrant5, requireAccessGrantAuthorization } from "@opengeni/core";
12733
+ import { requireAccessGrant as requireAccessGrant5, requireAccessGrantAuthorization as requireAccessGrantAuthorization2 } from "@opengeni/core";
12697
12734
  import { recordWorkspaceUsage as recordWorkspaceUsage3, requireLimit as requireLimit3 } from "@opengeni/core";
12698
12735
 
12699
12736
  // src/mcp/documents.ts
@@ -13400,7 +13437,7 @@ function registerDocumentRoutes(app, deps) {
13400
13437
  });
13401
13438
  app.post("/v1/workspaces/:workspaceId/document-bases/:baseId/documents", async (c) => {
13402
13439
  const workspaceId = c.req.param("workspaceId");
13403
- const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "documents:manage");
13440
+ const access = await requireAccessGrantAuthorization2(c, deps, workspaceId, "documents:manage");
13404
13441
  const { grant } = access;
13405
13442
  if (!objectStorage) {
13406
13443
  throw new HTTPException13(503, { message: "object storage is not configured" });
@@ -13467,7 +13504,7 @@ function registerDocumentRoutes(app, deps) {
13467
13504
  "/v1/workspaces/:workspaceId/document-bases/:baseId/documents/:documentId",
13468
13505
  async (c) => {
13469
13506
  const workspaceId = c.req.param("workspaceId");
13470
- const authorization = await requireAccessGrantAuthorization(
13507
+ const authorization = await requireAccessGrantAuthorization2(
13471
13508
  c,
13472
13509
  deps,
13473
13510
  workspaceId,
@@ -13504,7 +13541,7 @@ function registerDocumentRoutes(app, deps) {
13504
13541
  "/v1/workspaces/:workspaceId/document-bases/:baseId/documents/:documentId/reindex",
13505
13542
  async (c) => {
13506
13543
  const workspaceId = c.req.param("workspaceId");
13507
- const authorization = await requireAccessGrantAuthorization(
13544
+ const authorization = await requireAccessGrantAuthorization2(
13508
13545
  c,
13509
13546
  deps,
13510
13547
  workspaceId,
@@ -13630,7 +13667,7 @@ function registerDocumentRoutes(app, deps) {
13630
13667
  });
13631
13668
  app.post("/v1/workspaces/:workspaceId/knowledge/drops", async (c) => {
13632
13669
  const workspaceId = c.req.param("workspaceId");
13633
- const access = await requireAccessGrantAuthorization(c, deps, workspaceId, "documents:manage");
13670
+ const access = await requireAccessGrantAuthorization2(c, deps, workspaceId, "documents:manage");
13634
13671
  const { grant } = access;
13635
13672
  if (!objectStorage) {
13636
13673
  throw new HTTPException13(503, { message: "object storage is not configured" });
@@ -13750,7 +13787,7 @@ function registerDocumentRoutes(app, deps) {
13750
13787
  });
13751
13788
  app.post("/v1/workspaces/:workspaceId/documents/:documentId/move", async (c) => {
13752
13789
  const workspaceId = c.req.param("workspaceId");
13753
- const authorization = await requireAccessGrantAuthorization(
13790
+ const authorization = await requireAccessGrantAuthorization2(
13754
13791
  c,
13755
13792
  deps,
13756
13793
  workspaceId,
@@ -21868,6 +21905,7 @@ import { randomUUID } from "crypto";
21868
21905
  import {
21869
21906
  ActivateWorkspaceInstructionPolicyRequest,
21870
21907
  CreateWorkspaceInstructionPolicyDraftRequest,
21908
+ CreateWorkspaceInstructionPolicyOnboardingProposalRequest,
21871
21909
  ImportLegacyWorkspaceInstructionPolicyDraftRequest,
21872
21910
  RollbackWorkspaceInstructionPolicyRequest,
21873
21911
  WorkspaceInstructionPolicyActivationResponse,
@@ -21876,22 +21914,34 @@ import {
21876
21914
  WorkspaceInstructionPolicyDiffResponse,
21877
21915
  WorkspaceInstructionPolicyListQuery,
21878
21916
  WorkspaceInstructionPolicyListResponse,
21917
+ WorkspaceInstructionPolicyOnboardingProposal,
21918
+ WorkspaceInstructionPolicyOnboardingProposalConflictResponse,
21919
+ WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse,
21920
+ WorkspaceInstructionPolicyOnboardingProposalListQuery,
21921
+ WorkspaceInstructionPolicyOnboardingProposalListResponse,
21922
+ WorkspaceInstructionPolicyOnboardingProposalStaleResponse,
21879
21923
  WorkspaceInstructionPolicyOperationReuseResponse,
21880
- WorkspaceInstructionPolicyRevision
21924
+ WorkspaceInstructionPolicyRevision,
21925
+ WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS
21881
21926
  } from "@opengeni/contracts";
21882
21927
  import { requireAccessGrant as requireAccessGrant17 } from "@opengeni/core";
21883
21928
  import {
21884
21929
  activateWorkspaceInstructionPolicyRevision,
21885
21930
  createWorkspaceInstructionPolicyDraft,
21931
+ createWorkspaceInstructionPolicyOnboardingProposal,
21886
21932
  diffWorkspaceInstructionPolicyRevisions,
21887
21933
  getWorkspaceInstructionPolicyRevision,
21888
21934
  importLegacyWorkspaceInstructionPolicyDraft,
21889
21935
  listWorkspaceInstructionPolicyRevisions,
21936
+ listWorkspaceInstructionPolicyOnboardingProposals,
21890
21937
  rollbackWorkspaceInstructionPolicyRevision,
21891
21938
  WorkspaceInstructionPolicyConflictError,
21892
21939
  WorkspaceInstructionPolicyInvalidOperationError,
21893
21940
  WorkspaceInstructionPolicyLegacyUnavailableError,
21894
21941
  WorkspaceInstructionPolicyNotFoundError,
21942
+ WorkspaceInstructionPolicyOnboardingProposalConflictError,
21943
+ WorkspaceInstructionPolicyOnboardingProposalContentError,
21944
+ WorkspaceInstructionPolicyOnboardingProposalStaleError,
21895
21945
  WorkspaceInstructionPolicyOperationReuseError
21896
21946
  } from "@opengeni/db";
21897
21947
  import { HTTPException as HTTPException27 } from "hono/http-exception";
@@ -21924,6 +21974,37 @@ function policyErrorResponse(context, error) {
21924
21974
  409
21925
21975
  );
21926
21976
  }
21977
+ if (error instanceof WorkspaceInstructionPolicyOnboardingProposalContentError) {
21978
+ return context.json(
21979
+ WorkspaceInstructionPolicyOnboardingProposalContentErrorResponse.parse({
21980
+ code: error.code,
21981
+ message: error.message,
21982
+ maxChars: WORKSPACE_INSTRUCTION_POLICY_CONTENT_MAX_CHARS
21983
+ }),
21984
+ 422
21985
+ );
21986
+ }
21987
+ if (error instanceof WorkspaceInstructionPolicyOnboardingProposalStaleError) {
21988
+ return context.json(
21989
+ WorkspaceInstructionPolicyOnboardingProposalStaleResponse.parse({
21990
+ code: error.code,
21991
+ message: error.message,
21992
+ currentHead: error.currentHead
21993
+ }),
21994
+ 409
21995
+ );
21996
+ }
21997
+ if (error instanceof WorkspaceInstructionPolicyOnboardingProposalConflictError) {
21998
+ return context.json(
21999
+ WorkspaceInstructionPolicyOnboardingProposalConflictResponse.parse({
22000
+ code: error.code,
22001
+ message: error.message,
22002
+ existingProposalId: error.existingProposalId,
22003
+ existingDraftRevisionId: error.existingDraftRevisionId
22004
+ }),
22005
+ 409
22006
+ );
22007
+ }
21927
22008
  if (error instanceof WorkspaceInstructionPolicyNotFoundError) {
21928
22009
  return context.json(
21929
22010
  { code: "WORKSPACE_INSTRUCTION_POLICY_NOT_FOUND", message: error.message },
@@ -22027,6 +22108,56 @@ function registerWorkspaceInstructionPolicyRoutes(app, deps) {
22027
22108
  return policyErrorResponse(context, error);
22028
22109
  }
22029
22110
  });
22111
+ app.get(`${base}/onboarding-proposals`, async (context) => {
22112
+ const workspaceId = context.req.param("workspaceId");
22113
+ await requireAccessGrant17(context, deps, workspaceId, "workspace:read");
22114
+ const parsed = WorkspaceInstructionPolicyOnboardingProposalListQuery.safeParse({
22115
+ limit: context.req.query("limit")
22116
+ });
22117
+ if (!parsed.success) {
22118
+ throw new HTTPException27(422, {
22119
+ message: "Invalid workspace instruction-policy onboarding-proposal query"
22120
+ });
22121
+ }
22122
+ return context.json(
22123
+ WorkspaceInstructionPolicyOnboardingProposalListResponse.parse(
22124
+ await listWorkspaceInstructionPolicyOnboardingProposals(deps.db, workspaceId, parsed.data)
22125
+ )
22126
+ );
22127
+ });
22128
+ app.post(`${base}/onboarding-proposals`, async (context) => {
22129
+ const workspaceId = context.req.param("workspaceId");
22130
+ const grant = await requireAccessGrant17(context, deps, workspaceId, "workspace:admin");
22131
+ assertBoundedActor(grant.subjectId);
22132
+ const request = await parseBody(
22133
+ context,
22134
+ CreateWorkspaceInstructionPolicyOnboardingProposalRequest
22135
+ );
22136
+ try {
22137
+ return context.json(
22138
+ WorkspaceInstructionPolicyOnboardingProposal.parse(
22139
+ await createWorkspaceInstructionPolicyOnboardingProposal(deps.db, {
22140
+ operationId: request.operationId ?? randomUUID(),
22141
+ accountId: grant.accountId,
22142
+ workspaceId,
22143
+ createdBySubjectId: grant.subjectId,
22144
+ kind: request.kind,
22145
+ scope: request.scope,
22146
+ roleKey: request.roleKey,
22147
+ content: request.content,
22148
+ sourceId: request.sourceId,
22149
+ sourceVersion: request.sourceVersion,
22150
+ confidenceBps: request.confidenceBps,
22151
+ expectedCurrentRevisionId: request.expectedCurrentRevisionId,
22152
+ expectedActivationVersion: request.expectedActivationVersion
22153
+ })
22154
+ ),
22155
+ 201
22156
+ );
22157
+ } catch (error) {
22158
+ return policyErrorResponse(context, error);
22159
+ }
22160
+ });
22030
22161
  app.get(`${base}/diff`, async (context) => {
22031
22162
  const workspaceId = context.req.param("workspaceId");
22032
22163
  await requireAccessGrant17(context, deps, workspaceId, "workspace:read");
@@ -22821,7 +22952,7 @@ import {
22821
22952
  import {
22822
22953
  hasPermission as hasPermission13,
22823
22954
  requireAccessGrant as requireAccessGrant20,
22824
- requireAccessGrantAuthorization as requireAccessGrantAuthorization2
22955
+ requireAccessGrantAuthorization as requireAccessGrantAuthorization3
22825
22956
  } from "@opengeni/core";
22826
22957
  import {
22827
22958
  activatePreferenceRegistryRevision,
@@ -22969,7 +23100,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
22969
23100
  });
22970
23101
  app.post(`${base}/proposals`, async (context) => {
22971
23102
  const workspaceId = context.req.param("workspaceId");
22972
- const access = await requireAccessGrantAuthorization2(
23103
+ const access = await requireAccessGrantAuthorization3(
22973
23104
  context,
22974
23105
  deps,
22975
23106
  workspaceId,
@@ -23049,7 +23180,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
23049
23180
  });
23050
23181
  app.post(`${base}/:preferenceId/activate`, async (context) => {
23051
23182
  const workspaceId = context.req.param("workspaceId");
23052
- const access = await requireAccessGrantAuthorization2(
23183
+ const access = await requireAccessGrantAuthorization3(
23053
23184
  context,
23054
23185
  deps,
23055
23186
  workspaceId,
@@ -23078,7 +23209,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
23078
23209
  });
23079
23210
  app.post(`${base}/:preferenceId/correct`, async (context) => {
23080
23211
  const workspaceId = context.req.param("workspaceId");
23081
- const access = await requireAccessGrantAuthorization2(
23212
+ const access = await requireAccessGrantAuthorization3(
23082
23213
  context,
23083
23214
  deps,
23084
23215
  workspaceId,
@@ -23107,7 +23238,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
23107
23238
  });
23108
23239
  app.post(`${base}/:preferenceId/scope`, async (context) => {
23109
23240
  const workspaceId = context.req.param("workspaceId");
23110
- const access = await requireAccessGrantAuthorization2(
23241
+ const access = await requireAccessGrantAuthorization3(
23111
23242
  context,
23112
23243
  deps,
23113
23244
  workspaceId,
@@ -23136,7 +23267,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
23136
23267
  });
23137
23268
  app.post(`${base}/:preferenceId/deactivate`, async (context) => {
23138
23269
  const workspaceId = context.req.param("workspaceId");
23139
- const access = await requireAccessGrantAuthorization2(
23270
+ const access = await requireAccessGrantAuthorization3(
23140
23271
  context,
23141
23272
  deps,
23142
23273
  workspaceId,
@@ -23165,7 +23296,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
23165
23296
  });
23166
23297
  app.post(`${base}/:preferenceId/supersede`, async (context) => {
23167
23298
  const workspaceId = context.req.param("workspaceId");
23168
- const access = await requireAccessGrantAuthorization2(
23299
+ const access = await requireAccessGrantAuthorization3(
23169
23300
  context,
23170
23301
  deps,
23171
23302
  workspaceId,
@@ -23194,7 +23325,7 @@ function registerPreferenceRegistryRoutes(app, deps) {
23194
23325
  });
23195
23326
  app.post(`${base}/:preferenceId/reject`, async (context) => {
23196
23327
  const workspaceId = context.req.param("workspaceId");
23197
- const access = await requireAccessGrantAuthorization2(
23328
+ const access = await requireAccessGrantAuthorization3(
23198
23329
  context,
23199
23330
  deps,
23200
23331
  workspaceId,
@@ -25996,4 +26127,4 @@ export {
25996
26127
  withDefaultEnabledCapabilityMcpTools,
25997
26128
  workflowIdForSession2 as workflowIdForSession
25998
26129
  };
25999
- //# sourceMappingURL=chunk-AEVD7E2F.js.map
26130
+ //# sourceMappingURL=chunk-AMMQI2D3.js.map