@tearleads/client-sdk 0.1.13 → 0.1.15
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/README.md +32 -7
- package/client/containerContents.js +2 -1
- package/client/containerContents.js.map +1 -1
- package/data/documents/blob/shared/types.d.ts +4 -0
- package/data/documents/blob/shared/types.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 +2 -1
- package/data/keyingProjectionVerification/checkpointContext.js +22 -0
- package/data/keyingProjectionVerification/checkpointContext.js.map +1 -1
- package/data/keyingProjectionVerification/containerDestinationVerification.js +11 -1
- package/data/keyingProjectionVerification/containerDestinationVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerManifestVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerPathVerification.js.map +1 -1
- package/data/keyingProjectionVerification/containerProjectionVerification.d.ts +3 -2
- package/data/keyingProjectionVerification/containerProjectionVerification.js +10 -11
- package/data/keyingProjectionVerification/containerProjectionVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentManifestPolicies.js.map +1 -1
- package/data/keyingProjectionVerification/documentManifestVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentProjectionVerification.d.ts +2 -3
- package/data/keyingProjectionVerification/documentProjectionVerification.js +4 -0
- package/data/keyingProjectionVerification/documentProjectionVerification.js.map +1 -1
- package/data/keyingProjectionVerification/mergeProjectionPolicyEvidence.js +14 -12
- package/data/keyingProjectionVerification/mergeProjectionPolicyEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/organizationFounderBinding.js.map +1 -1
- package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js +33 -6
- package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/projectionLifetimes.js +13 -0
- package/data/keyingProjectionVerification/projectionLifetimes.js.map +1 -0
- package/data/keyingProjectionVerification/projectionPolicyEvidence.js +19 -66
- package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +13 -2
- package/data/keyingProjectionVerification/types.js +15 -0
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/keyingCheckpointAdvancePersistence.js +4 -1
- package/data/persistence/keyingCheckpointAdvancePersistence.js.map +1 -1
- package/data/persistence/organizationFounderPersistence.js +2 -2
- package/data/persistence/organizationFounderPersistence.js.map +1 -1
- package/data/persistence/principalAuthorizationCheckpoints.js +29 -0
- package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -0
- package/data/persistence/principalHistoryEvidencePersistence.d.ts +30 -0
- package/data/persistence/principalHistoryPrefixPersistence.d.ts +24 -0
- package/data/persistence/principalHistoryPrefixPersistence.js +6 -2
- package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
- package/data/persistence/principalHistoryStagePersistence.d.ts +21 -0
- package/data/principals/principalHistoryRuntime.js +12 -0
- package/data/principals/principalHistoryRuntime.js.map +1 -0
- package/data/principals/principalHistoryStageProtection.js +2 -12
- package/data/principals/principalHistoryStageProtection.js.map +1 -1
- package/data/principals/principalPolicyEvidence.d.ts +2 -2
- package/data/principals/principalPolicyEvidence.js.map +1 -1
- package/data/sqlite/principalHistoryEvidenceSchema.d.ts +308 -0
- package/data/sqlite/principalHistoryStageSchema.d.ts +119 -0
- package/index.d.ts +2 -2
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/internal/api-client/ApiCache.d.ts +54 -0
- package/internal/api-client/ApiClient.d.ts +255 -309
- package/internal/api-client/ApiClient.js +15 -6
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/index.d.ts +1 -0
- package/internal/api-client/index.js.map +1 -1
- package/internal/api-client/principalHistoryDeadline.js +20 -0
- package/internal/api-client/principalHistoryDeadline.js.map +1 -0
- package/internal/api-client/principalHistoryRequest.js +59 -22
- package/internal/api-client/principalHistoryRequest.js.map +1 -1
- package/internal/api-client/principalHistoryRequestContext.js +18 -5
- package/internal/api-client/principalHistoryRequestContext.js.map +1 -1
- package/internal/api-client/principalPolicyRequests.d.ts +799 -0
- package/internal/api-client/principalPolicyRequests.js +9 -4
- package/internal/api-client/principalPolicyRequests.js.map +1 -1
- package/internal/api-client/projectionPolicyHistoryPages.d.ts +9 -0
- package/internal/api-client/projectionPolicyHistoryPages.js +88 -0
- package/internal/api-client/projectionPolicyHistoryPages.js.map +1 -0
- package/internal/api-client/writerProjectionRequests.js +26 -0
- package/internal/api-client/writerProjectionRequests.js.map +1 -0
- package/internal/crypto/keying/principalPolicyHistory.js +4 -0
- package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
- package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
- package/internal/crypto/projectionHistorySlots.js +0 -4
- package/internal/crypto/projectionHistorySlots.js.map +1 -1
- package/internal/validators/operation/index.d.ts +1 -0
- package/internal/validators/operation/index.js +1 -0
- package/internal/validators/operation/index.js.map +1 -1
- package/internal/validators/operation/principals.d.ts +38 -16
- package/internal/validators/operation/principals.js +11 -5
- package/internal/validators/operation/principals.js.map +1 -1
- package/internal/validators/operation/projectionPolicyHistory.d.ts +512 -0
- package/internal/validators/operation/projectionPolicyHistory.js +37 -0
- package/internal/validators/operation/projectionPolicyHistory.js.map +1 -0
- package/internal/validators/operation/registry.d.ts +2 -0
- package/internal/validators/operation/registry.js +2 -0
- package/internal/validators/operation/registry.js.map +1 -1
- package/internal/validators/operation/writerProjections.d.ts +178 -1224
- package/internal/validators/operation/writerProjections.js +9 -2
- package/internal/validators/operation/writerProjections.js.map +1 -1
- package/internal/validators/response/container.d.ts +84 -612
- package/internal/validators/response/documentMutation.d.ts +84 -612
- package/internal/validators/response/index.d.ts +1 -0
- package/internal/validators/response/index.js +1 -0
- package/internal/validators/response/index.js.map +1 -1
- package/internal/validators/response/organizationBilling.d.ts +1 -0
- package/internal/validators/response/organizationBilling.js +1 -1
- package/internal/validators/response/organizationBilling.js.map +1 -1
- package/internal/validators/response/principalHistoryPreparation.js +28 -1
- package/internal/validators/response/principalHistoryPreparation.js.map +1 -1
- package/internal/validators/response/principalPolicySnapshotPage.d.ts +388 -0
- package/internal/validators/response/principalPolicySnapshotPage.js +24 -0
- package/internal/validators/response/principalPolicySnapshotPage.js.map +1 -0
- package/internal/validators/response/projectionPolicyEvidence.d.ts +85 -613
- package/internal/validators/response/projectionPolicyEvidence.js +10 -5
- package/internal/validators/response/projectionPolicyEvidence.js.map +1 -1
- package/package.json +4 -1
- package/sqlite/sqlite3-licenses.md +38 -0
- package/sqlite/sqlite3.wasm +0 -0
- package/sqlite/worker.js +4 -0
- package/stores/documents/documentStore/attachmentHydration.js +3 -0
- package/stores/documents/documentStore/attachmentHydration.js.map +1 -1
- package/stores/documents/documentStore/syncDetachedAttachments.js +3 -0
- package/stores/documents/documentStore/syncDetachedAttachments.js.map +1 -1
- package/workflows/blobs/decrypt.d.ts +1 -1
- package/workflows/blobs/decrypt.js +3 -1
- package/workflows/blobs/decrypt.js.map +1 -1
- package/workflows/blobs/detach.js +6 -1
- package/workflows/blobs/detach.js.map +1 -1
- package/workflows/blobs/hydrate.d.ts +3 -1
- package/workflows/blobs/hydrate.js +2 -0
- package/workflows/blobs/hydrate.js.map +1 -1
- package/workflows/blobs/retainedAttachmentVerification.js +2 -0
- package/workflows/blobs/retainedAttachmentVerification.js.map +1 -1
- package/workflows/container-contents/container-state/createAdoption.js +2 -0
- package/workflows/container-contents/container-state/createAdoption.js.map +1 -1
- package/workflows/container-contents/container-state/createWithMetadata.js +7 -39
- package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
- package/workflows/container-contents/container-state/createWithMetadataPlan.js +68 -0
- package/workflows/container-contents/container-state/createWithMetadataPlan.js.map +1 -0
- package/workflows/container-contents/remoteContainerState.js +3 -1
- package/workflows/container-contents/remoteContainerState.js.map +1 -1
- package/workflows/container-contents/remoteHydration/verifiedDestination.js +3 -0
- package/workflows/container-contents/remoteHydration/verifiedDestination.js.map +1 -1
- package/workflows/container-contents/runtime.d.ts +3 -0
- package/workflows/container-contents/runtime.js +7 -6
- package/workflows/container-contents/runtime.js.map +1 -1
- package/workflows/documents/create.d.ts +2 -15
- package/workflows/documents/create.js +9 -64
- package/workflows/documents/create.js.map +1 -1
- package/workflows/documents/createProjection.d.ts +14 -0
- package/workflows/documents/createProjection.js +26 -0
- package/workflows/documents/createProjection.js.map +1 -0
- package/workflows/documents/createResponse.js +49 -0
- package/workflows/documents/createResponse.js.map +1 -0
- package/workflows/documents/linkSetBlobRewraps.js +2 -0
- package/workflows/documents/linkSetBlobRewraps.js.map +1 -1
- package/workflows/documents/runtime.d.ts +3 -0
- package/workflows/documents/runtime.js +3 -2
- package/workflows/documents/runtime.js.map +1 -1
- package/workflows/documents/syncFailureClassification.js +3 -1
- package/workflows/documents/syncFailureClassification.js.map +1 -1
- package/workflows/principals/index.d.ts +2 -0
- package/workflows/principals/index.js +1 -0
- package/workflows/principals/index.js.map +1 -1
- package/workflows/principals/policyVerification.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryAuthority.js +20 -0
- package/workflows/principals/principalHistoryRecoveryAuthority.js.map +1 -0
- package/workflows/principals/principalHistoryRecoveryStage.js +1 -1
- package/workflows/principals/principalHistoryRecoveryStage.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryTypes.d.ts +3 -3
- package/workflows/principals/principalHistoryRecoveryTypes.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryVerification.js +6 -1
- package/workflows/principals/principalHistoryRecoveryVerification.js.map +1 -1
- package/workflows/principals/principalRecoveryOutage.js +1 -1
- package/workflows/principals/principalRecoveryOutage.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryAuthority.js +60 -0
- package/workflows/principals/publicPrincipalHistoryAuthority.js.map +1 -0
- package/workflows/principals/publicPrincipalHistoryPage.js +87 -0
- package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -0
- package/workflows/principals/publicPrincipalHistoryProgress.js +178 -0
- package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -0
- package/workflows/principals/publicPrincipalHistoryTypes.d.ts +39 -0
- package/workflows/principals/publicPrincipalHistoryTypes.js +2 -0
- package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -0
- package/workflows/principals/publicProjectionDirectory.js +40 -0
- package/workflows/principals/publicProjectionDirectory.js.map +1 -0
- package/workflows/principals/publicProjectionPrincipal.js +53 -0
- package/workflows/principals/publicProjectionPrincipal.js.map +1 -0
- package/workflows/principals/recoverPrincipalPolicyHistory.js +4 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverProjectionPolicyHistory.d.ts +9 -0
- package/workflows/principals/recoverProjectionPolicyHistory.js +98 -0
- package/workflows/principals/recoverProjectionPolicyHistory.js.map +1 -0
- package/workflows/principals/recoverPublicPrincipalHistory.js +176 -0
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -0
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +2 -5
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +2 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/runtimePolicyWarmer.js +2 -0
- package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
- package/workflows/principals/runtimeProjectionPolicyRecovery.js +56 -0
- package/workflows/principals/runtimeProjectionPolicyRecovery.js.map +1 -0
- package/workflows/principals/selectPublicPrincipalHistory.js +90 -0
- package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -0
- package/workflows/registration/provisioningBootstrapBuilders.d.ts +21 -153
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { resolveDocumentProjectorRegistry, } from "../../data/documents/documentKinds.js";
|
|
2
|
+
import { inheritPrincipalHistoryProtection } from "../../data/principals/principalHistoryRuntime.js";
|
|
2
3
|
import { requireTrustedUserIdentityResolver, } from "../../data/trustedUserIdentity/index.js";
|
|
3
4
|
import { createDocumentsWorkflowRuntime, } from "../documents/index.js";
|
|
4
5
|
function documentsRuntimeInput(runtime, containerId) {
|
|
5
|
-
return {
|
|
6
|
+
return inheritPrincipalHistoryProtection(runtime, {
|
|
6
7
|
apiClient: runtime.apiClient,
|
|
7
8
|
auth: runtime.auth,
|
|
8
9
|
crypto: runtime.crypto,
|
|
@@ -10,7 +11,7 @@ function documentsRuntimeInput(runtime, containerId) {
|
|
|
10
11
|
resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,
|
|
11
12
|
state: { ...runtime.state, containerId },
|
|
12
13
|
util: runtime.util,
|
|
13
|
-
};
|
|
14
|
+
});
|
|
14
15
|
}
|
|
15
16
|
export function createContainerContentsDocumentsRuntime(runtime, containerId) {
|
|
16
17
|
return createDocumentsWorkflowRuntime(documentsRuntimeInput(runtime, containerId));
|
|
@@ -21,7 +22,7 @@ function createContainerContentsWorkflowRuntimeWithRootAdopter(input, adoptRootC
|
|
|
21
22
|
...input.infra,
|
|
22
23
|
documentProjectors,
|
|
23
24
|
};
|
|
24
|
-
return {
|
|
25
|
+
return inheritPrincipalHistoryProtection(input, {
|
|
25
26
|
...(adoptRootContainer ? { adoptRootContainer } : {}),
|
|
26
27
|
apiClient: input.apiClient,
|
|
27
28
|
auth: input.auth,
|
|
@@ -30,16 +31,16 @@ function createContainerContentsWorkflowRuntimeWithRootAdopter(input, adoptRootC
|
|
|
30
31
|
resolveTrustedUserIdentity: requireTrustedUserIdentityResolver(input.resolveTrustedUserIdentity),
|
|
31
32
|
state: input.state,
|
|
32
33
|
util: input.util,
|
|
33
|
-
};
|
|
34
|
+
});
|
|
34
35
|
}
|
|
35
36
|
export function createContainerContentsWorkflowRuntime(input) {
|
|
36
37
|
return createContainerContentsWorkflowRuntimeWithRootAdopter(input);
|
|
37
38
|
}
|
|
38
39
|
/** Internal store runtime with the session-root adoption capability wired. */
|
|
39
40
|
export function createContainerContentsStoreWorkflowRuntime(input, adoptRootContainer) {
|
|
40
|
-
return {
|
|
41
|
+
return inheritPrincipalHistoryProtection(input, {
|
|
41
42
|
...createContainerContentsWorkflowRuntimeWithRootAdopter(input, adoptRootContainer),
|
|
42
43
|
adoptRootContainer,
|
|
43
|
-
};
|
|
44
|
+
});
|
|
44
45
|
}
|
|
45
46
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EACL,kCAAkC,GAEnC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,8BAA8B,GAE/B,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAElG,OAAO,EACL,kCAAkC,GAEnC,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,8BAA8B,GAE/B,MAAM,cAAc,CAAC;AAqGtB,SAAS,qBAAqB,CAC5B,OAAyC,EACzC,WAA0B;IAE1B,OAAO,iCAAiC,CAAC,OAAO,EAAE;QAChD,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;QAC9D,KAAK,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE;QACxC,IAAI,EAAE,OAAO,CAAC,IAAI;KACnB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uCAAuC,CACrD,OAAyC,EACzC,WAA0B;IAE1B,OAAO,8BAA8B,CACnC,qBAAqB,CAAC,OAAO,EAAE,WAAW,CAAC,CAC5C,CAAC;AACJ,CAAC;AAED,SAAS,qDAAqD,CAC5D,KAA4C,EAC5C,kBAA6D;IAE7D,MAAM,kBAAkB,GAAG,gCAAgC,CACzD,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAC/B,CAAC;IACF,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,KAAK;QACd,kBAAkB;KACnB,CAAC;IAEF,OAAO,iCAAiC,CAAC,KAAK,EAAE;QAC9C,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK;QACL,0BAA0B,EAAE,kCAAkC,CAC5D,KAAK,CAAC,0BAA0B,CACjC;QACD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,sCAAsC,CACpD,KAA4C;IAE5C,OAAO,qDAAqD,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,2CAA2C,CACzD,KAA4C,EAC5C,kBAAgD;IAEhD,OAAO,iCAAiC,CAAC,KAAK,EAAE;QAC9C,GAAG,qDAAqD,CACtD,KAAK,EACL,kBAAkB,CACnB;QACD,kBAAkB;KACnB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport {\n type DocumentProjectorRegistryInput,\n resolveDocumentProjectorRegistry,\n} from \"../../data/documents/documentKinds\";\nimport type { PrincipalHistoryProtectionLease } from \"../../data/principals/principalHistoryProtection\";\nimport { inheritPrincipalHistoryProtection } from \"../../data/principals/principalHistoryRuntime\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport {\n requireTrustedUserIdentityResolver,\n type TrustedUserIdentityResolver,\n} from \"../../data/trustedUserIdentity\";\nimport {\n createDocumentsWorkflowRuntime,\n type DocumentsWorkflowRuntime,\n} from \"../documents\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../runtimeInput\";\n\ntype DocumentsWorkflowRuntimeInput = Parameters<\n typeof createDocumentsWorkflowRuntime\n>[0];\n\ntype ContainerContentsWorkflowApi = ApiClient &\n DocumentsWorkflowRuntimeInput[\"apiClient\"];\n\nexport interface ContainerContentsWorkflowRuntimeAuth\n extends WorkflowRuntimeAuthInput {}\n\nexport interface ContainerContentsWorkflowRuntimeCrypto\n extends WorkflowRuntimeCryptoInput {}\n\nexport interface ContainerContentsWorkflowRuntimeInfra\n extends Omit<WorkflowRuntimeInfraInput, \"dbStatus\"> {\n readonly dbStatus: string;\n}\n\ninterface ContainerContentsWorkflowRuntimeInputInfra\n extends Omit<ContainerContentsWorkflowRuntimeInfra, \"documentProjectors\"> {\n readonly documentProjectors: DocumentProjectorRegistryInput;\n}\n\nexport interface ContainerContentsWorkflowRuntimeState\n extends WorkflowRuntimeStateInput {}\n\nexport interface ContainerContentsWorkflowRuntimeUtil\n extends Omit<WorkflowRuntimeUtilInput, \"logError\"> {\n // Store recovery is best-effort, so hosts may retain the causal error without\n // making structured error logging mandatory for general workflow runtimes.\n readonly logError?: WorkflowRuntimeUtilInput[\"logError\"] | undefined;\n}\n\nexport interface ContainerContentsRootAdoptionInput {\n readonly domainScope: ContainerContentsWorkflowRuntimeState[\"domainScope\"];\n readonly expectedContainerId: string;\n readonly nextContainerId: string;\n readonly organizationId: string;\n readonly userId: string;\n}\n\nexport type ContainerContentsRootAdopter = (\n input: ContainerContentsRootAdoptionInput,\n) => boolean | \"already-adopted\";\n\nexport interface ContainerContentsWorkflowRuntimeGroups {\n readonly auth: ContainerContentsWorkflowRuntimeAuth;\n readonly crypto: ContainerContentsWorkflowRuntimeCrypto;\n readonly infra: ContainerContentsWorkflowRuntimeInfra;\n readonly state: ContainerContentsWorkflowRuntimeState;\n readonly util: ContainerContentsWorkflowRuntimeUtil;\n}\n\nexport interface ContainerContentsWorkflowRuntimeInputGroups {\n readonly auth: ContainerContentsWorkflowRuntimeAuth;\n readonly crypto: ContainerContentsWorkflowRuntimeCrypto;\n readonly infra: ContainerContentsWorkflowRuntimeInputInfra;\n readonly state: ContainerContentsWorkflowRuntimeState;\n readonly util: ContainerContentsWorkflowRuntimeUtil;\n}\n\nexport interface ContainerContentsWorkflowRuntimeInput\n extends ContainerContentsWorkflowRuntimeInputGroups {\n /** Private host custody, inherited by container and derived document runtimes. */\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n readonly apiClient: ContainerContentsWorkflowApi;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport interface ContainerContentsWorkflowRuntime\n extends ContainerContentsWorkflowRuntimeGroups,\n Pick<ContainerContentsWorkflowRuntimeInput, \"apiClient\"> {\n readonly adoptRootContainer?: ContainerContentsRootAdopter | undefined;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport interface ContainerContentsStoreWorkflowRuntime\n extends ContainerContentsWorkflowRuntime {\n readonly adoptRootContainer: ContainerContentsRootAdopter;\n}\n\nexport interface ContainerContentsWorkflowSqlRuntime {\n readonly auth?: {\n readonly organizationId?: string | null | undefined;\n };\n readonly infra: {\n readonly execSql: ExecSql;\n };\n}\n\nfunction documentsRuntimeInput(\n runtime: ContainerContentsWorkflowRuntime,\n containerId: string | null,\n): DocumentsWorkflowRuntimeInput {\n return inheritPrincipalHistoryProtection(runtime, {\n apiClient: runtime.apiClient,\n auth: runtime.auth,\n crypto: runtime.crypto,\n infra: runtime.infra,\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n state: { ...runtime.state, containerId },\n util: runtime.util,\n });\n}\n\nexport function createContainerContentsDocumentsRuntime(\n runtime: ContainerContentsWorkflowRuntime,\n containerId: string | null,\n): DocumentsWorkflowRuntime {\n return createDocumentsWorkflowRuntime(\n documentsRuntimeInput(runtime, containerId),\n );\n}\n\nfunction createContainerContentsWorkflowRuntimeWithRootAdopter(\n input: ContainerContentsWorkflowRuntimeInput,\n adoptRootContainer?: ContainerContentsRootAdopter | undefined,\n): ContainerContentsWorkflowRuntime {\n const documentProjectors = resolveDocumentProjectorRegistry(\n input.infra.documentProjectors,\n );\n const infra = {\n ...input.infra,\n documentProjectors,\n };\n\n return inheritPrincipalHistoryProtection(input, {\n ...(adoptRootContainer ? { adoptRootContainer } : {}),\n apiClient: input.apiClient,\n auth: input.auth,\n crypto: input.crypto,\n infra,\n resolveTrustedUserIdentity: requireTrustedUserIdentityResolver(\n input.resolveTrustedUserIdentity,\n ),\n state: input.state,\n util: input.util,\n });\n}\n\nexport function createContainerContentsWorkflowRuntime(\n input: ContainerContentsWorkflowRuntimeInput,\n): ContainerContentsWorkflowRuntime {\n return createContainerContentsWorkflowRuntimeWithRootAdopter(input);\n}\n\n/** Internal store runtime with the session-root adoption capability wired. */\nexport function createContainerContentsStoreWorkflowRuntime(\n input: ContainerContentsWorkflowRuntimeInput,\n adoptRootContainer: ContainerContentsRootAdopter,\n): ContainerContentsStoreWorkflowRuntime {\n return inheritPrincipalHistoryProtection(input, {\n ...createContainerContentsWorkflowRuntimeWithRootAdopter(\n input,\n adoptRootContainer,\n ),\n adoptRootContainer,\n });\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ContainerWriterProjectionResponse, type DocumentCreateResponse
|
|
1
|
+
import { type ContainerWriterProjectionResponse, type DocumentCreateResponse } from "../../internal/validators/response/index.js";
|
|
2
2
|
import type { CreateRemoteDocumentResult, DocumentCreateApi, DocumentCreateAuthor, MaterializedDocumentCreatePlan, ProjectionVerificationOptions } from "../../data/documents/shared/types.js";
|
|
3
3
|
import type { ProjectionUserKeyResolver, ReferencedPrincipalPolicyWarmer } from "../../data/keyingProjectionVerification.js";
|
|
4
4
|
import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
|
|
@@ -16,19 +16,7 @@ export declare function buildMaterializedDocumentCreatePlan(input: {
|
|
|
16
16
|
signedAt?: string | undefined;
|
|
17
17
|
targetSecretKey: Uint8Array;
|
|
18
18
|
} & ProjectionVerificationOptions): Promise<MaterializedDocumentCreatePlan>;
|
|
19
|
-
|
|
20
|
-
* Build the writer projection a document-create response establishes, from the
|
|
21
|
-
* container projection the create was authored against plus the manifest,
|
|
22
|
-
* content-key bundle, and KEK targets the server just returned. This is the
|
|
23
|
-
* same material a cold `GET /documents/:id/writer-projection` would yield, so
|
|
24
|
-
* seeding it lets the first read after a create resolve locally. Shared by the
|
|
25
|
-
* plain document-create path and the container-with-metadata-document path,
|
|
26
|
-
* whose response carries an equivalent `DocumentCreateResponse`.
|
|
27
|
-
*/
|
|
28
|
-
export declare function documentWriterProjectionFromCreateResponse(input: {
|
|
29
|
-
containerProjection: ContainerWriterProjectionResponse;
|
|
30
|
-
response: DocumentCreateResponse;
|
|
31
|
-
}): DocumentWriterProjectionResponse;
|
|
19
|
+
export { documentWriterProjectionFromCreateResponse } from "./createProjection.js";
|
|
32
20
|
interface RemoteDocumentCreateInput {
|
|
33
21
|
apiClient: DocumentCreateApi;
|
|
34
22
|
author: DocumentCreateAuthor;
|
|
@@ -66,4 +54,3 @@ type DocumentCreateSubmission = {
|
|
|
66
54
|
readonly status: number | null;
|
|
67
55
|
};
|
|
68
56
|
export declare function isStaleDocumentCreateTargetConflict(submission: DocumentCreateSubmission): boolean;
|
|
69
|
-
export {};
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { DOCUMENT_SYNC_ERROR_CODES, } from "../../internal/validators/response/index.js";
|
|
2
2
|
import { assertContainerAuthorAccess } from "../../data/containers/shared/authorAccess.js";
|
|
3
3
|
import { buildDocumentCreatePlan } from "../../data/documents/shared/events.js";
|
|
4
|
-
import {
|
|
5
|
-
import { assertDocumentWriterProjectionConsistent, wrapDocumentContentKeyForCreate, } from "../../data/documents/shared/projection.js";
|
|
6
|
-
import { persistedDocumentCreateStateFromResponse } from "../../data/documents/shared/responses.js";
|
|
4
|
+
import { wrapDocumentContentKeyForCreate } from "../../data/documents/shared/projection.js";
|
|
7
5
|
import { projectionVerificationOptions } from "../../data/documents/shared/types.js";
|
|
8
6
|
import { collectContainerWriterProjectionPrincipalPolicies, nullOnProjectionVerificationCancellation, requireProjectionUserKeyResolver, } from "../../data/keyingProjectionVerification.js";
|
|
9
7
|
import { isContainerCreatePending } from "../../data/persistence/container-contents/pendingContainerCreate.js";
|
|
10
8
|
import { recordDocumentAuthorAccessFailure } from "./authorAccessFailure.js";
|
|
11
9
|
import { adoptExistingRemoteDocument } from "./createAdoption.js";
|
|
12
10
|
import { fetchContainerWriterProjectionForCreate } from "./createProjectionFetch.js";
|
|
11
|
+
import { acknowledgeRemoteDocumentCreate } from "./createResponse.js";
|
|
13
12
|
import { isDocumentManifestAlreadyExistsConflict, shouldRetryWithFreshProjection, } from "./syncFailureClassification.js";
|
|
14
13
|
export async function buildMaterializedDocumentCreatePlan(input) {
|
|
15
14
|
const contentKey = input.contentKey ?? crypto.getRandomValues(new Uint8Array(32));
|
|
@@ -65,31 +64,7 @@ export async function buildMaterializedDocumentCreatePlan(input) {
|
|
|
65
64
|
plan,
|
|
66
65
|
};
|
|
67
66
|
}
|
|
68
|
-
|
|
69
|
-
* Build the writer projection a document-create response establishes, from the
|
|
70
|
-
* container projection the create was authored against plus the manifest,
|
|
71
|
-
* content-key bundle, and KEK targets the server just returned. This is the
|
|
72
|
-
* same material a cold `GET /documents/:id/writer-projection` would yield, so
|
|
73
|
-
* seeding it lets the first read after a create resolve locally. Shared by the
|
|
74
|
-
* plain document-create path and the container-with-metadata-document path,
|
|
75
|
-
* whose response carries an equivalent `DocumentCreateResponse`.
|
|
76
|
-
*/
|
|
77
|
-
export function documentWriterProjectionFromCreateResponse(input) {
|
|
78
|
-
return {
|
|
79
|
-
policyEvidence: input.containerProjection.policyEvidence,
|
|
80
|
-
authorizingContainerPaths: [input.containerProjection],
|
|
81
|
-
contentKeyBundle: input.response.contentKeyBundle,
|
|
82
|
-
documentContainerManifestHistory: [
|
|
83
|
-
...input.containerProjection.path,
|
|
84
|
-
...input.containerProjection.containerKeks.flatMap((kek) => kek.containerManifestHistory),
|
|
85
|
-
],
|
|
86
|
-
documentId: input.response.id,
|
|
87
|
-
documentKekTargets: input.response.documentKekTargets,
|
|
88
|
-
documentManifest: input.response.accessManifest,
|
|
89
|
-
documentManifestContainerPaths: [[...input.containerProjection.path]],
|
|
90
|
-
documentManifestHistory: [],
|
|
91
|
-
};
|
|
92
|
-
}
|
|
67
|
+
export { documentWriterProjectionFromCreateResponse } from "./createProjection.js";
|
|
93
68
|
async function buildMaterializedDocumentCreatePlanWithFreshProjection(input) {
|
|
94
69
|
const buildWithProjection = async (containerProjection) => {
|
|
95
70
|
if (containerProjection.containerId !== input.containerId ||
|
|
@@ -227,43 +202,13 @@ export async function createRemoteDocument(input) {
|
|
|
227
202
|
const { createPlan, submission } = plannedSubmission;
|
|
228
203
|
if (input.stillCurrent?.() === false)
|
|
229
204
|
return null;
|
|
230
|
-
if (submission.ok)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
execSql: input.execSql,
|
|
235
|
-
plan: createPlan.materializedPlan.plan,
|
|
236
|
-
stillCurrent: input.stillCurrent,
|
|
237
|
-
});
|
|
238
|
-
if (input.stillCurrent?.() === false)
|
|
239
|
-
return null;
|
|
240
|
-
const writerProjection = documentWriterProjectionFromCreateResponse({
|
|
241
|
-
containerProjection: createPlan.containerProjection,
|
|
242
|
-
response,
|
|
243
|
-
});
|
|
244
|
-
const verifiedTargets = await nullOnProjectionVerificationCancellation(() => assertDocumentWriterProjectionConsistent(writerProjection, {
|
|
245
|
-
execSql: input.execSql,
|
|
205
|
+
if (submission.ok)
|
|
206
|
+
return acknowledgeRemoteDocumentCreate({
|
|
207
|
+
...input,
|
|
208
|
+
...createPlan,
|
|
246
209
|
resolveProjectionUserKey,
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}));
|
|
250
|
-
if (!verifiedTargets)
|
|
251
|
-
return null;
|
|
252
|
-
if (input.stillCurrent?.() === false)
|
|
253
|
-
return null;
|
|
254
|
-
// Seed the projection the create response already gave us so the first read
|
|
255
|
-
// after create (sync, blob attach, container-contents hydration) resolves
|
|
256
|
-
// locally instead of a cold GET writer-projection.
|
|
257
|
-
input.apiClient.primeDocumentWriterProjection(response.id, writerProjection);
|
|
258
|
-
return {
|
|
259
|
-
contentKey: createPlan.materializedPlan.contentKey,
|
|
260
|
-
documentId: response.id,
|
|
261
|
-
persistedState,
|
|
262
|
-
plan: createPlan.materializedPlan.plan,
|
|
263
|
-
response,
|
|
264
|
-
writerProjection,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
210
|
+
response: submission.data,
|
|
211
|
+
});
|
|
267
212
|
// A stable documentId means a retry after a lost create response re-submits
|
|
268
213
|
// the same id; the server then reports the manifest already exists. That is
|
|
269
214
|
// not a failure — the first attempt committed. Adopt the existing remote
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["create.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentCreateRequest } from \"@tearleads/validators/request\";\nimport {\n type ContainerWriterProjectionResponse,\n DOCUMENT_SYNC_ERROR_CODES,\n type DocumentCreateResponse,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../data/containers/shared/authorAccess\";\nimport { buildDocumentCreatePlan } from \"../../data/documents/shared/events\";\nimport { acknowledgeDocumentMutation } from \"../../data/documents/shared/mutationAcknowledgement\";\nimport {\n assertDocumentWriterProjectionConsistent,\n wrapDocumentContentKeyForCreate,\n} from \"../../data/documents/shared/projection\";\nimport { persistedDocumentCreateStateFromResponse } from \"../../data/documents/shared/responses\";\nimport type {\n CreateRemoteDocumentResult,\n DocumentCreateApi,\n DocumentCreateAuthor,\n MaterializedDocumentCreatePlan,\n ProjectionVerificationOptions,\n} from \"../../data/documents/shared/types\";\nimport { projectionVerificationOptions } from \"../../data/documents/shared/types\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../data/keyingProjectionVerification\";\nimport { isContainerCreatePending } from \"../../data/persistence/container-contents/pendingContainerCreate\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { recordDocumentAuthorAccessFailure } from \"./authorAccessFailure\";\nimport { adoptExistingRemoteDocument } from \"./createAdoption\";\nimport type { DocumentCreateTerminalFailureHandler } from \"./createProjectionFetch\";\nimport { fetchContainerWriterProjectionForCreate } from \"./createProjectionFetch\";\nimport {\n isDocumentManifestAlreadyExistsConflict,\n shouldRetryWithFreshProjection,\n} from \"./syncFailureClassification\";\n\nexport async function buildMaterializedDocumentCreatePlan(\n input: {\n author: DocumentCreateAuthor;\n containerProjection: ContainerWriterProjectionResponse;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n persistVerificationCheckpoints?: boolean | undefined;\n signedAt?: string | undefined;\n targetSecretKey: Uint8Array;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedDocumentCreatePlan> {\n const contentKey =\n input.contentKey ?? crypto.getRandomValues(new Uint8Array(32));\n if (contentKey.byteLength !== 32) {\n throw new Error(\"Document content key must be 32 bytes\");\n }\n // Resolved before wrapping: each envelope is sealed to its document and\n // content-key epoch.\n const documentId = input.documentId ?? crypto.randomUUID();\n const contentKeyEpoch = input.contentKeyEpoch ?? 1;\n const targetEnvelopes = await wrapDocumentContentKeyForCreate({\n contentKey,\n contentKeyEpoch,\n documentId,\n execSql: input.execSql,\n knownContainerKeks: input.knownContainerKeks,\n persistVerificationCheckpoints: input.persistVerificationCheckpoints,\n projection: input.containerProjection,\n secretKey: input.targetSecretKey,\n ...projectionVerificationOptions(input),\n });\n if (input.resolveProjectionUserKey) {\n const principalPolicies =\n await collectContainerWriterProjectionPrincipalPolicies({\n ...projectionVerificationOptions(input),\n execSql: input.execSql,\n projection: input.containerProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n assertContainerAuthorAccess({\n // Document signing derives its organization from the verified target.\n author: {\n ...input.author,\n organizationId: input.containerProjection.organizationId,\n },\n projection: input.containerProjection,\n principalPolicies,\n minimumAccess: \"write\",\n });\n }\n // The explicit local-trust variant builds provisioning artifacts before\n // their new principal policies exist remotely; remote creates cannot use it.\n const plan = await buildDocumentCreatePlan({\n author: input.author,\n containerProjection: input.containerProjection,\n contentKeyEpoch,\n documentId,\n ...(input.eventId === undefined ? {} : { eventId: input.eventId }),\n ...(input.signedAt === undefined ? {} : { signedAt: input.signedAt }),\n targetEnvelopes,\n });\n\n return {\n contentKey,\n plan,\n };\n}\n\n/**\n * Build the writer projection a document-create response establishes, from the\n * container projection the create was authored against plus the manifest,\n * content-key bundle, and KEK targets the server just returned. This is the\n * same material a cold `GET /documents/:id/writer-projection` would yield, so\n * seeding it lets the first read after a create resolve locally. Shared by the\n * plain document-create path and the container-with-metadata-document path,\n * whose response carries an equivalent `DocumentCreateResponse`.\n */\nexport function documentWriterProjectionFromCreateResponse(input: {\n containerProjection: ContainerWriterProjectionResponse;\n response: DocumentCreateResponse;\n}): DocumentWriterProjectionResponse {\n return {\n policyEvidence: input.containerProjection.policyEvidence,\n authorizingContainerPaths: [input.containerProjection],\n contentKeyBundle: input.response.contentKeyBundle,\n documentContainerManifestHistory: [\n ...input.containerProjection.path,\n ...input.containerProjection.containerKeks.flatMap(\n (kek) => kek.containerManifestHistory,\n ),\n ],\n documentId: input.response.id,\n documentKekTargets: input.response.documentKekTargets,\n documentManifest: input.response.accessManifest,\n documentManifestContainerPaths: [[...input.containerProjection.path]],\n documentManifestHistory: [],\n };\n}\n\ninterface MaterializedDocumentCreatePlanWithProjection {\n readonly containerProjection: ContainerWriterProjectionResponse;\n readonly materializedPlan: MaterializedDocumentCreatePlan;\n}\n\nasync function buildMaterializedDocumentCreatePlanWithFreshProjection(input: {\n apiClient: DocumentCreateApi;\n author: DocumentCreateAuthor;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | undefined;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId?: string | undefined;\n eventId?: string | undefined;\n execSql: ExecSql;\n expectedOrganizationId?: string | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n onTerminalSubmitFailure?: DocumentCreateTerminalFailureHandler | undefined;\n persistVerificationCheckpoints?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<MaterializedDocumentCreatePlanWithProjection | null> {\n const buildWithProjection = async (\n containerProjection: ContainerWriterProjectionResponse,\n ) => {\n if (\n containerProjection.containerId !== input.containerId ||\n (input.expectedOrganizationId !== undefined &&\n containerProjection.organizationId !== input.expectedOrganizationId)\n ) {\n throw new Error(\n \"Container writer projection belongs to another container or organization\",\n );\n }\n return {\n containerProjection,\n materializedPlan: await buildMaterializedDocumentCreatePlan({\n author: input.author,\n containerProjection,\n contentKey: input.contentKey,\n contentKeyEpoch: input.contentKeyEpoch,\n documentId: input.documentId,\n eventId: input.eventId,\n execSql: input.execSql,\n knownContainerKeks: input.knownContainerKeks,\n persistVerificationCheckpoints: input.persistVerificationCheckpoints,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n };\n };\n\n const containerProjection =\n input.containerProjection ??\n (await fetchContainerWriterProjectionForCreate({\n apiClient: input.apiClient,\n containerId: input.containerId,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n }));\n if (!containerProjection) {\n return null;\n }\n\n try {\n return await buildWithProjection(containerProjection);\n } catch (error) {\n if (\n !shouldRetryWithFreshProjection(error, (message) =>\n message.includes(\"could not be unwrapped\"),\n )\n ) {\n throw error;\n }\n }\n\n // Only this container's projection was stale; evict just it rather than\n // wiping every cached projection.\n input.apiClient.evictContainerWriterProjection(input.containerId);\n const refreshedProjection = await fetchContainerWriterProjectionForCreate({\n apiClient: input.apiClient,\n containerId: input.containerId,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n });\n return refreshedProjection ? buildWithProjection(refreshedProjection) : null;\n}\n\ninterface RemoteDocumentCreateInput {\n apiClient: DocumentCreateApi;\n author: DocumentCreateAuthor;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | undefined;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId?: string | undefined;\n eventId?: string | undefined;\n execSql: ExecSql;\n expectedOrganizationId?: string | undefined;\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n /**\n * Invoked when the create submission fails terminally (not a benign\n * adopt/stale-target conflict) — e.g. the server denies the write. Callers\n * persist the failure so the write queue can surface it.\n */\n onTerminalSubmitFailure?: DocumentCreateTerminalFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}\n\nfunction isRemoteDocumentCreatePlanBlocked(\n input: RemoteDocumentCreateInput,\n createPlan: MaterializedDocumentCreatePlanWithProjection,\n): boolean {\n const organizationId = createPlan.containerProjection.organizationId;\n return input.isRemoteSyncBlocked?.(organizationId) ?? false;\n}\n\nasync function submitPlannedDocumentCreate(\n input: RemoteDocumentCreateInput,\n resolveProjectionUserKey: ProjectionUserKeyResolver,\n): Promise<{\n readonly createPlan: MaterializedDocumentCreatePlanWithProjection;\n readonly submission: DocumentCreateSubmission;\n} | null> {\n const verificationOptions = { stillCurrent: input.stillCurrent };\n const warmReferencedPrincipalPolicies = input.warmReferencedPrincipalPolicies;\n let createPlan = await buildMaterializedDocumentCreatePlanWithFreshProjection(\n {\n apiClient: input.apiClient,\n author: input.author,\n containerId: input.containerId,\n containerProjection: input.containerProjection,\n contentKey: input.contentKey,\n contentKeyEpoch: input.contentKeyEpoch,\n documentId: input.documentId,\n eventId: input.eventId,\n execSql: input.execSql,\n expectedOrganizationId: input.expectedOrganizationId,\n knownContainerKeks: input.knownContainerKeks,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n resolveProjectionUserKey,\n signedAt: input.signedAt,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies,\n ...verificationOptions,\n },\n );\n if (!createPlan) {\n return null;\n }\n if (isRemoteDocumentCreatePlanBlocked(input, createPlan)) return null;\n if (input.stillCurrent?.() === false) return null;\n let submission = await submitDocumentCreate(\n input.apiClient,\n createPlan.materializedPlan.plan.request,\n createPlan.containerProjection.organizationId,\n );\n if (isStaleDocumentCreateTargetConflict(submission)) {\n if (input.stillCurrent?.() === false) {\n return { createPlan, submission };\n }\n input.apiClient.evictContainerWriterProjection(input.containerId);\n const firstPlan = createPlan.materializedPlan;\n const refreshedPlan =\n await buildMaterializedDocumentCreatePlanWithFreshProjection({\n apiClient: input.apiClient,\n author: input.author,\n containerId: input.containerId,\n contentKey: firstPlan.contentKey,\n contentKeyEpoch:\n firstPlan.plan.request.contentKeyBundle.contentKeyEpoch,\n documentId: firstPlan.plan.documentId,\n eventId: firstPlan.plan.event.eventId,\n execSql: input.execSql,\n expectedOrganizationId: input.expectedOrganizationId,\n knownContainerKeks: input.knownContainerKeks,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n resolveProjectionUserKey,\n signedAt: firstPlan.plan.event.signedAt,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies,\n ...verificationOptions,\n });\n if (!refreshedPlan) {\n return null;\n }\n if (isRemoteDocumentCreatePlanBlocked(input, refreshedPlan)) return null;\n createPlan = refreshedPlan;\n if (input.stillCurrent?.() === false) return null;\n submission = await submitDocumentCreate(\n input.apiClient,\n createPlan.materializedPlan.plan.request,\n createPlan.containerProjection.organizationId,\n );\n }\n return { createPlan, submission };\n}\n\nexport async function createRemoteDocument(\n input: RemoteDocumentCreateInput,\n): Promise<CreateRemoteDocumentResult | null> {\n // The store retries once the folder's own create settles.\n if (await isContainerCreatePending(input.execSql, input.containerId)) {\n return null;\n }\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote document create\",\n );\n const plannedSubmission = await recordDocumentAuthorAccessFailure(\n () =>\n nullOnProjectionVerificationCancellation(() =>\n submitPlannedDocumentCreate(input, resolveProjectionUserKey),\n ),\n input.onTerminalSubmitFailure,\n );\n if (!plannedSubmission) {\n return null;\n }\n const { createPlan, submission } = plannedSubmission;\n if (input.stillCurrent?.() === false) return null;\n if (submission.ok) {\n const response = submission.data;\n const persistedState = persistedDocumentCreateStateFromResponse(\n createPlan.materializedPlan.plan,\n response,\n );\n await acknowledgeDocumentMutation({\n execSql: input.execSql,\n plan: createPlan.materializedPlan.plan,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n const writerProjection = documentWriterProjectionFromCreateResponse({\n containerProjection: createPlan.containerProjection,\n response,\n });\n const verifiedTargets = await nullOnProjectionVerificationCancellation(() =>\n assertDocumentWriterProjectionConsistent(writerProjection, {\n execSql: input.execSql,\n resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n );\n if (!verifiedTargets) return null;\n if (input.stillCurrent?.() === false) return null;\n // Seed the projection the create response already gave us so the first read\n // after create (sync, blob attach, container-contents hydration) resolves\n // locally instead of a cold GET writer-projection.\n input.apiClient.primeDocumentWriterProjection(\n response.id,\n writerProjection,\n );\n\n return {\n contentKey: createPlan.materializedPlan.contentKey,\n documentId: response.id,\n persistedState,\n plan: createPlan.materializedPlan.plan,\n response,\n writerProjection,\n };\n }\n\n // A stable documentId means a retry after a lost create response re-submits\n // the same id; the server then reports the manifest already exists. That is\n // not a failure — the first attempt committed. Adopt the existing remote\n // document instead of leaking a duplicate. Requires the stable id we sent, so\n // we can fetch its projection back.\n const stableDocumentId = input.documentId;\n if (stableDocumentId && isDocumentManifestAlreadyExistsConflict(submission)) {\n if (input.stillCurrent?.() === false) return null;\n const adopted = await nullOnProjectionVerificationCancellation(() =>\n adoptExistingRemoteDocument({\n apiClient: input.apiClient,\n documentId: stableDocumentId,\n execSql: input.execSql,\n expectedContainerId: input.containerId,\n expectedOrganizationId:\n input.expectedOrganizationId ??\n createPlan.containerProjection.organizationId,\n expectedSignerUserId: input.author.signerUserId,\n resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n );\n if (adopted) {\n return adopted;\n }\n // A conflict is the expected, benign outcome of an idempotent retry after a\n // lost create response. If adoption cannot complete yet (e.g. the writer\n // projection fetch failed transiently), do not surface the conflict as a UI\n // error — the sync engine retries and adopts it on a later tick.\n return null;\n }\n\n submission.report?.();\n await input.onTerminalSubmitFailure?.(submission);\n return null;\n}\n\ntype DocumentCreateSubmission =\n | {\n readonly data: DocumentCreateResponse;\n readonly ok: true;\n }\n | {\n readonly code?: string | undefined;\n readonly message: string;\n readonly ok: false;\n readonly report?: (() => void) | undefined;\n readonly status: number | null;\n };\n\nexport function isStaleDocumentCreateTargetConflict(\n submission: DocumentCreateSubmission,\n): boolean {\n return (\n !submission.ok &&\n submission.status === 409 &&\n submission.code === DOCUMENT_SYNC_ERROR_CODES.stateStale\n );\n}\n\nasync function submitDocumentCreate(\n apiClient: DocumentCreateApi,\n request: DocumentCreateRequest,\n expectedOrganizationId: string,\n): Promise<DocumentCreateSubmission> {\n return apiClient.createDocumentResult(request, {\n expectedPaymentRequiredOrganizationId: expectedOrganizationId,\n reportErrors: false,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["create.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentCreateRequest } from \"@tearleads/validators/request\";\nimport {\n type ContainerWriterProjectionResponse,\n DOCUMENT_SYNC_ERROR_CODES,\n type DocumentCreateResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../data/containers/shared/authorAccess\";\nimport { buildDocumentCreatePlan } from \"../../data/documents/shared/events\";\nimport { wrapDocumentContentKeyForCreate } from \"../../data/documents/shared/projection\";\nimport type {\n CreateRemoteDocumentResult,\n DocumentCreateApi,\n DocumentCreateAuthor,\n MaterializedDocumentCreatePlan,\n ProjectionVerificationOptions,\n} from \"../../data/documents/shared/types\";\nimport { projectionVerificationOptions } from \"../../data/documents/shared/types\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../data/keyingProjectionVerification\";\nimport { isContainerCreatePending } from \"../../data/persistence/container-contents/pendingContainerCreate\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { recordDocumentAuthorAccessFailure } from \"./authorAccessFailure\";\nimport { adoptExistingRemoteDocument } from \"./createAdoption\";\nimport type { DocumentCreateTerminalFailureHandler } from \"./createProjectionFetch\";\nimport { fetchContainerWriterProjectionForCreate } from \"./createProjectionFetch\";\nimport { acknowledgeRemoteDocumentCreate } from \"./createResponse\";\nimport {\n isDocumentManifestAlreadyExistsConflict,\n shouldRetryWithFreshProjection,\n} from \"./syncFailureClassification\";\n\nexport async function buildMaterializedDocumentCreatePlan(\n input: {\n author: DocumentCreateAuthor;\n containerProjection: ContainerWriterProjectionResponse;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n persistVerificationCheckpoints?: boolean | undefined;\n signedAt?: string | undefined;\n targetSecretKey: Uint8Array;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedDocumentCreatePlan> {\n const contentKey =\n input.contentKey ?? crypto.getRandomValues(new Uint8Array(32));\n if (contentKey.byteLength !== 32) {\n throw new Error(\"Document content key must be 32 bytes\");\n }\n // Resolved before wrapping: each envelope is sealed to its document and\n // content-key epoch.\n const documentId = input.documentId ?? crypto.randomUUID();\n const contentKeyEpoch = input.contentKeyEpoch ?? 1;\n const targetEnvelopes = await wrapDocumentContentKeyForCreate({\n contentKey,\n contentKeyEpoch,\n documentId,\n execSql: input.execSql,\n knownContainerKeks: input.knownContainerKeks,\n persistVerificationCheckpoints: input.persistVerificationCheckpoints,\n projection: input.containerProjection,\n secretKey: input.targetSecretKey,\n ...projectionVerificationOptions(input),\n });\n if (input.resolveProjectionUserKey) {\n const principalPolicies =\n await collectContainerWriterProjectionPrincipalPolicies({\n ...projectionVerificationOptions(input),\n execSql: input.execSql,\n projection: input.containerProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n });\n assertContainerAuthorAccess({\n // Document signing derives its organization from the verified target.\n author: {\n ...input.author,\n organizationId: input.containerProjection.organizationId,\n },\n projection: input.containerProjection,\n principalPolicies,\n minimumAccess: \"write\",\n });\n }\n // The explicit local-trust variant builds provisioning artifacts before\n // their new principal policies exist remotely; remote creates cannot use it.\n const plan = await buildDocumentCreatePlan({\n author: input.author,\n containerProjection: input.containerProjection,\n contentKeyEpoch,\n documentId,\n ...(input.eventId === undefined ? {} : { eventId: input.eventId }),\n ...(input.signedAt === undefined ? {} : { signedAt: input.signedAt }),\n targetEnvelopes,\n });\n\n return {\n contentKey,\n plan,\n };\n}\n\nexport { documentWriterProjectionFromCreateResponse } from \"./createProjection\";\n\ninterface MaterializedDocumentCreatePlanWithProjection {\n readonly containerProjection: ContainerWriterProjectionResponse;\n readonly materializedPlan: MaterializedDocumentCreatePlan;\n}\n\nasync function buildMaterializedDocumentCreatePlanWithFreshProjection(input: {\n apiClient: DocumentCreateApi;\n author: DocumentCreateAuthor;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | undefined;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId?: string | undefined;\n eventId?: string | undefined;\n execSql: ExecSql;\n expectedOrganizationId?: string | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n onTerminalSubmitFailure?: DocumentCreateTerminalFailureHandler | undefined;\n persistVerificationCheckpoints?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<MaterializedDocumentCreatePlanWithProjection | null> {\n const buildWithProjection = async (\n containerProjection: ContainerWriterProjectionResponse,\n ) => {\n if (\n containerProjection.containerId !== input.containerId ||\n (input.expectedOrganizationId !== undefined &&\n containerProjection.organizationId !== input.expectedOrganizationId)\n ) {\n throw new Error(\n \"Container writer projection belongs to another container or organization\",\n );\n }\n return {\n containerProjection,\n materializedPlan: await buildMaterializedDocumentCreatePlan({\n author: input.author,\n containerProjection,\n contentKey: input.contentKey,\n contentKeyEpoch: input.contentKeyEpoch,\n documentId: input.documentId,\n eventId: input.eventId,\n execSql: input.execSql,\n knownContainerKeks: input.knownContainerKeks,\n persistVerificationCheckpoints: input.persistVerificationCheckpoints,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n };\n };\n\n const containerProjection =\n input.containerProjection ??\n (await fetchContainerWriterProjectionForCreate({\n apiClient: input.apiClient,\n containerId: input.containerId,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n }));\n if (!containerProjection) {\n return null;\n }\n\n try {\n return await buildWithProjection(containerProjection);\n } catch (error) {\n if (\n !shouldRetryWithFreshProjection(error, (message) =>\n message.includes(\"could not be unwrapped\"),\n )\n ) {\n throw error;\n }\n }\n\n // Only this container's projection was stale; evict just it rather than\n // wiping every cached projection.\n input.apiClient.evictContainerWriterProjection(input.containerId);\n const refreshedProjection = await fetchContainerWriterProjectionForCreate({\n apiClient: input.apiClient,\n containerId: input.containerId,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n });\n return refreshedProjection ? buildWithProjection(refreshedProjection) : null;\n}\n\ninterface RemoteDocumentCreateInput {\n apiClient: DocumentCreateApi;\n author: DocumentCreateAuthor;\n containerId: string;\n containerProjection?: ContainerWriterProjectionResponse | undefined;\n contentKey?: Uint8Array | undefined;\n contentKeyEpoch?: number | undefined;\n documentId?: string | undefined;\n eventId?: string | undefined;\n execSql: ExecSql;\n expectedOrganizationId?: string | undefined;\n isRemoteSyncBlocked?: ((organizationId: string) => boolean) | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n /**\n * Invoked when the create submission fails terminally (not a benign\n * adopt/stale-target conflict) — e.g. the server denies the write. Callers\n * persist the failure so the write queue can surface it.\n */\n onTerminalSubmitFailure?: DocumentCreateTerminalFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n targetSecretKey: Uint8Array;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}\n\nfunction isRemoteDocumentCreatePlanBlocked(\n input: RemoteDocumentCreateInput,\n createPlan: MaterializedDocumentCreatePlanWithProjection,\n): boolean {\n const organizationId = createPlan.containerProjection.organizationId;\n return input.isRemoteSyncBlocked?.(organizationId) ?? false;\n}\n\nasync function submitPlannedDocumentCreate(\n input: RemoteDocumentCreateInput,\n resolveProjectionUserKey: ProjectionUserKeyResolver,\n): Promise<{\n readonly createPlan: MaterializedDocumentCreatePlanWithProjection;\n readonly submission: DocumentCreateSubmission;\n} | null> {\n const verificationOptions = { stillCurrent: input.stillCurrent };\n const warmReferencedPrincipalPolicies = input.warmReferencedPrincipalPolicies;\n let createPlan = await buildMaterializedDocumentCreatePlanWithFreshProjection(\n {\n apiClient: input.apiClient,\n author: input.author,\n containerId: input.containerId,\n containerProjection: input.containerProjection,\n contentKey: input.contentKey,\n contentKeyEpoch: input.contentKeyEpoch,\n documentId: input.documentId,\n eventId: input.eventId,\n execSql: input.execSql,\n expectedOrganizationId: input.expectedOrganizationId,\n knownContainerKeks: input.knownContainerKeks,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n resolveProjectionUserKey,\n signedAt: input.signedAt,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies,\n ...verificationOptions,\n },\n );\n if (!createPlan) {\n return null;\n }\n if (isRemoteDocumentCreatePlanBlocked(input, createPlan)) return null;\n if (input.stillCurrent?.() === false) return null;\n let submission = await submitDocumentCreate(\n input.apiClient,\n createPlan.materializedPlan.plan.request,\n createPlan.containerProjection.organizationId,\n );\n if (isStaleDocumentCreateTargetConflict(submission)) {\n if (input.stillCurrent?.() === false) {\n return { createPlan, submission };\n }\n input.apiClient.evictContainerWriterProjection(input.containerId);\n const firstPlan = createPlan.materializedPlan;\n const refreshedPlan =\n await buildMaterializedDocumentCreatePlanWithFreshProjection({\n apiClient: input.apiClient,\n author: input.author,\n containerId: input.containerId,\n contentKey: firstPlan.contentKey,\n contentKeyEpoch:\n firstPlan.plan.request.contentKeyBundle.contentKeyEpoch,\n documentId: firstPlan.plan.documentId,\n eventId: firstPlan.plan.event.eventId,\n execSql: input.execSql,\n expectedOrganizationId: input.expectedOrganizationId,\n knownContainerKeks: input.knownContainerKeks,\n onTerminalSubmitFailure: input.onTerminalSubmitFailure,\n resolveProjectionUserKey,\n signedAt: firstPlan.plan.event.signedAt,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies,\n ...verificationOptions,\n });\n if (!refreshedPlan) {\n return null;\n }\n if (isRemoteDocumentCreatePlanBlocked(input, refreshedPlan)) return null;\n createPlan = refreshedPlan;\n if (input.stillCurrent?.() === false) return null;\n submission = await submitDocumentCreate(\n input.apiClient,\n createPlan.materializedPlan.plan.request,\n createPlan.containerProjection.organizationId,\n );\n }\n return { createPlan, submission };\n}\n\nexport async function createRemoteDocument(\n input: RemoteDocumentCreateInput,\n): Promise<CreateRemoteDocumentResult | null> {\n // The store retries once the folder's own create settles.\n if (await isContainerCreatePending(input.execSql, input.containerId)) {\n return null;\n }\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote document create\",\n );\n const plannedSubmission = await recordDocumentAuthorAccessFailure(\n () =>\n nullOnProjectionVerificationCancellation(() =>\n submitPlannedDocumentCreate(input, resolveProjectionUserKey),\n ),\n input.onTerminalSubmitFailure,\n );\n if (!plannedSubmission) {\n return null;\n }\n const { createPlan, submission } = plannedSubmission;\n if (input.stillCurrent?.() === false) return null;\n if (submission.ok)\n return acknowledgeRemoteDocumentCreate({\n ...input,\n ...createPlan,\n resolveProjectionUserKey,\n response: submission.data,\n });\n\n // A stable documentId means a retry after a lost create response re-submits\n // the same id; the server then reports the manifest already exists. That is\n // not a failure — the first attempt committed. Adopt the existing remote\n // document instead of leaking a duplicate. Requires the stable id we sent, so\n // we can fetch its projection back.\n const stableDocumentId = input.documentId;\n if (stableDocumentId && isDocumentManifestAlreadyExistsConflict(submission)) {\n if (input.stillCurrent?.() === false) return null;\n const adopted = await nullOnProjectionVerificationCancellation(() =>\n adoptExistingRemoteDocument({\n apiClient: input.apiClient,\n documentId: stableDocumentId,\n execSql: input.execSql,\n expectedContainerId: input.containerId,\n expectedOrganizationId:\n input.expectedOrganizationId ??\n createPlan.containerProjection.organizationId,\n expectedSignerUserId: input.author.signerUserId,\n resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n }),\n );\n if (adopted) {\n return adopted;\n }\n // A conflict is the expected, benign outcome of an idempotent retry after a\n // lost create response. If adoption cannot complete yet (e.g. the writer\n // projection fetch failed transiently), do not surface the conflict as a UI\n // error — the sync engine retries and adopts it on a later tick.\n return null;\n }\n\n submission.report?.();\n await input.onTerminalSubmitFailure?.(submission);\n return null;\n}\n\ntype DocumentCreateSubmission =\n | {\n readonly data: DocumentCreateResponse;\n readonly ok: true;\n }\n | {\n readonly code?: string | undefined;\n readonly message: string;\n readonly ok: false;\n readonly report?: (() => void) | undefined;\n readonly status: number | null;\n };\n\nexport function isStaleDocumentCreateTargetConflict(\n submission: DocumentCreateSubmission,\n): boolean {\n return (\n !submission.ok &&\n submission.status === 409 &&\n submission.code === DOCUMENT_SYNC_ERROR_CODES.stateStale\n );\n}\n\nasync function submitDocumentCreate(\n apiClient: DocumentCreateApi,\n request: DocumentCreateRequest,\n expectedOrganizationId: string,\n): Promise<DocumentCreateSubmission> {\n return apiClient.createDocumentResult(request, {\n expectedPaymentRequiredOrganizationId: expectedOrganizationId,\n reportErrors: false,\n });\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ContainerWriterProjectionResponse, DocumentCreateResponse, DocumentWriterProjectionResponse } from "../../internal/validators/response/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Build the writer projection a document-create response establishes, from the
|
|
4
|
+
* container projection the create was authored against plus the manifest,
|
|
5
|
+
* content-key bundle, and KEK targets the server just returned. This is the
|
|
6
|
+
* same material a cold `GET /documents/:id/writer-projection` would yield, so
|
|
7
|
+
* seeding it lets the first read after a create resolve locally. Shared by the
|
|
8
|
+
* plain document-create path and the container-with-metadata-document path,
|
|
9
|
+
* whose response carries an equivalent `DocumentCreateResponse`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function documentWriterProjectionFromCreateResponse(input: {
|
|
12
|
+
containerProjection: ContainerWriterProjectionResponse;
|
|
13
|
+
response: DocumentCreateResponse;
|
|
14
|
+
}): DocumentWriterProjectionResponse;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the writer projection a document-create response establishes, from the
|
|
3
|
+
* container projection the create was authored against plus the manifest,
|
|
4
|
+
* content-key bundle, and KEK targets the server just returned. This is the
|
|
5
|
+
* same material a cold `GET /documents/:id/writer-projection` would yield, so
|
|
6
|
+
* seeding it lets the first read after a create resolve locally. Shared by the
|
|
7
|
+
* plain document-create path and the container-with-metadata-document path,
|
|
8
|
+
* whose response carries an equivalent `DocumentCreateResponse`.
|
|
9
|
+
*/
|
|
10
|
+
export function documentWriterProjectionFromCreateResponse(input) {
|
|
11
|
+
return {
|
|
12
|
+
policyEvidence: input.containerProjection.policyEvidence,
|
|
13
|
+
authorizingContainerPaths: [input.containerProjection],
|
|
14
|
+
contentKeyBundle: input.response.contentKeyBundle,
|
|
15
|
+
documentContainerManifestHistory: [
|
|
16
|
+
...input.containerProjection.path,
|
|
17
|
+
...input.containerProjection.containerKeks.flatMap((kek) => kek.containerManifestHistory),
|
|
18
|
+
],
|
|
19
|
+
documentId: input.response.id,
|
|
20
|
+
documentKekTargets: input.response.documentKekTargets,
|
|
21
|
+
documentManifest: input.response.accessManifest,
|
|
22
|
+
documentManifestContainerPaths: [[...input.containerProjection.path]],
|
|
23
|
+
documentManifestHistory: [],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=createProjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createProjection.js","sourceRoot":"","sources":["createProjection.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,MAAM,UAAU,0CAA0C,CAAC,KAG1D;IACC,OAAO;QACL,cAAc,EAAE,KAAK,CAAC,mBAAmB,CAAC,cAAc;QACxD,yBAAyB,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC;QACtD,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,gBAAgB;QACjD,gCAAgC,EAAE;YAChC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI;YACjC,GAAG,KAAK,CAAC,mBAAmB,CAAC,aAAa,CAAC,OAAO,CAChD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,wBAAwB,CACtC;SACF;QACD,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE;QAC7B,kBAAkB,EAAE,KAAK,CAAC,QAAQ,CAAC,kBAAkB;QACrD,gBAAgB,EAAE,KAAK,CAAC,QAAQ,CAAC,cAAc;QAC/C,8BAA8B,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QACrE,uBAAuB,EAAE,EAAE;KAC5B,CAAC;AACJ,CAAC","sourcesContent":["import type {\n ContainerWriterProjectionResponse,\n DocumentCreateResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\n\n/**\n * Build the writer projection a document-create response establishes, from the\n * container projection the create was authored against plus the manifest,\n * content-key bundle, and KEK targets the server just returned. This is the\n * same material a cold `GET /documents/:id/writer-projection` would yield, so\n * seeding it lets the first read after a create resolve locally. Shared by the\n * plain document-create path and the container-with-metadata-document path,\n * whose response carries an equivalent `DocumentCreateResponse`.\n */\nexport function documentWriterProjectionFromCreateResponse(input: {\n containerProjection: ContainerWriterProjectionResponse;\n response: DocumentCreateResponse;\n}): DocumentWriterProjectionResponse {\n return {\n policyEvidence: input.containerProjection.policyEvidence,\n authorizingContainerPaths: [input.containerProjection],\n contentKeyBundle: input.response.contentKeyBundle,\n documentContainerManifestHistory: [\n ...input.containerProjection.path,\n ...input.containerProjection.containerKeks.flatMap(\n (kek) => kek.containerManifestHistory,\n ),\n ],\n documentId: input.response.id,\n documentKekTargets: input.response.documentKekTargets,\n documentManifest: input.response.accessManifest,\n documentManifestContainerPaths: [[...input.containerProjection.path]],\n documentManifestHistory: [],\n };\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { acknowledgeDocumentMutation } from "../../data/documents/shared/mutationAcknowledgement.js";
|
|
2
|
+
import { assertDocumentWriterProjectionConsistent } from "../../data/documents/shared/projection.js";
|
|
3
|
+
import { persistedDocumentCreateStateFromResponse } from "../../data/documents/shared/responses.js";
|
|
4
|
+
import { ProjectionDependencyUnavailableError } from "../../data/keyingProjectionVerification/dependencyUnavailable.js";
|
|
5
|
+
import { nullOnProjectionVerificationCancellation } from "../../data/keyingProjectionVerification/types.js";
|
|
6
|
+
import { adoptExistingRemoteDocument } from "./createAdoption.js";
|
|
7
|
+
import { documentWriterProjectionFromCreateResponse } from "./createProjection.js";
|
|
8
|
+
/** A matched acknowledgement remains committed if authorization evidence races. */
|
|
9
|
+
export async function acknowledgeRemoteDocumentCreate(input) {
|
|
10
|
+
const { materializedPlan, response } = input;
|
|
11
|
+
const persistedState = persistedDocumentCreateStateFromResponse(materializedPlan.plan, response);
|
|
12
|
+
await acknowledgeDocumentMutation({
|
|
13
|
+
execSql: input.execSql,
|
|
14
|
+
plan: materializedPlan.plan,
|
|
15
|
+
stillCurrent: input.stillCurrent,
|
|
16
|
+
});
|
|
17
|
+
if (input.stillCurrent?.() === false)
|
|
18
|
+
return null;
|
|
19
|
+
const writerProjection = documentWriterProjectionFromCreateResponse(input);
|
|
20
|
+
try {
|
|
21
|
+
const targets = await nullOnProjectionVerificationCancellation(() => assertDocumentWriterProjectionConsistent(writerProjection, input));
|
|
22
|
+
if (!targets || input.stillCurrent?.() === false)
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (!(error instanceof ProjectionDependencyUnavailableError))
|
|
27
|
+
throw error;
|
|
28
|
+
// A principal pin can advance while POST is in flight. Recover the already
|
|
29
|
+
// committed document from fresh evidence, without submitting another create.
|
|
30
|
+
// The adoption path still verifies its author, scope, chain and key binding.
|
|
31
|
+
return nullOnProjectionVerificationCancellation(() => adoptExistingRemoteDocument({
|
|
32
|
+
...input,
|
|
33
|
+
documentId: response.id,
|
|
34
|
+
expectedContainerId: input.containerProjection.containerId,
|
|
35
|
+
expectedOrganizationId: input.containerProjection.organizationId,
|
|
36
|
+
expectedSignerUserId: input.author.signerUserId,
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
input.apiClient.primeDocumentWriterProjection(response.id, writerProjection);
|
|
40
|
+
return {
|
|
41
|
+
contentKey: materializedPlan.contentKey,
|
|
42
|
+
documentId: response.id,
|
|
43
|
+
persistedState,
|
|
44
|
+
plan: materializedPlan.plan,
|
|
45
|
+
response,
|
|
46
|
+
writerProjection,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=createResponse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createResponse.js","sourceRoot":"","sources":["createResponse.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,wCAAwC,EAAE,MAAM,wCAAwC,CAAC;AAClG,OAAO,EAAE,wCAAwC,EAAE,MAAM,uCAAuC,CAAC;AASjG,OAAO,EAAE,oCAAoC,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAE,wCAAwC,EAAE,MAAM,+CAA+C,CAAC;AAEzG,OAAO,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,0CAA0C,EAAE,MAAM,oBAAoB,CAAC;AAEhF,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,KASiC;IAEjC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC7C,MAAM,cAAc,GAAG,wCAAwC,CAC7D,gBAAgB,CAAC,IAAI,EACrB,QAAQ,CACT,CAAC;IACF,MAAM,2BAA2B,CAAC;QAChC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,gBAAgB,CAAC,IAAI;QAC3B,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,gBAAgB,GAAG,0CAA0C,CAAC,KAAK,CAAC,CAAC;IAC3E,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,wCAAwC,CAAC,GAAG,EAAE,CAClE,wCAAwC,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAClE,CAAC;QACF,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;YAAE,OAAO,IAAI,CAAC;IAChE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,oCAAoC,CAAC;YAAE,MAAM,KAAK,CAAC;QAC1E,2EAA2E;QAC3E,6EAA6E;QAC7E,6EAA6E;QAC7E,OAAO,wCAAwC,CAAC,GAAG,EAAE,CACnD,2BAA2B,CAAC;YAC1B,GAAG,KAAK;YACR,UAAU,EAAE,QAAQ,CAAC,EAAE;YACvB,mBAAmB,EAAE,KAAK,CAAC,mBAAmB,CAAC,WAAW;YAC1D,sBAAsB,EAAE,KAAK,CAAC,mBAAmB,CAAC,cAAc;YAChE,oBAAoB,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;SAChD,CAAC,CACH,CAAC;IACJ,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,6BAA6B,CAAC,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;IAC7E,OAAO;QACL,UAAU,EAAE,gBAAgB,CAAC,UAAU;QACvC,UAAU,EAAE,QAAQ,CAAC,EAAE;QACvB,cAAc;QACd,IAAI,EAAE,gBAAgB,CAAC,IAAI;QAC3B,QAAQ;QACR,gBAAgB;KACjB,CAAC;AACJ,CAAC","sourcesContent":["import type {\n ContainerWriterProjectionResponse,\n DocumentCreateResponse,\n} from \"@tearleads/validators/response\";\nimport { acknowledgeDocumentMutation } from \"../../data/documents/shared/mutationAcknowledgement\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../data/documents/shared/projection\";\nimport { persistedDocumentCreateStateFromResponse } from \"../../data/documents/shared/responses\";\nimport type {\n CreateRemoteDocumentResult,\n DocumentCreateApi,\n DocumentCreateAuthor,\n MaterializedDocumentCreatePlan,\n ProjectionVerificationOptions,\n} from \"../../data/documents/shared/types\";\nimport type { ProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { nullOnProjectionVerificationCancellation } from \"../../data/keyingProjectionVerification/types\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { adoptExistingRemoteDocument } from \"./createAdoption\";\nimport { documentWriterProjectionFromCreateResponse } from \"./createProjection\";\n\n/** A matched acknowledgement remains committed if authorization evidence races. */\nexport async function acknowledgeRemoteDocumentCreate(\n input: {\n readonly apiClient: DocumentCreateApi;\n readonly author: DocumentCreateAuthor;\n readonly containerProjection: ContainerWriterProjectionResponse;\n readonly execSql: ExecSql;\n readonly materializedPlan: MaterializedDocumentCreatePlan;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly response: DocumentCreateResponse;\n readonly targetSecretKey: Uint8Array;\n } & ProjectionVerificationOptions,\n): Promise<CreateRemoteDocumentResult | null> {\n const { materializedPlan, response } = input;\n const persistedState = persistedDocumentCreateStateFromResponse(\n materializedPlan.plan,\n response,\n );\n await acknowledgeDocumentMutation({\n execSql: input.execSql,\n plan: materializedPlan.plan,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n const writerProjection = documentWriterProjectionFromCreateResponse(input);\n try {\n const targets = await nullOnProjectionVerificationCancellation(() =>\n assertDocumentWriterProjectionConsistent(writerProjection, input),\n );\n if (!targets || input.stillCurrent?.() === false) return null;\n } catch (error) {\n if (!(error instanceof ProjectionDependencyUnavailableError)) throw error;\n // A principal pin can advance while POST is in flight. Recover the already\n // committed document from fresh evidence, without submitting another create.\n // The adoption path still verifies its author, scope, chain and key binding.\n return nullOnProjectionVerificationCancellation(() =>\n adoptExistingRemoteDocument({\n ...input,\n documentId: response.id,\n expectedContainerId: input.containerProjection.containerId,\n expectedOrganizationId: input.containerProjection.organizationId,\n expectedSignerUserId: input.author.signerUserId,\n }),\n );\n }\n input.apiClient.primeDocumentWriterProjection(response.id, writerProjection);\n return {\n contentKey: materializedPlan.contentKey,\n documentId: response.id,\n persistedState,\n plan: materializedPlan.plan,\n response,\n writerProjection,\n };\n}\n"]}
|
|
@@ -35,6 +35,8 @@ export async function prepareDocumentLinkBlobRewraps(input) {
|
|
|
35
35
|
execSql: input.execSql,
|
|
36
36
|
resolveProjectionUserKey: requireProjectionUserKeyResolver(input.resolveProjectionUserKey, "Attachment relink"),
|
|
37
37
|
targetSecretKey: input.targetSecretKey,
|
|
38
|
+
stillCurrent: input.stillCurrent,
|
|
39
|
+
warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,
|
|
38
40
|
writerProjection: input.writerProjection,
|
|
39
41
|
};
|
|
40
42
|
const needsKey = input.targets.some((target) => !retainedTarget(binding, target, documentId));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linkSetBlobRewraps.js","sourceRoot":"","sources":["linkSetBlobRewraps.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BLOB_CONTENT_KEY_WRAP_SUITE,\n type DocumentContentKeyTarget,\n type DocumentLinkAccessEventBody,\n wrapContentKey,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type {\n BlobAttachmentSummary,\n ContainerWriterProjectionResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport {\n deriveDocumentTargetFromProjection,\n unwrapContainerKekPath,\n} from \"../../data/documents/shared/projection\";\nimport {\n assertEqualBytes,\n targetKey,\n} from \"../../data/documents/shared/readers\";\nimport type {\n DocumentLinkSetMutationApi,\n ProjectionVerificationOptions,\n} from \"../../data/documents/shared/types\";\nimport { projectionVerificationOptions } from \"../../data/documents/shared/types\";\nimport { readCanonicalJson } from \"../../data/keyingCanonicalJson\";\nimport { requireProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { documentContainerProjections } from \"../../data/keyingProjectionVerification/documentContainerProjections\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { createAttachmentProofReader } from \"../blobs/attachmentDecryptor\";\nimport { createAttachmentKeyAuthenticator } from \"../blobs/attachmentKeyAuthenticator\";\nimport { verifyRetainedAttachment } from \"../blobs/retainedAttachmentVerification\";\n\ninterface BlobRewrap {\n blobId: string;\n contentKeyEpoch: number;\n targets: DocumentLinkAccessEventBody[\"blobRewraps\"][number][\"targets\"][number][];\n}\n\n/** Authenticate the existing bytes before propagating their DEK to a new scope. */\nexport async function prepareDocumentLinkBlobRewraps(\n input: {\n apiClient: DocumentLinkSetMutationApi;\n execSql: ExecSql;\n targetContainerProjection: ContainerWriterProjectionResponse;\n targetSecretKey: Uint8Array;\n targets: readonly DocumentContentKeyTarget[];\n writerProjection: DocumentWriterProjectionResponse;\n } & ProjectionVerificationOptions,\n): Promise<DocumentLinkAccessEventBody[\"blobRewraps\"]> {\n const documentId = input.writerProjection.documentId;\n const bindings = await input.apiClient.listDocumentAttachments(documentId);\n // The API refuses the link unless every active binding is rewrapped, so an\n // unavailable listing (offline, or a 409 while a bind is mid-flight) is a\n // retryable availability failure of this mutation, not integrity evidence.\n if (!bindings)\n throw new ProjectionDependencyUnavailableError(\n \"Document attachments are unavailable for relinking\",\n );\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (bindings.length === 0) return [];\n const keks = await collectRelinkKeks(input);\n const authenticateKey = createAttachmentKeyAuthenticator(\n input.apiClient,\n documentId,\n );\n const verifyRetained = createAttachmentProofReader(\n input.apiClient,\n documentId,\n verifyRetainedAttachment,\n );\n const rewrapByBlob = new Map<string, BlobRewrap>();\n for (const binding of bindings) {\n const verification = {\n binding,\n expectedDocumentId: documentId,\n expectedSlotId: binding.slotId,\n execSql: input.execSql,\n resolveProjectionUserKey: requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Attachment relink\",\n ),\n targetSecretKey: input.targetSecretKey,\n writerProjection: input.writerProjection,\n };\n const needsKey = input.targets.some(\n (target) => !retainedTarget(binding, target, documentId),\n );\n const contentKey = needsKey ? await authenticateKey(verification) : null;\n if (!needsKey) await verifyRetained(verification);\n const targets = await Promise.all(\n input.targets.map(async (target) => {\n const previous = retainedTarget(binding, target, documentId);\n if (previous)\n return {\n ...previous,\n ...target,\n wrappingMetadata: readCanonicalJson(\n previous.wrappingMetadata,\n \"Attachment wrap metadata\",\n ),\n };\n const kek = keks.get(targetKey(target));\n if (!kek)\n throw new Error(\n \"Attachment destination is not a verified current container head\",\n );\n if (!contentKey)\n throw new Error(\"Attachment content key is unavailable\");\n return wrapBlobKeyForTarget({\n binding,\n contentKey,\n documentId,\n kek,\n target,\n });\n }),\n );\n const rewrap = rewrapByBlob.get(binding.blobId) ?? {\n blobId: binding.blobId,\n contentKeyEpoch: binding.contentKeyBundle.contentKeyEpoch,\n targets: [],\n };\n if (rewrap.contentKeyEpoch !== binding.contentKeyBundle.contentKeyEpoch)\n throw new Error(\"Attachment content epoch changed during relinking\");\n rewrap.targets.push(...targets);\n rewrapByBlob.set(binding.blobId, rewrap);\n assertProjectionVerificationCurrent(input.stillCurrent);\n }\n return [...rewrapByBlob.values()].sort(compareBlobIds);\n}\n\nasync function wrapBlobKeyForTarget(input: {\n binding: BlobAttachmentSummary;\n contentKey: Uint8Array;\n documentId: string;\n kek: Uint8Array;\n target: DocumentContentKeyTarget;\n}) {\n const { binding, target } = input;\n const wrapped = await wrapContentKey(input.contentKey, input.kek, {\n kind: \"Blob\",\n objectId: binding.blobId,\n contentKeyEpoch: binding.contentKeyBundle.contentKeyEpoch,\n containerId: target.containerId,\n containerKeyEpochId: target.containerKeyEpochId,\n });\n return {\n ...target,\n bindingId: binding.bindingId,\n documentId: input.documentId,\n wrappedKey: bytesToBase64(wrapped.ciphertext),\n wrappingMetadata: {\n suite: BLOB_CONTENT_KEY_WRAP_SUITE,\n iv: bytesToBase64(wrapped.iv),\n },\n };\n}\n\nfunction retainedTarget(\n binding: BlobAttachmentSummary,\n target: DocumentContentKeyTarget,\n documentId: string,\n) {\n return binding.contentKeyBundle.targets.find(\n (candidate) =>\n candidate.bindingId === binding.bindingId &&\n candidate.documentId === documentId &&\n candidate.containerId === target.containerId &&\n candidate.containerKeyEpochId === target.containerKeyEpochId,\n );\n}\n\nasync function collectRelinkKeks(\n input: Parameters<typeof prepareDocumentLinkBlobRewraps>[0],\n): Promise<Map<string, Uint8Array>> {\n const keks = new Map<string, Uint8Array>();\n for (const projection of [\n ...documentContainerProjections(input.writerProjection),\n input.targetContainerProjection,\n ]) {\n const keys = await unwrapContainerKekPath({\n projection,\n secretKey: input.targetSecretKey,\n execSql: input.execSql,\n ...projectionVerificationOptions(input),\n });\n // Every node of this verified path has a current signed head. Historical\n // keyring entries may open source bytes, but never enter the destination map.\n for (const [index, head] of projection.containerKeks.entries()) {\n const target = deriveDocumentTargetFromProjection({\n ...projection,\n containerId: head.containerId,\n path: projection.path.slice(0, index + 1),\n containerKeks: projection.containerKeks.slice(0, index + 1),\n });\n const key = keys.get(target.containerKeyEpochId);\n // A direct child grantee need not possess any ancestor secret.\n if (!key) continue;\n const id = targetKey(target);\n const previous = keks.get(id);\n if (previous)\n assertEqualBytes(\n previous,\n key,\n \"Attachment link projections contain conflicting KEKs\",\n );\n keks.set(id, key);\n }\n }\n return keks;\n}\n\nfunction compareBlobIds(a: { blobId: string }, b: { blobId: string }): number {\n return a.blobId < b.blobId ? -1 : a.blobId > b.blobId ? 1 : 0;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"linkSetBlobRewraps.js","sourceRoot":"","sources":["linkSetBlobRewraps.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n BLOB_CONTENT_KEY_WRAP_SUITE,\n type DocumentContentKeyTarget,\n type DocumentLinkAccessEventBody,\n wrapContentKey,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type {\n BlobAttachmentSummary,\n ContainerWriterProjectionResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport {\n deriveDocumentTargetFromProjection,\n unwrapContainerKekPath,\n} from \"../../data/documents/shared/projection\";\nimport {\n assertEqualBytes,\n targetKey,\n} from \"../../data/documents/shared/readers\";\nimport type {\n DocumentLinkSetMutationApi,\n ProjectionVerificationOptions,\n} from \"../../data/documents/shared/types\";\nimport { projectionVerificationOptions } from \"../../data/documents/shared/types\";\nimport { readCanonicalJson } from \"../../data/keyingCanonicalJson\";\nimport { requireProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { documentContainerProjections } from \"../../data/keyingProjectionVerification/documentContainerProjections\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { createAttachmentProofReader } from \"../blobs/attachmentDecryptor\";\nimport { createAttachmentKeyAuthenticator } from \"../blobs/attachmentKeyAuthenticator\";\nimport { verifyRetainedAttachment } from \"../blobs/retainedAttachmentVerification\";\n\ninterface BlobRewrap {\n blobId: string;\n contentKeyEpoch: number;\n targets: DocumentLinkAccessEventBody[\"blobRewraps\"][number][\"targets\"][number][];\n}\n\n/** Authenticate the existing bytes before propagating their DEK to a new scope. */\nexport async function prepareDocumentLinkBlobRewraps(\n input: {\n apiClient: DocumentLinkSetMutationApi;\n execSql: ExecSql;\n targetContainerProjection: ContainerWriterProjectionResponse;\n targetSecretKey: Uint8Array;\n targets: readonly DocumentContentKeyTarget[];\n writerProjection: DocumentWriterProjectionResponse;\n } & ProjectionVerificationOptions,\n): Promise<DocumentLinkAccessEventBody[\"blobRewraps\"]> {\n const documentId = input.writerProjection.documentId;\n const bindings = await input.apiClient.listDocumentAttachments(documentId);\n // The API refuses the link unless every active binding is rewrapped, so an\n // unavailable listing (offline, or a 409 while a bind is mid-flight) is a\n // retryable availability failure of this mutation, not integrity evidence.\n if (!bindings)\n throw new ProjectionDependencyUnavailableError(\n \"Document attachments are unavailable for relinking\",\n );\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (bindings.length === 0) return [];\n const keks = await collectRelinkKeks(input);\n const authenticateKey = createAttachmentKeyAuthenticator(\n input.apiClient,\n documentId,\n );\n const verifyRetained = createAttachmentProofReader(\n input.apiClient,\n documentId,\n verifyRetainedAttachment,\n );\n const rewrapByBlob = new Map<string, BlobRewrap>();\n for (const binding of bindings) {\n const verification = {\n binding,\n expectedDocumentId: documentId,\n expectedSlotId: binding.slotId,\n execSql: input.execSql,\n resolveProjectionUserKey: requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Attachment relink\",\n ),\n targetSecretKey: input.targetSecretKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n writerProjection: input.writerProjection,\n };\n const needsKey = input.targets.some(\n (target) => !retainedTarget(binding, target, documentId),\n );\n const contentKey = needsKey ? await authenticateKey(verification) : null;\n if (!needsKey) await verifyRetained(verification);\n const targets = await Promise.all(\n input.targets.map(async (target) => {\n const previous = retainedTarget(binding, target, documentId);\n if (previous)\n return {\n ...previous,\n ...target,\n wrappingMetadata: readCanonicalJson(\n previous.wrappingMetadata,\n \"Attachment wrap metadata\",\n ),\n };\n const kek = keks.get(targetKey(target));\n if (!kek)\n throw new Error(\n \"Attachment destination is not a verified current container head\",\n );\n if (!contentKey)\n throw new Error(\"Attachment content key is unavailable\");\n return wrapBlobKeyForTarget({\n binding,\n contentKey,\n documentId,\n kek,\n target,\n });\n }),\n );\n const rewrap = rewrapByBlob.get(binding.blobId) ?? {\n blobId: binding.blobId,\n contentKeyEpoch: binding.contentKeyBundle.contentKeyEpoch,\n targets: [],\n };\n if (rewrap.contentKeyEpoch !== binding.contentKeyBundle.contentKeyEpoch)\n throw new Error(\"Attachment content epoch changed during relinking\");\n rewrap.targets.push(...targets);\n rewrapByBlob.set(binding.blobId, rewrap);\n assertProjectionVerificationCurrent(input.stillCurrent);\n }\n return [...rewrapByBlob.values()].sort(compareBlobIds);\n}\n\nasync function wrapBlobKeyForTarget(input: {\n binding: BlobAttachmentSummary;\n contentKey: Uint8Array;\n documentId: string;\n kek: Uint8Array;\n target: DocumentContentKeyTarget;\n}) {\n const { binding, target } = input;\n const wrapped = await wrapContentKey(input.contentKey, input.kek, {\n kind: \"Blob\",\n objectId: binding.blobId,\n contentKeyEpoch: binding.contentKeyBundle.contentKeyEpoch,\n containerId: target.containerId,\n containerKeyEpochId: target.containerKeyEpochId,\n });\n return {\n ...target,\n bindingId: binding.bindingId,\n documentId: input.documentId,\n wrappedKey: bytesToBase64(wrapped.ciphertext),\n wrappingMetadata: {\n suite: BLOB_CONTENT_KEY_WRAP_SUITE,\n iv: bytesToBase64(wrapped.iv),\n },\n };\n}\n\nfunction retainedTarget(\n binding: BlobAttachmentSummary,\n target: DocumentContentKeyTarget,\n documentId: string,\n) {\n return binding.contentKeyBundle.targets.find(\n (candidate) =>\n candidate.bindingId === binding.bindingId &&\n candidate.documentId === documentId &&\n candidate.containerId === target.containerId &&\n candidate.containerKeyEpochId === target.containerKeyEpochId,\n );\n}\n\nasync function collectRelinkKeks(\n input: Parameters<typeof prepareDocumentLinkBlobRewraps>[0],\n): Promise<Map<string, Uint8Array>> {\n const keks = new Map<string, Uint8Array>();\n for (const projection of [\n ...documentContainerProjections(input.writerProjection),\n input.targetContainerProjection,\n ]) {\n const keys = await unwrapContainerKekPath({\n projection,\n secretKey: input.targetSecretKey,\n execSql: input.execSql,\n ...projectionVerificationOptions(input),\n });\n // Every node of this verified path has a current signed head. Historical\n // keyring entries may open source bytes, but never enter the destination map.\n for (const [index, head] of projection.containerKeks.entries()) {\n const target = deriveDocumentTargetFromProjection({\n ...projection,\n containerId: head.containerId,\n path: projection.path.slice(0, index + 1),\n containerKeks: projection.containerKeks.slice(0, index + 1),\n });\n const key = keys.get(target.containerKeyEpochId);\n // A direct child grantee need not possess any ancestor secret.\n if (!key) continue;\n const id = targetKey(target);\n const previous = keks.get(id);\n if (previous)\n assertEqualBytes(\n previous,\n key,\n \"Attachment link projections contain conflicting KEKs\",\n );\n keks.set(id, key);\n }\n }\n return keks;\n}\n\nfunction compareBlobIds(a: { blobId: string }, b: { blobId: string }): number {\n return a.blobId < b.blobId ? -1 : a.blobId > b.blobId ? 1 : 0;\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ApiClient } from "../../internal/api-client/index.js";
|
|
2
2
|
import { type DocumentProjectorRegistryInput } from "../../data/documents/documentKinds.js";
|
|
3
|
+
import type { PrincipalHistoryProtectionLease } from "../../data/principals/principalHistoryProtection.js";
|
|
3
4
|
import { type TrustedUserIdentityResolver } from "../../data/trustedUserIdentity/index.js";
|
|
4
5
|
import type { WorkflowRuntimeAuthInput, WorkflowRuntimeCryptoInput, WorkflowRuntimeInfraInput, WorkflowRuntimeStateInput, WorkflowRuntimeUtilInput } from "../runtimeInput.js";
|
|
5
6
|
interface DocumentsWorkflowRuntimeUtilInput extends Omit<WorkflowRuntimeUtilInput, "logError"> {
|
|
@@ -27,6 +28,8 @@ export interface DocumentsWorkflowRuntimeInputGroups {
|
|
|
27
28
|
readonly util: DocumentsWorkflowRuntimeUtilInput;
|
|
28
29
|
}
|
|
29
30
|
export interface DocumentsWorkflowRuntimeInput extends DocumentsWorkflowRuntimeInputGroups {
|
|
31
|
+
/** Private host custody, inherited without exposing it on runtime views. */
|
|
32
|
+
readonly withPrincipalHistoryProtection?: PrincipalHistoryProtectionLease | undefined;
|
|
30
33
|
readonly apiClient: ApiClient;
|
|
31
34
|
readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;
|
|
32
35
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { resolveDocumentProjectorRegistry, } from "../../data/documents/documentKinds.js";
|
|
2
|
+
import { inheritPrincipalHistoryProtection } from "../../data/principals/principalHistoryRuntime.js";
|
|
2
3
|
import { requireTrustedUserIdentityResolver, } from "../../data/trustedUserIdentity/index.js";
|
|
3
4
|
export function createDocumentsWorkflowRuntime(input) {
|
|
4
5
|
const documentProjectors = resolveDocumentProjectorRegistry(input.infra.documentProjectors);
|
|
@@ -6,7 +7,7 @@ export function createDocumentsWorkflowRuntime(input) {
|
|
|
6
7
|
...input.infra,
|
|
7
8
|
documentProjectors,
|
|
8
9
|
};
|
|
9
|
-
return {
|
|
10
|
+
return inheritPrincipalHistoryProtection(input, {
|
|
10
11
|
apiClient: input.apiClient,
|
|
11
12
|
auth: input.auth,
|
|
12
13
|
crypto: input.crypto,
|
|
@@ -14,6 +15,6 @@ export function createDocumentsWorkflowRuntime(input) {
|
|
|
14
15
|
resolveTrustedUserIdentity: requireTrustedUserIdentityResolver(input.resolveTrustedUserIdentity),
|
|
15
16
|
state: input.state,
|
|
16
17
|
util: input.util,
|
|
17
|
-
};
|
|
18
|
+
});
|
|
18
19
|
}
|
|
19
20
|
//# sourceMappingURL=runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,gCAAgC,GACjC,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAClG,OAAO,EACL,kCAAkC,GAEnC,MAAM,gCAAgC,CAAC;AAyDxC,MAAM,UAAU,8BAA8B,CAC5C,KAAoC;IAEpC,MAAM,kBAAkB,GAAG,gCAAgC,CACzD,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAC/B,CAAC;IACF,MAAM,KAAK,GAAG;QACZ,GAAG,KAAK,CAAC,KAAK;QACd,kBAAkB;KACnB,CAAC;IAEF,OAAO,iCAAiC,CAAC,KAAK,EAAE;QAC9C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,KAAK;QACL,0BAA0B,EAAE,kCAAkC,CAC5D,KAAK,CAAC,0BAA0B,CACjC;QACD,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport {\n type DocumentProjectorRegistryInput,\n resolveDocumentProjectorRegistry,\n} from \"../../data/documents/documentKinds\";\nimport type { PrincipalHistoryProtectionLease } from \"../../data/principals/principalHistoryProtection\";\nimport { inheritPrincipalHistoryProtection } from \"../../data/principals/principalHistoryRuntime\";\nimport {\n requireTrustedUserIdentityResolver,\n type TrustedUserIdentityResolver,\n} from \"../../data/trustedUserIdentity\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../runtimeInput\";\n\ninterface DocumentsWorkflowRuntimeUtilInput\n extends Omit<WorkflowRuntimeUtilInput, \"logError\"> {\n /** Receives handled quarantine errors without converting them to strings. */\n readonly logError?: WorkflowRuntimeUtilInput[\"logError\"] | undefined;\n}\n\nexport interface DocumentsWorkflowRuntimeInfra\n extends Omit<WorkflowRuntimeInfraInput, \"dbStatus\"> {\n readonly dbStatus: string;\n}\n\ninterface DocumentsWorkflowRuntimeInputInfra\n extends Omit<DocumentsWorkflowRuntimeInfra, \"documentProjectors\"> {\n readonly documentProjectors: DocumentProjectorRegistryInput;\n}\n\nexport interface DocumentsWorkflowRuntimeGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: DocumentsWorkflowRuntimeInfra;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: DocumentsWorkflowRuntimeUtilInput;\n}\n\nexport interface DocumentsWorkflowRuntimeInputGroups {\n readonly auth: WorkflowRuntimeAuthInput;\n readonly crypto: WorkflowRuntimeCryptoInput;\n readonly infra: DocumentsWorkflowRuntimeInputInfra;\n readonly state: WorkflowRuntimeStateInput;\n readonly util: DocumentsWorkflowRuntimeUtilInput;\n}\n\nexport interface DocumentsWorkflowRuntimeInput\n extends DocumentsWorkflowRuntimeInputGroups {\n /** Private host custody, inherited without exposing it on runtime views. */\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n readonly apiClient: ApiClient;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport interface DocumentsWorkflowRuntime\n extends DocumentsWorkflowRuntimeGroups {\n readonly apiClient: ApiClient;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\nexport function createDocumentsWorkflowRuntime(\n input: DocumentsWorkflowRuntimeInput,\n): DocumentsWorkflowRuntime {\n const documentProjectors = resolveDocumentProjectorRegistry(\n input.infra.documentProjectors,\n );\n const infra = {\n ...input.infra,\n documentProjectors,\n };\n\n return inheritPrincipalHistoryProtection(input, {\n apiClient: input.apiClient,\n auth: input.auth,\n crypto: input.crypto,\n infra,\n resolveTrustedUserIdentity: requireTrustedUserIdentityResolver(\n input.resolveTrustedUserIdentity,\n ),\n state: input.state,\n util: input.util,\n });\n}\n"]}
|