@opengeni/documents 0.3.3 → 0.5.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.
@@ -1,5 +1,6 @@
1
1
  import type { ScopedKnowledgeScope } from "@opengeni/contracts";
2
- import type { GoogleDriveSelectedSource, GoogleDriveTargetScope } from "@opengeni/contracts/google-drive";
2
+ import { type ConnectorDocumentDestination } from "@opengeni/contracts/connector-destinations";
3
+ import type { GoogleDriveSelectedSource } from "@opengeni/contracts/google-drive";
3
4
  export declare const GOOGLE_DRIVE_PROVIDER_KEY: "google-drive";
4
5
  export declare const GOOGLE_DRIVE_FOLDER_MIME_TYPE: "application/vnd.google-apps.folder";
5
6
  export declare const GOOGLE_DRIVE_SHORTCUT_MIME_TYPE: "application/vnd.google-apps.shortcut";
@@ -139,19 +140,25 @@ export declare class GoogleDriveInventoryProviderError extends Error {
139
140
  readonly providerCode: string;
140
141
  constructor(providerCode: string);
141
142
  }
142
- export declare function googleDriveKnowledgeScope(targetScope: GoogleDriveTargetScope, workspaceId: string, initiatingSubjectId: string): ScopedKnowledgeScope;
143
+ export declare function googleDriveKnowledgeScope(destination: ConnectorDocumentDestination): ScopedKnowledgeScope;
143
144
  export declare function googleDriveKnowledgeSourceIdentity(input: {
144
145
  googlePermissionId: string;
145
- source: Pick<GoogleDriveSelectedSource, "id" | "driveId" | "targetScope">;
146
+ source: Pick<GoogleDriveSelectedSource, "id" | "driveId" | "destination" | "targetScope">;
147
+ accountId?: string | undefined;
146
148
  workspaceId: string;
147
- initiatingSubjectId: string;
149
+ connectionSubjectId?: string | null | undefined;
150
+ /** @deprecated Used only to validate old callers while source destinations migrate. */
151
+ initiatingSubjectId?: string | undefined;
148
152
  }): GoogleDriveKnowledgeSourceIdentity;
149
153
  export declare function planGoogleDriveTransfer(item: GoogleDriveInventoryProviderItem, maxFileBytes: number): GoogleDriveTransferPlan;
