@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.
Files changed (204) hide show
  1. package/README.md +32 -7
  2. package/client/containerContents.js +2 -1
  3. package/client/containerContents.js.map +1 -1
  4. package/data/documents/blob/shared/types.d.ts +4 -0
  5. package/data/documents/blob/shared/types.js.map +1 -1
  6. package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js +2 -0
  7. package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js.map +1 -1
  8. package/data/keyingProjectionVerification/checkpointContext.d.ts +2 -1
  9. package/data/keyingProjectionVerification/checkpointContext.js +22 -0
  10. package/data/keyingProjectionVerification/checkpointContext.js.map +1 -1
  11. package/data/keyingProjectionVerification/containerDestinationVerification.js +11 -1
  12. package/data/keyingProjectionVerification/containerDestinationVerification.js.map +1 -1
  13. package/data/keyingProjectionVerification/containerManifestVerification.js.map +1 -1
  14. package/data/keyingProjectionVerification/containerPathVerification.js.map +1 -1
  15. package/data/keyingProjectionVerification/containerProjectionVerification.d.ts +3 -2
  16. package/data/keyingProjectionVerification/containerProjectionVerification.js +10 -11
  17. package/data/keyingProjectionVerification/containerProjectionVerification.js.map +1 -1
  18. package/data/keyingProjectionVerification/documentManifestPolicies.js.map +1 -1
  19. package/data/keyingProjectionVerification/documentManifestVerification.js.map +1 -1
  20. package/data/keyingProjectionVerification/documentProjectionVerification.d.ts +2 -3
  21. package/data/keyingProjectionVerification/documentProjectionVerification.js +4 -0
  22. package/data/keyingProjectionVerification/documentProjectionVerification.js.map +1 -1
  23. package/data/keyingProjectionVerification/mergeProjectionPolicyEvidence.js +14 -12
  24. package/data/keyingProjectionVerification/mergeProjectionPolicyEvidence.js.map +1 -1
  25. package/data/keyingProjectionVerification/organizationFounderBinding.js.map +1 -1
  26. package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js +33 -6
  27. package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js.map +1 -1
  28. package/data/keyingProjectionVerification/projectionLifetimes.js +13 -0
  29. package/data/keyingProjectionVerification/projectionLifetimes.js.map +1 -0
  30. package/data/keyingProjectionVerification/projectionPolicyEvidence.js +19 -66
  31. package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
  32. package/data/keyingProjectionVerification/types.d.ts +13 -2
  33. package/data/keyingProjectionVerification/types.js +15 -0
  34. package/data/keyingProjectionVerification/types.js.map +1 -1
  35. package/data/persistence/keyingCheckpointAdvancePersistence.js +4 -1
  36. package/data/persistence/keyingCheckpointAdvancePersistence.js.map +1 -1
  37. package/data/persistence/organizationFounderPersistence.js +2 -2
  38. package/data/persistence/organizationFounderPersistence.js.map +1 -1
  39. package/data/persistence/principalAuthorizationCheckpoints.js +29 -0
  40. package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -0
  41. package/data/persistence/principalHistoryEvidencePersistence.d.ts +30 -0
  42. package/data/persistence/principalHistoryPrefixPersistence.d.ts +24 -0
  43. package/data/persistence/principalHistoryPrefixPersistence.js +6 -2
  44. package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
  45. package/data/persistence/principalHistoryStagePersistence.d.ts +21 -0
  46. package/data/principals/principalHistoryRuntime.js +12 -0
  47. package/data/principals/principalHistoryRuntime.js.map +1 -0
  48. package/data/principals/principalHistoryStageProtection.js +2 -12
  49. package/data/principals/principalHistoryStageProtection.js.map +1 -1
  50. package/data/principals/principalPolicyEvidence.d.ts +2 -2
  51. package/data/principals/principalPolicyEvidence.js.map +1 -1
  52. package/data/sqlite/principalHistoryEvidenceSchema.d.ts +308 -0
  53. package/data/sqlite/principalHistoryStageSchema.d.ts +119 -0
  54. package/index.d.ts +2 -2
  55. package/index.js +1 -1
  56. package/index.js.map +1 -1
  57. package/internal/api-client/ApiCache.d.ts +54 -0
  58. package/internal/api-client/ApiClient.d.ts +255 -309
  59. package/internal/api-client/ApiClient.js +15 -6
  60. package/internal/api-client/ApiClient.js.map +1 -1
  61. package/internal/api-client/index.d.ts +1 -0
  62. package/internal/api-client/index.js.map +1 -1
  63. package/internal/api-client/principalHistoryDeadline.js +20 -0
  64. package/internal/api-client/principalHistoryDeadline.js.map +1 -0
  65. package/internal/api-client/principalHistoryRequest.js +59 -22
  66. package/internal/api-client/principalHistoryRequest.js.map +1 -1
  67. package/internal/api-client/principalHistoryRequestContext.js +18 -5
  68. package/internal/api-client/principalHistoryRequestContext.js.map +1 -1
  69. package/internal/api-client/principalPolicyRequests.d.ts +799 -0
  70. package/internal/api-client/principalPolicyRequests.js +9 -4
  71. package/internal/api-client/principalPolicyRequests.js.map +1 -1
  72. package/internal/api-client/projectionPolicyHistoryPages.d.ts +9 -0
  73. package/internal/api-client/projectionPolicyHistoryPages.js +88 -0
  74. package/internal/api-client/projectionPolicyHistoryPages.js.map +1 -0
  75. package/internal/api-client/writerProjectionRequests.js +26 -0
  76. package/internal/api-client/writerProjectionRequests.js.map +1 -0
  77. package/internal/crypto/keying/principalPolicyHistory.js +4 -0
  78. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  79. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
  80. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  81. package/internal/crypto/projectionHistorySlots.js +0 -4
  82. package/internal/crypto/projectionHistorySlots.js.map +1 -1
  83. package/internal/validators/operation/index.d.ts +1 -0
  84. package/internal/validators/operation/index.js +1 -0
  85. package/internal/validators/operation/index.js.map +1 -1
  86. package/internal/validators/operation/principals.d.ts +38 -16
  87. package/internal/validators/operation/principals.js +11 -5
  88. package/internal/validators/operation/principals.js.map +1 -1
  89. package/internal/validators/operation/projectionPolicyHistory.d.ts +512 -0
  90. package/internal/validators/operation/projectionPolicyHistory.js +37 -0
  91. package/internal/validators/operation/projectionPolicyHistory.js.map +1 -0
  92. package/internal/validators/operation/registry.d.ts +2 -0
  93. package/internal/validators/operation/registry.js +2 -0
  94. package/internal/validators/operation/registry.js.map +1 -1
  95. package/internal/validators/operation/writerProjections.d.ts +178 -1224
  96. package/internal/validators/operation/writerProjections.js +9 -2
  97. package/internal/validators/operation/writerProjections.js.map +1 -1
  98. package/internal/validators/response/container.d.ts +84 -612
  99. package/internal/validators/response/documentMutation.d.ts +84 -612
  100. package/internal/validators/response/index.d.ts +1 -0
  101. package/internal/validators/response/index.js +1 -0
  102. package/internal/validators/response/index.js.map +1 -1
  103. package/internal/validators/response/organizationBilling.d.ts +1 -0
  104. package/internal/validators/response/organizationBilling.js +1 -1
  105. package/internal/validators/response/organizationBilling.js.map +1 -1
  106. package/internal/validators/response/principalHistoryPreparation.js +28 -1
  107. package/internal/validators/response/principalHistoryPreparation.js.map +1 -1
  108. package/internal/validators/response/principalPolicySnapshotPage.d.ts +388 -0
  109. package/internal/validators/response/principalPolicySnapshotPage.js +24 -0
  110. package/internal/validators/response/principalPolicySnapshotPage.js.map +1 -0
  111. package/internal/validators/response/projectionPolicyEvidence.d.ts +85 -613
  112. package/internal/validators/response/projectionPolicyEvidence.js +10 -5
  113. package/internal/validators/response/projectionPolicyEvidence.js.map +1 -1
  114. package/package.json +4 -1
  115. package/sqlite/sqlite3-licenses.md +38 -0
  116. package/sqlite/sqlite3.wasm +0 -0
  117. package/sqlite/worker.js +4 -0
  118. package/stores/documents/documentStore/attachmentHydration.js +3 -0
  119. package/stores/documents/documentStore/attachmentHydration.js.map +1 -1
  120. package/stores/documents/documentStore/syncDetachedAttachments.js +3 -0
  121. package/stores/documents/documentStore/syncDetachedAttachments.js.map +1 -1
  122. package/workflows/blobs/decrypt.d.ts +1 -1
  123. package/workflows/blobs/decrypt.js +3 -1
  124. package/workflows/blobs/decrypt.js.map +1 -1
  125. package/workflows/blobs/detach.js +6 -1
  126. package/workflows/blobs/detach.js.map +1 -1
  127. package/workflows/blobs/hydrate.d.ts +3 -1
  128. package/workflows/blobs/hydrate.js +2 -0
  129. package/workflows/blobs/hydrate.js.map +1 -1
  130. package/workflows/blobs/retainedAttachmentVerification.js +2 -0
  131. package/workflows/blobs/retainedAttachmentVerification.js.map +1 -1
  132. package/workflows/container-contents/container-state/createAdoption.js +2 -0
  133. package/workflows/container-contents/container-state/createAdoption.js.map +1 -1
  134. package/workflows/container-contents/container-state/createWithMetadata.js +7 -39
  135. package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
  136. package/workflows/container-contents/container-state/createWithMetadataPlan.js +68 -0
  137. package/workflows/container-contents/container-state/createWithMetadataPlan.js.map +1 -0
  138. package/workflows/container-contents/remoteContainerState.js +3 -1
  139. package/workflows/container-contents/remoteContainerState.js.map +1 -1
  140. package/workflows/container-contents/remoteHydration/verifiedDestination.js +3 -0
  141. package/workflows/container-contents/remoteHydration/verifiedDestination.js.map +1 -1
  142. package/workflows/container-contents/runtime.d.ts +3 -0
  143. package/workflows/container-contents/runtime.js +7 -6
  144. package/workflows/container-contents/runtime.js.map +1 -1
  145. package/workflows/documents/create.d.ts +2 -15
  146. package/workflows/documents/create.js +9 -64
  147. package/workflows/documents/create.js.map +1 -1
  148. package/workflows/documents/createProjection.d.ts +14 -0
  149. package/workflows/documents/createProjection.js +26 -0
  150. package/workflows/documents/createProjection.js.map +1 -0
  151. package/workflows/documents/createResponse.js +49 -0
  152. package/workflows/documents/createResponse.js.map +1 -0
  153. package/workflows/documents/linkSetBlobRewraps.js +2 -0
  154. package/workflows/documents/linkSetBlobRewraps.js.map +1 -1
  155. package/workflows/documents/runtime.d.ts +3 -0
  156. package/workflows/documents/runtime.js +3 -2
  157. package/workflows/documents/runtime.js.map +1 -1
  158. package/workflows/documents/syncFailureClassification.js +3 -1
  159. package/workflows/documents/syncFailureClassification.js.map +1 -1
  160. package/workflows/principals/index.d.ts +2 -0
  161. package/workflows/principals/index.js +1 -0
  162. package/workflows/principals/index.js.map +1 -1
  163. package/workflows/principals/policyVerification.js.map +1 -1
  164. package/workflows/principals/principalHistoryRecoveryAuthority.js +20 -0
  165. package/workflows/principals/principalHistoryRecoveryAuthority.js.map +1 -0
  166. package/workflows/principals/principalHistoryRecoveryStage.js +1 -1
  167. package/workflows/principals/principalHistoryRecoveryStage.js.map +1 -1
  168. package/workflows/principals/principalHistoryRecoveryTypes.d.ts +3 -3
  169. package/workflows/principals/principalHistoryRecoveryTypes.js.map +1 -1
  170. package/workflows/principals/principalHistoryRecoveryVerification.js +6 -1
  171. package/workflows/principals/principalHistoryRecoveryVerification.js.map +1 -1
  172. package/workflows/principals/principalRecoveryOutage.js +1 -1
  173. package/workflows/principals/principalRecoveryOutage.js.map +1 -1
  174. package/workflows/principals/publicPrincipalHistoryAuthority.js +60 -0
  175. package/workflows/principals/publicPrincipalHistoryAuthority.js.map +1 -0
  176. package/workflows/principals/publicPrincipalHistoryPage.js +87 -0
  177. package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -0
  178. package/workflows/principals/publicPrincipalHistoryProgress.js +178 -0
  179. package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -0
  180. package/workflows/principals/publicPrincipalHistoryTypes.d.ts +39 -0
  181. package/workflows/principals/publicPrincipalHistoryTypes.js +2 -0
  182. package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -0
  183. package/workflows/principals/publicProjectionDirectory.js +40 -0
  184. package/workflows/principals/publicProjectionDirectory.js.map +1 -0
  185. package/workflows/principals/publicProjectionPrincipal.js +53 -0
  186. package/workflows/principals/publicProjectionPrincipal.js.map +1 -0
  187. package/workflows/principals/recoverPrincipalPolicyHistory.js +4 -1
  188. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  189. package/workflows/principals/recoverProjectionPolicyHistory.d.ts +9 -0
  190. package/workflows/principals/recoverProjectionPolicyHistory.js +98 -0
  191. package/workflows/principals/recoverProjectionPolicyHistory.js.map +1 -0
  192. package/workflows/principals/recoverPublicPrincipalHistory.js +176 -0
  193. package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -0
  194. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +2 -5
  195. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
  196. package/workflows/principals/runtimePolicyRecovery.js +2 -1
  197. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  198. package/workflows/principals/runtimePolicyWarmer.js +2 -0
  199. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
  200. package/workflows/principals/runtimeProjectionPolicyRecovery.js +56 -0
  201. package/workflows/principals/runtimeProjectionPolicyRecovery.js.map +1 -0
  202. package/workflows/principals/selectPublicPrincipalHistory.js +90 -0
  203. package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -0
  204. package/workflows/registration/provisioningBootstrapBuilders.d.ts +21 -153
