@tearleads/client-sdk 0.1.18 → 0.1.20

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 (214) hide show
  1. package/client/organizations/index.js +2 -2
  2. package/client/organizations/index.js.map +1 -1
  3. package/client/organizations/organizationHistory.js +66 -0
  4. package/client/organizations/organizationHistory.js.map +1 -0
  5. package/client/organizations/organizationReadModels.d.ts +1 -1
  6. package/client/organizations/organizationReadModels.js +7 -27
  7. package/client/organizations/organizationReadModels.js.map +1 -1
  8. package/client/organizations/organizationsTypes.d.ts +1 -1
  9. package/client/organizations/organizationsTypes.js.map +1 -1
  10. package/data/containers/shared/types.d.ts +2 -2
  11. package/data/containers/shared/types.js.map +1 -1
  12. package/data/documents/shared/syncSubmitFailure.d.ts +2 -2
  13. package/data/documents/shared/syncSubmitFailure.js.map +1 -1
  14. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js +34 -8
  15. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js.map +1 -1
  16. package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
  17. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js +17 -0
  18. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js.map +1 -0
  19. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js +55 -0
  20. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js.map +1 -0
  21. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js +25 -13
  22. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js.map +1 -1
  23. package/data/keyingProjectionVerification/documentPurgeProofVerification.d.ts +5 -3
  24. package/data/keyingProjectionVerification/documentPurgeProofVerification.js +52 -8
  25. package/data/keyingProjectionVerification/documentPurgeProofVerification.js.map +1 -1
  26. package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
  27. package/data/keyingProjectionVerification/types.d.ts +4 -0
  28. package/data/keyingProjectionVerification/types.js.map +1 -1
  29. package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
  30. package/data/persistence/principalAuthorizationCheckpoints.js +1 -1
  31. package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -1
  32. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +1 -0
  33. package/data/persistence/principalCurrentAcknowledgementPersistence.js +58 -12
  34. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  35. package/data/persistence/principalHistoryEvidencePersistence.d.ts +2 -0
  36. package/data/persistence/principalHistoryEvidencePersistence.js +2 -0
  37. package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -1
  38. package/data/persistence/principalHistoryIncompleteRetention.js +32 -0
  39. package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -0
  40. package/data/persistence/principalHistoryNodeRetention.js +76 -0
  41. package/data/persistence/principalHistoryNodeRetention.js.map +1 -0
  42. package/data/persistence/principalHistoryPrefixPersistence.d.ts +1 -0
  43. package/data/persistence/principalHistoryPrefixPersistence.js +30 -1
  44. package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
  45. package/data/persistence/principalHistoryRootOwnership.js +71 -0
  46. package/data/persistence/principalHistoryRootOwnership.js.map +1 -0
  47. package/data/persistence/principalHistoryStagePersistence.js +45 -0
  48. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  49. package/data/persistence/principalHistoryStageRetention.js +44 -0
  50. package/data/persistence/principalHistoryStageRetention.js.map +1 -0
  51. package/data/persistence/principalHistoryUnpublishedRetention.js +71 -0
  52. package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -0
  53. package/data/persistence/principalKeyEnvelopeArchivePersistence.js +63 -0
  54. package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +1 -0
  55. package/data/persistence/principalKeyEnvelopeCandidates.js +10 -1
  56. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
  57. package/data/sqlite/principalHistoryEvidenceSchema.js +2 -0
  58. package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -1
  59. package/data/sqlite/principalHistoryNodeRetentionSchema.js +30 -0
  60. package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +1 -0
  61. package/data/sqlite/principalHistoryRetentionSchema.js +40 -0
  62. package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -0
  63. package/data/sqlite/principalHistoryStageSchema.js +2 -0
  64. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  65. package/data/sqlite/schema.d.ts +453 -0
  66. package/data/sqlite/schema.js +6 -0
  67. package/data/sqlite/schema.js.map +1 -1
  68. package/data/sqlite/sqliteCommitGuards.js +49 -0
  69. package/data/sqlite/sqliteCommitGuards.js.map +1 -0
  70. package/data/sqlite/sqlitePersistenceRuntime.js +14 -2
  71. package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
  72. package/index.d.ts +3 -1
  73. package/index.js.map +1 -1
  74. package/internal/api-client/ApiClient.d.ts +60 -137
  75. package/internal/api-client/ApiClient.js +7 -5
  76. package/internal/api-client/ApiClient.js.map +1 -1
  77. package/internal/api-client/apiRequestRuntime.js +7 -7
  78. package/internal/api-client/apiRequestRuntime.js.map +1 -1
  79. package/internal/api-client/documentPurge.js +25 -0
  80. package/internal/api-client/documentPurge.js.map +1 -0
  81. package/internal/api-client/organizationPolicyHistory.d.ts +53 -0
  82. package/internal/api-client/organizationPolicyHistory.js +15 -0
  83. package/internal/api-client/organizationPolicyHistory.js.map +1 -0
  84. package/internal/api-client/requestInternals.js +4 -4
  85. package/internal/api-client/requestInternals.js.map +1 -1
  86. package/internal/api-client/types.d.ts +2 -2
  87. package/internal/api-client/types.js.map +1 -1
  88. package/internal/crypto/keying/principalPolicyHistory.js +4 -0
  89. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  90. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
  91. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  92. package/internal/loro/document.js +8 -11
  93. package/internal/loro/document.js.map +1 -1
  94. package/internal/validators/operation/containerMutations.d.ts +448 -6528
  95. package/internal/validators/operation/documentMutations.d.ts +323 -579
  96. package/internal/validators/operation/documentMutations.js +22 -4
  97. package/internal/validators/operation/documentMutations.js.map +1 -1
  98. package/internal/validators/operation/documentSync.d.ts +26 -406
  99. package/internal/validators/operation/organizationPolicyHistory.d.ts +188 -310
  100. package/internal/validators/operation/organizationPolicyHistory.js +17 -3
  101. package/internal/validators/operation/organizationPolicyHistory.js.map +1 -1
  102. package/internal/validators/response/containerMutationError.d.ts +28 -408
  103. package/internal/validators/response/documentMutation.d.ts +232 -544
  104. package/internal/validators/response/documentMutation.js +1 -2
  105. package/internal/validators/response/documentMutation.js.map +1 -1
  106. package/internal/validators/response/documentSyncError.d.ts +26 -406
  107. package/internal/validators/response/documentSyncError.js +4 -3
  108. package/internal/validators/response/documentSyncError.js.map +1 -1
  109. package/internal/validators/response/index.d.ts +1 -1
  110. package/internal/validators/response/index.js +1 -1
  111. package/internal/validators/response/index.js.map +1 -1
  112. package/internal/validators/response/organizationPolicyHistory.d.ts +127 -309
  113. package/internal/validators/response/organizationPolicyHistory.js +10 -4
  114. package/internal/validators/response/organizationPolicyHistory.js.map +1 -1
  115. package/internal/validators/response/principal.d.ts +28 -408
  116. package/internal/validators/response/principal.js +3 -1
  117. package/internal/validators/response/principal.js.map +1 -1
  118. package/internal/validators/util/index.d.ts +1 -1
  119. package/internal/validators/util/index.js +1 -1
  120. package/internal/validators/util/index.js.map +1 -1
  121. package/internal/validators/util/principalHistoryWire.d.ts +2 -0
  122. package/internal/validators/util/principalHistoryWire.js +2 -0
  123. package/internal/validators/util/principalHistoryWire.js.map +1 -1
  124. package/package.json +4 -4
  125. package/workflows/container-contents/container-state/createWithMetadata.js +19 -49
  126. package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
  127. package/workflows/container-contents/container-state/groupGrantVerification.js +29 -0
  128. package/workflows/container-contents/container-state/groupGrantVerification.js.map +1 -1
  129. package/workflows/container-contents/container-state/groupShareEpoch.js +33 -0
  130. package/workflows/container-contents/container-state/groupShareEpoch.js.map +1 -0
  131. package/workflows/container-contents/container-state/remote.js +4 -1
  132. package/workflows/container-contents/container-state/remote.js.map +1 -1
  133. package/workflows/container-contents/container-state/share.js +2 -24
  134. package/workflows/container-contents/container-state/share.js.map +1 -1
  135. package/workflows/container-contents/documentTombstoneEvidence.js +23 -12
  136. package/workflows/container-contents/documentTombstoneEvidence.js.map +1 -1
  137. package/workflows/containers/child/create.js +1 -3
  138. package/workflows/containers/child/create.js.map +1 -1
  139. package/workflows/containers/child/createSubmission.d.ts +1 -3
  140. package/workflows/containers/child/createSubmission.js +13 -15
  141. package/workflows/containers/child/createSubmission.js.map +1 -1
  142. package/workflows/containers/child/currentShareGrantMutation.js +82 -0
  143. package/workflows/containers/child/currentShareGrantMutation.js.map +1 -0
  144. package/workflows/containers/child/currentSharePrincipalPolicy.js +83 -0
  145. package/workflows/containers/child/currentSharePrincipalPolicy.js.map +1 -0
  146. package/workflows/containers/child/mutationSubmit.js +1 -1
  147. package/workflows/containers/child/mutationSubmit.js.map +1 -1
  148. package/workflows/containers/child/runtimeCurrentGroupShare.js +82 -0
  149. package/workflows/containers/child/runtimeCurrentGroupShare.js.map +1 -0
  150. package/workflows/containers/child/share.js +1 -14
  151. package/workflows/containers/child/share.js.map +1 -1
  152. package/workflows/containers/child/shareProjection.js +15 -0
  153. package/workflows/containers/child/shareProjection.js.map +1 -0
  154. package/workflows/documents/purge.d.ts +3 -0
  155. package/workflows/documents/purge.js +13 -0
  156. package/workflows/documents/purge.js.map +1 -1
  157. package/workflows/documents/sync.js +2 -0
  158. package/workflows/documents/sync.js.map +1 -1
  159. package/workflows/documents/syncFailures.js +2 -2
  160. package/workflows/documents/syncFailures.js.map +1 -1
  161. package/workflows/documents/syncPolicyRepair.js +15 -13
  162. package/workflows/documents/syncPolicyRepair.js.map +1 -1
  163. package/workflows/organizations/initialPrincipalCurrentPublication.js +2 -0
  164. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -1
  165. package/workflows/organizations/loadPolicyHistoryDetails.js +31 -32
  166. package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
  167. package/workflows/organizations/organizationPolicyHistoryDetails.js +37 -15
  168. package/workflows/organizations/organizationPolicyHistoryDetails.js.map +1 -1
  169. package/workflows/organizations/organizationPolicyHistoryVerification.js +56 -69
  170. package/workflows/organizations/organizationPolicyHistoryVerification.js.map +1 -1
  171. package/workflows/organizations/policyHistoryCache.js +5 -2
  172. package/workflows/organizations/policyHistoryCache.js.map +1 -1
  173. package/workflows/organizations/policyHistoryTypes.d.ts +1 -0
  174. package/workflows/organizations/policyHistoryTypes.js.map +1 -1
  175. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +4 -1
  176. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
  177. package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +0 -1
  178. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +1 -2
  179. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -1
  180. package/workflows/principals/policyRepair.js +38 -0
  181. package/workflows/principals/policyRepair.js.map +1 -0
  182. package/workflows/principals/policyRepairBudget.d.ts +2 -2
  183. package/workflows/principals/policyRepairBudget.js +3 -3
  184. package/workflows/principals/policyRepairBudget.js.map +1 -1
  185. package/workflows/principals/principalHistoryRecoveryPrefix.js +4 -0
  186. package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -1
  187. package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
  188. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
  189. package/workflows/principals/publicPrincipalHistoryPage.js +1 -0
  190. package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -1
  191. package/workflows/principals/publicPrincipalHistoryProgress.js +1 -0
  192. package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -1
  193. package/workflows/principals/publicPrincipalHistoryTypes.d.ts +2 -0
  194. package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -1
  195. package/workflows/principals/publicProjectionPrincipal.js +1 -0
  196. package/workflows/principals/publicProjectionPrincipal.js.map +1 -1
  197. package/workflows/principals/recoverPrincipalHistoryPage.js +2 -1
  198. package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -1
  199. package/workflows/principals/recoverPrincipalPolicyHistory.js +1 -0
  200. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  201. package/workflows/principals/recoverPublicPrincipalHistory.js +2 -0
  202. package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
  203. package/workflows/principals/runtimePolicyRecovery.js +2 -1
  204. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  205. package/workflows/principals/selectPublicPrincipalHistory.js +21 -15
  206. package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -1
  207. package/workflows/sync/remoteResetPrincipalScope.js +6 -0
  208. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  209. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js +0 -208
  210. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js.map +0 -1
  211. package/data/keyingProjectionVerification/snapshotVerificationCache.js +0 -39
  212. package/data/keyingProjectionVerification/snapshotVerificationCache.js.map +0 -1
  213. package/workflows/containers/child/policyRepair.js +0 -23
  214. package/workflows/containers/child/policyRepair.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"share.js","sourceRoot":"","sources":["share.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport {\n nullOnProjectionVerificationCancellation,\n type ProjectionUserKeyResolver,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport {\n advanceVerifiedSharePolicies,\n loadVerifiedGroupSharePrincipalPolicy,\n} from \"../../containers\";\nimport { createRuntimeGroupMetadataAccess } from \"../../organizations/groupMetadataRuntime\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerContentsPersistence } from \"../containerPersistence\";\nimport { projectionGeneration } from \"../projectionGeneration\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { loadContainerWriterProjectionForState } from \"./projectionCache\";\nimport { shareRemoteContainer, shareRemoteContainerWithGroup } from \"./remote\";\nimport {\n type MatchingRemoteContainerGrant,\n persistDuplicateContainerShare,\n persistSharedContainerState,\n} from \"./sharePersistence\";\nimport type {\n ContainerWorkflowRuntime,\n SharedContainerStateResult,\n} from \"./types\";\n\ntype ContainerShareSubjectType = \"group\" | \"user\";\ntype ContainerShareAccessLevel = \"read\" | \"write\" | \"admin\";\n\ninterface RemoteContainerShareContext {\n matchingGrant: MatchingRemoteContainerGrant | null;\n projection: ContainerWriterProjectionResponse;\n}\n\nfunction readOptionalProjectionString(\n projection: ContainerWriterProjectionResponse,\n key: string,\n): string | null {\n const value = Reflect.get(projection, key);\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nasync function resolveCurrentGroupKeyEpoch(input: {\n // Bound here, in the one verified load a duplicate share performs, so a\n // duplicate never reports success for a group the user did not choose.\n expectedGroupName?: string | undefined;\n groupId: string;\n organizationId: string;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<number | null> {\n if (input.stillCurrent?.() === false) return null;\n const verified = await loadVerifiedGroupSharePrincipalPolicy({\n apiClient: input.runtime.apiClient,\n execSql: input.runtime.infra.execSql,\n expectedGroupName: input.expectedGroupName,\n readEncryptedName: (bundle) =>\n createRuntimeGroupMetadataAccess(\n input.runtime,\n input.organizationId,\n input.stillCurrent,\n ).readName(bundle),\n groupId: input.groupId,\n organizationId: input.organizationId,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n // Commit the verification immediately: this read stands alone (no enclosing\n // mutation advances it later), and an unadvanced checkpoint would let a\n // newer same-epoch policy be rolled back on the next fetch.\n await advanceVerifiedSharePolicies(\n input.runtime.infra.execSql,\n verified,\n input.stillCurrent,\n );\n return input.stillCurrent?.() === false ? null : verified.policy.keyEpoch;\n}\n\n// A container's KEK is wrapped to a group's encapsulation key at a specific key\n// epoch, pinned into the manifest as a referenced principal head. When the group\n// rotates (org-admin add or any removal bumps the epoch and mints a fresh KEM\n// keypair), that wrap goes stale: members holding only the new epoch secret can\n// no longer unwrap it. A re-share to the same group at the same access level is\n// therefore NOT redundant when the pinned epoch trails the group's current head,\n// so it must not be deduped away. The current epoch comes from a network-fresh,\n// fully verified policy bundle guarded by any durable local checkpoint.\nfunction groupGrantIsStale(input: {\n currentKeyEpoch: number;\n referencedPrincipalHeads: ReadonlyArray<ReferencedPrincipalStateResponse>;\n subjectId: string;\n}): boolean {\n const pinnedHead = (input.referencedPrincipalHeads ?? []).find(\n (head) =>\n head.principalType === \"group\" && head.principalId === input.subjectId,\n );\n if (!pinnedHead) {\n return true;\n }\n return pinnedHead.keyEpoch !== input.currentKeyEpoch;\n}\n\nasync function loadRemoteContainerShareContext(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n expectedGroupName?: string | undefined;\n forceExistingGrantRewrap?: boolean | undefined;\n requireExistingGrant?: boolean | undefined;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n subjectId: string;\n subjectType: ContainerShareSubjectType;\n}): Promise<RemoteContainerShareContext | null> {\n if (input.stillCurrent?.() === false) return null;\n const projection = await loadContainerWriterProjectionForState({\n containerState: input.containerState,\n runtime: input.runtime,\n });\n if (!projection || input.stillCurrent?.() === false) {\n return null;\n }\n\n const target = getTargetContainerContext(projection);\n const remoteState = readContainerState(target.manifest);\n const hasMatchingGrant = remoteState.directGrants.some(\n (grant) =>\n grant.subjectType === input.subjectType &&\n grant.subjectId === input.subjectId &&\n grant.accessLevel === input.accessLevel,\n );\n if (!hasMatchingGrant) {\n if (input.requireExistingGrant) {\n // Re-wrap-only callers must never mint a brand-new grant: the container's\n // system slot is server-supplied and could point at a container that does\n // not already grant this subject, so minting here would leak its contents.\n input.runtime.util.log(\n `Container contents: refused to create a new ${input.subjectType} grant for ${input.subjectId} on container ${input.containerState.container.id} because the re-share requires an existing grant`,\n );\n return null;\n }\n return { matchingGrant: null, projection };\n }\n\n if (\n input.subjectType === \"group\" &&\n input.requireExistingGrant &&\n input.forceExistingGrantRewrap\n ) {\n // The cheap epoch probe below reads an unverified response and cannot prove\n // that a security-critical re-wrap is current. Force the verified policy\n // load and a real same-level mutation; failures must reach the retry owner.\n input.runtime.util.log(\n `Container contents: re-sharing container ${input.containerState.container.id} with group ${input.subjectId} because an existing grant re-wrap is required`,\n );\n return { matchingGrant: null, projection };\n }\n\n if (input.subjectType === \"group\") {\n const pinnedHead = remoteState.referencedPrincipalHeads.find(\n (head) =>\n head.principalType === \"group\" && head.principalId === input.subjectId,\n );\n const currentKeyEpoch = pinnedHead\n ? await resolveCurrentGroupKeyEpoch({\n expectedGroupName: input.expectedGroupName,\n groupId: input.subjectId,\n organizationId: remoteState.organizationId,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n })\n : null;\n if (input.stillCurrent?.() === false) return null;\n if (\n !pinnedHead ||\n (currentKeyEpoch !== null &&\n groupGrantIsStale({\n currentKeyEpoch,\n referencedPrincipalHeads: remoteState.referencedPrincipalHeads,\n subjectId: input.subjectId,\n }))\n ) {\n input.runtime.util.log(\n `Container contents: re-sharing container ${input.containerState.container.id} with group ${input.subjectId} because its key epoch advanced past the pinned grant`,\n );\n return { matchingGrant: null, projection };\n }\n }\n\n return {\n matchingGrant: {\n accessEpoch: remoteState.epoch,\n accessStateHash: target.manifest.manifestHash,\n createdAt: readOptionalProjectionString(projection, \"createdAt\"),\n metadataDocumentId: remoteState.metadataDocumentId,\n referencedPrincipalHeads: remoteState.referencedPrincipalHeads,\n updatedAt: readOptionalProjectionString(projection, \"updatedAt\"),\n },\n projection,\n };\n}\n\nasync function prepareContainerStateGroupRewrapInternal(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n groupId: string;\n requireExistingGrant?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | { status: \"not-granted\" }\n | {\n knownContainerKeks: ReadonlyMap<string, Uint8Array>;\n status: \"prepared\";\n }\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const projection = await loadContainerWriterProjectionForState({\n containerState: input.containerState,\n runtime: input.runtime,\n });\n if (!projection || input.stillCurrent?.() === false) {\n return null;\n }\n\n if (input.requireExistingGrant) {\n await verifyContainerWriterProjection({\n execSql: input.runtime.infra.execSql,\n projection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (input.stillCurrent?.() === false) return null;\n const verifiedState = readContainerState(\n getTargetContainerContext(projection).manifest,\n );\n if (\n projection.containerId !== input.containerState.container.id ||\n projection.organizationId !==\n input.containerState.container.organizationId ||\n verifiedState.containerId !== input.containerState.container.id ||\n verifiedState.organizationId !==\n input.containerState.container.organizationId ||\n verifiedState.parentContainerId !==\n input.containerState.container.parentId\n ) {\n throw new Error(\n \"Prepared container group re-wrap target is inconsistent\",\n );\n }\n const hasGrant = verifiedState.directGrants.some(\n (grant) =>\n grant.subjectType === \"group\" &&\n grant.subjectId === input.groupId &&\n grant.accessLevel === input.accessLevel,\n );\n if (!hasGrant) {\n return { status: \"not-granted\" };\n }\n }\n\n const targetSecretKey =\n input.runtime.crypto.encapsulationKeyPair?.secretKey ?? null;\n if (!targetSecretKey) {\n return null;\n }\n\n const target = getTargetContainerContext(projection);\n const keksByEpochId = await unwrapContainerKekPath({\n execSql: input.runtime.infra.execSql,\n projection,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n secretKey: targetSecretKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (input.stillCurrent?.() === false) return null;\n const targetKek = keksByEpochId.get(target.kek.containerKeyEpochId);\n return targetKek\n ? {\n knownContainerKeks: new Map([\n [target.kek.containerKeyEpochId, targetKek],\n ]),\n status: \"prepared\",\n }\n : null;\n}\n\nexport function prepareContainerStateGroupRewrap(\n input: Parameters<typeof prepareContainerStateGroupRewrapInternal>[0],\n): ReturnType<typeof prepareContainerStateGroupRewrapInternal> {\n return nullOnProjectionVerificationCancellation(() =>\n prepareContainerStateGroupRewrapInternal(input),\n );\n}\n\nexport async function shareContainerState(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n persistence: ContainerContentsPersistence;\n recipientUserId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedContainerStateResult | null> {\n if (input.stillCurrent?.() === false) return null;\n // Before the projection load and the share request: a hint that lands during\n // either must keep the resulting projection out of the cache.\n const writerProjectionGeneration = projectionGeneration(input.containerState);\n const shareContext = await loadRemoteContainerShareContext({\n accessLevel: input.accessLevel,\n containerState: input.containerState,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n subjectId: input.recipientUserId,\n subjectType: \"user\",\n });\n if (!shareContext || input.stillCurrent?.() === false) {\n return null;\n }\n if (shareContext.matchingGrant) {\n input.runtime.util.log(\n `Container contents: skipped duplicate share for container ${input.containerState.container.id} with user ${input.recipientUserId}`,\n );\n return persistDuplicateContainerShare({\n containerState: input.containerState,\n grant: shareContext.matchingGrant,\n persistence: input.persistence,\n projection: shareContext.projection,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n }\n\n const shared = await shareRemoteContainer({\n accessLevel: input.accessLevel,\n containerId: input.containerState.container.id,\n previousProjection: shareContext.projection,\n recipientUserId: input.recipientUserId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n\n if (!shared) return null;\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n\n return persistSharedContainerState({\n containerState: input.containerState,\n persistence: input.persistence,\n runtime: input.runtime,\n shared,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n}\n\nexport async function shareContainerStateWithGroup(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n expectedGroupName?: string | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n persistence: ContainerContentsPersistence;\n recipientGroupId: string;\n // When set, a re-share only re-wraps an already-granted group and never mints\n // a new grant. Used by organization access repair so a server cannot redirect\n // the operation onto a container the group is not entitled to. A prepared\n // re-wrap also supplies captured KEKs and must submit a real mutation.\n requireExistingGrant?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedContainerStateResult | null> {\n // A share chosen by name must carry that name so it can be bound to the\n // signed group policy. Only the grant-preserving re-wrap, which never mints\n // a grant, may run without one. Enforced here, in the workflow facade, so\n // every caller (not only the store) meets the invariant.\n if (!input.requireExistingGrant && input.expectedGroupName === undefined) {\n throw new Error(\"Container group share requires the chosen group name\");\n }\n if (input.stillCurrent?.() === false) return null;\n // Before the projection load and the share request: a hint that lands during\n // either must keep the resulting projection out of the cache.\n const writerProjectionGeneration = projectionGeneration(input.containerState);\n const shareContext = await loadRemoteContainerShareContext({\n accessLevel: input.accessLevel,\n containerState: input.containerState,\n expectedGroupName: input.expectedGroupName,\n forceExistingGrantRewrap:\n input.requireExistingGrant && input.knownContainerKeks !== undefined,\n requireExistingGrant: input.requireExistingGrant,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n subjectId: input.recipientGroupId,\n subjectType: \"group\",\n });\n if (!shareContext || input.stillCurrent?.() === false) {\n return null;\n }\n if (shareContext.matchingGrant) {\n // A duplicate share mints nothing, but it must not report success for a\n // group the user did not choose. A matching grant is only found after the\n // key-epoch probe verified the group's policy with the chosen name bound,\n // so the name is already checked here.\n input.runtime.util.log(\n `Container contents: skipped duplicate share for container ${input.containerState.container.id} with group ${input.recipientGroupId}`,\n );\n return persistDuplicateContainerShare({\n containerState: input.containerState,\n grant: shareContext.matchingGrant,\n persistence: input.persistence,\n projection: shareContext.projection,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n }\n\n const shared = await shareRemoteContainerWithGroup({\n accessLevel: input.accessLevel,\n containerId: input.containerState.container.id,\n expectedGroupName: input.expectedGroupName,\n knownContainerKeks: input.knownContainerKeks,\n previousProjection: shareContext.projection,\n recipientGroupId: input.recipientGroupId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n\n if (!shared) return null;\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n\n return persistSharedContainerState({\n containerState: input.containerState,\n persistence: input.persistence,\n runtime: input.runtime,\n shared,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n}\n"]}
