@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
|
@@ -15,9 +15,10 @@ const DEFERRED_TAIL_CANDIDATE_SQL = `
|
|
|
15
15
|
stored.updated_at AS updated_at,
|
|
16
16
|
(
|
|
17
17
|
SELECT pending.partial_end_version_vector
|
|
18
|
-
FROM
|
|
18
|
+
FROM document_history_updates pending
|
|
19
19
|
WHERE pending.app_kind = stored.app_kind
|
|
20
20
|
AND pending.local_id = stored.local_id
|
|
21
|
+
AND pending.update_id IS NOT NULL
|
|
21
22
|
ORDER BY pending.created_at DESC, pending.rowid DESC
|
|
22
23
|
LIMIT 1
|
|
23
24
|
) AS latest_pending_end_version,
|
|
@@ -63,9 +64,10 @@ const DEFERRED_TAIL_CANDIDATE_SQL = `
|
|
|
63
64
|
stored.pending_base_version IS NOT NULL
|
|
64
65
|
OR EXISTS (
|
|
65
66
|
SELECT 1
|
|
66
|
-
FROM
|
|
67
|
+
FROM document_history_updates pending
|
|
67
68
|
WHERE pending.app_kind = stored.app_kind
|
|
68
69
|
AND pending.local_id = stored.local_id
|
|
70
|
+
AND pending.update_id IS NOT NULL
|
|
69
71
|
)
|
|
70
72
|
)
|
|
71
73
|
`;
|
|
@@ -169,9 +171,10 @@ const DEFERRED_TAIL_SCOPE_SQL = `
|
|
|
169
171
|
stored.pending_base_version AS pending_base_version,
|
|
170
172
|
(
|
|
171
173
|
SELECT pending.partial_end_version_vector
|
|
172
|
-
FROM
|
|
174
|
+
FROM document_history_updates pending
|
|
173
175
|
WHERE pending.app_kind = stored.app_kind
|
|
174
176
|
AND pending.local_id = stored.local_id
|
|
177
|
+
AND pending.update_id IS NOT NULL
|
|
175
178
|
ORDER BY pending.created_at DESC, pending.rowid DESC
|
|
176
179
|
LIMIT 1
|
|
177
180
|
) AS latest_pending_end_version
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,GACvC,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,kEAAkE;AAClE,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;MAkB9B,sCAAsC,CAAC;IACvC,cAAc,EAAE,oBAAoB;IACpC,eAAe,EAAE,qBAAqB;CACvC,CAAC;;;;;MAKA,0BAA0B,CAAC;IAC3B,cAAc,EAAE,oBAAoB;IACpC,eAAe,EAAE,sBAAsB;CACxC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCL,CAAC;AAEF,SAAS,gBAAgB,CAAC,KAIzB;IACC,MAAM,gBAAgB,GAAG;QACvB,KAAK,CAAC,uBAAuB;QAC7B,KAAK,CAAC,kBAAkB;KACzB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACrD,MAAM,qBAAqB,GAAa,EAAE,CAAC;IAC3C,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,qBAAqB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,IAAI,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;QAClE,OAAO,CAAC,sBAAsB,CAAC,cAAc,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IAC/C,IAAI,OAAO,KAAK,oBAAoB;QAAE,OAAO,WAAW,CAAC;IACzD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,wBAAwB,CAC/B,GAA4B;IAE5B,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/D,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IACE,CAAC,gBAAgB,CAAC;QAChB,cAAc;QACd,uBAAuB,EAAE,UAAU,CAAC,GAAG,EAAE,4BAA4B,CAAC;QACtE,kBAAkB,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC;KAC5D,CAAC,EACF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAChD,OAAO;QACL,UAAU,EAAE,CAAC;QACb,WAAW,EACT,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,uBAAuB,CAAC;YAC1C,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,uBAAuB,CAAC;gBAC1C,CAAC,CAAC,IAAI;QACZ,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,SAAS;QACpB,SAAS,EAAE,QAAQ;QACnB,IAAI,EAAE,iBAAiB;QACvB,wEAAwE;QACxE,sEAAsE;QACtE,oBAAoB;QACpB,eAAe,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC;QACxD,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,iBAAiB,CAAC;QAC7C,OAAO;QACP,IAAI,EACF,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,gBAAgB,CAAC;YACnC,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,eAAe,CAAC;gBAClC,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QACpD,UAAU;QACV,cAAc,EACZ,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,0BAA0B,CAAC;YAC7C,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,0BAA0B,CAAC;gBAC7C,CAAC,CAAC,IAAI;QACZ,QAAQ,EACN,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,qBAAqB,CAAC;YACxC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,kBAAkB,CAAC;QACzC,MAAM,EAAE,SAAS;QACjB,iBAAiB,EAAE,IAAI;QACvB,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,OAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,MAAM,SAAS,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;CAqB/B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAgB,EAChB,KAA2C;IAE3C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,uBAAuB,EAAE;QAClD,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,OAAO;KACd,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,gBAAgB,CAAC;QACtB,cAAc;QACd,uBAAuB,EAAE,UAAU,CAAC,GAAG,EAAE,4BAA4B,CAAC;QACtE,kBAAkB,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC;KAC5D,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_pending_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql({\n containerAlias: \"metadata_container\",\n projectionAlias: \"container_projection\",\n })} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n failure.message AS failure_message,\n failure.attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = metadata_container.id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = stored.app_kind\n AND failure.local_id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_pending_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_pending_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql({\n containerAlias: \"metadata_container\",\n projectionAlias: \"container_projection\",\n })} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n failure.message AS failure_message,\n failure.attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = metadata_container.id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = stored.app_kind\n AND failure.local_id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
|
|
@@ -16,7 +16,8 @@ const PENDING_WRITE_SOURCE_SQL = `
|
|
|
16
16
|
COUNT(*) AS operation_count,
|
|
17
17
|
MIN(created_at) AS created_at,
|
|
18
18
|
MAX(created_at) AS updated_at
|
|
19
|
-
FROM
|
|
19
|
+
FROM document_history_updates
|
|
20
|
+
WHERE update_id IS NOT NULL
|
|
20
21
|
GROUP BY app_kind, local_id
|
|
21
22
|
)
|
|
22
23
|
SELECT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources.js","sourceRoot":"","sources":["sources.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type {\n PendingWriteCandidate,\n PendingWriteCandidateInclusion,\n} from \"./aggregation\";\nimport { readNumber, readString } from \"./rowReaders\";\n\nconst CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql({\n containerAlias: \"container\",\n projectionAlias: \"container_projection\",\n});\nconst DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({\n containerAlias: \"container\",\n projectionAlias: \"projection\",\n});\n\nconst PENDING_WRITE_SOURCE_SQL = `\n WITH pending_update_groups AS (\n SELECT\n app_kind,\n local_id,\n COUNT(*) AS operation_count,\n MIN(created_at) AS created_at,\n MAX(created_at) AS updated_at\n FROM document_pending_updates\n GROUP BY app_kind, local_id\n )\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = updates.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = updates.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'documents'\n\n UNION ALL\n\n -- Failure-only surface (edge-case row 13): a refused read-only\n -- revalidation records a durable failure row with NO pending work, so\n -- without this branch the refusal would never reach the queue view. The\n -- 'unless-item-covered' inclusion keeps it out whenever the document\n -- already has real operations — those candidates carry the same failure\n -- message through their own joins.\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n LEFT JOIN documents stored\n ON stored.app_kind = failure.app_kind\n AND stored.local_id = failure.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = failure.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE failure.app_kind = 'documents'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN containers container ON container.id = updates.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'container-metadata'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'container-metadata'\n -- Dormant retained metadata (container tombstoned access_revoked, row 4)\n -- has no containers row; keep it unsurfaced until rehydration re-attaches\n -- the container, or it renders as an anonymous phantom item.\n AND container.id IS NOT NULL\n\n UNION ALL\n\n -- An incoming metadata quarantine can exist without outbound updates. Keep\n -- it visible as a zero-operation diagnostic while the container is live;\n -- dormant retained metadata stays hidden until rehydration re-attaches it.\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n JOIN containers container ON container.id = failure.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = failure.local_id\n WHERE failure.app_kind = 'container-metadata'\n\n UNION ALL\n\n SELECT\n 'unknown' AS object_kind,\n updates.app_kind AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n NULL AS name,\n NULL AS container_id,\n NULL AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = updates.app_kind\n AND stored.local_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = updates.app_kind\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind NOT IN ('documents', 'container-metadata')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n attachment.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'attachment' AS operation_kind,\n COUNT(*) AS operation_count,\n COALESCE(SUM(attachment.byte_length), 0) AS byte_length,\n MIN(attachment.created_at) AS created_at,\n MAX(attachment.created_at) AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM document_pending_attachments attachment\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = attachment.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = attachment.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = attachment.local_id\n GROUP BY attachment.local_id\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n 'pending' AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_create_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.create'\n AND intent.sync_status = 'pending'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_move_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.move'\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n intent.local_id AS local_id,\n intent.document_id AS remote_id,\n projection.title AS name,\n COALESCE(projection.container_id, intent.target_container_id) AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,\n COALESCE(NULLIF(intent.last_error, ''), failure.message) AS last_error,\n COALESCE(intent.last_attempted_at, failure.attempted_at) AS last_attempted_at,\n 'always' AS inclusion\n FROM document_move_intents intent\n LEFT JOIN document_projection projection\n ON projection.local_id = intent.local_id\n LEFT JOIN containers container\n ON container.id = COALESCE(projection.container_id, intent.target_container_id)\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = intent.local_id\n WHERE intent.intent_type IN ('document.move', 'document.link')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n NULL AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n stored.updated_at AS created_at,\n stored.updated_at AS updated_at,\n projection.container_id AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND stored.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n container.local_created_at AS created_at,\n container.local_updated_at AS updated_at,\n container.parent_id AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = container.id\n WHERE container.server_created_at IS NULL\n OR container.metadata_document_id IS NULL\n OR metadata.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n NULL AS created_at,\n container.local_updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n WHERE container.local_updated_at IS NOT NULL\n AND (\n container.server_updated_at IS NULL\n OR container.local_updated_at > container.server_updated_at\n )\n`;\n\nfunction mapPendingWriteSourceRow(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const localId = readString(row, \"local_id\");\n const operationKind = readString(row, \"operation_kind\");\n if (\n !localId ||\n (operationKind !== \"attachment\" &&\n operationKind !== \"create\" &&\n operationKind !== \"move\" &&\n operationKind !== \"revalidation\" &&\n operationKind !== \"update\")\n ) {\n return null;\n }\n const rawObjectKind = readString(row, \"object_kind\");\n const objectKind =\n rawObjectKind === \"container\" || rawObjectKind === \"document\"\n ? rawObjectKind\n : \"unknown\";\n const rawInclusion = readString(row, \"inclusion\");\n const inclusion: PendingWriteCandidateInclusion =\n rawInclusion === \"unless-item-covered\" ||\n rawInclusion === \"unless-operation-covered\"\n ? rawInclusion\n : \"always\";\n\n return {\n byteLength: readNumber(row, \"byte_length\"),\n containerId: readString(row, \"container_id\"),\n // Diagnostic-only revalidation items carry NO local operations; clamping\n // them to 1 would falsely report pending local data.\n count:\n operationKind === \"revalidation\"\n ? 0\n : Math.max(1, readNumber(row, \"operation_count\")),\n createdAt: readString(row, \"created_at\"),\n inclusion,\n kind: operationKind,\n lastAttemptedAt: readString(row, \"last_attempted_at\"),\n lastError: readString(row, \"last_error\"),\n localId,\n name: readString(row, \"name\"),\n namespace: readString(row, \"namespace\"),\n objectKind,\n organizationId: readString(row, \"organization_id\"),\n remoteId: readString(row, \"remote_id\"),\n status:\n readString(row, \"operation_status\") === \"blocked\" ? \"blocked\" : \"pending\",\n targetContainerId: readString(row, \"target_container_id\"),\n updatedAt: readString(row, \"updated_at\"),\n };\n}\n\nexport async function listPersistedPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(PENDING_WRITE_SOURCE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapPendingWriteSourceRow(row);\n return candidate ? [candidate] : [];\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sources.js","sourceRoot":"","sources":["sources.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type {\n PendingWriteCandidate,\n PendingWriteCandidateInclusion,\n} from \"./aggregation\";\nimport { readNumber, readString } from \"./rowReaders\";\n\nconst CONTAINER_DISPLAY_NAME_SQL = getContainerDisplayNameSql({\n containerAlias: \"container\",\n projectionAlias: \"container_projection\",\n});\nconst DOCUMENT_ORGANIZATION_SQL = getContainerOrganizationAttributionSql({\n containerAlias: \"container\",\n projectionAlias: \"projection\",\n});\n\nconst PENDING_WRITE_SOURCE_SQL = `\n WITH pending_update_groups AS (\n SELECT\n app_kind,\n local_id,\n COUNT(*) AS operation_count,\n MIN(created_at) AS created_at,\n MAX(created_at) AS updated_at\n FROM document_history_updates\n WHERE update_id IS NOT NULL\n GROUP BY app_kind, local_id\n )\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = updates.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = updates.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'documents'\n\n UNION ALL\n\n -- Failure-only surface (edge-case row 13): a refused read-only\n -- revalidation records a durable failure row with NO pending work, so\n -- without this branch the refusal would never reach the queue view. The\n -- 'unless-item-covered' inclusion keeps it out whenever the document\n -- already has real operations — those candidates carry the same failure\n -- message through their own joins.\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n LEFT JOIN documents stored\n ON stored.app_kind = failure.app_kind\n AND stored.local_id = failure.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = failure.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n WHERE failure.app_kind = 'documents'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n updates.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN containers container ON container.id = updates.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'container-metadata'\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind = 'container-metadata'\n -- Dormant retained metadata (container tombstoned access_revoked, row 4)\n -- has no containers row; keep it unsurfaced until rehydration re-attaches\n -- the container, or it renders as an anonymous phantom item.\n AND container.id IS NOT NULL\n\n UNION ALL\n\n -- An incoming metadata quarantine can exist without outbound updates. Keep\n -- it visible as a zero-operation diagnostic while the container is live;\n -- dormant retained metadata stays hidden until rehydration re-attaches it.\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n failure.local_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'revalidation' AS operation_kind,\n 0 AS operation_count,\n 0 AS byte_length,\n failure.attempted_at AS created_at,\n failure.attempted_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM document_sync_failures failure\n JOIN containers container ON container.id = failure.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = failure.local_id\n WHERE failure.app_kind = 'container-metadata'\n\n UNION ALL\n\n SELECT\n 'unknown' AS object_kind,\n updates.app_kind AS namespace,\n updates.local_id AS local_id,\n stored.document_id AS remote_id,\n NULL AS name,\n NULL AS container_id,\n NULL AS organization_id,\n 'update' AS operation_kind,\n updates.operation_count AS operation_count,\n 0 AS byte_length,\n updates.created_at AS created_at,\n updates.updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM pending_update_groups updates\n LEFT JOIN documents stored\n ON stored.app_kind = updates.app_kind\n AND stored.local_id = updates.local_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = updates.app_kind\n AND failure.local_id = updates.local_id\n WHERE updates.app_kind NOT IN ('documents', 'container-metadata')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n attachment.local_id AS local_id,\n stored.document_id AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'attachment' AS operation_kind,\n COUNT(*) AS operation_count,\n COALESCE(SUM(attachment.byte_length), 0) AS byte_length,\n MIN(attachment.created_at) AS created_at,\n MAX(attachment.created_at) AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM document_pending_attachments attachment\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = attachment.local_id\n LEFT JOIN document_projection projection\n ON projection.local_id = attachment.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = attachment.local_id\n GROUP BY attachment.local_id\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n COALESCE(intent.remote_container_id, CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END) AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n 'pending' AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_create_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.create'\n AND intent.sync_status = 'pending'\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n intent.container_id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n intent.container_id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.parent_container_id AS target_container_id,\n CASE WHEN intent.sync_status = 'blocked' THEN 'blocked' ELSE 'pending' END AS operation_status,\n intent.last_error AS last_error,\n intent.last_attempted_at AS last_attempted_at,\n 'always' AS inclusion\n FROM container_move_intents intent\n LEFT JOIN containers container ON container.id = intent.container_id\n LEFT JOIN container_projection\n ON container_projection.container_id = intent.container_id\n WHERE intent.intent_type = 'container.move'\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n intent.local_id AS local_id,\n intent.document_id AS remote_id,\n projection.title AS name,\n COALESCE(projection.container_id, intent.target_container_id) AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'move' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n intent.created_at AS created_at,\n intent.updated_at AS updated_at,\n intent.target_container_id AS target_container_id,\n CASE WHEN intent.sync_status IN ('blocked', 'unavailable') THEN 'blocked' ELSE 'pending' END AS operation_status,\n COALESCE(NULLIF(intent.last_error, ''), failure.message) AS last_error,\n COALESCE(intent.last_attempted_at, failure.attempted_at) AS last_attempted_at,\n 'always' AS inclusion\n FROM document_move_intents intent\n LEFT JOIN document_projection projection\n ON projection.local_id = intent.local_id\n LEFT JOIN containers container\n ON container.id = COALESCE(projection.container_id, intent.target_container_id)\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = intent.local_id\n WHERE intent.intent_type IN ('document.move', 'document.link')\n\n UNION ALL\n\n SELECT\n 'document' AS object_kind,\n NULL AS namespace,\n stored.local_id AS local_id,\n NULL AS remote_id,\n projection.title AS name,\n projection.container_id AS container_id,\n ${DOCUMENT_ORGANIZATION_SQL} AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n stored.updated_at AS created_at,\n stored.updated_at AS updated_at,\n projection.container_id AS target_container_id,\n 'pending' AS operation_status,\n failure.message AS last_error,\n failure.attempted_at AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM documents stored\n LEFT JOIN document_projection projection\n ON projection.local_id = stored.local_id\n LEFT JOIN containers container\n ON container.id = projection.container_id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = 'documents'\n AND failure.local_id = stored.local_id\n WHERE stored.app_kind = 'documents'\n AND stored.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'create' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n container.local_created_at AS created_at,\n container.local_updated_at AS updated_at,\n container.parent_id AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-operation-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n LEFT JOIN documents metadata\n ON metadata.app_kind = 'container-metadata'\n AND metadata.local_id = container.id\n WHERE container.server_created_at IS NULL\n OR container.metadata_document_id IS NULL\n OR metadata.document_id IS NULL\n\n UNION ALL\n\n SELECT\n 'container' AS object_kind,\n NULL AS namespace,\n container.id AS local_id,\n CASE WHEN container.server_created_at IS NULL THEN NULL ELSE container.id END AS remote_id,\n ${CONTAINER_DISPLAY_NAME_SQL} AS name,\n container.id AS container_id,\n NULLIF(container.organization_id, '') AS organization_id,\n 'update' AS operation_kind,\n 1 AS operation_count,\n 0 AS byte_length,\n NULL AS created_at,\n container.local_updated_at AS updated_at,\n NULL AS target_container_id,\n 'pending' AS operation_status,\n NULL AS last_error,\n NULL AS last_attempted_at,\n 'unless-item-covered' AS inclusion\n FROM containers container\n LEFT JOIN container_projection\n ON container_projection.container_id = container.id\n WHERE container.local_updated_at IS NOT NULL\n AND (\n container.server_updated_at IS NULL\n OR container.local_updated_at > container.server_updated_at\n )\n`;\n\nfunction mapPendingWriteSourceRow(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const localId = readString(row, \"local_id\");\n const operationKind = readString(row, \"operation_kind\");\n if (\n !localId ||\n (operationKind !== \"attachment\" &&\n operationKind !== \"create\" &&\n operationKind !== \"move\" &&\n operationKind !== \"revalidation\" &&\n operationKind !== \"update\")\n ) {\n return null;\n }\n const rawObjectKind = readString(row, \"object_kind\");\n const objectKind =\n rawObjectKind === \"container\" || rawObjectKind === \"document\"\n ? rawObjectKind\n : \"unknown\";\n const rawInclusion = readString(row, \"inclusion\");\n const inclusion: PendingWriteCandidateInclusion =\n rawInclusion === \"unless-item-covered\" ||\n rawInclusion === \"unless-operation-covered\"\n ? rawInclusion\n : \"always\";\n\n return {\n byteLength: readNumber(row, \"byte_length\"),\n containerId: readString(row, \"container_id\"),\n // Diagnostic-only revalidation items carry NO local operations; clamping\n // them to 1 would falsely report pending local data.\n count:\n operationKind === \"revalidation\"\n ? 0\n : Math.max(1, readNumber(row, \"operation_count\")),\n createdAt: readString(row, \"created_at\"),\n inclusion,\n kind: operationKind,\n lastAttemptedAt: readString(row, \"last_attempted_at\"),\n lastError: readString(row, \"last_error\"),\n localId,\n name: readString(row, \"name\"),\n namespace: readString(row, \"namespace\"),\n objectKind,\n organizationId: readString(row, \"organization_id\"),\n remoteId: readString(row, \"remote_id\"),\n status:\n readString(row, \"operation_status\") === \"blocked\" ? \"blocked\" : \"pending\",\n targetContainerId: readString(row, \"target_container_id\"),\n updatedAt: readString(row, \"updated_at\"),\n };\n}\n\nexport async function listPersistedPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(PENDING_WRITE_SOURCE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapPendingWriteSourceRow(row);\n return candidate ? [candidate] : [];\n });\n}\n"]}
|
|
@@ -78,8 +78,9 @@ async function hasQueuedScopeWork(execSql, scope) {
|
|
|
78
78
|
]);
|
|
79
79
|
const rows = await execSql(`SELECT 1 AS present
|
|
80
80
|
WHERE EXISTS (
|
|
81
|
-
SELECT 1 FROM
|
|
81
|
+
SELECT 1 FROM document_history_updates pending
|
|
82
82
|
WHERE pending.app_kind = ? AND pending.local_id = ?
|
|
83
|
+
AND pending.update_id IS NOT NULL
|
|
83
84
|
)
|
|
84
85
|
OR EXISTS (
|
|
85
86
|
SELECT 1 FROM document_pending_attachments attachment
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pendingWrites.js","sourceRoot":"","sources":["pendingWrites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,wEAAwE,CAAC;AACrH,OAAO,EAAE,gCAAgC,EAAE,MAAM,yEAAyE,CAAC;AAC3H,OAAO,EAAE,uBAAuB,EAAE,MAAM,uDAAuD,CAAC;AAChG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qDAAqD,CAAC;AACzF,OAAO,EACL,wBAAwB,EACxB,qCAAqC,GACtC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,wBAAwB,EACxB,cAAc,GACf,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,mCAAmC,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EACL,wBAAwB,EACxB,kCAAkC,GACnC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,mCAAmC,EAAE,MAAM,yBAAyB,CAAC;AAY9E;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAgB;IAEhB,MAAM,mCAAmC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,uBAAuB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,gCAAgC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IAE7D,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9C,mCAAmC,CAAC,OAAO,CAAC;QAC5C,kCAAkC,CAAC,OAAO,CAAC;KAC5C,CAAC,CAAC;IACH,OAAO,2BAA2B,CAAC,CAAC,GAAG,SAAS,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC;AAClE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,OAAgB,EAChB,KAKC;IAED,MAAM,OAAO,GACX,KAAK,CAAC,UAAU,KAAK,WAAW;QAC9B,CAAC,CAAC,2BAA2B;QAC7B,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;YAChB,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,wEAAwE;QACxE,uEAAuE;QACvE,OAAO;IACT,CAAC;IACD,MAAM,KAAK,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAClD,MAAM,qCAAqC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5D,IAAI,OAAO,KAAK,kBAAkB,EAAE,CAAC;QACnC,yEAAyE;QACzE,sEAAsE;QACtE,uBAAuB;QACvB,MAAM,gCAAgC,CAAC,sBAAsB,CAAC,OAAO,EAAE;YACrE,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAC;IACL,CAAC;IACD,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,wEAAwE;IACxE,yEAAyE;IACzE,IAAI,MAAM,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,wBAAwB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,kBAAkB,CAC/B,OAAgB,EAChB,KAA2C;IAE3C,MAAM,eAAe,CAAC,OAAO,EAAE;QAC7B,GAAG,cAAc;QACjB,GAAG,wBAAwB;KAC5B,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,OAAO,CACxB
|
|
1
|
+
{"version":3,"file":"pendingWrites.js","sourceRoot":"","sources":["pendingWrites.ts"],"names":[],"mappings":"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","sourcesContent":["import { CONTAINER_METADATA_APP_KIND } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport { DOCUMENTS_APP_KIND } from \"../../data/persistence/documents/internal/constants\";\nimport {\n clearDocumentSyncFailure,\n resetDocumentPendingUpdateRekeyBudget,\n} from \"../../data/sqlite/documentPersistence\";\nimport {\n documentMoveIntentTables,\n documentTables,\n} from \"../../data/sqlite/schema\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { defaultContainerContentsPersistence } from \"./containerPersistence\";\nimport { groupPendingWriteCandidates } from \"./pendingWrites/aggregation\";\nimport {\n hasDeferredTailScopeWork,\n listDeferredPendingWriteCandidates,\n} from \"./pendingWrites/deferredTails\";\nimport { listPersistedPendingWriteCandidates } from \"./pendingWrites/sources\";\nimport type { PendingWriteQueueItem } from \"./pendingWritesTypes\";\n\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\n/**\n * List identity-wide local state that still requires a remote write. The\n * returned diagnostic contains only navigation/display metadata and aggregate\n * counts; serialized updates, local storage keys, and upload crypto stay below\n * the workflow boundary.\n */\nexport async function listPendingWrites(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingWriteQueueItem>> {\n await defaultContainerContentsPersistence.ensureSchema(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await sqlDocumentMoveIntentPersistence.ensureSchema(execSql);\n\n const [persisted, deferred] = await Promise.all([\n listPersistedPendingWriteCandidates(execSql),\n listDeferredPendingWriteCandidates(execSql),\n ]);\n return groupPendingWriteCandidates([...persisted, ...deferred]);\n}\n\n/**\n * Explicit manual retry for one write-queue item: reset the durable re-key\n * budget for the item's ACTUAL pending-update scope (container metadata and\n * unknown document namespaces re-key through the same recovery path as\n * ordinary documents) and clear the recorded terminal failure — the next\n * pass re-records both if they still hold. The cap protects against a\n * server driving a network-speed re-key loop; a deliberate user retry is\n * the rate-limited signal that conditions have changed (e.g. an outage that\n * burned the budget has healed). The caller re-arms the sync lanes.\n */\nexport async function resetPendingWriteRetryState(\n execSql: ExecSql,\n input: {\n localId: string;\n /** The item's `namespace` — the unrecognized documents.app_kind, if any. */\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n },\n): Promise<void> {\n const appKind =\n input.objectKind === \"container\"\n ? CONTAINER_METADATA_APP_KIND\n : (input.namespace ??\n (input.objectKind === \"document\" ? DOCUMENTS_APP_KIND : null));\n if (appKind === null) {\n // An unknown object kind with no namespace: there is no scope to reset,\n // and guessing one could clear an unrelated scope sharing the localId.\n return;\n }\n const scope = { appKind, localId: input.localId };\n await resetDocumentPendingUpdateRekeyBudget(execSql, scope);\n if (appKind === DOCUMENTS_APP_KIND) {\n // A deliberate retry is the rate-limited signal that conditions changed:\n // a parked permission-denied move (row 7) replays once, like row 11's\n // re-key budget reset.\n await sqlDocumentMoveIntentPersistence.resetDeniedMoveIntents(execSql, {\n localId: input.localId,\n });\n }\n // Clearing the failure row is part of the re-key budget reset (edge-case\n // row 11) and only makes sense alongside queued work. A failure-only item\n // (a refused revalidation, row 13) has no queued work: its row is the\n // priming ticket that re-drives the store, so it must survive the retry\n // and clear on the next clean pass instead of vanishing with no request.\n if (await hasQueuedScopeWork(execSql, scope)) {\n await clearDocumentSyncFailure(execSql, scope);\n }\n}\n\n/**\n * Whether ANY durable outbound work exists for the scope — CRDT updates,\n * staged attachment uploads, move intents, a never-created local document, or\n * a deferred write whose only durable content is the history tail ahead of\n * its covered frontier. Mirrors the queue's own document candidate sources,\n * so \"failure-only\" here agrees with the item the panel rendered.\n */\nasync function hasQueuedScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n await ensureSqlTables(execSql, [\n ...documentTables,\n ...documentMoveIntentTables,\n ]);\n const rows = await execSql(\n `SELECT 1 AS present\n WHERE EXISTS (\n SELECT 1 FROM document_history_updates pending\n WHERE pending.app_kind = ? AND pending.local_id = ?\n AND pending.update_id IS NOT NULL\n )\n OR EXISTS (\n SELECT 1 FROM document_pending_attachments attachment\n WHERE attachment.local_id = ?\n )\n OR EXISTS (\n SELECT 1 FROM document_move_intents intent\n WHERE intent.local_id = ? AND intent.intent_type IN ('document.move', 'document.link')\n )\n OR EXISTS (\n SELECT 1 FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.document_id IS NULL\n )\n LIMIT 1`,\n [\n scope.appKind,\n scope.localId,\n scope.localId,\n scope.localId,\n scope.appKind,\n scope.localId,\n ],\n );\n if (rows.length > 0) {\n return true;\n }\n // The queue's deferred-update source has no queued rows to probe: the\n // write lives in the durable history tail, detectable only by the\n // version-vector coverage check.\n return hasDeferredTailScopeWork(execSql, scope);\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import { assertContainerAuthorAccess } from "../../../data/containers/shared/aut
|
|
|
3
3
|
import { assertContainerChildPathFits } from "../../../data/containers/shared/containerPathLimits.js";
|
|
4
4
|
import { buildContainerCreateBody, buildContainerCreateKeyEpoch, buildParentRecipientTargets, deriveContainerCreateManifest, resolveContainerKekEpochId, signContainerCreateEvent, } from "../../../data/containers/shared/events.js";
|
|
5
5
|
import { acknowledgeContainerMutation } from "../../../data/containers/shared/mutationAcknowledgement.js";
|
|
6
|
-
import {
|
|
6
|
+
import { containerManifestRef, getParentCreateContext, readContainerState, wrapContainerKeyToManagedPrincipal, wrapContainerKeyToParent, } from "../../../data/containers/shared/projection.js";
|
|
7
7
|
import { assertContainerKekPathCurrent } from "../../../data/documents/shared/containerKekCurrency.js";
|
|
8
8
|
import { unwrapContainerKekPath } from "../../../data/documents/shared/projection.js";
|
|
9
9
|
import { projectionVerificationOptions, } from "../../../data/documents/shared/types.js";
|
|
@@ -28,8 +28,8 @@ function buildContainerCreateRequest(input) {
|
|
|
28
28
|
...input,
|
|
29
29
|
userRecipientKeys: [],
|
|
30
30
|
}),
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
previousManifestRef: null,
|
|
32
|
+
parentContainerPathRefs: input.parentProjection.path.map(containerManifestRef),
|
|
33
33
|
predecessorBridge: null,
|
|
34
34
|
keyring: null,
|
|
35
35
|
parentKekState: readCanonicalRecord(input.parentKek, "Container create parent KEK state"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["create.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n type ContainerCreateAccessEventBody,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n deriveContainerKekWrappingPublicKey,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../data/containers/shared/containerPathLimits\";\nimport {\n buildContainerCreateBody,\n buildContainerCreateKeyEpoch,\n buildParentRecipientTargets,\n deriveContainerCreateManifest,\n resolveContainerKekEpochId,\n signContainerCreateEvent,\n} from \"../../../data/containers/shared/events\";\nimport { acknowledgeContainerMutation } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n asContainerManifestBundle,\n getParentCreateContext,\n readContainerState,\n wrapContainerKeyToManagedPrincipal,\n wrapContainerKeyToParent,\n} from \"../../../data/containers/shared/projection\";\nimport type {\n BuildContainerCreatePlanInput,\n ContainerCreatePlan,\n ContainerCreatePlanContext,\n ContainerMutationAuthor,\n CreateRemoteContainerResult,\n MaterializedContainerCreatePlan,\n} from \"../../../data/containers/shared/types\";\nimport { assertContainerKekPathCurrent } from \"../../../data/documents/shared/containerKekCurrency\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport {\n type ProjectionVerificationOptions,\n projectionVerificationOptions,\n} from \"../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../data/keyingCanonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport {\n type ContainerCreateRepairState,\n type RemoteContainerCreateInput,\n repairContainerCreateFailure,\n submitRemoteContainerCreate,\n} from \"./createSubmission\";\nimport { containerMutationRequestCore } from \"./mutationRequestCore\";\nimport { requireUnwrappedKek } from \"./rotationContext\";\n\nfunction assertContainerCreatePlanInput(input: {\n containerKey: Uint8Array;\n}): void {\n if (input.containerKey.byteLength !== 32) {\n throw new Error(\"Container KEK material must be 32 bytes\");\n }\n // The child container's organization is derived from the parent projection\n // (see buildContainerCreatePlan), so it always matches the parent by\n // construction — a member writing under another org's shared root is the\n // expected case, not an error. The author supplies only the signer identity.\n}\n\nfunction buildContainerCreateRequest(input: {\n body: ContainerCreateAccessEventBody;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n parentKek: ContainerKekResponse;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"create\", {\n ...input,\n userRecipientKeys: [],\n }),\n previousManifest: null,\n parentContainerPath: input.parentProjection.path.map(\n asContainerManifestBundle,\n ),\n predecessorBridge: null,\n keyring: null,\n parentKekState: readCanonicalRecord(\n input.parentKek,\n \"Container create parent KEK state\",\n ),\n };\n}\n\nasync function resolveContainerCreatePlanContext(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlanContext> {\n assertContainerCreatePlanInput(input);\n assertContainerKekPathCurrent(input.parentProjection.containerKeks);\n const containerId = input.containerId ?? crypto.randomUUID();\n\n return {\n ...input,\n containerId,\n containerKeyPublicKey: await deriveContainerKekWrappingPublicKey({\n containerId,\n keyMaterial: input.containerKey,\n }),\n containerKeyEpochId: await resolveContainerKekEpochId({\n containerId,\n keyEpoch: 1,\n keyMaterial: input.containerKey,\n override: input.containerKeyEpochId,\n }),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parent: getParentCreateContext(input.parentProjection),\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n}\n\nfunction buildChildContainerCreateBody(\n context: ContainerCreatePlanContext,\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"],\n): ContainerCreateAccessEventBody {\n const baseBody = buildContainerCreateBody({\n systemSlot: context.systemSlot ?? null,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId: context.parentProjection.containerId,\n parentManifestHash: context.parent.manifest.manifestHash,\n });\n if (!managedGrant) {\n return baseBody;\n }\n return {\n ...baseBody,\n directGrants: [\n {\n accessLevel: managedGrant.accessLevel,\n subjectId: managedGrant.principalHead.principalId,\n subjectType: managedGrant.principalHead.principalType,\n },\n ],\n referencedPrincipalHeads: [managedGrant.principalHead],\n };\n}\n\n// A managed-principal grant adds a second recipient: the group/organization key\n// wrap alongside the parent-inheritance wrap. The server derives both targets\n// (parent inheritance + directGrant) and requires exactly one wrap each; target\n// order is irrelevant since the key-target hash is normalized.\nasync function buildChildContainerWrapsAndTargets(input: {\n context: ContainerCreatePlanContext;\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n manifestHash: string;\n}): Promise<{\n recipientTargets: ContainerKekRecipientTarget[];\n wraps: ContainerKeyWrap[];\n}> {\n const { context, managedGrant, manifestHash } = input;\n const parentPublicKey = readContainerState(\n context.parent.manifest,\n ).containerKeyPublicKey;\n if (!parentPublicKey)\n throw new Error(\"Container parent wrapping public key is missing\");\n const parentWrap = await wrapContainerKeyToParent({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n parentKek: context.parent.kek,\n parentPublicKey,\n });\n const parentTargets = buildParentRecipientTargets(context.parent.kek);\n if (!managedGrant) {\n return { recipientTargets: parentTargets, wraps: [parentWrap] };\n }\n const managedRecipient = await wrapContainerKeyToManagedPrincipal({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n principalEncapsulationPublicKey:\n managedGrant.principalEncapsulationPublicKey,\n principalHead: managedGrant.principalHead,\n });\n return {\n recipientTargets: [...parentTargets, managedRecipient.recipientTarget],\n wraps: [parentWrap, managedRecipient.wrap],\n };\n}\n\nexport async function buildContainerCreatePlan(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlan> {\n const context = await resolveContainerCreatePlanContext(input);\n const parentContainerId = context.parentProjection.containerId;\n const parentManifestHash = context.parent.manifest.manifestHash;\n const managedGrant = input.managedPrincipalGrant;\n const body = buildChildContainerCreateBody(context, managedGrant);\n // The new container belongs to the parent's organization, not the author's.\n // A member writing under another org's shared root mints a container owned by\n // that org; the author only supplies the signer identity.\n const organizationId = context.parentProjection.organizationId;\n const { event, eventHash } = await signContainerCreateEvent({\n author: context.author,\n body,\n containerId: context.containerId,\n eventId: context.eventId,\n organizationId,\n parentPath: context.parentProjection.path,\n signedAt: context.signedAt,\n });\n const { manifest, manifestHash, state } = await deriveContainerCreateManifest(\n {\n systemSlot: context.systemSlot ?? null,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n directGrants: body.directGrants,\n eventHash,\n metadataDocumentId: context.metadataDocumentId,\n organizationId,\n parentContainerId,\n parentManifestHash,\n referencedPrincipalHeads: body.referencedPrincipalHeads,\n },\n );\n const keyEpoch = buildContainerCreateKeyEpoch({\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n eventHash,\n manifestHash,\n parentContainerKeyEpochId: context.parent.kek.containerKeyEpochId,\n });\n const { recipientTargets, wraps } = await buildChildContainerWrapsAndTargets({\n context,\n managedGrant,\n manifestHash,\n });\n const keyTargetHash =\n await computeContainerKekRecipientTargetHash(recipientTargets);\n const keyEpochHash = await computeContainerKeyEpochHash(keyEpoch);\n return {\n body,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n event,\n eventHash,\n keyEpoch,\n keyEpochHash,\n keyTargetHash,\n manifest,\n manifestHash,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId,\n parentManifestHash,\n recipientTargets,\n request: buildContainerCreateRequest({\n body,\n event,\n keyEpoch,\n manifest,\n manifestHash,\n parentKek: context.parent.kek,\n parentProjection: context.parentProjection,\n principalPolicies: context.principalPolicies ?? [],\n wraps,\n }),\n state,\n wraps,\n };\n}\n\nexport async function buildMaterializedContainerCreatePlan(\n input: {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n managedPrincipalGrant?: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n parentSecretKey: Uint8Array;\n signedAt?: string | undefined;\n // Fetches the parent path's referenced principal policies on demand when\n // they are not cached locally — lets a member create under another org's\n // shared root without having first hydrated that org's group policy.\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedContainerCreatePlan> {\n const containerKey =\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32));\n\n const parentKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.parentProjection,\n secretKey: input.parentSecretKey,\n ...projectionVerificationOptions(input),\n });\n const parent = getParentCreateContext(input.parentProjection);\n requireUnwrappedKek(parentKeksByEpochId, parent.kek, \"Container parent\");\n // Checked on the path verification just accepted, never on the raw response.\n assertContainerChildPathFits(input.parentProjection.path);\n const principalPolicies = input.resolveProjectionUserKey\n ? await collectContainerWriterProjectionPrincipalPolicies({\n execSql: input.execSql,\n projection: input.parentProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })\n : [];\n if (input.resolveProjectionUserKey) {\n assertContainerAuthorAccess({\n author: {\n ...input.author,\n organizationId: input.parentProjection.organizationId,\n },\n projection: input.parentProjection,\n principalPolicies,\n minimumAccess: input.systemSlot ? \"admin\" : \"write\",\n });\n }\n const plan = await buildContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey,\n containerKeyEpochId: input.containerKeyEpochId,\n eventId: input.eventId,\n managedPrincipalGrant: input.managedPrincipalGrant,\n metadataDocumentId: input.metadataDocumentId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n principalPolicies,\n signedAt: input.signedAt,\n });\n\n return {\n containerKey,\n plan,\n };\n}\n\nexport { childContainerWriterProjectionFromCreatePlan } from \"./createProjection\";\n\nasync function createRemoteContainerWithRepairs(input: {\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly eventId: string;\n readonly metadataDocumentId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly request: RemoteContainerCreateInput;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly signedAt: string;\n}): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n let parentProjection = input.parentProjection;\n const repairState: ContainerCreateRepairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const materializedPlan = await buildMaterializedContainerCreatePlan({\n author: input.request.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n containerKeyEpochId: input.request.containerKeyEpochId,\n eventId: input.eventId,\n execSql: input.request.execSql,\n metadataDocumentId: input.metadataDocumentId,\n parentProjection,\n parentSecretKey: input.request.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.request.stillCurrent,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n });\n const submitted = await submitRemoteContainerCreate({\n apiClient: input.request.apiClient,\n plan: materializedPlan.plan,\n stillCurrent: input.request.stillCurrent,\n });\n if (!submitted) return null;\n if (!submitted.ok) {\n const repair = await repairContainerCreateFailure({\n apiClient: input.request.apiClient,\n failure: submitted,\n parentContainerId: input.request.parentContainerId,\n parentProjection,\n state: repairState,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n stillCurrent: input.request.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") {\n return null;\n }\n submitted.report();\n return null;\n }\n const acknowledged = await acknowledgeContainerMutation({\n execSql: input.request.execSql,\n plan: materializedPlan.plan,\n response: submitted.response,\n stillCurrent: input.request.stillCurrent,\n });\n return {\n acknowledged,\n result: {\n containerKey: materializedPlan.containerKey,\n containerId: submitted.response.containerId,\n metadataDocumentId: materializedPlan.plan.metadataDocumentId,\n plan: materializedPlan.plan,\n response: submitted.response,\n },\n };\n }\n}\n\nasync function createRemoteContainerOutcome(\n input: RemoteContainerCreateInput,\n): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container create\",\n );\n const parentProjection =\n input.parentProjection ??\n (await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n ));\n if (!parentProjection) {\n return null;\n }\n return nullOnProjectionVerificationCancellation(() =>\n createRemoteContainerWithRepairs({\n containerId: input.containerId ?? crypto.randomUUID(),\n containerKey:\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32)),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parentProjection,\n request: input,\n resolveProjectionUserKey,\n signedAt: input.signedAt ?? new Date().toISOString(),\n }),\n );\n}\n\nexport async function createRemoteContainer(\n input: RemoteContainerCreateInput,\n): Promise<CreateRemoteContainerResult | null> {\n const outcome = await createRemoteContainerOutcome(input);\n return outcome?.acknowledged && input.stillCurrent?.() !== false\n ? outcome.result\n : null;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["create.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n type ContainerCreateAccessEventBody,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n deriveContainerKekWrappingPublicKey,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../data/containers/shared/containerPathLimits\";\nimport {\n buildContainerCreateBody,\n buildContainerCreateKeyEpoch,\n buildParentRecipientTargets,\n deriveContainerCreateManifest,\n resolveContainerKekEpochId,\n signContainerCreateEvent,\n} from \"../../../data/containers/shared/events\";\nimport { acknowledgeContainerMutation } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n containerManifestRef,\n getParentCreateContext,\n readContainerState,\n wrapContainerKeyToManagedPrincipal,\n wrapContainerKeyToParent,\n} from \"../../../data/containers/shared/projection\";\nimport type {\n BuildContainerCreatePlanInput,\n ContainerCreatePlan,\n ContainerCreatePlanContext,\n ContainerMutationAuthor,\n CreateRemoteContainerResult,\n MaterializedContainerCreatePlan,\n} from \"../../../data/containers/shared/types\";\nimport { assertContainerKekPathCurrent } from \"../../../data/documents/shared/containerKekCurrency\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport {\n type ProjectionVerificationOptions,\n projectionVerificationOptions,\n} from \"../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../data/keyingCanonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport {\n type ContainerCreateRepairState,\n type RemoteContainerCreateInput,\n repairContainerCreateFailure,\n submitRemoteContainerCreate,\n} from \"./createSubmission\";\nimport { containerMutationRequestCore } from \"./mutationRequestCore\";\nimport { requireUnwrappedKek } from \"./rotationContext\";\n\nfunction assertContainerCreatePlanInput(input: {\n containerKey: Uint8Array;\n}): void {\n if (input.containerKey.byteLength !== 32) {\n throw new Error(\"Container KEK material must be 32 bytes\");\n }\n // The child container's organization is derived from the parent projection\n // (see buildContainerCreatePlan), so it always matches the parent by\n // construction — a member writing under another org's shared root is the\n // expected case, not an error. The author supplies only the signer identity.\n}\n\nfunction buildContainerCreateRequest(input: {\n body: ContainerCreateAccessEventBody;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n parentKek: ContainerKekResponse;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"create\", {\n ...input,\n userRecipientKeys: [],\n }),\n previousManifestRef: null,\n parentContainerPathRefs:\n input.parentProjection.path.map(containerManifestRef),\n predecessorBridge: null,\n keyring: null,\n parentKekState: readCanonicalRecord(\n input.parentKek,\n \"Container create parent KEK state\",\n ),\n };\n}\n\nasync function resolveContainerCreatePlanContext(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlanContext> {\n assertContainerCreatePlanInput(input);\n assertContainerKekPathCurrent(input.parentProjection.containerKeks);\n const containerId = input.containerId ?? crypto.randomUUID();\n\n return {\n ...input,\n containerId,\n containerKeyPublicKey: await deriveContainerKekWrappingPublicKey({\n containerId,\n keyMaterial: input.containerKey,\n }),\n containerKeyEpochId: await resolveContainerKekEpochId({\n containerId,\n keyEpoch: 1,\n keyMaterial: input.containerKey,\n override: input.containerKeyEpochId,\n }),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parent: getParentCreateContext(input.parentProjection),\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n}\n\nfunction buildChildContainerCreateBody(\n context: ContainerCreatePlanContext,\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"],\n): ContainerCreateAccessEventBody {\n const baseBody = buildContainerCreateBody({\n systemSlot: context.systemSlot ?? null,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId: context.parentProjection.containerId,\n parentManifestHash: context.parent.manifest.manifestHash,\n });\n if (!managedGrant) {\n return baseBody;\n }\n return {\n ...baseBody,\n directGrants: [\n {\n accessLevel: managedGrant.accessLevel,\n subjectId: managedGrant.principalHead.principalId,\n subjectType: managedGrant.principalHead.principalType,\n },\n ],\n referencedPrincipalHeads: [managedGrant.principalHead],\n };\n}\n\n// A managed-principal grant adds a second recipient: the group/organization key\n// wrap alongside the parent-inheritance wrap. The server derives both targets\n// (parent inheritance + directGrant) and requires exactly one wrap each; target\n// order is irrelevant since the key-target hash is normalized.\nasync function buildChildContainerWrapsAndTargets(input: {\n context: ContainerCreatePlanContext;\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n manifestHash: string;\n}): Promise<{\n recipientTargets: ContainerKekRecipientTarget[];\n wraps: ContainerKeyWrap[];\n}> {\n const { context, managedGrant, manifestHash } = input;\n const parentPublicKey = readContainerState(\n context.parent.manifest,\n ).containerKeyPublicKey;\n if (!parentPublicKey)\n throw new Error(\"Container parent wrapping public key is missing\");\n const parentWrap = await wrapContainerKeyToParent({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n parentKek: context.parent.kek,\n parentPublicKey,\n });\n const parentTargets = buildParentRecipientTargets(context.parent.kek);\n if (!managedGrant) {\n return { recipientTargets: parentTargets, wraps: [parentWrap] };\n }\n const managedRecipient = await wrapContainerKeyToManagedPrincipal({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n principalEncapsulationPublicKey:\n managedGrant.principalEncapsulationPublicKey,\n principalHead: managedGrant.principalHead,\n });\n return {\n recipientTargets: [...parentTargets, managedRecipient.recipientTarget],\n wraps: [parentWrap, managedRecipient.wrap],\n };\n}\n\nexport async function buildContainerCreatePlan(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlan> {\n const context = await resolveContainerCreatePlanContext(input);\n const parentContainerId = context.parentProjection.containerId;\n const parentManifestHash = context.parent.manifest.manifestHash;\n const managedGrant = input.managedPrincipalGrant;\n const body = buildChildContainerCreateBody(context, managedGrant);\n // The new container belongs to the parent's organization, not the author's.\n // A member writing under another org's shared root mints a container owned by\n // that org; the author only supplies the signer identity.\n const organizationId = context.parentProjection.organizationId;\n const { event, eventHash } = await signContainerCreateEvent({\n author: context.author,\n body,\n containerId: context.containerId,\n eventId: context.eventId,\n organizationId,\n parentPath: context.parentProjection.path,\n signedAt: context.signedAt,\n });\n const { manifest, manifestHash, state } = await deriveContainerCreateManifest(\n {\n systemSlot: context.systemSlot ?? null,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n directGrants: body.directGrants,\n eventHash,\n metadataDocumentId: context.metadataDocumentId,\n organizationId,\n parentContainerId,\n parentManifestHash,\n referencedPrincipalHeads: body.referencedPrincipalHeads,\n },\n );\n const keyEpoch = buildContainerCreateKeyEpoch({\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n eventHash,\n manifestHash,\n parentContainerKeyEpochId: context.parent.kek.containerKeyEpochId,\n });\n const { recipientTargets, wraps } = await buildChildContainerWrapsAndTargets({\n context,\n managedGrant,\n manifestHash,\n });\n const keyTargetHash =\n await computeContainerKekRecipientTargetHash(recipientTargets);\n const keyEpochHash = await computeContainerKeyEpochHash(keyEpoch);\n return {\n body,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n event,\n eventHash,\n keyEpoch,\n keyEpochHash,\n keyTargetHash,\n manifest,\n manifestHash,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId,\n parentManifestHash,\n recipientTargets,\n request: buildContainerCreateRequest({\n body,\n event,\n keyEpoch,\n manifest,\n manifestHash,\n parentKek: context.parent.kek,\n parentProjection: context.parentProjection,\n principalPolicies: context.principalPolicies ?? [],\n wraps,\n }),\n state,\n wraps,\n };\n}\n\nexport async function buildMaterializedContainerCreatePlan(\n input: {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n managedPrincipalGrant?: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n parentSecretKey: Uint8Array;\n signedAt?: string | undefined;\n // Fetches the parent path's referenced principal policies on demand when\n // they are not cached locally — lets a member create under another org's\n // shared root without having first hydrated that org's group policy.\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedContainerCreatePlan> {\n const containerKey =\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32));\n\n const parentKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.parentProjection,\n secretKey: input.parentSecretKey,\n ...projectionVerificationOptions(input),\n });\n const parent = getParentCreateContext(input.parentProjection);\n requireUnwrappedKek(parentKeksByEpochId, parent.kek, \"Container parent\");\n // Checked on the path verification just accepted, never on the raw response.\n assertContainerChildPathFits(input.parentProjection.path);\n const principalPolicies = input.resolveProjectionUserKey\n ? await collectContainerWriterProjectionPrincipalPolicies({\n execSql: input.execSql,\n projection: input.parentProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })\n : [];\n if (input.resolveProjectionUserKey) {\n assertContainerAuthorAccess({\n author: {\n ...input.author,\n organizationId: input.parentProjection.organizationId,\n },\n projection: input.parentProjection,\n principalPolicies,\n minimumAccess: input.systemSlot ? \"admin\" : \"write\",\n });\n }\n const plan = await buildContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey,\n containerKeyEpochId: input.containerKeyEpochId,\n eventId: input.eventId,\n managedPrincipalGrant: input.managedPrincipalGrant,\n metadataDocumentId: input.metadataDocumentId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n principalPolicies,\n signedAt: input.signedAt,\n });\n\n return {\n containerKey,\n plan,\n };\n}\n\nexport { childContainerWriterProjectionFromCreatePlan } from \"./createProjection\";\n\nasync function createRemoteContainerWithRepairs(input: {\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly eventId: string;\n readonly metadataDocumentId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly request: RemoteContainerCreateInput;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly signedAt: string;\n}): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n let parentProjection = input.parentProjection;\n const repairState: ContainerCreateRepairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const materializedPlan = await buildMaterializedContainerCreatePlan({\n author: input.request.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n containerKeyEpochId: input.request.containerKeyEpochId,\n eventId: input.eventId,\n execSql: input.request.execSql,\n metadataDocumentId: input.metadataDocumentId,\n parentProjection,\n parentSecretKey: input.request.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.request.stillCurrent,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n });\n const submitted = await submitRemoteContainerCreate({\n apiClient: input.request.apiClient,\n plan: materializedPlan.plan,\n stillCurrent: input.request.stillCurrent,\n });\n if (!submitted) return null;\n if (!submitted.ok) {\n const repair = await repairContainerCreateFailure({\n apiClient: input.request.apiClient,\n failure: submitted,\n parentContainerId: input.request.parentContainerId,\n parentProjection,\n state: repairState,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n stillCurrent: input.request.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") {\n return null;\n }\n submitted.report();\n return null;\n }\n const acknowledged = await acknowledgeContainerMutation({\n execSql: input.request.execSql,\n plan: materializedPlan.plan,\n response: submitted.response,\n stillCurrent: input.request.stillCurrent,\n });\n return {\n acknowledged,\n result: {\n containerKey: materializedPlan.containerKey,\n containerId: submitted.response.containerId,\n metadataDocumentId: materializedPlan.plan.metadataDocumentId,\n plan: materializedPlan.plan,\n response: submitted.response,\n },\n };\n }\n}\n\nasync function createRemoteContainerOutcome(\n input: RemoteContainerCreateInput,\n): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container create\",\n );\n const parentProjection =\n input.parentProjection ??\n (await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n ));\n if (!parentProjection) {\n return null;\n }\n return nullOnProjectionVerificationCancellation(() =>\n createRemoteContainerWithRepairs({\n containerId: input.containerId ?? crypto.randomUUID(),\n containerKey:\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32)),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parentProjection,\n request: input,\n resolveProjectionUserKey,\n signedAt: input.signedAt ?? new Date().toISOString(),\n }),\n );\n}\n\nexport async function createRemoteContainer(\n input: RemoteContainerCreateInput,\n): Promise<CreateRemoteContainerResult | null> {\n const outcome = await createRemoteContainerOutcome(input);\n return outcome?.acknowledged && input.stillCurrent?.() !== false\n ? outcome.result\n : null;\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assertContainerAuthorAccess } from "../../../data/containers/shared/authorAccess.js";
|
|
2
2
|
import { assertContainerChildPathFits } from "../../../data/containers/shared/containerPathLimits.js";
|
|
3
|
-
import { asContainerManifestBundle, getTargetContainerContext, readContainerState, uniqueSortedManifestHashes, } from "../../../data/containers/shared/projection.js";
|
|
3
|
+
import { asContainerManifestBundle, containerManifestRef, getTargetContainerContext, readContainerState, uniqueSortedManifestHashes, } from "../../../data/containers/shared/projection.js";
|
|
4
4
|
import { unwrapContainerKekPath } from "../../../data/documents/shared/projection.js";
|
|
5
5
|
import { projectionVerificationOptions } from "../../../data/documents/shared/types.js";
|
|
6
6
|
import { readCanonicalRecord } from "../../../data/keyingCanonicalJson.js";
|
|
@@ -15,7 +15,7 @@ function buildContainerMoveRequest(input) {
|
|
|
15
15
|
return {
|
|
16
16
|
...containerMutationRequestCore("move", input),
|
|
17
17
|
...previousPathRequestFields(input.previousManifest, input.previousProjection),
|
|
18
|
-
|
|
18
|
+
destinationParentContainerPathRefs: input.destinationParentProjection.path.map(containerManifestRef),
|
|
19
19
|
predecessorBridge: readCanonicalRecord(input.predecessorBridge, "Container move predecessor bridge"),
|
|
20
20
|
keyring: readCanonicalRecord(input.keyring, "Container move keyring"),
|
|
21
21
|
parentKekState: readCanonicalRecord(input.destinationParentKek, "Container move destination parent KEK state"),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"move.js","sourceRoot":"","sources":["move.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AccessEvent,\n AccessManifest,\n ContainerAccessManifestState,\n ContainerKekKeyring,\n ContainerKekPredecessorBridge,\n ContainerKeyEpoch,\n ContainerKeyWrap,\n ContainerMoveAccessEventBody,\n ContainerUserRecipientKey,\n VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWire,\n ContainerMutationRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerRotationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../data/containers/shared/containerPathLimits\";\nimport {\n asContainerManifestBundle,\n getTargetContainerContext,\n readContainerState,\n uniqueSortedManifestHashes,\n} from \"../../../data/containers/shared/projection\";\nimport type {\n BuildMaterializedContainerMovePlanInput,\n ContainerMoveApi,\n ContainerMovePlan,\n ContainerMutationAuthor,\n MaterializedContainerMovePlan,\n} from \"../../../data/containers/shared/types\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport { projectionVerificationOptions } from \"../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../data/keyingCanonicalJson\";\nimport {\n nullOnProjectionVerificationCancellation,\n type ProjectionUserKeyResolver,\n type ReferencedPrincipalPolicyWarmer,\n requireProjectionUserKeyResolver,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { SecurityIncidentReporter } from \"../../../data/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n buildMoveRotationWithBody,\n deriveMoveManifestArtifacts,\n} from \"./moveArtifacts\";\nimport {\n buildContainerMoveWraps,\n collectContainerMovePrincipalPolicies,\n} from \"./moveWraps\";\nimport {\n containerMutationRequestCore,\n previousPathRequestFields,\n} from \"./mutationRequestCore\";\nimport {\n submitAcknowledgedContainerMutation,\n submitContainerRotation,\n} from \"./mutationSubmit\";\nimport { containerWriterProjectionFromRotationPlan } from \"./rekeyProjection\";\nimport {\n requireUnwrappedKek,\n type SignedRotationTarget,\n signedRotationTarget,\n} from \"./rotationContext\";\n\nfunction buildContainerMoveRequest(input: {\n body: ContainerMoveAccessEventBody;\n destinationParentKek: ContainerKekResponse;\n destinationParentProjection: ContainerWriterProjectionResponse;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n previousProjection: ContainerWriterProjectionResponse;\n predecessorBridge: ContainerKekPredecessorBridge;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n userRecipientKeys: readonly ContainerUserRecipientKey[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"move\", input),\n ...previousPathRequestFields(\n input.previousManifest,\n input.previousProjection,\n ),\n destinationParentContainerPath: input.destinationParentProjection.path.map(\n asContainerManifestBundle,\n ),\n predecessorBridge: readCanonicalRecord(\n input.predecessorBridge,\n \"Container move predecessor bridge\",\n ),\n keyring: readCanonicalRecord(input.keyring, \"Container move keyring\"),\n parentKekState: readCanonicalRecord(\n input.destinationParentKek,\n \"Container move destination parent KEK state\",\n ),\n };\n}\n\nasync function unwrapMoveContainerKeys(input: {\n destinationParentProjection: ContainerWriterProjectionResponse;\n execSql: ExecSql;\n previousProjection: ContainerWriterProjectionResponse;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<{\n containerKey: Uint8Array;\n destinationParent: ReturnType<typeof getTargetContainerContext>;\n source: SignedRotationTarget;\n}> {\n const verifiedByHash = new Map<string, VerifiedContainerAccessManifest>();\n const keksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.previousProjection,\n secretKey: input.targetSecretKey,\n verifiedByHash,\n ...projectionVerificationOptions(input),\n });\n const source = signedRotationTarget(input.previousProjection, verifiedByHash);\n const containerKey = requireUnwrappedKek(\n keksByEpochId,\n source.kek,\n \"Container move source\",\n );\n\n const destinationKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.destinationParentProjection,\n secretKey: input.targetSecretKey,\n ...projectionVerificationOptions(input),\n });\n const destinationParent = getTargetContainerContext(\n input.destinationParentProjection,\n );\n requireUnwrappedKek(\n destinationKeksByEpochId,\n destinationParent.kek,\n \"Container move destination parent\",\n );\n\n return { containerKey, destinationParent, source };\n}\n\nfunction assertContainerMoveOrganizations(input: {\n authorOrganizationId: string;\n destinationState: ContainerAccessManifestState;\n previousState: ContainerAccessManifestState;\n}): void {\n if (input.previousState.organizationId !== input.authorOrganizationId) {\n throw new Error(\"Container move author organization mismatch\");\n }\n if (input.destinationState.organizationId !== input.authorOrganizationId) {\n throw new Error(\"Container move destination organization mismatch\");\n }\n}\n\nfunction readContainerMoveStates(input: {\n authorOrganizationId: string;\n destinationParent: ReturnType<typeof getTargetContainerContext>;\n source: ReturnType<typeof getTargetContainerContext>;\n}) {\n const previousState = readContainerState(input.source.manifest);\n const destinationState = readContainerState(input.destinationParent.manifest);\n assertContainerMoveOrganizations({\n authorOrganizationId: input.authorOrganizationId,\n destinationState,\n previousState,\n });\n return { destinationState, previousState };\n}\n\nfunction containerMoveDependencyManifestHashes(input: {\n destinationParentProjection: ContainerWriterProjectionResponse;\n previousProjection: ContainerWriterProjectionResponse;\n}): string[] {\n return [\n ...uniqueSortedManifestHashes(input.previousProjection.path),\n ...uniqueSortedManifestHashes(input.destinationParentProjection.path),\n ];\n}\n\nfunction buildContainerMovePlanResult(input: {\n body: ContainerMoveAccessEventBody;\n containerId: string;\n containerKey: Uint8Array;\n containerKeyEpochId: string;\n destinationParentKek: ContainerKekResponse;\n destinationParentProjection: ContainerWriterProjectionResponse;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n previousProjection: ContainerWriterProjectionResponse;\n predecessorBridge: ContainerKekPredecessorBridge;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}): MaterializedContainerMovePlan {\n const plan: ContainerMovePlan = {\n body: input.body,\n containerId: input.containerId,\n containerKeyEpochId: input.containerKeyEpochId,\n event: input.event,\n eventHash: input.eventHash,\n keyEpoch: input.keyEpoch,\n keyring: input.keyring,\n manifest: input.manifest,\n manifestHash: input.manifestHash,\n previousManifest: input.previousManifest,\n request: buildContainerMoveRequest({\n body: input.body,\n destinationParentKek: input.destinationParentKek,\n destinationParentProjection: input.destinationParentProjection,\n event: input.event,\n keyEpoch: input.keyEpoch,\n keyring: input.keyring,\n manifest: input.manifest,\n manifestHash: input.manifestHash,\n previousManifest: input.previousManifest,\n previousProjection: input.previousProjection,\n predecessorBridge: input.predecessorBridge,\n principalPolicies: input.principalPolicies,\n userRecipientKeys: input.userRecipientKeys,\n wraps: input.wraps,\n }),\n state: input.state,\n wraps: input.wraps,\n };\n\n return { containerKey: input.containerKey, plan };\n}\n\ntype MaterializedContainerMoveInput =\n BuildMaterializedContainerMovePlanInput & {\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n };\n\nasync function collectAuthorizedMovePolicies(\n input: MaterializedContainerMoveInput,\n) {\n const principalPolicies = await collectContainerMovePrincipalPolicies({\n ...input,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n assertContainerAuthorAccess({\n author: input.author,\n projection: input.previousProjection,\n principalPolicies,\n minimumAccess: \"admin\",\n });\n assertContainerAuthorAccess({\n author: input.author,\n projection: input.destinationParentProjection,\n principalPolicies,\n minimumAccess: \"write\",\n });\n return principalPolicies;\n}\n\nasync function buildMaterializedContainerMovePlan(\n input: MaterializedContainerMoveInput,\n): Promise<MaterializedContainerMovePlan> {\n const {\n containerKey: predecessorContainerKey,\n destinationParent,\n source,\n } = await unwrapMoveContainerKeys({\n destinationParentProjection: input.destinationParentProjection,\n execSql: input.execSql,\n previousProjection: input.previousProjection,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n // Only a verified path is a final depth refusal; a padded unverified path\n // must fail verification (an incident), never look like an honest refusal.\n assertContainerChildPathFits(input.destinationParentProjection.path);\n const { destinationState, previousState } = readContainerMoveStates({\n authorOrganizationId: input.author.organizationId,\n destinationParent,\n source,\n });\n const principalPolicies = await collectAuthorizedMovePolicies(input);\n const {\n body,\n containerKey,\n containerKeyEpochId,\n keyring,\n predecessorBridge,\n } = await buildMoveRotationWithBody({\n destinationParent,\n destinationState,\n override: input.containerKeyEpochId,\n predecessorContainerKey,\n previousState,\n source,\n });\n const { event, eventHash, keyEpoch, manifest, manifestHash, state } =\n await deriveMoveManifestArtifacts({\n body,\n containerKeyEpochId,\n destinationParent,\n previousState,\n signing: {\n author: input.author,\n dependencyManifestHashes: containerMoveDependencyManifestHashes(input),\n eventId: input.eventId,\n signedAt: input.signedAt,\n },\n source,\n });\n const { userRecipientKeys, wraps } = await buildContainerMoveWraps({\n principalPolicies,\n containerKey,\n containerKeyEpochId,\n destinationParentKek: destinationParent.kek,\n destinationParentProjection: input.destinationParentProjection,\n execSql: input.execSql,\n manifestHash,\n previousProjection: input.previousProjection,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n state,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n\n return buildContainerMovePlanResult({\n body,\n containerKey,\n containerId: previousState.containerId,\n containerKeyEpochId,\n destinationParentKek: destinationParent.kek,\n destinationParentProjection: input.destinationParentProjection,\n event,\n eventHash,\n keyEpoch,\n keyring,\n manifest,\n manifestHash,\n previousManifest: asContainerManifestBundle(source.manifest),\n previousProjection: input.previousProjection,\n predecessorBridge,\n principalPolicies,\n state,\n userRecipientKeys,\n wraps,\n });\n}\n\nexport async function moveRemoteContainer(input: {\n reportSecurityIncident: SecurityIncidentReporter;\n apiClient: ContainerMoveApi;\n author: ContainerMutationAuthor;\n containerId: string;\n destinationParentContainerId: string;\n eventId?: string | undefined;\n execSql: ExecSql;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<{\n containerKey: Uint8Array;\n plan: ContainerMovePlan;\n response: ContainerRotationResponse;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container move\",\n );\n const [previousProjection, destinationParentProjection] = await Promise.all([\n input.apiClient.getContainerWriterProjection(input.containerId),\n input.apiClient.getContainerWriterProjection(\n input.destinationParentContainerId,\n ),\n ]);\n if (!previousProjection || !destinationParentProjection) {\n return null;\n }\n\n const materializedPlan = await nullOnProjectionVerificationCancellation(() =>\n buildMaterializedContainerMovePlan({\n author: input.author,\n eventId: input.eventId,\n execSql: input.execSql,\n previousProjection,\n destinationParentProjection,\n resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n );\n if (!materializedPlan) return null;\n return submitAcknowledgedContainerMutation({\n reportSecurityIncident: input.reportSecurityIncident,\n recitationPolicies: [],\n apiClient: input.apiClient,\n author: input.author,\n carriedRekeys: {\n planning: {\n apiClient: input.apiClient,\n author: input.author,\n execSql: input.execSql,\n knownContainerKeks: new Map([\n [\n materializedPlan.plan.containerKeyEpochId,\n materializedPlan.containerKey,\n ],\n ]),\n resolveProjectionUserKey: resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n },\n rotated: () =>\n containerWriterProjectionFromRotationPlan({\n ancestors: destinationParentProjection,\n plan: materializedPlan.plan,\n previousProjection,\n }),\n },\n containerKey: materializedPlan.containerKey,\n execSql: input.execSql,\n plan: materializedPlan.plan,\n stillCurrent: input.stillCurrent,\n submit: (carried) => {\n const request = carried.length\n ? { ...materializedPlan.plan.request, containerRekeys: [...carried] }\n : materializedPlan.plan.request;\n const options = {\n expectedPaymentRequiredOrganizationId: input.author.organizationId,\n };\n const { moveContainerResult } = input.apiClient;\n return submitContainerRotation({\n plain: () =>\n input.apiClient.moveContainer(input.containerId, request, options),\n result: moveContainerResult\n ? () =>\n moveContainerResult.call(\n input.apiClient,\n input.containerId,\n request,\n { ...options, reportErrors: false },\n )\n : undefined,\n });\n },\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"move.js","sourceRoot":"","sources":["move.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,2BAA2B,EAAE,MAAM,8CAA8C,CAAC;AAC3F,OAAO,EAAE,4BAA4B,EAAE,MAAM,qDAAqD,CAAC;AACnG,OAAO,EACL,yBAAyB,EACzB,oBAAoB,EACpB,yBAAyB,EACzB,kBAAkB,EAClB,0BAA0B,GAC3B,MAAM,4CAA4C,CAAC;AAQpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,6BAA6B,EAAE,MAAM,sCAAsC,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EACL,wCAAwC,EAGxC,gCAAgC,GACjC,MAAM,4CAA4C,CAAC;AAIpD,OAAO,EACL,yBAAyB,EACzB,2BAA2B,GAC5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,uBAAuB,EACvB,qCAAqC,GACtC,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,4BAA4B,EAC5B,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mCAAmC,EACnC,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,yCAAyC,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EACL,mBAAmB,EAEnB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAE3B,SAAS,yBAAyB,CAAC,KAelC;IACC,OAAO;QACL,GAAG,4BAA4B,CAAC,MAAM,EAAE,KAAK,CAAC;QAC9C,GAAG,yBAAyB,CAC1B,KAAK,CAAC,gBAAgB,EACtB,KAAK,CAAC,kBAAkB,CACzB;QACD,kCAAkC,EAChC,KAAK,CAAC,2BAA2B,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC;QAClE,iBAAiB,EAAE,mBAAmB,CACpC,KAAK,CAAC,iBAAiB,EACvB,mCAAmC,CACpC;QACD,OAAO,EAAE,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,wBAAwB,CAAC;QACrE,cAAc,EAAE,mBAAmB,CACjC,KAAK,CAAC,oBAAoB,EAC1B,6CAA6C,CAC9C;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,KAQtC;IAKC,MAAM,cAAc,GAAG,IAAI,GAAG,EAA2C,CAAC;IAC1E,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC;QACjD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,kBAAkB;QACpC,SAAS,EAAE,KAAK,CAAC,eAAe;QAChC,cAAc;QACd,GAAG,6BAA6B,CAAC,KAAK,CAAC;KACxC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,mBAAmB,CACtC,aAAa,EACb,MAAM,CAAC,GAAG,EACV,uBAAuB,CACxB,CAAC;IAEF,MAAM,wBAAwB,GAAG,MAAM,sBAAsB,CAAC;QAC5D,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,UAAU,EAAE,KAAK,CAAC,2BAA2B;QAC7C,SAAS,EAAE,KAAK,CAAC,eAAe;QAChC,GAAG,6BAA6B,CAAC,KAAK,CAAC;KACxC,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG,yBAAyB,CACjD,KAAK,CAAC,2BAA2B,CAClC,CAAC;IACF,mBAAmB,CACjB,wBAAwB,EACxB,iBAAiB,CAAC,GAAG,EACrB,mCAAmC,CACpC,CAAC;IAEF,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,SAAS,gCAAgC,CAAC,KAIzC;IACC,IAAI,KAAK,CAAC,aAAa,CAAC,cAAc,KAAK,KAAK,CAAC,oBAAoB,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,KAAK,CAAC,gBAAgB,CAAC,cAAc,KAAK,KAAK,CAAC,oBAAoB,EAAE,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;AACH,CAAC;AAED,SAAS,uBAAuB,CAAC,KAIhC;IACC,MAAM,aAAa,GAAG,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChE,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAC9E,gCAAgC,CAAC;QAC/B,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,gBAAgB;QAChB,aAAa;KACd,CAAC,CAAC;IACH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,qCAAqC,CAAC,KAG9C;IACC,OAAO;QACL,GAAG,0BAA0B,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC;QAC5D,GAAG,0BAA0B,CAAC,KAAK,CAAC,2BAA2B,CAAC,IAAI,CAAC;KACtE,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CAAC,KAoBrC;IACC,MAAM,IAAI,GAAsB;QAC9B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;QAC9C,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,OAAO,EAAE,yBAAyB,CAAC;YACjC,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;YAChD,2BAA2B,EAAE,KAAK,CAAC,2BAA2B;YAC9D,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;YAC5C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,KAAK,EAAE,KAAK,CAAC,KAAK;KACnB,CAAC;IAEF,OAAO,EAAE,YAAY,EAAE,KAAK,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC;AACpD,CAAC;AAWD,KAAK,UAAU,6BAA6B,CAC1C,KAAqC;IAErC,MAAM,iBAAiB,GAAG,MAAM,qCAAqC,CAAC;QACpE,GAAG,KAAK;QACR,cAAc,EAAE,KAAK,CAAC,wBAAwB;KAC/C,CAAC,CAAC;IACH,2BAA2B,CAAC;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,kBAAkB;QACpC,iBAAiB;QACjB,aAAa,EAAE,OAAO;KACvB,CAAC,CAAC;IACH,2BAA2B,CAAC;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,UAAU,EAAE,KAAK,CAAC,2BAA2B;QAC7C,iBAAiB;QACjB,aAAa,EAAE,OAAO;KACvB,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,kCAAkC,CAC/C,KAAqC;IAErC,MAAM,EACJ,YAAY,EAAE,uBAAuB,EACrC,iBAAiB,EACjB,MAAM,GACP,GAAG,MAAM,uBAAuB,CAAC;QAChC,2BAA2B,EAAE,KAAK,CAAC,2BAA2B;QAC9D,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;QACxD,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,+BAA+B,EAAE,KAAK,CAAC,+BAA+B;KACvE,CAAC,CAAC;IACH,0EAA0E;IAC1E,2EAA2E;IAC3E,4BAA4B,CAAC,KAAK,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,EAAE,gBAAgB,EAAE,aAAa,EAAE,GAAG,uBAAuB,CAAC;QAClE,oBAAoB,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;QACjD,iBAAiB;QACjB,MAAM;KACP,CAAC,CAAC;IACH,MAAM,iBAAiB,GAAG,MAAM,6BAA6B,CAAC,KAAK,CAAC,CAAC;IACrE,MAAM,EACJ,IAAI,EACJ,YAAY,EACZ,mBAAmB,EACnB,OAAO,EACP,iBAAiB,GAClB,GAAG,MAAM,yBAAyB,CAAC;QAClC,iBAAiB;QACjB,gBAAgB;QAChB,QAAQ,EAAE,KAAK,CAAC,mBAAmB;QACnC,uBAAuB;QACvB,aAAa;QACb,MAAM;KACP,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,GACjE,MAAM,2BAA2B,CAAC;QAChC,IAAI;QACJ,mBAAmB;QACnB,iBAAiB;QACjB,aAAa;QACb,OAAO,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,wBAAwB,EAAE,qCAAqC,CAAC,KAAK,CAAC;YACtE,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;SACzB;QACD,MAAM;KACP,CAAC,CAAC;IACL,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,GAAG,MAAM,uBAAuB,CAAC;QACjE,iBAAiB;QACjB,YAAY;QACZ,mBAAmB;QACnB,oBAAoB,EAAE,iBAAiB,CAAC,GAAG;QAC3C,2BAA2B,EAAE,KAAK,CAAC,2BAA2B;QAC9D,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,YAAY;QACZ,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;QACxD,KAAK;QACL,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,+BAA+B,EAAE,KAAK,CAAC,+BAA+B;KACvE,CAAC,CAAC;IAEH,OAAO,4BAA4B,CAAC;QAClC,IAAI;QACJ,YAAY;QACZ,WAAW,EAAE,aAAa,CAAC,WAAW;QACtC,mBAAmB;QACnB,oBAAoB,EAAE,iBAAiB,CAAC,GAAG;QAC3C,2BAA2B,EAAE,KAAK,CAAC,2BAA2B;QAC9D,KAAK;QACL,SAAS;QACT,QAAQ;QACR,OAAO;QACP,QAAQ;QACR,YAAY;QACZ,gBAAgB,EAAE,yBAAyB,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC5D,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,iBAAiB;QACjB,iBAAiB;QACjB,KAAK;QACL,iBAAiB;QACjB,KAAK;KACN,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,KAazC;IAKC,MAAM,wBAAwB,GAAG,gCAAgC,CAC/D,KAAK,CAAC,wBAAwB,EAC9B,uBAAuB,CACxB,CAAC;IACF,MAAM,CAAC,kBAAkB,EAAE,2BAA2B,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC1E,KAAK,CAAC,SAAS,CAAC,4BAA4B,CAAC,KAAK,CAAC,WAAW,CAAC;QAC/D,KAAK,CAAC,SAAS,CAAC,4BAA4B,CAC1C,KAAK,CAAC,4BAA4B,CACnC;KACF,CAAC,CAAC;IACH,IAAI,CAAC,kBAAkB,IAAI,CAAC,2BAA2B,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,wCAAwC,CAAC,GAAG,EAAE,CAC3E,kCAAkC,CAAC;QACjC,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,kBAAkB;QAClB,2BAA2B;QAC3B,wBAAwB;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,+BAA+B,EAAE,KAAK,CAAC,+BAA+B;KACvE,CAAC,CACH,CAAC;IACF,IAAI,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,mCAAmC,CAAC;QACzC,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,kBAAkB,EAAE,EAAE;QACtB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,aAAa,EAAE;YACb,QAAQ,EAAE;gBACR,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,kBAAkB,EAAE,IAAI,GAAG,CAAC;oBAC1B;wBACE,gBAAgB,CAAC,IAAI,CAAC,mBAAmB;wBACzC,gBAAgB,CAAC,YAAY;qBAC9B;iBACF,CAAC;gBACF,wBAAwB,EAAE,wBAAwB;gBAClD,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,eAAe,EAAE,KAAK,CAAC,eAAe;gBACtC,+BAA+B,EAAE,KAAK,CAAC,+BAA+B;aACvE;YACD,OAAO,EAAE,GAAG,EAAE,CACZ,yCAAyC,CAAC;gBACxC,SAAS,EAAE,2BAA2B;gBACtC,IAAI,EAAE,gBAAgB,CAAC,IAAI;gBAC3B,kBAAkB;aACnB,CAAC;SACL;QACD,YAAY,EAAE,gBAAgB,CAAC,YAAY;QAC3C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,gBAAgB,CAAC,IAAI;QAC3B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE;YAClB,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM;gBAC5B,CAAC,CAAC,EAAE,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE;gBACrE,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC;YAClC,MAAM,OAAO,GAAG;gBACd,qCAAqC,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;aACnE,CAAC;YACF,MAAM,EAAE,mBAAmB,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;YAChD,OAAO,uBAAuB,CAAC;gBAC7B,KAAK,EAAE,GAAG,EAAE,CACV,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC;gBACpE,MAAM,EAAE,mBAAmB;oBACzB,CAAC,CAAC,GAAG,EAAE,CACH,mBAAmB,CAAC,IAAI,CACtB,KAAK,CAAC,SAAS,EACf,KAAK,CAAC,WAAW,EACjB,OAAO,EACP,EAAE,GAAG,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,CACpC;oBACL,CAAC,CAAC,SAAS;aACd,CAAC,CAAC;QACL,CAAC;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type {\n AccessEvent,\n AccessManifest,\n ContainerAccessManifestState,\n ContainerKekKeyring,\n ContainerKekPredecessorBridge,\n ContainerKeyEpoch,\n ContainerKeyWrap,\n ContainerMoveAccessEventBody,\n ContainerUserRecipientKey,\n VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWire,\n ContainerMutationRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerRotationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../data/containers/shared/containerPathLimits\";\nimport {\n asContainerManifestBundle,\n containerManifestRef,\n getTargetContainerContext,\n readContainerState,\n uniqueSortedManifestHashes,\n} from \"../../../data/containers/shared/projection\";\nimport type {\n BuildMaterializedContainerMovePlanInput,\n ContainerMoveApi,\n ContainerMovePlan,\n ContainerMutationAuthor,\n MaterializedContainerMovePlan,\n} from \"../../../data/containers/shared/types\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport { projectionVerificationOptions } from \"../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../data/keyingCanonicalJson\";\nimport {\n nullOnProjectionVerificationCancellation,\n type ProjectionUserKeyResolver,\n type ReferencedPrincipalPolicyWarmer,\n requireProjectionUserKeyResolver,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { SecurityIncidentReporter } from \"../../../data/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n buildMoveRotationWithBody,\n deriveMoveManifestArtifacts,\n} from \"./moveArtifacts\";\nimport {\n buildContainerMoveWraps,\n collectContainerMovePrincipalPolicies,\n} from \"./moveWraps\";\nimport {\n containerMutationRequestCore,\n previousPathRequestFields,\n} from \"./mutationRequestCore\";\nimport {\n submitAcknowledgedContainerMutation,\n submitContainerRotation,\n} from \"./mutationSubmit\";\nimport { containerWriterProjectionFromRotationPlan } from \"./rekeyProjection\";\nimport {\n requireUnwrappedKek,\n type SignedRotationTarget,\n signedRotationTarget,\n} from \"./rotationContext\";\n\nfunction buildContainerMoveRequest(input: {\n body: ContainerMoveAccessEventBody;\n destinationParentKek: ContainerKekResponse;\n destinationParentProjection: ContainerWriterProjectionResponse;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n previousProjection: ContainerWriterProjectionResponse;\n predecessorBridge: ContainerKekPredecessorBridge;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n userRecipientKeys: readonly ContainerUserRecipientKey[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"move\", input),\n ...previousPathRequestFields(\n input.previousManifest,\n input.previousProjection,\n ),\n destinationParentContainerPathRefs:\n input.destinationParentProjection.path.map(containerManifestRef),\n predecessorBridge: readCanonicalRecord(\n input.predecessorBridge,\n \"Container move predecessor bridge\",\n ),\n keyring: readCanonicalRecord(input.keyring, \"Container move keyring\"),\n parentKekState: readCanonicalRecord(\n input.destinationParentKek,\n \"Container move destination parent KEK state\",\n ),\n };\n}\n\nasync function unwrapMoveContainerKeys(input: {\n destinationParentProjection: ContainerWriterProjectionResponse;\n execSql: ExecSql;\n previousProjection: ContainerWriterProjectionResponse;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<{\n containerKey: Uint8Array;\n destinationParent: ReturnType<typeof getTargetContainerContext>;\n source: SignedRotationTarget;\n}> {\n const verifiedByHash = new Map<string, VerifiedContainerAccessManifest>();\n const keksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.previousProjection,\n secretKey: input.targetSecretKey,\n verifiedByHash,\n ...projectionVerificationOptions(input),\n });\n const source = signedRotationTarget(input.previousProjection, verifiedByHash);\n const containerKey = requireUnwrappedKek(\n keksByEpochId,\n source.kek,\n \"Container move source\",\n );\n\n const destinationKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.destinationParentProjection,\n secretKey: input.targetSecretKey,\n ...projectionVerificationOptions(input),\n });\n const destinationParent = getTargetContainerContext(\n input.destinationParentProjection,\n );\n requireUnwrappedKek(\n destinationKeksByEpochId,\n destinationParent.kek,\n \"Container move destination parent\",\n );\n\n return { containerKey, destinationParent, source };\n}\n\nfunction assertContainerMoveOrganizations(input: {\n authorOrganizationId: string;\n destinationState: ContainerAccessManifestState;\n previousState: ContainerAccessManifestState;\n}): void {\n if (input.previousState.organizationId !== input.authorOrganizationId) {\n throw new Error(\"Container move author organization mismatch\");\n }\n if (input.destinationState.organizationId !== input.authorOrganizationId) {\n throw new Error(\"Container move destination organization mismatch\");\n }\n}\n\nfunction readContainerMoveStates(input: {\n authorOrganizationId: string;\n destinationParent: ReturnType<typeof getTargetContainerContext>;\n source: ReturnType<typeof getTargetContainerContext>;\n}) {\n const previousState = readContainerState(input.source.manifest);\n const destinationState = readContainerState(input.destinationParent.manifest);\n assertContainerMoveOrganizations({\n authorOrganizationId: input.authorOrganizationId,\n destinationState,\n previousState,\n });\n return { destinationState, previousState };\n}\n\nfunction containerMoveDependencyManifestHashes(input: {\n destinationParentProjection: ContainerWriterProjectionResponse;\n previousProjection: ContainerWriterProjectionResponse;\n}): string[] {\n return [\n ...uniqueSortedManifestHashes(input.previousProjection.path),\n ...uniqueSortedManifestHashes(input.destinationParentProjection.path),\n ];\n}\n\nfunction buildContainerMovePlanResult(input: {\n body: ContainerMoveAccessEventBody;\n containerId: string;\n containerKey: Uint8Array;\n containerKeyEpochId: string;\n destinationParentKek: ContainerKekResponse;\n destinationParentProjection: ContainerWriterProjectionResponse;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n previousProjection: ContainerWriterProjectionResponse;\n predecessorBridge: ContainerKekPredecessorBridge;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}): MaterializedContainerMovePlan {\n const plan: ContainerMovePlan = {\n body: input.body,\n containerId: input.containerId,\n containerKeyEpochId: input.containerKeyEpochId,\n event: input.event,\n eventHash: input.eventHash,\n keyEpoch: input.keyEpoch,\n keyring: input.keyring,\n manifest: input.manifest,\n manifestHash: input.manifestHash,\n previousManifest: input.previousManifest,\n request: buildContainerMoveRequest({\n body: input.body,\n destinationParentKek: input.destinationParentKek,\n destinationParentProjection: input.destinationParentProjection,\n event: input.event,\n keyEpoch: input.keyEpoch,\n keyring: input.keyring,\n manifest: input.manifest,\n manifestHash: input.manifestHash,\n previousManifest: input.previousManifest,\n previousProjection: input.previousProjection,\n predecessorBridge: input.predecessorBridge,\n principalPolicies: input.principalPolicies,\n userRecipientKeys: input.userRecipientKeys,\n wraps: input.wraps,\n }),\n state: input.state,\n wraps: input.wraps,\n };\n\n return { containerKey: input.containerKey, plan };\n}\n\ntype MaterializedContainerMoveInput =\n BuildMaterializedContainerMovePlanInput & {\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n };\n\nasync function collectAuthorizedMovePolicies(\n input: MaterializedContainerMoveInput,\n) {\n const principalPolicies = await collectContainerMovePrincipalPolicies({\n ...input,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n assertContainerAuthorAccess({\n author: input.author,\n projection: input.previousProjection,\n principalPolicies,\n minimumAccess: \"admin\",\n });\n assertContainerAuthorAccess({\n author: input.author,\n projection: input.destinationParentProjection,\n principalPolicies,\n minimumAccess: \"write\",\n });\n return principalPolicies;\n}\n\nasync function buildMaterializedContainerMovePlan(\n input: MaterializedContainerMoveInput,\n): Promise<MaterializedContainerMovePlan> {\n const {\n containerKey: predecessorContainerKey,\n destinationParent,\n source,\n } = await unwrapMoveContainerKeys({\n destinationParentProjection: input.destinationParentProjection,\n execSql: input.execSql,\n previousProjection: input.previousProjection,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n // Only a verified path is a final depth refusal; a padded unverified path\n // must fail verification (an incident), never look like an honest refusal.\n assertContainerChildPathFits(input.destinationParentProjection.path);\n const { destinationState, previousState } = readContainerMoveStates({\n authorOrganizationId: input.author.organizationId,\n destinationParent,\n source,\n });\n const principalPolicies = await collectAuthorizedMovePolicies(input);\n const {\n body,\n containerKey,\n containerKeyEpochId,\n keyring,\n predecessorBridge,\n } = await buildMoveRotationWithBody({\n destinationParent,\n destinationState,\n override: input.containerKeyEpochId,\n predecessorContainerKey,\n previousState,\n source,\n });\n const { event, eventHash, keyEpoch, manifest, manifestHash, state } =\n await deriveMoveManifestArtifacts({\n body,\n containerKeyEpochId,\n destinationParent,\n previousState,\n signing: {\n author: input.author,\n dependencyManifestHashes: containerMoveDependencyManifestHashes(input),\n eventId: input.eventId,\n signedAt: input.signedAt,\n },\n source,\n });\n const { userRecipientKeys, wraps } = await buildContainerMoveWraps({\n principalPolicies,\n containerKey,\n containerKeyEpochId,\n destinationParentKek: destinationParent.kek,\n destinationParentProjection: input.destinationParentProjection,\n execSql: input.execSql,\n manifestHash,\n previousProjection: input.previousProjection,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n state,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n\n return buildContainerMovePlanResult({\n body,\n containerKey,\n containerId: previousState.containerId,\n containerKeyEpochId,\n destinationParentKek: destinationParent.kek,\n destinationParentProjection: input.destinationParentProjection,\n event,\n eventHash,\n keyEpoch,\n keyring,\n manifest,\n manifestHash,\n previousManifest: asContainerManifestBundle(source.manifest),\n previousProjection: input.previousProjection,\n predecessorBridge,\n principalPolicies,\n state,\n userRecipientKeys,\n wraps,\n });\n}\n\nexport async function moveRemoteContainer(input: {\n reportSecurityIncident: SecurityIncidentReporter;\n apiClient: ContainerMoveApi;\n author: ContainerMutationAuthor;\n containerId: string;\n destinationParentContainerId: string;\n eventId?: string | undefined;\n execSql: ExecSql;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<{\n containerKey: Uint8Array;\n plan: ContainerMovePlan;\n response: ContainerRotationResponse;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container move\",\n );\n const [previousProjection, destinationParentProjection] = await Promise.all([\n input.apiClient.getContainerWriterProjection(input.containerId),\n input.apiClient.getContainerWriterProjection(\n input.destinationParentContainerId,\n ),\n ]);\n if (!previousProjection || !destinationParentProjection) {\n return null;\n }\n\n const materializedPlan = await nullOnProjectionVerificationCancellation(() =>\n buildMaterializedContainerMovePlan({\n author: input.author,\n eventId: input.eventId,\n execSql: input.execSql,\n previousProjection,\n destinationParentProjection,\n resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n );\n if (!materializedPlan) return null;\n return submitAcknowledgedContainerMutation({\n reportSecurityIncident: input.reportSecurityIncident,\n recitationPolicies: [],\n apiClient: input.apiClient,\n author: input.author,\n carriedRekeys: {\n planning: {\n apiClient: input.apiClient,\n author: input.author,\n execSql: input.execSql,\n knownContainerKeks: new Map([\n [\n materializedPlan.plan.containerKeyEpochId,\n materializedPlan.containerKey,\n ],\n ]),\n resolveProjectionUserKey: resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n },\n rotated: () =>\n containerWriterProjectionFromRotationPlan({\n ancestors: destinationParentProjection,\n plan: materializedPlan.plan,\n previousProjection,\n }),\n },\n containerKey: materializedPlan.containerKey,\n execSql: input.execSql,\n plan: materializedPlan.plan,\n stillCurrent: input.stillCurrent,\n submit: (carried) => {\n const request = carried.length\n ? { ...materializedPlan.plan.request, containerRekeys: [...carried] }\n : materializedPlan.plan.request;\n const options = {\n expectedPaymentRequiredOrganizationId: input.author.organizationId,\n };\n const { moveContainerResult } = input.apiClient;\n return submitContainerRotation({\n plain: () =>\n input.apiClient.moveContainer(input.containerId, request, options),\n result: moveContainerResult\n ? () =>\n moveContainerResult.call(\n input.apiClient,\n input.containerId,\n request,\n { ...options, reportErrors: false },\n )\n : undefined,\n });\n },\n });\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { principalPolicyRequestRecord } from "../../../data/containers/shared/principalPolicies.js";
|
|
2
|
-
import {
|
|
2
|
+
import { containerManifestRef } from "../../../data/containers/shared/projection.js";
|
|
3
3
|
import { readCanonicalRecord, readCanonicalRecords, } from "../../../data/keyingCanonicalJson.js";
|
|
4
4
|
export function readCanonicalRecordOrNull(value, label) {
|
|
5
5
|
return value === null || value === undefined
|
|
@@ -8,12 +8,13 @@ export function readCanonicalRecordOrNull(value, label) {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* The previous-manifest identity every non-create mutation
|
|
11
|
-
* (share/rekey/revoke/move) sends alongside the core request fields
|
|
11
|
+
* (share/rekey/revoke/move) sends alongside the core request fields: the
|
|
12
|
+
* previous head and the current path, cited by hash rather than echoed.
|
|
12
13
|
*/
|
|
13
14
|
export function previousPathRequestFields(previousManifest, previousProjection) {
|
|
14
15
|
return {
|
|
15
|
-
previousManifest,
|
|
16
|
-
|
|
16
|
+
previousManifestRef: containerManifestRef(previousManifest),
|
|
17
|
+
previousContainerPathRefs: previousProjection.path.map(containerManifestRef),
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
/**
|