@@ -3,12 +3,12 @@ import { locallyAcknowledgedContainerMutationHead } from "../../../data/containe
3
3
  import { isStaleParentContainerPathFailure } from "../../../data/containers/shared/mutationFailures.js";
4
4
  import { assertDocumentWriterProjectionConsistent } from "../../../data/documents/shared/projection.js";
5
5
  import { advanceLocallyAcknowledgedAccessManifestHeadsAtomically, locallyAuthoredAccessManifestHead, } from "../../../data/persistence/locallyAcknowledgedCheckpointPersistence.js";
6
- import { buildMaterializedContainerCreatePlan, childContainerWriterProjectionFromCreatePlan, readContainerMutationMetadataDocumentId, } from "../../containers/index.js";
7
- import { buildMaterializedDocumentCreatePlan, documentWriterProjectionFromCreateResponse, persistedDocumentCreateStateFromResponse, resolveDocumentCreateAuthor, } from "../../documents/index.js";
6
+ import { readContainerMutationMetadataDocumentId, } from "../../containers/index.js";
7
+ import { documentWriterProjectionFromCreateResponse, persistedDocumentCreateStateFromResponse, resolveDocumentCreateAuthor, } from "../../documents/index.js";
8
8
  import { cachePrincipalPolicyBundles } from "../../principals/policyCache.js";
9
9
  import { PrincipalPolicyRepairBudget } from "../../principals/policyRepairBudget.js";
10
- import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
11
10
  import { settleTerminalCreateFailure } from "./createTerminalFailure.js";
