@tearleads/client-sdk 0.1.41 → 0.1.43
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/client/Tearleads.js +3 -0
- package/client/Tearleads.js.map +1 -1
- package/data/blobs/transferPool.js +35 -8
- package/data/blobs/transferPool.js.map +1 -1
- package/data/containers/shared/projection.js +12 -0
- package/data/containers/shared/projection.js.map +1 -1
- package/data/documents/blob/shared/types.d.ts +2 -3
- package/data/documents/blob/shared/types.js.map +1 -1
- package/data/documents/shared/events.js +0 -1
- package/data/documents/shared/events.js.map +1 -1
- package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js +2 -0
- package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js.map +1 -1
- package/data/keyingProjectionVerification/checkpointContext.d.ts +12 -0
- package/data/keyingProjectionVerification/checkpointContext.js +16 -0
- package/data/keyingProjectionVerification/checkpointContext.js.map +1 -1
- package/data/keyingProjectionVerification/containerDestinationVerification.js +3 -1
- package/data/keyingProjectionVerification/containerDestinationVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerProjectionVerification.js +12 -6
- package/data/keyingProjectionVerification/containerProjectionVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentProjectionVerification.js +10 -4
- package/data/keyingProjectionVerification/documentProjectionVerification.js.map +1 -1
- package/data/persistence/container-contents/containerContentsPersistence.js +6 -22
- package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js +5 -15
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerPendingUpdatePersistence.js +6 -15
- package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
- package/data/persistence/container-contents/containerRecoveryPersistence.js +3 -4
- package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerRemovalWork.js +3 -5
- package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
- package/data/persistence/container-contents/dormantContainerMetadata.js +1 -5
- package/data/persistence/container-contents/dormantContainerMetadata.js.map +1 -1
- package/data/persistence/documents/documentsPersistence.js +4 -9
- package/data/persistence/documents/documentsPersistence.js.map +1 -1
- package/data/persistence/documents/internal/discardDocument.js +1 -2
- package/data/persistence/documents/internal/discardDocument.js.map +1 -1
- package/data/persistence/documents/internal/documentDeletionPersistence.js +1 -2
- package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
- package/data/persistence/documents/internal/documentMutationPersistence.js +17 -25
- package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
- package/data/persistence/documents/internal/orphanSideRows.js +2 -14
- package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
- package/data/persistence/documents/internal/syncQueuePersistence.js +3 -3
- package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
- package/data/persistence/keyingCheckpointAdvancePersistence.js +27 -8
- package/data/persistence/keyingCheckpointAdvancePersistence.js.map +1 -1
- package/data/persistence/verifiedManifestBundlePersistence.d.ts +45 -0
- package/data/persistence/verifiedManifestBundlePersistence.js +282 -0
- package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -0
- package/data/sqlite/documentHistoryPersistence.d.ts +9 -3
- package/data/sqlite/documentHistoryPersistence.js +31 -8
- package/data/sqlite/documentHistoryPersistence.js.map +1 -1
- package/data/sqlite/documentPendingUpdatePersistence.d.ts +58 -11
- package/data/sqlite/documentPendingUpdatePersistence.js +137 -63
- package/data/sqlite/documentPendingUpdatePersistence.js.map +1 -1
- package/data/sqlite/documentPersistence.d.ts +1 -1
- package/data/sqlite/documentPersistence.js +1 -1
- package/data/sqlite/documentPersistence.js.map +1 -1
- package/data/sqlite/documentPersistenceTypes.d.ts +2 -2
- package/data/sqlite/documentPersistenceTypes.js.map +1 -1
- package/data/sqlite/documentRecordPersistence.js +5 -4
- package/data/sqlite/documentRecordPersistence.js.map +1 -1
- package/data/sqlite/schema.d.ts +350 -443
- package/data/sqlite/schema.js +49 -47
- package/data/sqlite/schema.js.map +1 -1
- package/data/sqlite/verifiedManifestBundleSchema.d.ts +174 -0
- package/data/sqlite/verifiedManifestBundleSchema.js +36 -0
- package/data/sqlite/verifiedManifestBundleSchema.js.map +1 -0
- package/internal/api-client/ApiClient.d.ts +17 -19
- package/internal/api-client/ApiClient.js +10 -11
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/binaryRequestOperationTransport.d.ts +18 -0
- package/internal/api-client/index.d.ts +2 -1
- package/internal/api-client/index.js +1 -1
- package/internal/api-client/index.js.map +1 -1
- package/internal/api-client/operationTransportFactory.d.ts +6 -0
- package/internal/api-client/principalHistoryRequest.js +8 -2
- package/internal/api-client/principalHistoryRequest.js.map +1 -1
- package/internal/api-client/principalHistoryRequestContext.js +15 -5
- package/internal/api-client/principalHistoryRequestContext.js.map +1 -1
- package/internal/api-client/routes/blobs/get.d.ts +7 -0
- package/internal/api-client/routes/blobs/get.js.map +1 -1
- package/internal/api-client/routes/blobs/multipart.js +1 -11
- package/internal/api-client/routes/blobs/multipart.js.map +1 -1
- package/internal/api-client/routes/blobs/multipartUpload.d.ts +14 -0
- package/internal/api-client/routes/blobs/multipartUpload.js +94 -43
- package/internal/api-client/routes/blobs/multipartUpload.js.map +1 -1
- package/internal/api-client/routes/writerProjections.js +6 -3
- package/internal/api-client/routes/writerProjections.js.map +1 -1
- package/internal/api-client/verifiedManifestCitations.d.ts +23 -0
- package/internal/api-client/verifiedManifestCitations.js +60 -0
- package/internal/api-client/verifiedManifestCitations.js.map +1 -0
- package/internal/api-client/writerProjectionRequests.js +75 -14
- package/internal/api-client/writerProjectionRequests.js.map +1 -1
- package/internal/crypto/index.d.ts +0 -1
- package/internal/crypto/index.js +0 -1
- package/internal/crypto/index.js.map +1 -1
- package/internal/validators/knownManifestsRefinements.js +5 -0
- package/internal/validators/knownManifestsRefinements.js.map +1 -0
- package/internal/validators/operation/attachments.d.ts +80 -160
- package/internal/validators/operation/auth.d.ts +760 -1664
- package/internal/validators/operation/blobDownloads.js +1 -1
- package/internal/validators/operation/blobDownloads.js.map +1 -1
- package/internal/validators/operation/containerMutations.d.ts +416 -856
- package/internal/validators/operation/documentMutations.d.ts +120 -264
- package/internal/validators/operation/documentSync.d.ts +40 -80
- package/internal/validators/operation/index.d.ts +1 -1
- package/internal/validators/operation/index.js +1 -1
- package/internal/validators/operation/index.js.map +1 -1
- package/internal/validators/operation/multipartBlobs.d.ts +70 -190
- package/internal/validators/operation/multipartBlobs.js +2 -24
- package/internal/validators/operation/multipartBlobs.js.map +1 -1
- package/internal/validators/operation/multipartPartUploads.d.ts +5 -5
- package/internal/validators/operation/multipartPartUploads.js +6 -20
- package/internal/validators/operation/multipartPartUploads.js.map +1 -1
- package/internal/validators/operation/organizations.d.ts +882 -1906
- package/internal/validators/operation/principals.d.ts +120 -240
- package/internal/validators/operation/registry.d.ts +1 -2
- package/internal/validators/operation/registry.js +1 -2
- package/internal/validators/operation/registry.js.map +1 -1
- package/internal/validators/operation/writerProjections.d.ts +85 -319
- package/internal/validators/operation/writerProjections.js +11 -11
- package/internal/validators/operation/writerProjections.js.map +1 -1
- package/internal/validators/request/blob.d.ts +100 -201
- package/internal/validators/request/blob.js +6 -13
- package/internal/validators/request/blob.js.map +1 -1
- package/internal/validators/request/container.d.ts +136 -272
- package/internal/validators/request/container.js +16 -10
- package/internal/validators/request/container.js.map +1 -1
- package/internal/validators/request/containerManifestRef.d.ts +54 -0
- package/internal/validators/request/containerManifestRef.js +28 -0
- package/internal/validators/request/containerManifestRef.js.map +1 -0
- package/internal/validators/request/containerMetadata.d.ts +160 -368
- package/internal/validators/request/document.d.ts +100 -245
- package/internal/validators/request/document.js +1 -2
- package/internal/validators/request/document.js.map +1 -1
- package/internal/validators/request/documentSyncSchema.d.ts +42 -109
- package/internal/validators/request/documentSyncSchema.js +8 -25
- package/internal/validators/request/documentSyncSchema.js.map +1 -1
- package/internal/validators/request/index.d.ts +1 -1
- package/internal/validators/request/index.js +1 -1
- package/internal/validators/request/index.js.map +1 -1
- package/internal/validators/request/organization.d.ts +160 -320
- package/internal/validators/request/organizationProvisioning.d.ts +2424 -5312
- package/internal/validators/request/principal.d.ts +160 -320
- package/internal/validators/request/registration.d.ts +760 -1664
- package/internal/validators/response/blob.d.ts +48 -27
- package/internal/validators/response/blob.js +3 -10
- package/internal/validators/response/blob.js.map +1 -1
- package/internal/validators/response/container.d.ts +429 -20
- package/internal/validators/response/container.js +40 -5
- package/internal/validators/response/container.js.map +1 -1
- package/internal/validators/response/documentMutation.d.ts +440 -20
- package/internal/validators/response/documentMutation.js +33 -3
- package/internal/validators/response/documentMutation.js.map +1 -1
- package/internal/validators/response/index.d.ts +4 -3
- package/internal/validators/response/index.js +4 -3
- package/internal/validators/response/index.js.map +1 -1
- package/internal/validators/response/manifestBundleReferences.js +79 -0
- package/internal/validators/response/manifestBundleReferences.js.map +1 -0
- package/internal/validators/response/writerProjectionWire.d.ts +19 -0
- package/internal/validators/response/writerProjectionWire.js +132 -0
- package/internal/validators/response/writerProjectionWire.js.map +1 -0
- package/internal/validators/schema.js +20 -0
- package/internal/validators/schema.js.map +1 -1
- package/internal/validators/util/blob.d.ts +7 -0
- package/internal/validators/util/blob.js +7 -0
- package/internal/validators/util/blob.js.map +1 -1
- package/internal/validators/util/blobTransferSchemas.d.ts +41 -0
- package/internal/validators/util/blobTransferSchemas.js +39 -0
- package/internal/validators/util/blobTransferSchemas.js.map +1 -0
- package/internal/validators/util/containerLimits.d.ts +7 -0
- package/internal/validators/util/containerLimits.js +7 -0
- package/internal/validators/util/containerLimits.js.map +1 -1
- package/internal/validators/util/index.d.ts +3 -2
- package/internal/validators/util/index.js +3 -2
- package/internal/validators/util/index.js.map +1 -1
- package/internal/validators/util/knownManifestWire.d.ts +11 -0
- package/internal/validators/util/knownManifestWire.js +28 -0
- package/internal/validators/util/knownManifestWire.js.map +1 -0
- package/internal/validators/writerProjectionRefinements.js +5 -0
- package/internal/validators/writerProjectionRefinements.js.map +1 -1
- package/package.json +1 -1
- package/workflows/blobs/multipartFirstParts.js +82 -0
- package/workflows/blobs/multipartFirstParts.js.map +1 -0
- package/workflows/blobs/multipartStageResolution.js +83 -0
- package/workflows/blobs/multipartStageResolution.js.map +1 -0
- package/workflows/blobs/multipartUpload.js +45 -89
- package/workflows/blobs/multipartUpload.js.map +1 -1
- package/workflows/container-contents/documentPriming.js +2 -1
- package/workflows/container-contents/documentPriming.js.map +1 -1
- package/workflows/container-contents/documentQueries/sql.js +4 -4
- package/workflows/container-contents/documentQueries/sql.js.map +1 -1
- package/workflows/container-contents/pendingWrites/deferredTails.js +6 -3
- package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
- package/workflows/container-contents/pendingWrites/sources.js +2 -1
- package/workflows/container-contents/pendingWrites/sources.js.map +1 -1
- package/workflows/container-contents/pendingWrites.js +2 -1
- package/workflows/container-contents/pendingWrites.js.map +1 -1
- package/workflows/containers/child/create.js +3 -3
- package/workflows/containers/child/create.js.map +1 -1
- package/workflows/containers/child/move.js +2 -2
- package/workflows/containers/child/move.js.map +1 -1
- package/workflows/containers/child/mutationRequestCore.js +5 -4
- package/workflows/containers/child/mutationRequestCore.js.map +1 -1
- package/workflows/containers/child/recitePlan.js +3 -2
- package/workflows/containers/child/recitePlan.js.map +1 -1
- package/workflows/containers/child/sharePlanCore.js +2 -2
- package/workflows/containers/child/sharePlanCore.js.map +1 -1
- package/workflows/containers/root/create.js +2 -2
- package/workflows/containers/root/create.js.map +1 -1
- package/workflows/registration/provisioningBootstrapBuilders.d.ts +20 -51
- package/workflows/sync/remoteReset.js +11 -9
- package/workflows/sync/remoteReset.js.map +1 -1
- package/workflows/sync/remoteResetPlans.js +6 -3
- package/workflows/sync/remoteResetPlans.js.map +1 -1
- package/internal/api-client/projectionHistoryTransport.js +0 -107
- package/internal/api-client/projectionHistoryTransport.js.map +0 -1
- package/internal/api-client/verifiedProjectionHistory.d.ts +0 -4
- package/internal/api-client/verifiedProjectionHistory.js +0 -12
- package/internal/api-client/verifiedProjectionHistory.js.map +0 -1
- package/internal/crypto/projectionHistory.d.ts +0 -14
- package/internal/crypto/projectionHistory.js +0 -90
- package/internal/crypto/projectionHistory.js.map +0 -1
- package/internal/crypto/projectionHistorySlots.d.ts +0 -13
- package/internal/crypto/projectionHistorySlots.js +0 -81
- package/internal/crypto/projectionHistorySlots.js.map +0 -1
- package/internal/validators/operation/blobTransferSchemas.js +0 -11
- package/internal/validators/operation/blobTransferSchemas.js.map +0 -1
- package/internal/validators/projectionHistoryRefinements.js +0 -5
- package/internal/validators/projectionHistoryRefinements.js.map +0 -1
- package/internal/validators/util/projectionHistoryWire.d.ts +0 -23
- package/internal/validators/util/projectionHistoryWire.js +0 -33
- package/internal/validators/util/projectionHistoryWire.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncQueuePersistence.js","sourceRoot":"","sources":["syncQueuePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, isNull } from \"drizzle-orm\";\nimport {\n appendDocumentHistoryUpdates,\n listDocumentHistoryTailEntries,\n loadDocumentHistoryRestoreState,\n readDocumentHistoryTailSize,\n replaceDocumentHistoryCheckpoint,\n} from \"../../../sqlite/documentHistoryPersistence\";\nimport {\n deleteDocumentPendingUpdate,\n deleteDocumentPendingUpdates,\n enqueueDocumentPendingUpdateWithHistory,\n listDocumentPendingUpdates,\n rekeyDocumentPendingUpdate,\n} from \"../../../sqlite/documentPersistence\";\nimport {\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n} from \"../../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../sqlite/sqlitePersistenceRuntime\";\nimport { runSerializedSqlMutation } from \"../../../sqlite/sqlSchema\";\nimport type { DocumentsPersistence } from \"../types\";\nimport {\n buildPendingAttachmentRow,\n mapLocalAttachmentRecord,\n mapPendingAttachmentRecord,\n} from \"./attachmentRows\";\nimport { getDocumentScope } from \"./documentRows\";\nimport { queueDocumentAttachmentStorageKeys } from \"./orphanSideRows\";\n\ntype DocumentSyncQueuePersistence = Pick<\n DocumentsPersistence,\n | \"listPendingUpdates\"\n | \"rekeyPendingUpdate\"\n | \"listPendingAttachments\"\n | \"listLocalAttachments\"\n | \"appendHistoryUpdates\"\n | \"loadHistoryRestoreState\"\n | \"readHistoryTailSize\"\n | \"listHistoryTailEntries\"\n | \"replaceHistoryCheckpoint\"\n | \"enqueuePendingUpdate\"\n | \"saveLocalAttachment\"\n | \"deleteLocalAttachment\"\n | \"markLocalAttachmentDetached\"\n | \"savePendingAttachment\"\n | \"deletePendingUpdate\"\n | \"deletePendingUpdates\"\n | \"deletePendingAttachment\"\n | \"deletePendingAttachments\"\n>;\n\nexport const documentSyncQueuePersistence: DocumentSyncQueuePersistence = {\n async listPendingUpdates(execSql, localId) {\n return listDocumentPendingUpdates(execSql, getDocumentScope(localId));\n },\n async rekeyPendingUpdate(execSql, id) {\n return rekeyDocumentPendingUpdate(execSql, id);\n },\n async listPendingAttachments(execSql, localId) {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n localId: documentPendingAttachments.localId,\n slotId: documentPendingAttachments.slotId,\n name: documentPendingAttachments.name,\n mimeType: documentPendingAttachments.mimeType,\n storageKey: documentPendingAttachments.storageKey,\n byteLength: documentPendingAttachments.byteLength,\n contentSha256: documentPendingAttachments.contentSha256,\n uploadBlobId: documentPendingAttachments.uploadBlobId,\n uploadContentKey: documentPendingAttachments.uploadContentKey,\n uploadIv: documentPendingAttachments.uploadIv,\n uploadContentKeyEpoch: documentPendingAttachments.uploadContentKeyEpoch,\n uploadPartSize: documentPendingAttachments.uploadPartSize,\n uploadPlaintextSha256: documentPendingAttachments.uploadPlaintextSha256,\n uploadStageId: documentPendingAttachments.uploadStageId,\n })\n .from(documentPendingAttachments)\n .where(eq(documentPendingAttachments.localId, localId))\n .orderBy(\n documentPendingAttachments.createdAt,\n documentPendingAttachments.slotId,\n );\n\n return rows.map(mapPendingAttachmentRecord);\n },\n // Detached rows are included on purpose: they are the durable markers the\n // next sync uses to detach the remote binding, so a restart has to restore\n // them alongside the live slots.\n async listLocalAttachments(execSql, localId) {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n localId: documentAttachmentBlobProjection.localId,\n slotId: documentAttachmentBlobProjection.slotId,\n blobId: documentAttachmentBlobProjection.blobId,\n storageKey: documentAttachmentBlobProjection.storageKey,\n mimeType: documentAttachmentBlobProjection.mimeType,\n byteLength: documentAttachmentBlobProjection.byteLength,\n contentSha256: documentAttachmentBlobProjection.contentSha256,\n detachedAt: documentAttachmentBlobProjection.detachedAt,\n })\n .from(documentAttachmentBlobProjection)\n .where(eq(documentAttachmentBlobProjection.localId, localId));\n\n return rows.map(mapLocalAttachmentRecord);\n },\n async appendHistoryUpdates(execSql, input) {\n await appendDocumentHistoryUpdates(\n execSql,\n getDocumentScope(input.localId),\n input.updates,\n input.origin,\n );\n },\n async loadHistoryRestoreState(execSql, localId) {\n return loadDocumentHistoryRestoreState(execSql, getDocumentScope(localId));\n },\n async readHistoryTailSize(execSql, localId) {\n return readDocumentHistoryTailSize(execSql, getDocumentScope(localId));\n },\n async listHistoryTailEntries(execSql, localId) {\n return listDocumentHistoryTailEntries(execSql, getDocumentScope(localId));\n },\n async replaceHistoryCheckpoint(execSql, input) {\n await replaceDocumentHistoryCheckpoint(\n execSql,\n getDocumentScope(input.localId),\n {\n coveredTailIds: input.coveredTailIds,\n endVersionVector: input.endVersionVector,\n ...(input.force === undefined ? {} : { force: input.force }),\n snapshot: input.snapshot,\n ...(input.stillCurrent === undefined\n ? {}\n : { stillCurrent: input.stillCurrent }),\n },\n );\n },\n async enqueuePendingUpdate(execSql, pendingUpdate, options) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const pendingUpdateId = await enqueueDocumentPendingUpdateWithHistory(\n lockedExecSql,\n getDocumentScope(pendingUpdate.localId),\n pendingUpdate,\n options,\n );\n return pendingUpdateId !== null;\n });\n },\n async saveLocalAttachment(execSql, attachment) {\n const updatedAt = new Date().toISOString();\n\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n const attachmentRow = {\n localId: attachment.localId,\n slotId: attachment.slotId,\n blobId: attachment.blobId,\n storageKey: attachment.storageKey,\n mimeType: attachment.mimeType,\n byteLength: attachment.byteLength,\n contentSha256: attachment.contentSha256,\n updatedAt,\n // Written on every save so re-filling a slot clears a stale detach\n // marker instead of inheriting it from the row it replaces.\n detachedAt: attachment.detachedAt,\n };\n await db\n .insert(documentAttachmentBlobProjection)\n .values(attachmentRow)\n .onConflictDoUpdate({\n target: [\n documentAttachmentBlobProjection.localId,\n documentAttachmentBlobProjection.slotId,\n ],\n set: attachmentRow,\n })\n .run();\n });\n },\n async deleteLocalAttachment(execSql, localId, slotId, storageKey) {\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (db) => {\n await db\n .delete(documentAttachmentBlobProjection)\n .where(\n and(\n eq(documentAttachmentBlobProjection.localId, localId),\n eq(documentAttachmentBlobProjection.slotId, slotId),\n eq(documentAttachmentBlobProjection.storageKey, storageKey),\n ),\n )\n .run();\n // Another slot may hold the same hydrated copy; the reclaim deletes\n // the bytes only once no row references them.\n await queueDocumentAttachmentStorageKeys(db, [storageKey]);\n });\n },\n async markLocalAttachmentDetached(execSql, localId, slotId, storageKey) {\n const detachedAt = new Date().toISOString();\n\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .update(documentAttachmentBlobProjection)\n .set({ detachedAt })\n .where(\n and(\n eq(documentAttachmentBlobProjection.localId, localId),\n eq(documentAttachmentBlobProjection.slotId, slotId),\n eq(documentAttachmentBlobProjection.storageKey, storageKey),\n isNull(documentAttachmentBlobProjection.detachedAt),\n ),\n )\n .run();\n });\n },\n async savePendingAttachment(execSql, attachment) {\n const createdAt = new Date().toISOString();\n\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n const attachmentRow = buildPendingAttachmentRow(attachment, createdAt);\n await db\n .insert(documentPendingAttachments)\n .values(attachmentRow)\n .onConflictDoUpdate({\n target: [\n documentPendingAttachments.localId,\n documentPendingAttachments.slotId,\n ],\n set: {\n name: attachmentRow.name,\n mimeType: attachmentRow.mimeType,\n storageKey: attachmentRow.storageKey,\n byteLength: attachmentRow.byteLength,\n contentSha256: attachmentRow.contentSha256,\n uploadBlobId: attachmentRow.uploadBlobId,\n uploadContentKey: attachmentRow.uploadContentKey,\n uploadIv: attachmentRow.uploadIv,\n uploadContentKeyEpoch: attachmentRow.uploadContentKeyEpoch,\n uploadPartSize: attachmentRow.uploadPartSize,\n uploadPlaintextSha256: attachmentRow.uploadPlaintextSha256,\n uploadStageId: attachmentRow.uploadStageId,\n },\n })\n .run();\n });\n },\n async deletePendingUpdate(execSql, id) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await deleteDocumentPendingUpdate(lockedExecSql, id);\n });\n },\n async deletePendingUpdates(execSql, localId) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await deleteDocumentPendingUpdates(\n lockedExecSql,\n getDocumentScope(localId),\n );\n });\n },\n async deletePendingAttachment(execSql, localId, slotId, storageKey) {\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (db) => {\n await db\n .delete(documentPendingAttachments)\n .where(\n and(\n eq(documentPendingAttachments.localId, localId),\n eq(documentPendingAttachments.slotId, slotId),\n eq(documentPendingAttachments.storageKey, storageKey),\n ),\n )\n .run();\n // A dropped upload may hold the last reference to its staged bytes.\n await queueDocumentAttachmentStorageKeys(db, [storageKey]);\n });\n },\n async deletePendingAttachments(execSql, localId) {\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (db) => {\n const deleted = await db\n .delete(documentPendingAttachments)\n .where(eq(documentPendingAttachments.localId, localId))\n .returning({ storageKey: documentPendingAttachments.storageKey });\n await queueDocumentAttachmentStorageKeys(\n db,\n deleted.map(({ storageKey }) => storageKey),\n );\n });\n },\n};\n"]}
|
|
1
|
+
{"version":3,"file":"syncQueuePersistence.js","sourceRoot":"","sources":["syncQueuePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, isNull } from \"drizzle-orm\";\nimport {\n appendDocumentHistoryUpdates,\n listDocumentHistoryTailEntries,\n loadDocumentHistoryRestoreState,\n readDocumentHistoryTailSize,\n replaceDocumentHistoryCheckpoint,\n} from \"../../../sqlite/documentHistoryPersistence\";\nimport {\n enqueueDocumentPendingUpdateWithHistory,\n listDocumentPendingUpdates,\n rekeyDocumentPendingUpdate,\n settleDocumentPendingUpdate,\n unqueueDocumentPendingUpdates,\n} from \"../../../sqlite/documentPersistence\";\nimport {\n documentAttachmentBlobProjection,\n documentPendingAttachments,\n} from \"../../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../sqlite/sqlitePersistenceRuntime\";\nimport { runSerializedSqlMutation } from \"../../../sqlite/sqlSchema\";\nimport type { DocumentsPersistence } from \"../types\";\nimport {\n buildPendingAttachmentRow,\n mapLocalAttachmentRecord,\n mapPendingAttachmentRecord,\n} from \"./attachmentRows\";\nimport { getDocumentScope } from \"./documentRows\";\nimport { queueDocumentAttachmentStorageKeys } from \"./orphanSideRows\";\n\ntype DocumentSyncQueuePersistence = Pick<\n DocumentsPersistence,\n | \"listPendingUpdates\"\n | \"rekeyPendingUpdate\"\n | \"listPendingAttachments\"\n | \"listLocalAttachments\"\n | \"appendHistoryUpdates\"\n | \"loadHistoryRestoreState\"\n | \"readHistoryTailSize\"\n | \"listHistoryTailEntries\"\n | \"replaceHistoryCheckpoint\"\n | \"enqueuePendingUpdate\"\n | \"saveLocalAttachment\"\n | \"deleteLocalAttachment\"\n | \"markLocalAttachmentDetached\"\n | \"savePendingAttachment\"\n | \"deletePendingUpdate\"\n | \"deletePendingUpdates\"\n | \"deletePendingAttachment\"\n | \"deletePendingAttachments\"\n>;\n\nexport const documentSyncQueuePersistence: DocumentSyncQueuePersistence = {\n async listPendingUpdates(execSql, localId) {\n return listDocumentPendingUpdates(execSql, getDocumentScope(localId));\n },\n async rekeyPendingUpdate(execSql, id) {\n return rekeyDocumentPendingUpdate(execSql, id);\n },\n async listPendingAttachments(execSql, localId) {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n localId: documentPendingAttachments.localId,\n slotId: documentPendingAttachments.slotId,\n name: documentPendingAttachments.name,\n mimeType: documentPendingAttachments.mimeType,\n storageKey: documentPendingAttachments.storageKey,\n byteLength: documentPendingAttachments.byteLength,\n contentSha256: documentPendingAttachments.contentSha256,\n uploadBlobId: documentPendingAttachments.uploadBlobId,\n uploadContentKey: documentPendingAttachments.uploadContentKey,\n uploadIv: documentPendingAttachments.uploadIv,\n uploadContentKeyEpoch: documentPendingAttachments.uploadContentKeyEpoch,\n uploadPartSize: documentPendingAttachments.uploadPartSize,\n uploadPlaintextSha256: documentPendingAttachments.uploadPlaintextSha256,\n uploadStageId: documentPendingAttachments.uploadStageId,\n })\n .from(documentPendingAttachments)\n .where(eq(documentPendingAttachments.localId, localId))\n .orderBy(\n documentPendingAttachments.createdAt,\n documentPendingAttachments.slotId,\n );\n\n return rows.map(mapPendingAttachmentRecord);\n },\n // Detached rows are included on purpose: they are the durable markers the\n // next sync uses to detach the remote binding, so a restart has to restore\n // them alongside the live slots.\n async listLocalAttachments(execSql, localId) {\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n localId: documentAttachmentBlobProjection.localId,\n slotId: documentAttachmentBlobProjection.slotId,\n blobId: documentAttachmentBlobProjection.blobId,\n storageKey: documentAttachmentBlobProjection.storageKey,\n mimeType: documentAttachmentBlobProjection.mimeType,\n byteLength: documentAttachmentBlobProjection.byteLength,\n contentSha256: documentAttachmentBlobProjection.contentSha256,\n detachedAt: documentAttachmentBlobProjection.detachedAt,\n })\n .from(documentAttachmentBlobProjection)\n .where(eq(documentAttachmentBlobProjection.localId, localId));\n\n return rows.map(mapLocalAttachmentRecord);\n },\n async appendHistoryUpdates(execSql, input) {\n await appendDocumentHistoryUpdates(\n execSql,\n getDocumentScope(input.localId),\n input.updates,\n input.origin,\n );\n },\n async loadHistoryRestoreState(execSql, localId) {\n return loadDocumentHistoryRestoreState(execSql, getDocumentScope(localId));\n },\n async readHistoryTailSize(execSql, localId) {\n return readDocumentHistoryTailSize(execSql, getDocumentScope(localId));\n },\n async listHistoryTailEntries(execSql, localId) {\n return listDocumentHistoryTailEntries(execSql, getDocumentScope(localId));\n },\n async replaceHistoryCheckpoint(execSql, input) {\n await replaceDocumentHistoryCheckpoint(\n execSql,\n getDocumentScope(input.localId),\n {\n coveredTailIds: input.coveredTailIds,\n endVersionVector: input.endVersionVector,\n ...(input.force === undefined ? {} : { force: input.force }),\n snapshot: input.snapshot,\n ...(input.stillCurrent === undefined\n ? {}\n : { stillCurrent: input.stillCurrent }),\n },\n );\n },\n async enqueuePendingUpdate(execSql, pendingUpdate, options) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const pendingUpdateId = await enqueueDocumentPendingUpdateWithHistory(\n lockedExecSql,\n getDocumentScope(pendingUpdate.localId),\n pendingUpdate,\n options,\n );\n return pendingUpdateId !== null;\n });\n },\n async saveLocalAttachment(execSql, attachment) {\n const updatedAt = new Date().toISOString();\n\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n const attachmentRow = {\n localId: attachment.localId,\n slotId: attachment.slotId,\n blobId: attachment.blobId,\n storageKey: attachment.storageKey,\n mimeType: attachment.mimeType,\n byteLength: attachment.byteLength,\n contentSha256: attachment.contentSha256,\n updatedAt,\n // Written on every save so re-filling a slot clears a stale detach\n // marker instead of inheriting it from the row it replaces.\n detachedAt: attachment.detachedAt,\n };\n await db\n .insert(documentAttachmentBlobProjection)\n .values(attachmentRow)\n .onConflictDoUpdate({\n target: [\n documentAttachmentBlobProjection.localId,\n documentAttachmentBlobProjection.slotId,\n ],\n set: attachmentRow,\n })\n .run();\n });\n },\n async deleteLocalAttachment(execSql, localId, slotId, storageKey) {\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (db) => {\n await db\n .delete(documentAttachmentBlobProjection)\n .where(\n and(\n eq(documentAttachmentBlobProjection.localId, localId),\n eq(documentAttachmentBlobProjection.slotId, slotId),\n eq(documentAttachmentBlobProjection.storageKey, storageKey),\n ),\n )\n .run();\n // Another slot may hold the same hydrated copy; the reclaim deletes\n // the bytes only once no row references them.\n await queueDocumentAttachmentStorageKeys(db, [storageKey]);\n });\n },\n async markLocalAttachmentDetached(execSql, localId, slotId, storageKey) {\n const detachedAt = new Date().toISOString();\n\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n await db\n .update(documentAttachmentBlobProjection)\n .set({ detachedAt })\n .where(\n and(\n eq(documentAttachmentBlobProjection.localId, localId),\n eq(documentAttachmentBlobProjection.slotId, slotId),\n eq(documentAttachmentBlobProjection.storageKey, storageKey),\n isNull(documentAttachmentBlobProjection.detachedAt),\n ),\n )\n .run();\n });\n },\n async savePendingAttachment(execSql, attachment) {\n const createdAt = new Date().toISOString();\n\n await getClientSQLitePersistenceRuntime(execSql).runMutation(async (db) => {\n const attachmentRow = buildPendingAttachmentRow(attachment, createdAt);\n await db\n .insert(documentPendingAttachments)\n .values(attachmentRow)\n .onConflictDoUpdate({\n target: [\n documentPendingAttachments.localId,\n documentPendingAttachments.slotId,\n ],\n set: {\n name: attachmentRow.name,\n mimeType: attachmentRow.mimeType,\n storageKey: attachmentRow.storageKey,\n byteLength: attachmentRow.byteLength,\n contentSha256: attachmentRow.contentSha256,\n uploadBlobId: attachmentRow.uploadBlobId,\n uploadContentKey: attachmentRow.uploadContentKey,\n uploadIv: attachmentRow.uploadIv,\n uploadContentKeyEpoch: attachmentRow.uploadContentKeyEpoch,\n uploadPartSize: attachmentRow.uploadPartSize,\n uploadPlaintextSha256: attachmentRow.uploadPlaintextSha256,\n uploadStageId: attachmentRow.uploadStageId,\n },\n })\n .run();\n });\n },\n async deletePendingUpdate(execSql, id) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await settleDocumentPendingUpdate(lockedExecSql, id);\n });\n },\n async deletePendingUpdates(execSql, localId) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await unqueueDocumentPendingUpdates(\n lockedExecSql,\n getDocumentScope(localId),\n );\n });\n },\n async deletePendingAttachment(execSql, localId, slotId, storageKey) {\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (db) => {\n await db\n .delete(documentPendingAttachments)\n .where(\n and(\n eq(documentPendingAttachments.localId, localId),\n eq(documentPendingAttachments.slotId, slotId),\n eq(documentPendingAttachments.storageKey, storageKey),\n ),\n )\n .run();\n // A dropped upload may hold the last reference to its staged bytes.\n await queueDocumentAttachmentStorageKeys(db, [storageKey]);\n });\n },\n async deletePendingAttachments(execSql, localId) {\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (db) => {\n const deleted = await db\n .delete(documentPendingAttachments)\n .where(eq(documentPendingAttachments.localId, localId))\n .returning({ storageKey: documentPendingAttachments.storageKey });\n await queueDocumentAttachmentStorageKeys(\n db,\n deleted.map(({ storageKey }) => storageKey),\n );\n });\n },\n};\n"]}
|
|
@@ -2,12 +2,14 @@ import { KeyingVerificationError, verifyAccessManifestLocalCheckpoint, verifyPri
|
|
|
2
2
|
import { keyingCheckpointTables, principalPolicyTables, } from "../sqlite/schema.js";
|
|
3
3
|
import { getClientSQLitePersistenceRuntime, } from "../sqlite/sqlitePersistenceRuntime.js";
|
|
4
4
|
import { ensureSqlTables } from "../sqlite/sqlSchema.js";
|
|
5
|
+
import { verifiedManifestBundleTables } from "../sqlite/verifiedManifestBundleSchema.js";
|
|
5
6
|
import { storeDocumentPurgeCheckpointInTransaction, } from "./documentPurgeCheckpointPersistence.js";
|
|
6
7
|
import { validateAccessManifestCheckpointEvidence } from "./keyingCheckpointEvidence.js";
|
|
7
8
|
import { accessManifestObjectKey, loadStoredAccessManifestCheckpoint, loadStoredPrincipalPolicyCheckpoint, principalPolicyKey, upsertAccessManifestCheckpointInTransaction, upsertPrincipalPolicyCheckpointInTransaction, } from "./keyingCheckpointPersistence.js";
|
|
8
9
|
import { validatePrincipalAuthorizationCheckpoints } from "./principalAuthorizationCheckpoints.js";
|
|
9
10
|
import { assertContainerNotRetired } from "./principalGrantRetirementPersistence.js";
|
|
10
11
|
import { assertPrincipalPolicyBundleStoredInTransaction, writePrincipalPolicyBundleInTransaction, } from "./principalPolicyPersistence.js";
|
|
12
|
+
import { verifiedManifestBundleRows, writeVerifiedManifestBundlesInTransaction, } from "./verifiedManifestBundlePersistence.js";
|
|
11
13
|
import { assertBundleMatchesVerifiedPolicy } from "./verifiedPrincipalPolicyBundle.js";
|
|
12
14
|
function validateAccessAdvance(advance, localCheckpoint) {
|
|
13
15
|
const current = {
|
|
@@ -106,18 +108,34 @@ async function writePolicyCheckpoints(tx, pending, updatedAt, organizationId) {
|
|
|
106
108
|
await upsertPrincipalPolicyCheckpointInTransaction(tx, policy.checkpoint, updatedAt, organizationId);
|
|
107
109
|
}
|
|
108
110
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Digests the verified bundles and ensures every table the batch touches,
|
|
113
|
+
* all before its transaction begins.
|
|
114
|
+
*/
|
|
115
|
+
async function prepareKeyingCheckpointBatch(input) {
|
|
116
|
+
const bundleRows = await verifiedManifestBundleRows(input.verifiedBundles ?? []);
|
|
117
|
+
await ensureSqlTables(input.execSql, [
|
|
118
|
+
...(input.policies.length > 0 ||
|
|
119
|
+
(input.authorizationPolicies?.length ?? 0) > 0
|
|
120
|
+
? principalPolicyTables
|
|
121
|
+
: []),
|
|
122
|
+
...keyingCheckpointTables,
|
|
123
|
+
...(bundleRows.length > 0 ? verifiedManifestBundleTables : []),
|
|
124
|
+
]);
|
|
125
|
+
return bundleRows;
|
|
113
126
|
}
|
|
114
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* Re-checks verified candidates against durable pins without advancing them.
|
|
129
|
+
* Only the verified bundles' citation rows are written.
|
|
130
|
+
*/
|
|
115
131
|
export async function validateKeyingCheckpointsAtomically(input) {
|
|
116
|
-
await
|
|
132
|
+
const bundleRows = await prepareKeyingCheckpointBatch(input);
|
|
133
|
+
const verifiedAt = new Date().toISOString();
|
|
117
134
|
const validate = async (tx) => {
|
|
118
135
|
await validateAccessAdvances(tx, input.access);
|
|
119
136
|
await validatePolicyAdvances(tx, input.policies);
|
|
120
137
|
await validatePrincipalAuthorizationCheckpoints(tx, input.authorizationPolicies ?? []);
|
|
138
|
+
await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, verifiedAt);
|
|
121
139
|
};
|
|
122
140
|
const runtime = getClientSQLitePersistenceRuntime(input.execSql);
|
|
123
141
|
if (input.stillCurrent) {
|
|
@@ -132,10 +150,10 @@ export async function validateKeyingCheckpointsAtomically(input) {
|
|
|
132
150
|
* Re-check every verified projection candidate against the latest durable pins
|
|
133
151
|
* and advance the complete batch atomically. Signature verification and remote
|
|
134
152
|
* fetching happen before this short transaction; only checkpoint comparison
|
|
135
|
-
* and persistence are serialized here.
|
|
153
|
+
* and persistence, with the batch's verified bundles, are serialized here.
|
|
136
154
|
*/
|
|
137
155
|
export async function advanceKeyingCheckpointsAtomically(input) {
|
|
138
|
-
await
|
|
156
|
+
const bundleRows = await prepareKeyingCheckpointBatch(input);
|
|
139
157
|
const updatedAt = new Date().toISOString();
|
|
140
158
|
const runtime = getClientSQLitePersistenceRuntime(input.execSql);
|
|
141
159
|
const advance = async (tx) => {
|
|
@@ -147,6 +165,7 @@ export async function advanceKeyingCheckpointsAtomically(input) {
|
|
|
147
165
|
if (input.documentPurgeCheckpoint) {
|
|
148
166
|
await storeDocumentPurgeCheckpointInTransaction(tx, input.documentPurgeCheckpoint, updatedAt);
|
|
149
167
|
}
|
|
168
|
+
await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, updatedAt);
|
|
150
169
|
};
|
|
151
170
|
if (input.stillCurrent) {
|
|
152
171
|
await runtime.guardedTransaction(advance, input.stillCurrent, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyingCheckpointAdvancePersistence.js","sourceRoot":"","sources":["keyingCheckpointAdvancePersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,uBAAuB,EAKvB,mCAAmC,EACnC,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,iCAAiC,GAClC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAgB,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAEL,yCAAyC,GAC1C,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,wCAAwC,EAAE,MAAM,4BAA4B,CAAC;AACtF,OAAO,EACL,uBAAuB,EACvB,kCAAkC,EAClC,mCAAmC,EACnC,kBAAkB,EAClB,2CAA2C,EAC3C,4CAA4C,GAC7C,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yCAAyC,EAAE,MAAM,qCAAqC,CAAC;AAChG,OAAO,EAAE,yBAAyB,EAAE,MAAM,uCAAuC,CAAC;AAClF,OAAO,EACL,8CAA8C,EAC9C,uCAAuC,GACxC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AA8BpF,SAAS,qBAAqB,CAC5B,OAAwC,EACxC,eAAgD;IAEhD,MAAM,OAAO,GAAG;QACd,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU;QAC1B,oBAAoB,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB;KACjE,CAAC;IACF,MAAM,YAAY,GAAG,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CACjD,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,KAAK,CAChE,CAAC;IAEF,IAAI,eAAe,IAAI,OAAO,CAAC,KAAK,IAAI,eAAe,CAAC,KAAK,EAAE,CAAC;QAC9D,mCAAmC,CAAC;YAClC,OAAO;YACP,eAAe;YACf,sBAAsB,EAAE,SAAS;SAClC,CAAC,CAAC;IACL,CAAC;IAED,wCAAwC,CAAC;QACvC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,YAAY;QACZ,eAAe;KAChB,CAAC,CAAC;IAEH,mCAAmC,CAAC;QAClC,OAAO;QACP,eAAe;QACf,sBAAsB,EAAE,YAAY,CAAC,MAAM,CACzC,CAAC,QAAQ,EAAE,EAAE,CACX,eAAe,KAAK,IAAI;YACxB,QAAQ,CAAC,UAAU,CAAC,KAAK,GAAG,eAAe,CAAC,KAAK;YACjD,QAAQ,CAAC,UAAU,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAC5C;KACF,CAAC,CAAC;IAEH,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU;KACpC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,EAAgC,EAChC,QAAoD;IAEpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmC,CAAC;IAE3D,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,yBAAyB,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7D,MAAM,GAAG,GAAG,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7D,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,uBAAuB,CAC/B,cAAc,EACd,4DAA4D,GAAG,EAAE,CAClE,CAAC;QACJ,CAAC;QACD,MAAM,eAAe,GAAG,MAAM,kCAAkC,CAC9D,EAAE,EACF,OAAO,CAAC,IAAI,CAAC,UAAU,CACxB,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,qBAAqB,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAAsB,EACtB,SAA2B;IAE3B,MAAM,OAAO,GACX,iBAAiB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;IAClE,OAAO,CACL,OAAO,EAAE,IAAI,CACX,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CACZ,KAAK,CAAC,aAAa,KAAK,SAAS,CAAC,aAAa;QAC/C,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW;QAC3C,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,OAAO;QACnC,KAAK,CAAC,SAAS,KAAK,SAAS,CAAC,SAAS,CAC1C,IAAI,KAAK,CACX,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,EAAgC,EAChC,QAAqC;IAErC,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAA8B,CAAC;IAClE,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,UAAU,GAAG,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACtD,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAA4B,CAAC;IACpD,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACzD,MAAM,UAAU,GAAG,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC3E,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,KAAK,UAAU,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACtE,MAAM,IAAI,uBAAuB,CAC/B,cAAc,EACd,mDAAmD,GAAG,EAAE,CACzD,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,SAAS,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;gBACvC,SAAS;YACX,CAAC;YACD,IAAI,CAAC,qBAAqB,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;gBAC5C,MAAM,IAAI,uBAAuB,CAC/B,mBAAmB,EACnB,4DAA4D,GAAG,EAAE,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,eAAe,GAAG,MAAM,mCAAmC,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC5E,+BAA+B,CAAC;YAC9B,KAAK,EACH,iBAAiB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;YACzE,YAAY,EAAE,IAAI,CAAC,KAAK;YACxB,eAAe;SAChB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,EAAgC,EAChC,OAAqD,EACrD,SAAiB;IAEjB,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,MAAM,2CAA2C,CAC/C,EAAE,EACF,UAAU,EACV,SAAS,CACV,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,sBAAsB,CACnC,EAAgC,EAChC,OAA8C,EAC9C,SAAiB,EACjB,cAAmC;IAEnC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;QACtC,MAAM,4CAA4C,CAChD,EAAE,EACF,MAAM,CAAC,UAAU,EACjB,SAAS,EACT,cAAc,CACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,sCAAsC,CACnD,KAAsC;IAEtC,MAAM,eAAe,CACnB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,qBAAqB,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;QACzE,CAAC,CAAC,CAAC,GAAG,qBAAqB,EAAE,GAAG,sBAAsB,CAAC;QACvD,CAAC,CAAC,sBAAsB,CAC3B,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,KAAsC;IAEtC,MAAM,sCAAsC,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,KAAK,EAAE,EAAgC,EAAE,EAAE;QAC1D,MAAM,sBAAsB,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,sBAAsB,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACjD,MAAM,yCAAyC,CAC7C,EAAE,EACF,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAClC,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,OAAO,CAAC,kBAAkB,CAAC,QAAQ,EAAE,KAAK,CAAC,YAAY,EAAE;YAC7D,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,MAAM,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;AACjE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kCAAkC,CAAC,KAUxD;IACC,MAAM,sCAAsC,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE3C,MAAM,OAAO,GAAG,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,KAAK,EAAE,EAAgC,EAAE,EAAE;QACzD,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAAC,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClE,MAAM,yCAAyC,CAC7C,EAAE,EACF,KAAK,CAAC,qBAAqB,IAAI,EAAE,CAClC,CAAC;QAEF,MAAM,sBAAsB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QACpD,MAAM,sBAAsB,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;QAC5E,IAAI,KAAK,CAAC,uBAAuB,EAAE,CAAC;YAClC,MAAM,yCAAyC,CAC7C,EAAE,EACF,KAAK,CAAC,uBAAuB,EAC7B,SAAS,CACV,CAAC;QACJ,CAAC;IACH,CAAC,CAAC;IACF,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,OAAO,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,EAAE;YAC5D,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,+CAA+C,CAAC,KAMrE;IACC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,wCAAwC,GAAG,EAAE,CAC9C,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,CAAC;IACD,MAAM,OAAO,CAAC,GAAG,CACf,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iCAAiC,CAAC,KAAK,CAAC,CAAC,CACvE,CAAC;IACF,MAAM,eAAe,CAAC,KAAK,CAAC,OAAO,EAAE;QACnC,GAAG,qBAAqB;QACxB,GAAG,sBAAsB;KAC1B,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,KAAK,EAAE,EAAgC,EAAE,EAAE;QACzD,MAAM,QAAQ,GAAG,MAAM,sBAAsB,CAC3C,EAAE,EACF,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAC3C,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClC,MAAM,uCAAuC,CAC3C,EAAE,EACF,KAAK,CAAC,MAAM,EACZ,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,cAAc,CACrB,CAAC;YACF,MAAM,8CAA8C,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,sBAAsB,CAC1B,EAAE,EACF,QAAQ,EACR,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,cAAc,CACrB,CAAC;QACF,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,MAAM,mCAAmC,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACzE,IACE,CAAC,UAAU;gBACX,UAAU,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO;gBACrC,UAAU,CAAC,SAAS,KAAK,MAAM,CAAC,SAAS,EACzC,CAAC;gBACD,MAAM,IAAI,KAAK,CACb,wDAAwD,CACzD,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,KAAK,CAAC,YAAY,EAAE,CAAC;QACvB,MAAM,OAAO,CAAC,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,EAAE;YAC5D,QAAQ,EAAE,WAAW;SACtB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,MAAM,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAAC;AAChE,CAAC","sourcesContent":["import {\n type AccessManifestCheckpoint,\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n type VerifiedAccessManifestCheckpointEvidence,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n type VerifiedPrincipalPolicySelection,\n verifyAccessManifestLocalCheckpoint,\n verifyPrincipalPolicyCheckpoint,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport {\n keyingCheckpointTables,\n principalPolicyTables,\n} from \"../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport {\n type DocumentPurgeCheckpoint,\n storeDocumentPurgeCheckpointInTransaction,\n} from \"./documentPurgeCheckpointPersistence\";\nimport { validateAccessManifestCheckpointEvidence } from \"./keyingCheckpointEvidence\";\nimport {\n accessManifestObjectKey,\n loadStoredAccessManifestCheckpoint,\n loadStoredPrincipalPolicyCheckpoint,\n principalPolicyKey,\n upsertAccessManifestCheckpointInTransaction,\n upsertPrincipalPolicyCheckpointInTransaction,\n} from \"./keyingCheckpointPersistence\";\nimport { validatePrincipalAuthorizationCheckpoints } from \"./principalAuthorizationCheckpoints\";\nimport { assertContainerNotRetired } from \"./principalGrantRetirementPersistence\";\nimport {\n assertPrincipalPolicyBundleStoredInTransaction,\n writePrincipalPolicyBundleInTransaction,\n} from \"./principalPolicyPersistence\";\nimport { assertBundleMatchesVerifiedPolicy } from \"./verifiedPrincipalPolicyBundle\";\n\nexport interface AccessManifestCheckpointAdvance {\n readonly head: VerifiedAccessManifestCheckpointEvidence;\n readonly predecessors: readonly VerifiedAccessManifestCheckpointEvidence[];\n}\n\ntype CheckpointPolicy =\n | AnyVerifiedPrincipalPolicy\n | VerifiedPrincipalPolicyCurrent;\n\ninterface KeyingCheckpointValidationInput {\n readonly access: readonly AccessManifestCheckpointAdvance[];\n readonly execSql: ExecSql;\n readonly policies: readonly CheckpointPolicy[];\n readonly authorizationPolicies?:\n | readonly VerifiedPrincipalPolicySelection[]\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\ninterface VerifiedPrincipalPolicyBundleEntry {\n readonly bundle: PrincipalPolicyBundleResponse;\n readonly policy: VerifiedPrincipalPolicy;\n}\n\ninterface PendingAccessCheckpoint {\n readonly checkpoint: AccessManifestCheckpoint;\n}\n\nfunction validateAccessAdvance(\n advance: AccessManifestCheckpointAdvance,\n localCheckpoint: AccessManifestCheckpoint | null,\n): PendingAccessCheckpoint {\n const current = {\n ...advance.head.checkpoint,\n previousManifestHash: advance.head.manifest.previousManifestHash,\n };\n const predecessors = [...advance.predecessors].sort(\n (left, right) => left.checkpoint.epoch - right.checkpoint.epoch,\n );\n\n if (localCheckpoint && current.epoch <= localCheckpoint.epoch) {\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: undefined,\n });\n }\n\n validateAccessManifestCheckpointEvidence({\n head: advance.head,\n predecessors,\n localCheckpoint,\n });\n\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: predecessors.filter(\n (manifest) =>\n localCheckpoint !== null &&\n manifest.checkpoint.epoch > localCheckpoint.epoch &&\n manifest.checkpoint.epoch < current.epoch,\n ),\n });\n\n return {\n checkpoint: advance.head.checkpoint,\n };\n}\n\nasync function validateAccessAdvances(\n tx: ClientSQLiteTransactionScope,\n advances: readonly AccessManifestCheckpointAdvance[],\n): Promise<Map<string, PendingAccessCheckpoint>> {\n const pending = new Map<string, PendingAccessCheckpoint>();\n\n for (const advance of advances) {\n await assertContainerNotRetired(tx, advance.head.checkpoint);\n const key = accessManifestObjectKey(advance.head.checkpoint);\n if (pending.has(key)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `projection declares multiple access checkpoint heads for ${key}`,\n );\n }\n const localCheckpoint = await loadStoredAccessManifestCheckpoint(\n tx,\n advance.head.checkpoint,\n );\n pending.set(key, validateAccessAdvance(advance, localCheckpoint));\n }\n\n return pending;\n}\n\nfunction extendsObservedPolicy(\n head: CheckpointPolicy,\n candidate: CheckpointPolicy,\n): boolean {\n const history =\n \"retainedHistory\" in head ? head.retainedHistory : head.history;\n return (\n history?.some(\n ({ state }) =>\n state.principalType === candidate.principalType &&\n state.principalId === candidate.principalId &&\n state.version === candidate.version &&\n state.stateHash === candidate.stateHash,\n ) ?? false\n );\n}\n\nasync function validatePolicyAdvances(\n tx: ClientSQLiteTransactionScope,\n policies: readonly CheckpointPolicy[],\n): Promise<Map<string, CheckpointPolicy>> {\n const policiesByPrincipal = new Map<string, CheckpointPolicy[]>();\n for (const policy of policies) {\n const key = principalPolicyKey(policy);\n const candidates = policiesByPrincipal.get(key) ?? [];\n candidates.push(policy);\n policiesByPrincipal.set(key, candidates);\n }\n\n const pending = new Map<string, CheckpointPolicy>();\n for (const key of [...policiesByPrincipal.keys()].sort()) {\n const candidates = policiesByPrincipal.get(key) ?? [];\n const maxVersion = Math.max(...candidates.map((policy) => policy.version));\n const heads = candidates.filter((policy) => policy.version === maxVersion);\n const head = heads[0];\n if (!head) {\n continue;\n }\n if (heads.some((candidate) => candidate.stateHash !== head.stateHash)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `principal policy declares conflicting heads for ${key}`,\n );\n }\n for (const candidate of candidates) {\n if (candidate.version === head.version) {\n continue;\n }\n if (!extendsObservedPolicy(head, candidate)) {\n throw new KeyingVerificationError(\n \"stale_predecessor\",\n `principal policy head does not extend observed state for ${key}`,\n );\n }\n }\n\n const localCheckpoint = await loadStoredPrincipalPolicyCheckpoint(tx, head);\n verifyPrincipalPolicyCheckpoint({\n chain:\n \"retainedHistory\" in head ? head.retainedHistory : (head.history ?? []),\n currentState: head.state,\n localCheckpoint,\n });\n pending.set(key, head);\n }\n\n return pending;\n}\n\nasync function writeAccessCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, PendingAccessCheckpoint>,\n updatedAt: string,\n): Promise<void> {\n for (const { checkpoint } of pending.values()) {\n await upsertAccessManifestCheckpointInTransaction(\n tx,\n checkpoint,\n updatedAt,\n );\n }\n}\n\nasync function writePolicyCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, CheckpointPolicy>,\n updatedAt: string,\n organizationId?: string | undefined,\n): Promise<void> {\n for (const policy of pending.values()) {\n await upsertPrincipalPolicyCheckpointInTransaction(\n tx,\n policy.checkpoint,\n updatedAt,\n organizationId,\n );\n }\n}\n\nasync function ensureKeyingCheckpointValidationTables(\n input: KeyingCheckpointValidationInput,\n): Promise<void> {\n await ensureSqlTables(\n input.execSql,\n input.policies.length > 0 || (input.authorizationPolicies?.length ?? 0) > 0\n ? [...principalPolicyTables, ...keyingCheckpointTables]\n : keyingCheckpointTables,\n );\n}\n\n/** Re-checks verified candidates against durable pins without advancing them. */\nexport async function validateKeyingCheckpointsAtomically(\n input: KeyingCheckpointValidationInput,\n): Promise<void> {\n await ensureKeyingCheckpointValidationTables(input);\n const validate = async (tx: ClientSQLiteTransactionScope) => {\n await validateAccessAdvances(tx, input.access);\n await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n if (input.stillCurrent) {\n await runtime.guardedTransaction(validate, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(validate, { behavior: \"immediate\" });\n}\n\n/**\n * Re-check every verified projection candidate against the latest durable pins\n * and advance the complete batch atomically. Signature verification and remote\n * fetching happen before this short transaction; only checkpoint comparison\n * and persistence are serialized here.\n */\nexport async function advanceKeyingCheckpointsAtomically(input: {\n readonly access: readonly AccessManifestCheckpointAdvance[];\n readonly documentPurgeCheckpoint?: DocumentPurgeCheckpoint | undefined;\n readonly execSql: ExecSql;\n readonly organizationId?: string | undefined;\n readonly policies: readonly CheckpointPolicy[];\n readonly authorizationPolicies?:\n | readonly VerifiedPrincipalPolicySelection[]\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<void> {\n await ensureKeyingCheckpointValidationTables(input);\n const updatedAt = new Date().toISOString();\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const advance = async (tx: ClientSQLiteTransactionScope) => {\n const access = await validateAccessAdvances(tx, input.access);\n const policies = await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n\n await writeAccessCheckpoints(tx, access, updatedAt);\n await writePolicyCheckpoints(tx, policies, updatedAt, input.organizationId);\n if (input.documentPurgeCheckpoint) {\n await storeDocumentPurgeCheckpointInTransaction(\n tx,\n input.documentPurgeCheckpoint,\n updatedAt,\n );\n }\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(advance, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(advance, { behavior: \"immediate\" });\n}\n\n/**\n * Persists each verified full policy bundle together with its durable head.\n * This prevents a crash or bundle-write failure from leaving a checkpoint\n * without the exact same-head payload and member-envelope evidence.\n */\nexport async function persistVerifiedPrincipalPolicyBundlesAtomically(input: {\n readonly entries: readonly VerifiedPrincipalPolicyBundleEntry[];\n readonly execSql: ExecSql;\n readonly organizationId?: string | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly updatedAt: string;\n}): Promise<void> {\n const seen = new Set<string>();\n for (const entry of input.entries) {\n const key = principalPolicyKey(entry.policy);\n if (seen.has(key)) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `verified policy bundle batch repeats ${key}`,\n );\n }\n seen.add(key);\n }\n await Promise.all(\n input.entries.map((entry) => assertBundleMatchesVerifiedPolicy(entry)),\n );\n await ensureSqlTables(input.execSql, [\n ...principalPolicyTables,\n ...keyingCheckpointTables,\n ]);\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const persist = async (tx: ClientSQLiteTransactionScope) => {\n const policies = await validatePolicyAdvances(\n tx,\n input.entries.map((entry) => entry.policy),\n );\n for (const entry of input.entries) {\n await writePrincipalPolicyBundleInTransaction(\n tx,\n entry.bundle,\n input.updatedAt,\n input.organizationId,\n );\n await assertPrincipalPolicyBundleStoredInTransaction(tx, entry.bundle);\n }\n await writePolicyCheckpoints(\n tx,\n policies,\n input.updatedAt,\n input.organizationId,\n );\n for (const policy of policies.values()) {\n const checkpoint = await loadStoredPrincipalPolicyCheckpoint(tx, policy);\n if (\n !checkpoint ||\n checkpoint.version !== policy.version ||\n checkpoint.stateHash !== policy.stateHash\n ) {\n throw new Error(\n \"Verified principal policy checkpoint was not persisted\",\n );\n }\n }\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(persist, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(persist, { behavior: \"immediate\" });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"keyingCheckpointAdvancePersistence.js","sourceRoot":"","sources":["keyingCheckpointAdvancePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n type VerifiedAccessManifestCheckpointEvidence,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n type VerifiedPrincipalPolicySelection,\n verifyAccessManifestLocalCheckpoint,\n verifyPrincipalPolicyCheckpoint,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport {\n keyingCheckpointTables,\n principalPolicyTables,\n} from \"../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport { verifiedManifestBundleTables } from \"../sqlite/verifiedManifestBundleSchema\";\nimport {\n type DocumentPurgeCheckpoint,\n storeDocumentPurgeCheckpointInTransaction,\n} from \"./documentPurgeCheckpointPersistence\";\nimport { validateAccessManifestCheckpointEvidence } from \"./keyingCheckpointEvidence\";\nimport {\n accessManifestObjectKey,\n loadStoredAccessManifestCheckpoint,\n loadStoredPrincipalPolicyCheckpoint,\n principalPolicyKey,\n upsertAccessManifestCheckpointInTransaction,\n upsertPrincipalPolicyCheckpointInTransaction,\n} from \"./keyingCheckpointPersistence\";\nimport { validatePrincipalAuthorizationCheckpoints } from \"./principalAuthorizationCheckpoints\";\nimport { assertContainerNotRetired } from \"./principalGrantRetirementPersistence\";\nimport {\n assertPrincipalPolicyBundleStoredInTransaction,\n writePrincipalPolicyBundleInTransaction,\n} from \"./principalPolicyPersistence\";\nimport {\n type VerifiedManifestBundle,\n type VerifiedManifestBundleRow,\n verifiedManifestBundleRows,\n writeVerifiedManifestBundlesInTransaction,\n} from \"./verifiedManifestBundlePersistence\";\nimport { assertBundleMatchesVerifiedPolicy } from \"./verifiedPrincipalPolicyBundle\";\n\nexport interface AccessManifestCheckpointAdvance {\n readonly head: VerifiedAccessManifestCheckpointEvidence;\n readonly predecessors: readonly VerifiedAccessManifestCheckpointEvidence[];\n}\n\ntype CheckpointPolicy =\n | AnyVerifiedPrincipalPolicy\n | VerifiedPrincipalPolicyCurrent;\n\ninterface KeyingCheckpointValidationInput {\n readonly access: readonly AccessManifestCheckpointAdvance[];\n readonly execSql: ExecSql;\n readonly policies: readonly CheckpointPolicy[];\n readonly authorizationPolicies?:\n | readonly VerifiedPrincipalPolicySelection[]\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n /**\n * Bundles this projection verified. They are stored for later citation in\n * the same transaction, so they commit only with the batch they verified.\n */\n readonly verifiedBundles?: readonly VerifiedManifestBundle[] | undefined;\n}\n\ninterface VerifiedPrincipalPolicyBundleEntry {\n readonly bundle: PrincipalPolicyBundleResponse;\n readonly policy: VerifiedPrincipalPolicy;\n}\n\ninterface PendingAccessCheckpoint {\n readonly checkpoint: AccessManifestCheckpoint;\n}\n\nfunction validateAccessAdvance(\n advance: AccessManifestCheckpointAdvance,\n localCheckpoint: AccessManifestCheckpoint | null,\n): PendingAccessCheckpoint {\n const current = {\n ...advance.head.checkpoint,\n previousManifestHash: advance.head.manifest.previousManifestHash,\n };\n const predecessors = [...advance.predecessors].sort(\n (left, right) => left.checkpoint.epoch - right.checkpoint.epoch,\n );\n\n if (localCheckpoint && current.epoch <= localCheckpoint.epoch) {\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: undefined,\n });\n }\n\n validateAccessManifestCheckpointEvidence({\n head: advance.head,\n predecessors,\n localCheckpoint,\n });\n\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: predecessors.filter(\n (manifest) =>\n localCheckpoint !== null &&\n manifest.checkpoint.epoch > localCheckpoint.epoch &&\n manifest.checkpoint.epoch < current.epoch,\n ),\n });\n\n return {\n checkpoint: advance.head.checkpoint,\n };\n}\n\nasync function validateAccessAdvances(\n tx: ClientSQLiteTransactionScope,\n advances: readonly AccessManifestCheckpointAdvance[],\n): Promise<Map<string, PendingAccessCheckpoint>> {\n const pending = new Map<string, PendingAccessCheckpoint>();\n\n for (const advance of advances) {\n await assertContainerNotRetired(tx, advance.head.checkpoint);\n const key = accessManifestObjectKey(advance.head.checkpoint);\n if (pending.has(key)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `projection declares multiple access checkpoint heads for ${key}`,\n );\n }\n const localCheckpoint = await loadStoredAccessManifestCheckpoint(\n tx,\n advance.head.checkpoint,\n );\n pending.set(key, validateAccessAdvance(advance, localCheckpoint));\n }\n\n return pending;\n}\n\nfunction extendsObservedPolicy(\n head: CheckpointPolicy,\n candidate: CheckpointPolicy,\n): boolean {\n const history =\n \"retainedHistory\" in head ? head.retainedHistory : head.history;\n return (\n history?.some(\n ({ state }) =>\n state.principalType === candidate.principalType &&\n state.principalId === candidate.principalId &&\n state.version === candidate.version &&\n state.stateHash === candidate.stateHash,\n ) ?? false\n );\n}\n\nasync function validatePolicyAdvances(\n tx: ClientSQLiteTransactionScope,\n policies: readonly CheckpointPolicy[],\n): Promise<Map<string, CheckpointPolicy>> {\n const policiesByPrincipal = new Map<string, CheckpointPolicy[]>();\n for (const policy of policies) {\n const key = principalPolicyKey(policy);\n const candidates = policiesByPrincipal.get(key) ?? [];\n candidates.push(policy);\n policiesByPrincipal.set(key, candidates);\n }\n\n const pending = new Map<string, CheckpointPolicy>();\n for (const key of [...policiesByPrincipal.keys()].sort()) {\n const candidates = policiesByPrincipal.get(key) ?? [];\n const maxVersion = Math.max(...candidates.map((policy) => policy.version));\n const heads = candidates.filter((policy) => policy.version === maxVersion);\n const head = heads[0];\n if (!head) {\n continue;\n }\n if (heads.some((candidate) => candidate.stateHash !== head.stateHash)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `principal policy declares conflicting heads for ${key}`,\n );\n }\n for (const candidate of candidates) {\n if (candidate.version === head.version) {\n continue;\n }\n if (!extendsObservedPolicy(head, candidate)) {\n throw new KeyingVerificationError(\n \"stale_predecessor\",\n `principal policy head does not extend observed state for ${key}`,\n );\n }\n }\n\n const localCheckpoint = await loadStoredPrincipalPolicyCheckpoint(tx, head);\n verifyPrincipalPolicyCheckpoint({\n chain:\n \"retainedHistory\" in head ? head.retainedHistory : (head.history ?? []),\n currentState: head.state,\n localCheckpoint,\n });\n pending.set(key, head);\n }\n\n return pending;\n}\n\nasync function writeAccessCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, PendingAccessCheckpoint>,\n updatedAt: string,\n): Promise<void> {\n for (const { checkpoint } of pending.values()) {\n await upsertAccessManifestCheckpointInTransaction(\n tx,\n checkpoint,\n updatedAt,\n );\n }\n}\n\nasync function writePolicyCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, CheckpointPolicy>,\n updatedAt: string,\n organizationId?: string | undefined,\n): Promise<void> {\n for (const policy of pending.values()) {\n await upsertPrincipalPolicyCheckpointInTransaction(\n tx,\n policy.checkpoint,\n updatedAt,\n organizationId,\n );\n }\n}\n\n/**\n * Digests the verified bundles and ensures every table the batch touches,\n * all before its transaction begins.\n */\nasync function prepareKeyingCheckpointBatch(\n input: KeyingCheckpointValidationInput,\n): Promise<VerifiedManifestBundleRow[]> {\n const bundleRows = await verifiedManifestBundleRows(\n input.verifiedBundles ?? [],\n );\n await ensureSqlTables(input.execSql, [\n ...(input.policies.length > 0 ||\n (input.authorizationPolicies?.length ?? 0) > 0\n ? principalPolicyTables\n : []),\n ...keyingCheckpointTables,\n ...(bundleRows.length > 0 ? verifiedManifestBundleTables : []),\n ]);\n return bundleRows;\n}\n\n/**\n * Re-checks verified candidates against durable pins without advancing them.\n * Only the verified bundles' citation rows are written.\n */\nexport async function validateKeyingCheckpointsAtomically(\n input: KeyingCheckpointValidationInput,\n): Promise<void> {\n const bundleRows = await prepareKeyingCheckpointBatch(input);\n const verifiedAt = new Date().toISOString();\n const validate = async (tx: ClientSQLiteTransactionScope) => {\n await validateAccessAdvances(tx, input.access);\n await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, verifiedAt);\n };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n if (input.stillCurrent) {\n await runtime.guardedTransaction(validate, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(validate, { behavior: \"immediate\" });\n}\n\n/**\n * Re-check every verified projection candidate against the latest durable pins\n * and advance the complete batch atomically. Signature verification and remote\n * fetching happen before this short transaction; only checkpoint comparison\n * and persistence, with the batch's verified bundles, are serialized here.\n */\nexport async function advanceKeyingCheckpointsAtomically(\n input: KeyingCheckpointValidationInput & {\n readonly documentPurgeCheckpoint?: DocumentPurgeCheckpoint | undefined;\n readonly organizationId?: string | undefined;\n },\n): Promise<void> {\n const bundleRows = await prepareKeyingCheckpointBatch(input);\n const updatedAt = new Date().toISOString();\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const advance = async (tx: ClientSQLiteTransactionScope) => {\n const access = await validateAccessAdvances(tx, input.access);\n const policies = await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n\n await writeAccessCheckpoints(tx, access, updatedAt);\n await writePolicyCheckpoints(tx, policies, updatedAt, input.organizationId);\n if (input.documentPurgeCheckpoint) {\n await storeDocumentPurgeCheckpointInTransaction(\n tx,\n input.documentPurgeCheckpoint,\n updatedAt,\n );\n }\n await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, updatedAt);\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(advance, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(advance, { behavior: \"immediate\" });\n}\n\n/**\n * Persists each verified full policy bundle together with its durable head.\n * This prevents a crash or bundle-write failure from leaving a checkpoint\n * without the exact same-head payload and member-envelope evidence.\n */\nexport async function persistVerifiedPrincipalPolicyBundlesAtomically(input: {\n readonly entries: readonly VerifiedPrincipalPolicyBundleEntry[];\n readonly execSql: ExecSql;\n readonly organizationId?: string | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly updatedAt: string;\n}): Promise<void> {\n const seen = new Set<string>();\n for (const entry of input.entries) {\n const key = principalPolicyKey(entry.policy);\n if (seen.has(key)) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `verified policy bundle batch repeats ${key}`,\n );\n }\n seen.add(key);\n }\n await Promise.all(\n input.entries.map((entry) => assertBundleMatchesVerifiedPolicy(entry)),\n );\n await ensureSqlTables(input.execSql, [\n ...principalPolicyTables,\n ...keyingCheckpointTables,\n ]);\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const persist = async (tx: ClientSQLiteTransactionScope) => {\n const policies = await validatePolicyAdvances(\n tx,\n input.entries.map((entry) => entry.policy),\n );\n for (const entry of input.entries) {\n await writePrincipalPolicyBundleInTransaction(\n tx,\n entry.bundle,\n input.updatedAt,\n input.organizationId,\n );\n await assertPrincipalPolicyBundleStoredInTransaction(tx, entry.bundle);\n }\n await writePolicyCheckpoints(\n tx,\n policies,\n input.updatedAt,\n input.organizationId,\n );\n for (const policy of policies.values()) {\n const checkpoint = await loadStoredPrincipalPolicyCheckpoint(tx, policy);\n if (\n !checkpoint ||\n checkpoint.version !== policy.version ||\n checkpoint.stateHash !== policy.stateHash\n ) {\n throw new Error(\n \"Verified principal policy checkpoint was not persisted\",\n );\n }\n }\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(persist, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(persist, { behavior: \"immediate\" });\n}\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { VerifiedManifestCitations, WriterProjectionTarget } from "../../internal/api-client/index.js";
|
|
2
|
+
import { type AccessManifestBundleWireResponse } from "../../internal/validators/response/index.js";
|
|
3
|
+
import { type ClientSQLiteTransactionScope } from "../sqlite/sqlitePersistenceRuntime.js";
|
|
4
|
+
import { type ExecSql } from "../sqlite/sqlSchema.js";
|
|
5
|
+
import { verifiedAccessManifestBundles as bundles } from "../sqlite/verifiedManifestBundleSchema.js";
|
|
6
|
+
/**
|
|
7
|
+
* Bounds local bytes (a bundle is ~10–20 KB). Evicting the least recently
|
|
8
|
+
* verified rows only makes a later read carry those bundles again.
|
|
9
|
+
*/
|
|
10
|
+
export declare const MAX_VERIFIED_MANIFEST_BUNDLES = 1024;
|
|
11
|
+
export interface VerifiedManifestBundle {
|
|
12
|
+
readonly bundle: AccessManifestBundleWireResponse;
|
|
13
|
+
readonly checkpoint: {
|
|
14
|
+
readonly objectKind: string;
|
|
15
|
+
readonly organizationId: string;
|
|
16
|
+
readonly objectId: string;
|
|
17
|
+
readonly epoch: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** A verified bundle's exact JSON and that JSON's digest. */
|
|
21
|
+
export type VerifiedManifestBundleRow = Omit<typeof bundles.$inferInsert, "verifiedAt">;
|
|
22
|
+
/**
|
|
23
|
+
* Prepares rows for bundles that just passed projection verification. The
|
|
24
|
+
* digests are computed here, before the checkpoint transaction that writes
|
|
25
|
+
* them begins.
|
|
26
|
+
*/
|
|
27
|
+
export declare function verifiedManifestBundleRows(entries: readonly VerifiedManifestBundle[]): Promise<VerifiedManifestBundleRow[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Records verified bundles inside the transaction that finalizes their
|
|
30
|
+
* projection's checkpoints, so they commit or roll back with it and no cache
|
|
31
|
+
* work outlives the verification. Freshly verified bytes replace any stored
|
|
32
|
+
* copy.
|
|
33
|
+
*/
|
|
34
|
+
export declare function writeVerifiedManifestBundlesInTransaction(tx: ClientSQLiteTransactionScope, rows: readonly VerifiedManifestBundleRow[], verifiedAt: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Verified bundles of the target's object and of the containers its
|
|
37
|
+
* projection walks, newest epochs first; then the most recently verified rows
|
|
38
|
+
* of its organization, since a just-verified parent is the likeliest part of
|
|
39
|
+
* a new child's projection. Citations never leave the target's organization:
|
|
40
|
+
* an object whose organization the device cannot place cites nothing.
|
|
41
|
+
* Damaged rows are dropped.
|
|
42
|
+
*/
|
|
43
|
+
export declare function loadVerifiedManifestCitations(execSql: ExecSql, target: WriterProjectionTarget, limit?: number): Promise<AccessManifestBundleWireResponse[]>;
|
|
44
|
+
/** Cites from whichever database the signed-in identity currently uses. */
|
|
45
|
+
export declare function createVerifiedManifestCitations(resolveExecSql: () => ExecSql | null): VerifiedManifestCitations;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import { toFingerprint } from "../../internal/crypto/index.js";
|
|
2
|
+
import { isAccessManifestBundleWireResponse, } from "../../internal/validators/response/index.js";
|
|
3
|
+
import { KNOWN_MANIFEST_HINT_LIMIT, MAX_CONTAINER_PATH_LENGTH, } from "../../internal/validators/util/index.js";
|
|
4
|
+
import { and, asc, desc, eq, inArray, sql } from "drizzle-orm";
|
|
5
|
+
import { containers } from "../sqlite/containerSchema.js";
|
|
6
|
+
import { documentDiscoveryHeads, pendingDocumentDiscoveries, } from "../sqlite/documentDiscoveryEvidenceSchema.js";
|
|
7
|
+
import { containerTables, documentContainerProjection, documentContainerProjectionTables, } from "../sqlite/schema.js";
|
|
8
|
+
import { getClientSQLitePersistenceRuntime, } from "../sqlite/sqlitePersistenceRuntime.js";
|
|
9
|
+
import { ensureSqlTables } from "../sqlite/sqlSchema.js";
|
|
10
|
+
import { verifiedAccessManifestBundles as bundles, verifiedManifestBundleTables, } from "../sqlite/verifiedManifestBundleSchema.js";
|
|
11
|
+
/**
|
|
12
|
+
* Bounds local bytes (a bundle is ~10–20 KB). Evicting the least recently
|
|
13
|
+
* verified rows only makes a later read carry those bundles again.
|
|
14
|
+
*/
|
|
15
|
+
export const MAX_VERIFIED_MANIFEST_BUNDLES = 1024;
|
|
16
|
+
const STATEMENT_BATCH = 200;
|
|
17
|
+
function sha256Hex(text) {
|
|
18
|
+
return toFingerprint(new TextEncoder().encode(text));
|
|
19
|
+
}
|
|
20
|
+
function batches(values) {
|
|
21
|
+
const result = [];
|
|
22
|
+
for (let index = 0; index < values.length; index += STATEMENT_BATCH)
|
|
23
|
+
result.push(values.slice(index, index + STATEMENT_BATCH));
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
async function pruneInTransaction(tx) {
|
|
27
|
+
const [row] = await tx.select({ count: sql `count(*)` }).from(bundles);
|
|
28
|
+
const excess = (row?.count ?? 0) - MAX_VERIFIED_MANIFEST_BUNDLES;
|
|
29
|
+
if (excess <= 0)
|
|
30
|
+
return;
|
|
31
|
+
const evicted = await tx
|
|
32
|
+
.select({ manifestHash: bundles.manifestHash })
|
|
33
|
+
.from(bundles)
|
|
34
|
+
.orderBy(asc(bundles.verifiedAt), asc(bundles.manifestHash))
|
|
35
|
+
.limit(excess);
|
|
36
|
+
for (const batch of batches(evicted.map((entry) => entry.manifestHash)))
|
|
37
|
+
await tx.delete(bundles).where(inArray(bundles.manifestHash, batch)).run();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Prepares rows for bundles that just passed projection verification. The
|
|
41
|
+
* digests are computed here, before the checkpoint transaction that writes
|
|
42
|
+
* them begins.
|
|
43
|
+
*/
|
|
44
|
+
export function verifiedManifestBundleRows(entries) {
|
|
45
|
+
const unique = new Map(entries.map((entry) => [entry.bundle.manifestHash, entry]));
|
|
46
|
+
return Promise.all([...unique.values()].map(async ({ bundle, checkpoint }) => {
|
|
47
|
+
const bundleJson = JSON.stringify(bundle);
|
|
48
|
+
return {
|
|
49
|
+
manifestHash: bundle.manifestHash,
|
|
50
|
+
organizationId: checkpoint.organizationId,
|
|
51
|
+
objectKind: checkpoint.objectKind,
|
|
52
|
+
objectId: checkpoint.objectId,
|
|
53
|
+
epoch: checkpoint.epoch,
|
|
54
|
+
bundleJson,
|
|
55
|
+
bundleDigest: await sha256Hex(bundleJson),
|
|
56
|
+
};
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Records verified bundles inside the transaction that finalizes their
|
|
61
|
+
* projection's checkpoints, so they commit or roll back with it and no cache
|
|
62
|
+
* work outlives the verification. Freshly verified bytes replace any stored
|
|
63
|
+
* copy.
|
|
64
|
+
*/
|
|
65
|
+
export async function writeVerifiedManifestBundlesInTransaction(tx, rows, verifiedAt) {
|
|
66
|
+
if (rows.length === 0)
|
|
67
|
+
return;
|
|
68
|
+
const stored = await storedDigests(tx, rows.map((row) => row.manifestHash));
|
|
69
|
+
// An identical stored row only needs its recency refreshed.
|
|
70
|
+
const unchanged = rows.filter((row) => stored.get(row.manifestHash) === row.bundleDigest);
|
|
71
|
+
for (const batch of batches(unchanged.map((row) => row.manifestHash)))
|
|
72
|
+
await tx
|
|
73
|
+
.update(bundles)
|
|
74
|
+
.set({ verifiedAt })
|
|
75
|
+
.where(inArray(bundles.manifestHash, batch))
|
|
76
|
+
.run();
|
|
77
|
+
for (const row of rows) {
|
|
78
|
+
if (stored.get(row.manifestHash) === row.bundleDigest)
|
|
79
|
+
continue;
|
|
80
|
+
const verified = { ...row, verifiedAt };
|
|
81
|
+
await tx
|
|
82
|
+
.insert(bundles)
|
|
83
|
+
.values(verified)
|
|
84
|
+
.onConflictDoUpdate({ target: bundles.manifestHash, set: verified })
|
|
85
|
+
.run();
|
|
86
|
+
}
|
|
87
|
+
await pruneInTransaction(tx);
|
|
88
|
+
}
|
|
89
|
+
async function storedDigests(tx, manifestHashes) {
|
|
90
|
+
const digests = new Map();
|
|
91
|
+
for (const batch of batches(manifestHashes)) {
|
|
92
|
+
const rows = await tx
|
|
93
|
+
.select({
|
|
94
|
+
bundleDigest: bundles.bundleDigest,
|
|
95
|
+
manifestHash: bundles.manifestHash,
|
|
96
|
+
})
|
|
97
|
+
.from(bundles)
|
|
98
|
+
.where(inArray(bundles.manifestHash, batch));
|
|
99
|
+
for (const row of rows)
|
|
100
|
+
digests.set(row.manifestHash, row.bundleDigest);
|
|
101
|
+
}
|
|
102
|
+
return digests;
|
|
103
|
+
}
|
|
104
|
+
/** The requested object first, then each container whose lineage it cites. */
|
|
105
|
+
async function containerLineage(db, containerId) {
|
|
106
|
+
const lineage = [containerId];
|
|
107
|
+
while (lineage.length < MAX_CONTAINER_PATH_LENGTH) {
|
|
108
|
+
const [row] = await db
|
|
109
|
+
.select({ parentId: containers.parentId })
|
|
110
|
+
.from(containers)
|
|
111
|
+
.where(eq(containers.id, lineage.at(-1) ?? ""))
|
|
112
|
+
.limit(1);
|
|
113
|
+
const parentId = row?.parentId;
|
|
114
|
+
if (!parentId || lineage.includes(parentId))
|
|
115
|
+
break;
|
|
116
|
+
lineage.push(parentId);
|
|
117
|
+
}
|
|
118
|
+
return lineage;
|
|
119
|
+
}
|
|
120
|
+
async function citedObjects(db, target) {
|
|
121
|
+
if (target.kind === "container")
|
|
122
|
+
return (await containerLineage(db, target.id)).map((id) => ({
|
|
123
|
+
kind: "container",
|
|
124
|
+
id,
|
|
125
|
+
}));
|
|
126
|
+
// Linked containers, containers listing the document before its signed
|
|
127
|
+
// placement is checked, and a container whose metadata document it is.
|
|
128
|
+
const placements = [
|
|
129
|
+
...(await db
|
|
130
|
+
.select({ containerId: documentContainerProjection.containerId })
|
|
131
|
+
.from(documentContainerProjection)
|
|
132
|
+
.where(eq(documentContainerProjection.documentId, target.id))),
|
|
133
|
+
...(await db
|
|
134
|
+
.select({ containerId: pendingDocumentDiscoveries.containerId })
|
|
135
|
+
.from(pendingDocumentDiscoveries)
|
|
136
|
+
.where(eq(pendingDocumentDiscoveries.documentId, target.id))),
|
|
137
|
+
...(await db
|
|
138
|
+
.select({ containerId: containers.id })
|
|
139
|
+
.from(containers)
|
|
140
|
+
.where(eq(containers.metadataDocumentId, target.id))),
|
|
141
|
+
];
|
|
142
|
+
const containerIds = new Set();
|
|
143
|
+
for (const { containerId } of placements)
|
|
144
|
+
if (containerId)
|
|
145
|
+
for (const id of await containerLineage(db, containerId))
|
|
146
|
+
containerIds.add(id);
|
|
147
|
+
return [
|
|
148
|
+
{ kind: "document", id: target.id },
|
|
149
|
+
...[...containerIds].map((id) => ({ kind: "container", id })),
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The one organization every local source places the read in. Verified
|
|
154
|
+
* ownership (stored verified bundles of the target and of the containers on
|
|
155
|
+
* its walk, and a document's verified discovery head) and local placement
|
|
156
|
+
* (listed container rows reached through links, pending listings, metadata,
|
|
157
|
+
* or parents) must all agree: any disagreement, or no source at all, yields
|
|
158
|
+
* null, so the read is sent with no hints rather than another
|
|
159
|
+
* organization's.
|
|
160
|
+
*/
|
|
161
|
+
async function targetOrganization(db, target, objects) {
|
|
162
|
+
const containerIds = objects
|
|
163
|
+
.filter((object) => object.kind === "container")
|
|
164
|
+
.map((object) => object.id);
|
|
165
|
+
const listed = containerIds.length === 0
|
|
166
|
+
? []
|
|
167
|
+
: await db
|
|
168
|
+
.select({ organizationId: containers.organizationId })
|
|
169
|
+
.from(containers)
|
|
170
|
+
.where(inArray(containers.id, containerIds));
|
|
171
|
+
const verifiedContainers = containerIds.length === 0
|
|
172
|
+
? []
|
|
173
|
+
: await db
|
|
174
|
+
.select({ organizationId: bundles.organizationId })
|
|
175
|
+
.from(bundles)
|
|
176
|
+
.where(and(eq(bundles.objectKind, "container"), inArray(bundles.objectId, containerIds)));
|
|
177
|
+
const verifiedTarget = await db
|
|
178
|
+
.select({ organizationId: bundles.organizationId })
|
|
179
|
+
.from(bundles)
|
|
180
|
+
.where(and(eq(bundles.objectKind, target.kind), eq(bundles.objectId, target.id)));
|
|
181
|
+
const discovered = target.kind === "document"
|
|
182
|
+
? await db
|
|
183
|
+
.select({ organizationId: documentDiscoveryHeads.organizationId })
|
|
184
|
+
.from(documentDiscoveryHeads)
|
|
185
|
+
.where(eq(documentDiscoveryHeads.documentId, target.id))
|
|
186
|
+
: [];
|
|
187
|
+
const sources = [listed, verifiedContainers, verifiedTarget, discovered];
|
|
188
|
+
const organizations = new Set(sources.flat().map((row) => row.organizationId));
|
|
189
|
+
const [organizationId] = organizations;
|
|
190
|
+
return organizations.size === 1 && organizationId ? organizationId : null;
|
|
191
|
+
}
|
|
192
|
+
const storedColumns = {
|
|
193
|
+
bundleDigest: bundles.bundleDigest,
|
|
194
|
+
bundleJson: bundles.bundleJson,
|
|
195
|
+
manifestHash: bundles.manifestHash,
|
|
196
|
+
};
|
|
197
|
+
async function readStoredBundle(row) {
|
|
198
|
+
if ((await sha256Hex(row.bundleJson)) !== row.bundleDigest)
|
|
199
|
+
return null;
|
|
200
|
+
try {
|
|
201
|
+
const bundle = JSON.parse(row.bundleJson);
|
|
202
|
+
return isAccessManifestBundleWireResponse(bundle) &&
|
|
203
|
+
bundle.manifestHash === row.manifestHash
|
|
204
|
+
? bundle
|
|
205
|
+
: null;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function objectRows(db, organizationId, object, limit) {
|
|
212
|
+
return db
|
|
213
|
+
.select(storedColumns)
|
|
214
|
+
.from(bundles)
|
|
215
|
+
.where(and(eq(bundles.organizationId, organizationId), eq(bundles.objectKind, object.kind), eq(bundles.objectId, object.id)))
|
|
216
|
+
.orderBy(desc(bundles.epoch))
|
|
217
|
+
.limit(limit);
|
|
218
|
+
}
|
|
219
|
+
function recentRows(db, organizationId, limit) {
|
|
220
|
+
return db
|
|
221
|
+
.select(storedColumns)
|
|
222
|
+
.from(bundles)
|
|
223
|
+
.where(eq(bundles.organizationId, organizationId))
|
|
224
|
+
.orderBy(desc(bundles.verifiedAt), asc(bundles.manifestHash))
|
|
225
|
+
.limit(limit);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Verified bundles of the target's object and of the containers its
|
|
229
|
+
* projection walks, newest epochs first; then the most recently verified rows
|
|
230
|
+
* of its organization, since a just-verified parent is the likeliest part of
|
|
231
|
+
* a new child's projection. Citations never leave the target's organization:
|
|
232
|
+
* an object whose organization the device cannot place cites nothing.
|
|
233
|
+
* Damaged rows are dropped.
|
|
234
|
+
*/
|
|
235
|
+
export async function loadVerifiedManifestCitations(execSql, target, limit = KNOWN_MANIFEST_HINT_LIMIT) {
|
|
236
|
+
await ensureSqlTables(execSql, [
|
|
237
|
+
...verifiedManifestBundleTables,
|
|
238
|
+
...containerTables,
|
|
239
|
+
...documentContainerProjectionTables,
|
|
240
|
+
]);
|
|
241
|
+
const { db } = getClientSQLitePersistenceRuntime(execSql);
|
|
242
|
+
const cited = new Map();
|
|
243
|
+
const damaged = [];
|
|
244
|
+
const collect = async (rows) => {
|
|
245
|
+
for (const row of rows) {
|
|
246
|
+
if (cited.size >= limit || cited.has(row.manifestHash))
|
|
247
|
+
continue;
|
|
248
|
+
const bundle = await readStoredBundle(row);
|
|
249
|
+
if (bundle)
|
|
250
|
+
cited.set(row.manifestHash, bundle);
|
|
251
|
+
else
|
|
252
|
+
damaged.push(row.manifestHash);
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const objects = await citedObjects(db, target);
|
|
256
|
+
const organizationId = await targetOrganization(db, target, objects);
|
|
257
|
+
if (organizationId === null)
|
|
258
|
+
return [];
|
|
259
|
+
for (const object of objects)
|
|
260
|
+
if (cited.size < limit)
|
|
261
|
+
await collect(await objectRows(db, organizationId, object, limit - cited.size));
|
|
262
|
+
if (cited.size < limit)
|
|
263
|
+
await collect(await recentRows(db, organizationId, limit + cited.size));
|
|
264
|
+
if (damaged.length > 0)
|
|
265
|
+
await getClientSQLitePersistenceRuntime(execSql)
|
|
266
|
+
.runMutation((handle) => handle
|
|
267
|
+
.delete(bundles)
|
|
268
|
+
.where(inArray(bundles.manifestHash, damaged))
|
|
269
|
+
.run())
|
|
270
|
+
.catch(() => undefined);
|
|
271
|
+
return [...cited.values()];
|
|
272
|
+
}
|
|
273
|
+
/** Cites from whichever database the signed-in identity currently uses. */
|
|
274
|
+
export function createVerifiedManifestCitations(resolveExecSql) {
|
|
275
|
+
return {
|
|
276
|
+
cite: async (target) => {
|
|
277
|
+
const execSql = resolveExecSql();
|
|
278
|
+
return execSql ? loadVerifiedManifestCitations(execSql, target) : [];
|
|
279
|
+
},
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=verifiedManifestBundlePersistence.js.map
|