150
154
  export declare function inventoryGoogleDriveSource(input: {
151
155
  googlePermissionId: string;
152
156
  source: GoogleDriveSelectedSource;
157
+ accountId?: string | undefined;
153
158
  workspaceId: string;
154
- initiatingSubjectId: string;
159
+ connectionSubjectId?: string | null | undefined;
160
+ /** @deprecated Used only to validate old callers while source destinations migrate. */
161
+ initiatingSubjectId?: string | undefined;
155
162
  limits: GoogleDriveInventoryLimits;
156
163
  listChildren: GoogleDriveListChildren;
157
164
  checkpoint?: GoogleDriveInventoryCheckpoint | null;
@@ -1,4 +1,8 @@
1
1
  // src/google-drive.ts
2
+ import {
3
+ connectorDestinationDocumentAuthority,
4
+ resolveConnectorDocumentDestination
5
+ } from "@opengeni/contracts/connector-destinations";
2
6
  var GOOGLE_DRIVE_PROVIDER_KEY = "google-drive";
3
7
  var GOOGLE_DRIVE_FOLDER_MIME_TYPE = "application/vnd.google-apps.folder";
4
8
  var GOOGLE_DRIVE_SHORTCUT_MIME_TYPE = "application/vnd.google-apps.shortcut";
@@ -64,36 +68,46 @@ var GoogleDriveInventoryProviderError = class extends Error {
64
68
  this.name = "GoogleDriveInventoryProviderError";
65
69
  }
66
70
  };
67
- function googleDriveKnowledgeScope(targetScope, workspaceId, initiatingSubjectId) {
68
- const boundedWorkspaceId = boundedText(workspaceId, "workspaceId", 256);
69
- const boundedSubjectId = boundedText(initiatingSubjectId, "initiatingSubjectId", 1024);
70
- if (targetScope === "organization") {
71
+ function googleDriveKnowledgeScope(destination) {
72
+ const authority = connectorDestinationDocumentAuthority(destination);
73
+ if (authority.authorityKind === "organization") {
71
74
  return { kind: "organization", workspaceId: null, subjectId: null };
72
75
  }
73
- if (targetScope === "workspace") {
74
- return { kind: "workspace", workspaceId: boundedWorkspaceId, subjectId: null };
76
+ if (authority.authorityKind === "workspace") {
77
+ if (!authority.authorityWorkspaceId) {
78
+ throw new Error("workspace connector destination is missing workspace authority");
79
+ }
80
+ return {
81
+ kind: "workspace",
82
+ workspaceId: authority.authorityWorkspaceId,
83
+ subjectId: null
84
+ };
85
+ }
86
+ if (!authority.authorityWorkspaceId || !authority.authoritySubjectId) {
87
+ throw new Error("personal connector destination is missing immutable authority");
75
88
  }
76
89
  return {
77
90
  kind: "personal",
78
- workspaceId: boundedWorkspaceId,
79
- subjectId: boundedSubjectId
91
+ workspaceId: authority.authorityWorkspaceId,
92
+ subjectId: authority.authoritySubjectId
80
93
  };
81
94
  }
82
95
  function googleDriveKnowledgeSourceIdentity(input) {
83
96
  const sourceId = driveId(input.source.id, "source.id");
84
97
  const externalTenantId = normalizedGooglePermissionId(input.googlePermissionId);
85
98
  const sourceDriveId = nullableDriveId(input.source.driveId, "source.driveId");
99
+ const destination = resolveConnectorDocumentDestination(input.source.destination, {
100
+ accountId: input.accountId ?? input.workspaceId,
101
+ workspaceId: input.workspaceId,
102
+ connectionSubjectId: input.connectionSubjectId !== void 0 ? input.connectionSubjectId : input.initiatingSubjectId ?? null
103
+ });
86
104
  return {
87
105
  providerKey: GOOGLE_DRIVE_PROVIDER_KEY,
88
106
  externalTenantId,
89
107
  externalSourceId: sourceId,
90
108
  sourceKind: sourceId === "root" ? "google-drive-my-drive" : sourceDriveId === sourceId ? "google-drive-shared-drive" : "google-drive-folder",
91
109
  sourceUri: googleDriveSourceUri(sourceId),
92
- scope: googleDriveKnowledgeScope(
93
- input.source.targetScope,
94
- input.workspaceId,
95
- input.initiatingSubjectId
96
- )
110
+ scope: googleDriveKnowledgeScope(destination)
97
111
  };
98
112
  }
99
113
  function planGoogleDriveTransfer(item, maxFileBytes) {
@@ -141,8 +155,10 @@ async function inventoryGoogleDriveSource(input) {
141
155
  const source = googleDriveKnowledgeSourceIdentity({
142
156
  googlePermissionId,
143
157
  source: input.source,
158
+ ...input.accountId ? { accountId: input.accountId } : {},
144
159
  workspaceId: input.workspaceId,
145
- initiatingSubjectId: input.initiatingSubjectId
160
+ ...input.connectionSubjectId !== void 0 ? { connectionSubjectId: input.connectionSubjectId } : {},
161
+ ...input.initiatingSubjectId ? { initiatingSubjectId: input.initiatingSubjectId } : {}
146
162
  });
147
163
  const checkpointIdentity = {
148
164
  googlePermissionId,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/google-drive.ts"],"sourcesContent":["import type { ScopedKnowledgeScope } from \"@opengeni/contracts\";\nimport type {\n GoogleDriveSelectedSource,\n GoogleDriveTargetScope,\n} from \"@opengeni/contracts/google-drive\";\n\nexport const GOOGLE_DRIVE_PROVIDER_KEY = \"google-drive\" as const;\nexport const GOOGLE_DRIVE_FOLDER_MIME_TYPE = \"application/vnd.google-apps.folder\" as const;\nexport const GOOGLE_DRIVE_SHORTCUT_MIME_TYPE = \"application/vnd.google-apps.shortcut\" as const;\n\nconst GOOGLE_DRIVE_NATIVE_MIME_PREFIX = \"application/vnd.google-apps.\";\nconst GOOGLE_DRIVE_MAX_ID_CHARS = 256;\nconst GOOGLE_DRIVE_MAX_NAME_CHARS = 1024;\nconst GOOGLE_DRIVE_MAX_MIME_CHARS = 256;\nconst GOOGLE_DRIVE_MAX_PAGE_TOKEN_CHARS = 4096;\nconst GOOGLE_DRIVE_MAX_PAGE_ITEMS = 100;\nconst GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS = 2_000;\nconst GOOGLE_DRIVE_MAX_CHECKPOINT_BYTES = 2 * 1024 * 1024;\n\nconst GOOGLE_DRIVE_NATIVE_EXPORTS = new Map<string, { contentType: string; extension: string }>([\n [\n \"application/vnd.google-apps.document\",\n {\n contentType: \"application/pdf\",\n extension: \".pdf\",\n },\n ],\n [\n \"application/vnd.google-apps.spreadsheet\",\n {\n contentType: \"application/pdf\",\n extension: \".pdf\",\n },\n ],\n [\n \"application/vnd.google-apps.presentation\",\n {\n contentType: \"application/pdf\",\n extension: \".pdf\",\n },\n ],\n [\"application/vnd.google-apps.drawing\", { contentType: \"application/pdf\", extension: \".pdf\" }],\n]);\n\nconst DEPENDENCY_FREE_ORDINARY_CONTENT_TYPES = new Set([\n \"application/json\",\n \"application/pdf\",\n \"application/xml\",\n \"application/x-yaml\",\n \"application/yaml\",\n]);\n\nconst GENERIC_BINARY_CONTENT_TYPES = new Set([\"application/octet-stream\", \"binary/octet-stream\"]);\n\nconst DEPENDENCY_FREE_EXTENSION_CONTENT_TYPES = new Map([\n [\".csv\", \"text/csv\"],\n [\".htm\", \"text/html\"],\n [\".html\", \"text/html\"],\n [\".json\", \"application/json\"],\n [\".markdown\", \"text/markdown\"],\n [\".md\", \"text/markdown\"],\n [\".pdf\", \"application/pdf\"],\n [\".text\", \"text/plain\"],\n [\".tsv\", \"text/tab-separated-values\"],\n [\".txt\", \"text/plain\"],\n [\".xml\", \"application/xml\"],\n [\".yaml\", \"application/x-yaml\"],\n [\".yml\", \"application/x-yaml\"],\n]);\n\nexport type GoogleDriveKnowledgeSourceIdentity = {\n providerKey: typeof GOOGLE_DRIVE_PROVIDER_KEY;\n externalTenantId: string;\n externalSourceId: string;\n sourceKind: \"google-drive-my-drive\" | \"google-drive-shared-drive\" | \"google-drive-folder\";\n sourceUri: string;\n scope: ScopedKnowledgeScope;\n};\n\n/**\n * Normalized item metadata expected from a bounded Drive files.list adapter.\n * The adapter owns provider JSON validation; this planner owns traversal,\n * checkpointing, resource limits, stable identity, and transfer classification.\n */\nexport type GoogleDriveInventoryProviderItem = {\n id: string;\n name: string;\n mimeType: string;\n driveId: string | null;\n parents: string[];\n modifiedTime: string | null;\n createdTime: string | null;\n version: string | null;\n md5Checksum: string | null;\n size: string | null;\n webViewLink: string | null;\n trashed: boolean;\n};\n\nexport type GoogleDriveInventoryPage = {\n items: GoogleDriveInventoryProviderItem[];\n nextPageToken: string | null;\n incompleteSearch: boolean;\n};\n\nexport type GoogleDriveInventoryLimits = {\n /** Hard cumulative provider-item discovery limit for this checkpoint. */\n maxItems: number;\n /** Hard cumulative known-byte limit for ordinary file downloads. */\n maxKnownBytes: number;\n /** Hard cumulative Drive list request/cost limit for this checkpoint. */\n maxApiRequests: number;\n /** Wall-clock budget for one invocation; checkpoint counters remain cumulative. */\n maxElapsedMs: number;\n /** Per-file byte ceiling. Unknown/export sizes must be enforced again while streaming. */\n maxFileBytes: number;\n /** Cycle/graph explosion guard for traversed folders. */\n maxFolders: number;\n /** Requested Drive page size. */\n pageSize: number;\n};\n\nexport type GoogleDriveTransferSkipReason =\n | \"file_too_large\"\n | \"folder_limit\"\n | \"folder_loop\"\n | \"shortcut_unsupported\"\n | \"trashed\"\n | \"unsupported_file_type\"\n | \"unsupported_native_type\";\n\nexport type GoogleDriveTransferPlan =\n | { action: \"traverse\" }\n | {\n action: \"export\";\n contentType: string;\n filename: string;\n declaredBytes: null;\n }\n | {\n action: \"download\";\n contentType: string;\n filename: string;\n declaredBytes: string | null;\n }\n | { action: \"skip\"; reason: GoogleDriveTransferSkipReason };\n\nexport type GoogleDriveInventoryEntry = {\n externalObjectId: string;\n externalVersionId: string | null;\n sourceId: string;\n parentFolderId: string;\n driveId: string | null;\n title: string;\n mimeType: string;\n modifiedTime: string | null;\n createdTime: string | null;\n sourceUri: string;\n transfer: GoogleDriveTransferPlan;\n};\n\nexport type GoogleDriveInventoryIssue = {\n code: \"incomplete_search\" | \"invalid_page\" | \"provider_error\";\n folderId: string;\n providerCode: string | null;\n};\n\nexport type GoogleDriveInventoryStopReason =\n | \"api_request_limit\"\n | \"elapsed_time_limit\"\n | \"incomplete_search\"\n | \"item_limit\"\n | \"known_byte_limit\"\n | \"provider_error\";\n\nexport type GoogleDriveInventoryTotals = {\n itemCount: number;\n folderCount: number;\n plannedFileCount: number;\n skippedItemCount: number;\n exportFileCount: number;\n downloadFileCount: number;\n unknownSizeFileCount: number;\n apiRequestCount: number;\n knownBytes: string;\n};\n\ntype GoogleDriveInventoryFrame = {\n folderId: string;\n driveId: string | null;\n pageToken: string | null;\n loaded: boolean;\n bufferedItems: GoogleDriveInventoryProviderItem[];\n nextPageToken: string | null;\n};\n\nexport type GoogleDriveInventoryCheckpoint = {\n version: 2;\n googlePermissionId: string;\n externalTenantId: string;\n sourceId: string;\n sourceDriveId: string | null;\n scope: ScopedKnowledgeScope;\n pendingFolders: GoogleDriveInventoryFrame[];\n seenFolderIds: string[];\n totals: GoogleDriveInventoryTotals;\n};\n\nexport type GoogleDriveInventoryResult = {\n status: \"complete\" | \"paused\";\n stopReason: GoogleDriveInventoryStopReason | null;\n source: GoogleDriveKnowledgeSourceIdentity;\n entries: GoogleDriveInventoryEntry[];\n issues: GoogleDriveInventoryIssue[];\n totals: GoogleDriveInventoryTotals;\n run: GoogleDriveInventoryTotals & { elapsedMs: number };\n checkpoint: GoogleDriveInventoryCheckpoint | null;\n};\n\nexport type GoogleDriveListChildren = (input: {\n folderId: string;\n driveId: string | null;\n pageToken: string | null;\n pageSize: number;\n}) => Promise<GoogleDriveInventoryPage>;\n\nexport class GoogleDriveInventoryProviderError extends Error {\n constructor(readonly providerCode: string) {\n super(providerCode);\n this.name = \"GoogleDriveInventoryProviderError\";\n }\n}\n\nexport function googleDriveKnowledgeScope(\n targetScope: GoogleDriveTargetScope,\n workspaceId: string,\n initiatingSubjectId: string,\n): ScopedKnowledgeScope {\n const boundedWorkspaceId = boundedText(workspaceId, \"workspaceId\", 256);\n const boundedSubjectId = boundedText(initiatingSubjectId, \"initiatingSubjectId\", 1024);\n if (targetScope === \"organization\") {\n return { kind: \"organization\", workspaceId: null, subjectId: null };\n }\n if (targetScope === \"workspace\") {\n return { kind: \"workspace\", workspaceId: boundedWorkspaceId, subjectId: null };\n }\n // Google Drive connections are workspace-bound today. Preserve that boundary\n // for personal knowledge rather than silently widening it across workspaces.\n return {\n kind: \"personal\",\n workspaceId: boundedWorkspaceId,\n subjectId: boundedSubjectId,\n };\n}\n\nexport function googleDriveKnowledgeSourceIdentity(input: {\n googlePermissionId: string;\n source: Pick<GoogleDriveSelectedSource, \"id\" | \"driveId\" | \"targetScope\">;\n workspaceId: string;\n initiatingSubjectId: string;\n}): GoogleDriveKnowledgeSourceIdentity {\n const sourceId = driveId(input.source.id, \"source.id\");\n const externalTenantId = normalizedGooglePermissionId(input.googlePermissionId);\n const sourceDriveId = nullableDriveId(input.source.driveId, \"source.driveId\");\n return {\n providerKey: GOOGLE_DRIVE_PROVIDER_KEY,\n externalTenantId,\n externalSourceId: sourceId,\n sourceKind:\n sourceId === \"root\"\n ? \"google-drive-my-drive\"\n : sourceDriveId === sourceId\n ? \"google-drive-shared-drive\"\n : \"google-drive-folder\",\n sourceUri: googleDriveSourceUri(sourceId),\n scope: googleDriveKnowledgeScope(\n input.source.targetScope,\n input.workspaceId,\n input.initiatingSubjectId,\n ),\n };\n}\n\nexport function planGoogleDriveTransfer(\n item: GoogleDriveInventoryProviderItem,\n maxFileBytes: number,\n): GoogleDriveTransferPlan {\n const normalized = validatedProviderItem(item);\n const byteLimit = safePositiveInteger(maxFileBytes, \"maxFileBytes\");\n if (normalized.trashed) {\n return { action: \"skip\", reason: \"trashed\" };\n }\n if (normalized.mimeType === GOOGLE_DRIVE_FOLDER_MIME_TYPE) {\n return { action: \"traverse\" };\n }\n if (normalized.mimeType === GOOGLE_DRIVE_SHORTCUT_MIME_TYPE) {\n return { action: \"skip\", reason: \"shortcut_unsupported\" };\n }\n const nativeExport = GOOGLE_DRIVE_NATIVE_EXPORTS.get(normalized.mimeType);\n if (nativeExport) {\n return {\n action: \"export\",\n contentType: nativeExport.contentType,\n filename: exportedFilename(normalized.name, nativeExport.extension),\n declaredBytes: null,\n };\n }\n if (normalized.mimeType.startsWith(GOOGLE_DRIVE_NATIVE_MIME_PREFIX)) {\n return { action: \"skip\", reason: \"unsupported_native_type\" };\n }\n const declaredBytes = fileSize(normalized.size);\n if (declaredBytes !== null && declaredBytes > BigInt(byteLimit)) {\n return { action: \"skip\", reason: \"file_too_large\" };\n }\n const contentType = dependencyFreeOrdinaryContentType(normalized.name, normalized.mimeType);\n if (!contentType) {\n return { action: \"skip\", reason: \"unsupported_file_type\" };\n }\n return {\n action: \"download\",\n contentType,\n filename: safeFilename(normalized.name),\n declaredBytes: declaredBytes?.toString() ?? null,\n };\n}\n\nexport async function inventoryGoogleDriveSource(input: {\n googlePermissionId: string;\n source: GoogleDriveSelectedSource;\n workspaceId: string;\n initiatingSubjectId: string;\n limits: GoogleDriveInventoryLimits;\n listChildren: GoogleDriveListChildren;\n checkpoint?: GoogleDriveInventoryCheckpoint | null;\n now?: (() => number) | undefined;\n}): Promise<GoogleDriveInventoryResult> {\n const limits = validatedLimits(input.limits);\n const googlePermissionId = normalizedGooglePermissionId(input.googlePermissionId);\n const source = googleDriveKnowledgeSourceIdentity({\n googlePermissionId,\n source: input.source,\n workspaceId: input.workspaceId,\n initiatingSubjectId: input.initiatingSubjectId,\n });\n const checkpointIdentity: GoogleDriveInventoryCheckpointIdentity = {\n googlePermissionId,\n externalTenantId: source.externalTenantId,\n sourceId: source.externalSourceId,\n sourceDriveId: nullableDriveId(input.source.driveId, \"source.driveId\"),\n scope: source.scope,\n };\n const now = input.now ?? Date.now;\n const startedAt = now();\n const checkpoint = input.checkpoint\n ? validatedCheckpoint(input.checkpoint, checkpointIdentity, limits)\n : initialCheckpoint(checkpointIdentity);\n const initialTotals = cloneTotals(checkpoint.totals);\n const entries: GoogleDriveInventoryEntry[] = [];\n const issues: GoogleDriveInventoryIssue[] = [];\n let stopReason: GoogleDriveInventoryStopReason | null = null;\n\n while (checkpoint.pendingFolders.length > 0) {\n if (now() - startedAt >= limits.maxElapsedMs) {\n stopReason = \"elapsed_time_limit\";\n break;\n }\n const frame = checkpoint.pendingFolders[0]!;\n if (frame.loaded && frame.bufferedItems.length === 0) {\n if (frame.nextPageToken) {\n frame.pageToken = frame.nextPageToken;\n frame.nextPageToken = null;\n frame.loaded = false;\n } else {\n checkpoint.pendingFolders.shift();\n }\n continue;\n }\n if (checkpoint.totals.itemCount >= limits.maxItems) {\n stopReason = \"item_limit\";\n break;\n }\n\n if (!frame.loaded) {\n if (checkpoint.totals.apiRequestCount >= limits.maxApiRequests) {\n stopReason = \"api_request_limit\";\n break;\n }\n const remainingItems = limits.maxItems - checkpoint.totals.itemCount;\n const requestedPageSize = Math.min(limits.pageSize, remainingItems);\n let page: GoogleDriveInventoryPage;\n try {\n page = await input.listChildren({\n folderId: frame.folderId,\n driveId: frame.driveId,\n pageToken: frame.pageToken,\n pageSize: requestedPageSize,\n });\n } catch (error) {\n checkpoint.totals.apiRequestCount += 1;\n issues.push({\n code: \"provider_error\",\n folderId: frame.folderId,\n providerCode: providerErrorCode(error),\n });\n stopReason = \"provider_error\";\n break;\n }\n checkpoint.totals.apiRequestCount += 1;\n if (!validPage(page, requestedPageSize)) {\n issues.push({ code: \"invalid_page\", folderId: frame.folderId, providerCode: null });\n stopReason = \"provider_error\";\n break;\n }\n if (page.incompleteSearch) {\n issues.push({ code: \"incomplete_search\", folderId: frame.folderId, providerCode: null });\n stopReason = \"incomplete_search\";\n break;\n }\n frame.loaded = true;\n frame.bufferedItems = page.items.map(validatedProviderItem);\n frame.nextPageToken = page.nextPageToken;\n if (now() - startedAt >= limits.maxElapsedMs) {\n stopReason = \"elapsed_time_limit\";\n break;\n }\n }\n\n if (frame.bufferedItems.length === 0) {\n if (frame.nextPageToken) {\n frame.pageToken = frame.nextPageToken;\n frame.nextPageToken = null;\n frame.loaded = false;\n } else {\n checkpoint.pendingFolders.shift();\n }\n continue;\n }\n\n const item = validatedProviderItem(frame.bufferedItems[0]!);\n let transfer = planGoogleDriveTransfer(item, limits.maxFileBytes);\n if (transfer.action === \"download\" && transfer.declaredBytes !== null) {\n const nextKnownBytes = BigInt(checkpoint.totals.knownBytes) + BigInt(transfer.declaredBytes);\n if (nextKnownBytes > BigInt(limits.maxKnownBytes)) {\n stopReason = \"known_byte_limit\";\n break;\n }\n }\n\n frame.bufferedItems.shift();\n checkpoint.totals.itemCount += 1;\n const effectiveDriveId = item.driveId ?? frame.driveId;\n if (transfer.action === \"traverse\") {\n if (checkpoint.seenFolderIds.includes(item.id)) {\n transfer = { action: \"skip\", reason: \"folder_loop\" };\n } else if (checkpoint.seenFolderIds.length >= limits.maxFolders) {\n transfer = { action: \"skip\", reason: \"folder_limit\" };\n } else {\n checkpoint.seenFolderIds.push(item.id);\n checkpoint.totals.folderCount += 1;\n checkpoint.pendingFolders.push({\n folderId: item.id,\n driveId: effectiveDriveId,\n pageToken: null,\n loaded: false,\n bufferedItems: [],\n nextPageToken: null,\n });\n }\n }\n\n if (transfer.action === \"skip\") {\n checkpoint.totals.skippedItemCount += 1;\n } else if (transfer.action === \"download\") {\n checkpoint.totals.plannedFileCount += 1;\n checkpoint.totals.downloadFileCount += 1;\n if (transfer.declaredBytes === null) {\n checkpoint.totals.unknownSizeFileCount += 1;\n } else {\n checkpoint.totals.knownBytes = (\n BigInt(checkpoint.totals.knownBytes) + BigInt(transfer.declaredBytes)\n ).toString();\n }\n } else if (transfer.action === \"export\") {\n checkpoint.totals.plannedFileCount += 1;\n checkpoint.totals.exportFileCount += 1;\n checkpoint.totals.unknownSizeFileCount += 1;\n }\n\n entries.push({\n externalObjectId: item.id,\n externalVersionId: item.version ?? item.md5Checksum ?? item.modifiedTime,\n sourceId: source.externalSourceId,\n parentFolderId: frame.folderId,\n driveId: effectiveDriveId,\n title: item.name,\n mimeType: item.mimeType,\n modifiedTime: item.modifiedTime,\n createdTime: item.createdTime,\n sourceUri: item.webViewLink ?? googleDriveFileUri(item.id),\n transfer,\n });\n }\n\n const elapsedMs = Math.max(0, now() - startedAt);\n const complete = checkpoint.pendingFolders.length === 0;\n const outputCheckpoint = complete ? null : cloneCheckpoint(checkpoint);\n if (outputCheckpoint) assertCheckpointBytes(outputCheckpoint);\n return {\n status: complete ? \"complete\" : \"paused\",\n stopReason: complete ? null : stopReason,\n source,\n entries,\n issues,\n totals: cloneTotals(checkpoint.totals),\n run: {\n ...subtractTotals(checkpoint.totals, initialTotals),\n elapsedMs,\n },\n checkpoint: outputCheckpoint,\n };\n}\n\ntype GoogleDriveInventoryCheckpointIdentity = Pick<\n GoogleDriveInventoryCheckpoint,\n \"googlePermissionId\" | \"externalTenantId\" | \"sourceId\" | \"sourceDriveId\" | \"scope\"\n>;\n\nfunction initialCheckpoint(\n identity: GoogleDriveInventoryCheckpointIdentity,\n): GoogleDriveInventoryCheckpoint {\n return {\n version: 2,\n googlePermissionId: identity.googlePermissionId,\n externalTenantId: identity.externalTenantId,\n sourceId: identity.sourceId,\n sourceDriveId: identity.sourceDriveId,\n scope: cloneScope(identity.scope),\n pendingFolders: [\n {\n folderId: identity.sourceId,\n driveId: identity.sourceDriveId,\n pageToken: null,\n loaded: false,\n bufferedItems: [],\n nextPageToken: null,\n },\n ],\n seenFolderIds: [identity.sourceId],\n totals: emptyTotals(),\n };\n}\n\nfunction validatedCheckpoint(\n value: GoogleDriveInventoryCheckpoint,\n identity: GoogleDriveInventoryCheckpointIdentity,\n limits: GoogleDriveInventoryLimits,\n): GoogleDriveInventoryCheckpoint {\n if (!value || typeof value !== \"object\" || value.version !== 2) {\n throw new Error(\"unsupported Google Drive inventory checkpoint\");\n }\n if (\n value.googlePermissionId !== identity.googlePermissionId ||\n value.externalTenantId !== identity.externalTenantId ||\n value.sourceId !== identity.sourceId ||\n value.sourceDriveId !== identity.sourceDriveId ||\n !sameScope(value.scope, identity.scope)\n ) {\n throw new Error(\"Google Drive inventory checkpoint does not match the selected source\");\n }\n const checkpoint = cloneCheckpoint(value);\n if (checkpoint.pendingFolders.length === 0) {\n throw new Error(\"Google Drive inventory checkpoint is already complete\");\n }\n if (\n checkpoint.pendingFolders.length > GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS ||\n checkpoint.seenFolderIds.length > GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS ||\n checkpoint.seenFolderIds.length > limits.maxFolders\n ) {\n throw new Error(\"Google Drive inventory checkpoint exceeds the folder limit\");\n }\n if (!checkpoint.seenFolderIds.includes(identity.sourceId)) {\n throw new Error(\"Google Drive inventory checkpoint lost its source boundary\");\n }\n if (new Set(checkpoint.seenFolderIds).size !== checkpoint.seenFolderIds.length) {\n throw new Error(\"Google Drive inventory checkpoint contains duplicate folder identity\");\n }\n for (const folderId of checkpoint.seenFolderIds) driveId(folderId, \"checkpoint.folderId\");\n const pendingFolderIds = new Set<string>();\n for (const frame of checkpoint.pendingFolders) {\n driveId(frame.folderId, \"checkpoint.pending.folderId\");\n if (\n !checkpoint.seenFolderIds.includes(frame.folderId) ||\n pendingFolderIds.has(frame.folderId)\n ) {\n throw new Error(\"Google Drive inventory checkpoint contains an invalid pending folder\");\n }\n pendingFolderIds.add(frame.folderId);\n nullableDriveId(frame.driveId, \"checkpoint.pending.driveId\");\n pageToken(frame.pageToken, \"checkpoint.pending.pageToken\");\n pageToken(frame.nextPageToken, \"checkpoint.pending.nextPageToken\");\n if (\n typeof frame.loaded !== \"boolean\" ||\n frame.bufferedItems.length > GOOGLE_DRIVE_MAX_PAGE_ITEMS\n ) {\n throw new Error(\"Google Drive inventory checkpoint contains an invalid page frame\");\n }\n if (!frame.loaded && (frame.bufferedItems.length > 0 || frame.nextPageToken !== null)) {\n throw new Error(\"Google Drive inventory checkpoint contains an uncommitted page frame\");\n }\n frame.bufferedItems = frame.bufferedItems.map(validatedProviderItem);\n }\n validatedTotals(checkpoint.totals);\n if (\n checkpoint.totals.folderCount !== checkpoint.seenFolderIds.length ||\n checkpoint.totals.plannedFileCount !==\n checkpoint.totals.exportFileCount + checkpoint.totals.downloadFileCount ||\n checkpoint.totals.unknownSizeFileCount > checkpoint.totals.plannedFileCount ||\n checkpoint.totals.itemCount !==\n checkpoint.totals.skippedItemCount +\n checkpoint.totals.plannedFileCount +\n checkpoint.totals.folderCount -\n 1\n ) {\n throw new Error(\"Google Drive inventory checkpoint totals are inconsistent\");\n }\n if (\n checkpoint.totals.itemCount > limits.maxItems ||\n checkpoint.totals.apiRequestCount > limits.maxApiRequests ||\n BigInt(checkpoint.totals.knownBytes) > BigInt(limits.maxKnownBytes)\n ) {\n throw new Error(\"Google Drive inventory checkpoint exceeds the supplied limits\");\n }\n assertCheckpointBytes(checkpoint);\n return checkpoint;\n}\n\nfunction validatedLimits(value: GoogleDriveInventoryLimits): GoogleDriveInventoryLimits {\n const limits = {\n maxItems: safePositiveInteger(value.maxItems, \"limits.maxItems\"),\n maxKnownBytes: safePositiveInteger(value.maxKnownBytes, \"limits.maxKnownBytes\"),\n maxApiRequests: safePositiveInteger(value.maxApiRequests, \"limits.maxApiRequests\"),\n maxElapsedMs: safePositiveInteger(value.maxElapsedMs, \"limits.maxElapsedMs\"),\n maxFileBytes: safePositiveInteger(value.maxFileBytes, \"limits.maxFileBytes\"),\n maxFolders: safePositiveInteger(value.maxFolders, \"limits.maxFolders\"),\n pageSize: safePositiveInteger(value.pageSize, \"limits.pageSize\"),\n };\n if (limits.pageSize > GOOGLE_DRIVE_MAX_PAGE_ITEMS) {\n throw new Error(`limits.pageSize must be <= ${GOOGLE_DRIVE_MAX_PAGE_ITEMS}`);\n }\n if (limits.maxFolders > GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS) {\n throw new Error(`limits.maxFolders must be <= ${GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS}`);\n }\n return limits;\n}\n\nfunction validPage(value: GoogleDriveInventoryPage, expectedMaxItems: number): boolean {\n if (\n !value ||\n !Array.isArray(value.items) ||\n value.items.length > expectedMaxItems ||\n value.items.length > GOOGLE_DRIVE_MAX_PAGE_ITEMS\n ) {\n return false;\n }\n try {\n pageToken(value.nextPageToken, \"page.nextPageToken\");\n value.items.forEach(validatedProviderItem);\n return typeof value.incompleteSearch === \"boolean\";\n } catch {\n return false;\n }\n}\n\nfunction validatedProviderItem(\n item: GoogleDriveInventoryProviderItem,\n): GoogleDriveInventoryProviderItem {\n const id = driveId(item.id, \"item.id\");\n const name = boundedText(item.name, \"item.name\", GOOGLE_DRIVE_MAX_NAME_CHARS);\n const mimeType = boundedText(item.mimeType, \"item.mimeType\", GOOGLE_DRIVE_MAX_MIME_CHARS);\n const parents = Array.isArray(item.parents)\n ? item.parents.map((parent) => driveId(parent, \"item.parent\"))\n : [];\n if (parents.length > 100) throw new Error(\"item.parents exceeds the supported bound\");\n return {\n id,\n name,\n mimeType,\n driveId: nullableDriveId(item.driveId, \"item.driveId\"),\n parents,\n modifiedTime: nullableBoundedText(item.modifiedTime, \"item.modifiedTime\", 128),\n createdTime: nullableBoundedText(item.createdTime, \"item.createdTime\", 128),\n version: nullableBoundedText(item.version, \"item.version\", 256),\n md5Checksum: nullableBoundedText(item.md5Checksum, \"item.md5Checksum\", 128),\n size: fileSize(item.size)?.toString() ?? null,\n webViewLink: nullableHttpsUrl(item.webViewLink, \"item.webViewLink\"),\n trashed: item.trashed === true,\n };\n}\n\nfunction dependencyFreeOrdinaryContentType(name: string, mimeType: string): string | null {\n const normalizedMime = mimeType.trim().toLowerCase();\n if (normalizedMime.startsWith(\"text/\")) return normalizedMime;\n if (DEPENDENCY_FREE_ORDINARY_CONTENT_TYPES.has(normalizedMime)) return normalizedMime;\n if (!GENERIC_BINARY_CONTENT_TYPES.has(normalizedMime)) return null;\n const lowerName = name.toLowerCase();\n for (const [extension, contentType] of DEPENDENCY_FREE_EXTENSION_CONTENT_TYPES) {\n if (lowerName.endsWith(extension)) return contentType;\n }\n return null;\n}\n\nfunction exportedFilename(name: string, extension: string): string {\n const filename = safeFilename(name);\n return filename.toLowerCase().endsWith(extension) ? filename : `${filename}${extension}`;\n}\n\nfunction safeFilename(value: string): string {\n const cleaned = value\n .normalize(\"NFKC\")\n .replace(/[\\u0000-\\u001f\\u007f/\\\\]/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .trim()\n .slice(0, 512);\n return cleaned || \"untitled\";\n}\n\nfunction googleDriveSourceUri(id: string): string {\n return id === \"root\"\n ? \"https://drive.google.com/drive/my-drive\"\n : `https://drive.google.com/drive/folders/${encodeURIComponent(id)}`;\n}\n\nfunction googleDriveFileUri(id: string): string {\n return `https://drive.google.com/open?id=${encodeURIComponent(id)}`;\n}\n\nfunction fileSize(value: string | null): bigint | null {\n if (value === null) return null;\n if (!/^\\d{1,40}$/u.test(value)) throw new Error(\"item.size is invalid\");\n return BigInt(value);\n}\n\nfunction providerErrorCode(error: unknown): string | null {\n if (!(error instanceof GoogleDriveInventoryProviderError)) return null;\n const normalized = error.providerCode.trim().toLowerCase();\n return /^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$/u.test(normalized) ? normalized : null;\n}\n\nfunction driveId(value: string, label: string): string {\n const candidate = boundedText(value, label, GOOGLE_DRIVE_MAX_ID_CHARS);\n if (candidate === \"root\" || /^[A-Za-z0-9_-]+$/u.test(candidate)) return candidate;\n throw new Error(`${label} is invalid`);\n}\n\nfunction normalizedGooglePermissionId(value: string): string {\n return boundedText(value, \"googlePermissionId\", GOOGLE_DRIVE_MAX_ID_CHARS);\n}\n\nfunction nullableDriveId(value: string | null, label: string): string | null {\n return value === null ? null : driveId(value, label);\n}\n\nfunction pageToken(value: string | null, label: string): string | null {\n if (value === null) return null;\n return boundedText(value, label, GOOGLE_DRIVE_MAX_PAGE_TOKEN_CHARS);\n}\n\nfunction boundedText(value: string, label: string, maxChars: number): string {\n if (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > maxChars || /[\\u0000-\\u001f\\u007f]/u.test(trimmed)) {\n throw new Error(`${label} is invalid`);\n }\n return trimmed;\n}\n\nfunction nullableBoundedText(value: string | null, label: string, maxChars: number): string | null {\n return value === null ? null : boundedText(value, label, maxChars);\n}\n\nfunction nullableHttpsUrl(value: string | null, label: string): string | null {\n if (value === null) return null;\n const bounded = boundedText(value, label, 4096);\n const parsed = new URL(bounded);\n if (parsed.protocol !== \"https:\") throw new Error(`${label} must use https`);\n return parsed.toString();\n}\n\nfunction safePositiveInteger(value: number, label: string): number {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${label} must be a positive safe integer`);\n }\n return value;\n}\n\nfunction validatedTotals(totals: GoogleDriveInventoryTotals): void {\n for (const [key, value] of Object.entries(totals)) {\n if (key === \"knownBytes\") continue;\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n throw new Error(`checkpoint.totals.${key} is invalid`);\n }\n }\n if (!/^\\d+$/u.test(totals.knownBytes)) {\n throw new Error(\"checkpoint.totals.knownBytes is invalid\");\n }\n}\n\nfunction emptyTotals(): GoogleDriveInventoryTotals {\n return {\n itemCount: 0,\n folderCount: 1,\n plannedFileCount: 0,\n skippedItemCount: 0,\n exportFileCount: 0,\n downloadFileCount: 0,\n unknownSizeFileCount: 0,\n apiRequestCount: 0,\n knownBytes: \"0\",\n };\n}\n\nfunction cloneTotals(value: GoogleDriveInventoryTotals): GoogleDriveInventoryTotals {\n return { ...value };\n}\n\nfunction subtractTotals(\n value: GoogleDriveInventoryTotals,\n initial: GoogleDriveInventoryTotals,\n): GoogleDriveInventoryTotals {\n return {\n itemCount: value.itemCount - initial.itemCount,\n folderCount: value.folderCount - initial.folderCount,\n plannedFileCount: value.plannedFileCount - initial.plannedFileCount,\n skippedItemCount: value.skippedItemCount - initial.skippedItemCount,\n exportFileCount: value.exportFileCount - initial.exportFileCount,\n downloadFileCount: value.downloadFileCount - initial.downloadFileCount,\n unknownSizeFileCount: value.unknownSizeFileCount - initial.unknownSizeFileCount,\n apiRequestCount: value.apiRequestCount - initial.apiRequestCount,\n knownBytes: (BigInt(value.knownBytes) - BigInt(initial.knownBytes)).toString(),\n };\n}\n\nfunction cloneProviderItem(\n value: GoogleDriveInventoryProviderItem,\n): GoogleDriveInventoryProviderItem {\n return { ...value, parents: [...value.parents] };\n}\n\nfunction cloneScope(scope: ScopedKnowledgeScope): ScopedKnowledgeScope {\n return { ...scope };\n}\n\nfunction cloneCheckpoint(value: GoogleDriveInventoryCheckpoint): GoogleDriveInventoryCheckpoint {\n return {\n version: 2,\n googlePermissionId: value.googlePermissionId,\n externalTenantId: value.externalTenantId,\n sourceId: value.sourceId,\n sourceDriveId: value.sourceDriveId,\n scope: cloneScope(value.scope),\n pendingFolders: value.pendingFolders.map((frame) => ({\n ...frame,\n bufferedItems: frame.bufferedItems.map(cloneProviderItem),\n })),\n seenFolderIds: [...value.seenFolderIds],\n totals: cloneTotals(value.totals),\n };\n}\n\nfunction sameScope(\n left: ScopedKnowledgeScope | null | undefined,\n right: ScopedKnowledgeScope,\n): boolean {\n return (\n !!left &&\n typeof left === \"object\" &&\n left.kind === right.kind &&\n left.workspaceId === right.workspaceId &&\n left.subjectId === right.subjectId\n );\n}\n\nfunction assertCheckpointBytes(checkpoint: GoogleDriveInventoryCheckpoint): void {\n if (Buffer.byteLength(JSON.stringify(checkpoint), \"utf8\") > GOOGLE_DRIVE_MAX_CHECKPOINT_BYTES) {\n throw new Error(\"Google Drive inventory checkpoint exceeds the serialized byte limit\");\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/google-drive.ts"],"sourcesContent":["import type { ScopedKnowledgeScope } from \"@opengeni/contracts\";\nimport {\n connectorDestinationDocumentAuthority,\n resolveConnectorDocumentDestination,\n type ConnectorDocumentDestination,\n} from \"@opengeni/contracts/connector-destinations\";\nimport type { GoogleDriveSelectedSource } from \"@opengeni/contracts/google-drive\";\n\nexport const GOOGLE_DRIVE_PROVIDER_KEY = \"google-drive\" as const;\nexport const GOOGLE_DRIVE_FOLDER_MIME_TYPE = \"application/vnd.google-apps.folder\" as const;\nexport const GOOGLE_DRIVE_SHORTCUT_MIME_TYPE = \"application/vnd.google-apps.shortcut\" as const;\n\nconst GOOGLE_DRIVE_NATIVE_MIME_PREFIX = \"application/vnd.google-apps.\";\nconst GOOGLE_DRIVE_MAX_ID_CHARS = 256;\nconst GOOGLE_DRIVE_MAX_NAME_CHARS = 1024;\nconst GOOGLE_DRIVE_MAX_MIME_CHARS = 256;\nconst GOOGLE_DRIVE_MAX_PAGE_TOKEN_CHARS = 4096;\nconst GOOGLE_DRIVE_MAX_PAGE_ITEMS = 100;\nconst GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS = 2_000;\nconst GOOGLE_DRIVE_MAX_CHECKPOINT_BYTES = 2 * 1024 * 1024;\n\nconst GOOGLE_DRIVE_NATIVE_EXPORTS = new Map<string, { contentType: string; extension: string }>([\n [\n \"application/vnd.google-apps.document\",\n {\n contentType: \"application/pdf\",\n extension: \".pdf\",\n },\n ],\n [\n \"application/vnd.google-apps.spreadsheet\",\n {\n contentType: \"application/pdf\",\n extension: \".pdf\",\n },\n ],\n [\n \"application/vnd.google-apps.presentation\",\n {\n contentType: \"application/pdf\",\n extension: \".pdf\",\n },\n ],\n [\"application/vnd.google-apps.drawing\", { contentType: \"application/pdf\", extension: \".pdf\" }],\n]);\n\nconst DEPENDENCY_FREE_ORDINARY_CONTENT_TYPES = new Set([\n \"application/json\",\n \"application/pdf\",\n \"application/xml\",\n \"application/x-yaml\",\n \"application/yaml\",\n]);\n\nconst GENERIC_BINARY_CONTENT_TYPES = new Set([\"application/octet-stream\", \"binary/octet-stream\"]);\n\nconst DEPENDENCY_FREE_EXTENSION_CONTENT_TYPES = new Map([\n [\".csv\", \"text/csv\"],\n [\".htm\", \"text/html\"],\n [\".html\", \"text/html\"],\n [\".json\", \"application/json\"],\n [\".markdown\", \"text/markdown\"],\n [\".md\", \"text/markdown\"],\n [\".pdf\", \"application/pdf\"],\n [\".text\", \"text/plain\"],\n [\".tsv\", \"text/tab-separated-values\"],\n [\".txt\", \"text/plain\"],\n [\".xml\", \"application/xml\"],\n [\".yaml\", \"application/x-yaml\"],\n [\".yml\", \"application/x-yaml\"],\n]);\n\nexport type GoogleDriveKnowledgeSourceIdentity = {\n providerKey: typeof GOOGLE_DRIVE_PROVIDER_KEY;\n externalTenantId: string;\n externalSourceId: string;\n sourceKind: \"google-drive-my-drive\" | \"google-drive-shared-drive\" | \"google-drive-folder\";\n sourceUri: string;\n scope: ScopedKnowledgeScope;\n};\n\n/**\n * Normalized item metadata expected from a bounded Drive files.list adapter.\n * The adapter owns provider JSON validation; this planner owns traversal,\n * checkpointing, resource limits, stable identity, and transfer classification.\n */\nexport type GoogleDriveInventoryProviderItem = {\n id: string;\n name: string;\n mimeType: string;\n driveId: string | null;\n parents: string[];\n modifiedTime: string | null;\n createdTime: string | null;\n version: string | null;\n md5Checksum: string | null;\n size: string | null;\n webViewLink: string | null;\n trashed: boolean;\n};\n\nexport type GoogleDriveInventoryPage = {\n items: GoogleDriveInventoryProviderItem[];\n nextPageToken: string | null;\n incompleteSearch: boolean;\n};\n\nexport type GoogleDriveInventoryLimits = {\n /** Hard cumulative provider-item discovery limit for this checkpoint. */\n maxItems: number;\n /** Hard cumulative known-byte limit for ordinary file downloads. */\n maxKnownBytes: number;\n /** Hard cumulative Drive list request/cost limit for this checkpoint. */\n maxApiRequests: number;\n /** Wall-clock budget for one invocation; checkpoint counters remain cumulative. */\n maxElapsedMs: number;\n /** Per-file byte ceiling. Unknown/export sizes must be enforced again while streaming. */\n maxFileBytes: number;\n /** Cycle/graph explosion guard for traversed folders. */\n maxFolders: number;\n /** Requested Drive page size. */\n pageSize: number;\n};\n\nexport type GoogleDriveTransferSkipReason =\n | \"file_too_large\"\n | \"folder_limit\"\n | \"folder_loop\"\n | \"shortcut_unsupported\"\n | \"trashed\"\n | \"unsupported_file_type\"\n | \"unsupported_native_type\";\n\nexport type GoogleDriveTransferPlan =\n | { action: \"traverse\" }\n | {\n action: \"export\";\n contentType: string;\n filename: string;\n declaredBytes: null;\n }\n | {\n action: \"download\";\n contentType: string;\n filename: string;\n declaredBytes: string | null;\n }\n | { action: \"skip\"; reason: GoogleDriveTransferSkipReason };\n\nexport type GoogleDriveInventoryEntry = {\n externalObjectId: string;\n externalVersionId: string | null;\n sourceId: string;\n parentFolderId: string;\n driveId: string | null;\n title: string;\n mimeType: string;\n modifiedTime: string | null;\n createdTime: string | null;\n sourceUri: string;\n transfer: GoogleDriveTransferPlan;\n};\n\nexport type GoogleDriveInventoryIssue = {\n code: \"incomplete_search\" | \"invalid_page\" | \"provider_error\";\n folderId: string;\n providerCode: string | null;\n};\n\nexport type GoogleDriveInventoryStopReason =\n | \"api_request_limit\"\n | \"elapsed_time_limit\"\n | \"incomplete_search\"\n | \"item_limit\"\n | \"known_byte_limit\"\n | \"provider_error\";\n\nexport type GoogleDriveInventoryTotals = {\n itemCount: number;\n folderCount: number;\n plannedFileCount: number;\n skippedItemCount: number;\n exportFileCount: number;\n downloadFileCount: number;\n unknownSizeFileCount: number;\n apiRequestCount: number;\n knownBytes: string;\n};\n\ntype GoogleDriveInventoryFrame = {\n folderId: string;\n driveId: string | null;\n pageToken: string | null;\n loaded: boolean;\n bufferedItems: GoogleDriveInventoryProviderItem[];\n nextPageToken: string | null;\n};\n\nexport type GoogleDriveInventoryCheckpoint = {\n version: 2;\n googlePermissionId: string;\n externalTenantId: string;\n sourceId: string;\n sourceDriveId: string | null;\n scope: ScopedKnowledgeScope;\n pendingFolders: GoogleDriveInventoryFrame[];\n seenFolderIds: string[];\n totals: GoogleDriveInventoryTotals;\n};\n\nexport type GoogleDriveInventoryResult = {\n status: \"complete\" | \"paused\";\n stopReason: GoogleDriveInventoryStopReason | null;\n source: GoogleDriveKnowledgeSourceIdentity;\n entries: GoogleDriveInventoryEntry[];\n issues: GoogleDriveInventoryIssue[];\n totals: GoogleDriveInventoryTotals;\n run: GoogleDriveInventoryTotals & { elapsedMs: number };\n checkpoint: GoogleDriveInventoryCheckpoint | null;\n};\n\nexport type GoogleDriveListChildren = (input: {\n folderId: string;\n driveId: string | null;\n pageToken: string | null;\n pageSize: number;\n}) => Promise<GoogleDriveInventoryPage>;\n\nexport class GoogleDriveInventoryProviderError extends Error {\n constructor(readonly providerCode: string) {\n super(providerCode);\n this.name = \"GoogleDriveInventoryProviderError\";\n }\n}\n\nexport function googleDriveKnowledgeScope(\n destination: ConnectorDocumentDestination,\n): ScopedKnowledgeScope {\n const authority = connectorDestinationDocumentAuthority(destination);\n if (authority.authorityKind === \"organization\") {\n return { kind: \"organization\", workspaceId: null, subjectId: null };\n }\n if (authority.authorityKind === \"workspace\") {\n if (!authority.authorityWorkspaceId) {\n throw new Error(\"workspace connector destination is missing workspace authority\");\n }\n return {\n kind: \"workspace\",\n workspaceId: authority.authorityWorkspaceId,\n subjectId: null,\n };\n }\n if (!authority.authorityWorkspaceId || !authority.authoritySubjectId) {\n throw new Error(\"personal connector destination is missing immutable authority\");\n }\n return {\n kind: \"personal\",\n workspaceId: authority.authorityWorkspaceId,\n subjectId: authority.authoritySubjectId,\n };\n}\n\nexport function googleDriveKnowledgeSourceIdentity(input: {\n googlePermissionId: string;\n source: Pick<GoogleDriveSelectedSource, \"id\" | \"driveId\" | \"destination\" | \"targetScope\">;\n accountId?: string | undefined;\n workspaceId: string;\n connectionSubjectId?: string | null | undefined;\n /** @deprecated Used only to validate old callers while source destinations migrate. */\n initiatingSubjectId?: string | undefined;\n}): GoogleDriveKnowledgeSourceIdentity {\n const sourceId = driveId(input.source.id, \"source.id\");\n const externalTenantId = normalizedGooglePermissionId(input.googlePermissionId);\n const sourceDriveId = nullableDriveId(input.source.driveId, \"source.driveId\");\n const destination = resolveConnectorDocumentDestination(input.source.destination, {\n accountId: input.accountId ?? input.workspaceId,\n workspaceId: input.workspaceId,\n connectionSubjectId:\n input.connectionSubjectId !== undefined\n ? input.connectionSubjectId\n : (input.initiatingSubjectId ?? null),\n });\n return {\n providerKey: GOOGLE_DRIVE_PROVIDER_KEY,\n externalTenantId,\n externalSourceId: sourceId,\n sourceKind:\n sourceId === \"root\"\n ? \"google-drive-my-drive\"\n : sourceDriveId === sourceId\n ? \"google-drive-shared-drive\"\n : \"google-drive-folder\",\n sourceUri: googleDriveSourceUri(sourceId),\n scope: googleDriveKnowledgeScope(destination),\n };\n}\n\nexport function planGoogleDriveTransfer(\n item: GoogleDriveInventoryProviderItem,\n maxFileBytes: number,\n): GoogleDriveTransferPlan {\n const normalized = validatedProviderItem(item);\n const byteLimit = safePositiveInteger(maxFileBytes, \"maxFileBytes\");\n if (normalized.trashed) {\n return { action: \"skip\", reason: \"trashed\" };\n }\n if (normalized.mimeType === GOOGLE_DRIVE_FOLDER_MIME_TYPE) {\n return { action: \"traverse\" };\n }\n if (normalized.mimeType === GOOGLE_DRIVE_SHORTCUT_MIME_TYPE) {\n return { action: \"skip\", reason: \"shortcut_unsupported\" };\n }\n const nativeExport = GOOGLE_DRIVE_NATIVE_EXPORTS.get(normalized.mimeType);\n if (nativeExport) {\n return {\n action: \"export\",\n contentType: nativeExport.contentType,\n filename: exportedFilename(normalized.name, nativeExport.extension),\n declaredBytes: null,\n };\n }\n if (normalized.mimeType.startsWith(GOOGLE_DRIVE_NATIVE_MIME_PREFIX)) {\n return { action: \"skip\", reason: \"unsupported_native_type\" };\n }\n const declaredBytes = fileSize(normalized.size);\n if (declaredBytes !== null && declaredBytes > BigInt(byteLimit)) {\n return { action: \"skip\", reason: \"file_too_large\" };\n }\n const contentType = dependencyFreeOrdinaryContentType(normalized.name, normalized.mimeType);\n if (!contentType) {\n return { action: \"skip\", reason: \"unsupported_file_type\" };\n }\n return {\n action: \"download\",\n contentType,\n filename: safeFilename(normalized.name),\n declaredBytes: declaredBytes?.toString() ?? null,\n };\n}\n\nexport async function inventoryGoogleDriveSource(input: {\n googlePermissionId: string;\n source: GoogleDriveSelectedSource;\n accountId?: string | undefined;\n workspaceId: string;\n connectionSubjectId?: string | null | undefined;\n /** @deprecated Used only to validate old callers while source destinations migrate. */\n initiatingSubjectId?: string | undefined;\n limits: GoogleDriveInventoryLimits;\n listChildren: GoogleDriveListChildren;\n checkpoint?: GoogleDriveInventoryCheckpoint | null;\n now?: (() => number) | undefined;\n}): Promise<GoogleDriveInventoryResult> {\n const limits = validatedLimits(input.limits);\n const googlePermissionId = normalizedGooglePermissionId(input.googlePermissionId);\n const source = googleDriveKnowledgeSourceIdentity({\n googlePermissionId,\n source: input.source,\n ...(input.accountId ? { accountId: input.accountId } : {}),\n workspaceId: input.workspaceId,\n ...(input.connectionSubjectId !== undefined\n ? { connectionSubjectId: input.connectionSubjectId }\n : {}),\n ...(input.initiatingSubjectId ? { initiatingSubjectId: input.initiatingSubjectId } : {}),\n });\n const checkpointIdentity: GoogleDriveInventoryCheckpointIdentity = {\n googlePermissionId,\n externalTenantId: source.externalTenantId,\n sourceId: source.externalSourceId,\n sourceDriveId: nullableDriveId(input.source.driveId, \"source.driveId\"),\n scope: source.scope,\n };\n const now = input.now ?? Date.now;\n const startedAt = now();\n const checkpoint = input.checkpoint\n ? validatedCheckpoint(input.checkpoint, checkpointIdentity, limits)\n : initialCheckpoint(checkpointIdentity);\n const initialTotals = cloneTotals(checkpoint.totals);\n const entries: GoogleDriveInventoryEntry[] = [];\n const issues: GoogleDriveInventoryIssue[] = [];\n let stopReason: GoogleDriveInventoryStopReason | null = null;\n\n while (checkpoint.pendingFolders.length > 0) {\n if (now() - startedAt >= limits.maxElapsedMs) {\n stopReason = \"elapsed_time_limit\";\n break;\n }\n const frame = checkpoint.pendingFolders[0]!;\n if (frame.loaded && frame.bufferedItems.length === 0) {\n if (frame.nextPageToken) {\n frame.pageToken = frame.nextPageToken;\n frame.nextPageToken = null;\n frame.loaded = false;\n } else {\n checkpoint.pendingFolders.shift();\n }\n continue;\n }\n if (checkpoint.totals.itemCount >= limits.maxItems) {\n stopReason = \"item_limit\";\n break;\n }\n\n if (!frame.loaded) {\n if (checkpoint.totals.apiRequestCount >= limits.maxApiRequests) {\n stopReason = \"api_request_limit\";\n break;\n }\n const remainingItems = limits.maxItems - checkpoint.totals.itemCount;\n const requestedPageSize = Math.min(limits.pageSize, remainingItems);\n let page: GoogleDriveInventoryPage;\n try {\n page = await input.listChildren({\n folderId: frame.folderId,\n driveId: frame.driveId,\n pageToken: frame.pageToken,\n pageSize: requestedPageSize,\n });\n } catch (error) {\n checkpoint.totals.apiRequestCount += 1;\n issues.push({\n code: \"provider_error\",\n folderId: frame.folderId,\n providerCode: providerErrorCode(error),\n });\n stopReason = \"provider_error\";\n break;\n }\n checkpoint.totals.apiRequestCount += 1;\n if (!validPage(page, requestedPageSize)) {\n issues.push({ code: \"invalid_page\", folderId: frame.folderId, providerCode: null });\n stopReason = \"provider_error\";\n break;\n }\n if (page.incompleteSearch) {\n issues.push({ code: \"incomplete_search\", folderId: frame.folderId, providerCode: null });\n stopReason = \"incomplete_search\";\n break;\n }\n frame.loaded = true;\n frame.bufferedItems = page.items.map(validatedProviderItem);\n frame.nextPageToken = page.nextPageToken;\n if (now() - startedAt >= limits.maxElapsedMs) {\n stopReason = \"elapsed_time_limit\";\n break;\n }\n }\n\n if (frame.bufferedItems.length === 0) {\n if (frame.nextPageToken) {\n frame.pageToken = frame.nextPageToken;\n frame.nextPageToken = null;\n frame.loaded = false;\n } else {\n checkpoint.pendingFolders.shift();\n }\n continue;\n }\n\n const item = validatedProviderItem(frame.bufferedItems[0]!);\n let transfer = planGoogleDriveTransfer(item, limits.maxFileBytes);\n if (transfer.action === \"download\" && transfer.declaredBytes !== null) {\n const nextKnownBytes = BigInt(checkpoint.totals.knownBytes) + BigInt(transfer.declaredBytes);\n if (nextKnownBytes > BigInt(limits.maxKnownBytes)) {\n stopReason = \"known_byte_limit\";\n break;\n }\n }\n\n frame.bufferedItems.shift();\n checkpoint.totals.itemCount += 1;\n const effectiveDriveId = item.driveId ?? frame.driveId;\n if (transfer.action === \"traverse\") {\n if (checkpoint.seenFolderIds.includes(item.id)) {\n transfer = { action: \"skip\", reason: \"folder_loop\" };\n } else if (checkpoint.seenFolderIds.length >= limits.maxFolders) {\n transfer = { action: \"skip\", reason: \"folder_limit\" };\n } else {\n checkpoint.seenFolderIds.push(item.id);\n checkpoint.totals.folderCount += 1;\n checkpoint.pendingFolders.push({\n folderId: item.id,\n driveId: effectiveDriveId,\n pageToken: null,\n loaded: false,\n bufferedItems: [],\n nextPageToken: null,\n });\n }\n }\n\n if (transfer.action === \"skip\") {\n checkpoint.totals.skippedItemCount += 1;\n } else if (transfer.action === \"download\") {\n checkpoint.totals.plannedFileCount += 1;\n checkpoint.totals.downloadFileCount += 1;\n if (transfer.declaredBytes === null) {\n checkpoint.totals.unknownSizeFileCount += 1;\n } else {\n checkpoint.totals.knownBytes = (\n BigInt(checkpoint.totals.knownBytes) + BigInt(transfer.declaredBytes)\n ).toString();\n }\n } else if (transfer.action === \"export\") {\n checkpoint.totals.plannedFileCount += 1;\n checkpoint.totals.exportFileCount += 1;\n checkpoint.totals.unknownSizeFileCount += 1;\n }\n\n entries.push({\n externalObjectId: item.id,\n externalVersionId: item.version ?? item.md5Checksum ?? item.modifiedTime,\n sourceId: source.externalSourceId,\n parentFolderId: frame.folderId,\n driveId: effectiveDriveId,\n title: item.name,\n mimeType: item.mimeType,\n modifiedTime: item.modifiedTime,\n createdTime: item.createdTime,\n sourceUri: item.webViewLink ?? googleDriveFileUri(item.id),\n transfer,\n });\n }\n\n const elapsedMs = Math.max(0, now() - startedAt);\n const complete = checkpoint.pendingFolders.length === 0;\n const outputCheckpoint = complete ? null : cloneCheckpoint(checkpoint);\n if (outputCheckpoint) assertCheckpointBytes(outputCheckpoint);\n return {\n status: complete ? \"complete\" : \"paused\",\n stopReason: complete ? null : stopReason,\n source,\n entries,\n issues,\n totals: cloneTotals(checkpoint.totals),\n run: {\n ...subtractTotals(checkpoint.totals, initialTotals),\n elapsedMs,\n },\n checkpoint: outputCheckpoint,\n };\n}\n\ntype GoogleDriveInventoryCheckpointIdentity = Pick<\n GoogleDriveInventoryCheckpoint,\n \"googlePermissionId\" | \"externalTenantId\" | \"sourceId\" | \"sourceDriveId\" | \"scope\"\n>;\n\nfunction initialCheckpoint(\n identity: GoogleDriveInventoryCheckpointIdentity,\n): GoogleDriveInventoryCheckpoint {\n return {\n version: 2,\n googlePermissionId: identity.googlePermissionId,\n externalTenantId: identity.externalTenantId,\n sourceId: identity.sourceId,\n sourceDriveId: identity.sourceDriveId,\n scope: cloneScope(identity.scope),\n pendingFolders: [\n {\n folderId: identity.sourceId,\n driveId: identity.sourceDriveId,\n pageToken: null,\n loaded: false,\n bufferedItems: [],\n nextPageToken: null,\n },\n ],\n seenFolderIds: [identity.sourceId],\n totals: emptyTotals(),\n };\n}\n\nfunction validatedCheckpoint(\n value: GoogleDriveInventoryCheckpoint,\n identity: GoogleDriveInventoryCheckpointIdentity,\n limits: GoogleDriveInventoryLimits,\n): GoogleDriveInventoryCheckpoint {\n if (!value || typeof value !== \"object\" || value.version !== 2) {\n throw new Error(\"unsupported Google Drive inventory checkpoint\");\n }\n if (\n value.googlePermissionId !== identity.googlePermissionId ||\n value.externalTenantId !== identity.externalTenantId ||\n value.sourceId !== identity.sourceId ||\n value.sourceDriveId !== identity.sourceDriveId ||\n !sameScope(value.scope, identity.scope)\n ) {\n throw new Error(\"Google Drive inventory checkpoint does not match the selected source\");\n }\n const checkpoint = cloneCheckpoint(value);\n if (checkpoint.pendingFolders.length === 0) {\n throw new Error(\"Google Drive inventory checkpoint is already complete\");\n }\n if (\n checkpoint.pendingFolders.length > GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS ||\n checkpoint.seenFolderIds.length > GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS ||\n checkpoint.seenFolderIds.length > limits.maxFolders\n ) {\n throw new Error(\"Google Drive inventory checkpoint exceeds the folder limit\");\n }\n if (!checkpoint.seenFolderIds.includes(identity.sourceId)) {\n throw new Error(\"Google Drive inventory checkpoint lost its source boundary\");\n }\n if (new Set(checkpoint.seenFolderIds).size !== checkpoint.seenFolderIds.length) {\n throw new Error(\"Google Drive inventory checkpoint contains duplicate folder identity\");\n }\n for (const folderId of checkpoint.seenFolderIds) driveId(folderId, \"checkpoint.folderId\");\n const pendingFolderIds = new Set<string>();\n for (const frame of checkpoint.pendingFolders) {\n driveId(frame.folderId, \"checkpoint.pending.folderId\");\n if (\n !checkpoint.seenFolderIds.includes(frame.folderId) ||\n pendingFolderIds.has(frame.folderId)\n ) {\n throw new Error(\"Google Drive inventory checkpoint contains an invalid pending folder\");\n }\n pendingFolderIds.add(frame.folderId);\n nullableDriveId(frame.driveId, \"checkpoint.pending.driveId\");\n pageToken(frame.pageToken, \"checkpoint.pending.pageToken\");\n pageToken(frame.nextPageToken, \"checkpoint.pending.nextPageToken\");\n if (\n typeof frame.loaded !== \"boolean\" ||\n frame.bufferedItems.length > GOOGLE_DRIVE_MAX_PAGE_ITEMS\n ) {\n throw new Error(\"Google Drive inventory checkpoint contains an invalid page frame\");\n }\n if (!frame.loaded && (frame.bufferedItems.length > 0 || frame.nextPageToken !== null)) {\n throw new Error(\"Google Drive inventory checkpoint contains an uncommitted page frame\");\n }\n frame.bufferedItems = frame.bufferedItems.map(validatedProviderItem);\n }\n validatedTotals(checkpoint.totals);\n if (\n checkpoint.totals.folderCount !== checkpoint.seenFolderIds.length ||\n checkpoint.totals.plannedFileCount !==\n checkpoint.totals.exportFileCount + checkpoint.totals.downloadFileCount ||\n checkpoint.totals.unknownSizeFileCount > checkpoint.totals.plannedFileCount ||\n checkpoint.totals.itemCount !==\n checkpoint.totals.skippedItemCount +\n checkpoint.totals.plannedFileCount +\n checkpoint.totals.folderCount -\n 1\n ) {\n throw new Error(\"Google Drive inventory checkpoint totals are inconsistent\");\n }\n if (\n checkpoint.totals.itemCount > limits.maxItems ||\n checkpoint.totals.apiRequestCount > limits.maxApiRequests ||\n BigInt(checkpoint.totals.knownBytes) > BigInt(limits.maxKnownBytes)\n ) {\n throw new Error(\"Google Drive inventory checkpoint exceeds the supplied limits\");\n }\n assertCheckpointBytes(checkpoint);\n return checkpoint;\n}\n\nfunction validatedLimits(value: GoogleDriveInventoryLimits): GoogleDriveInventoryLimits {\n const limits = {\n maxItems: safePositiveInteger(value.maxItems, \"limits.maxItems\"),\n maxKnownBytes: safePositiveInteger(value.maxKnownBytes, \"limits.maxKnownBytes\"),\n maxApiRequests: safePositiveInteger(value.maxApiRequests, \"limits.maxApiRequests\"),\n maxElapsedMs: safePositiveInteger(value.maxElapsedMs, \"limits.maxElapsedMs\"),\n maxFileBytes: safePositiveInteger(value.maxFileBytes, \"limits.maxFileBytes\"),\n maxFolders: safePositiveInteger(value.maxFolders, \"limits.maxFolders\"),\n pageSize: safePositiveInteger(value.pageSize, \"limits.pageSize\"),\n };\n if (limits.pageSize > GOOGLE_DRIVE_MAX_PAGE_ITEMS) {\n throw new Error(`limits.pageSize must be <= ${GOOGLE_DRIVE_MAX_PAGE_ITEMS}`);\n }\n if (limits.maxFolders > GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS) {\n throw new Error(`limits.maxFolders must be <= ${GOOGLE_DRIVE_MAX_CHECKPOINT_FOLDERS}`);\n }\n return limits;\n}\n\nfunction validPage(value: GoogleDriveInventoryPage, expectedMaxItems: number): boolean {\n if (\n !value ||\n !Array.isArray(value.items) ||\n value.items.length > expectedMaxItems ||\n value.items.length > GOOGLE_DRIVE_MAX_PAGE_ITEMS\n ) {\n return false;\n }\n try {\n pageToken(value.nextPageToken, \"page.nextPageToken\");\n value.items.forEach(validatedProviderItem);\n return typeof value.incompleteSearch === \"boolean\";\n } catch {\n return false;\n }\n}\n\nfunction validatedProviderItem(\n item: GoogleDriveInventoryProviderItem,\n): GoogleDriveInventoryProviderItem {\n const id = driveId(item.id, \"item.id\");\n const name = boundedText(item.name, \"item.name\", GOOGLE_DRIVE_MAX_NAME_CHARS);\n const mimeType = boundedText(item.mimeType, \"item.mimeType\", GOOGLE_DRIVE_MAX_MIME_CHARS);\n const parents = Array.isArray(item.parents)\n ? item.parents.map((parent) => driveId(parent, \"item.parent\"))\n : [];\n if (parents.length > 100) throw new Error(\"item.parents exceeds the supported bound\");\n return {\n id,\n name,\n mimeType,\n driveId: nullableDriveId(item.driveId, \"item.driveId\"),\n parents,\n modifiedTime: nullableBoundedText(item.modifiedTime, \"item.modifiedTime\", 128),\n createdTime: nullableBoundedText(item.createdTime, \"item.createdTime\", 128),\n version: nullableBoundedText(item.version, \"item.version\", 256),\n md5Checksum: nullableBoundedText(item.md5Checksum, \"item.md5Checksum\", 128),\n size: fileSize(item.size)?.toString() ?? null,\n webViewLink: nullableHttpsUrl(item.webViewLink, \"item.webViewLink\"),\n trashed: item.trashed === true,\n };\n}\n\nfunction dependencyFreeOrdinaryContentType(name: string, mimeType: string): string | null {\n const normalizedMime = mimeType.trim().toLowerCase();\n if (normalizedMime.startsWith(\"text/\")) return normalizedMime;\n if (DEPENDENCY_FREE_ORDINARY_CONTENT_TYPES.has(normalizedMime)) return normalizedMime;\n if (!GENERIC_BINARY_CONTENT_TYPES.has(normalizedMime)) return null;\n const lowerName = name.toLowerCase();\n for (const [extension, contentType] of DEPENDENCY_FREE_EXTENSION_CONTENT_TYPES) {\n if (lowerName.endsWith(extension)) return contentType;\n }\n return null;\n}\n\nfunction exportedFilename(name: string, extension: string): string {\n const filename = safeFilename(name);\n return filename.toLowerCase().endsWith(extension) ? filename : `${filename}${extension}`;\n}\n\nfunction safeFilename(value: string): string {\n const cleaned = value\n .normalize(\"NFKC\")\n .replace(/[\\u0000-\\u001f\\u007f/\\\\]/gu, \" \")\n .replace(/\\s+/gu, \" \")\n .trim()\n .slice(0, 512);\n return cleaned || \"untitled\";\n}\n\nfunction googleDriveSourceUri(id: string): string {\n return id === \"root\"\n ? \"https://drive.google.com/drive/my-drive\"\n : `https://drive.google.com/drive/folders/${encodeURIComponent(id)}`;\n}\n\nfunction googleDriveFileUri(id: string): string {\n return `https://drive.google.com/open?id=${encodeURIComponent(id)}`;\n}\n\nfunction fileSize(value: string | null): bigint | null {\n if (value === null) return null;\n if (!/^\\d{1,40}$/u.test(value)) throw new Error(\"item.size is invalid\");\n return BigInt(value);\n}\n\nfunction providerErrorCode(error: unknown): string | null {\n if (!(error instanceof GoogleDriveInventoryProviderError)) return null;\n const normalized = error.providerCode.trim().toLowerCase();\n return /^[a-z0-9](?:[a-z0-9._-]{0,126}[a-z0-9])?$/u.test(normalized) ? normalized : null;\n}\n\nfunction driveId(value: string, label: string): string {\n const candidate = boundedText(value, label, GOOGLE_DRIVE_MAX_ID_CHARS);\n if (candidate === \"root\" || /^[A-Za-z0-9_-]+$/u.test(candidate)) return candidate;\n throw new Error(`${label} is invalid`);\n}\n\nfunction normalizedGooglePermissionId(value: string): string {\n return boundedText(value, \"googlePermissionId\", GOOGLE_DRIVE_MAX_ID_CHARS);\n}\n\nfunction nullableDriveId(value: string | null, label: string): string | null {\n return value === null ? null : driveId(value, label);\n}\n\nfunction pageToken(value: string | null, label: string): string | null {\n if (value === null) return null;\n return boundedText(value, label, GOOGLE_DRIVE_MAX_PAGE_TOKEN_CHARS);\n}\n\nfunction boundedText(value: string, label: string, maxChars: number): string {\n if (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n const trimmed = value.trim();\n if (!trimmed || trimmed.length > maxChars || /[\\u0000-\\u001f\\u007f]/u.test(trimmed)) {\n throw new Error(`${label} is invalid`);\n }\n return trimmed;\n}\n\nfunction nullableBoundedText(value: string | null, label: string, maxChars: number): string | null {\n return value === null ? null : boundedText(value, label, maxChars);\n}\n\nfunction nullableHttpsUrl(value: string | null, label: string): string | null {\n if (value === null) return null;\n const bounded = boundedText(value, label, 4096);\n const parsed = new URL(bounded);\n if (parsed.protocol !== \"https:\") throw new Error(`${label} must use https`);\n return parsed.toString();\n}\n\nfunction safePositiveInteger(value: number, label: string): number {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`${label} must be a positive safe integer`);\n }\n return value;\n}\n\nfunction validatedTotals(totals: GoogleDriveInventoryTotals): void {\n for (const [key, value] of Object.entries(totals)) {\n if (key === \"knownBytes\") continue;\n if (typeof value !== \"number\" || !Number.isSafeInteger(value) || value < 0) {\n throw new Error(`checkpoint.totals.${key} is invalid`);\n }\n }\n if (!/^\\d+$/u.test(totals.knownBytes)) {\n throw new Error(\"checkpoint.totals.knownBytes is invalid\");\n }\n}\n\nfunction emptyTotals(): GoogleDriveInventoryTotals {\n return {\n itemCount: 0,\n folderCount: 1,\n plannedFileCount: 0,\n skippedItemCount: 0,\n exportFileCount: 0,\n downloadFileCount: 0,\n unknownSizeFileCount: 0,\n apiRequestCount: 0,\n knownBytes: \"0\",\n };\n}\n\nfunction cloneTotals(value: GoogleDriveInventoryTotals): GoogleDriveInventoryTotals {\n return { ...value };\n}\n\nfunction subtractTotals(\n value: GoogleDriveInventoryTotals,\n initial: GoogleDriveInventoryTotals,\n): GoogleDriveInventoryTotals {\n return {\n itemCount: value.itemCount - initial.itemCount,\n folderCount: value.folderCount - initial.folderCount,\n plannedFileCount: value.plannedFileCount - initial.plannedFileCount,\n skippedItemCount: value.skippedItemCount - initial.skippedItemCount,\n exportFileCount: value.exportFileCount - initial.exportFileCount,\n downloadFileCount: value.downloadFileCount - initial.downloadFileCount,\n unknownSizeFileCount: value.unknownSizeFileCount - initial.unknownSizeFileCount,\n apiRequestCount: value.apiRequestCount - initial.apiRequestCount,\n knownBytes: (BigInt(value.knownBytes) - BigInt(initial.knownBytes)).toString(),\n };\n}\n\nfunction cloneProviderItem(\n value: GoogleDriveInventoryProviderItem,\n): GoogleDriveInventoryProviderItem {\n return { ...value, parents: [...value.parents] };\n}\n\nfunction cloneScope(scope: ScopedKnowledgeScope): ScopedKnowledgeScope {\n return { ...scope };\n}\n\nfunction cloneCheckpoint(value: GoogleDriveInventoryCheckpoint): GoogleDriveInventoryCheckpoint {\n return {\n version: 2,\n googlePermissionId: value.googlePermissionId,\n externalTenantId: value.externalTenantId,\n sourceId: value.sourceId,\n sourceDriveId: value.sourceDriveId,\n scope: cloneScope(value.scope),\n pendingFolders: value.pendingFolders.map((frame) => ({\n ...frame,\n bufferedItems: frame.bufferedItems.map(cloneProviderItem),\n })),\n seenFolderIds: [...value.seenFolderIds],\n totals: cloneTotals(value.totals),\n };\n}\n\nfunction sameScope(\n left: ScopedKnowledgeScope | null | undefined,\n right: ScopedKnowledgeScope,\n): boolean {\n return (\n !!left &&\n typeof left === \"object\" &&\n left.kind === right.kind &&\n left.workspaceId === right.workspaceId &&\n left.subjectId === right.subjectId\n );\n}\n\nfunction assertCheckpointBytes(checkpoint: GoogleDriveInventoryCheckpoint): void {\n if (Buffer.byteLength(JSON.stringify(checkpoint), \"utf8\") > GOOGLE_DRIVE_MAX_CHECKPOINT_BYTES) {\n throw new Error(\"Google Drive inventory checkpoint exceeds the serialized byte limit\");\n }\n}\n"],"mappings":";AACA;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AAGA,IAAM,4BAA4B;AAClC,IAAM,gCAAgC;AACtC,IAAM,kCAAkC;AAE/C,IAAM,kCAAkC;AACxC,IAAM,4BAA4B;AAClC,IAAM,8BAA8B;AACpC,IAAM,8BAA8B;AACpC,IAAM,oCAAoC;AAC1C,IAAM,8BAA8B;AACpC,IAAM,sCAAsC;AAC5C,IAAM,oCAAoC,IAAI,OAAO;AAErD,IAAM,8BAA8B,oBAAI,IAAwD;AAAA,EAC9F;AAAA,IACE;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA;AAAA,IACE;AAAA,IACA;AAAA,MACE,aAAa;AAAA,MACb,WAAW;AAAA,IACb;AAAA,EACF;AAAA,EACA,CAAC,uCAAuC,EAAE,aAAa,mBAAmB,WAAW,OAAO,CAAC;AAC/F,CAAC;AAED,IAAM,yCAAyC,oBAAI,IAAI;AAAA,EACrD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,+BAA+B,oBAAI,IAAI,CAAC,4BAA4B,qBAAqB,CAAC;AAEhG,IAAM,0CAA0C,oBAAI,IAAI;AAAA,EACtD,CAAC,QAAQ,UAAU;AAAA,EACnB,CAAC,QAAQ,WAAW;AAAA,EACpB,CAAC,SAAS,WAAW;AAAA,EACrB,CAAC,SAAS,kBAAkB;AAAA,EAC5B,CAAC,aAAa,eAAe;AAAA,EAC7B,CAAC,OAAO,eAAe;AAAA,EACvB,CAAC,QAAQ,iBAAiB;AAAA,EAC1B,CAAC,SAAS,YAAY;AAAA,EACtB,CAAC,QAAQ,2BAA2B;AAAA,EACpC,CAAC,QAAQ,YAAY;AAAA,EACrB,CAAC,QAAQ,iBAAiB;AAAA,EAC1B,CAAC,SAAS,oBAAoB;AAAA,EAC9B,CAAC,QAAQ,oBAAoB;AAC/B,CAAC;AA8JM,IAAM,oCAAN,cAAgD,MAAM;AAAA,EAC3D,YAAqB,cAAsB;AACzC,UAAM,YAAY;AADC;AAEnB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,0BACd,aACsB;AACtB,QAAM,YAAY,sCAAsC,WAAW;AACnE,MAAI,UAAU,kBAAkB,gBAAgB;AAC9C,WAAO,EAAE,MAAM,gBAAgB,aAAa,MAAM,WAAW,KAAK;AAAA,EACpE;AACA,MAAI,UAAU,kBAAkB,aAAa;AAC3C,QAAI,CAAC,UAAU,sBAAsB;AACnC,YAAM,IAAI,MAAM,gEAAgE;AAAA,IAClF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa,UAAU;AAAA,MACvB,WAAW;AAAA,IACb;AAAA,EACF;AACA,MAAI,CAAC,UAAU,wBAAwB,CAAC,UAAU,oBAAoB;AACpE,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,aAAa,UAAU;AAAA,IACvB,WAAW,UAAU;AAAA,EACvB;AACF;AAEO,SAAS,mCAAmC,OAQZ;AACrC,QAAM,WAAW,QAAQ,MAAM,OAAO,IAAI,WAAW;AACrD,QAAM,mBAAmB,6BAA6B,MAAM,kBAAkB;AAC9E,QAAM,gBAAgB,gBAAgB,MAAM,OAAO,SAAS,gBAAgB;AAC5E,QAAM,cAAc,oCAAoC,MAAM,OAAO,aAAa;AAAA,IAChF,WAAW,MAAM,aAAa,MAAM;AAAA,IACpC,aAAa,MAAM;AAAA,IACnB,qBACE,MAAM,wBAAwB,SAC1B,MAAM,sBACL,MAAM,uBAAuB;AAAA,EACtC,CAAC;AACD,SAAO;AAAA,IACL,aAAa;AAAA,IACb;AAAA,IACA,kBAAkB;AAAA,IAClB,YACE,aAAa,SACT,0BACA,kBAAkB,WAChB,8BACA;AAAA,IACR,WAAW,qBAAqB,QAAQ;AAAA,IACxC,OAAO,0BAA0B,WAAW;AAAA,EAC9C;AACF;AAEO,SAAS,wBACd,MACA,cACyB;AACzB,QAAM,aAAa,sBAAsB,IAAI;AAC7C,QAAM,YAAY,oBAAoB,cAAc,cAAc;AAClE,MAAI,WAAW,SAAS;AACtB,WAAO,EAAE,QAAQ,QAAQ,QAAQ,UAAU;AAAA,EAC7C;AACA,MAAI,WAAW,aAAa,+BAA+B;AACzD,WAAO,EAAE,QAAQ,WAAW;AAAA,EAC9B;AACA,MAAI,WAAW,aAAa,iCAAiC;AAC3D,WAAO,EAAE,QAAQ,QAAQ,QAAQ,uBAAuB;AAAA,EAC1D;AACA,QAAM,eAAe,4BAA4B,IAAI,WAAW,QAAQ;AACxE,MAAI,cAAc;AAChB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa,aAAa;AAAA,MAC1B,UAAU,iBAAiB,WAAW,MAAM,aAAa,SAAS;AAAA,MAClE,eAAe;AAAA,IACjB;AAAA,EACF;AACA,MAAI,WAAW,SAAS,WAAW,+BAA+B,GAAG;AACnE,WAAO,EAAE,QAAQ,QAAQ,QAAQ,0BAA0B;AAAA,EAC7D;AACA,QAAM,gBAAgB,SAAS,WAAW,IAAI;AAC9C,MAAI,kBAAkB,QAAQ,gBAAgB,OAAO,SAAS,GAAG;AAC/D,WAAO,EAAE,QAAQ,QAAQ,QAAQ,iBAAiB;AAAA,EACpD;AACA,QAAM,cAAc,kCAAkC,WAAW,MAAM,WAAW,QAAQ;AAC1F,MAAI,CAAC,aAAa;AAChB,WAAO,EAAE,QAAQ,QAAQ,QAAQ,wBAAwB;AAAA,EAC3D;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR;AAAA,IACA,UAAU,aAAa,WAAW,IAAI;AAAA,IACtC,eAAe,eAAe,SAAS,KAAK;AAAA,EAC9C;AACF;AAEA,eAAsB,2BAA2B,OAYT;AACtC,QAAM,SAAS,gBAAgB,MAAM,MAAM;AAC3C,QAAM,qBAAqB,6BAA6B,MAAM,kBAAkB;AAChF,QAAM,SAAS,mCAAmC;AAAA,IAChD;AAAA,IACA,QAAQ,MAAM;AAAA,IACd,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,IACxD,aAAa,MAAM;AAAA,IACnB,GAAI,MAAM,wBAAwB,SAC9B,EAAE,qBAAqB,MAAM,oBAAoB,IACjD,CAAC;AAAA,IACL,GAAI,MAAM,sBAAsB,EAAE,qBAAqB,MAAM,oBAAoB,IAAI,CAAC;AAAA,EACxF,CAAC;AACD,QAAM,qBAA6D;AAAA,IACjE;AAAA,IACA,kBAAkB,OAAO;AAAA,IACzB,UAAU,OAAO;AAAA,IACjB,eAAe,gBAAgB,MAAM,OAAO,SAAS,gBAAgB;AAAA,IACrE,OAAO,OAAO;AAAA,EAChB;AACA,QAAM,MAAM,MAAM,OAAO,KAAK;AAC9B,QAAM,YAAY,IAAI;AACtB,QAAM,aAAa,MAAM,aACrB,oBAAoB,MAAM,YAAY,oBAAoB,MAAM,IAChE,kBAAkB,kBAAkB;AACxC,QAAM,gBAAgB,YAAY,WAAW,MAAM;AACnD,QAAM,UAAuC,CAAC;AAC9C,QAAM,SAAsC,CAAC;AAC7C,MAAI,aAAoD;AAExD,SAAO,WAAW,eAAe,SAAS,GAAG;AAC3C,QAAI,IAAI,IAAI,aAAa,OAAO,cAAc;AAC5C,mBAAa;AACb;AAAA,IACF;AACA,UAAM,QAAQ,WAAW,eAAe,CAAC;AACzC,QAAI,MAAM,UAAU,MAAM,cAAc,WAAW,GAAG;AACpD,UAAI,MAAM,eAAe;AACvB,cAAM,YAAY,MAAM;AACxB,cAAM,gBAAgB;AACtB,cAAM,SAAS;AAAA,MACjB,OAAO;AACL,mBAAW,eAAe,MAAM;AAAA,MAClC;AACA;AAAA,IACF;AACA,QAAI,WAAW,OAAO,aAAa,OAAO,UAAU;AAClD,mBAAa;AACb;AAAA,IACF;AAEA,QAAI,CAAC,MAAM,QAAQ;AACjB,UAAI,WAAW,OAAO,mBAAmB,OAAO,gBAAgB;AAC9D,qBAAa;AACb;AAAA,MACF;AACA,YAAM,iBAAiB,OAAO,WAAW,WAAW,OAAO;AAC3D,YAAM,oBAAoB,KAAK,IAAI,OAAO,UAAU,cAAc;AAClE,UAAI;AACJ,UAAI;AACF,eAAO,MAAM,MAAM,aAAa;AAAA,UAC9B,UAAU,MAAM;AAAA,UAChB,SAAS,MAAM;AAAA,UACf,WAAW,MAAM;AAAA,UACjB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH,SAAS,OAAO;AACd,mBAAW,OAAO,mBAAmB;AACrC,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,UAAU,MAAM;AAAA,UAChB,cAAc,kBAAkB,KAAK;AAAA,QACvC,CAAC;AACD,qBAAa;AACb;AAAA,MACF;AACA,iBAAW,OAAO,mBAAmB;AACrC,UAAI,CAAC,UAAU,MAAM,iBAAiB,GAAG;AACvC,eAAO,KAAK,EAAE,MAAM,gBAAgB,UAAU,MAAM,UAAU,cAAc,KAAK,CAAC;AAClF,qBAAa;AACb;AAAA,MACF;AACA,UAAI,KAAK,kBAAkB;AACzB,eAAO,KAAK,EAAE,MAAM,qBAAqB,UAAU,MAAM,UAAU,cAAc,KAAK,CAAC;AACvF,qBAAa;AACb;AAAA,MACF;AACA,YAAM,SAAS;AACf,YAAM,gBAAgB,KAAK,MAAM,IAAI,qBAAqB;AAC1D,YAAM,gBAAgB,KAAK;AAC3B,UAAI,IAAI,IAAI,aAAa,OAAO,cAAc;AAC5C,qBAAa;AACb;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,cAAc,WAAW,GAAG;AACpC,UAAI,MAAM,eAAe;AACvB,cAAM,YAAY,MAAM;AACxB,cAAM,gBAAgB;AACtB,cAAM,SAAS;AAAA,MACjB,OAAO;AACL,mBAAW,eAAe,MAAM;AAAA,MAClC;AACA;AAAA,IACF;AAEA,UAAM,OAAO,sBAAsB,MAAM,cAAc,CAAC,CAAE;AAC1D,QAAI,WAAW,wBAAwB,MAAM,OAAO,YAAY;AAChE,QAAI,SAAS,WAAW,cAAc,SAAS,kBAAkB,MAAM;AACrE,YAAM,iBAAiB,OAAO,WAAW,OAAO,UAAU,IAAI,OAAO,SAAS,aAAa;AAC3F,UAAI,iBAAiB,OAAO,OAAO,aAAa,GAAG;AACjD,qBAAa;AACb;AAAA,MACF;AAAA,IACF;AAEA,UAAM,cAAc,MAAM;AAC1B,eAAW,OAAO,aAAa;AAC/B,UAAM,mBAAmB,KAAK,WAAW,MAAM;AAC/C,QAAI,SAAS,WAAW,YAAY;AAClC,UAAI,WAAW,cAAc,SAAS,KAAK,EAAE,GAAG;AAC9C,mBAAW,EAAE,QAAQ,QAAQ,QAAQ,cAAc;AAAA,MACrD,WAAW,WAAW,cAAc,UAAU,OAAO,YAAY;AAC/D,mBAAW,EAAE,QAAQ,QAAQ,QAAQ,eAAe;AAAA,MACtD,OAAO;AACL,mBAAW,cAAc,KAAK,KAAK,EAAE;AACrC,mBAAW,OAAO,eAAe;AACjC,mBAAW,eAAe,KAAK;AAAA,UAC7B,UAAU,KAAK;AAAA,UACf,SAAS;AAAA,UACT,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,eAAe,CAAC;AAAA,UAChB,eAAe;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,SAAS,WAAW,QAAQ;AAC9B,iBAAW,OAAO,oBAAoB;AAAA,IACxC,WAAW,SAAS,WAAW,YAAY;AACzC,iBAAW,OAAO,oBAAoB;AACtC,iBAAW,OAAO,qBAAqB;AACvC,UAAI,SAAS,kBAAkB,MAAM;AACnC,mBAAW,OAAO,wBAAwB;AAAA,MAC5C,OAAO;AACL,mBAAW,OAAO,cAChB,OAAO,WAAW,OAAO,UAAU,IAAI,OAAO,SAAS,aAAa,GACpE,SAAS;AAAA,MACb;AAAA,IACF,WAAW,SAAS,WAAW,UAAU;AACvC,iBAAW,OAAO,oBAAoB;AACtC,iBAAW,OAAO,mBAAmB;AACrC,iBAAW,OAAO,wBAAwB;AAAA,IAC5C;AAEA,YAAQ,KAAK;AAAA,MACX,kBAAkB,KAAK;AAAA,MACvB,mBAAmB,KAAK,WAAW,KAAK,eAAe,KAAK;AAAA,MAC5D,UAAU,OAAO;AAAA,MACjB,gBAAgB,MAAM;AAAA,MACtB,SAAS;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK,eAAe,mBAAmB,KAAK,EAAE;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,YAAY,KAAK,IAAI,GAAG,IAAI,IAAI,SAAS;AAC/C,QAAM,WAAW,WAAW,eAAe,WAAW;AACtD,QAAM,mBAAmB,WAAW,OAAO,gBAAgB,UAAU;AACrE,MAAI,iBAAkB,uBAAsB,gBAAgB;AAC5D,SAAO;AAAA,IACL,QAAQ,WAAW,aAAa;AAAA,IAChC,YAAY,WAAW,OAAO;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,YAAY,WAAW,MAAM;AAAA,IACrC,KAAK;AAAA,MACH,GAAG,eAAe,WAAW,QAAQ,aAAa;AAAA,MAClD;AAAA,IACF;AAAA,IACA,YAAY;AAAA,EACd;AACF;AAOA,SAAS,kBACP,UACgC;AAChC,SAAO;AAAA,IACL,SAAS;AAAA,IACT,oBAAoB,SAAS;AAAA,IAC7B,kBAAkB,SAAS;AAAA,IAC3B,UAAU,SAAS;AAAA,IACnB,eAAe,SAAS;AAAA,IACxB,OAAO,WAAW,SAAS,KAAK;AAAA,IAChC,gBAAgB;AAAA,MACd;AAAA,QACE,UAAU,SAAS;AAAA,QACnB,SAAS,SAAS;AAAA,QAClB,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,eAAe,CAAC;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,IACF;AAAA,IACA,eAAe,CAAC,SAAS,QAAQ;AAAA,IACjC,QAAQ,YAAY;AAAA,EACtB;AACF;AAEA,SAAS,oBACP,OACA,UACA,QACgC;AAChC,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,YAAY,GAAG;AAC9D,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AACA,MACE,MAAM,uBAAuB,SAAS,sBACtC,MAAM,qBAAqB,SAAS,oBACpC,MAAM,aAAa,SAAS,YAC5B,MAAM,kBAAkB,SAAS,iBACjC,CAAC,UAAU,MAAM,OAAO,SAAS,KAAK,GACtC;AACA,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AACA,QAAM,aAAa,gBAAgB,KAAK;AACxC,MAAI,WAAW,eAAe,WAAW,GAAG;AAC1C,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,MACE,WAAW,eAAe,SAAS,uCACnC,WAAW,cAAc,SAAS,uCAClC,WAAW,cAAc,SAAS,OAAO,YACzC;AACA,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AACA,MAAI,CAAC,WAAW,cAAc,SAAS,SAAS,QAAQ,GAAG;AACzD,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AACA,MAAI,IAAI,IAAI,WAAW,aAAa,EAAE,SAAS,WAAW,cAAc,QAAQ;AAC9E,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AACA,aAAW,YAAY,WAAW,cAAe,SAAQ,UAAU,qBAAqB;AACxF,QAAM,mBAAmB,oBAAI,IAAY;AACzC,aAAW,SAAS,WAAW,gBAAgB;AAC7C,YAAQ,MAAM,UAAU,6BAA6B;AACrD,QACE,CAAC,WAAW,cAAc,SAAS,MAAM,QAAQ,KACjD,iBAAiB,IAAI,MAAM,QAAQ,GACnC;AACA,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AACA,qBAAiB,IAAI,MAAM,QAAQ;AACnC,oBAAgB,MAAM,SAAS,4BAA4B;AAC3D,cAAU,MAAM,WAAW,8BAA8B;AACzD,cAAU,MAAM,eAAe,kCAAkC;AACjE,QACE,OAAO,MAAM,WAAW,aACxB,MAAM,cAAc,SAAS,6BAC7B;AACA,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AACA,QAAI,CAAC,MAAM,WAAW,MAAM,cAAc,SAAS,KAAK,MAAM,kBAAkB,OAAO;AACrF,YAAM,IAAI,MAAM,sEAAsE;AAAA,IACxF;AACA,UAAM,gBAAgB,MAAM,cAAc,IAAI,qBAAqB;AAAA,EACrE;AACA,kBAAgB,WAAW,MAAM;AACjC,MACE,WAAW,OAAO,gBAAgB,WAAW,cAAc,UAC3D,WAAW,OAAO,qBAChB,WAAW,OAAO,kBAAkB,WAAW,OAAO,qBACxD,WAAW,OAAO,uBAAuB,WAAW,OAAO,oBAC3D,WAAW,OAAO,cAChB,WAAW,OAAO,mBAChB,WAAW,OAAO,mBAClB,WAAW,OAAO,cAClB,GACJ;AACA,UAAM,IAAI,MAAM,2DAA2D;AAAA,EAC7E;AACA,MACE,WAAW,OAAO,YAAY,OAAO,YACrC,WAAW,OAAO,kBAAkB,OAAO,kBAC3C,OAAO,WAAW,OAAO,UAAU,IAAI,OAAO,OAAO,aAAa,GAClE;AACA,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,wBAAsB,UAAU;AAChC,SAAO;AACT;AAEA,SAAS,gBAAgB,OAA+D;AACtF,QAAM,SAAS;AAAA,IACb,UAAU,oBAAoB,MAAM,UAAU,iBAAiB;AAAA,IAC/D,eAAe,oBAAoB,MAAM,eAAe,sBAAsB;AAAA,IAC9E,gBAAgB,oBAAoB,MAAM,gBAAgB,uBAAuB;AAAA,IACjF,cAAc,oBAAoB,MAAM,cAAc,qBAAqB;AAAA,IAC3E,cAAc,oBAAoB,MAAM,cAAc,qBAAqB;AAAA,IAC3E,YAAY,oBAAoB,MAAM,YAAY,mBAAmB;AAAA,IACrE,UAAU,oBAAoB,MAAM,UAAU,iBAAiB;AAAA,EACjE;AACA,MAAI,OAAO,WAAW,6BAA6B;AACjD,UAAM,IAAI,MAAM,8BAA8B,2BAA2B,EAAE;AAAA,EAC7E;AACA,MAAI,OAAO,aAAa,qCAAqC;AAC3D,UAAM,IAAI,MAAM,gCAAgC,mCAAmC,EAAE;AAAA,EACvF;AACA,SAAO;AACT;AAEA,SAAS,UAAU,OAAiC,kBAAmC;AACrF,MACE,CAAC,SACD,CAAC,MAAM,QAAQ,MAAM,KAAK,KAC1B,MAAM,MAAM,SAAS,oBACrB,MAAM,MAAM,SAAS,6BACrB;AACA,WAAO;AAAA,EACT;AACA,MAAI;AACF,cAAU,MAAM,eAAe,oBAAoB;AACnD,UAAM,MAAM,QAAQ,qBAAqB;AACzC,WAAO,OAAO,MAAM,qBAAqB;AAAA,EAC3C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,sBACP,MACkC;AAClC,QAAM,KAAK,QAAQ,KAAK,IAAI,SAAS;AACrC,QAAM,OAAO,YAAY,KAAK,MAAM,aAAa,2BAA2B;AAC5E,QAAM,WAAW,YAAY,KAAK,UAAU,iBAAiB,2BAA2B;AACxF,QAAM,UAAU,MAAM,QAAQ,KAAK,OAAO,IACtC,KAAK,QAAQ,IAAI,CAAC,WAAW,QAAQ,QAAQ,aAAa,CAAC,IAC3D,CAAC;AACL,MAAI,QAAQ,SAAS,IAAK,OAAM,IAAI,MAAM,0CAA0C;AACpF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,gBAAgB,KAAK,SAAS,cAAc;AAAA,IACrD;AAAA,IACA,cAAc,oBAAoB,KAAK,cAAc,qBAAqB,GAAG;AAAA,IAC7E,aAAa,oBAAoB,KAAK,aAAa,oBAAoB,GAAG;AAAA,IAC1E,SAAS,oBAAoB,KAAK,SAAS,gBAAgB,GAAG;AAAA,IAC9D,aAAa,oBAAoB,KAAK,aAAa,oBAAoB,GAAG;AAAA,IAC1E,MAAM,SAAS,KAAK,IAAI,GAAG,SAAS,KAAK;AAAA,IACzC,aAAa,iBAAiB,KAAK,aAAa,kBAAkB;AAAA,IAClE,SAAS,KAAK,YAAY;AAAA,EAC5B;AACF;AAEA,SAAS,kCAAkC,MAAc,UAAiC;AACxF,QAAM,iBAAiB,SAAS,KAAK,EAAE,YAAY;AACnD,MAAI,eAAe,WAAW,OAAO,EAAG,QAAO;AAC/C,MAAI,uCAAuC,IAAI,cAAc,EAAG,QAAO;AACvE,MAAI,CAAC,6BAA6B,IAAI,cAAc,EAAG,QAAO;AAC9D,QAAM,YAAY,KAAK,YAAY;AACnC,aAAW,CAAC,WAAW,WAAW,KAAK,yCAAyC;AAC9E,QAAI,UAAU,SAAS,SAAS,EAAG,QAAO;AAAA,EAC5C;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAc,WAA2B;AACjE,QAAM,WAAW,aAAa,IAAI;AAClC,SAAO,SAAS,YAAY,EAAE,SAAS,SAAS,IAAI,WAAW,GAAG,QAAQ,GAAG,SAAS;AACxF;AAEA,SAAS,aAAa,OAAuB;AAC3C,QAAM,UAAU,MACb,UAAU,MAAM,EAChB,QAAQ,8BAA8B,GAAG,EACzC,QAAQ,SAAS,GAAG,EACpB,KAAK,EACL,MAAM,GAAG,GAAG;AACf,SAAO,WAAW;AACpB;AAEA,SAAS,qBAAqB,IAAoB;AAChD,SAAO,OAAO,SACV,4CACA,0CAA0C,mBAAmB,EAAE,CAAC;AACtE;AAEA,SAAS,mBAAmB,IAAoB;AAC9C,SAAO,oCAAoC,mBAAmB,EAAE,CAAC;AACnE;AAEA,SAAS,SAAS,OAAqC;AACrD,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,CAAC,cAAc,KAAK,KAAK,EAAG,OAAM,IAAI,MAAM,sBAAsB;AACtE,SAAO,OAAO,KAAK;AACrB;AAEA,SAAS,kBAAkB,OAA+B;AACxD,MAAI,EAAE,iBAAiB,mCAAoC,QAAO;AAClE,QAAM,aAAa,MAAM,aAAa,KAAK,EAAE,YAAY;AACzD,SAAO,6CAA6C,KAAK,UAAU,IAAI,aAAa;AACtF;AAEA,SAAS,QAAQ,OAAe,OAAuB;AACrD,QAAM,YAAY,YAAY,OAAO,OAAO,yBAAyB;AACrE,MAAI,cAAc,UAAU,oBAAoB,KAAK,SAAS,EAAG,QAAO;AACxE,QAAM,IAAI,MAAM,GAAG,KAAK,aAAa;AACvC;AAEA,SAAS,6BAA6B,OAAuB;AAC3D,SAAO,YAAY,OAAO,sBAAsB,yBAAyB;AAC3E;AAEA,SAAS,gBAAgB,OAAsB,OAA8B;AAC3E,SAAO,UAAU,OAAO,OAAO,QAAQ,OAAO,KAAK;AACrD;AAEA,SAAS,UAAU,OAAsB,OAA8B;AACrE,MAAI,UAAU,KAAM,QAAO;AAC3B,SAAO,YAAY,OAAO,OAAO,iCAAiC;AACpE;AAEA,SAAS,YAAY,OAAe,OAAe,UAA0B;AAC3E,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,MAAM,GAAG,KAAK,mBAAmB;AAC1E,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,WAAW,QAAQ,SAAS,YAAY,yBAAyB,KAAK,OAAO,GAAG;AACnF,UAAM,IAAI,MAAM,GAAG,KAAK,aAAa;AAAA,EACvC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAsB,OAAe,UAAiC;AACjG,SAAO,UAAU,OAAO,OAAO,YAAY,OAAO,OAAO,QAAQ;AACnE;AAEA,SAAS,iBAAiB,OAAsB,OAA8B;AAC5E,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,UAAU,YAAY,OAAO,OAAO,IAAI;AAC9C,QAAM,SAAS,IAAI,IAAI,OAAO;AAC9B,MAAI,OAAO,aAAa,SAAU,OAAM,IAAI,MAAM,GAAG,KAAK,iBAAiB;AAC3E,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,oBAAoB,OAAe,OAAuB;AACjE,MAAI,CAAC,OAAO,cAAc,KAAK,KAAK,SAAS,GAAG;AAC9C,UAAM,IAAI,MAAM,GAAG,KAAK,kCAAkC;AAAA,EAC5D;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,QAA0C;AACjE,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,QAAQ,aAAc;AAC1B,QAAI,OAAO,UAAU,YAAY,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAAG;AAC1E,YAAM,IAAI,MAAM,qBAAqB,GAAG,aAAa;AAAA,IACvD;AAAA,EACF;AACA,MAAI,CAAC,SAAS,KAAK,OAAO,UAAU,GAAG;AACrC,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACF;AAEA,SAAS,cAA0C;AACjD,SAAO;AAAA,IACL,WAAW;AAAA,IACX,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,IACtB,iBAAiB;AAAA,IACjB,YAAY;AAAA,EACd;AACF;AAEA,SAAS,YAAY,OAA+D;AAClF,SAAO,EAAE,GAAG,MAAM;AACpB;AAEA,SAAS,eACP,OACA,SAC4B;AAC5B,SAAO;AAAA,IACL,WAAW,MAAM,YAAY,QAAQ;AAAA,IACrC,aAAa,MAAM,cAAc,QAAQ;AAAA,IACzC,kBAAkB,MAAM,mBAAmB,QAAQ;AAAA,IACnD,kBAAkB,MAAM,mBAAmB,QAAQ;AAAA,IACnD,iBAAiB,MAAM,kBAAkB,QAAQ;AAAA,IACjD,mBAAmB,MAAM,oBAAoB,QAAQ;AAAA,IACrD,sBAAsB,MAAM,uBAAuB,QAAQ;AAAA,IAC3D,iBAAiB,MAAM,kBAAkB,QAAQ;AAAA,IACjD,aAAa,OAAO,MAAM,UAAU,IAAI,OAAO,QAAQ,UAAU,GAAG,SAAS;AAAA,EAC/E;AACF;AAEA,SAAS,kBACP,OACkC;AAClC,SAAO,EAAE,GAAG,OAAO,SAAS,CAAC,GAAG,MAAM,OAAO,EAAE;AACjD;AAEA,SAAS,WAAW,OAAmD;AACrE,SAAO,EAAE,GAAG,MAAM;AACpB;AAEA,SAAS,gBAAgB,OAAuE;AAC9F,SAAO;AAAA,IACL,SAAS;AAAA,IACT,oBAAoB,MAAM;AAAA,IAC1B,kBAAkB,MAAM;AAAA,IACxB,UAAU,MAAM;AAAA,IAChB,eAAe,MAAM;AAAA,IACrB,OAAO,WAAW,MAAM,KAAK;AAAA,IAC7B,gBAAgB,MAAM,eAAe,IAAI,CAAC,WAAW;AAAA,MACnD,GAAG;AAAA,MACH,eAAe,MAAM,cAAc,IAAI,iBAAiB;AAAA,IAC1D,EAAE;AAAA,IACF,eAAe,CAAC,GAAG,MAAM,aAAa;AAAA,IACtC,QAAQ,YAAY,MAAM,MAAM;AAAA,EAClC;AACF;AAEA,SAAS,UACP,MACA,OACS;AACT,SACE,CAAC,CAAC,QACF,OAAO,SAAS,YAChB,KAAK,SAAS,MAAM,QACpB,KAAK,gBAAgB,MAAM,eAC3B,KAAK,cAAc,MAAM;AAE7B;AAEA,SAAS,sBAAsB,YAAkD;AAC/E,MAAI,OAAO,WAAW,KAAK,UAAU,UAAU,GAAG,MAAM,IAAI,mCAAmC;AAC7F,UAAM,IAAI,MAAM,qEAAqE;AAAA,EACvF;AACF;","names":[]}
package/dist/index.d.ts CHANGED
@@ -90,6 +90,7 @@ export type DocumentAuthority = {
90
90
  };
91
91
  export type DocumentInventoryStatusCounts = Record<DocumentStatus, number>;
92
92
  export type DocumentInventorySourceKindCounts = Record<KnowledgeSourceKind, number>;
93
+ export type DocumentInventoryAuthorityKindCounts = Record<DocumentAuthorityKind, number>;
93
94
  export type DocumentInventory = {
94
95
  baseCount: number;
95
96
  bases: Array<{
@@ -102,6 +103,7 @@ export type DocumentInventory = {
102
103
  visibleDocumentCount: number;
103
104
  statusCounts: DocumentInventoryStatusCounts;
104
105
  sourceKindCounts: DocumentInventorySourceKindCounts;
106
+ authorityKindCounts: DocumentInventoryAuthorityKindCounts;
105
107
  latestUpdatedAt: string | null;
106
108
  topics: Array<{
107
109
  name: string;
@@ -300,10 +302,19 @@ export declare function resolveDocumentAuthority(input: {
300
302
  workspaceId: string;
301
303
  initiatingSubjectId?: string | null | undefined;
302
304
  }): DocumentAuthority;
303
- /** Whether a single already-fetched document is readable by this human viewer. */
304
- export declare function canViewDocument(document: Pick<DocumentAccessRecord, "authorityKind" | "authoritySubjectId">, viewerSubjectId: string | null | undefined): boolean;
305
+ /**
306
+ * Whether a single already-fetched document is readable in this workspace.
307
+ *
308
+ * Keep this compatibility predicate as strict as SQL/RLS: personal authority
309
+ * remains anchored to its originating workspace, and unknown or incomplete
310
+ * authority tuples deny instead of falling through as workspace-visible.
311
+ */
312
+ export declare function canViewDocument(document: Pick<DocumentAccessRecord, "authorityKind" | "authoritySubjectId"> & {
313
+ authorityWorkspaceId?: string | null | undefined;
314
+ }, viewerSubjectId: string | null | undefined, workspaceId?: string | null | undefined): boolean;
305
315
  type DocumentAccessRecord = {
306
316
  authorityKind: string;
317
+ authorityWorkspaceId: string | null;
307
318
  authoritySubjectId: string | null;
308
319
  agentAccess: boolean;
309
320
  };
package/dist/index.js CHANGED
@@ -405,6 +405,9 @@ async function getDocumentInventory(db, workspaceId, input) {
405
405
  documentCount: sql`count(${schema.documents.id}) filter (where ${schema.documents.sourceKind} = 'document')::int`,
406
406
  webCount: sql`count(${schema.documents.id}) filter (where ${schema.documents.sourceKind} = 'web')::int`,
407
407
  otherCount: sql`count(${schema.documents.id}) filter (where ${schema.documents.sourceKind} = 'other')::int`,
408
+ organizationAuthorityCount: sql`count(${schema.documents.id}) filter (where ${schema.documents.authorityKind} = 'organization')::int`,
409
+ workspaceAuthorityCount: sql`count(${schema.documents.id}) filter (where ${schema.documents.authorityKind} = 'workspace')::int`,
410
+ personalAuthorityCount: sql`count(${schema.documents.id}) filter (where ${schema.documents.authorityKind} = 'personal')::int`,
408
411
  latestUpdatedAt: sql`max(${schema.documents.updatedAt})`
409
412
  }).from(schema.documents).where(documentWhere);
410
413
  const topicStringValue = sql`topic.value #>> '{}'`;
@@ -447,6 +450,11 @@ async function getDocumentInventory(db, workspaceId, input) {
447
450
  web: Number(summary?.webCount ?? 0),
448
451
  other: Number(summary?.otherCount ?? 0)
449
452
  },
453
+ authorityKindCounts: {
454
+ organization: Number(summary?.organizationAuthorityCount ?? 0),
455
+ workspace: Number(summary?.workspaceAuthorityCount ?? 0),
456
+ personal: Number(summary?.personalAuthorityCount ?? 0)
457
+ },
450
458
  latestUpdatedAt: documentInventoryTimestamp(summary?.latestUpdatedAt ?? null),
451
459
  topics,
452
460
  topicsTruncated: topicRows.length > topics.length
@@ -535,7 +543,7 @@ async function addDocumentToBase(db, input) {
535
543
  )
536
544
  ).limit(1);
537
545
  if (existing) {
538
- if (!documentMatchesAccess(existing, input.access)) {
546
+ if (!documentMatchesAccess(existing, input.workspaceId, input.access)) {
539
547
  throw new Error(`Document not found: ${existing.id}`);
540
548
  }
541
549
  assertOrganizationDocumentAuthority(
@@ -1204,14 +1212,38 @@ function documentAccessConditions(workspaceId, access) {
1204
1212
  }
1205
1213
  return [authority];
1206
1214
  }
1207
- function documentMatchesAccess(document, access) {
1215
+ function documentMatchesAccess(document, workspaceId, access) {
1208
1216
  if (access?.agentOnly) {
1209
- return document.agentAccess && canViewDocument(document, access.viewerSubjectId);
1217
+ return document.agentAccess && canViewDocument(document, access.viewerSubjectId, workspaceId);
1218
+ }
1219
+ return canViewDocument(document, access?.viewerSubjectId, workspaceId);
1220
+ }
1221
+ function canonicalDocumentAuthoritySubject(value) {
1222
+ if (typeof value !== "string") return void 0;
1223
+ const subjectId = cleanString(value);
1224
+ if (!subjectId || subjectId !== value) return void 0;
1225
+ if (new TextEncoder().encode(subjectId).byteLength > DOCUMENT_AUTHORITY_SUBJECT_MAX_BYTES) {
1226
+ return void 0;
1210
1227
  }
1211
- return canViewDocument(document, access?.viewerSubjectId);
1228
+ return subjectId;
1212
1229
  }
1213
- function canViewDocument(document, viewerSubjectId) {
1214
- return document.authorityKind !== "personal" || !!viewerSubjectId && document.authoritySubjectId === viewerSubjectId;
1230
+ function canViewDocument(document, viewerSubjectId, workspaceId) {
1231
+ if (document.authorityKind === "organization") {
1232
+ return document.authorityWorkspaceId === null && document.authoritySubjectId === null;
1233
+ }
1234
+ const normalizedWorkspaceId = cleanString(workspaceId ?? null);
1235
+ if (!normalizedWorkspaceId || document.authorityWorkspaceId !== normalizedWorkspaceId) {
1236
+ return false;
1237
+ }
1238
+ if (document.authorityKind === "workspace") {
1239
+ return document.authoritySubjectId === null;
1240
+ }
1241
+ if (document.authorityKind === "personal") {
1242
+ const authoritySubjectId = canonicalDocumentAuthoritySubject(document.authoritySubjectId);
1243
+ const viewer = canonicalDocumentAuthoritySubject(viewerSubjectId);
1244
+ return !!authoritySubjectId && authoritySubjectId === viewer;
1245
+ }
1246
+ return false;
1215
1247
  }
1216
1248
  function documentSearchConditions(input, embeddingModel) {
1217
1249
  const conditions = [