11
+ import { buildContainerWithMetadataPlans, } from "./createWithMetadataPlan.js";
12
12
  /**
13
13
  * Sentinel for a lost-response retry whose manifest already exists remotely.
14
14
  * Callers avoid a duplicate; the next parent hydration settles local state.
@@ -187,42 +187,10 @@ async function settleContainerWithMetadataCreate(input) {
187
187
  }
188
188
  async function createRemoteContainerWithMetadataDocumentAttempt(input) {
189
189
  const execSql = input.runtime.infra.execSql;
190
- // Rebuild parent- and policy-dependent hashes, signatures, and wraps on every
191
- // attempt while retaining the logical mutation identities and key material.
192
- const containerPlan = await buildMaterializedContainerCreatePlan({
193
- author: input.author,
194
- containerId: input.containerId,
195
- containerKey: input.containerKey,
196
- execSql,
197
- eventId: input.containerEventId,
198
- metadataDocumentId: input.containerId,
199
- systemSlot: input.systemSlot,
200
- parentProjection: input.parentProjection,
201
- parentSecretKey: input.parentSecretKey,
202
- resolveProjectionUserKey: input.resolveProjectionUserKey,
203
- signedAt: input.containerSignedAt,
204
- stillCurrent: input.stillCurrent,
205
- warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(input.runtime),
206
- });
207
- const childProjection = childContainerWriterProjectionFromCreatePlan({
208
- materializedPlan: containerPlan,
209
- parentProjection: input.parentProjection,
210
- });
211
- const metadataDocumentPlan = await buildMaterializedDocumentCreatePlan({
212
- author: input.author,
213
- containerProjection: childProjection,
214
- contentKey: input.metadataContentKey,
215
- documentId: containerPlan.plan.metadataDocumentId,
216
- eventId: input.metadataEventId,
217
- execSql,
218
- knownContainerKeks: new Map([
219
- [containerPlan.plan.containerKeyEpochId, containerPlan.containerKey],
220
- ]),
221
- signedAt: input.metadataSignedAt,
222
- stillCurrent: input.stillCurrent,
223
- targetSecretKey: input.parentSecretKey,
224
- trustedLocalProjection: true,
225
- });
190
+ const plans = await buildContainerWithMetadataPlans(input);
191
+ if (!plans)
192
+ return null;
193
+ const { containerPlan, childProjection, metadataDocumentPlan } = plans;
226
194
  const submitted = await submitContainerWithMetadataDocument({
227
195
  organizationId: containerPlan.plan.state.organizationId,
228
196
  request: {
@@ -1 +1 @@
1
- {"version":3,"file":"createWithMetadata.js","sourceRoot":"","sources":["createWithMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerAccessManifestState } from \"@tearleads/crypto\";\nimport {\n type ContainerSystemSlot,\n isContainerSystemSlot,\n} from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerCreateWithMetadataDocumentRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerCreateWithMetadataDocumentResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { locallyAcknowledgedContainerMutationHead } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport { isStaleParentContainerPathFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type { ContainerMutationSubmitFailure } from \"../../../data/containers/shared/types\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../../data/documents/shared/projection\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n locallyAuthoredAccessManifestHead,\n} from \"../../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n buildMaterializedContainerCreatePlan,\n childContainerWriterProjectionFromCreatePlan,\n readContainerMutationMetadataDocumentId,\n} from \"../../containers\";\nimport {\n buildMaterializedDocumentCreatePlan,\n documentWriterProjectionFromCreateResponse,\n persistedDocumentCreateStateFromResponse,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport { cachePrincipalPolicyBundles } from \"../../principals/policyCache\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport { settleTerminalCreateFailure } from \"./createTerminalFailure\";\nimport type {\n ContainerWorkflowRuntime,\n CreatedRemoteContainerState,\n} from \"./types\";\n\n/**\n * Sentinel for a lost-response retry whose manifest already exists remotely.\n * Callers avoid a duplicate; the next parent hydration settles local state.\n */\nexport const CONTAINER_ALREADY_COMMITTED = Symbol(\"containerAlreadyCommitted\");\nexport type ContainerAlreadyCommitted = typeof CONTAINER_ALREADY_COMMITTED;\n\nasync function submitContainerWithMetadataDocument(input: {\n readonly organizationId: string;\n readonly request: ContainerCreateWithMetadataDocumentRequest;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const { apiClient } = input.runtime;\n const result = await apiClient.createContainerWithMetadataDocumentResult(\n input.request,\n {\n expectedPaymentRequiredOrganizationId: input.organizationId,\n reportErrors: false,\n },\n );\n return result.ok ? { ok: true, response: result.data } : result;\n}\n\nasync function cacheStalePrincipalPolicyBundles(input: {\n readonly failure: ContainerMutationSubmitFailure;\n readonly organizationId: string;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n const bundles = input.failure.stalePrincipalPolicies;\n const apiClient = input.runtime.apiClient;\n const getCurrentPrincipalPolicy =\n apiClient.getCurrentPrincipalPolicy.bind(apiClient);\n if (input.stillCurrent?.() === false) return false;\n if (!bundles || bundles.length === 0) {\n return false;\n }\n\n // A stale-policy failure is actionable only after the supplied bundles have\n // been verified and cached; the next attempt will rebuild from that cache.\n await cachePrincipalPolicyBundles({\n bundles,\n execSql: input.runtime.infra.execSql,\n getCurrentPrincipalPolicy,\n log: input.runtime.util.log,\n organizationId: input.organizationId,\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n return input.stillCurrent?.() !== false;\n}\n\n/**\n * Seed the metadata document's writer projection from the create response so the\n * first read after the container is created (its own metadata sync, contents\n * hydration) resolves locally instead of a cold `GET writer-projection`. The\n * authorizing path is the child container projection the create was authored\n * against — locally built rather than server-fetched, so unlike the plain\n * document-create path this is gated on the projection's internal consistency;\n * on any mismatch the seed is skipped and the next read falls back to a fetch.\n */\nasync function seedMetadataDocumentWriterProjection(input: {\n readonly runtime: ContainerWorkflowRuntime;\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly execSql?: ExecSql | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<void> {\n const projection = documentWriterProjectionFromCreateResponse({\n containerProjection: input.childProjection,\n response: input.response.metadataDocument,\n });\n try {\n await assertDocumentWriterProjectionConsistent(projection, {\n execSql: input.execSql,\n stillCurrent: input.stillCurrent,\n trustedLocalProjection: true,\n });\n } catch {\n return;\n }\n if (input.stillCurrent?.() === false) return;\n input.runtime.apiClient.primeDocumentWriterProjection(\n input.response.metadataDocument.id,\n projection,\n );\n}\n\nasync function acknowledgeContainerWithMetadata(input: {\n containerPlan: Parameters<\n typeof locallyAcknowledgedContainerMutationHead\n >[0][\"plan\"];\n execSql: ExecSql;\n metadataDocumentPlan: Parameters<\n typeof persistedDocumentCreateStateFromResponse\n >[0];\n response: ContainerCreateWithMetadataDocumentResponse;\n stillCurrent?: (() => boolean) | undefined;\n}) {\n const persistedState = persistedDocumentCreateStateFromResponse(\n input.metadataDocumentPlan,\n input.response.metadataDocument,\n );\n const containerHead = await locallyAcknowledgedContainerMutationHead({\n plan: input.containerPlan,\n response: input.response.container,\n });\n await advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads: [\n containerHead,\n locallyAuthoredAccessManifestHead(input.metadataDocumentPlan),\n ],\n stillCurrent: input.stillCurrent,\n });\n return persistedState;\n}\n\n/**\n * Prime the new container's writer projection from the create plan the client\n * just authored, so the first write under it (a child folder, a document)\n * resolves locally instead of a cold `GET writer-projection`. Only primed when\n * the locally-built projection matches what the server created — the create\n * response echoes the container id and manifest head — so a mismatch skips the\n * seed and the next write falls back to a fetch (same fail-closed contract as\n * the metadata-document seed). Priming is safe for writes: the server still\n * validates every mutation, so a projection that later goes stale (rekey/share/\n * move evict it) just yields a rejected write that retries with a fresh fetch.\n */\nfunction seedChildContainerWriterProjection(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n}): void {\n const createdManifestHash =\n input.response.container.manifestHead.manifestHash;\n const projectedManifestHash = input.childProjection.path.at(-1)?.manifestHash;\n // Both hashes must be present and equal, or two undefined hashes would compare\n // equal and prime an empty/invalid projection.\n if (\n !createdManifestHash ||\n !projectedManifestHash ||\n input.childProjection.containerId !==\n input.response.container.containerId ||\n projectedManifestHash !== createdManifestHash\n ) {\n return;\n }\n\n input.runtime.apiClient.primeContainerWriterProjection(\n input.response.container.containerId,\n input.childProjection,\n );\n}\n\n/**\n * The persisted slot is the one this client signed into the manifest state.\n * The acknowledgement already refused a response that echoed anything else,\n * so the server's column never chooses which local record becomes Trash.\n */\nfunction signedCreateSystemSlot(\n state: ContainerAccessManifestState,\n): ContainerSystemSlot | null {\n if (state.systemSlot === null) return null;\n if (!isContainerSystemSlot(state.systemSlot)) {\n throw new Error(\"Container create plan signed an invalid system slot\");\n }\n return state.systemSlot;\n}\n\nasync function settleContainerWithMetadataCreate(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly containerPlan: Awaited<\n ReturnType<typeof buildMaterializedContainerCreatePlan>\n >;\n readonly execSql: ExecSql;\n readonly metadataDocumentPlan: Awaited<\n ReturnType<typeof buildMaterializedDocumentCreatePlan>\n >;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<{\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n} | null> {\n if (\n input.response.container.containerId !==\n input.containerPlan.plan.containerId\n ) {\n throw new Error(\"Container metadata create response container mismatch\");\n }\n // The acknowledgement echoed the signed parent, which a child always names.\n const parentId = input.containerPlan.plan.state.parentContainerId;\n if (parentId === null) {\n throw new Error(\"A container create must commit under a parent\");\n }\n const metadataDocumentId = readContainerMutationMetadataDocumentId({\n response: input.response.container,\n });\n if (\n metadataDocumentId !== input.containerPlan.plan.metadataDocumentId ||\n input.response.metadataDocument.id !==\n input.metadataDocumentPlan.plan.documentId\n ) {\n throw new Error(\"Container metadata create response document mismatch\");\n }\n const persistedMetadataState = await acknowledgeContainerWithMetadata({\n containerPlan: input.containerPlan.plan,\n execSql: input.execSql,\n metadataDocumentPlan: input.metadataDocumentPlan.plan,\n response: input.response,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n await seedMetadataDocumentWriterProjection({\n childProjection: input.childProjection,\n execSql: input.execSql,\n response: input.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n seedChildContainerWriterProjection({\n childProjection: input.childProjection,\n response: input.response,\n runtime: input.runtime,\n });\n return {\n ok: true,\n state: {\n accessManifestHash: input.response.container.manifestHead.manifestHash,\n systemSlot: signedCreateSystemSlot(input.containerPlan.plan.state),\n containerId: input.response.container.containerId,\n createdAt: input.response.container.createdAt,\n metadataDocumentId,\n organizationId: input.response.container.organizationId,\n parentId,\n persistedMetadataState,\n updatedAt: input.response.container.updatedAt,\n },\n };\n}\n\nasync function createRemoteContainerWithMetadataDocumentAttempt(input: {\n readonly author: NonNullable<ReturnType<typeof resolveDocumentCreateAuthor>>;\n readonly containerEventId: string;\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly containerSignedAt: string;\n readonly metadataContentKey: Uint8Array;\n readonly metadataEventId: string;\n readonly metadataSignedAt: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly parentSecretKey: Uint8Array;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly runtime: ContainerWorkflowRuntime;\n readonly systemSlot?: ContainerSystemSlot | null | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n const execSql = input.runtime.infra.execSql;\n // Rebuild parent- and policy-dependent hashes, signatures, and wraps on every\n // attempt while retaining the logical mutation identities and key material.\n const containerPlan = await buildMaterializedContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n execSql,\n eventId: input.containerEventId,\n metadataDocumentId: input.containerId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n parentSecretKey: input.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.containerSignedAt,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n const childProjection = childContainerWriterProjectionFromCreatePlan({\n materializedPlan: containerPlan,\n parentProjection: input.parentProjection,\n });\n const metadataDocumentPlan = await buildMaterializedDocumentCreatePlan({\n author: input.author,\n containerProjection: childProjection,\n contentKey: input.metadataContentKey,\n documentId: containerPlan.plan.metadataDocumentId,\n eventId: input.metadataEventId,\n execSql,\n knownContainerKeks: new Map([\n [containerPlan.plan.containerKeyEpochId, containerPlan.containerKey],\n ]),\n signedAt: input.metadataSignedAt,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.parentSecretKey,\n trustedLocalProjection: true,\n });\n const submitted = await submitContainerWithMetadataDocument({\n organizationId: containerPlan.plan.state.organizationId,\n request: {\n systemSlot: input.systemSlot ?? null,\n container: containerPlan.plan.request,\n metadataDocument: metadataDocumentPlan.plan.request,\n },\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (!submitted?.ok) {\n return submitted;\n }\n return settleContainerWithMetadataCreate({\n childProjection,\n containerPlan,\n execSql,\n metadataDocumentPlan,\n response: submitted.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n}\n\nasync function createContainerWithMetadataWithRepairs(\n input: Parameters<\n typeof createRemoteContainerWithMetadataDocumentAttempt\n >[0] & {\n readonly parentContainerId: string;\n },\n): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const { apiClient } = input.runtime;\n let parentProjection = input.parentProjection;\n let didRepairStaleParent = false;\n const policyRepairs = new PrincipalPolicyRepairBudget();\n for (;;) {\n const submitted = await createRemoteContainerWithMetadataDocumentAttempt({\n ...input,\n parentProjection,\n });\n if (!submitted) {\n return null;\n }\n if (submitted.ok) {\n return submitted.state;\n }\n if (\n policyRepairs.take(submitted.stalePrincipalPolicies) &&\n (await cacheStalePrincipalPolicyBundles({\n failure: submitted,\n organizationId: parentProjection.organizationId,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n }))\n ) {\n continue;\n }\n if (\n !didRepairStaleParent &&\n isStaleParentContainerPathFailure(submitted) &&\n apiClient.evictContainerWriterProjection &&\n input.stillCurrent?.() !== false\n ) {\n didRepairStaleParent = true;\n apiClient.evictContainerWriterProjection(input.parentContainerId);\n const refreshedProjection = await apiClient.getContainerWriterProjection(\n input.parentContainerId,\n );\n if (!refreshedProjection) {\n return null;\n }\n if (input.stillCurrent?.() === false) return null;\n parentProjection = refreshedProjection;\n continue;\n }\n return settleTerminalCreateFailure(submitted, input.stillCurrent) ===\n \"committed\"\n ? CONTAINER_ALREADY_COMMITTED\n : null;\n }\n}\n\nexport async function createRemoteContainerWithMetadataDocument(input: {\n systemSlot?: ContainerSystemSlot | null | undefined;\n containerId: string;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const author = resolveDocumentCreateAuthor(input.runtime);\n const { apiClient } = input.runtime;\n const parentSecretKey = input.runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!author || !parentSecretKey) {\n input.runtime.util.log(\n \"Container contents: skipped container create because the writer context is unavailable.\",\n );\n return null;\n }\n\n const parentProjection =\n input.parentProjection ??\n (await apiClient.getContainerWriterProjection(input.parentContainerId));\n if (!parentProjection) {\n return null;\n }\n\n const containerEventId = crypto.randomUUID();\n const containerKey = crypto.getRandomValues(new Uint8Array(32));\n const containerSignedAt = new Date().toISOString();\n const metadataContentKey = crypto.getRandomValues(new Uint8Array(32));\n const metadataEventId = crypto.randomUUID();\n const metadataSignedAt = new Date().toISOString();\n return createContainerWithMetadataWithRepairs({\n author,\n containerEventId,\n containerId: input.containerId,\n containerKey,\n containerSignedAt,\n metadataContentKey,\n metadataEventId,\n metadataSignedAt,\n parentContainerId: input.parentContainerId,\n parentProjection,\n parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n systemSlot: input.systemSlot,\n });\n}\n"]}
1
+ {"version":3,"file":"createWithMetadata.js","sourceRoot":"","sources":["createWithMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerAccessManifestState } from \"@tearleads/crypto\";\nimport {\n type ContainerSystemSlot,\n isContainerSystemSlot,\n} from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerCreateWithMetadataDocumentRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerCreateWithMetadataDocumentResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { locallyAcknowledgedContainerMutationHead } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport { isStaleParentContainerPathFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type { ContainerMutationSubmitFailure } from \"../../../data/containers/shared/types\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../../data/documents/shared/projection\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n locallyAuthoredAccessManifestHead,\n} from \"../../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n type buildMaterializedContainerCreatePlan,\n readContainerMutationMetadataDocumentId,\n} from \"../../containers\";\nimport {\n type buildMaterializedDocumentCreatePlan,\n documentWriterProjectionFromCreateResponse,\n persistedDocumentCreateStateFromResponse,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport { cachePrincipalPolicyBundles } from \"../../principals/policyCache\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport { settleTerminalCreateFailure } from \"./createTerminalFailure\";\nimport {\n buildContainerWithMetadataPlans,\n type ContainerWithMetadataPlanInput,\n} from \"./createWithMetadataPlan\";\nimport type {\n ContainerWorkflowRuntime,\n CreatedRemoteContainerState,\n} from \"./types\";\n\n/**\n * Sentinel for a lost-response retry whose manifest already exists remotely.\n * Callers avoid a duplicate; the next parent hydration settles local state.\n */\nexport const CONTAINER_ALREADY_COMMITTED = Symbol(\"containerAlreadyCommitted\");\nexport type ContainerAlreadyCommitted = typeof CONTAINER_ALREADY_COMMITTED;\n\nasync function submitContainerWithMetadataDocument(input: {\n readonly organizationId: string;\n readonly request: ContainerCreateWithMetadataDocumentRequest;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const { apiClient } = input.runtime;\n const result = await apiClient.createContainerWithMetadataDocumentResult(\n input.request,\n {\n expectedPaymentRequiredOrganizationId: input.organizationId,\n reportErrors: false,\n },\n );\n return result.ok ? { ok: true, response: result.data } : result;\n}\n\nasync function cacheStalePrincipalPolicyBundles(input: {\n readonly failure: ContainerMutationSubmitFailure;\n readonly organizationId: string;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n const bundles = input.failure.stalePrincipalPolicies;\n const apiClient = input.runtime.apiClient;\n const getCurrentPrincipalPolicy =\n apiClient.getCurrentPrincipalPolicy.bind(apiClient);\n if (input.stillCurrent?.() === false) return false;\n if (!bundles || bundles.length === 0) {\n return false;\n }\n\n // A stale-policy failure is actionable only after the supplied bundles have\n // been verified and cached; the next attempt will rebuild from that cache.\n await cachePrincipalPolicyBundles({\n bundles,\n execSql: input.runtime.infra.execSql,\n getCurrentPrincipalPolicy,\n log: input.runtime.util.log,\n organizationId: input.organizationId,\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n return input.stillCurrent?.() !== false;\n}\n\n/**\n * Seed the metadata document's writer projection from the create response so the\n * first read after the container is created (its own metadata sync, contents\n * hydration) resolves locally instead of a cold `GET writer-projection`. The\n * authorizing path is the child container projection the create was authored\n * against — locally built rather than server-fetched, so unlike the plain\n * document-create path this is gated on the projection's internal consistency;\n * on any mismatch the seed is skipped and the next read falls back to a fetch.\n */\nasync function seedMetadataDocumentWriterProjection(input: {\n readonly runtime: ContainerWorkflowRuntime;\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly execSql?: ExecSql | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<void> {\n const projection = documentWriterProjectionFromCreateResponse({\n containerProjection: input.childProjection,\n response: input.response.metadataDocument,\n });\n try {\n await assertDocumentWriterProjectionConsistent(projection, {\n execSql: input.execSql,\n stillCurrent: input.stillCurrent,\n trustedLocalProjection: true,\n });\n } catch {\n return;\n }\n if (input.stillCurrent?.() === false) return;\n input.runtime.apiClient.primeDocumentWriterProjection(\n input.response.metadataDocument.id,\n projection,\n );\n}\n\nasync function acknowledgeContainerWithMetadata(input: {\n containerPlan: Parameters<\n typeof locallyAcknowledgedContainerMutationHead\n >[0][\"plan\"];\n execSql: ExecSql;\n metadataDocumentPlan: Parameters<\n typeof persistedDocumentCreateStateFromResponse\n >[0];\n response: ContainerCreateWithMetadataDocumentResponse;\n stillCurrent?: (() => boolean) | undefined;\n}) {\n const persistedState = persistedDocumentCreateStateFromResponse(\n input.metadataDocumentPlan,\n input.response.metadataDocument,\n );\n const containerHead = await locallyAcknowledgedContainerMutationHead({\n plan: input.containerPlan,\n response: input.response.container,\n });\n await advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads: [\n containerHead,\n locallyAuthoredAccessManifestHead(input.metadataDocumentPlan),\n ],\n stillCurrent: input.stillCurrent,\n });\n return persistedState;\n}\n\n/**\n * Prime the new container's writer projection from the create plan the client\n * just authored, so the first write under it (a child folder, a document)\n * resolves locally instead of a cold `GET writer-projection`. Only primed when\n * the locally-built projection matches what the server created — the create\n * response echoes the container id and manifest head — so a mismatch skips the\n * seed and the next write falls back to a fetch (same fail-closed contract as\n * the metadata-document seed). Priming is safe for writes: the server still\n * validates every mutation, so a projection that later goes stale (rekey/share/\n * move evict it) just yields a rejected write that retries with a fresh fetch.\n */\nfunction seedChildContainerWriterProjection(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n}): void {\n const createdManifestHash =\n input.response.container.manifestHead.manifestHash;\n const projectedManifestHash = input.childProjection.path.at(-1)?.manifestHash;\n // Both hashes must be present and equal, or two undefined hashes would compare\n // equal and prime an empty/invalid projection.\n if (\n !createdManifestHash ||\n !projectedManifestHash ||\n input.childProjection.containerId !==\n input.response.container.containerId ||\n projectedManifestHash !== createdManifestHash\n ) {\n return;\n }\n\n input.runtime.apiClient.primeContainerWriterProjection(\n input.response.container.containerId,\n input.childProjection,\n );\n}\n\n/**\n * The persisted slot is the one this client signed into the manifest state.\n * The acknowledgement already refused a response that echoed anything else,\n * so the server's column never chooses which local record becomes Trash.\n */\nfunction signedCreateSystemSlot(\n state: ContainerAccessManifestState,\n): ContainerSystemSlot | null {\n if (state.systemSlot === null) return null;\n if (!isContainerSystemSlot(state.systemSlot)) {\n throw new Error(\"Container create plan signed an invalid system slot\");\n }\n return state.systemSlot;\n}\n\nasync function settleContainerWithMetadataCreate(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly containerPlan: Awaited<\n ReturnType<typeof buildMaterializedContainerCreatePlan>\n >;\n readonly execSql: ExecSql;\n readonly metadataDocumentPlan: Awaited<\n ReturnType<typeof buildMaterializedDocumentCreatePlan>\n >;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<{\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n} | null> {\n if (\n input.response.container.containerId !==\n input.containerPlan.plan.containerId\n ) {\n throw new Error(\"Container metadata create response container mismatch\");\n }\n // The acknowledgement echoed the signed parent, which a child always names.\n const parentId = input.containerPlan.plan.state.parentContainerId;\n if (parentId === null) {\n throw new Error(\"A container create must commit under a parent\");\n }\n const metadataDocumentId = readContainerMutationMetadataDocumentId({\n response: input.response.container,\n });\n if (\n metadataDocumentId !== input.containerPlan.plan.metadataDocumentId ||\n input.response.metadataDocument.id !==\n input.metadataDocumentPlan.plan.documentId\n ) {\n throw new Error(\"Container metadata create response document mismatch\");\n }\n const persistedMetadataState = await acknowledgeContainerWithMetadata({\n containerPlan: input.containerPlan.plan,\n execSql: input.execSql,\n metadataDocumentPlan: input.metadataDocumentPlan.plan,\n response: input.response,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n await seedMetadataDocumentWriterProjection({\n childProjection: input.childProjection,\n execSql: input.execSql,\n response: input.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n seedChildContainerWriterProjection({\n childProjection: input.childProjection,\n response: input.response,\n runtime: input.runtime,\n });\n return {\n ok: true,\n state: {\n accessManifestHash: input.response.container.manifestHead.manifestHash,\n systemSlot: signedCreateSystemSlot(input.containerPlan.plan.state),\n containerId: input.response.container.containerId,\n createdAt: input.response.container.createdAt,\n metadataDocumentId,\n organizationId: input.response.container.organizationId,\n parentId,\n persistedMetadataState,\n updatedAt: input.response.container.updatedAt,\n },\n };\n}\n\nasync function createRemoteContainerWithMetadataDocumentAttempt(\n input: ContainerWithMetadataPlanInput,\n): Promise<\n | {\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n const execSql = input.runtime.infra.execSql;\n const plans = await buildContainerWithMetadataPlans(input);\n if (!plans) return null;\n const { containerPlan, childProjection, metadataDocumentPlan } = plans;\n const submitted = await submitContainerWithMetadataDocument({\n organizationId: containerPlan.plan.state.organizationId,\n request: {\n systemSlot: input.systemSlot ?? null,\n container: containerPlan.plan.request,\n metadataDocument: metadataDocumentPlan.plan.request,\n },\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (!submitted?.ok) {\n return submitted;\n }\n return settleContainerWithMetadataCreate({\n childProjection,\n containerPlan,\n execSql,\n metadataDocumentPlan,\n response: submitted.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n}\n\nasync function createContainerWithMetadataWithRepairs(\n input: Parameters<\n typeof createRemoteContainerWithMetadataDocumentAttempt\n >[0] & {\n readonly parentContainerId: string;\n },\n): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const { apiClient } = input.runtime;\n let parentProjection = input.parentProjection;\n let didRepairStaleParent = false;\n const policyRepairs = new PrincipalPolicyRepairBudget();\n for (;;) {\n const submitted = await createRemoteContainerWithMetadataDocumentAttempt({\n ...input,\n parentProjection,\n });\n if (!submitted) {\n return null;\n }\n if (submitted.ok) {\n return submitted.state;\n }\n if (\n policyRepairs.take(submitted.stalePrincipalPolicies) &&\n (await cacheStalePrincipalPolicyBundles({\n failure: submitted,\n organizationId: parentProjection.organizationId,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n }))\n ) {\n continue;\n }\n if (\n !didRepairStaleParent &&\n isStaleParentContainerPathFailure(submitted) &&\n apiClient.evictContainerWriterProjection &&\n input.stillCurrent?.() !== false\n ) {\n didRepairStaleParent = true;\n apiClient.evictContainerWriterProjection(input.parentContainerId);\n const refreshedProjection = await apiClient.getContainerWriterProjection(\n input.parentContainerId,\n );\n if (!refreshedProjection) {\n return null;\n }\n if (input.stillCurrent?.() === false) return null;\n parentProjection = refreshedProjection;\n continue;\n }\n return settleTerminalCreateFailure(submitted, input.stillCurrent) ===\n \"committed\"\n ? CONTAINER_ALREADY_COMMITTED\n : null;\n }\n}\n\nexport async function createRemoteContainerWithMetadataDocument(input: {\n systemSlot?: ContainerSystemSlot | null | undefined;\n containerId: string;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const author = resolveDocumentCreateAuthor(input.runtime);\n const { apiClient } = input.runtime;\n const parentSecretKey = input.runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!author || !parentSecretKey) {\n input.runtime.util.log(\n \"Container contents: skipped container create because the writer context is unavailable.\",\n );\n return null;\n }\n\n const parentProjection =\n input.parentProjection ??\n (await apiClient.getContainerWriterProjection(input.parentContainerId));\n if (!parentProjection) {\n return null;\n }\n\n const containerEventId = crypto.randomUUID();\n const containerKey = crypto.getRandomValues(new Uint8Array(32));\n const containerSignedAt = new Date().toISOString();\n const metadataContentKey = crypto.getRandomValues(new Uint8Array(32));\n const metadataEventId = crypto.randomUUID();\n const metadataSignedAt = new Date().toISOString();\n return createContainerWithMetadataWithRepairs({\n author,\n containerEventId,\n containerId: input.containerId,\n containerKey,\n containerSignedAt,\n metadataContentKey,\n metadataEventId,\n metadataSignedAt,\n parentContainerId: input.parentContainerId,\n parentProjection,\n parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n systemSlot: input.systemSlot,\n });\n}\n"]}
@@ -0,0 +1,68 @@
1
+ import { ProjectionDependencyUnavailableError } from "../../../data/keyingProjectionVerification/dependencyUnavailable.js";
2
+ import { buildMaterializedContainerCreatePlan, childContainerWriterProjectionFromCreatePlan, } from "../../containers/index.js";
3
+ import { buildMaterializedDocumentCreatePlan, } from "../../documents/index.js";
4
+ import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
5
+ async function buildPlans(input) {
6
+ const execSql = input.runtime.infra.execSql;
7
+ // Rebuild parent- and policy-dependent hashes, signatures, and wraps on every
8
+ // attempt while retaining the logical mutation identities and key material.
9
+ const containerPlan = await buildMaterializedContainerCreatePlan({
10
+ author: input.author,
11
+ containerId: input.containerId,
12
+ containerKey: input.containerKey,
13
+ execSql,
14
+ eventId: input.containerEventId,
15
+ metadataDocumentId: input.containerId,
16
+ systemSlot: input.systemSlot,
17
+ parentProjection: input.parentProjection,
18
+ parentSecretKey: input.parentSecretKey,
19
+ resolveProjectionUserKey: input.resolveProjectionUserKey,
20
+ signedAt: input.containerSignedAt,
21
+ stillCurrent: input.stillCurrent,
22
+ warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(input.runtime),
23
+ });
24
+ const childProjection = childContainerWriterProjectionFromCreatePlan({
25
+ materializedPlan: containerPlan,
26
+ parentProjection: input.parentProjection,
27
+ });
28
+ const metadataDocumentPlan = await buildMaterializedDocumentCreatePlan({
29
+ author: input.author,
30
+ containerProjection: childProjection,
31
+ contentKey: input.metadataContentKey,
32
+ documentId: containerPlan.plan.metadataDocumentId,
33
+ eventId: input.metadataEventId,
34
+ execSql,
35
+ knownContainerKeks: new Map([
36
+ [containerPlan.plan.containerKeyEpochId, containerPlan.containerKey],
37
+ ]),
38
+ signedAt: input.metadataSignedAt,
39
+ stillCurrent: input.stillCurrent,
40
+ targetSecretKey: input.parentSecretKey,
41
+ trustedLocalProjection: true,
42
+ });
43
+ return { containerPlan, childProjection, metadataDocumentPlan };
44
+ }
45
+ /** Refresh stale history evidence once, strictly before submitting the write. */
46
+ export async function buildContainerWithMetadataPlans(input) {
47
+ try {
48
+ return await buildPlans(input);
49
+ }
50
+ catch (error) {
51
+ if (!(error instanceof ProjectionDependencyUnavailableError))
52
+ throw error;
53
+ }
54
+ if (input.stillCurrent?.() === false)
55
+ return null;
56
+ const { apiClient } = input.runtime;
57
+ const parentId = input.parentProjection.containerId;
58
+ apiClient.evictContainerWriterProjection(parentId);
59
+ const parentProjection = await apiClient.getContainerWriterProjection(parentId);
60
+ if (!parentProjection || input.stillCurrent?.() === false)
61
+ return null;
62
+ if (parentProjection.containerId !== parentId ||
63
+ parentProjection.organizationId !== input.parentProjection.organizationId) {
64
+ throw new Error("Refreshed parent projection belongs to another container or organization");
65
+ }
66
+ return buildPlans({ ...input, parentProjection });
67
+ }
68
+ //# sourceMappingURL=createWithMetadataPlan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createWithMetadataPlan.js","sourceRoot":"","sources":["createWithMetadataPlan.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { ProjectionDependencyUnavailableError } from \"../../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport {\n buildMaterializedContainerCreatePlan,\n childContainerWriterProjectionFromCreatePlan,\n} from \"../../containers\";\nimport {\n buildMaterializedDocumentCreatePlan,\n type resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerWorkflowRuntime } from \"./types\";\n\nexport interface ContainerWithMetadataPlanInput {\n readonly author: NonNullable<ReturnType<typeof resolveDocumentCreateAuthor>>;\n readonly containerEventId: string;\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly containerSignedAt: string;\n readonly metadataContentKey: Uint8Array;\n readonly metadataEventId: string;\n readonly metadataSignedAt: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly parentSecretKey: Uint8Array;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly runtime: ContainerWorkflowRuntime;\n readonly systemSlot?: ContainerSystemSlot | null | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nasync function buildPlans(input: ContainerWithMetadataPlanInput) {\n const execSql = input.runtime.infra.execSql;\n // Rebuild parent- and policy-dependent hashes, signatures, and wraps on every\n // attempt while retaining the logical mutation identities and key material.\n const containerPlan = await buildMaterializedContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n execSql,\n eventId: input.containerEventId,\n metadataDocumentId: input.containerId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n parentSecretKey: input.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.containerSignedAt,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n const childProjection = childContainerWriterProjectionFromCreatePlan({\n materializedPlan: containerPlan,\n parentProjection: input.parentProjection,\n });\n const metadataDocumentPlan = await buildMaterializedDocumentCreatePlan({\n author: input.author,\n containerProjection: childProjection,\n contentKey: input.metadataContentKey,\n documentId: containerPlan.plan.metadataDocumentId,\n eventId: input.metadataEventId,\n execSql,\n knownContainerKeks: new Map([\n [containerPlan.plan.containerKeyEpochId, containerPlan.containerKey],\n ]),\n signedAt: input.metadataSignedAt,\n stillCurrent: input.stillCurrent,\n targetSecretKey: input.parentSecretKey,\n trustedLocalProjection: true,\n });\n return { containerPlan, childProjection, metadataDocumentPlan };\n}\n\n/** Refresh stale history evidence once, strictly before submitting the write. */\nexport async function buildContainerWithMetadataPlans(\n input: ContainerWithMetadataPlanInput,\n) {\n try {\n return await buildPlans(input);\n } catch (error) {\n if (!(error instanceof ProjectionDependencyUnavailableError)) throw error;\n }\n if (input.stillCurrent?.() === false) return null;\n const { apiClient } = input.runtime;\n const parentId = input.parentProjection.containerId;\n apiClient.evictContainerWriterProjection(parentId);\n const parentProjection =\n await apiClient.getContainerWriterProjection(parentId);\n if (!parentProjection || input.stillCurrent?.() === false) return null;\n if (\n parentProjection.containerId !== parentId ||\n parentProjection.organizationId !== input.parentProjection.organizationId\n ) {\n throw new Error(\n \"Refreshed parent projection belongs to another container or organization\",\n );\n }\n return buildPlans({ ...input, parentProjection });\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { heldContainerBinding, listingRepeatsHeldOrdinaryBinding, } from "../../data/containers/containerBinding.js";
2
2
  import { isKeyingVerificationError, runWithSecurityIncidentReporting, } from "../../data/keyingProjectionVerification/error.js";