1
+ {"version":3,"file":"share.js","sourceRoot":"","sources":["share.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport {\n nullOnProjectionVerificationCancellation,\n type ProjectionUserKeyResolver,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerContentsPersistence } from \"../containerPersistence\";\nimport { projectionGeneration } from \"../projectionGeneration\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { resolveCurrentGroupKeyEpoch } from \"./groupShareEpoch\";\nimport { loadContainerWriterProjectionForState } from \"./projectionCache\";\nimport { shareRemoteContainer, shareRemoteContainerWithGroup } from \"./remote\";\nimport {\n type MatchingRemoteContainerGrant,\n persistDuplicateContainerShare,\n persistSharedContainerState,\n} from \"./sharePersistence\";\nimport type {\n ContainerWorkflowRuntime,\n SharedContainerStateResult,\n} from \"./types\";\n\ntype ContainerShareSubjectType = \"group\" | \"user\";\ntype ContainerShareAccessLevel = \"read\" | \"write\" | \"admin\";\n\ninterface RemoteContainerShareContext {\n matchingGrant: MatchingRemoteContainerGrant | null;\n projection: ContainerWriterProjectionResponse;\n}\n\nfunction readOptionalProjectionString(\n projection: ContainerWriterProjectionResponse,\n key: string,\n): string | null {\n const value = Reflect.get(projection, key);\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n// A container's KEK is wrapped to a group's encapsulation key at a specific key\n// epoch, pinned into the manifest as a referenced principal head. When the group\n// rotates (org-admin add or any removal bumps the epoch and mints a fresh KEM\n// keypair), that wrap goes stale: members holding only the new epoch secret can\n// no longer unwrap it. A re-share to the same group at the same access level is\n// therefore NOT redundant when the pinned epoch trails the group's current head,\n// so it must not be deduped away. The current epoch comes from a network-fresh,\n// fully verified current policy guarded by durable local checkpoints.\nfunction groupGrantIsStale(input: {\n currentKeyEpoch: number;\n referencedPrincipalHeads: ReadonlyArray<ReferencedPrincipalStateResponse>;\n subjectId: string;\n}): boolean {\n const pinnedHead = (input.referencedPrincipalHeads ?? []).find(\n (head) =>\n head.principalType === \"group\" && head.principalId === input.subjectId,\n );\n if (!pinnedHead) {\n return true;\n }\n return pinnedHead.keyEpoch !== input.currentKeyEpoch;\n}\n\nasync function loadRemoteContainerShareContext(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n expectedGroupName?: string | undefined;\n forceExistingGrantRewrap?: boolean | undefined;\n requireExistingGrant?: boolean | undefined;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n subjectId: string;\n subjectType: ContainerShareSubjectType;\n}): Promise<RemoteContainerShareContext | null> {\n if (input.stillCurrent?.() === false) return null;\n const projection = await loadContainerWriterProjectionForState({\n containerState: input.containerState,\n runtime: input.runtime,\n });\n if (!projection || input.stillCurrent?.() === false) {\n return null;\n }\n\n const target = getTargetContainerContext(projection);\n const remoteState = readContainerState(target.manifest);\n const hasMatchingGrant = remoteState.directGrants.some(\n (grant) =>\n grant.subjectType === input.subjectType &&\n grant.subjectId === input.subjectId &&\n grant.accessLevel === input.accessLevel,\n );\n if (!hasMatchingGrant) {\n if (input.requireExistingGrant) {\n // Re-wrap-only callers must never mint a brand-new grant: the container's\n // system slot is server-supplied and could point at a container that does\n // not already grant this subject, so minting here would leak its contents.\n input.runtime.util.log(\n `Container contents: refused to create a new ${input.subjectType} grant for ${input.subjectId} on container ${input.containerState.container.id} because the re-share requires an existing grant`,\n );\n return null;\n }\n return { matchingGrant: null, projection };\n }\n\n if (\n input.subjectType === \"group\" &&\n input.requireExistingGrant &&\n input.forceExistingGrantRewrap\n ) {\n // The cheap epoch probe below reads an unverified response and cannot prove\n // that a security-critical re-wrap is current. Force the verified policy\n // load and a real same-level mutation; failures must reach the retry owner.\n input.runtime.util.log(\n `Container contents: re-sharing container ${input.containerState.container.id} with group ${input.subjectId} because an existing grant re-wrap is required`,\n );\n return { matchingGrant: null, projection };\n }\n\n if (input.subjectType === \"group\") {\n const pinnedHead = remoteState.referencedPrincipalHeads.find(\n (head) =>\n head.principalType === \"group\" && head.principalId === input.subjectId,\n );\n const currentKeyEpoch = pinnedHead\n ? await resolveCurrentGroupKeyEpoch({\n expectedGroupName: input.expectedGroupName,\n groupId: input.subjectId,\n organizationId: remoteState.organizationId,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n })\n : null;\n if (input.stillCurrent?.() === false) return null;\n if (\n !pinnedHead ||\n (currentKeyEpoch !== null &&\n groupGrantIsStale({\n currentKeyEpoch,\n referencedPrincipalHeads: remoteState.referencedPrincipalHeads,\n subjectId: input.subjectId,\n }))\n ) {\n input.runtime.util.log(\n `Container contents: re-sharing container ${input.containerState.container.id} with group ${input.subjectId} because its key epoch advanced past the pinned grant`,\n );\n return { matchingGrant: null, projection };\n }\n }\n\n return {\n matchingGrant: {\n accessEpoch: remoteState.epoch,\n accessStateHash: target.manifest.manifestHash,\n createdAt: readOptionalProjectionString(projection, \"createdAt\"),\n metadataDocumentId: remoteState.metadataDocumentId,\n referencedPrincipalHeads: remoteState.referencedPrincipalHeads,\n updatedAt: readOptionalProjectionString(projection, \"updatedAt\"),\n },\n projection,\n };\n}\n\nasync function prepareContainerStateGroupRewrapInternal(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n groupId: string;\n requireExistingGrant?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | { status: \"not-granted\" }\n | {\n knownContainerKeks: ReadonlyMap<string, Uint8Array>;\n status: \"prepared\";\n }\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const projection = await loadContainerWriterProjectionForState({\n containerState: input.containerState,\n runtime: input.runtime,\n });\n if (!projection || input.stillCurrent?.() === false) {\n return null;\n }\n\n if (input.requireExistingGrant) {\n await verifyContainerWriterProjection({\n execSql: input.runtime.infra.execSql,\n projection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (input.stillCurrent?.() === false) return null;\n const verifiedState = readContainerState(\n getTargetContainerContext(projection).manifest,\n );\n if (\n projection.containerId !== input.containerState.container.id ||\n projection.organizationId !==\n input.containerState.container.organizationId ||\n verifiedState.containerId !== input.containerState.container.id ||\n verifiedState.organizationId !==\n input.containerState.container.organizationId ||\n verifiedState.parentContainerId !==\n input.containerState.container.parentId\n ) {\n throw new Error(\n \"Prepared container group re-wrap target is inconsistent\",\n );\n }\n const hasGrant = verifiedState.directGrants.some(\n (grant) =>\n grant.subjectType === \"group\" &&\n grant.subjectId === input.groupId &&\n grant.accessLevel === input.accessLevel,\n );\n if (!hasGrant) {\n return { status: \"not-granted\" };\n }\n }\n\n const targetSecretKey =\n input.runtime.crypto.encapsulationKeyPair?.secretKey ?? null;\n if (!targetSecretKey) {\n return null;\n }\n\n const target = getTargetContainerContext(projection);\n const keksByEpochId = await unwrapContainerKekPath({\n execSql: input.runtime.infra.execSql,\n projection,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n secretKey: targetSecretKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (input.stillCurrent?.() === false) return null;\n const targetKek = keksByEpochId.get(target.kek.containerKeyEpochId);\n return targetKek\n ? {\n knownContainerKeks: new Map([\n [target.kek.containerKeyEpochId, targetKek],\n ]),\n status: \"prepared\",\n }\n : null;\n}\n\nexport function prepareContainerStateGroupRewrap(\n input: Parameters<typeof prepareContainerStateGroupRewrapInternal>[0],\n): ReturnType<typeof prepareContainerStateGroupRewrapInternal> {\n return nullOnProjectionVerificationCancellation(() =>\n prepareContainerStateGroupRewrapInternal(input),\n );\n}\n\nexport async function shareContainerState(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n persistence: ContainerContentsPersistence;\n recipientUserId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedContainerStateResult | null> {\n if (input.stillCurrent?.() === false) return null;\n // Before the projection load and the share request: a hint that lands during\n // either must keep the resulting projection out of the cache.\n const writerProjectionGeneration = projectionGeneration(input.containerState);\n const shareContext = await loadRemoteContainerShareContext({\n accessLevel: input.accessLevel,\n containerState: input.containerState,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n subjectId: input.recipientUserId,\n subjectType: \"user\",\n });\n if (!shareContext || input.stillCurrent?.() === false) {\n return null;\n }\n if (shareContext.matchingGrant) {\n input.runtime.util.log(\n `Container contents: skipped duplicate share for container ${input.containerState.container.id} with user ${input.recipientUserId}`,\n );\n return persistDuplicateContainerShare({\n containerState: input.containerState,\n grant: shareContext.matchingGrant,\n persistence: input.persistence,\n projection: shareContext.projection,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n }\n\n const shared = await shareRemoteContainer({\n accessLevel: input.accessLevel,\n containerId: input.containerState.container.id,\n previousProjection: shareContext.projection,\n recipientUserId: input.recipientUserId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n\n if (!shared) return null;\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n\n return persistSharedContainerState({\n containerState: input.containerState,\n persistence: input.persistence,\n runtime: input.runtime,\n shared,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n}\n\nexport async function shareContainerStateWithGroup(input: {\n accessLevel: ContainerShareAccessLevel;\n containerState: ContainerState;\n expectedGroupName?: string | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n persistence: ContainerContentsPersistence;\n recipientGroupId: string;\n // When set, a re-share only re-wraps an already-granted group and never mints\n // a new grant. Used by organization access repair so a server cannot redirect\n // the operation onto a container the group is not entitled to. A prepared\n // re-wrap also supplies captured KEKs and must submit a real mutation.\n requireExistingGrant?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedContainerStateResult | null> {\n // A share chosen by name must carry that name so it can be bound to the\n // signed group policy. Only the grant-preserving re-wrap, which never mints\n // a grant, may run without one. Enforced here, in the workflow facade, so\n // every caller (not only the store) meets the invariant.\n if (!input.requireExistingGrant && input.expectedGroupName === undefined) {\n throw new Error(\"Container group share requires the chosen group name\");\n }\n if (input.stillCurrent?.() === false) return null;\n // Before the projection load and the share request: a hint that lands during\n // either must keep the resulting projection out of the cache.\n const writerProjectionGeneration = projectionGeneration(input.containerState);\n const shareContext = await loadRemoteContainerShareContext({\n accessLevel: input.accessLevel,\n containerState: input.containerState,\n expectedGroupName: input.expectedGroupName,\n forceExistingGrantRewrap:\n input.requireExistingGrant && input.knownContainerKeks !== undefined,\n requireExistingGrant: input.requireExistingGrant,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n subjectId: input.recipientGroupId,\n subjectType: \"group\",\n });\n if (!shareContext || input.stillCurrent?.() === false) {\n return null;\n }\n if (shareContext.matchingGrant) {\n // A duplicate share mints nothing, but it must not report success for a\n // group the user did not choose. A matching grant is only found after the\n // key-epoch probe verified the group's policy with the chosen name bound,\n // so the name is already checked here.\n input.runtime.util.log(\n `Container contents: skipped duplicate share for container ${input.containerState.container.id} with group ${input.recipientGroupId}`,\n );\n return persistDuplicateContainerShare({\n containerState: input.containerState,\n grant: shareContext.matchingGrant,\n persistence: input.persistence,\n projection: shareContext.projection,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n }\n\n const shared = await shareRemoteContainerWithGroup({\n accessLevel: input.accessLevel,\n containerId: input.containerState.container.id,\n expectedGroupName: input.expectedGroupName,\n knownContainerKeks: input.knownContainerKeks,\n previousProjection: shareContext.projection,\n recipientGroupId: input.recipientGroupId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n\n if (!shared) return null;\n if (input.stillCurrent?.() === false) return { status: \"confirmed\" };\n\n return persistSharedContainerState({\n containerState: input.containerState,\n persistence: input.persistence,\n runtime: input.runtime,\n shared,\n stillCurrent: input.stillCurrent,\n writerProjectionGeneration,\n });\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { DOCUMENT_NOT_FOUND_ERROR_CODE, } from "../../internal/validators/response/index.js";
2
2
  import { assertDocumentWriterProjectionConsistent } from "../../data/documents/shared/projection.js";
3
3
  import { uniqueSortedStrings } from "../../data/documents/shared/readers.js";
4
+ import { ProjectionDependencyUnavailableError } from "../../data/keyingProjectionVerification/dependencyUnavailable.js";
4
5
  import { reportKeyingVerificationErrorInCauseChain } from "../../data/keyingProjectionVerification/error.js";
5
6
  import { createProjectionUserKeyResolver } from "../../data/keyingProjectionVerification/userKeyResolver.js";
6
7
  import { loadDocumentPurgeCheckpoint } from "../../data/persistence/documentPurgeCheckpointPersistence.js";
@@ -39,6 +40,27 @@ async function verifiedHeadLinkSet(runtime, deps, documentId, projection) {
39
40
  }
40
41
  return verified.value;
41
42
  }
43
+ async function reportUnavailableHead(runtime, documentId, error) {
44
+ const integrityFailure = await reportKeyingVerificationErrorInCauseChain(error, runtime.util.reportSecurityIncident, {
45
+ objectId: documentId,
46
+ objectKind: "document",
47
+ operation: "document.tombstone-evidence",
48
+ });
49
+ try {
50
+ if (!integrityFailure &&
51
+ error instanceof ProjectionDependencyUnavailableError) {
52
+ // A policy can advance without changing this document's hash. Drop its
53
+ // cached evidence so the held head can recover on the next run.
54
+ runtime.apiClient.evictDocumentWriterProjection(documentId);
55
+ runtime.util.log(`Container contents: tombstone evidence for document ${documentId} is awaiting current policy history`);
56
+ return;
57
+ }
58
+ runtime.util.logError?.("Container contents: tombstone evidence is unavailable", error);
59
+ }
60
+ catch {
61
+ // A host logger that throws must not fail the discovery pass.
62
+ }
63
+ }
42
64
  export function createDocumentHeadLinkSetLoader(runtime, deps = {
43
65
  assertDocumentWriterProjectionConsistent,
44
66
  loadDocumentPurgeCheckpoint,
@@ -77,18 +99,7 @@ export function createDocumentHeadLinkSetLoader(runtime, deps = {
77
99
  catch (error) {
78
100
  // Any failure leaves the tombstone unverified (held and retried); a
79
101
  // thrown error here must not fail the whole discovery pass.
80
- await reportKeyingVerificationErrorInCauseChain(error, runtime.util.reportSecurityIncident, {
81
- objectId: documentId,
82
- objectKind: "document",
83
- operation: "document.tombstone-evidence",
84
- });
85
- try {
86
- // A host logger that throws must not fail the discovery pass.
87
- runtime.util.logError?.("Container contents: tombstone evidence is unavailable", error);
88
- }
89
- catch {
90
- // Hosts may throw synchronously.
91
- }
102
+ await reportUnavailableHead(runtime, documentId, error);
92
103
  return null;
93
104
  }
94
105
  };
@@ -1 +1 @@
1
- {"version":3,"file":"documentTombstoneEvidence.js","sourceRoot":"","sources":["documentTombstoneEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DOCUMENT_NOT_FOUND_ERROR_CODE,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../data/documents/shared/projection\";\nimport { uniqueSortedStrings } from \"../../data/documents/shared/readers\";\nimport { reportKeyingVerificationErrorInCauseChain } from \"../../data/keyingProjectionVerification/error\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport { loadDocumentPurgeCheckpoint } from \"../../data/persistence/documentPurgeCheckpointPersistence\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../principals/runtimePolicyWarmer\";\nimport type {\n ContainerDocumentTombstone,\n ContainerDocumentTombstoneVerdict,\n ContainerDocumentTombstoneVerifier,\n} from \"./documentDiscoveryTypes\";\nimport { documentHeadMatchesOrganization } from \"./documentHeadScope\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\nexport interface VerifiedDocumentHeadLinkSet {\n readonly organizationId: string | null;\n readonly accessEpoch: number;\n /** Present for a signed head; a terminal purge has no live access state. */\n readonly accessStateHash?: string;\n readonly linkedContainerIds: ReadonlyArray<string>;\n}\n\n/**\n * The document's verified head link set, or `null` when no verified head is\n * available: the projection could not be fetched (the requester may no\n * longer read the document, or it was purged) or failed verification.\n */\nexport type DocumentHeadLinkSetLoader = (\n documentId: string,\n expectedManifestHash?: string,\n) => Promise<VerifiedDocumentHeadLinkSet | \"not-found\" | null>;\n\n/** The highest access epoch local state records for the document. */\nexport type LocalDocumentAccessEpochLoader = (\n documentId: string,\n) => Promise<number>;\n\nexport interface DocumentHeadLinkSetLoaderDeps {\n readonly assertDocumentWriterProjectionConsistent: typeof assertDocumentWriterProjectionConsistent;\n readonly loadDocumentPurgeCheckpoint: typeof loadDocumentPurgeCheckpoint;\n}\n\nexport const HEAD_LINK_SET_LOAD_CONCURRENCY = 4;\n/**\n * Head loads per settle. Tombstones beyond it stay unverified and are held\n * for a later, backed-off retry, so a bulk move out of a folder does not cost\n * every device an unbounded burst of fetches before the watermark advances.\n */\nexport const HEAD_LINK_SET_LOADS_PER_RUN = 32;\n\nasync function verifiedHeadLinkSet(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps,\n documentId: string,\n projection: DocumentWriterProjectionResponse,\n): Promise<VerifiedDocumentHeadLinkSet> {\n const verified: { value?: VerifiedDocumentHeadLinkSet } = {};\n await deps.assertDocumentWriterProjectionConsistent(projection, {\n // Only the link set is read; a bundle wrapped to superseded KEK targets\n // still carries the signed head.\n allowStaleContentKeyBundle: true,\n execSql: runtime.infra.execSql,\n onVerifiedAuthorization: (authorization) => {\n const head = authorization.documentManifestByHash.get(\n projection.documentManifest.manifestHash,\n );\n if (head && head.state.documentId === documentId) {\n verified.value = {\n organizationId: head.state.organizationId,\n accessEpoch: head.state.epoch,\n accessStateHash: head.manifestHash,\n linkedContainerIds: uniqueSortedStrings(\n head.state.linkedContainerIds,\n ),\n };\n }\n },\n resolveProjectionUserKey: createProjectionUserKeyResolver(runtime),\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!verified.value) {\n throw new Error(\"Tombstone evidence lacks a verified document head\");\n }\n return verified.value;\n}\n\nexport function createDocumentHeadLinkSetLoader(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps = {\n assertDocumentWriterProjectionConsistent,\n loadDocumentPurgeCheckpoint,\n },\n): DocumentHeadLinkSetLoader {\n return async (documentId, expectedManifestHash) => {\n try {\n // A verified purge proof is terminal signed evidence that the document\n // links nothing any more.\n if (\n await deps.loadDocumentPurgeCheckpoint(\n runtime.infra.execSql,\n documentId,\n )\n ) {\n return {\n organizationId: null,\n accessEpoch: Number.MAX_SAFE_INTEGER,\n linkedContainerIds: [],\n };\n }\n // Tombstones require a fresh head. Listings can reuse a matching cached\n // projection, whose signature and local checkpoint are still verified.\n if (!expectedManifestHash)\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n let result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n if (\n expectedManifestHash &&\n result.ok &&\n result.data.documentManifest.manifestHash !== expectedManifestHash\n ) {\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n }\n if (!result.ok) {\n if (\n result.status === 404 &&\n result.code === DOCUMENT_NOT_FOUND_ERROR_CODE\n )\n return \"not-found\";\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is unavailable (${result.status ?? \"offline\"})`,\n );\n return null;\n }\n return await verifiedHeadLinkSet(runtime, deps, documentId, result.data);\n } catch (error) {\n // Any failure leaves the tombstone unverified (held and retried); a\n // thrown error here must not fail the whole discovery pass.\n await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: \"document.tombstone-evidence\",\n },\n );\n try {\n // A host logger that throws must not fail the discovery pass.\n runtime.util.logError?.(\n \"Container contents: tombstone evidence is unavailable\",\n error,\n );\n } catch {\n // Hosts may throw synchronously.\n }\n return null;\n }\n };\n}\n\nfunction judgeTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n head: VerifiedDocumentHeadLinkSet | null,\n): ContainerDocumentTombstoneVerdict[] {\n return tombstones.map((tombstone): ContainerDocumentTombstoneVerdict => {\n if (head === null) {\n return { kind: \"unverified\", tombstone };\n }\n if (head.linkedContainerIds.includes(tombstone.containerId)) {\n return {\n kind: \"refuted\",\n linkedContainerIds: head.linkedContainerIds,\n tombstone,\n };\n }\n return {\n kind: \"verified\",\n tombstone: {\n ...tombstone,\n accessEpoch: head.accessEpoch,\n linkedContainerIds: head.linkedContainerIds,\n },\n };\n });\n}\n\n/**\n * Judge listing tombstones against each document's verified head link set,\n * fetched once per document with bounded concurrency and a per-run cap. A\n * head whose epoch is below local document state is no evidence: it may be a\n * lagging replica or a replay, and applying it could delete rows a newer\n * listing or settled move wrote.\n */\nexport function createContainerDocumentTombstoneVerifier(\n organizationId: string | undefined,\n loadDocumentHeadLinkSet: DocumentHeadLinkSetLoader,\n loadLocalDocumentAccessEpoch: LocalDocumentAccessEpochLoader,\n): ContainerDocumentTombstoneVerifier {\n return async (tombstones) => {\n const byDocumentId = new Map<string, ContainerDocumentTombstone[]>();\n for (const tombstone of tombstones) {\n const group = byDocumentId.get(tombstone.documentId) ?? [];\n group.push(tombstone);\n byDocumentId.set(tombstone.documentId, group);\n }\n const groups = [...byDocumentId.entries()];\n const verdicts: ContainerDocumentTombstoneVerdict[][] = groups.map(\n ([, group], index): ContainerDocumentTombstoneVerdict[] =>\n index < HEAD_LINK_SET_LOADS_PER_RUN\n ? judgeTombstones(group, null)\n : group.map((tombstone) => ({ kind: \"deferred\", tombstone })),\n );\n let next = 0;\n const worker = async () => {\n while (next < Math.min(groups.length, HEAD_LINK_SET_LOADS_PER_RUN)) {\n const index = next++;\n const entry = groups[index];\n if (!entry) break;\n const [documentId, group] = entry;\n const head = await loadDocumentHeadLinkSet(documentId);\n if (head === null || head === \"not-found\") continue;\n if (!documentHeadMatchesOrganization(head, organizationId)) continue;\n // A local-state read that fails is treated like an unavailable head:\n // the tombstones stay held rather than failing the discovery pass.\n const localEpoch = await loadLocalDocumentAccessEpoch(documentId).catch(\n () => Number.MAX_SAFE_INTEGER,\n );\n if (head.accessEpoch < localEpoch) continue;\n verdicts[index] = judgeTombstones(group, head);\n }\n };\n await Promise.all(\n Array.from(\n { length: Math.min(HEAD_LINK_SET_LOAD_CONCURRENCY, groups.length) },\n worker,\n ),\n );\n return verdicts.flat();\n };\n}\n"]}
1
+ {"version":3,"file":"documentTombstoneEvidence.js","sourceRoot":"","sources":["documentTombstoneEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DOCUMENT_NOT_FOUND_ERROR_CODE,\n type DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../data/documents/shared/projection\";\nimport { uniqueSortedStrings } from \"../../data/documents/shared/readers\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { reportKeyingVerificationErrorInCauseChain } from \"../../data/keyingProjectionVerification/error\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport { loadDocumentPurgeCheckpoint } from \"../../data/persistence/documentPurgeCheckpointPersistence\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../principals/runtimePolicyWarmer\";\nimport type {\n ContainerDocumentTombstone,\n ContainerDocumentTombstoneVerdict,\n ContainerDocumentTombstoneVerifier,\n} from \"./documentDiscoveryTypes\";\nimport { documentHeadMatchesOrganization } from \"./documentHeadScope\";\nimport type { ContainerContentsWorkflowRuntime } from \"./runtime\";\n\nexport interface VerifiedDocumentHeadLinkSet {\n readonly organizationId: string | null;\n readonly accessEpoch: number;\n /** Present for a signed head; a terminal purge has no live access state. */\n readonly accessStateHash?: string;\n readonly linkedContainerIds: ReadonlyArray<string>;\n}\n\n/**\n * The document's verified head link set, or `null` when no verified head is\n * available: the projection could not be fetched (the requester may no\n * longer read the document, or it was purged) or failed verification.\n */\nexport type DocumentHeadLinkSetLoader = (\n documentId: string,\n expectedManifestHash?: string,\n) => Promise<VerifiedDocumentHeadLinkSet | \"not-found\" | null>;\n\n/** The highest access epoch local state records for the document. */\nexport type LocalDocumentAccessEpochLoader = (\n documentId: string,\n) => Promise<number>;\n\nexport interface DocumentHeadLinkSetLoaderDeps {\n readonly assertDocumentWriterProjectionConsistent: typeof assertDocumentWriterProjectionConsistent;\n readonly loadDocumentPurgeCheckpoint: typeof loadDocumentPurgeCheckpoint;\n}\n\nexport const HEAD_LINK_SET_LOAD_CONCURRENCY = 4;\n/**\n * Head loads per settle. Tombstones beyond it stay unverified and are held\n * for a later, backed-off retry, so a bulk move out of a folder does not cost\n * every device an unbounded burst of fetches before the watermark advances.\n */\nexport const HEAD_LINK_SET_LOADS_PER_RUN = 32;\n\nasync function verifiedHeadLinkSet(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps,\n documentId: string,\n projection: DocumentWriterProjectionResponse,\n): Promise<VerifiedDocumentHeadLinkSet> {\n const verified: { value?: VerifiedDocumentHeadLinkSet } = {};\n await deps.assertDocumentWriterProjectionConsistent(projection, {\n // Only the link set is read; a bundle wrapped to superseded KEK targets\n // still carries the signed head.\n allowStaleContentKeyBundle: true,\n execSql: runtime.infra.execSql,\n onVerifiedAuthorization: (authorization) => {\n const head = authorization.documentManifestByHash.get(\n projection.documentManifest.manifestHash,\n );\n if (head && head.state.documentId === documentId) {\n verified.value = {\n organizationId: head.state.organizationId,\n accessEpoch: head.state.epoch,\n accessStateHash: head.manifestHash,\n linkedContainerIds: uniqueSortedStrings(\n head.state.linkedContainerIds,\n ),\n };\n }\n },\n resolveProjectionUserKey: createProjectionUserKeyResolver(runtime),\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!verified.value) {\n throw new Error(\"Tombstone evidence lacks a verified document head\");\n }\n return verified.value;\n}\n\nasync function reportUnavailableHead(\n runtime: ContainerContentsWorkflowRuntime,\n documentId: string,\n error: unknown,\n): Promise<void> {\n const integrityFailure = await reportKeyingVerificationErrorInCauseChain(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: \"document.tombstone-evidence\",\n },\n );\n try {\n if (\n !integrityFailure &&\n error instanceof ProjectionDependencyUnavailableError\n ) {\n // A policy can advance without changing this document's hash. Drop its\n // cached evidence so the held head can recover on the next run.\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is awaiting current policy history`,\n );\n return;\n }\n runtime.util.logError?.(\n \"Container contents: tombstone evidence is unavailable\",\n error,\n );\n } catch {\n // A host logger that throws must not fail the discovery pass.\n }\n}\n\nexport function createDocumentHeadLinkSetLoader(\n runtime: ContainerContentsWorkflowRuntime,\n deps: DocumentHeadLinkSetLoaderDeps = {\n assertDocumentWriterProjectionConsistent,\n loadDocumentPurgeCheckpoint,\n },\n): DocumentHeadLinkSetLoader {\n return async (documentId, expectedManifestHash) => {\n try {\n // A verified purge proof is terminal signed evidence that the document\n // links nothing any more.\n if (\n await deps.loadDocumentPurgeCheckpoint(\n runtime.infra.execSql,\n documentId,\n )\n ) {\n return {\n organizationId: null,\n accessEpoch: Number.MAX_SAFE_INTEGER,\n linkedContainerIds: [],\n };\n }\n // Tombstones require a fresh head. Listings can reuse a matching cached\n // projection, whose signature and local checkpoint are still verified.\n if (!expectedManifestHash)\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n let result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n if (\n expectedManifestHash &&\n result.ok &&\n result.data.documentManifest.manifestHash !== expectedManifestHash\n ) {\n runtime.apiClient.evictDocumentWriterProjection(documentId);\n result = await runtime.apiClient.getDocumentWriterProjectionResult(\n documentId,\n { reportErrors: false },\n );\n }\n if (!result.ok) {\n if (\n result.status === 404 &&\n result.code === DOCUMENT_NOT_FOUND_ERROR_CODE\n )\n return \"not-found\";\n runtime.util.log(\n `Container contents: tombstone evidence for document ${documentId} is unavailable (${result.status ?? \"offline\"})`,\n );\n return null;\n }\n return await verifiedHeadLinkSet(runtime, deps, documentId, result.data);\n } catch (error) {\n // Any failure leaves the tombstone unverified (held and retried); a\n // thrown error here must not fail the whole discovery pass.\n await reportUnavailableHead(runtime, documentId, error);\n return null;\n }\n };\n}\n\nfunction judgeTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n head: VerifiedDocumentHeadLinkSet | null,\n): ContainerDocumentTombstoneVerdict[] {\n return tombstones.map((tombstone): ContainerDocumentTombstoneVerdict => {\n if (head === null) {\n return { kind: \"unverified\", tombstone };\n }\n if (head.linkedContainerIds.includes(tombstone.containerId)) {\n return {\n kind: \"refuted\",\n linkedContainerIds: head.linkedContainerIds,\n tombstone,\n };\n }\n return {\n kind: \"verified\",\n tombstone: {\n ...tombstone,\n accessEpoch: head.accessEpoch,\n linkedContainerIds: head.linkedContainerIds,\n },\n };\n });\n}\n\n/**\n * Judge listing tombstones against each document's verified head link set,\n * fetched once per document with bounded concurrency and a per-run cap. A\n * head whose epoch is below local document state is no evidence: it may be a\n * lagging replica or a replay, and applying it could delete rows a newer\n * listing or settled move wrote.\n */\nexport function createContainerDocumentTombstoneVerifier(\n organizationId: string | undefined,\n loadDocumentHeadLinkSet: DocumentHeadLinkSetLoader,\n loadLocalDocumentAccessEpoch: LocalDocumentAccessEpochLoader,\n): ContainerDocumentTombstoneVerifier {\n return async (tombstones) => {\n const byDocumentId = new Map<string, ContainerDocumentTombstone[]>();\n for (const tombstone of tombstones) {\n const group = byDocumentId.get(tombstone.documentId) ?? [];\n group.push(tombstone);\n byDocumentId.set(tombstone.documentId, group);\n }\n const groups = [...byDocumentId.entries()];\n const verdicts: ContainerDocumentTombstoneVerdict[][] = groups.map(\n ([, group], index): ContainerDocumentTombstoneVerdict[] =>\n index < HEAD_LINK_SET_LOADS_PER_RUN\n ? judgeTombstones(group, null)\n : group.map((tombstone) => ({ kind: \"deferred\", tombstone })),\n );\n let next = 0;\n const worker = async () => {\n while (next < Math.min(groups.length, HEAD_LINK_SET_LOADS_PER_RUN)) {\n const index = next++;\n const entry = groups[index];\n if (!entry) break;\n const [documentId, group] = entry;\n const head = await loadDocumentHeadLinkSet(documentId);\n if (head === null || head === \"not-found\") continue;\n if (!documentHeadMatchesOrganization(head, organizationId)) continue;\n // A local-state read that fails is treated like an unavailable head:\n // the tombstones stay held rather than failing the discovery pass.\n const localEpoch = await loadLocalDocumentAccessEpoch(documentId).catch(\n () => Number.MAX_SAFE_INTEGER,\n );\n if (head.accessEpoch < localEpoch) continue;\n verdicts[index] = judgeTombstones(group, head);\n }\n };\n await Promise.all(\n Array.from(\n { length: Math.min(HEAD_LINK_SET_LOAD_CONCURRENCY, groups.length) },\n worker,\n ),\n );\n return verdicts.flat();\n };\n}\n"]}
@@ -273,13 +273,11 @@ async function createRemoteContainerWithRepairs(input) {
273
273
  if (!submitted.ok) {
274
274
  const repair = await repairContainerCreateFailure({
275
275
  apiClient: input.request.apiClient,
276
- execSql: input.request.execSql,
277
276
  failure: submitted,
278
277
  parentContainerId: input.request.parentContainerId,
279
278
  parentProjection,
280
- reportSecurityIncident: input.request.reportSecurityIncident,
281
- resolveTrustedUserIdentity: input.request.resolveTrustedUserIdentity,
282
279
  state: repairState,
280
+ warmReferencedPrincipalPolicies: input.request.warmReferencedPrincipalPolicies,
283
281
  stillCurrent: input.request.stillCurrent,
284
282
  });
285
283
  if (repair.kind === "retry") {
@@ -1 +1 @@
1
- {"version":3,"file":"create.js","sourceRoot":"","sources":["create.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n type ContainerCreateAccessEventBody,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n deriveContainerKekWrappingPublicKey,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../data/containers/shared/containerPathLimits\";\nimport {\n buildContainerCreateBody,\n buildContainerCreateKeyEpoch,\n buildParentRecipientTargets,\n deriveContainerCreateManifest,\n resolveContainerKekEpochId,\n signContainerCreateEvent,\n} from \"../../../data/containers/shared/events\";\nimport { acknowledgeContainerMutation } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n asContainerManifestBundle,\n getParentCreateContext,\n readContainerState,\n wrapContainerKeyToManagedPrincipal,\n wrapContainerKeyToParent,\n} from \"../../../data/containers/shared/projection\";\nimport type {\n BuildContainerCreatePlanInput,\n ContainerCreatePlan,\n ContainerCreatePlanContext,\n ContainerMutationAuthor,\n CreateRemoteContainerResult,\n MaterializedContainerCreatePlan,\n} from \"../../../data/containers/shared/types\";\nimport { assertContainerKekPathCurrent } from \"../../../data/documents/shared/containerKekCurrency\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport {\n type ProjectionVerificationOptions,\n projectionVerificationOptions,\n} from \"../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../data/keyingCanonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport {\n type ContainerCreateRepairState,\n type RemoteContainerCreateInput,\n repairContainerCreateFailure,\n submitRemoteContainerCreate,\n} from \"./createSubmission\";\nimport { containerMutationRequestCore } from \"./mutationRequestCore\";\nimport { requireUnwrappedKek } from \"./rotationContext\";\n\nfunction assertContainerCreatePlanInput(input: {\n containerKey: Uint8Array;\n}): void {\n if (input.containerKey.byteLength !== 32) {\n throw new Error(\"Container KEK material must be 32 bytes\");\n }\n // The child container's organization is derived from the parent projection\n // (see buildContainerCreatePlan), so it always matches the parent by\n // construction — a member writing under another org's shared root is the\n // expected case, not an error. The author supplies only the signer identity.\n}\n\nfunction buildContainerCreateRequest(input: {\n body: ContainerCreateAccessEventBody;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n parentKek: ContainerKekResponse;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"create\", {\n ...input,\n userRecipientKeys: [],\n }),\n previousManifest: null,\n parentContainerPath: input.parentProjection.path.map(\n asContainerManifestBundle,\n ),\n predecessorBridge: null,\n keyring: null,\n parentKekState: readCanonicalRecord(\n input.parentKek,\n \"Container create parent KEK state\",\n ),\n };\n}\n\nasync function resolveContainerCreatePlanContext(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlanContext> {\n assertContainerCreatePlanInput(input);\n assertContainerKekPathCurrent(input.parentProjection.containerKeks);\n const containerId = input.containerId ?? crypto.randomUUID();\n\n return {\n ...input,\n containerId,\n containerKeyPublicKey: await deriveContainerKekWrappingPublicKey({\n containerId,\n keyMaterial: input.containerKey,\n }),\n containerKeyEpochId: await resolveContainerKekEpochId({\n containerId,\n keyEpoch: 1,\n keyMaterial: input.containerKey,\n override: input.containerKeyEpochId,\n }),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parent: getParentCreateContext(input.parentProjection),\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n}\n\nfunction buildChildContainerCreateBody(\n context: ContainerCreatePlanContext,\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"],\n): ContainerCreateAccessEventBody {\n const baseBody = buildContainerCreateBody({\n systemSlot: context.systemSlot ?? null,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId: context.parentProjection.containerId,\n parentManifestHash: context.parent.manifest.manifestHash,\n });\n if (!managedGrant) {\n return baseBody;\n }\n return {\n ...baseBody,\n directGrants: [\n {\n accessLevel: managedGrant.accessLevel,\n subjectId: managedGrant.principalHead.principalId,\n subjectType: managedGrant.principalHead.principalType,\n },\n ],\n referencedPrincipalHeads: [managedGrant.principalHead],\n };\n}\n\n// A managed-principal grant adds a second recipient: the group/organization key\n// wrap alongside the parent-inheritance wrap. The server derives both targets\n// (parent inheritance + directGrant) and requires exactly one wrap each; target\n// order is irrelevant since the key-target hash is normalized.\nasync function buildChildContainerWrapsAndTargets(input: {\n context: ContainerCreatePlanContext;\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n manifestHash: string;\n}): Promise<{\n recipientTargets: ContainerKekRecipientTarget[];\n wraps: ContainerKeyWrap[];\n}> {\n const { context, managedGrant, manifestHash } = input;\n const parentPublicKey = readContainerState(\n context.parent.manifest,\n ).containerKeyPublicKey;\n if (!parentPublicKey)\n throw new Error(\"Container parent wrapping public key is missing\");\n const parentWrap = await wrapContainerKeyToParent({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n parentKek: context.parent.kek,\n parentPublicKey,\n });\n const parentTargets = buildParentRecipientTargets(context.parent.kek);\n if (!managedGrant) {\n return { recipientTargets: parentTargets, wraps: [parentWrap] };\n }\n const managedRecipient = await wrapContainerKeyToManagedPrincipal({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n principalEncapsulationPublicKey:\n managedGrant.principalEncapsulationPublicKey,\n principalHead: managedGrant.principalHead,\n });\n return {\n recipientTargets: [...parentTargets, managedRecipient.recipientTarget],\n wraps: [parentWrap, managedRecipient.wrap],\n };\n}\n\nexport async function buildContainerCreatePlan(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlan> {\n const context = await resolveContainerCreatePlanContext(input);\n const parentContainerId = context.parentProjection.containerId;\n const parentManifestHash = context.parent.manifest.manifestHash;\n const managedGrant = input.managedPrincipalGrant;\n const body = buildChildContainerCreateBody(context, managedGrant);\n // The new container belongs to the parent's organization, not the author's.\n // A member writing under another org's shared root mints a container owned by\n // that org; the author only supplies the signer identity.\n const organizationId = context.parentProjection.organizationId;\n const { event, eventHash } = await signContainerCreateEvent({\n author: context.author,\n body,\n containerId: context.containerId,\n eventId: context.eventId,\n organizationId,\n parentPath: context.parentProjection.path,\n signedAt: context.signedAt,\n });\n const { manifest, manifestHash, state } = await deriveContainerCreateManifest(\n {\n systemSlot: context.systemSlot ?? null,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n directGrants: body.directGrants,\n eventHash,\n metadataDocumentId: context.metadataDocumentId,\n organizationId,\n parentContainerId,\n parentManifestHash,\n referencedPrincipalHeads: body.referencedPrincipalHeads,\n },\n );\n const keyEpoch = buildContainerCreateKeyEpoch({\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n eventHash,\n manifestHash,\n parentContainerKeyEpochId: context.parent.kek.containerKeyEpochId,\n });\n const { recipientTargets, wraps } = await buildChildContainerWrapsAndTargets({\n context,\n managedGrant,\n manifestHash,\n });\n const keyTargetHash =\n await computeContainerKekRecipientTargetHash(recipientTargets);\n const keyEpochHash = await computeContainerKeyEpochHash(keyEpoch);\n return {\n body,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n event,\n eventHash,\n keyEpoch,\n keyEpochHash,\n keyTargetHash,\n manifest,\n manifestHash,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId,\n parentManifestHash,\n recipientTargets,\n request: buildContainerCreateRequest({\n body,\n event,\n keyEpoch,\n manifest,\n manifestHash,\n parentKek: context.parent.kek,\n parentProjection: context.parentProjection,\n principalPolicies: context.principalPolicies ?? [],\n wraps,\n }),\n state,\n wraps,\n };\n}\n\nexport async function buildMaterializedContainerCreatePlan(\n input: {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n managedPrincipalGrant?: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n parentSecretKey: Uint8Array;\n signedAt?: string | undefined;\n // Fetches the parent path's referenced principal policies on demand when\n // they are not cached locally — lets a member create under another org's\n // shared root without having first hydrated that org's group policy.\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedContainerCreatePlan> {\n const containerKey =\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32));\n\n const parentKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.parentProjection,\n secretKey: input.parentSecretKey,\n ...projectionVerificationOptions(input),\n });\n const parent = getParentCreateContext(input.parentProjection);\n requireUnwrappedKek(parentKeksByEpochId, parent.kek, \"Container parent\");\n // Checked on the path verification just accepted, never on the raw response.\n assertContainerChildPathFits(input.parentProjection.path);\n const principalPolicies = input.resolveProjectionUserKey\n ? await collectContainerWriterProjectionPrincipalPolicies({\n execSql: input.execSql,\n projection: input.parentProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })\n : [];\n if (input.resolveProjectionUserKey) {\n assertContainerAuthorAccess({\n author: {\n ...input.author,\n organizationId: input.parentProjection.organizationId,\n },\n projection: input.parentProjection,\n principalPolicies,\n minimumAccess: input.systemSlot ? \"admin\" : \"write\",\n });\n }\n const plan = await buildContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey,\n containerKeyEpochId: input.containerKeyEpochId,\n eventId: input.eventId,\n managedPrincipalGrant: input.managedPrincipalGrant,\n metadataDocumentId: input.metadataDocumentId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n principalPolicies,\n signedAt: input.signedAt,\n });\n\n return {\n containerKey,\n plan,\n };\n}\n\nexport { childContainerWriterProjectionFromCreatePlan } from \"./createProjection\";\n\nasync function createRemoteContainerWithRepairs(input: {\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly eventId: string;\n readonly metadataDocumentId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly request: RemoteContainerCreateInput;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly signedAt: string;\n}): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n let parentProjection = input.parentProjection;\n const repairState: ContainerCreateRepairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const materializedPlan = await buildMaterializedContainerCreatePlan({\n author: input.request.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n containerKeyEpochId: input.request.containerKeyEpochId,\n eventId: input.eventId,\n execSql: input.request.execSql,\n metadataDocumentId: input.metadataDocumentId,\n parentProjection,\n parentSecretKey: input.request.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.request.stillCurrent,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n });\n const submitted = await submitRemoteContainerCreate({\n apiClient: input.request.apiClient,\n plan: materializedPlan.plan,\n stillCurrent: input.request.stillCurrent,\n });\n if (!submitted) return null;\n if (!submitted.ok) {\n const repair = await repairContainerCreateFailure({\n apiClient: input.request.apiClient,\n execSql: input.request.execSql,\n failure: submitted,\n parentContainerId: input.request.parentContainerId,\n parentProjection,\n reportSecurityIncident: input.request.reportSecurityIncident,\n resolveTrustedUserIdentity: input.request.resolveTrustedUserIdentity,\n state: repairState,\n stillCurrent: input.request.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") {\n return null;\n }\n submitted.report();\n return null;\n }\n const acknowledged = await acknowledgeContainerMutation({\n execSql: input.request.execSql,\n plan: materializedPlan.plan,\n response: submitted.response,\n stillCurrent: input.request.stillCurrent,\n });\n return {\n acknowledged,\n result: {\n containerKey: materializedPlan.containerKey,\n containerId: submitted.response.containerId,\n metadataDocumentId: materializedPlan.plan.metadataDocumentId,\n plan: materializedPlan.plan,\n response: submitted.response,\n },\n };\n }\n}\n\nasync function createRemoteContainerOutcome(\n input: RemoteContainerCreateInput,\n): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container create\",\n );\n const parentProjection =\n input.parentProjection ??\n (await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n ));\n if (!parentProjection) {\n return null;\n }\n return nullOnProjectionVerificationCancellation(() =>\n createRemoteContainerWithRepairs({\n containerId: input.containerId ?? crypto.randomUUID(),\n containerKey:\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32)),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parentProjection,\n request: input,\n resolveProjectionUserKey,\n signedAt: input.signedAt ?? new Date().toISOString(),\n }),\n );\n}\n\nexport async function createRemoteContainer(\n input: RemoteContainerCreateInput,\n): Promise<CreateRemoteContainerResult | null> {\n const outcome = await createRemoteContainerOutcome(input);\n return outcome?.acknowledged && input.stillCurrent?.() !== false\n ? outcome.result\n : null;\n}\n"]}
1
+ {"version":3,"file":"create.js","sourceRoot":"","sources":["create.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessEvent,\n type AccessManifest,\n type ContainerCreateAccessEventBody,\n type ContainerKekRecipientTarget,\n type ContainerKeyEpoch,\n type ContainerKeyWrap,\n computeContainerKekRecipientTargetHash,\n computeContainerKeyEpochHash,\n deriveContainerKekWrappingPublicKey,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerKekResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { assertContainerAuthorAccess } from \"../../../data/containers/shared/authorAccess\";\nimport { assertContainerChildPathFits } from \"../../../data/containers/shared/containerPathLimits\";\nimport {\n buildContainerCreateBody,\n buildContainerCreateKeyEpoch,\n buildParentRecipientTargets,\n deriveContainerCreateManifest,\n resolveContainerKekEpochId,\n signContainerCreateEvent,\n} from \"../../../data/containers/shared/events\";\nimport { acknowledgeContainerMutation } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n asContainerManifestBundle,\n getParentCreateContext,\n readContainerState,\n wrapContainerKeyToManagedPrincipal,\n wrapContainerKeyToParent,\n} from \"../../../data/containers/shared/projection\";\nimport type {\n BuildContainerCreatePlanInput,\n ContainerCreatePlan,\n ContainerCreatePlanContext,\n ContainerMutationAuthor,\n CreateRemoteContainerResult,\n MaterializedContainerCreatePlan,\n} from \"../../../data/containers/shared/types\";\nimport { assertContainerKekPathCurrent } from \"../../../data/documents/shared/containerKekCurrency\";\nimport { unwrapContainerKekPath } from \"../../../data/documents/shared/projection\";\nimport {\n type ProjectionVerificationOptions,\n projectionVerificationOptions,\n} from \"../../../data/documents/shared/types\";\nimport { readCanonicalRecord } from \"../../../data/keyingCanonicalJson\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport {\n collectContainerWriterProjectionPrincipalPolicies,\n nullOnProjectionVerificationCancellation,\n requireProjectionUserKeyResolver,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport {\n type ContainerCreateRepairState,\n type RemoteContainerCreateInput,\n repairContainerCreateFailure,\n submitRemoteContainerCreate,\n} from \"./createSubmission\";\nimport { containerMutationRequestCore } from \"./mutationRequestCore\";\nimport { requireUnwrappedKek } from \"./rotationContext\";\n\nfunction assertContainerCreatePlanInput(input: {\n containerKey: Uint8Array;\n}): void {\n if (input.containerKey.byteLength !== 32) {\n throw new Error(\"Container KEK material must be 32 bytes\");\n }\n // The child container's organization is derived from the parent projection\n // (see buildContainerCreatePlan), so it always matches the parent by\n // construction — a member writing under another org's shared root is the\n // expected case, not an error. The author supplies only the signer identity.\n}\n\nfunction buildContainerCreateRequest(input: {\n body: ContainerCreateAccessEventBody;\n event: AccessEvent;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n parentKek: ContainerKekResponse;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies: readonly PrincipalPolicyCurrentEvidence[];\n wraps: readonly ContainerKeyWrap[];\n}): ContainerMutationRequest {\n return {\n ...containerMutationRequestCore(\"create\", {\n ...input,\n userRecipientKeys: [],\n }),\n previousManifest: null,\n parentContainerPath: input.parentProjection.path.map(\n asContainerManifestBundle,\n ),\n predecessorBridge: null,\n keyring: null,\n parentKekState: readCanonicalRecord(\n input.parentKek,\n \"Container create parent KEK state\",\n ),\n };\n}\n\nasync function resolveContainerCreatePlanContext(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlanContext> {\n assertContainerCreatePlanInput(input);\n assertContainerKekPathCurrent(input.parentProjection.containerKeks);\n const containerId = input.containerId ?? crypto.randomUUID();\n\n return {\n ...input,\n containerId,\n containerKeyPublicKey: await deriveContainerKekWrappingPublicKey({\n containerId,\n keyMaterial: input.containerKey,\n }),\n containerKeyEpochId: await resolveContainerKekEpochId({\n containerId,\n keyEpoch: 1,\n keyMaterial: input.containerKey,\n override: input.containerKeyEpochId,\n }),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parent: getParentCreateContext(input.parentProjection),\n signedAt: input.signedAt ?? new Date().toISOString(),\n };\n}\n\nfunction buildChildContainerCreateBody(\n context: ContainerCreatePlanContext,\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"],\n): ContainerCreateAccessEventBody {\n const baseBody = buildContainerCreateBody({\n systemSlot: context.systemSlot ?? null,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId: context.parentProjection.containerId,\n parentManifestHash: context.parent.manifest.manifestHash,\n });\n if (!managedGrant) {\n return baseBody;\n }\n return {\n ...baseBody,\n directGrants: [\n {\n accessLevel: managedGrant.accessLevel,\n subjectId: managedGrant.principalHead.principalId,\n subjectType: managedGrant.principalHead.principalType,\n },\n ],\n referencedPrincipalHeads: [managedGrant.principalHead],\n };\n}\n\n// A managed-principal grant adds a second recipient: the group/organization key\n// wrap alongside the parent-inheritance wrap. The server derives both targets\n// (parent inheritance + directGrant) and requires exactly one wrap each; target\n// order is irrelevant since the key-target hash is normalized.\nasync function buildChildContainerWrapsAndTargets(input: {\n context: ContainerCreatePlanContext;\n managedGrant: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n manifestHash: string;\n}): Promise<{\n recipientTargets: ContainerKekRecipientTarget[];\n wraps: ContainerKeyWrap[];\n}> {\n const { context, managedGrant, manifestHash } = input;\n const parentPublicKey = readContainerState(\n context.parent.manifest,\n ).containerKeyPublicKey;\n if (!parentPublicKey)\n throw new Error(\"Container parent wrapping public key is missing\");\n const parentWrap = await wrapContainerKeyToParent({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n parentKek: context.parent.kek,\n parentPublicKey,\n });\n const parentTargets = buildParentRecipientTargets(context.parent.kek);\n if (!managedGrant) {\n return { recipientTargets: parentTargets, wraps: [parentWrap] };\n }\n const managedRecipient = await wrapContainerKeyToManagedPrincipal({\n containerKey: context.containerKey,\n containerKeyEpochId: context.containerKeyEpochId,\n manifestHash,\n principalEncapsulationPublicKey:\n managedGrant.principalEncapsulationPublicKey,\n principalHead: managedGrant.principalHead,\n });\n return {\n recipientTargets: [...parentTargets, managedRecipient.recipientTarget],\n wraps: [parentWrap, managedRecipient.wrap],\n };\n}\n\nexport async function buildContainerCreatePlan(\n input: BuildContainerCreatePlanInput,\n): Promise<ContainerCreatePlan> {\n const context = await resolveContainerCreatePlanContext(input);\n const parentContainerId = context.parentProjection.containerId;\n const parentManifestHash = context.parent.manifest.manifestHash;\n const managedGrant = input.managedPrincipalGrant;\n const body = buildChildContainerCreateBody(context, managedGrant);\n // The new container belongs to the parent's organization, not the author's.\n // A member writing under another org's shared root mints a container owned by\n // that org; the author only supplies the signer identity.\n const organizationId = context.parentProjection.organizationId;\n const { event, eventHash } = await signContainerCreateEvent({\n author: context.author,\n body,\n containerId: context.containerId,\n eventId: context.eventId,\n organizationId,\n parentPath: context.parentProjection.path,\n signedAt: context.signedAt,\n });\n const { manifest, manifestHash, state } = await deriveContainerCreateManifest(\n {\n systemSlot: context.systemSlot ?? null,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n containerKeyPublicKey: context.containerKeyPublicKey,\n directGrants: body.directGrants,\n eventHash,\n metadataDocumentId: context.metadataDocumentId,\n organizationId,\n parentContainerId,\n parentManifestHash,\n referencedPrincipalHeads: body.referencedPrincipalHeads,\n },\n );\n const keyEpoch = buildContainerCreateKeyEpoch({\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n eventHash,\n manifestHash,\n parentContainerKeyEpochId: context.parent.kek.containerKeyEpochId,\n });\n const { recipientTargets, wraps } = await buildChildContainerWrapsAndTargets({\n context,\n managedGrant,\n manifestHash,\n });\n const keyTargetHash =\n await computeContainerKekRecipientTargetHash(recipientTargets);\n const keyEpochHash = await computeContainerKeyEpochHash(keyEpoch);\n return {\n body,\n containerId: context.containerId,\n containerKeyEpochId: context.containerKeyEpochId,\n event,\n eventHash,\n keyEpoch,\n keyEpochHash,\n keyTargetHash,\n manifest,\n manifestHash,\n metadataDocumentId: context.metadataDocumentId,\n parentContainerId,\n parentManifestHash,\n recipientTargets,\n request: buildContainerCreateRequest({\n body,\n event,\n keyEpoch,\n manifest,\n manifestHash,\n parentKek: context.parent.kek,\n parentProjection: context.parentProjection,\n principalPolicies: context.principalPolicies ?? [],\n wraps,\n }),\n state,\n wraps,\n };\n}\n\nexport async function buildMaterializedContainerCreatePlan(\n input: {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql?: ExecSql | undefined;\n managedPrincipalGrant?: BuildContainerCreatePlanInput[\"managedPrincipalGrant\"];\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n parentSecretKey: Uint8Array;\n signedAt?: string | undefined;\n // Fetches the parent path's referenced principal policies on demand when\n // they are not cached locally — lets a member create under another org's\n // shared root without having first hydrated that org's group policy.\n warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n } & ProjectionVerificationOptions,\n): Promise<MaterializedContainerCreatePlan> {\n const containerKey =\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32));\n\n const parentKeksByEpochId = await unwrapContainerKekPath({\n execSql: input.execSql,\n projection: input.parentProjection,\n secretKey: input.parentSecretKey,\n ...projectionVerificationOptions(input),\n });\n const parent = getParentCreateContext(input.parentProjection);\n requireUnwrappedKek(parentKeksByEpochId, parent.kek, \"Container parent\");\n // Checked on the path verification just accepted, never on the raw response.\n assertContainerChildPathFits(input.parentProjection.path);\n const principalPolicies = input.resolveProjectionUserKey\n ? await collectContainerWriterProjectionPrincipalPolicies({\n execSql: input.execSql,\n projection: input.parentProjection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n })\n : [];\n if (input.resolveProjectionUserKey) {\n assertContainerAuthorAccess({\n author: {\n ...input.author,\n organizationId: input.parentProjection.organizationId,\n },\n projection: input.parentProjection,\n principalPolicies,\n minimumAccess: input.systemSlot ? \"admin\" : \"write\",\n });\n }\n const plan = await buildContainerCreatePlan({\n author: input.author,\n containerId: input.containerId,\n containerKey,\n containerKeyEpochId: input.containerKeyEpochId,\n eventId: input.eventId,\n managedPrincipalGrant: input.managedPrincipalGrant,\n metadataDocumentId: input.metadataDocumentId,\n systemSlot: input.systemSlot,\n parentProjection: input.parentProjection,\n principalPolicies,\n signedAt: input.signedAt,\n });\n\n return {\n containerKey,\n plan,\n };\n}\n\nexport { childContainerWriterProjectionFromCreatePlan } from \"./createProjection\";\n\nasync function createRemoteContainerWithRepairs(input: {\n readonly containerId: string;\n readonly containerKey: Uint8Array;\n readonly eventId: string;\n readonly metadataDocumentId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly request: RemoteContainerCreateInput;\n readonly resolveProjectionUserKey: ProjectionUserKeyResolver;\n readonly signedAt: string;\n}): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n let parentProjection = input.parentProjection;\n const repairState: ContainerCreateRepairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const materializedPlan = await buildMaterializedContainerCreatePlan({\n author: input.request.author,\n containerId: input.containerId,\n containerKey: input.containerKey,\n containerKeyEpochId: input.request.containerKeyEpochId,\n eventId: input.eventId,\n execSql: input.request.execSql,\n metadataDocumentId: input.metadataDocumentId,\n parentProjection,\n parentSecretKey: input.request.parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n signedAt: input.signedAt,\n stillCurrent: input.request.stillCurrent,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n });\n const submitted = await submitRemoteContainerCreate({\n apiClient: input.request.apiClient,\n plan: materializedPlan.plan,\n stillCurrent: input.request.stillCurrent,\n });\n if (!submitted) return null;\n if (!submitted.ok) {\n const repair = await repairContainerCreateFailure({\n apiClient: input.request.apiClient,\n failure: submitted,\n parentContainerId: input.request.parentContainerId,\n parentProjection,\n state: repairState,\n warmReferencedPrincipalPolicies:\n input.request.warmReferencedPrincipalPolicies,\n stillCurrent: input.request.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") {\n return null;\n }\n submitted.report();\n return null;\n }\n const acknowledged = await acknowledgeContainerMutation({\n execSql: input.request.execSql,\n plan: materializedPlan.plan,\n response: submitted.response,\n stillCurrent: input.request.stillCurrent,\n });\n return {\n acknowledged,\n result: {\n containerKey: materializedPlan.containerKey,\n containerId: submitted.response.containerId,\n metadataDocumentId: materializedPlan.plan.metadataDocumentId,\n plan: materializedPlan.plan,\n response: submitted.response,\n },\n };\n }\n}\n\nasync function createRemoteContainerOutcome(\n input: RemoteContainerCreateInput,\n): Promise<{\n readonly acknowledged: boolean;\n readonly result: CreateRemoteContainerResult;\n} | null> {\n const resolveProjectionUserKey = requireProjectionUserKeyResolver(\n input.resolveProjectionUserKey,\n \"Remote container create\",\n );\n const parentProjection =\n input.parentProjection ??\n (await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n ));\n if (!parentProjection) {\n return null;\n }\n return nullOnProjectionVerificationCancellation(() =>\n createRemoteContainerWithRepairs({\n containerId: input.containerId ?? crypto.randomUUID(),\n containerKey:\n input.containerKey ?? crypto.getRandomValues(new Uint8Array(32)),\n eventId: input.eventId ?? crypto.randomUUID(),\n metadataDocumentId: input.metadataDocumentId ?? crypto.randomUUID(),\n parentProjection,\n request: input,\n resolveProjectionUserKey,\n signedAt: input.signedAt ?? new Date().toISOString(),\n }),\n );\n}\n\nexport async function createRemoteContainer(\n input: RemoteContainerCreateInput,\n): Promise<CreateRemoteContainerResult | null> {\n const outcome = await createRemoteContainerOutcome(input);\n return outcome?.acknowledged && input.stillCurrent?.() !== false\n ? outcome.result\n : null;\n}\n"]}
@@ -46,13 +46,11 @@ export declare function submitRemoteContainerCreate(input: {
46
46
  } | ContainerMutationSubmitFailure | null>;
47
47
  export declare function repairContainerCreateFailure(input: {
48
48
  readonly apiClient: ContainerCreateApi;
49
- readonly execSql: ExecSql;
50
49
  readonly failure: ContainerMutationSubmitFailure;
51
50
  readonly parentContainerId: string;
52
51
  readonly parentProjection: ContainerWriterProjectionResponse;
53
- readonly reportSecurityIncident: SecurityIncidentReporter;
54
- readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;
55
52
  readonly state: ContainerCreateRepairState;
53
+ readonly warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;
56
54
  readonly stillCurrent?: (() => boolean) | undefined;
57
55
  }): Promise<ContainerCreateFailureRepair>;
58
56
  export {};
@@ -1,5 +1,5 @@
1
1
  import { isStaleParentContainerPathFailure } from "../../../data/containers/shared/mutationFailures.js";
2
- import { cacheRemoteContainerCreatePolicyRepair } from "./policyRepair.js";
2
+ import { recoverPrincipalPolicyRepair } from "../../principals/policyRepair.js";
3
3
  export async function submitRemoteContainerCreate(input) {
4
4
  if (input.stillCurrent?.() === false)
5
5
  return null;
@@ -13,26 +13,24 @@ export async function repairContainerCreateFailure(input) {
13
13
  if (input.stillCurrent?.() === false) {
14
14
  return { kind: "unavailable" };
15
15
  }
16
- if (input.state.policyRepairs.take(input.failure.stalePrincipalPolicies) &&
17
- (await cacheRemoteContainerCreatePolicyRepair({
18
- apiClient: input.apiClient,
19
- execSql: input.execSql,
20
- failure: input.failure,
16
+ const repairedPolicy = input.state.policyRepairs.take(input.failure.stalePrincipalHeads) &&
17
+ (await recoverPrincipalPolicyRepair({
18
+ heads: input.failure.stalePrincipalHeads,
21
19
  organizationId: input.parentProjection.organizationId,
22
- reportSecurityIncident: input.reportSecurityIncident,
23
- resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,
20
+ warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,
24
21
  stillCurrent: input.stillCurrent,
25
- }))) {
26
- return { kind: "retry", parentProjection: input.parentProjection };
27
- }
22
+ }));
28
23
  if (input.stillCurrent?.() === false) {
29
24
  return { kind: "unavailable" };
30
25
  }
31
- if (input.state.didRepairStaleParent ||
32
- !isStaleParentContainerPathFailure(input.failure)) {
33
- return { kind: "none" };
26
+ if (!repairedPolicy) {
27
+ if (input.state.didRepairStaleParent ||
28
+ !isStaleParentContainerPathFailure(input.failure))
29
+ return { kind: "none" };
30
+ input.state.didRepairStaleParent = true;
34
31
  }
35
- input.state.didRepairStaleParent = true;
32
+ // Recovery may select newer policies. Rebuild against a fresh public evidence
33
+ // source so the old projection cannot conflict with newly admitted pins.
36
34
  input.apiClient.evictContainerWriterProjection(input.parentContainerId);
37
35
  const parentProjection = await input.apiClient.getContainerWriterProjection(input.parentContainerId);
38
36
  if (input.stillCurrent?.() === false) {
@@ -1 +1 @@
1
- {"version":3,"file":"createSubmission.js","sourceRoot":"","sources":["createSubmission.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iCAAiC,EAAE,MAAM,kDAAkD,CAAC;AAerG,OAAO,EAAE,sCAAsC,EAAE,MAAM,gBAAgB,CAAC;AAmCxE,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAIjD;IAQC,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,qBAAqB,CACxD,KAAK,CAAC,IAAI,CAAC,OAAO,EAClB;QACE,qCAAqC,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc;QACtE,YAAY,EAAE,KAAK;KACpB,CACF,CAAC;IACF,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAClE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAUlD;IACC,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,IACE,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,sBAAsB,CAAC;QACpE,CAAC,MAAM,sCAAsC,CAAC;YAC5C,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc;YACrD,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;YACpD,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;YAC5D,YAAY,EAAE,KAAK,CAAC,YAAY;SACjC,CAAC,CAAC,EACH,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,IACE,KAAK,CAAC,KAAK,CAAC,oBAAoB;QAChC,CAAC,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,EACjD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,CAAC;IACD,KAAK,CAAC,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACxC,KAAK,CAAC,SAAS,CAAC,8BAA8B,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,4BAA4B,CACzE,KAAK,CAAC,iBAAiB,CACxB,CAAC;IACF,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,gBAAgB;QACrB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE;QACrC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AAC9B,CAAC","sourcesContent":["import type {\n ContainerMutationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { isStaleParentContainerPathFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type {\n ContainerCreateApi,\n ContainerCreatePlan,\n ContainerMutationAuthor,\n ContainerMutationSubmitFailure,\n} from \"../../../data/containers/shared/types\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { SecurityIncidentReporter } from \"../../../data/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport type { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport { cacheRemoteContainerCreatePolicyRepair } from \"./policyRepair\";\n\nexport interface ContainerCreateRepairState {\n didRepairStaleParent: boolean;\n policyRepairs: PrincipalPolicyRepairBudget;\n}\n\nexport interface RemoteContainerCreateInput {\n apiClient: ContainerCreateApi;\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql: ExecSql;\n metadataDocumentId?: string | undefined;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n parentSecretKey: Uint8Array;\n reportSecurityIncident: SecurityIncidentReporter;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}\n\ntype ContainerCreateFailureRepair =\n | { readonly kind: \"none\" }\n | { readonly kind: \"unavailable\" }\n | {\n readonly kind: \"retry\";\n readonly parentProjection: ContainerWriterProjectionResponse;\n };\n\nexport async function submitRemoteContainerCreate(input: {\n readonly apiClient: ContainerCreateApi;\n readonly plan: ContainerCreatePlan;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly response: ContainerMutationResponse;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const result = await input.apiClient.createContainerResult(\n input.plan.request,\n {\n expectedPaymentRequiredOrganizationId: input.plan.state.organizationId,\n reportErrors: false,\n },\n );\n return result.ok ? { ok: true, response: result.data } : result;\n}\n\nexport async function repairContainerCreateFailure(input: {\n readonly apiClient: ContainerCreateApi;\n readonly execSql: ExecSql;\n readonly failure: ContainerMutationSubmitFailure;\n readonly parentContainerId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly state: ContainerCreateRepairState;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<ContainerCreateFailureRepair> {\n if (input.stillCurrent?.() === false) {\n return { kind: \"unavailable\" };\n }\n if (\n input.state.policyRepairs.take(input.failure.stalePrincipalPolicies) &&\n (await cacheRemoteContainerCreatePolicyRepair({\n apiClient: input.apiClient,\n execSql: input.execSql,\n failure: input.failure,\n organizationId: input.parentProjection.organizationId,\n reportSecurityIncident: input.reportSecurityIncident,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n }))\n ) {\n return { kind: \"retry\", parentProjection: input.parentProjection };\n }\n if (input.stillCurrent?.() === false) {\n return { kind: \"unavailable\" };\n }\n if (\n input.state.didRepairStaleParent ||\n !isStaleParentContainerPathFailure(input.failure)\n ) {\n return { kind: \"none\" };\n }\n input.state.didRepairStaleParent = true;\n input.apiClient.evictContainerWriterProjection(input.parentContainerId);\n const parentProjection = await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n );\n if (input.stillCurrent?.() === false) {\n return { kind: \"unavailable\" };\n }\n return parentProjection\n ? { kind: \"retry\", parentProjection }\n : { kind: \"unavailable\" };\n}\n"]}
1
+ {"version":3,"file":"createSubmission.js","sourceRoot":"","sources":["createSubmission.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iCAAiC,EAAE,MAAM,kDAAkD,CAAC;AAcrG,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAoC7E,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAIjD;IAQC,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,qBAAqB,CACxD,KAAK,CAAC,IAAI,CAAC,OAAO,EAClB;QACE,qCAAqC,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc;QACtE,YAAY,EAAE,KAAK;KACpB,CACF,CAAC;IACF,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AAClE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,KAUlD;IACC,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,MAAM,cAAc,GAClB,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC;QACjE,CAAC,MAAM,4BAA4B,CAAC;YAClC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,mBAAmB;YACxC,cAAc,EAAE,KAAK,CAAC,gBAAgB,CAAC,cAAc;YACrD,+BAA+B,EAAE,KAAK,CAAC,+BAA+B;YACtE,YAAY,EAAE,KAAK,CAAC,YAAY;SACjC,CAAC,CAAC,CAAC;IACN,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,IACE,KAAK,CAAC,KAAK,CAAC,oBAAoB;YAChC,CAAC,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC;YAEjD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC1B,KAAK,CAAC,KAAK,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAC1C,CAAC;IACD,8EAA8E;IAC9E,yEAAyE;IACzE,KAAK,CAAC,SAAS,CAAC,8BAA8B,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACxE,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,4BAA4B,CACzE,KAAK,CAAC,iBAAiB,CACxB,CAAC;IACF,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,gBAAgB;QACrB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,gBAAgB,EAAE;QACrC,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AAC9B,CAAC","sourcesContent":["import type {\n ContainerMutationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { isStaleParentContainerPathFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type {\n ContainerCreateApi,\n ContainerCreatePlan,\n ContainerMutationAuthor,\n ContainerMutationSubmitFailure,\n} from \"../../../data/containers/shared/types\";\nimport type {\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { SecurityIncidentReporter } from \"../../../data/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport { recoverPrincipalPolicyRepair } from \"../../principals/policyRepair\";\nimport type { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\n\nexport interface ContainerCreateRepairState {\n didRepairStaleParent: boolean;\n policyRepairs: PrincipalPolicyRepairBudget;\n}\n\nexport interface RemoteContainerCreateInput {\n apiClient: ContainerCreateApi;\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey?: Uint8Array | undefined;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n execSql: ExecSql;\n metadataDocumentId?: string | undefined;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n parentSecretKey: Uint8Array;\n reportSecurityIncident: SecurityIncidentReporter;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n signedAt?: string | undefined;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}\n\ntype ContainerCreateFailureRepair =\n | { readonly kind: \"none\" }\n | { readonly kind: \"unavailable\" }\n | {\n readonly kind: \"retry\";\n readonly parentProjection: ContainerWriterProjectionResponse;\n };\n\nexport async function submitRemoteContainerCreate(input: {\n readonly apiClient: ContainerCreateApi;\n readonly plan: ContainerCreatePlan;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly response: ContainerMutationResponse;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const result = await input.apiClient.createContainerResult(\n input.plan.request,\n {\n expectedPaymentRequiredOrganizationId: input.plan.state.organizationId,\n reportErrors: false,\n },\n );\n return result.ok ? { ok: true, response: result.data } : result;\n}\n\nexport async function repairContainerCreateFailure(input: {\n readonly apiClient: ContainerCreateApi;\n readonly failure: ContainerMutationSubmitFailure;\n readonly parentContainerId: string;\n readonly parentProjection: ContainerWriterProjectionResponse;\n readonly state: ContainerCreateRepairState;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<ContainerCreateFailureRepair> {\n if (input.stillCurrent?.() === false) {\n return { kind: \"unavailable\" };\n }\n const repairedPolicy =\n input.state.policyRepairs.take(input.failure.stalePrincipalHeads) &&\n (await recoverPrincipalPolicyRepair({\n heads: input.failure.stalePrincipalHeads,\n organizationId: input.parentProjection.organizationId,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n stillCurrent: input.stillCurrent,\n }));\n if (input.stillCurrent?.() === false) {\n return { kind: \"unavailable\" };\n }\n if (!repairedPolicy) {\n if (\n input.state.didRepairStaleParent ||\n !isStaleParentContainerPathFailure(input.failure)\n )\n return { kind: \"none\" };\n input.state.didRepairStaleParent = true;\n }\n // Recovery may select newer policies. Rebuild against a fresh public evidence\n // source so the old projection cannot conflict with newly admitted pins.\n input.apiClient.evictContainerWriterProjection(input.parentContainerId);\n const parentProjection = await input.apiClient.getContainerWriterProjection(\n input.parentContainerId,\n );\n if (input.stillCurrent?.() === false) {\n return { kind: \"unavailable\" };\n }\n return parentProjection\n ? { kind: \"retry\", parentProjection }\n : { kind: \"unavailable\" };\n}\n"]}
@@ -0,0 +1,82 @@
1
+ import { assertProjectionVerificationCurrent } from "../../../data/keyingProjectionVerification/types.js";
2
+ import { commitCurrentGroupPolicyMutation } from "../../organizations/commitCurrentGroupPolicyMutation.js";
3
+ import { createRuntimeGroupMetadataAccess } from "../../organizations/groupMetadataRuntime.js";
4
+ import { buildSetGroupContainerGrantPolicyRequest } from "../../organizations/groupPolicyRequests.js";
5
+ import { preparePrincipalContainerRematerializationBatch, } from "../../organizations/principalContainerRematerialization.js";
6
+ import { groupPolicyNameMismatch } from "../../organizations/principalPolicyRequest.js";
7
+ import { GroupShareNameMismatchError } from "./sharePrincipalPolicy.js";
8
+ /** Fresh mutation authority rechecks the chosen name before authoring a grant. */
9
+ export async function commitCurrentShareGrant(input) {
10
+ const share = input.share;
11
+ const expectedName = share.expectedGroupName;
12
+ if (expectedName === null)
13
+ throw new Error("Minting a group grant requires the chosen group name; only a re-wrap of an existing signed grant may omit it");
14
+ const signingKeyPair = share.signingKeyPair;
15
+ if (!signingKeyPair)
16
+ throw new Error("Container group share requires principal policy signing context");
17
+ return input.mutate({
18
+ groupId: share.recipientGroupId,
19
+ organizationId: share.author.organizationId,
20
+ signerUserId: share.author.signerUserId,
21
+ stillCurrent: share.stillCurrent ?? (() => true),
22
+ }, async (context) => {
23
+ await assertCurrentShareGrantName(input.runtime, share, context, expectedName);
24
+ const request = await buildSetGroupContainerGrantPolicyRequest({
25
+ ...context,
26
+ accessLevel: share.accessLevel,
27
+ containerId: share.containerId,
28
+ signerUserId: share.author.signerUserId,
29
+ signingFingerprint: share.author.signerKeyFingerprint,
30
+ signingKeyPair,
31
+ });
32
+ const prepared = {};
33
+ const response = await commitCurrentGroupPolicyMutation({
34
+ apiClient: share.apiClient,
35
+ context,
36
+ groupId: share.recipientGroupId,
37
+ organizationId: share.author.organizationId,
38
+ request,
39
+ signerUserId: share.author.signerUserId,
40
+ signingFingerprint: share.author.signerKeyFingerprint,
41
+ signingKeyPair,
42
+ resolveTrustedUserIdentity: share.resolveTrustedUserIdentity,
43
+ prepareContainerMutations: async (nextPolicy) => {
44
+ prepared.batch = await prepareCurrentShareGrantBatch(share, context, nextPolicy, input.recitationStillCurrent);
45
+ return prepared.batch;
46
+ },
47
+ });
48
+ const index = prepared.batch?.plans.findIndex((planned) => planned.plan.containerId === share.containerId) ?? -1;
49
+ const plan = prepared.batch?.plans[index];
50
+ const acknowledgement = response.containerMutations[index];
51
+ if (!plan || !acknowledgement || !isSharePlan(plan))
52
+ throw new Error("Container group share acknowledgement is incomplete");
53
+ return {
54
+ containerKey: plan.containerKey,
55
+ plan: plan.plan,
56
+ response: acknowledgement,
57
+ };
58
+ });
59
+ }
60
+ function isSharePlan(plan) {
61
+ return plan.plan.body.eventType === "container.grant";
62
+ }
63
+ async function assertCurrentShareGrantName(runtime, share, context, expectedName) {
64
+ const mismatch = await groupPolicyNameMismatch(context.currentPolicy, expectedName, createRuntimeGroupMetadataAccess(runtime, share.author.organizationId, context.stillCurrent, context.verifyMetadataContainer).readName);
65
+ if (mismatch)
66
+ throw new GroupShareNameMismatchError("Container share group name does not match the signed group policy");
67
+ assertProjectionVerificationCurrent(context.stillCurrent);
68
+ }
69
+ function prepareCurrentShareGrantBatch(share, context, nextPolicy, recitationStillCurrent) {
70
+ return preparePrincipalContainerRematerializationBatch({
71
+ ...share,
72
+ grants: [
73
+ ...new Map([...context.currentPolicy.currentGrants, ...nextPolicy.grants].map((grant) => [grant.containerId, grant])).values(),
74
+ ],
75
+ groupId: share.recipientGroupId,
76
+ nextPolicy,
77
+ resolveAuthoredPolicyReferences: context.resolveAuthoredPolicyReferences,
78
+ stillCurrent: context.stillCurrent,
79
+ recitationStillCurrent,
80
+ });
81
+ }
82
+ //# sourceMappingURL=currentShareGrantMutation.js.map