@opengeni/documents 0.6.9-canary.0 → 0.7.0-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +89 -0
- package/dist/index.js +200 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +266 -0
package/dist/index.d.ts
CHANGED
|
@@ -117,6 +117,14 @@ export type RunDocumentDefaultCollectionBackfillInput = RunDocumentDefaultCollec
|
|
|
117
117
|
actorSubjectId: string;
|
|
118
118
|
accountAdminAuthorization: DocumentAccountAdminAuthorization;
|
|
119
119
|
};
|
|
120
|
+
export type DocumentMigrationAuditInput = {
|
|
121
|
+
accountId: string;
|
|
122
|
+
workspaceId: string;
|
|
123
|
+
actorSubjectId: string;
|
|
124
|
+
accountAdminAuthorization: DocumentAccountAdminAuthorization;
|
|
125
|
+
limit?: number | undefined;
|
|
126
|
+
cursor?: string | undefined;
|
|
127
|
+
};
|
|
120
128
|
export type AgentDocumentAuthorityContext = {
|
|
121
129
|
sessionId: string;
|
|
122
130
|
attemptId: string;
|
|
@@ -321,6 +329,87 @@ export declare function runDocumentDefaultCollectionBackfill(db: Database, input
|
|
|
321
329
|
adoptedCount: number;
|
|
322
330
|
completedAt: string | null;
|
|
323
331
|
}>;
|
|
332
|
+
export declare function listDocumentDefaultCollectionBackfillRuns(db: Database, input: DocumentMigrationAuditInput): Promise<{
|
|
333
|
+
runs: {
|
|
334
|
+
runId: string;
|
|
335
|
+
status: "completed" | "running";
|
|
336
|
+
lastWorkspaceId: string | null;
|
|
337
|
+
processedCount: number;
|
|
338
|
+
createdCount: number;
|
|
339
|
+
adoptedCount: number;
|
|
340
|
+
completedAt: string | null;
|
|
341
|
+
actorSubjectId: string;
|
|
342
|
+
startedAt: string;
|
|
343
|
+
updatedAt: string;
|
|
344
|
+
}[];
|
|
345
|
+
hasMore: boolean;
|
|
346
|
+
nextCursor: string | null;
|
|
347
|
+
}>;
|
|
348
|
+
export declare function getDocumentDefaultCollectionBackfillAudit(db: Database, input: DocumentMigrationAuditInput & {
|
|
349
|
+
runId: string;
|
|
350
|
+
operationCursor?: string | undefined;
|
|
351
|
+
receiptCursor?: string | undefined;
|
|
352
|
+
}): Promise<{
|
|
353
|
+
run: {
|
|
354
|
+
runId: string;
|
|
355
|
+
status: "completed" | "running";
|
|
356
|
+
lastWorkspaceId: string | null;
|
|
357
|
+
processedCount: number;
|
|
358
|
+
createdCount: number;
|
|
359
|
+
adoptedCount: number;
|
|
360
|
+
completedAt: string | null;
|
|
361
|
+
actorSubjectId: string;
|
|
362
|
+
startedAt: string;
|
|
363
|
+
updatedAt: string;
|
|
364
|
+
};
|
|
365
|
+
operations: {
|
|
366
|
+
operationId: string;
|
|
367
|
+
result: {
|
|
368
|
+
runId: string;
|
|
369
|
+
operationId: string;
|
|
370
|
+
status: "completed" | "running";
|
|
371
|
+
lastWorkspaceId: string | null;
|
|
372
|
+
processedCount: number;
|
|
373
|
+
createdCount: number;
|
|
374
|
+
adoptedCount: number;
|
|
375
|
+
completedAt: string | null;
|
|
376
|
+
};
|
|
377
|
+
createdAt: string;
|
|
378
|
+
}[];
|
|
379
|
+
receipts: {
|
|
380
|
+
workspaceId: string;
|
|
381
|
+
baseId: string;
|
|
382
|
+
outcome: "adopted" | "created";
|
|
383
|
+
createdAt: string;
|
|
384
|
+
}[];
|
|
385
|
+
operationsHasMore: boolean;
|
|
386
|
+
operationsNextCursor: string | null;
|
|
387
|
+
receiptsHasMore: boolean;
|
|
388
|
+
receiptsNextCursor: string | null;
|
|
389
|
+
}>;
|
|
390
|
+
export declare function listOrganizationDocumentAuthorityReclassifications(db: Database, input: DocumentMigrationAuditInput): Promise<{
|
|
391
|
+
receipts: {
|
|
392
|
+
operationId: string;
|
|
393
|
+
documentId: string;
|
|
394
|
+
previousAuthority: {
|
|
395
|
+
kind: "organization" | "personal" | "workspace";
|
|
396
|
+
workspaceId: string | null;
|
|
397
|
+
subjectId: string | null;
|
|
398
|
+
authorityId: string | null;
|
|
399
|
+
};
|
|
400
|
+
authority: {
|
|
401
|
+
kind: "organization" | "personal" | "workspace";
|
|
402
|
+
workspaceId: string | null;
|
|
403
|
+
subjectId: string | null;
|
|
404
|
+
authorityId: string | null;
|
|
405
|
+
};
|
|
406
|
+
createdAt: string;
|
|
407
|
+
actorSubjectId: string;
|
|
408
|
+
requestWorkspaceId: string;
|
|
409
|
+
}[];
|
|
410
|
+
hasMore: boolean;
|
|
411
|
+
nextCursor: string | null;
|
|
412
|
+
}>;
|
|
324
413
|
export declare function reclassifyDocumentAuthority(db: Database, input: ReclassifyDocumentAuthorityInput): Promise<{
|
|
325
414
|
operationId: string;
|
|
326
415
|
documentId: string;
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,14 @@ import {
|
|
|
3
3
|
KnowledgeProviderCitation,
|
|
4
4
|
DocumentAuthorityReclassification,
|
|
5
5
|
ListDocumentAuthorityReclassificationsResponse,
|
|
6
|
-
DocumentDefaultCollectionBackfill
|
|
6
|
+
DocumentDefaultCollectionBackfill,
|
|
7
|
+
DocumentDefaultCollectionBackfillAudit,
|
|
8
|
+
DocumentDefaultCollectionBackfillOperationAudit,
|
|
9
|
+
DocumentDefaultCollectionBackfillReceiptAudit,
|
|
10
|
+
DocumentDefaultCollectionBackfillRunAudit,
|
|
11
|
+
ListDocumentDefaultCollectionBackfillRunsResponse,
|
|
12
|
+
ListOrganizationDocumentAuthorityReclassificationsResponse,
|
|
13
|
+
OrganizationDocumentAuthorityReclassification
|
|
7
14
|
} from "@opengeni/contracts";
|
|
8
15
|
import {
|
|
9
16
|
createPersonalDocumentAuthority,
|
|
@@ -740,6 +747,195 @@ async function runDocumentDefaultCollectionBackfill(db, input) {
|
|
|
740
747
|
}
|
|
741
748
|
);
|
|
742
749
|
}
|
|
750
|
+
async function listDocumentDefaultCollectionBackfillRuns(db, input) {
|
|
751
|
+
const limit = validateDocumentMigrationAuditLimit(input.limit);
|
|
752
|
+
const cursor = input.cursor ? decodeDocumentMigrationAuditCursor(input.cursor, ["backfill-runs", input.accountId], true) : null;
|
|
753
|
+
return await withDocumentAccountRls(
|
|
754
|
+
db,
|
|
755
|
+
input.accountId,
|
|
756
|
+
input.workspaceId,
|
|
757
|
+
{ viewerSubjectId: input.actorSubjectId },
|
|
758
|
+
async (scopedDb) => {
|
|
759
|
+
const command = {
|
|
760
|
+
accountId: input.accountId,
|
|
761
|
+
workspaceId: input.workspaceId,
|
|
762
|
+
actorSubjectId: input.actorSubjectId,
|
|
763
|
+
accountAdminAuthorization: input.accountAdminAuthorization,
|
|
764
|
+
limit: limit + 1,
|
|
765
|
+
beforeStartedAt: cursor?.timestamp ?? null,
|
|
766
|
+
beforeRunId: cursor?.id ?? null
|
|
767
|
+
};
|
|
768
|
+
const rows = await scopedDb.execute(sql`
|
|
769
|
+
SELECT list_document_default_collection_backfill_runs(
|
|
770
|
+
${JSON.stringify(command)}::jsonb
|
|
771
|
+
) AS result
|
|
772
|
+
`);
|
|
773
|
+
const parsed = rows.map((row) => DocumentDefaultCollectionBackfillRunAudit.parse(row.result));
|
|
774
|
+
const hasMore = parsed.length > limit;
|
|
775
|
+
const runs = parsed.slice(0, limit);
|
|
776
|
+
const tail = hasMore ? runs.at(-1) : null;
|
|
777
|
+
return ListDocumentDefaultCollectionBackfillRunsResponse.parse({
|
|
778
|
+
runs,
|
|
779
|
+
hasMore,
|
|
780
|
+
nextCursor: tail ? encodeDocumentMigrationAuditCursor(["backfill-runs", input.accountId], {
|
|
781
|
+
timestamp: tail.startedAt,
|
|
782
|
+
id: tail.runId
|
|
783
|
+
}) : null
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
async function getDocumentDefaultCollectionBackfillAudit(db, input) {
|
|
789
|
+
const limit = validateDocumentMigrationAuditLimit(input.limit);
|
|
790
|
+
const operationCursor = input.operationCursor ? decodeDocumentMigrationAuditCursor(
|
|
791
|
+
input.operationCursor,
|
|
792
|
+
["backfill-operations", input.accountId, input.runId],
|
|
793
|
+
true
|
|
794
|
+
) : null;
|
|
795
|
+
const receiptCursor = input.receiptCursor ? decodeDocumentMigrationAuditCursor(
|
|
796
|
+
input.receiptCursor,
|
|
797
|
+
["backfill-receipts", input.accountId, input.runId],
|
|
798
|
+
false
|
|
799
|
+
) : null;
|
|
800
|
+
return await withDocumentAccountRls(
|
|
801
|
+
db,
|
|
802
|
+
input.accountId,
|
|
803
|
+
input.workspaceId,
|
|
804
|
+
{ viewerSubjectId: input.actorSubjectId },
|
|
805
|
+
async (scopedDb) => {
|
|
806
|
+
const command = {
|
|
807
|
+
accountId: input.accountId,
|
|
808
|
+
workspaceId: input.workspaceId,
|
|
809
|
+
actorSubjectId: input.actorSubjectId,
|
|
810
|
+
accountAdminAuthorization: input.accountAdminAuthorization,
|
|
811
|
+
runId: input.runId,
|
|
812
|
+
limit,
|
|
813
|
+
operationBeforeCreatedAt: operationCursor?.timestamp ?? null,
|
|
814
|
+
operationBeforeId: operationCursor?.id ?? null,
|
|
815
|
+
receiptAfterWorkspaceId: receiptCursor?.id ?? null
|
|
816
|
+
};
|
|
817
|
+
const rows = await scopedDb.execute(sql`
|
|
818
|
+
SELECT get_document_default_collection_backfill_audit(
|
|
819
|
+
${JSON.stringify(command)}::jsonb
|
|
820
|
+
) AS result
|
|
821
|
+
`);
|
|
822
|
+
const raw = rows[0]?.result;
|
|
823
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
824
|
+
throw new Error("document Default collection backfill audit returned no result");
|
|
825
|
+
}
|
|
826
|
+
const value = raw;
|
|
827
|
+
const run = DocumentDefaultCollectionBackfillRunAudit.parse(value.run);
|
|
828
|
+
const operations = Array.isArray(value.operations) ? value.operations.map(
|
|
829
|
+
(operation) => DocumentDefaultCollectionBackfillOperationAudit.parse(operation)
|
|
830
|
+
) : [];
|
|
831
|
+
const receipts = Array.isArray(value.receipts) ? value.receipts.map(
|
|
832
|
+
(receipt) => DocumentDefaultCollectionBackfillReceiptAudit.parse(receipt)
|
|
833
|
+
) : [];
|
|
834
|
+
const operationsHasMore = operations.length > limit;
|
|
835
|
+
const receiptsHasMore = receipts.length > limit;
|
|
836
|
+
const operationPage = operations.slice(0, limit);
|
|
837
|
+
const receiptPage = receipts.slice(0, limit);
|
|
838
|
+
const operationTail = operationsHasMore ? operationPage.at(-1) : null;
|
|
839
|
+
const receiptTail = receiptsHasMore ? receiptPage.at(-1) : null;
|
|
840
|
+
return DocumentDefaultCollectionBackfillAudit.parse({
|
|
841
|
+
run,
|
|
842
|
+
operations: operationPage,
|
|
843
|
+
receipts: receiptPage,
|
|
844
|
+
operationsHasMore,
|
|
845
|
+
operationsNextCursor: operationTail ? encodeDocumentMigrationAuditCursor(
|
|
846
|
+
["backfill-operations", input.accountId, input.runId],
|
|
847
|
+
{ timestamp: operationTail.createdAt, id: operationTail.operationId }
|
|
848
|
+
) : null,
|
|
849
|
+
receiptsHasMore,
|
|
850
|
+
receiptsNextCursor: receiptTail ? encodeDocumentMigrationAuditCursor(
|
|
851
|
+
["backfill-receipts", input.accountId, input.runId],
|
|
852
|
+
{ timestamp: null, id: receiptTail.workspaceId }
|
|
853
|
+
) : null
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
async function listOrganizationDocumentAuthorityReclassifications(db, input) {
|
|
859
|
+
const limit = validateDocumentMigrationAuditLimit(input.limit);
|
|
860
|
+
const cursor = input.cursor ? decodeDocumentMigrationAuditCursor(
|
|
861
|
+
input.cursor,
|
|
862
|
+
["organization-reclassifications", input.accountId],
|
|
863
|
+
true
|
|
864
|
+
) : null;
|
|
865
|
+
return await withDocumentAccountRls(
|
|
866
|
+
db,
|
|
867
|
+
input.accountId,
|
|
868
|
+
input.workspaceId,
|
|
869
|
+
{ viewerSubjectId: input.actorSubjectId },
|
|
870
|
+
async (scopedDb) => {
|
|
871
|
+
const command = {
|
|
872
|
+
accountId: input.accountId,
|
|
873
|
+
workspaceId: input.workspaceId,
|
|
874
|
+
actorSubjectId: input.actorSubjectId,
|
|
875
|
+
accountAdminAuthorization: input.accountAdminAuthorization,
|
|
876
|
+
limit: limit + 1,
|
|
877
|
+
beforeCreatedAt: cursor?.timestamp ?? null,
|
|
878
|
+
beforeOperationId: cursor?.id ?? null
|
|
879
|
+
};
|
|
880
|
+
const rows = await scopedDb.execute(sql`
|
|
881
|
+
SELECT list_organization_document_authority_reclassifications(
|
|
882
|
+
${JSON.stringify(command)}::jsonb
|
|
883
|
+
) AS result
|
|
884
|
+
`);
|
|
885
|
+
const parsed = rows.map(
|
|
886
|
+
(row) => OrganizationDocumentAuthorityReclassification.parse(row.result)
|
|
887
|
+
);
|
|
888
|
+
const hasMore = parsed.length > limit;
|
|
889
|
+
const receipts = parsed.slice(0, limit);
|
|
890
|
+
const tail = hasMore ? receipts.at(-1) : null;
|
|
891
|
+
return ListOrganizationDocumentAuthorityReclassificationsResponse.parse({
|
|
892
|
+
receipts,
|
|
893
|
+
hasMore,
|
|
894
|
+
nextCursor: tail ? encodeDocumentMigrationAuditCursor(
|
|
895
|
+
["organization-reclassifications", input.accountId],
|
|
896
|
+
{ timestamp: tail.createdAt, id: tail.operationId }
|
|
897
|
+
) : null
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
);
|
|
901
|
+
}
|
|
902
|
+
function validateDocumentMigrationAuditLimit(value) {
|
|
903
|
+
const limit = value ?? 50;
|
|
904
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > 100) {
|
|
905
|
+
throw new Error("document migration audit limit must be between 1 and 100");
|
|
906
|
+
}
|
|
907
|
+
return limit;
|
|
908
|
+
}
|
|
909
|
+
function documentMigrationAuditCursorScope(parts) {
|
|
910
|
+
return createHash("sha256").update(JSON.stringify(["document-migration-audit", 1, ...parts]), "utf8").digest("hex").slice(0, 32);
|
|
911
|
+
}
|
|
912
|
+
function encodeDocumentMigrationAuditCursor(parts, cursor) {
|
|
913
|
+
return Buffer.from(
|
|
914
|
+
JSON.stringify({
|
|
915
|
+
v: 1,
|
|
916
|
+
s: documentMigrationAuditCursorScope(parts),
|
|
917
|
+
t: cursor.timestamp,
|
|
918
|
+
i: cursor.id
|
|
919
|
+
}),
|
|
920
|
+
"utf8"
|
|
921
|
+
).toString("base64url");
|
|
922
|
+
}
|
|
923
|
+
function decodeDocumentMigrationAuditCursor(value, parts, requireTimestamp) {
|
|
924
|
+
try {
|
|
925
|
+
if (!value || value.length > 1024) throw new Error("cursor length");
|
|
926
|
+
const bytes = Buffer.from(value, "base64url");
|
|
927
|
+
if (bytes.toString("base64url") !== value) throw new Error("cursor encoding");
|
|
928
|
+
const parsed = JSON.parse(bytes.toString("utf8"));
|
|
929
|
+
if (Object.keys(parsed).sort().join(",") !== "i,s,t,v" || parsed.v !== 1 || parsed.s !== documentMigrationAuditCursorScope(parts) || typeof parsed.i !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(
|
|
930
|
+
parsed.i
|
|
931
|
+
) || (requireTimestamp ? typeof parsed.t !== "string" || !Number.isFinite(new Date(parsed.t).getTime()) : parsed.t !== null)) {
|
|
932
|
+
throw new Error("cursor payload");
|
|
933
|
+
}
|
|
934
|
+
return { timestamp: typeof parsed.t === "string" ? parsed.t : null, id: parsed.i };
|
|
935
|
+
} catch (error) {
|
|
936
|
+
throw new Error("invalid document migration audit cursor", { cause: error });
|
|
937
|
+
}
|
|
938
|
+
}
|
|
743
939
|
async function reclassifyDocumentAuthority(db, input) {
|
|
744
940
|
return await withDocumentAccountRls(
|
|
745
941
|
db,
|
|
@@ -2909,6 +3105,7 @@ export {
|
|
|
2909
3105
|
getDocument,
|
|
2910
3106
|
getDocumentBase,
|
|
2911
3107
|
getDocumentChunk,
|
|
3108
|
+
getDocumentDefaultCollectionBackfillAudit,
|
|
2912
3109
|
getDocumentForIndexing,
|
|
2913
3110
|
getDocumentInventory,
|
|
2914
3111
|
getDocumentOriginalFile,
|
|
@@ -2919,8 +3116,10 @@ export {
|
|
|
2919
3116
|
listDocumentAuthorityReclassifications,
|
|
2920
3117
|
listDocumentBases,
|
|
2921
3118
|
listDocumentBasesEnsuringDefault,
|
|
3119
|
+
listDocumentDefaultCollectionBackfillRuns,
|
|
2922
3120
|
listDocuments,
|
|
2923
3121
|
listEffectiveIndexedDocuments,
|
|
3122
|
+
listOrganizationDocumentAuthorityReclassifications,
|
|
2924
3123
|
moveDocumentToBase,
|
|
2925
3124
|
parseCurationOutcome,
|
|
2926
3125
|
parseDocumentBytes,
|