3
+ import { isProjectionVerificationCancelledError } from "../../data/keyingProjectionVerification/types.js";
3
4
  import { installContainerMetadataRecord } from "./metadataPersistence.js";
4
5
  import { projectionGeneration } from "./projectionGeneration.js";
5
6
  import { moveIndexedContainerChild, removeIndexedContainerChild, } from "./remoteHydration/childIndex.js";
@@ -229,7 +230,8 @@ export async function upsertIsolatedRemoteContainerState(input) {
229
230
  return await upsertRemoteContainerState(input);
230
231
  }
231
232
  catch (error) {
232
- if (!isKeyingVerificationError(error))
233
+ if (!isKeyingVerificationError(error) &&
234
+ !isProjectionVerificationCancelledError(error))
233
235
  throw error;
234
236
  return null;
235
237
  }
@@ -1 +1 @@
1
- {"version":3,"file":"remoteContainerState.js","sourceRoot":"","sources":["remoteContainerState.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccessManifestCheckpoint } from \"@tearleads/crypto\";\nimport {\n heldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../data/containers/containerBinding\";\nimport {\n isKeyingVerificationError,\n runWithSecurityIncidentReporting,\n} from \"../../data/keyingProjectionVerification/error\";\nimport type { ContainerHydrationTombstone } from \"./containerPersistence\";\nimport { installContainerMetadataRecord } from \"./metadataPersistence\";\nimport { projectionGeneration } from \"./projectionGeneration\";\nimport {\n moveIndexedContainerChild,\n removeIndexedContainerChild,\n} from \"./remoteHydration/childIndex\";\nimport type { PrefetchedDestinationProjection } from \"./remoteHydration/destinationPrefetch\";\nimport { rebindReHomedContainer } from \"./remoteHydration/heldContainerRebind\";\nimport { insertRemoteContainerState } from \"./remoteHydration/insertRemoteContainer\";\nimport {\n reconcileLocalOnlyRootContainers,\n reconcileLocalOnlySystemContainers,\n} from \"./remoteHydration/reconciliation\";\nimport {\n applyRemoteContainerTimestamps,\n remoteContainerHydrationSaveOptions,\n resolveRemoteContainerHydrationLocalUpdatedAt,\n} from \"./remoteHydration/remoteContainerTimestamps\";\nimport type {\n ContainerChildIndex,\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationHost,\n RemoteContainerHydrationState,\n} from \"./remoteHydration/types\";\nimport { verifyRemoteContainerDestination } from \"./remoteHydration/verifiedDestination\";\n\n// Container ids (restricted to the inbound page) that carry an unsynced local\n// create or move intent. Such a container's parent and local-edit timestamp are\n// owned by its structural-intent lane until that lane reconciles, so inbound\n// hydration must not revert parentId to the server value nor collapse\n// localUpdatedAt — doing so silently undoes a queued move and falsely reads\n// \"synced\". Move intents are read via listUnsyncedMoveIntents so a blocked\n// move — one whose destination parent has not synced yet, the common boot-time\n// case — is protected too. Pending *metadata*\n// updates are handled separately (listRemoteContainerIdsWithPendingMetadataUpdates);\n// these live in dedicated create/move intent tables that that query does not cover.\nexport async function listRemoteContainerIdsWithPendingStructuralIntents(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n if (input.remoteContainers.length === 0) {\n return new Set();\n }\n const remoteContainerIds = new Set(\n input.remoteContainers.map((remoteContainer) => remoteContainer.id),\n );\n\n const execSql = input.state.runtime.infra.execSql;\n const [pendingCreateIntents, unsyncedMoveIntents] = await Promise.all([\n input.state.persistence.listPendingCreateIntents(execSql),\n input.state.persistence.listUnsyncedMoveIntents(execSql),\n ]);\n const containerIdsWithPendingStructuralIntents = new Set<string>();\n for (const intent of pendingCreateIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n for (const intent of unsyncedMoveIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n return containerIdsWithPendingStructuralIntents;\n}\n\nexport async function listRemoteContainerIdsWithPendingMetadataUpdates(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n const containerIds = input.remoteContainers.flatMap((remoteContainer) => {\n const previousLocalUpdatedAt = input.state.containersById.get(\n remoteContainer.id,\n )?.container.localUpdatedAt;\n\n return previousLocalUpdatedAt &&\n previousLocalUpdatedAt.localeCompare(remoteContainer.updatedAt) > 0\n ? [remoteContainer.id]\n : [];\n });\n if (containerIds.length === 0) {\n return new Set();\n }\n\n const execSql = input.state.runtime.infra.execSql;\n return new Set(\n await input.state.persistence.listContainerIdsWithPendingUpdates(\n execSql,\n containerIds,\n ),\n );\n}\n\nfunction removeMissingHydratedContainer(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n existingState: ContainerState;\n host: RemoteContainerHydrationHost;\n previousParentId: string | null;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): void {\n const { existingState, remoteContainer, state } = input;\n if (state.containersById.get(remoteContainer.id) !== existingState) {\n return;\n }\n\n state.containersById.delete(remoteContainer.id);\n if (input.childIdsByParentId) {\n removeIndexedContainerChild(\n input.childIdsByParentId,\n remoteContainer.id,\n input.previousParentId,\n );\n input.childIdsByParentId.delete(remoteContainer.id);\n }\n input.host.updateSnapshot();\n}\n\nfunction createUpdatedRemoteContainerState(\n existingState: ContainerState,\n remoteContainer: RemoteContainer,\n): ContainerState {\n return {\n ...existingState,\n container: applyRemoteContainerTimestamps(\n existingState.container,\n remoteContainer,\n ),\n containerWriterProjection: null,\n metadataReferencedPrincipals: remoteContainer.metadataReferencedPrincipals,\n };\n}\n\nfunction installUpdatedRemoteContainerState(\n existingState: ContainerState,\n nextState: ContainerState,\n host: RemoteContainerHydrationHost,\n): void {\n const wasLocalOnly = existingState.container.serverCreatedAt == null;\n existingState.container = nextState.container;\n existingState.containerWriterProjection = nextState.containerWriterProjection;\n existingState.metadataReferencedPrincipals =\n nextState.metadataReferencedPrincipals;\n // The snapshot copied the live generation when it was taken; a hint that\n // landed during the persist leaves the live metadata projection dropped.\n if (projectionGeneration(existingState) === projectionGeneration(nextState))\n existingState.metadataWriterProjection = nextState.metadataWriterProjection;\n installContainerMetadataRecord(existingState, nextState.record);\n // A document pass may have deferred while this root was awaiting proof.\n // The first durable remote acknowledgement makes its pending creates runnable.\n if (wasLocalOnly && existingState.container.serverCreatedAt != null)\n host.requestDocumentPriming?.();\n}\n\nasync function updateExistingRemoteContainerState(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n isCurrent?: (() => boolean) | undefined;\n existingState: ContainerState;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): Promise<ContainerState | null> {\n const { childIdsByParentId, existingState, host, remoteContainer, state } =\n input;\n const previousParentId = existingState.container.parentId;\n const previousLocalUpdatedAt = existingState.container.localUpdatedAt;\n // A queued, not-yet-synced local move/create owns this container's parent\n // until its intent lane reconciles. Omit the remote parent when the page scan\n // saw one; persistence also rechecks the intent transactionally so a move\n // created after that scan wins. Both paths preserve the durable local clock.\n const hasPendingStructuralIntent =\n input.containerIdsWithPendingStructuralIntents.has(remoteContainer.id);\n const nextParentId = hasPendingStructuralIntent\n ? undefined\n : remoteContainer.parentId;\n const localUpdatedAt = resolveRemoteContainerHydrationLocalUpdatedAt({\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n hasPendingStructuralIntent,\n previousLocalUpdatedAt,\n remoteContainer,\n });\n const nextState = createUpdatedRemoteContainerState(\n existingState,\n remoteContainer,\n );\n const persistenceResult = await host.persistContainerState(\n nextState,\n {\n accessEpoch: remoteContainer.metadataAccessEpoch,\n accessStateHash: remoteContainer.metadataAccessStateHash,\n documentId: remoteContainer.metadataDocumentId,\n effectiveAccessLevel: remoteContainer.effectiveAccessLevel,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n systemSlot: remoteContainer.systemSlot ?? null,\n organizationId: remoteContainer.organizationId,\n ...(nextParentId !== undefined ? { parentId: nextParentId } : {}),\n },\n false,\n remoteContainerHydrationSaveOptions({\n localUpdatedAt,\n remoteContainer,\n }),\n {\n preserveDurableStructureWhenPending: true,\n },\n );\n if (persistenceResult.status === \"missing\") {\n // Hydration persists a detached candidate so an in-flight response cannot\n // mutate mapped state before its guards settle. Retire the exact state this\n // hydration read because store-level reference cleanup cannot see the clone.\n removeMissingHydratedContainer({\n childIdsByParentId,\n existingState,\n host,\n previousParentId,\n remoteContainer,\n state,\n });\n return null;\n }\n if (persistenceResult.status !== \"persisted\") return null;\n const { record: nextRecord } = persistenceResult;\n installContainerMetadataRecord(nextState, nextRecord);\n if (input.isCurrent?.() === false) {\n return existingState;\n }\n nextState.container = {\n ...nextState.container,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n organizationId: remoteContainer.organizationId,\n parentId: nextState.container.parentId,\n };\n\n installUpdatedRemoteContainerState(existingState, nextState, host);\n moveIndexedContainerChild(\n childIdsByParentId,\n remoteContainer.id,\n previousParentId,\n existingState.container.parentId,\n );\n await reconcileLocalOnlyRootContainers({\n childIdsByParentId,\n isCurrent: input.isCurrent,\n remoteRootState: existingState,\n requestDocumentPriming: host.requestDocumentPriming,\n state,\n });\n return existingState;\n}\n\ninterface UpsertRemoteContainerStateInput {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n expectedHydrationTombstone?: ContainerHydrationTombstone | null | undefined;\n isCurrent?: (() => boolean) | undefined;\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}\n\nexport async function upsertRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n let expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n const heldState = input.state.containersById.get(input.remoteContainer.id);\n const heldBinding = heldState\n ? heldContainerBinding(heldState)\n : await input.state.persistence.loadHeldContainerBinding(\n input.state.runtime.infra.execSql,\n input.remoteContainer.id,\n );\n const listed = input.remoteContainer;\n // A folder re-homed away from the listed organization never returns there,\n // whatever binding (possibly none, after a reset) the device holds now.\n const supersededListing =\n !listingRepeatsHeldOrdinaryBinding(heldBinding, listed) &&\n (await input.state.persistence.isSupersededContainerBinding(\n input.state.runtime.infra.execSql,\n { containerId: listed.id, organizationId: listed.organizationId },\n ));\n if (input.isCurrent?.() === false) return null;\n const verified = await verifyRemoteContainerDestination({\n ...input,\n heldBinding,\n supersededListing,\n refresh: !!input.expectedHydrationTombstone,\n onVerifiedCheckpoint: (checkpoint) => {\n expectedPlacementCheckpoint = checkpoint;\n },\n });\n if (!verified || input.isCurrent?.() === false) return null;\n input = { ...input, remoteContainer: verified };\n const existingState = input.state.containersById.get(\n input.remoteContainer.id,\n );\n const remoteState = await runWithSecurityIncidentReporting(\n input.state.runtime.util.reportSecurityIncident,\n {\n objectId: verified.id,\n objectKind: \"container\",\n operation: \"container.binding.persist\",\n organizationId: verified.organizationId,\n },\n async () =>\n (await rebindReHomedContainer({\n existingState,\n heldBinding,\n isCurrent: input.isCurrent,\n state: input.state,\n verified,\n }))\n ? persistVerifiedRemoteContainer({\n ...input,\n existingState,\n expectedPlacementCheckpoint,\n })\n : null,\n );\n if (!remoteState) {\n return null;\n }\n await reconcileLocalOnlySystemContainers({\n childIdsByParentId: input.childIdsByParentId,\n isCurrent: input.isCurrent,\n requestDocumentPriming: input.host.requestDocumentPriming,\n remoteSystemState: remoteState,\n state: input.state,\n });\n return remoteState;\n}\n\n/**\n * Upsert one listed folder, isolating a rejected proof or binding. The refusal\n * was already reported; returning no state leaves the item unapplied without\n * blocking independent folders.\n */\nexport async function upsertIsolatedRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n try {\n return await upsertRemoteContainerState(input);\n } catch (error) {\n if (!isKeyingVerificationError(error)) throw error;\n return null;\n }\n}\n\nfunction persistVerifiedRemoteContainer(\n input: UpsertRemoteContainerStateInput & {\n existingState: ContainerState | undefined;\n expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n },\n): Promise<ContainerState | null> {\n const { existingState, expectedPlacementCheckpoint } = input;\n return existingState\n ? updateExistingRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n containerIdsWithPendingStructuralIntents:\n input.containerIdsWithPendingStructuralIntents,\n existingState,\n host: input.host,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n })\n : insertRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n host: input.host,\n expectedHydrationTombstone: input.expectedHydrationTombstone ?? null,\n expectedPlacementCheckpoint,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n });\n}\n"]}
1
+ {"version":3,"file":"remoteContainerState.js","sourceRoot":"","sources":["remoteContainerState.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccessManifestCheckpoint } from \"@tearleads/crypto\";\nimport {\n heldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../data/containers/containerBinding\";\nimport {\n isKeyingVerificationError,\n runWithSecurityIncidentReporting,\n} from \"../../data/keyingProjectionVerification/error\";\nimport { isProjectionVerificationCancelledError } from \"../../data/keyingProjectionVerification/types\";\nimport type { ContainerHydrationTombstone } from \"./containerPersistence\";\nimport { installContainerMetadataRecord } from \"./metadataPersistence\";\nimport { projectionGeneration } from \"./projectionGeneration\";\nimport {\n moveIndexedContainerChild,\n removeIndexedContainerChild,\n} from \"./remoteHydration/childIndex\";\nimport type { PrefetchedDestinationProjection } from \"./remoteHydration/destinationPrefetch\";\nimport { rebindReHomedContainer } from \"./remoteHydration/heldContainerRebind\";\nimport { insertRemoteContainerState } from \"./remoteHydration/insertRemoteContainer\";\nimport {\n reconcileLocalOnlyRootContainers,\n reconcileLocalOnlySystemContainers,\n} from \"./remoteHydration/reconciliation\";\nimport {\n applyRemoteContainerTimestamps,\n remoteContainerHydrationSaveOptions,\n resolveRemoteContainerHydrationLocalUpdatedAt,\n} from \"./remoteHydration/remoteContainerTimestamps\";\nimport type {\n ContainerChildIndex,\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationHost,\n RemoteContainerHydrationState,\n} from \"./remoteHydration/types\";\nimport { verifyRemoteContainerDestination } from \"./remoteHydration/verifiedDestination\";\n\n// Container ids (restricted to the inbound page) that carry an unsynced local\n// create or move intent. Such a container's parent and local-edit timestamp are\n// owned by its structural-intent lane until that lane reconciles, so inbound\n// hydration must not revert parentId to the server value nor collapse\n// localUpdatedAt — doing so silently undoes a queued move and falsely reads\n// \"synced\". Move intents are read via listUnsyncedMoveIntents so a blocked\n// move — one whose destination parent has not synced yet, the common boot-time\n// case — is protected too. Pending *metadata*\n// updates are handled separately (listRemoteContainerIdsWithPendingMetadataUpdates);\n// these live in dedicated create/move intent tables that that query does not cover.\nexport async function listRemoteContainerIdsWithPendingStructuralIntents(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n if (input.remoteContainers.length === 0) {\n return new Set();\n }\n const remoteContainerIds = new Set(\n input.remoteContainers.map((remoteContainer) => remoteContainer.id),\n );\n\n const execSql = input.state.runtime.infra.execSql;\n const [pendingCreateIntents, unsyncedMoveIntents] = await Promise.all([\n input.state.persistence.listPendingCreateIntents(execSql),\n input.state.persistence.listUnsyncedMoveIntents(execSql),\n ]);\n const containerIdsWithPendingStructuralIntents = new Set<string>();\n for (const intent of pendingCreateIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n for (const intent of unsyncedMoveIntents) {\n if (remoteContainerIds.has(intent.containerId)) {\n containerIdsWithPendingStructuralIntents.add(intent.containerId);\n }\n }\n return containerIdsWithPendingStructuralIntents;\n}\n\nexport async function listRemoteContainerIdsWithPendingMetadataUpdates(input: {\n remoteContainers: ReadonlyArray<RemoteContainer>;\n state: RemoteContainerHydrationState;\n}): Promise<Set<string>> {\n const containerIds = input.remoteContainers.flatMap((remoteContainer) => {\n const previousLocalUpdatedAt = input.state.containersById.get(\n remoteContainer.id,\n )?.container.localUpdatedAt;\n\n return previousLocalUpdatedAt &&\n previousLocalUpdatedAt.localeCompare(remoteContainer.updatedAt) > 0\n ? [remoteContainer.id]\n : [];\n });\n if (containerIds.length === 0) {\n return new Set();\n }\n\n const execSql = input.state.runtime.infra.execSql;\n return new Set(\n await input.state.persistence.listContainerIdsWithPendingUpdates(\n execSql,\n containerIds,\n ),\n );\n}\n\nfunction removeMissingHydratedContainer(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n existingState: ContainerState;\n host: RemoteContainerHydrationHost;\n previousParentId: string | null;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): void {\n const { existingState, remoteContainer, state } = input;\n if (state.containersById.get(remoteContainer.id) !== existingState) {\n return;\n }\n\n state.containersById.delete(remoteContainer.id);\n if (input.childIdsByParentId) {\n removeIndexedContainerChild(\n input.childIdsByParentId,\n remoteContainer.id,\n input.previousParentId,\n );\n input.childIdsByParentId.delete(remoteContainer.id);\n }\n input.host.updateSnapshot();\n}\n\nfunction createUpdatedRemoteContainerState(\n existingState: ContainerState,\n remoteContainer: RemoteContainer,\n): ContainerState {\n return {\n ...existingState,\n container: applyRemoteContainerTimestamps(\n existingState.container,\n remoteContainer,\n ),\n containerWriterProjection: null,\n metadataReferencedPrincipals: remoteContainer.metadataReferencedPrincipals,\n };\n}\n\nfunction installUpdatedRemoteContainerState(\n existingState: ContainerState,\n nextState: ContainerState,\n host: RemoteContainerHydrationHost,\n): void {\n const wasLocalOnly = existingState.container.serverCreatedAt == null;\n existingState.container = nextState.container;\n existingState.containerWriterProjection = nextState.containerWriterProjection;\n existingState.metadataReferencedPrincipals =\n nextState.metadataReferencedPrincipals;\n // The snapshot copied the live generation when it was taken; a hint that\n // landed during the persist leaves the live metadata projection dropped.\n if (projectionGeneration(existingState) === projectionGeneration(nextState))\n existingState.metadataWriterProjection = nextState.metadataWriterProjection;\n installContainerMetadataRecord(existingState, nextState.record);\n // A document pass may have deferred while this root was awaiting proof.\n // The first durable remote acknowledgement makes its pending creates runnable.\n if (wasLocalOnly && existingState.container.serverCreatedAt != null)\n host.requestDocumentPriming?.();\n}\n\nasync function updateExistingRemoteContainerState(input: {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n isCurrent?: (() => boolean) | undefined;\n existingState: ContainerState;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}): Promise<ContainerState | null> {\n const { childIdsByParentId, existingState, host, remoteContainer, state } =\n input;\n const previousParentId = existingState.container.parentId;\n const previousLocalUpdatedAt = existingState.container.localUpdatedAt;\n // A queued, not-yet-synced local move/create owns this container's parent\n // until its intent lane reconciles. Omit the remote parent when the page scan\n // saw one; persistence also rechecks the intent transactionally so a move\n // created after that scan wins. Both paths preserve the durable local clock.\n const hasPendingStructuralIntent =\n input.containerIdsWithPendingStructuralIntents.has(remoteContainer.id);\n const nextParentId = hasPendingStructuralIntent\n ? undefined\n : remoteContainer.parentId;\n const localUpdatedAt = resolveRemoteContainerHydrationLocalUpdatedAt({\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n hasPendingStructuralIntent,\n previousLocalUpdatedAt,\n remoteContainer,\n });\n const nextState = createUpdatedRemoteContainerState(\n existingState,\n remoteContainer,\n );\n const persistenceResult = await host.persistContainerState(\n nextState,\n {\n accessEpoch: remoteContainer.metadataAccessEpoch,\n accessStateHash: remoteContainer.metadataAccessStateHash,\n documentId: remoteContainer.metadataDocumentId,\n effectiveAccessLevel: remoteContainer.effectiveAccessLevel,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n systemSlot: remoteContainer.systemSlot ?? null,\n organizationId: remoteContainer.organizationId,\n ...(nextParentId !== undefined ? { parentId: nextParentId } : {}),\n },\n false,\n remoteContainerHydrationSaveOptions({\n localUpdatedAt,\n remoteContainer,\n }),\n {\n preserveDurableStructureWhenPending: true,\n },\n );\n if (persistenceResult.status === \"missing\") {\n // Hydration persists a detached candidate so an in-flight response cannot\n // mutate mapped state before its guards settle. Retire the exact state this\n // hydration read because store-level reference cleanup cannot see the clone.\n removeMissingHydratedContainer({\n childIdsByParentId,\n existingState,\n host,\n previousParentId,\n remoteContainer,\n state,\n });\n return null;\n }\n if (persistenceResult.status !== \"persisted\") return null;\n const { record: nextRecord } = persistenceResult;\n installContainerMetadataRecord(nextState, nextRecord);\n if (input.isCurrent?.() === false) {\n return existingState;\n }\n nextState.container = {\n ...nextState.container,\n metadataDocumentId: remoteContainer.metadataDocumentId,\n organizationId: remoteContainer.organizationId,\n parentId: nextState.container.parentId,\n };\n\n installUpdatedRemoteContainerState(existingState, nextState, host);\n moveIndexedContainerChild(\n childIdsByParentId,\n remoteContainer.id,\n previousParentId,\n existingState.container.parentId,\n );\n await reconcileLocalOnlyRootContainers({\n childIdsByParentId,\n isCurrent: input.isCurrent,\n remoteRootState: existingState,\n requestDocumentPriming: host.requestDocumentPriming,\n state,\n });\n return existingState;\n}\n\ninterface UpsertRemoteContainerStateInput {\n childIdsByParentId?: ContainerChildIndex | undefined;\n containerIdsWithPendingMetadataUpdates: ReadonlySet<string>;\n containerIdsWithPendingStructuralIntents: ReadonlySet<string>;\n host: RemoteContainerHydrationHost;\n expectedHydrationTombstone?: ContainerHydrationTombstone | null | undefined;\n isCurrent?: (() => boolean) | undefined;\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n}\n\nexport async function upsertRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n let expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n const heldState = input.state.containersById.get(input.remoteContainer.id);\n const heldBinding = heldState\n ? heldContainerBinding(heldState)\n : await input.state.persistence.loadHeldContainerBinding(\n input.state.runtime.infra.execSql,\n input.remoteContainer.id,\n );\n const listed = input.remoteContainer;\n // A folder re-homed away from the listed organization never returns there,\n // whatever binding (possibly none, after a reset) the device holds now.\n const supersededListing =\n !listingRepeatsHeldOrdinaryBinding(heldBinding, listed) &&\n (await input.state.persistence.isSupersededContainerBinding(\n input.state.runtime.infra.execSql,\n { containerId: listed.id, organizationId: listed.organizationId },\n ));\n if (input.isCurrent?.() === false) return null;\n const verified = await verifyRemoteContainerDestination({\n ...input,\n heldBinding,\n supersededListing,\n refresh: !!input.expectedHydrationTombstone,\n onVerifiedCheckpoint: (checkpoint) => {\n expectedPlacementCheckpoint = checkpoint;\n },\n });\n if (!verified || input.isCurrent?.() === false) return null;\n input = { ...input, remoteContainer: verified };\n const existingState = input.state.containersById.get(\n input.remoteContainer.id,\n );\n const remoteState = await runWithSecurityIncidentReporting(\n input.state.runtime.util.reportSecurityIncident,\n {\n objectId: verified.id,\n objectKind: \"container\",\n operation: \"container.binding.persist\",\n organizationId: verified.organizationId,\n },\n async () =>\n (await rebindReHomedContainer({\n existingState,\n heldBinding,\n isCurrent: input.isCurrent,\n state: input.state,\n verified,\n }))\n ? persistVerifiedRemoteContainer({\n ...input,\n existingState,\n expectedPlacementCheckpoint,\n })\n : null,\n );\n if (!remoteState) {\n return null;\n }\n await reconcileLocalOnlySystemContainers({\n childIdsByParentId: input.childIdsByParentId,\n isCurrent: input.isCurrent,\n requestDocumentPriming: input.host.requestDocumentPriming,\n remoteSystemState: remoteState,\n state: input.state,\n });\n return remoteState;\n}\n\n/**\n * Upsert one listed folder, isolating a rejected proof or binding. The refusal\n * was already reported; returning no state leaves the item unapplied without\n * blocking independent folders.\n */\nexport async function upsertIsolatedRemoteContainerState(\n input: UpsertRemoteContainerStateInput,\n): Promise<ContainerState | null> {\n try {\n return await upsertRemoteContainerState(input);\n } catch (error) {\n if (\n !isKeyingVerificationError(error) &&\n !isProjectionVerificationCancelledError(error)\n )\n throw error;\n return null;\n }\n}\n\nfunction persistVerifiedRemoteContainer(\n input: UpsertRemoteContainerStateInput & {\n existingState: ContainerState | undefined;\n expectedPlacementCheckpoint: AccessManifestCheckpoint | undefined;\n },\n): Promise<ContainerState | null> {\n const { existingState, expectedPlacementCheckpoint } = input;\n return existingState\n ? updateExistingRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n containerIdsWithPendingMetadataUpdates:\n input.containerIdsWithPendingMetadataUpdates,\n containerIdsWithPendingStructuralIntents:\n input.containerIdsWithPendingStructuralIntents,\n existingState,\n host: input.host,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n })\n : insertRemoteContainerState({\n childIdsByParentId: input.childIdsByParentId,\n host: input.host,\n expectedHydrationTombstone: input.expectedHydrationTombstone ?? null,\n expectedPlacementCheckpoint,\n isCurrent: input.isCurrent,\n remoteContainer: input.remoteContainer,\n state: input.state,\n });\n}\n"]}
@@ -6,6 +6,7 @@ import { verifyContainerDestinationProjection } from "../../../data/keyingProjec
6
6
  import { verifyContainerWriterProjection } from "../../../data/keyingProjectionVerification/containerProjectionVerification.js";
7
7
  import { isKeyingVerificationError, reportKeyingVerificationErrorInCauseChain, runWithSecurityIncidentReporting, } from "../../../data/keyingProjectionVerification/error.js";
8
8
  import { createGroupMetadataContainerVerifier } from "../../organizations/groupMetadataContainerAuthority.js";
9
+ import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
9
10
  import { cachedDestinationRole, rememberDestinationRole, } from "./destinationRoleCache.js";
10
11
  import { resolveWithMetadataRootReload } from "./destinationRootReload.js";
11
12
  import { assertPermittedDestinationBinding } from "./replacementBinding.js";
@@ -97,6 +98,8 @@ async function verifyDestinationRole(input) {
97
98
  execSql: runtime.infra.execSql,
98
99
  projection,
99
100
  resolveUserKey: runtime.resolveTrustedUserIdentity,
101
+ stillCurrent: isCurrent,
102
+ warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(runtime),
100
103
  };
101
104
  const { path, verifiedByHash } = await verifyContainerDestinationProjection(verificationInput);
102
105
  if (isCurrent?.() === false)
@@ -1 +1 @@
1
- {"version":3,"file":"verifiedDestination.js","sourceRoot":"","sources":["verifiedDestination.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport { deriveOrganizationMetadataContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport {\n type HeldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../../data/containers/containerBinding\";\nimport { verifiedContainerCreateManifest } from \"../../../data/keyingProjectionVerification/containerCreateManifest\";\nimport { verifyContainerDestinationProjection } from \"../../../data/keyingProjectionVerification/containerDestinationVerification\";\nimport { verifyContainerWriterProjection } from \"../../../data/keyingProjectionVerification/containerProjectionVerification\";\nimport {\n isKeyingVerificationError,\n reportKeyingVerificationErrorInCauseChain,\n runWithSecurityIncidentReporting,\n} from \"../../../data/keyingProjectionVerification/error\";\nimport { createGroupMetadataContainerVerifier } from \"../../organizations/groupMetadataContainerAuthority\";\nimport type { PrefetchedDestinationProjection } from \"./destinationPrefetch\";\nimport {\n cachedDestinationRole,\n type DestinationRole,\n rememberDestinationRole,\n} from \"./destinationRoleCache\";\nimport { resolveWithMetadataRootReload } from \"./destinationRootReload\";\nimport { assertPermittedDestinationBinding } from \"./replacementBinding\";\nimport type {\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationState,\n} from \"./types\";\n\n/** The identity a role is verified and cached under. */\ntype DestinationIdentity = Pick<RemoteContainer, \"id\" | \"organizationId\">;\n\nasync function destinationRoleFromPath(input: {\n listed: DestinationIdentity;\n path: readonly VerifiedContainerAccessManifest[];\n verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): Promise<{ role: DestinationRole; parentId: string | null }> {\n const { listed, path } = input;\n const head = path.at(-1);\n if (\n !head ||\n head.state.containerId !== listed.id ||\n head.state.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination manifest has the wrong identity\",\n );\n }\n const metadataSlot = await deriveOrganizationMetadataContainerSystemSlot({\n organizationId: listed.organizationId,\n });\n if (\n head.state.systemSlot !== null &&\n path.length !== (head.state.systemSlot === metadataSlot ? 1 : 2)\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"system destination has the wrong signed topology\",\n );\n }\n // The head may be a later grant signed by any admin; only the epoch-1\n // create names the creator, and roots are always created by the org owner.\n const created = verifiedContainerCreateManifest({\n head,\n label: \"Container destination\",\n verifiedByHash: input.verifiedByHash,\n });\n const root = path[0];\n if (!root) throw new Error(\"Destination root is unavailable\");\n const rootCreated = verifiedContainerCreateManifest({\n head: root,\n label: \"Destination root\",\n verifiedByHash: input.verifiedByHash,\n });\n return {\n parentId: head.state.parentContainerId,\n role: {\n createSignerUserId: created.event.event.signerUserId,\n rootContainerId: rootCreated.state.containerId,\n rootCreateManifestHash: rootCreated.manifestHash,\n rootMetadataDocumentId: rootCreated.state.metadataDocumentId,\n metadataDocumentId: head.state.metadataDocumentId,\n ...(head.state.parentContainerId === null ||\n head.state.systemSlot !== null\n ? { parentId: head.state.parentContainerId }\n : {}),\n systemSlot: head.state.systemSlot,\n },\n };\n}\n\n/**\n * The session's root id arrives in an unsigned login response, so the root it\n * names must prove it belongs to this user: every acknowledged organization was\n * created by the session user, whose device signed the root's `container.create`.\n * A verified root created by anyone else is a substitution, never the merge\n * target for pre-login local content, whatever grants it carries. The check\n * runs on cache reuse too, since the cache is not scoped to the session user.\n */\nfunction assertRootCreatedBySessionUser(\n role: DestinationRole,\n runtime: RemoteContainerHydrationState[\"runtime\"],\n): void {\n if (role.systemSlot !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"acknowledged session root cannot be a system container\",\n );\n }\n if (role.createSignerUserId !== runtime.auth.userId) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"acknowledged session root was not created by the session user\",\n );\n }\n}\n\nfunction assertAcknowledgedRootSigner(input: {\n listed: DestinationIdentity;\n role: DestinationRole;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): void {\n const { listed, role, runtime } = input;\n if (role.parentId !== null || listed.id !== runtime.auth.rootContainerId) {\n return;\n }\n assertRootCreatedBySessionUser(role, runtime);\n}\n\n/**\n * Authenticate destination roles before admitting a binding or advancing any\n * placement pin. Shared rehomes additionally require signed replacement evidence.\n */\nasync function verifyDestinationRole(input: {\n heldBinding: HeldContainerBinding | null;\n prefetched: PrefetchedDestinationProjection | undefined;\n verifyCurrentPlacement: boolean;\n onVerifiedCheckpoint:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n isCurrent?: (() => boolean) | undefined;\n listed: DestinationIdentity;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): Promise<{ role: DestinationRole; parentId: string | null } | null> {\n const { isCurrent, listed, runtime } = input;\n const projection = input.prefetched\n ? input.prefetched.projection\n : await runtime.apiClient.getContainerWriterProjection(listed.id);\n if (!projection || isCurrent?.() === false) return null;\n if (\n projection.containerId !== listed.id ||\n projection.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination projection has the wrong identity\",\n );\n }\n const verificationInput = {\n execSql: runtime.infra.execSql,\n projection,\n resolveUserKey: runtime.resolveTrustedUserIdentity,\n };\n const { path, verifiedByHash } =\n await verifyContainerDestinationProjection(verificationInput);\n if (isCurrent?.() === false) return null;\n const destination = await destinationRoleFromPath({\n listed,\n path,\n verifiedByHash,\n });\n const { role } = destination;\n // Refuse a rebinding before group checks or placement pins run for it.\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (role.parentId === null && role.systemSlot !== null) {\n const head = path.at(-1);\n if (!head) throw new Error(\"Metadata root manifest is unavailable\");\n await createGroupMetadataContainerVerifier({\n apiClient: runtime.apiClient,\n execSql: runtime.infra.execSql,\n organizationId: listed.organizationId,\n reportSecurityIncident: runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n stillCurrent: isCurrent ?? (() => true),\n })(head.state);\n }\n if (isCurrent?.() === false) return null;\n if (input.verifyCurrentPlacement) {\n // Check the immutable role before allowing current placement to advance pins.\n assertAcknowledgedRootSigner({ listed, role, runtime });\n const currentPath = await verifyContainerWriterProjection({\n ...verificationInput,\n stillCurrent: isCurrent,\n });\n const currentHead = currentPath.at(-1);\n if (!currentHead)\n throw new Error(\"Recovery placement manifest is unavailable\");\n input.onVerifiedCheckpoint?.(currentHead.checkpoint);\n }\n if (isCurrent?.() === false) return null;\n return destination;\n}\n\ntype VerifyRemoteContainerDestinationInput = {\n heldBinding: HeldContainerBinding | null;\n /** The held folder was re-homed away from the listed organization. */\n supersededListing?: boolean | undefined;\n /** Fetched ahead by page hydration; ignored when placement is refreshed. */\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n refresh?: boolean;\n onVerifiedCheckpoint?:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n isCurrent?: (() => boolean) | undefined;\n};\n\n/** A cached immutable role, or a freshly verified one with its signed parent. */\nasync function resolveDestinationRole(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<{\n freshlyVerified: boolean;\n parentId: string | null | undefined;\n role: DestinationRole;\n} | null> {\n const { remoteContainer: listed, isCurrent } = input;\n const runtime = input.state.runtime;\n const cached = input.refresh\n ? undefined\n : cachedDestinationRole(runtime.infra.execSql, listed);\n // Ordinary parent edges are not immutable. A refresh authenticates current\n // placement; a forged root hint must also be corrected from a signed path.\n if (cached && !(cached.parentId === undefined && listed.parentId === null)) {\n return { freshlyVerified: false, parentId: cached.parentId, role: cached };\n }\n const verified = await verifyDestinationRole({\n heldBinding: input.heldBinding,\n prefetched: input.refresh ? undefined : input.prefetchedProjection,\n isCurrent,\n listed,\n runtime,\n verifyCurrentPlacement: input.refresh === true,\n onVerifiedCheckpoint: input.onVerifiedCheckpoint,\n });\n if (!verified) return null;\n return {\n freshlyVerified: true,\n parentId:\n input.refresh || listed.parentId === null\n ? verified.parentId\n : verified.role.parentId,\n role: verified.role,\n };\n}\n\n/**\n * Listing hints never establish a metadata target or a system/root role, and a\n * held folder keeps its organization and metadata target unless its own user\n * re-created it or its pinned founder authorized a verified replacement.\n * A conflicting proof is refused before placement pins\n * advance or its role is cached.\n */\nexport async function verifyRemoteContainerDestination(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<RemoteContainer | null> {\n const { remoteContainer: listed, state, isCurrent } = input;\n const runtime = state.runtime;\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: listed.id,\n objectKind: \"container\",\n operation: \"container.destination.verify\",\n organizationId: listed.organizationId,\n },\n async () => {\n if (input.supersededListing) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container was re-homed away from the listed organization\",\n );\n }\n // A held ordinary binding was verified (or signed by this device) when\n // it was stored; a listing that repeats it needs no second proof.\n if (\n !input.refresh &&\n listingRepeatsHeldOrdinaryBinding(input.heldBinding, listed)\n ) {\n return { ...listed, systemSlot: null };\n }\n if (input.refresh)\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n // A metadata root read before a reserved-group commit is reloaded once.\n const resolved = await resolveWithMetadataRootReload(\n input,\n resolveDestinationRole,\n () => runtime.apiClient.evictContainerWriterProjection(listed.id),\n ).catch((error: unknown) => {\n // Never re-serve a cached projection that failed verification.\n if (isKeyingVerificationError(error))\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n throw error;\n });\n if (!resolved || isCurrent?.() === false) return null;\n const { role, parentId } = resolved;\n // Fresh verification checked this binding before any placement pins.\n // A cached role still needs the held binding and replacement proof checked.\n if (!resolved.freshlyVerified)\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (resolved.freshlyVerified)\n rememberDestinationRole(runtime.infra.execSql, listed, role);\n assertAcknowledgedRootSigner({ listed, role, runtime });\n return {\n ...listed,\n metadataDocumentId: role.metadataDocumentId,\n parentId: parentId === undefined ? listed.parentId : parentId,\n systemSlot: role.systemSlot,\n };\n },\n );\n}\n\n/** The root the unsigned login answer named, in the expected organization. */\nexport function isSessionRootState(\n remoteRootState: ContainerState,\n state: RemoteContainerHydrationState,\n): boolean {\n const { container } = remoteRootState;\n const { auth } = state.runtime;\n return (\n container.parentId === null &&\n !container.systemSlot &&\n container.id === auth.rootContainerId &&\n container.organizationId === auth.organizationId\n );\n}\n\n/**\n * Whether the session root may absorb the pre-login local roots. The unsigned\n * login answer only names the root; the merge target must also be the verified\n * root whose epoch-1 `container.create` the session user signed. A row persisted\n * earlier as an ordinary shared container (another user's root this device once\n * hydrated) never passed that check for this session, so the creator is checked\n * here, at the reconciliation boundary itself, before any local content is\n * re-parented. The role comes only from the cache remote hydration fills when\n * it verifies the destination: this gate never fetches, so a local refresh stays\n * independent of the network. Without a cached role the merge is left pending\n * (no incident) until hydration verifies the root and reconciles from the\n * cache. A different creator is a `signer_mismatch` incident and never a merge;\n * the refusal is the \"no merge\" outcome, so the refresh that carried it\n * completes with the local content left in place.\n */\nexport async function isVerifiedLocalRootReconciliationTarget(input: {\n remoteRootState: ContainerState;\n state: RemoteContainerHydrationState;\n}): Promise<boolean> {\n const { remoteRootState, state } = input;\n const { container } = remoteRootState;\n const runtime = state.runtime;\n if (!isSessionRootState(remoteRootState, state)) return false;\n const role = cachedDestinationRole(runtime.infra.execSql, container);\n if (!role) return false;\n try {\n if (role.parentId !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"session root reconciliation target is not a verified root\",\n );\n }\n assertRootCreatedBySessionUser(role, runtime);\n return true;\n } catch (error) {\n const reported = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: container.id,\n objectKind: \"container\",\n operation: \"container.root.reconcile\",\n organizationId: container.organizationId,\n },\n );\n if (!reported) throw error;\n return false;\n }\n}\n"]}
1
+ {"version":3,"file":"verifiedDestination.js","sourceRoot":"","sources":["verifiedDestination.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type VerifiedContainerAccessManifest,\n} from \"@tearleads/crypto\";\nimport { deriveOrganizationMetadataContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport {\n type HeldContainerBinding,\n listingRepeatsHeldOrdinaryBinding,\n} from \"../../../data/containers/containerBinding\";\nimport { verifiedContainerCreateManifest } from \"../../../data/keyingProjectionVerification/containerCreateManifest\";\nimport { verifyContainerDestinationProjection } from \"../../../data/keyingProjectionVerification/containerDestinationVerification\";\nimport { verifyContainerWriterProjection } from \"../../../data/keyingProjectionVerification/containerProjectionVerification\";\nimport {\n isKeyingVerificationError,\n reportKeyingVerificationErrorInCauseChain,\n runWithSecurityIncidentReporting,\n} from \"../../../data/keyingProjectionVerification/error\";\nimport { createGroupMetadataContainerVerifier } from \"../../organizations/groupMetadataContainerAuthority\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { PrefetchedDestinationProjection } from \"./destinationPrefetch\";\nimport {\n cachedDestinationRole,\n type DestinationRole,\n rememberDestinationRole,\n} from \"./destinationRoleCache\";\nimport { resolveWithMetadataRootReload } from \"./destinationRootReload\";\nimport { assertPermittedDestinationBinding } from \"./replacementBinding\";\nimport type {\n ContainerState,\n RemoteContainer,\n RemoteContainerHydrationState,\n} from \"./types\";\n\n/** The identity a role is verified and cached under. */\ntype DestinationIdentity = Pick<RemoteContainer, \"id\" | \"organizationId\">;\n\nasync function destinationRoleFromPath(input: {\n listed: DestinationIdentity;\n path: readonly VerifiedContainerAccessManifest[];\n verifiedByHash: ReadonlyMap<string, VerifiedContainerAccessManifest>;\n}): Promise<{ role: DestinationRole; parentId: string | null }> {\n const { listed, path } = input;\n const head = path.at(-1);\n if (\n !head ||\n head.state.containerId !== listed.id ||\n head.state.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination manifest has the wrong identity\",\n );\n }\n const metadataSlot = await deriveOrganizationMetadataContainerSystemSlot({\n organizationId: listed.organizationId,\n });\n if (\n head.state.systemSlot !== null &&\n path.length !== (head.state.systemSlot === metadataSlot ? 1 : 2)\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"system destination has the wrong signed topology\",\n );\n }\n // The head may be a later grant signed by any admin; only the epoch-1\n // create names the creator, and roots are always created by the org owner.\n const created = verifiedContainerCreateManifest({\n head,\n label: \"Container destination\",\n verifiedByHash: input.verifiedByHash,\n });\n const root = path[0];\n if (!root) throw new Error(\"Destination root is unavailable\");\n const rootCreated = verifiedContainerCreateManifest({\n head: root,\n label: \"Destination root\",\n verifiedByHash: input.verifiedByHash,\n });\n return {\n parentId: head.state.parentContainerId,\n role: {\n createSignerUserId: created.event.event.signerUserId,\n rootContainerId: rootCreated.state.containerId,\n rootCreateManifestHash: rootCreated.manifestHash,\n rootMetadataDocumentId: rootCreated.state.metadataDocumentId,\n metadataDocumentId: head.state.metadataDocumentId,\n ...(head.state.parentContainerId === null ||\n head.state.systemSlot !== null\n ? { parentId: head.state.parentContainerId }\n : {}),\n systemSlot: head.state.systemSlot,\n },\n };\n}\n\n/**\n * The session's root id arrives in an unsigned login response, so the root it\n * names must prove it belongs to this user: every acknowledged organization was\n * created by the session user, whose device signed the root's `container.create`.\n * A verified root created by anyone else is a substitution, never the merge\n * target for pre-login local content, whatever grants it carries. The check\n * runs on cache reuse too, since the cache is not scoped to the session user.\n */\nfunction assertRootCreatedBySessionUser(\n role: DestinationRole,\n runtime: RemoteContainerHydrationState[\"runtime\"],\n): void {\n if (role.systemSlot !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"acknowledged session root cannot be a system container\",\n );\n }\n if (role.createSignerUserId !== runtime.auth.userId) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"acknowledged session root was not created by the session user\",\n );\n }\n}\n\nfunction assertAcknowledgedRootSigner(input: {\n listed: DestinationIdentity;\n role: DestinationRole;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): void {\n const { listed, role, runtime } = input;\n if (role.parentId !== null || listed.id !== runtime.auth.rootContainerId) {\n return;\n }\n assertRootCreatedBySessionUser(role, runtime);\n}\n\n/**\n * Authenticate destination roles before admitting a binding or advancing any\n * placement pin. Shared rehomes additionally require signed replacement evidence.\n */\nasync function verifyDestinationRole(input: {\n heldBinding: HeldContainerBinding | null;\n prefetched: PrefetchedDestinationProjection | undefined;\n verifyCurrentPlacement: boolean;\n onVerifiedCheckpoint:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n isCurrent?: (() => boolean) | undefined;\n listed: DestinationIdentity;\n runtime: RemoteContainerHydrationState[\"runtime\"];\n}): Promise<{ role: DestinationRole; parentId: string | null } | null> {\n const { isCurrent, listed, runtime } = input;\n const projection = input.prefetched\n ? input.prefetched.projection\n : await runtime.apiClient.getContainerWriterProjection(listed.id);\n if (!projection || isCurrent?.() === false) return null;\n if (\n projection.containerId !== listed.id ||\n projection.organizationId !== listed.organizationId\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container destination projection has the wrong identity\",\n );\n }\n const verificationInput = {\n execSql: runtime.infra.execSql,\n projection,\n resolveUserKey: runtime.resolveTrustedUserIdentity,\n stillCurrent: isCurrent,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n };\n const { path, verifiedByHash } =\n await verifyContainerDestinationProjection(verificationInput);\n if (isCurrent?.() === false) return null;\n const destination = await destinationRoleFromPath({\n listed,\n path,\n verifiedByHash,\n });\n const { role } = destination;\n // Refuse a rebinding before group checks or placement pins run for it.\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (role.parentId === null && role.systemSlot !== null) {\n const head = path.at(-1);\n if (!head) throw new Error(\"Metadata root manifest is unavailable\");\n await createGroupMetadataContainerVerifier({\n apiClient: runtime.apiClient,\n execSql: runtime.infra.execSql,\n organizationId: listed.organizationId,\n reportSecurityIncident: runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n stillCurrent: isCurrent ?? (() => true),\n })(head.state);\n }\n if (isCurrent?.() === false) return null;\n if (input.verifyCurrentPlacement) {\n // Check the immutable role before allowing current placement to advance pins.\n assertAcknowledgedRootSigner({ listed, role, runtime });\n const currentPath = await verifyContainerWriterProjection({\n ...verificationInput,\n stillCurrent: isCurrent,\n });\n const currentHead = currentPath.at(-1);\n if (!currentHead)\n throw new Error(\"Recovery placement manifest is unavailable\");\n input.onVerifiedCheckpoint?.(currentHead.checkpoint);\n }\n if (isCurrent?.() === false) return null;\n return destination;\n}\n\ntype VerifyRemoteContainerDestinationInput = {\n heldBinding: HeldContainerBinding | null;\n /** The held folder was re-homed away from the listed organization. */\n supersededListing?: boolean | undefined;\n /** Fetched ahead by page hydration; ignored when placement is refreshed. */\n prefetchedProjection?: PrefetchedDestinationProjection | undefined;\n refresh?: boolean;\n onVerifiedCheckpoint?:\n | ((checkpoint: AccessManifestCheckpoint) => void)\n | undefined;\n remoteContainer: RemoteContainer;\n state: RemoteContainerHydrationState;\n isCurrent?: (() => boolean) | undefined;\n};\n\n/** A cached immutable role, or a freshly verified one with its signed parent. */\nasync function resolveDestinationRole(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<{\n freshlyVerified: boolean;\n parentId: string | null | undefined;\n role: DestinationRole;\n} | null> {\n const { remoteContainer: listed, isCurrent } = input;\n const runtime = input.state.runtime;\n const cached = input.refresh\n ? undefined\n : cachedDestinationRole(runtime.infra.execSql, listed);\n // Ordinary parent edges are not immutable. A refresh authenticates current\n // placement; a forged root hint must also be corrected from a signed path.\n if (cached && !(cached.parentId === undefined && listed.parentId === null)) {\n return { freshlyVerified: false, parentId: cached.parentId, role: cached };\n }\n const verified = await verifyDestinationRole({\n heldBinding: input.heldBinding,\n prefetched: input.refresh ? undefined : input.prefetchedProjection,\n isCurrent,\n listed,\n runtime,\n verifyCurrentPlacement: input.refresh === true,\n onVerifiedCheckpoint: input.onVerifiedCheckpoint,\n });\n if (!verified) return null;\n return {\n freshlyVerified: true,\n parentId:\n input.refresh || listed.parentId === null\n ? verified.parentId\n : verified.role.parentId,\n role: verified.role,\n };\n}\n\n/**\n * Listing hints never establish a metadata target or a system/root role, and a\n * held folder keeps its organization and metadata target unless its own user\n * re-created it or its pinned founder authorized a verified replacement.\n * A conflicting proof is refused before placement pins\n * advance or its role is cached.\n */\nexport async function verifyRemoteContainerDestination(\n input: VerifyRemoteContainerDestinationInput,\n): Promise<RemoteContainer | null> {\n const { remoteContainer: listed, state, isCurrent } = input;\n const runtime = state.runtime;\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: listed.id,\n objectKind: \"container\",\n operation: \"container.destination.verify\",\n organizationId: listed.organizationId,\n },\n async () => {\n if (input.supersededListing) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"container was re-homed away from the listed organization\",\n );\n }\n // A held ordinary binding was verified (or signed by this device) when\n // it was stored; a listing that repeats it needs no second proof.\n if (\n !input.refresh &&\n listingRepeatsHeldOrdinaryBinding(input.heldBinding, listed)\n ) {\n return { ...listed, systemSlot: null };\n }\n if (input.refresh)\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n // A metadata root read before a reserved-group commit is reloaded once.\n const resolved = await resolveWithMetadataRootReload(\n input,\n resolveDestinationRole,\n () => runtime.apiClient.evictContainerWriterProjection(listed.id),\n ).catch((error: unknown) => {\n // Never re-serve a cached projection that failed verification.\n if (isKeyingVerificationError(error))\n runtime.apiClient.evictContainerWriterProjection(listed.id);\n throw error;\n });\n if (!resolved || isCurrent?.() === false) return null;\n const { role, parentId } = resolved;\n // Fresh verification checked this binding before any placement pins.\n // A cached role still needs the held binding and replacement proof checked.\n if (!resolved.freshlyVerified)\n await assertPermittedDestinationBinding({\n stillCurrent: isCurrent,\n heldBinding: input.heldBinding,\n listed,\n role,\n runtime,\n });\n if (isCurrent?.() === false) return null;\n if (resolved.freshlyVerified)\n rememberDestinationRole(runtime.infra.execSql, listed, role);\n assertAcknowledgedRootSigner({ listed, role, runtime });\n return {\n ...listed,\n metadataDocumentId: role.metadataDocumentId,\n parentId: parentId === undefined ? listed.parentId : parentId,\n systemSlot: role.systemSlot,\n };\n },\n );\n}\n\n/** The root the unsigned login answer named, in the expected organization. */\nexport function isSessionRootState(\n remoteRootState: ContainerState,\n state: RemoteContainerHydrationState,\n): boolean {\n const { container } = remoteRootState;\n const { auth } = state.runtime;\n return (\n container.parentId === null &&\n !container.systemSlot &&\n container.id === auth.rootContainerId &&\n container.organizationId === auth.organizationId\n );\n}\n\n/**\n * Whether the session root may absorb the pre-login local roots. The unsigned\n * login answer only names the root; the merge target must also be the verified\n * root whose epoch-1 `container.create` the session user signed. A row persisted\n * earlier as an ordinary shared container (another user's root this device once\n * hydrated) never passed that check for this session, so the creator is checked\n * here, at the reconciliation boundary itself, before any local content is\n * re-parented. The role comes only from the cache remote hydration fills when\n * it verifies the destination: this gate never fetches, so a local refresh stays\n * independent of the network. Without a cached role the merge is left pending\n * (no incident) until hydration verifies the root and reconciles from the\n * cache. A different creator is a `signer_mismatch` incident and never a merge;\n * the refusal is the \"no merge\" outcome, so the refresh that carried it\n * completes with the local content left in place.\n */\nexport async function isVerifiedLocalRootReconciliationTarget(input: {\n remoteRootState: ContainerState;\n state: RemoteContainerHydrationState;\n}): Promise<boolean> {\n const { remoteRootState, state } = input;\n const { container } = remoteRootState;\n const runtime = state.runtime;\n if (!isSessionRootState(remoteRootState, state)) return false;\n const role = cachedDestinationRole(runtime.infra.execSql, container);\n if (!role) return false;\n try {\n if (role.parentId !== null) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"session root reconciliation target is not a verified root\",\n );\n }\n assertRootCreatedBySessionUser(role, runtime);\n return true;\n } catch (error) {\n const reported = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: container.id,\n objectKind: \"container\",\n operation: \"container.root.reconcile\",\n organizationId: container.organizationId,\n },\n );\n if (!reported) throw error;\n return false;\n }\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 { ExecSql } from "../../data/sqlite/sqlSchema.js";
4
5
  import { type TrustedUserIdentityResolver } from "../../data/trustedUserIdentity/index.js";
5
6
  import { createDocumentsWorkflowRuntime, type DocumentsWorkflowRuntime } from "../documents/index.js";
@@ -44,6 +45,8 @@ export interface ContainerContentsWorkflowRuntimeInputGroups {
44
45
  readonly util: ContainerContentsWorkflowRuntimeUtil;
45
46
  }
46
47
  export interface ContainerContentsWorkflowRuntimeInput extends ContainerContentsWorkflowRuntimeInputGroups {
48
+ /** Private host custody, inherited by container and derived document runtimes. */
49
+ readonly withPrincipalHistoryProtection?: PrincipalHistoryProtectionLease | undefined;
47
50
  readonly apiClient: ContainerContentsWorkflowApi;
48
51
  readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;
49
52
  }