@tearleads/client-sdk 0.1.64 → 0.1.65

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 (622) hide show
  1. package/client/organizations/organizationAccessRestoration.js +1 -1
  2. package/data/containers/shared/mutationAcknowledgement.js +1 -1
  3. package/data/containers/shared/mutationAcknowledgement.js.map +1 -1
  4. package/data/documents/blob/shared/projection.js +3 -3
  5. package/data/documents/blob/shared/projection.js.map +1 -1
  6. package/data/documents/shared/{containerKekCurrency.d.ts → containerKek/containerKekCurrency.d.ts} +1 -1
  7. package/data/documents/shared/{containerKekEntryVerification.js → containerKek/containerKekEntryVerification.js} +1 -1
  8. package/data/documents/shared/{containerKekLogFetch.d.ts → containerKek/containerKekLogFetch.d.ts} +1 -1
  9. package/data/documents/shared/{containerKekLogFetch.js → containerKek/containerKekLogFetch.js} +1 -1
  10. package/data/documents/shared/{containerKekPath.js → containerKek/containerKekPath.js} +3 -3
  11. package/data/documents/shared/containerKek/containerKekPath.js.map +1 -0
  12. package/data/documents/shared/{containerKekPathHistory.d.ts → containerKek/containerKekPathHistory.d.ts} +3 -3
  13. package/data/documents/shared/{containerKekPathHistory.js → containerKek/containerKekPathHistory.js} +4 -4
  14. package/data/documents/shared/containerKek/containerKekPathHistory.js.map +1 -0
  15. package/data/documents/shared/{containerKekPathVerification.d.ts → containerKek/containerKekPathVerification.d.ts} +5 -5
  16. package/data/documents/shared/{containerKekPathVerification.js → containerKek/containerKekPathVerification.js} +2 -2
  17. package/data/documents/shared/containerKek/containerKekPathVerification.js.map +1 -0
  18. package/data/documents/shared/{containerKekWrapping.js → containerKek/containerKekWrapping.js} +3 -3
  19. package/data/documents/shared/containerKek/containerKekWrapping.js.map +1 -0
  20. package/data/documents/shared/{keyringLogWalk.d.ts → containerKek/keyringLogWalk.d.ts} +2 -2
  21. package/data/documents/shared/{keyringLogWalk.js → containerKek/keyringLogWalk.js} +1 -1
  22. package/data/documents/shared/{keyringRebuild.d.ts → containerKek/keyringRebuild.d.ts} +3 -3
  23. package/data/documents/shared/{keyringRebuild.js → containerKek/keyringRebuild.js} +3 -3
  24. package/data/documents/shared/containerKek/keyringRebuild.js.map +1 -0
  25. package/data/documents/shared/crypto.js +2 -2
  26. package/data/documents/shared/crypto.js.map +1 -1
  27. package/data/documents/shared/events.js +1 -1
  28. package/data/documents/shared/{projection.d.ts → projection/index.d.ts} +7 -7
  29. package/data/documents/shared/{projection.js → projection/index.js} +9 -9
  30. package/data/documents/shared/projection/index.js.map +1 -0
  31. package/data/documents/shared/{projectionContentKeys.d.ts → projection/projectionContentKeys.d.ts} +6 -6
  32. package/data/documents/shared/{projectionContentKeys.js → projection/projectionContentKeys.js} +9 -9
  33. package/data/documents/shared/projection/projectionContentKeys.js.map +1 -0
  34. package/data/documents/shared/{projectionTargets.d.ts → projection/projectionTargets.d.ts} +4 -4
  35. package/data/documents/shared/{projectionTargets.js → projection/projectionTargets.js} +3 -3
  36. package/data/documents/shared/projection/projectionTargets.js.map +1 -0
  37. package/data/documents/shared/responses.d.ts +1 -1
  38. package/data/documents/shared/responses.js +1 -1
  39. package/data/documents/shared/responses.js.map +1 -1
  40. package/data/documents/shared/{documentSyncUpdateDecryption.js → sync/documentSyncUpdateDecryption.js} +10 -10
  41. package/data/documents/shared/sync/documentSyncUpdateDecryption.js.map +1 -0
  42. package/data/documents/shared/{documentSyncUpdateIsolation.d.ts → sync/documentSyncUpdateIsolation.d.ts} +3 -3
  43. package/data/documents/shared/{documentSyncUpdateIsolation.js → sync/documentSyncUpdateIsolation.js} +1 -1
  44. package/data/documents/shared/sync/documentSyncUpdateIsolation.js.map +1 -0
  45. package/data/documents/shared/{mutationAcknowledgement.js → sync/mutationAcknowledgement.js} +1 -1
  46. package/data/documents/shared/sync/mutationAcknowledgement.js.map +1 -0
  47. package/data/documents/shared/{pullContinuation.js → sync/pullContinuation.js} +1 -1
  48. package/data/documents/shared/{syncPagination.d.ts → sync/syncPagination.d.ts} +2 -2
  49. package/data/documents/shared/{syncPagination.js → sync/syncPagination.js} +1 -1
  50. package/data/documents/shared/sync/syncPagination.js.map +1 -0
  51. package/data/documents/shared/{syncResponseAuthorization.js → sync/syncResponseAuthorization.js} +3 -3
  52. package/data/documents/shared/sync/syncResponseAuthorization.js.map +1 -0
  53. package/data/documents/shared/{syncResponses.d.ts → sync/syncResponses.d.ts} +2 -2
  54. package/data/documents/shared/{syncResponses.js → sync/syncResponses.js} +6 -6
  55. package/data/documents/shared/sync/syncResponses.js.map +1 -0
  56. package/data/documents/shared/{syncSubmitFailure.d.ts → sync/syncSubmitFailure.d.ts} +1 -1
  57. package/data/documents/shared/types.d.ts +3 -3
  58. package/data/documents/shared/types.js.map +1 -1
  59. package/data/keyingProjectionVerification/checkpoints/accessManifestCheckpointEnforcement.js +1 -1
  60. package/data/keyingProjectionVerification/checkpoints/accessManifestCheckpointEnforcement.js.map +1 -1
  61. package/data/keyingProjectionVerification/checkpoints/checkpointContext.d.ts +1 -1
  62. package/data/keyingProjectionVerification/checkpoints/checkpointContext.js +1 -1
  63. package/data/keyingProjectionVerification/checkpoints/checkpointContext.js.map +1 -1
  64. package/data/keyingProjectionVerification/checkpoints/manifestCheckpointVerification.js +1 -1
  65. package/data/keyingProjectionVerification/checkpoints/manifestCheckpointVerification.js.map +1 -1
  66. package/data/keyingProjectionVerification/documentPurge/documentPurgeCheckpointCurrency.js +4 -4
  67. package/data/keyingProjectionVerification/documentPurge/documentPurgeCheckpointCurrency.js.map +1 -1
  68. package/data/keyingProjectionVerification/documentPurge/documentPurgeCheckpointEnforcement.js +1 -1
  69. package/data/keyingProjectionVerification/documentPurge/documentPurgeCheckpointEnforcement.js.map +1 -1
  70. package/data/keyingProjectionVerification/documentPurge/documentPurgePolicyCheckpoints.js +1 -1
  71. package/data/keyingProjectionVerification/documentPurge/documentPurgePolicyCheckpoints.js.map +1 -1
  72. package/data/keyingProjectionVerification/documentPurge/documentPurgePolicyCurrency.js +1 -1
  73. package/data/keyingProjectionVerification/documentPurge/documentPurgePolicyCurrency.js.map +1 -1
  74. package/data/keyingProjectionVerification/principalPolicy/principalPolicyCache.js +3 -3
  75. package/data/keyingProjectionVerification/principalPolicy/principalPolicyCache.js.map +1 -1
  76. package/data/keyingProjectionVerification/principalPolicy/principalPolicyVerification.js +4 -4
  77. package/data/keyingProjectionVerification/principalPolicy/principalPolicyVerification.js.map +1 -1
  78. package/data/keyingProjectionVerification/principalPolicy/resolvedPrincipalPolicy.js +2 -2
  79. package/data/keyingProjectionVerification/principalPolicy/resolvedPrincipalPolicy.js.map +1 -1
  80. package/data/persistence/container-contents/containerContentsPersistence.js +3 -3
  81. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  82. package/data/persistence/container-contents/containerContentsPersistenceTypes.d.ts +2 -2
  83. package/data/persistence/container-contents/containerContentsPersistenceTypes.js.map +1 -1
  84. package/data/persistence/container-contents/containerCreateIntentSettlement.js +1 -1
  85. package/data/persistence/container-contents/containerDeletionPersistence.js +2 -2
  86. package/data/persistence/container-contents/containerDocumentReassignment.js +2 -2
  87. package/data/persistence/container-contents/containerDocumentReassignment.js.map +1 -1
  88. package/data/persistence/container-contents/containerHydrationPersistence.js +3 -3
  89. package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
  90. package/data/persistence/container-contents/containerIntentPersistence.js +1 -1
  91. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +5 -5
  92. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  93. package/data/persistence/container-contents/containerMetadataPullContinuationPersistence.js +1 -1
  94. package/data/persistence/container-contents/containerMetadataRows.js +3 -3
  95. package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
  96. package/data/persistence/container-contents/containerMoveAbandonPersistence.js +1 -1
  97. package/data/persistence/container-contents/containerMoveIntentRows.js +1 -1
  98. package/data/persistence/container-contents/containerPendingUpdatePersistence.js +3 -3
  99. package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
  100. package/data/persistence/container-contents/containerRebindPersistence.js +1 -1
  101. package/data/persistence/container-contents/containerReconcilePersistence.js +2 -2
  102. package/data/persistence/container-contents/containerRecoveryPersistence.js +1 -1
  103. package/data/persistence/container-contents/containerRemovalWork.js +3 -3
  104. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  105. package/data/persistence/container-contents/containerStructuralRepair.js +1 -1
  106. package/data/persistence/container-contents/documentLinkRemovalRepair.js +2 -2
  107. package/data/persistence/container-contents/documentLinkRemovalRepair.js.map +1 -1
  108. package/data/persistence/container-contents/documentMoveIntentPersistence.js +2 -2
  109. package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
  110. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js +2 -2
  111. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js.map +1 -1
  112. package/data/persistence/container-contents/documentPurgePlacement.js +1 -1
  113. package/data/persistence/container-contents/dormantContainerMetadata.js +1 -1
  114. package/data/persistence/container-contents/dormantMetadataSweep.js +1 -1
  115. package/data/persistence/container-contents/pendingContainerCreate.js +1 -1
  116. package/data/persistence/container-contents/supersededContainerBindings.js +1 -1
  117. package/data/persistence/containers/containerPersistence.js +1 -1
  118. package/data/persistence/containers/containerSyncWatermarkPersistence.js +1 -1
  119. package/data/persistence/containers/documentContainerProjectionPersistence.js +1 -1
  120. package/data/persistence/containers/documentPlacement.js +1 -1
  121. package/data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js +1 -1
  122. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js +3 -3
  123. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js.map +1 -1
  124. package/data/persistence/documents/documentDiscoveryReset.js +1 -1
  125. package/data/persistence/documents/documentDiscoveryReset.js.map +1 -1
  126. package/data/persistence/documents/documentsPersistence.js +3 -3
  127. package/data/persistence/documents/documentsPersistence.js.map +1 -1
  128. package/data/persistence/documents/internal/attachmentStagingPersistence.js +1 -1
  129. package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js +1 -1
  130. package/data/persistence/documents/internal/containerDocumentTombstones.js +1 -1
  131. package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js +2 -2
  132. package/data/persistence/documents/internal/createDocumentWithHistoryCheckpoint.js.map +1 -1
  133. package/data/persistence/documents/internal/discardDocument.js +3 -3
  134. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  135. package/data/persistence/documents/internal/documentDeletionPersistence.js +4 -4
  136. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  137. package/data/persistence/documents/internal/documentMutationPersistence.js +5 -5
  138. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  139. package/data/persistence/documents/internal/documentProjectionRows.js +1 -1
  140. package/data/persistence/documents/internal/documentPullContinuationPersistence.js +1 -1
  141. package/data/persistence/documents/internal/documentRows.js +2 -2
  142. package/data/persistence/documents/internal/documentRows.js.map +1 -1
  143. package/data/persistence/documents/internal/documentSummaryQueries.js +1 -1
  144. package/data/persistence/documents/internal/ensureDocumentsSchema.js +2 -2
  145. package/data/persistence/documents/internal/hydratedAttachmentPersistence.js +1 -1
  146. package/data/persistence/documents/internal/orphanSideRows.js +2 -2
  147. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  148. package/data/persistence/documents/internal/pendingCreateAdoption.js +1 -1
  149. package/data/persistence/documents/internal/rowQueryPersistence.js +2 -2
  150. package/data/persistence/documents/internal/syncQueuePersistence.js +3 -3
  151. package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
  152. package/data/persistence/documents/types.d.ts +3 -3
  153. package/data/persistence/documents/types.js.map +1 -1
  154. package/data/persistence/{documentPurgeCheckpointPersistence.d.ts → keyingCheckpoints/documentPurgeCheckpointPersistence.d.ts} +2 -2
  155. package/data/persistence/{documentPurgeCheckpointPersistence.js → keyingCheckpoints/documentPurgeCheckpointPersistence.js} +4 -4
  156. package/data/persistence/keyingCheckpoints/documentPurgeCheckpointPersistence.js.map +1 -0
  157. package/data/persistence/{keyingCheckpointAdvancePersistence.js → keyingCheckpoints/keyingCheckpointAdvancePersistence.js} +9 -9
  158. package/data/persistence/keyingCheckpoints/keyingCheckpointAdvancePersistence.js.map +1 -0
  159. package/data/persistence/{keyingCheckpointEvidence.js → keyingCheckpoints/keyingCheckpointEvidence.js} +1 -1
  160. package/data/persistence/{keyingCheckpointPersistence.js → keyingCheckpoints/keyingCheckpointPersistence.js} +5 -5
  161. package/data/persistence/keyingCheckpoints/keyingCheckpointPersistence.js.map +1 -0
  162. package/data/persistence/{locallyAcknowledgedCheckpointPersistence.d.ts → keyingCheckpoints/locallyAcknowledgedCheckpointPersistence.d.ts} +4 -4
  163. package/data/persistence/{locallyAcknowledgedCheckpointPersistence.js → keyingCheckpoints/locallyAcknowledgedCheckpointPersistence.js} +7 -7
  164. package/data/persistence/keyingCheckpoints/locallyAcknowledgedCheckpointPersistence.js.map +1 -0
  165. package/data/persistence/{organizationReplacementCheckpointPersistence.js → keyingCheckpoints/organizationReplacementCheckpointPersistence.js} +6 -6
  166. package/data/persistence/keyingCheckpoints/organizationReplacementCheckpointPersistence.js.map +1 -0
  167. package/data/persistence/{principalAuthorizationCheckpoints.js → keyingCheckpoints/principalAuthorizationCheckpoints.js} +1 -1
  168. package/data/persistence/keyingCheckpoints/principalAuthorizationCheckpoints.js.map +1 -0
  169. package/data/persistence/organizationFounderPersistence.js +2 -2
  170. package/data/persistence/organizationFounderPersistence.js.map +1 -1
  171. package/data/persistence/organizations/organizationAccessRevocationPersistence.js +3 -3
  172. package/data/persistence/organizations/organizationAccessRevocationPersistence.js.map +1 -1
  173. package/data/persistence/organizations/organizationDataUsagePersistence.js +2 -2
  174. package/data/persistence/organizations/organizationDataUsagePersistence.js.map +1 -1
  175. package/data/persistence/organizations/organizationGroupNamePersistence.js +2 -2
  176. package/data/persistence/organizations/organizationGroupNamePersistence.js.map +1 -1
  177. package/data/persistence/organizations/organizationPresentationDenialPersistence.js +2 -2
  178. package/data/persistence/organizations/organizationPresentationDenialPersistence.js.map +1 -1
  179. package/data/persistence/organizations/organizationProfileDocumentPointers.js +2 -2
  180. package/data/persistence/organizations/organizationProfileDocumentPointers.js.map +1 -1
  181. package/data/persistence/organizations/organizationProvisioningAttemptPersistence.js +1 -1
  182. package/data/persistence/organizations/organizationProvisioningAttemptPersistence.js.map +1 -1
  183. package/data/persistence/organizations/organizationReadModelGrantPersistence.js +1 -1
  184. package/data/persistence/organizations/organizationReadModelGrantPersistence.js.map +1 -1
  185. package/data/persistence/organizations/organizationReadModelMemberLoad.js +1 -1
  186. package/data/persistence/organizations/organizationReadModelMemberLoad.js.map +1 -1
  187. package/data/persistence/organizations/organizationReadModelMembershipPersistence.js +1 -1
  188. package/data/persistence/organizations/organizationReadModelMembershipPersistence.js.map +1 -1
  189. package/data/persistence/organizations/organizationReadModelPersistence.js +3 -3
  190. package/data/persistence/organizations/organizationReadModelPersistence.js.map +1 -1
  191. package/data/persistence/organizations/organizationReadModelProjection.js +1 -1
  192. package/data/persistence/organizations/organizationReadModelProjection.js.map +1 -1
  193. package/data/persistence/organizations/organizationReadModelPurge.js +3 -3
  194. package/data/persistence/organizations/organizationReadModelPurge.js.map +1 -1
  195. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +3 -3
  196. package/data/persistence/principalCurrentAcknowledgementPersistence.js +10 -10
  197. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  198. package/data/persistence/{principalHistoryEvidencePersistence.d.ts → principalHistory/principalHistoryEvidencePersistence.d.ts} +4 -4
  199. package/data/persistence/{principalHistoryEvidencePersistence.js → principalHistory/principalHistoryEvidencePersistence.js} +7 -7
  200. package/data/persistence/principalHistory/principalHistoryEvidencePersistence.js.map +1 -0
  201. package/data/persistence/{principalHistoryIncompleteRetention.js → principalHistory/principalHistoryIncompleteRetention.js} +1 -1
  202. package/data/persistence/principalHistory/principalHistoryIncompleteRetention.js.map +1 -0
  203. package/data/persistence/{principalHistoryNodeRetention.js → principalHistory/principalHistoryNodeRetention.js} +4 -4
  204. package/data/persistence/principalHistory/principalHistoryNodeRetention.js.map +1 -0
  205. package/data/persistence/{principalHistoryPrefixPersistence.d.ts → principalHistory/principalHistoryPrefixPersistence.d.ts} +2 -2
  206. package/data/persistence/{principalHistoryPrefixPersistence.js → principalHistory/principalHistoryPrefixPersistence.js} +6 -6
  207. package/data/persistence/principalHistory/principalHistoryPrefixPersistence.js.map +1 -0
  208. package/data/persistence/{principalHistoryRootOwnership.js → principalHistory/principalHistoryRootOwnership.js} +1 -1
  209. package/data/persistence/principalHistory/principalHistoryRootOwnership.js.map +1 -0
  210. package/data/persistence/{principalHistoryStagePersistence.d.ts → principalHistory/principalHistoryStagePersistence.d.ts} +2 -2
  211. package/data/persistence/{principalHistoryStagePersistence.js → principalHistory/principalHistoryStagePersistence.js} +6 -6
  212. package/data/persistence/principalHistory/principalHistoryStagePersistence.js.map +1 -0
  213. package/data/persistence/{principalHistoryStageRetention.js → principalHistory/principalHistoryStageRetention.js} +2 -2
  214. package/data/persistence/principalHistory/principalHistoryStageRetention.js.map +1 -0
  215. package/data/persistence/{principalHistoryUnpublishedRetention.js → principalHistory/principalHistoryUnpublishedRetention.js} +3 -3
  216. package/data/persistence/principalHistory/principalHistoryUnpublishedRetention.js.map +1 -0
  217. package/data/persistence/{principalGrantRetirementPersistence.d.ts → principalKeys/principalGrantRetirementPersistence.d.ts} +2 -2
  218. package/data/persistence/{principalGrantRetirementPersistence.js → principalKeys/principalGrantRetirementPersistence.js} +2 -2
  219. package/data/persistence/principalKeys/principalGrantRetirementPersistence.js.map +1 -0
  220. package/data/persistence/{principalKeyEnvelopeArchivePersistence.js → principalKeys/principalKeyEnvelopeArchivePersistence.js} +3 -3
  221. package/data/persistence/principalKeys/principalKeyEnvelopeArchivePersistence.js.map +1 -0
  222. package/data/persistence/{principalKeyEnvelopeCandidates.js → principalKeys/principalKeyEnvelopeCandidates.js} +9 -9
  223. package/data/persistence/principalKeys/principalKeyEnvelopeCandidates.js.map +1 -0
  224. package/data/persistence/principalMutationJournalPersistence.d.ts +1 -1
  225. package/data/persistence/principalMutationJournalPersistence.js +1 -1
  226. package/data/persistence/principalMutationJournalPersistence.js.map +1 -1
  227. package/data/persistence/{principalPolicyBundleIntegrity.js → principalPolicy/principalPolicyBundleIntegrity.js} +3 -3
  228. package/data/persistence/principalPolicy/principalPolicyBundleIntegrity.js.map +1 -0
  229. package/data/persistence/{principalPolicyCheckpointSelection.js → principalPolicy/principalPolicyCheckpointSelection.js} +2 -2
  230. package/data/persistence/principalPolicy/principalPolicyCheckpointSelection.js.map +1 -0
  231. package/data/persistence/{principalPolicyOrganizationPersistence.js → principalPolicy/principalPolicyOrganizationPersistence.js} +2 -2
  232. package/data/persistence/principalPolicy/principalPolicyOrganizationPersistence.js.map +1 -0
  233. package/data/persistence/{principalPolicyPersistence.js → principalPolicy/principalPolicyPersistence.js} +5 -5
  234. package/data/persistence/principalPolicy/principalPolicyPersistence.js.map +1 -0
  235. package/data/persistence/{principalPolicyReferenceCheckpoint.js → principalPolicy/principalPolicyReferenceCheckpoint.js} +3 -3
  236. package/data/persistence/principalPolicy/principalPolicyReferenceCheckpoint.js.map +1 -0
  237. package/data/persistence/{principalPolicyReferenceIndexPersistence.js → principalPolicy/principalPolicyReferenceIndexPersistence.js} +4 -4
  238. package/data/persistence/principalPolicy/principalPolicyReferenceIndexPersistence.js.map +1 -0
  239. package/data/persistence/{principalPolicyReferencePersistence.js → principalPolicy/principalPolicyReferencePersistence.js} +5 -5
  240. package/data/persistence/principalPolicy/principalPolicyReferencePersistence.js.map +1 -0
  241. package/data/persistence/{verifiedPrincipalPolicyBundle.js → principalPolicy/verifiedPrincipalPolicyBundle.js} +2 -2
  242. package/data/persistence/principalPolicy/verifiedPrincipalPolicyBundle.js.map +1 -0
  243. package/data/persistence/{verifiedPrincipalPolicyCurrent.js → principalPolicy/verifiedPrincipalPolicyCurrent.js} +2 -2
  244. package/data/persistence/principalPolicy/verifiedPrincipalPolicyCurrent.js.map +1 -0
  245. package/data/persistence/{verifiedPrincipalPolicyRetentionPersistence.js → principalPolicy/verifiedPrincipalPolicyRetentionPersistence.js} +1 -1
  246. package/data/persistence/principalPolicy/verifiedPrincipalPolicyRetentionPersistence.js.map +1 -0
  247. package/data/persistence/securityIncidentPersistence.js +1 -1
  248. package/data/persistence/securityIncidentPersistence.js.map +1 -1
  249. package/data/persistence/trustedUserIdentityPinPersistence.js +1 -1
  250. package/data/persistence/verifiedManifestBundlePersistence.d.ts +1 -1
  251. package/data/persistence/verifiedManifestBundlePersistence.js +4 -4
  252. package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -1
  253. package/data/principals/organizationGroupRoles.js +2 -2
  254. package/data/principals/organizationGroupRoles.js.map +1 -1
  255. package/data/principals/principalHistoryPrefixProtection.js.map +1 -1
  256. package/data/principals/principalHistoryStageProtection.js.map +1 -1
  257. package/data/principals/principalPolicyCrypto.js +1 -1
  258. package/data/principals/principalPolicyCrypto.js.map +1 -1
  259. package/data/sqlite/{documentHistoryPersistence.d.ts → documentPersistence/documentHistoryPersistence.d.ts} +1 -1
  260. package/data/sqlite/{documentHistoryPersistence.js → documentPersistence/documentHistoryPersistence.js} +5 -5
  261. package/data/sqlite/documentPersistence/documentHistoryPersistence.js.map +1 -0
  262. package/data/sqlite/{documentOrphanBlobReclaims.js → documentPersistence/documentOrphanBlobReclaims.js} +1 -1
  263. package/data/sqlite/documentPersistence/documentOrphanBlobReclaims.js.map +1 -0
  264. package/data/sqlite/{documentPendingUpdatePersistence.d.ts → documentPersistence/documentPendingUpdatePersistence.d.ts} +2 -2
  265. package/data/sqlite/{documentPendingUpdatePersistence.js → documentPersistence/documentPendingUpdatePersistence.js} +2 -2
  266. package/data/sqlite/documentPersistence/documentPendingUpdatePersistence.js.map +1 -0
  267. package/data/sqlite/{documentPersistenceTypes.d.ts → documentPersistence/documentPersistenceTypes.d.ts} +2 -2
  268. package/data/sqlite/documentPersistence/documentPersistenceTypes.js.map +1 -0
  269. package/data/sqlite/{documentRecordPersistence.d.ts → documentPersistence/documentRecordPersistence.d.ts} +1 -1
  270. package/data/sqlite/{documentRecordPersistence.js → documentPersistence/documentRecordPersistence.js} +4 -4
  271. package/data/sqlite/documentPersistence/documentRecordPersistence.js.map +1 -0
  272. package/data/sqlite/{documentSyncFailurePersistence.d.ts → documentPersistence/documentSyncFailurePersistence.d.ts} +2 -2
  273. package/data/sqlite/{documentSyncFailurePersistence.js → documentPersistence/documentSyncFailurePersistence.js} +3 -3
  274. package/data/sqlite/documentPersistence/documentSyncFailurePersistence.js.map +1 -0
  275. package/data/sqlite/{documentPersistence.d.ts → documentPersistence/index.d.ts} +2 -2
  276. package/data/sqlite/{documentPersistence.js → documentPersistence/index.js} +5 -5
  277. package/data/sqlite/documentPersistence/index.js.map +1 -0
  278. package/data/sqlite/{containerSchema.d.ts → schema/containerSchema.d.ts} +1 -1
  279. package/data/sqlite/{containerSchema.js → schema/containerSchema.js} +1 -1
  280. package/data/sqlite/schema/containerSchema.js.map +1 -0
  281. package/data/sqlite/{schema.d.ts → schema/index.d.ts} +1 -1
  282. package/data/sqlite/{schema.js → schema/index.js} +3 -3
  283. package/data/sqlite/schema/index.js.map +1 -0
  284. package/data/sqlite/{organizationDataUsageSchema.js → schema/organizationDataUsageSchema.js} +1 -1
  285. package/data/sqlite/schema/organizationDataUsageSchema.js.map +1 -0
  286. package/data/sqlite/{organizationProvisioningAttemptSchema.js → schema/organizationProvisioningAttemptSchema.js} +1 -1
  287. package/data/sqlite/schema/organizationProvisioningAttemptSchema.js.map +1 -0
  288. package/data/sqlite/{organizationReadModelTableRegistry.d.ts → schema/organizationReadModelTableRegistry.d.ts} +1 -1
  289. package/data/sqlite/{organizationReadModelTableRegistry.js → schema/organizationReadModelTableRegistry.js} +1 -1
  290. package/data/sqlite/schema/organizationReadModelTableRegistry.js.map +1 -0
  291. package/data/sqlite/{principalHistoryEvidenceSchema.d.ts → schema/principalHistoryEvidenceSchema.d.ts} +1 -1
  292. package/data/sqlite/{principalHistoryEvidenceSchema.js → schema/principalHistoryEvidenceSchema.js} +2 -2
  293. package/data/sqlite/schema/principalHistoryEvidenceSchema.js.map +1 -0
  294. package/data/sqlite/{principalHistoryNodeRetentionSchema.js → schema/principalHistoryNodeRetentionSchema.js} +1 -1
  295. package/data/sqlite/schema/principalHistoryNodeRetentionSchema.js.map +1 -0
  296. package/data/sqlite/{principalHistoryRetentionSchema.js → schema/principalHistoryRetentionSchema.js} +1 -1
  297. package/data/sqlite/{principalHistoryRetentionSchema.js.map → schema/principalHistoryRetentionSchema.js.map} +1 -1
  298. package/data/sqlite/{principalHistoryStageSchema.d.ts → schema/principalHistoryStageSchema.d.ts} +1 -1
  299. package/data/sqlite/{principalHistoryStageSchema.js → schema/principalHistoryStageSchema.js} +2 -2
  300. package/data/sqlite/schema/principalHistoryStageSchema.js.map +1 -0
  301. package/data/sqlite/{principalMutationJournalSchema.d.ts → schema/principalMutationJournalSchema.d.ts} +1 -1
  302. package/data/sqlite/{principalMutationJournalSchema.js → schema/principalMutationJournalSchema.js} +1 -1
  303. package/data/sqlite/{principalMutationJournalSchema.js.map → schema/principalMutationJournalSchema.js.map} +1 -1
  304. package/data/sqlite/{principalPolicySchema.js → schema/principalPolicySchema.js} +1 -1
  305. package/data/sqlite/schema/principalPolicySchema.js.map +1 -0
  306. package/data/sqlite/{securityIncidentSchema.d.ts → schema/securityIncidentSchema.d.ts} +1 -1
  307. package/data/sqlite/{securityIncidentSchema.js → schema/securityIncidentSchema.js} +1 -1
  308. package/data/sqlite/schema/securityIncidentSchema.js.map +1 -0
  309. package/data/sqlite/{verifiedManifestBundleSchema.d.ts → schema/verifiedManifestBundleSchema.d.ts} +1 -1
  310. package/data/sqlite/{verifiedManifestBundleSchema.js → schema/verifiedManifestBundleSchema.js} +1 -1
  311. package/data/sqlite/schema/verifiedManifestBundleSchema.js.map +1 -0
  312. package/data/sqlite/sqlitePersistenceRuntime.d.ts +1 -1
  313. package/data/sqlite/sqlitePersistenceRuntime.js +1 -1
  314. package/package.json +1 -1
  315. package/sqlite/index.d.ts +1 -1
  316. package/sqlite/index.js +1 -1
  317. package/stores/documents/documentStore/history/historyRebuild.js +1 -1
  318. package/stores/documents/documentStore/history/historyRebuild.js.map +1 -1
  319. package/stores/documents/documentStore/state.js.map +1 -1
  320. package/stores/documents/documentStore/sync/syncFinalize.js +1 -1
  321. package/stores/documents/documentStore/sync/syncFinalize.js.map +1 -1
  322. package/stores/documents/documentStore/sync/syncUpdateImport.js +1 -1
  323. package/stores/documents/documentStore/sync/syncUpdateImport.js.map +1 -1
  324. package/workflows/blobs/detach.js +1 -1
  325. package/workflows/blobs/hydration/decrypt.js +1 -1
  326. package/workflows/blobs/upload/index.js +1 -1
  327. package/workflows/blobs/verification/retainedAttachmentVerification.js +1 -1
  328. package/workflows/blobs/verification/writerProjection.js +1 -1
  329. package/workflows/container-contents/container-state/create/createWithMetadata.js +2 -2
  330. package/workflows/container-contents/container-state/create/createWithMetadata.js.map +1 -1
  331. package/workflows/container-contents/container-state/share/index.js +1 -1
  332. package/workflows/container-contents/documentLinks/index.js +1 -1
  333. package/workflows/container-contents/documentMove/documentMoveVanishedRefresh.js +1 -1
  334. package/workflows/container-contents/documentPriming/documentHydrationProbe.js +1 -1
  335. package/workflows/container-contents/documentPriming/index.js +1 -1
  336. package/workflows/container-contents/documentQueries/index.js +1 -1
  337. package/workflows/container-contents/documentQueries/sql.js +1 -1
  338. package/workflows/container-contents/info/blobInfo.js +1 -1
  339. package/workflows/container-contents/info/containerInfo.js +1 -1
  340. package/workflows/container-contents/info/documentInfo.js +1 -1
  341. package/workflows/container-contents/metadata/index.js +1 -1
  342. package/workflows/container-contents/metadata/index.js.map +1 -1
  343. package/workflows/container-contents/metadata/metadataEvents.d.ts +1 -1
  344. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js +2 -2
  345. package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -1
  346. package/workflows/container-contents/metadata/metadataMutationPreparation.js +1 -1
  347. package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -1
  348. package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js +1 -1
  349. package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js.map +1 -1
  350. package/workflows/container-contents/metadata/metadataRemoteSync.d.ts +1 -1
  351. package/workflows/container-contents/metadata/metadataSyncErrors.js +1 -1
  352. package/workflows/container-contents/metadata/metadataSyncErrors.js.map +1 -1
  353. package/workflows/container-contents/metadata/metadataSyncSettlement.d.ts +1 -1
  354. package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -1
  355. package/workflows/container-contents/metadata/metadataTypes.d.ts +1 -1
  356. package/workflows/container-contents/metadata/metadataTypes.js.map +1 -1
  357. package/workflows/container-contents/pendingWrites/index.js +2 -2
  358. package/workflows/container-contents/pendingWrites/sources.js +1 -1
  359. package/workflows/container-contents/remoteHydration/destination/replacementBinding.js +1 -1
  360. package/workflows/container-contents/remoteHydration/destination/replacementBinding.js.map +1 -1
  361. package/workflows/container-contents/remoteHydration/reattachMetadata.js.map +1 -1
  362. package/workflows/container-contents/tombstones/documentTombstoneEvidence.js +2 -2
  363. package/workflows/container-contents/tombstones/documentTombstoneEvidence.js.map +1 -1
  364. package/workflows/containers/child/create/index.js +2 -2
  365. package/workflows/containers/child/create/index.js.map +1 -1
  366. package/workflows/containers/child/move/index.js +1 -1
  367. package/workflows/containers/child/move/moveRotation.js +1 -1
  368. package/workflows/containers/child/move/moveRotation.js.map +1 -1
  369. package/workflows/containers/child/move/moveWraps.js +1 -1
  370. package/workflows/containers/child/move/moveWraps.js.map +1 -1
  371. package/workflows/containers/child/recite.js +2 -2
  372. package/workflows/containers/child/recite.js.map +1 -1
  373. package/workflows/containers/child/rotation/rotationContext.js +3 -3
  374. package/workflows/containers/child/rotation/rotationContext.js.map +1 -1
  375. package/workflows/containers/child/share/currentSharePrincipalPolicy.js +1 -1
  376. package/workflows/containers/child/share/currentSharePrincipalPolicy.js.map +1 -1
  377. package/workflows/containers/child/share/index.js +1 -1
  378. package/workflows/containers/child/share/index.js.map +1 -1
  379. package/workflows/containers/child/share/shareAncestorRepair.js +2 -2
  380. package/workflows/containers/child/share/shareAncestorRepair.js.map +1 -1
  381. package/workflows/containers/child/share/shareMaterialization.js +1 -1
  382. package/workflows/containers/child/share/sharePrincipalPolicy.js +5 -5
  383. package/workflows/containers/child/share/sharePrincipalPolicy.js.map +1 -1
  384. package/workflows/containers/index.d.ts +3 -3
  385. package/workflows/containers/index.js +2 -2
  386. package/workflows/containers/index.js.map +1 -1
  387. package/workflows/containers/writeRefusal.js +1 -1
  388. package/workflows/containers/writeRefusal.js.map +1 -1
  389. package/workflows/documents/create/createAdoption.js +1 -1
  390. package/workflows/documents/create/createResponse.js +2 -2
  391. package/workflows/documents/create/createResponse.js.map +1 -1
  392. package/workflows/documents/create/index.js +1 -1
  393. package/workflows/documents/documentMutationCommit.d.ts +1 -1
  394. package/workflows/documents/documentMutationPreparation.d.ts +1 -1
  395. package/workflows/documents/documentMutationPreparation.js +1 -1
  396. package/workflows/documents/documentMutationPreparation.js.map +1 -1
  397. package/workflows/documents/index.d.ts +5 -5
  398. package/workflows/documents/index.js +5 -5
  399. package/workflows/documents/index.js.map +1 -1
  400. package/workflows/documents/linkSet/index.js +2 -2
  401. package/workflows/documents/linkSet/index.js.map +1 -1
  402. package/workflows/documents/linkSet/linkSetAuthority.js +1 -1
  403. package/workflows/documents/linkSet/linkSetBlobRewraps.js +1 -1
  404. package/workflows/documents/linkSet/linkSetProjectionSeed.js +1 -1
  405. package/workflows/documents/linkSet/linkSetRemote.js +1 -1
  406. package/workflows/documents/linkSet/linkSetRemote.js.map +1 -1
  407. package/workflows/documents/purge/index.js +1 -1
  408. package/workflows/documents/sync/index.js +2 -2
  409. package/workflows/documents/sync/index.js.map +1 -1
  410. package/workflows/documents/sync/initialSync.js +1 -1
  411. package/workflows/documents/sync/readOnlyProjectionFailure.js +1 -1
  412. package/workflows/documents/sync/readOnlyProjectionFailure.js.map +1 -1
  413. package/workflows/documents/sync/readOnlySync.d.ts +3 -3
  414. package/workflows/documents/sync/readOnlySync.js +1 -1
  415. package/workflows/documents/sync/readOnlySync.js.map +1 -1
  416. package/workflows/documents/sync/reportDocumentSyncQuarantine.js.map +1 -1
  417. package/workflows/documents/sync/syncAttemptPlanning.js +2 -2
  418. package/workflows/documents/sync/syncAttemptPlanning.js.map +1 -1
  419. package/workflows/documents/sync/syncAttemptState.d.ts +2 -2
  420. package/workflows/documents/sync/syncAttemptState.js.map +1 -1
  421. package/workflows/documents/sync/syncResponseResult.js +2 -2
  422. package/workflows/documents/sync/syncResponseResult.js.map +1 -1
  423. package/workflows/documents/syncFailures/index.js +1 -1
  424. package/workflows/documents/syncFailures/index.js.map +1 -1
  425. package/workflows/documents/syncFailures/syncAbandon.js.map +1 -1
  426. package/workflows/documents/syncFailures/syncFailureClassification.js +1 -1
  427. package/workflows/documents/syncFailures/syncFailureClassification.js.map +1 -1
  428. package/workflows/documents/syncPlan/syncContentKeys.d.ts +1 -1
  429. package/workflows/documents/syncPlan/syncContentKeys.js +3 -3
  430. package/workflows/documents/syncPlan/syncContentKeys.js.map +1 -1
  431. package/workflows/documents/syncPlan/syncPlanMaterial.js +2 -2
  432. package/workflows/documents/syncPlan/syncPlanMaterial.js.map +1 -1
  433. package/workflows/documents/syncRekeys/syncAutomaticContainerRekeys.js +2 -2
  434. package/workflows/documents/syncRekeys/syncAutomaticContainerRekeys.js.map +1 -1
  435. package/workflows/documents/syncRekeys/syncContainerRekeyPreparation.js +1 -1
  436. package/workflows/documents/syncRekeys/syncRecoveryRekey.d.ts +1 -1
  437. package/workflows/documents/syncRekeys/syncRecoveryRekey.js +1 -1
  438. package/workflows/organizations/currentOrganizationAuthority.js +2 -2
  439. package/workflows/organizations/currentOrganizationAuthority.js.map +1 -1
  440. package/workflows/organizations/groupMetadata/groupMetadataAccess.js +1 -1
  441. package/workflows/organizations/groupMetadata/groupMetadataAccess.js.map +1 -1
  442. package/workflows/organizations/groupMetadata/groupMetadataContainerAuthority.js +1 -1
  443. package/workflows/organizations/groupMetadata/groupMetadataContainerAuthority.js.map +1 -1
  444. package/workflows/organizations/groupNames/currentOrganizationGroupNames.js +1 -1
  445. package/workflows/organizations/groupNames/currentOrganizationGroupNames.js.map +1 -1
  446. package/workflows/organizations/groupNames/groupNameUniqueness.js +3 -3
  447. package/workflows/organizations/groupNames/groupNameUniqueness.js.map +1 -1
  448. package/workflows/organizations/groupNames/organizationGroupNamePolicies.js +2 -2
  449. package/workflows/organizations/groupNames/organizationGroupNamePolicies.js.map +1 -1
  450. package/workflows/organizations/groupPolicy/currentGroupPolicyMutationContext.js +1 -1
  451. package/workflows/organizations/groupPolicy/currentGroupPolicyMutationContext.js.map +1 -1
  452. package/workflows/organizations/groupPolicy/groupPolicyMutationContext.js +2 -2
  453. package/workflows/organizations/groupPolicy/groupPolicyMutationContext.js.map +1 -1
  454. package/workflows/organizations/groupPolicy/groupPolicyMutationEvidence.js +1 -1
  455. package/workflows/organizations/groupPolicy/groupPolicyMutationEvidence.js.map +1 -1
  456. package/workflows/organizations/groupPolicy/groupPolicyVerification.js +1 -1
  457. package/workflows/organizations/groupPolicy/groupPolicyVerification.js.map +1 -1
  458. package/workflows/organizations/groups/createCurrentOrganizationGroup.js +1 -1
  459. package/workflows/organizations/groups/createCurrentOrganizationGroup.js.map +1 -1
  460. package/workflows/organizations/groups/deleteOrganizationGroup.js +1 -1
  461. package/workflows/organizations/groups/deleteOrganizationGroup.js.map +1 -1
  462. package/workflows/organizations/groups/organizationGroupDirectory.js +1 -1
  463. package/workflows/organizations/groups/organizationGroupDirectory.js.map +1 -1
  464. package/workflows/organizations/principalMutations/runtimeCurrentOrganizationMutation.js +1 -1
  465. package/workflows/organizations/principalMutations/runtimeCurrentOrganizationMutation.js.map +1 -1
  466. package/workflows/organizations/provisioning/organizationReplacementVerification.js +1 -1
  467. package/workflows/organizations/provisioning/organizationReplacementVerification.js.map +1 -1
  468. package/workflows/organizations/readModel/listLocalOrganizations.js +1 -1
  469. package/workflows/organizations/readModel/localReadModelDetails.js +1 -1
  470. package/workflows/organizations/readModel/localReadModelDetails.js.map +1 -1
  471. package/workflows/principals/acknowledgements/acknowledgedPrincipalCurrents.js +1 -1
  472. package/workflows/principals/acknowledgements/acknowledgedPrincipalCurrents.js.map +1 -1
  473. package/workflows/principals/acknowledgements/acknowledgedPrincipalPredecessor.d.ts +1 -1
  474. package/workflows/principals/acknowledgements/acknowledgedPrincipalPredecessor.js +1 -1
  475. package/workflows/principals/acknowledgements/acknowledgedPrincipalPredecessor.js.map +1 -1
  476. package/workflows/principals/acknowledgements/initialPrincipalCurrentPublication.js +1 -1
  477. package/workflows/principals/acknowledgements/initialPrincipalCurrentPublication.js.map +1 -1
  478. package/workflows/principals/acknowledgements/reconcileAcknowledgedPrincipalCurrent.js +2 -2
  479. package/workflows/principals/acknowledgements/reconcileAcknowledgedPrincipalCurrent.js.map +1 -1
  480. package/workflows/principals/externalAdminPolicy.js +2 -2
  481. package/workflows/principals/externalAdminPolicy.js.map +1 -1
  482. package/workflows/principals/historyRecovery/loadRecoveredPrincipalHistoryPage.js +2 -2
  483. package/workflows/principals/historyRecovery/loadRecoveredPrincipalHistoryPage.js.map +1 -1
  484. package/workflows/principals/historyRecovery/principalHistoryRecoveryPrefix.js +1 -1
  485. package/workflows/principals/historyRecovery/principalHistoryRecoveryPrefix.js.map +1 -1
  486. package/workflows/principals/historyRecovery/principalHistoryRecoveryReferences.js +1 -1
  487. package/workflows/principals/historyRecovery/principalHistoryRecoveryReferences.js.map +1 -1
  488. package/workflows/principals/historyRecovery/principalHistoryRecoveryStage.js +1 -1
  489. package/workflows/principals/historyRecovery/principalHistoryRecoveryStage.js.map +1 -1
  490. package/workflows/principals/historyRecovery/recoverPrincipalPolicyHistory.js +3 -3
  491. package/workflows/principals/historyRecovery/recoverPrincipalPolicyHistory.js.map +1 -1
  492. package/workflows/principals/policyCache/index.js +3 -3
  493. package/workflows/principals/policyCache/index.js.map +1 -1
  494. package/workflows/principals/policyCache/principalPolicyCacheAdvance.js +1 -1
  495. package/workflows/principals/policyCache/principalPolicyCacheAdvance.js.map +1 -1
  496. package/workflows/principals/policyCache/principalPolicyOrganizationScope.js +3 -3
  497. package/workflows/principals/policyCache/principalPolicyOrganizationScope.js.map +1 -1
  498. package/workflows/principals/publicHistory/publicPrincipalHistoryAuthority.js.map +1 -1
  499. package/workflows/principals/publicHistory/publicPrincipalHistoryPage.js +2 -2
  500. package/workflows/principals/publicHistory/publicPrincipalHistoryPage.js.map +1 -1
  501. package/workflows/principals/publicHistory/publicPrincipalHistoryProgress.js +3 -3
  502. package/workflows/principals/publicHistory/publicPrincipalHistoryProgress.js.map +1 -1
  503. package/workflows/principals/publicHistory/publicPrincipalHistoryTypes.d.ts +2 -2
  504. package/workflows/principals/publicHistory/publicPrincipalHistoryTypes.js.map +1 -1
  505. package/workflows/principals/publicHistory/publicProjectionPrincipal.js +1 -1
  506. package/workflows/principals/publicHistory/publicProjectionPrincipal.js.map +1 -1
  507. package/workflows/principals/publicHistory/recoverPublicPrincipalHistory.js +1 -1
  508. package/workflows/principals/publicHistory/recoverPublicPrincipalHistory.js.map +1 -1
  509. package/workflows/principals/publicHistory/selectPublicPrincipalHistory.js +1 -1
  510. package/workflows/principals/publicHistory/selectPublicPrincipalHistory.js.map +1 -1
  511. package/workflows/principals/recoveryOperation/principalRecoveryDirectory.js +1 -1
  512. package/workflows/principals/recoveryOperation/principalRecoveryDirectory.js.map +1 -1
  513. package/workflows/principals/recoveryOperation/principalRecoveryMemoValidity.js +1 -1
  514. package/workflows/principals/recoveryOperation/principalRecoveryMemoValidity.js.map +1 -1
  515. package/workflows/registration/persistRegistrationBootstrap.d.ts +2 -2
  516. package/workflows/registration/persistRegistrationBootstrap.js +2 -2
  517. package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
  518. package/workflows/registration/provisioningAcknowledgement.js +1 -1
  519. package/workflows/registration/provisioningAcknowledgement.js.map +1 -1
  520. package/workflows/registration/registrationPrincipalPolicyPersistence.js +1 -1
  521. package/workflows/registration/registrationPrincipalPolicyPersistence.js.map +1 -1
  522. package/workflows/sync/remoteReset.js +7 -7
  523. package/workflows/sync/remoteReset.js.map +1 -1
  524. package/workflows/sync/remoteResetAttachments.js +1 -1
  525. package/workflows/sync/remoteResetCursorScope.js +1 -1
  526. package/workflows/sync/remoteResetPlans.js +1 -1
  527. package/workflows/sync/remoteResetPrincipalScope.js +5 -5
  528. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  529. package/workflows/sync/remoteResetScope.js +1 -1
  530. package/data/documents/shared/containerKekPath.js.map +0 -1
  531. package/data/documents/shared/containerKekPathHistory.js.map +0 -1
  532. package/data/documents/shared/containerKekPathVerification.js.map +0 -1
  533. package/data/documents/shared/containerKekWrapping.js.map +0 -1
  534. package/data/documents/shared/documentSyncUpdateDecryption.js.map +0 -1
  535. package/data/documents/shared/documentSyncUpdateIsolation.js.map +0 -1
  536. package/data/documents/shared/keyringRebuild.js.map +0 -1
  537. package/data/documents/shared/mutationAcknowledgement.js.map +0 -1
  538. package/data/documents/shared/projection.js.map +0 -1
  539. package/data/documents/shared/projectionContentKeys.js.map +0 -1
  540. package/data/documents/shared/projectionTargets.js.map +0 -1
  541. package/data/documents/shared/syncPagination.js.map +0 -1
  542. package/data/documents/shared/syncResponseAuthorization.js.map +0 -1
  543. package/data/documents/shared/syncResponses.js.map +0 -1
  544. package/data/persistence/documentPurgeCheckpointPersistence.js.map +0 -1
  545. package/data/persistence/keyingCheckpointAdvancePersistence.js.map +0 -1
  546. package/data/persistence/keyingCheckpointPersistence.js.map +0 -1
  547. package/data/persistence/locallyAcknowledgedCheckpointPersistence.js.map +0 -1
  548. package/data/persistence/organizationReplacementCheckpointPersistence.js.map +0 -1
  549. package/data/persistence/principalAuthorizationCheckpoints.js.map +0 -1
  550. package/data/persistence/principalGrantRetirementPersistence.js.map +0 -1
  551. package/data/persistence/principalHistoryEvidencePersistence.js.map +0 -1
  552. package/data/persistence/principalHistoryIncompleteRetention.js.map +0 -1
  553. package/data/persistence/principalHistoryNodeRetention.js.map +0 -1
  554. package/data/persistence/principalHistoryPrefixPersistence.js.map +0 -1
  555. package/data/persistence/principalHistoryRootOwnership.js.map +0 -1
  556. package/data/persistence/principalHistoryStagePersistence.js.map +0 -1
  557. package/data/persistence/principalHistoryStageRetention.js.map +0 -1
  558. package/data/persistence/principalHistoryUnpublishedRetention.js.map +0 -1
  559. package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +0 -1
  560. package/data/persistence/principalKeyEnvelopeCandidates.js.map +0 -1
  561. package/data/persistence/principalPolicyBundleIntegrity.js.map +0 -1
  562. package/data/persistence/principalPolicyCheckpointSelection.js.map +0 -1
  563. package/data/persistence/principalPolicyOrganizationPersistence.js.map +0 -1
  564. package/data/persistence/principalPolicyPersistence.js.map +0 -1
  565. package/data/persistence/principalPolicyReferenceCheckpoint.js.map +0 -1
  566. package/data/persistence/principalPolicyReferenceIndexPersistence.js.map +0 -1
  567. package/data/persistence/principalPolicyReferencePersistence.js.map +0 -1
  568. package/data/persistence/verifiedPrincipalPolicyBundle.js.map +0 -1
  569. package/data/persistence/verifiedPrincipalPolicyCurrent.js.map +0 -1
  570. package/data/persistence/verifiedPrincipalPolicyRetentionPersistence.js.map +0 -1
  571. package/data/sqlite/containerSchema.js.map +0 -1
  572. package/data/sqlite/documentHistoryPersistence.js.map +0 -1
  573. package/data/sqlite/documentOrphanBlobReclaims.js.map +0 -1
  574. package/data/sqlite/documentPendingUpdatePersistence.js.map +0 -1
  575. package/data/sqlite/documentPersistence.js.map +0 -1
  576. package/data/sqlite/documentPersistenceTypes.js.map +0 -1
  577. package/data/sqlite/documentRecordPersistence.js.map +0 -1
  578. package/data/sqlite/documentSyncFailurePersistence.js.map +0 -1
  579. package/data/sqlite/organizationDataUsageSchema.js.map +0 -1
  580. package/data/sqlite/organizationProvisioningAttemptSchema.js.map +0 -1
  581. package/data/sqlite/organizationReadModelTableRegistry.js.map +0 -1
  582. package/data/sqlite/principalHistoryEvidenceSchema.js.map +0 -1
  583. package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +0 -1
  584. package/data/sqlite/principalHistoryStageSchema.js.map +0 -1
  585. package/data/sqlite/principalPolicySchema.js.map +0 -1
  586. package/data/sqlite/schema.js.map +0 -1
  587. package/data/sqlite/securityIncidentSchema.js.map +0 -1
  588. package/data/sqlite/verifiedManifestBundleSchema.js.map +0 -1
  589. /package/data/documents/shared/{containerKekCurrency.js → containerKek/containerKekCurrency.js} +0 -0
  590. /package/data/documents/shared/{containerKekCurrency.js.map → containerKek/containerKekCurrency.js.map} +0 -0
  591. /package/data/documents/shared/{containerKekEntryVerification.js.map → containerKek/containerKekEntryVerification.js.map} +0 -0
  592. /package/data/documents/shared/{containerKekLogFetch.js.map → containerKek/containerKekLogFetch.js.map} +0 -0
  593. /package/data/documents/shared/{containerKekPath.d.ts → containerKek/containerKekPath.d.ts} +0 -0
  594. /package/data/documents/shared/{keyringLogWalk.js.map → containerKek/keyringLogWalk.js.map} +0 -0
  595. /package/data/documents/shared/{pullContinuation.d.ts → sync/pullContinuation.d.ts} +0 -0
  596. /package/data/documents/shared/{pullContinuation.js.map → sync/pullContinuation.js.map} +0 -0
  597. /package/data/documents/shared/{syncSubmitFailure.js → sync/syncSubmitFailure.js} +0 -0
  598. /package/data/documents/shared/{syncSubmitFailure.js.map → sync/syncSubmitFailure.js.map} +0 -0
  599. /package/data/persistence/{keyingCheckpointEvidence.js.map → keyingCheckpoints/keyingCheckpointEvidence.js.map} +0 -0
  600. /package/data/persistence/{storedPrincipalPolicyBundle.js → principalPolicy/storedPrincipalPolicyBundle.js} +0 -0
  601. /package/data/persistence/{storedPrincipalPolicyBundle.js.map → principalPolicy/storedPrincipalPolicyBundle.js.map} +0 -0
  602. /package/data/sqlite/{documentPersistenceTypes.js → documentPersistence/documentPersistenceTypes.js} +0 -0
  603. /package/data/sqlite/{containerDocumentTombstoneHoldSchema.d.ts → schema/containerDocumentTombstoneHoldSchema.d.ts} +0 -0
  604. /package/data/sqlite/{containerDocumentTombstoneHoldSchema.js → schema/containerDocumentTombstoneHoldSchema.js} +0 -0
  605. /package/data/sqlite/{containerDocumentTombstoneHoldSchema.js.map → schema/containerDocumentTombstoneHoldSchema.js.map} +0 -0
  606. /package/data/sqlite/{documentAttachmentSchema.d.ts → schema/documentAttachmentSchema.d.ts} +0 -0
  607. /package/data/sqlite/{documentAttachmentSchema.js → schema/documentAttachmentSchema.js} +0 -0
  608. /package/data/sqlite/{documentAttachmentSchema.js.map → schema/documentAttachmentSchema.js.map} +0 -0
  609. /package/data/sqlite/{documentDiscoveryEvidenceSchema.js → schema/documentDiscoveryEvidenceSchema.js} +0 -0
  610. /package/data/sqlite/{documentDiscoveryEvidenceSchema.js.map → schema/documentDiscoveryEvidenceSchema.js.map} +0 -0
  611. /package/data/sqlite/{documentPlacementIntentSchema.js → schema/documentPlacementIntentSchema.js} +0 -0
  612. /package/data/sqlite/{documentPlacementIntentSchema.js.map → schema/documentPlacementIntentSchema.js.map} +0 -0
  613. /package/data/sqlite/{localIntentSchema.d.ts → schema/localIntentSchema.d.ts} +0 -0
  614. /package/data/sqlite/{localIntentSchema.js → schema/localIntentSchema.js} +0 -0
  615. /package/data/sqlite/{localIntentSchema.js.map → schema/localIntentSchema.js.map} +0 -0
  616. /package/data/sqlite/{organizationFounderSchema.js → schema/organizationFounderSchema.js} +0 -0
  617. /package/data/sqlite/{organizationFounderSchema.js.map → schema/organizationFounderSchema.js.map} +0 -0
  618. /package/data/sqlite/{organizationReadModelSchema.js → schema/organizationReadModelSchema.js} +0 -0
  619. /package/data/sqlite/{organizationReadModelSchema.js.map → schema/organizationReadModelSchema.js.map} +0 -0
  620. /package/data/sqlite/{principalGrantRetirementSchema.js → schema/principalGrantRetirementSchema.js} +0 -0
  621. /package/data/sqlite/{principalGrantRetirementSchema.js.map → schema/principalGrantRetirementSchema.js.map} +0 -0
  622. /package/data/sqlite/{principalPolicySchema.d.ts → schema/principalPolicySchema.d.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"organizationReadModelMemberLoad.js","sourceRoot":"","sources":["organizationReadModelMemberLoad.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n OrganizationReadModelGroupMemberResponse,\n OrganizationRole,\n} from \"@tearleads/validators/response\";\nimport { and, asc, eq } from \"drizzle-orm\";\nimport {\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport { OrganizationReadModelIntegrityError } from \"./organizationReadModelProtocol\";\nimport { loadWithOrganizationReadModelIntegrityPurge } from \"./organizationReadModelPurge\";\n\ninterface SelectedGroupMember {\n readonly userId: string;\n readonly role: string;\n readonly stateHash: string;\n}\n\n/** Locally projected members of one group, by user and role. */\nexport interface OrganizationReadModelGroupMembers {\n readonly groupId: string;\n readonly members: OrganizationReadModelGroupMemberResponse[];\n readonly organizationId: string;\n}\n\nfunction requireOrganizationRole(value: string): OrganizationRole {\n if (value !== \"member\" && value !== \"admin\") {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group member role is invalid\",\n );\n }\n return value;\n}\n\nfunction toGroupMember(\n row: SelectedGroupMember,\n expectedStateHash: string,\n): OrganizationReadModelGroupMemberResponse {\n if (row.stateHash !== expectedStateHash) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group membership state is inconsistent\",\n );\n }\n return {\n userId: row.userId,\n role: requireOrganizationRole(row.role),\n };\n}\n\nasync function loadMembershipRows(input: {\n readonly groupId: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<SelectedGroupMember[]> {\n return input.tx\n .select({\n userId: organizationReadModelGroupMembers.userId,\n role: organizationReadModelGroupMembers.role,\n stateHash: organizationReadModelGroupMembers.stateHash,\n })\n .from(organizationReadModelGroupMembers)\n .where(\n and(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n eq(organizationReadModelGroupMembers.groupId, input.groupId),\n ),\n )\n .orderBy(\n asc(organizationReadModelGroupMembers.sortOrder),\n asc(organizationReadModelGroupMembers.userId),\n );\n}\n\ninterface StoredMembershipHead {\n readonly memberCount: number | null;\n readonly stateHash: string;\n}\n\n/** The reserved Members head lives on the state row; others on catalog rows. */\nasync function loadMembershipHead(input: {\n readonly groupId: string;\n readonly memberGroup: {\n readonly groupId: string;\n readonly stateHash: string;\n };\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<StoredMembershipHead | null> {\n if (input.groupId === input.memberGroup.groupId) {\n return { memberCount: null, stateHash: input.memberGroup.stateHash };\n }\n const [group] = await input.tx\n .select({\n memberCount: organizationReadModelGroups.memberCount,\n membersStateHash: organizationReadModelGroups.membersStateHash,\n stateHash: organizationReadModelGroups.stateHash,\n })\n .from(organizationReadModelGroups)\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n eq(organizationReadModelGroups.groupId, input.groupId),\n ),\n )\n .limit(1);\n if (!group?.membersStateHash) {\n return null;\n }\n if (group.stateHash !== group.membersStateHash) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group membership binding is invalid\",\n );\n }\n return { memberCount: group.memberCount, stateHash: group.membersStateHash };\n}\n\nasync function loadOrganizationReadModelGroupMembersInTransaction(input: {\n readonly groupId: string;\n readonly memberGroup: {\n readonly groupId: string;\n readonly stateHash: string;\n };\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<OrganizationReadModelGroupMembers | null> {\n const head = await loadMembershipHead(input);\n if (!head) {\n return null;\n }\n const rows = await loadMembershipRows(input);\n if (head.memberCount !== null && head.memberCount !== rows.length) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group membership binding is invalid\",\n );\n }\n return {\n organizationId: input.organizationId,\n groupId: input.groupId,\n members: rows.map((row) => toGroupMember(row, head.stateHash)),\n };\n}\n\nexport async function loadOrganizationReadModelGroupMembers(\n execSql: ExecSql,\n organizationId: string,\n groupId: string,\n currentUserId: string,\n): Promise<OrganizationReadModelGroupMembers | null> {\n return loadWithOrganizationReadModelIntegrityPurge({\n execSql,\n organizationId,\n load: async (tx) => {\n const [state] = await tx\n .select({\n memberGroupId: organizationReadModelState.memberGroupId,\n memberGroupStateHash: organizationReadModelState.memberGroupStateHash,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, organizationId))\n .limit(1);\n if (!state) {\n return null;\n }\n const [requester] = await tx\n .select({ userId: organizationReadModelRequesters.userId })\n .from(organizationReadModelRequesters)\n .where(\n and(\n eq(organizationReadModelRequesters.organizationId, organizationId),\n eq(organizationReadModelRequesters.userId, currentUserId),\n ),\n )\n .limit(1);\n if (!requester) {\n return null;\n }\n return loadOrganizationReadModelGroupMembersInTransaction({\n groupId,\n memberGroup: {\n groupId: state.memberGroupId,\n stateHash: state.memberGroupStateHash,\n },\n organizationId,\n tx,\n });\n },\n });\n}\n"]}
1
+ {"version":3,"file":"organizationReadModelMemberLoad.js","sourceRoot":"","sources":["organizationReadModelMemberLoad.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n OrganizationReadModelGroupMemberResponse,\n OrganizationRole,\n} from \"@tearleads/validators/response\";\nimport { and, asc, eq } from \"drizzle-orm\";\nimport {\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/schema/organizationReadModelSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport { OrganizationReadModelIntegrityError } from \"./organizationReadModelProtocol\";\nimport { loadWithOrganizationReadModelIntegrityPurge } from \"./organizationReadModelPurge\";\n\ninterface SelectedGroupMember {\n readonly userId: string;\n readonly role: string;\n readonly stateHash: string;\n}\n\n/** Locally projected members of one group, by user and role. */\nexport interface OrganizationReadModelGroupMembers {\n readonly groupId: string;\n readonly members: OrganizationReadModelGroupMemberResponse[];\n readonly organizationId: string;\n}\n\nfunction requireOrganizationRole(value: string): OrganizationRole {\n if (value !== \"member\" && value !== \"admin\") {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group member role is invalid\",\n );\n }\n return value;\n}\n\nfunction toGroupMember(\n row: SelectedGroupMember,\n expectedStateHash: string,\n): OrganizationReadModelGroupMemberResponse {\n if (row.stateHash !== expectedStateHash) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group membership state is inconsistent\",\n );\n }\n return {\n userId: row.userId,\n role: requireOrganizationRole(row.role),\n };\n}\n\nasync function loadMembershipRows(input: {\n readonly groupId: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<SelectedGroupMember[]> {\n return input.tx\n .select({\n userId: organizationReadModelGroupMembers.userId,\n role: organizationReadModelGroupMembers.role,\n stateHash: organizationReadModelGroupMembers.stateHash,\n })\n .from(organizationReadModelGroupMembers)\n .where(\n and(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n eq(organizationReadModelGroupMembers.groupId, input.groupId),\n ),\n )\n .orderBy(\n asc(organizationReadModelGroupMembers.sortOrder),\n asc(organizationReadModelGroupMembers.userId),\n );\n}\n\ninterface StoredMembershipHead {\n readonly memberCount: number | null;\n readonly stateHash: string;\n}\n\n/** The reserved Members head lives on the state row; others on catalog rows. */\nasync function loadMembershipHead(input: {\n readonly groupId: string;\n readonly memberGroup: {\n readonly groupId: string;\n readonly stateHash: string;\n };\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<StoredMembershipHead | null> {\n if (input.groupId === input.memberGroup.groupId) {\n return { memberCount: null, stateHash: input.memberGroup.stateHash };\n }\n const [group] = await input.tx\n .select({\n memberCount: organizationReadModelGroups.memberCount,\n membersStateHash: organizationReadModelGroups.membersStateHash,\n stateHash: organizationReadModelGroups.stateHash,\n })\n .from(organizationReadModelGroups)\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n eq(organizationReadModelGroups.groupId, input.groupId),\n ),\n )\n .limit(1);\n if (!group?.membersStateHash) {\n return null;\n }\n if (group.stateHash !== group.membersStateHash) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group membership binding is invalid\",\n );\n }\n return { memberCount: group.memberCount, stateHash: group.membersStateHash };\n}\n\nasync function loadOrganizationReadModelGroupMembersInTransaction(input: {\n readonly groupId: string;\n readonly memberGroup: {\n readonly groupId: string;\n readonly stateHash: string;\n };\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<OrganizationReadModelGroupMembers | null> {\n const head = await loadMembershipHead(input);\n if (!head) {\n return null;\n }\n const rows = await loadMembershipRows(input);\n if (head.memberCount !== null && head.memberCount !== rows.length) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group membership binding is invalid\",\n );\n }\n return {\n organizationId: input.organizationId,\n groupId: input.groupId,\n members: rows.map((row) => toGroupMember(row, head.stateHash)),\n };\n}\n\nexport async function loadOrganizationReadModelGroupMembers(\n execSql: ExecSql,\n organizationId: string,\n groupId: string,\n currentUserId: string,\n): Promise<OrganizationReadModelGroupMembers | null> {\n return loadWithOrganizationReadModelIntegrityPurge({\n execSql,\n organizationId,\n load: async (tx) => {\n const [state] = await tx\n .select({\n memberGroupId: organizationReadModelState.memberGroupId,\n memberGroupStateHash: organizationReadModelState.memberGroupStateHash,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, organizationId))\n .limit(1);\n if (!state) {\n return null;\n }\n const [requester] = await tx\n .select({ userId: organizationReadModelRequesters.userId })\n .from(organizationReadModelRequesters)\n .where(\n and(\n eq(organizationReadModelRequesters.organizationId, organizationId),\n eq(organizationReadModelRequesters.userId, currentUserId),\n ),\n )\n .limit(1);\n if (!requester) {\n return null;\n }\n return loadOrganizationReadModelGroupMembersInTransaction({\n groupId,\n memberGroup: {\n groupId: state.memberGroupId,\n stateHash: state.memberGroupStateHash,\n },\n organizationId,\n tx,\n });\n },\n });\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { and, eq, inArray, sql } from "drizzle-orm";
2
- import { organizationReadModelGroupMembers, organizationReadModelGroups, } from "../../sqlite/organizationReadModelSchema.js";
2
+ import { organizationReadModelGroupMembers, organizationReadModelGroups, } from "../../sqlite/schema/organizationReadModelSchema.js";
3
3
  import { sqliteInsertBatchSize, sqliteRowsPerStatement, } from "../../sqlite/sqliteBindBudget.js";
4
4
  // Group ID lists bind one value per group; the head-clearing update also
5
5
  // binds its null value beside the organization ID.
@@ -1 +1 @@
1
- {"version":3,"file":"organizationReadModelMembershipPersistence.js","sourceRoot":"","sources":["organizationReadModelMembershipPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n OrganizationReadModelGroupMemberResponse,\n OrganizationReadModelGroupMembershipsResponse,\n} from \"@tearleads/validators/response\";\nimport { and, eq, inArray, sql } from \"drizzle-orm\";\nimport {\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport {\n sqliteInsertBatchSize,\n sqliteRowsPerStatement,\n} from \"../../sqlite/sqliteBindBudget\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\n\n// Group ID lists bind one value per group; the head-clearing update also\n// binds its null value beside the organization ID.\nconst GROUP_MEMBERSHIP_BATCH_SIZE = sqliteRowsPerStatement(1, 2);\n// Each head binds two values in its CASE arm and one in the IN list, plus the\n// organization ID.\nconst GROUP_HEAD_UPDATE_BATCH_SIZE = sqliteRowsPerStatement(3, 1);\nconst GROUP_MEMBER_INSERT_BATCH_SIZE = sqliteInsertBatchSize(\n organizationReadModelGroupMembers,\n);\n\nexport class OrganizationReadModelBindingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OrganizationReadModelBindingError\";\n }\n}\n\nfunction membershipCoverageError(): OrganizationReadModelBindingError {\n return new OrganizationReadModelBindingError(\n \"Organization group membership coverage is inconsistent\",\n );\n}\n\nfunction membershipMemberKey(\n member: Pick<OrganizationReadModelGroupMemberResponse, \"userId\">,\n): string {\n return member.userId;\n}\n\nfunction assertUniqueMembershipRows(\n lane: OrganizationReadModelGroupMembershipsResponse,\n): void {\n const groupIds = lane.groups.map((group) => group.groupId);\n if (new Set(groupIds).size !== groupIds.length) {\n throw new Error(\n \"Organization read-model group memberships contain duplicate groups\",\n );\n }\n if (new Set(lane.deletedGroupIds).size !== lane.deletedGroupIds.length) {\n throw new Error(\n \"Organization read-model group memberships contain duplicate deletions\",\n );\n }\n const deletedGroupIds = new Set(lane.deletedGroupIds);\n if (groupIds.some((groupId) => deletedGroupIds.has(groupId))) {\n throw new Error(\n \"Organization read-model group membership is both replaced and deleted\",\n );\n }\n for (const group of lane.groups) {\n const memberKeys = group.members.map(membershipMemberKey);\n if (new Set(memberKeys).size !== memberKeys.length) {\n throw new Error(\n \"Organization read-model group membership contains duplicate members\",\n );\n }\n }\n}\n\ninterface ApplyGroupMembershipsLaneInput {\n /** The reserved Members head before this lane applies. */\n readonly currentMemberGroupStateHash: string | null;\n readonly lane: OrganizationReadModelGroupMembershipsResponse;\n readonly memberGroupId: string;\n readonly organizationId: string;\n readonly replaceAll: boolean;\n readonly tx: ClientSQLiteTransactionScope;\n}\n\nasync function clearMembershipRows(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n await input.tx\n .delete(organizationReadModelGroupMembers)\n .where(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .update(organizationReadModelGroups)\n .set({ membersStateHash: null })\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n}\n\nasync function deleteMembershipRows(\n input: ApplyGroupMembershipsLaneInput,\n groupIds: string[],\n): Promise<void> {\n for (\n let index = 0;\n index < groupIds.length;\n index += GROUP_MEMBERSHIP_BATCH_SIZE\n ) {\n const groupIdBatch = groupIds.slice(\n index,\n index + GROUP_MEMBERSHIP_BATCH_SIZE,\n );\n await input.tx\n .delete(organizationReadModelGroupMembers)\n .where(\n and(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n inArray(organizationReadModelGroupMembers.groupId, groupIdBatch),\n ),\n )\n .run();\n await input.tx\n .update(organizationReadModelGroups)\n .set({ membersStateHash: null })\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n inArray(organizationReadModelGroups.groupId, groupIdBatch),\n ),\n )\n .run();\n }\n}\n\nasync function removeExistingMembershipRows(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n if (input.replaceAll) {\n if (input.lane.deletedGroupIds.length > 0) {\n throw new Error(\"Organization membership snapshot contains deletions\");\n }\n return clearMembershipRows(input);\n }\n const replacedGroupIds = input.lane.groups.map((group) => group.groupId);\n const removedGroupIds = [...replacedGroupIds, ...input.lane.deletedGroupIds];\n if (removedGroupIds.length > 0) {\n await deleteMembershipRows(input, removedGroupIds);\n }\n}\n\n/**\n * Record each visible group's membership head on its catalog row. A head for\n * a group the catalog does not list cannot be bound and fails the page. The\n * reserved Members head binds to the state row instead; the catalog normally\n * omits Members, so its row is updated only when one exists.\n */\nasync function writeVisibleGroupHeads(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n const memberGroupHead = input.lane.groups.find(\n (group) => group.groupId === input.memberGroupId,\n );\n if (memberGroupHead) {\n await input.tx\n .update(organizationReadModelGroups)\n .set({ membersStateHash: memberGroupHead.stateHash })\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n eq(organizationReadModelGroups.groupId, input.memberGroupId),\n ),\n )\n .run();\n }\n const heads = input.lane.groups.filter(\n (group) => group.groupId !== input.memberGroupId,\n );\n for (\n let index = 0;\n index < heads.length;\n index += GROUP_HEAD_UPDATE_BATCH_SIZE\n ) {\n const batch = heads.slice(index, index + GROUP_HEAD_UPDATE_BATCH_SIZE);\n const arms = sql.join(\n batch.map((head) => sql`WHEN ${head.groupId} THEN ${head.stateHash}`),\n sql` `,\n );\n const updated = await input.tx\n .update(organizationReadModelGroups)\n .set({\n membersStateHash: sql`CASE ${organizationReadModelGroups.groupId} ${arms} END`,\n })\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n inArray(\n organizationReadModelGroups.groupId,\n batch.map((head) => head.groupId),\n ),\n ),\n )\n .returning({ groupId: organizationReadModelGroups.groupId });\n if (updated.length !== batch.length) {\n throw membershipCoverageError();\n }\n }\n}\n\nasync function insertMemberRows(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n const memberRows = input.lane.groups.flatMap((group) =>\n group.members.map((member, sortOrder) => ({\n organizationId: input.organizationId,\n groupId: group.groupId,\n userId: member.userId,\n sortOrder,\n stateHash: group.stateHash,\n role: member.role,\n })),\n );\n for (\n let index = 0;\n index < memberRows.length;\n index += GROUP_MEMBER_INSERT_BATCH_SIZE\n ) {\n await input.tx\n .insert(organizationReadModelGroupMembers)\n .values(memberRows.slice(index, index + GROUP_MEMBER_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nfunction nextMemberGroupStateHash(\n input: ApplyGroupMembershipsLaneInput,\n): string | null {\n const head = input.lane.groups.find(\n (group) => group.groupId === input.memberGroupId,\n );\n if (head) {\n return head.stateHash;\n }\n return input.replaceAll ||\n input.lane.deletedGroupIds.includes(input.memberGroupId)\n ? null\n : input.currentMemberGroupStateHash;\n}\n\n/**\n * Apply one groupMemberships lane and return the reserved Members head, which\n * the caller persists on the organization state row.\n */\nexport async function applyGroupMembershipsLane(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<string | null> {\n assertUniqueMembershipRows(input.lane);\n await removeExistingMembershipRows(input);\n await writeVisibleGroupHeads(input);\n await insertMemberRows(input);\n return nextMemberGroupStateHash(input);\n}\n\ninterface StoredGroupHead {\n readonly groupId: string;\n readonly memberCount: number | null;\n readonly membersStateHash: string | null;\n readonly stateHash: string | null;\n}\n\nfunction membershipHeadsByGroupId(input: {\n readonly groups: readonly StoredGroupHead[];\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string | null;\n}): Map<string, string> {\n if (input.memberGroupStateHash === null) {\n throw membershipCoverageError();\n }\n const heads = new Map([[input.memberGroupId, input.memberGroupStateHash]]);\n for (const group of input.groups) {\n if (group.membersStateHash === null) {\n continue;\n }\n // A head is expected exactly for stateful visible groups; a listed\n // Members row must carry the same head as the state row.\n const isMemberGroup = group.groupId === input.memberGroupId;\n if (\n group.stateHash === null ||\n (isMemberGroup\n ? group.membersStateHash !== input.memberGroupStateHash\n : heads.has(group.groupId))\n ) {\n throw membershipCoverageError();\n }\n heads.set(group.groupId, group.membersStateHash);\n }\n return heads;\n}\n\nexport async function assertStoredGroupMembershipBindings(input: {\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string | null;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const groups = await input.tx\n .select({\n groupId: organizationReadModelGroups.groupId,\n memberCount: organizationReadModelGroups.memberCount,\n membersStateHash: organizationReadModelGroups.membersStateHash,\n stateHash: organizationReadModelGroups.stateHash,\n })\n .from(organizationReadModelGroups)\n .where(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n );\n const members = await input.tx\n .select({\n groupId: organizationReadModelGroupMembers.groupId,\n stateHash: organizationReadModelGroupMembers.stateHash,\n })\n .from(organizationReadModelGroupMembers)\n .where(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n );\n const headsByGroupId = membershipHeadsByGroupId({ ...input, groups });\n\n const memberCountsByGroupId = new Map<string, number>();\n for (const member of members) {\n if (headsByGroupId.get(member.groupId) !== member.stateHash) {\n throw new OrganizationReadModelBindingError(\n \"Organization group membership member state is inconsistent\",\n );\n }\n memberCountsByGroupId.set(\n member.groupId,\n (memberCountsByGroupId.get(member.groupId) ?? 0) + 1,\n );\n }\n\n for (const group of groups) {\n if (group.stateHash === null) {\n continue;\n }\n if (\n group.membersStateHash !== group.stateHash ||\n group.memberCount === null ||\n group.memberCount !== (memberCountsByGroupId.get(group.groupId) ?? 0)\n ) {\n throw new OrganizationReadModelBindingError(\n \"Organization group membership state hash is inconsistent\",\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"organizationReadModelMembershipPersistence.js","sourceRoot":"","sources":["organizationReadModelMembershipPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n OrganizationReadModelGroupMemberResponse,\n OrganizationReadModelGroupMembershipsResponse,\n} from \"@tearleads/validators/response\";\nimport { and, eq, inArray, sql } from \"drizzle-orm\";\nimport {\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n} from \"../../sqlite/schema/organizationReadModelSchema\";\nimport {\n sqliteInsertBatchSize,\n sqliteRowsPerStatement,\n} from \"../../sqlite/sqliteBindBudget\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\n\n// Group ID lists bind one value per group; the head-clearing update also\n// binds its null value beside the organization ID.\nconst GROUP_MEMBERSHIP_BATCH_SIZE = sqliteRowsPerStatement(1, 2);\n// Each head binds two values in its CASE arm and one in the IN list, plus the\n// organization ID.\nconst GROUP_HEAD_UPDATE_BATCH_SIZE = sqliteRowsPerStatement(3, 1);\nconst GROUP_MEMBER_INSERT_BATCH_SIZE = sqliteInsertBatchSize(\n organizationReadModelGroupMembers,\n);\n\nexport class OrganizationReadModelBindingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OrganizationReadModelBindingError\";\n }\n}\n\nfunction membershipCoverageError(): OrganizationReadModelBindingError {\n return new OrganizationReadModelBindingError(\n \"Organization group membership coverage is inconsistent\",\n );\n}\n\nfunction membershipMemberKey(\n member: Pick<OrganizationReadModelGroupMemberResponse, \"userId\">,\n): string {\n return member.userId;\n}\n\nfunction assertUniqueMembershipRows(\n lane: OrganizationReadModelGroupMembershipsResponse,\n): void {\n const groupIds = lane.groups.map((group) => group.groupId);\n if (new Set(groupIds).size !== groupIds.length) {\n throw new Error(\n \"Organization read-model group memberships contain duplicate groups\",\n );\n }\n if (new Set(lane.deletedGroupIds).size !== lane.deletedGroupIds.length) {\n throw new Error(\n \"Organization read-model group memberships contain duplicate deletions\",\n );\n }\n const deletedGroupIds = new Set(lane.deletedGroupIds);\n if (groupIds.some((groupId) => deletedGroupIds.has(groupId))) {\n throw new Error(\n \"Organization read-model group membership is both replaced and deleted\",\n );\n }\n for (const group of lane.groups) {\n const memberKeys = group.members.map(membershipMemberKey);\n if (new Set(memberKeys).size !== memberKeys.length) {\n throw new Error(\n \"Organization read-model group membership contains duplicate members\",\n );\n }\n }\n}\n\ninterface ApplyGroupMembershipsLaneInput {\n /** The reserved Members head before this lane applies. */\n readonly currentMemberGroupStateHash: string | null;\n readonly lane: OrganizationReadModelGroupMembershipsResponse;\n readonly memberGroupId: string;\n readonly organizationId: string;\n readonly replaceAll: boolean;\n readonly tx: ClientSQLiteTransactionScope;\n}\n\nasync function clearMembershipRows(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n await input.tx\n .delete(organizationReadModelGroupMembers)\n .where(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .update(organizationReadModelGroups)\n .set({ membersStateHash: null })\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n}\n\nasync function deleteMembershipRows(\n input: ApplyGroupMembershipsLaneInput,\n groupIds: string[],\n): Promise<void> {\n for (\n let index = 0;\n index < groupIds.length;\n index += GROUP_MEMBERSHIP_BATCH_SIZE\n ) {\n const groupIdBatch = groupIds.slice(\n index,\n index + GROUP_MEMBERSHIP_BATCH_SIZE,\n );\n await input.tx\n .delete(organizationReadModelGroupMembers)\n .where(\n and(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n inArray(organizationReadModelGroupMembers.groupId, groupIdBatch),\n ),\n )\n .run();\n await input.tx\n .update(organizationReadModelGroups)\n .set({ membersStateHash: null })\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n inArray(organizationReadModelGroups.groupId, groupIdBatch),\n ),\n )\n .run();\n }\n}\n\nasync function removeExistingMembershipRows(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n if (input.replaceAll) {\n if (input.lane.deletedGroupIds.length > 0) {\n throw new Error(\"Organization membership snapshot contains deletions\");\n }\n return clearMembershipRows(input);\n }\n const replacedGroupIds = input.lane.groups.map((group) => group.groupId);\n const removedGroupIds = [...replacedGroupIds, ...input.lane.deletedGroupIds];\n if (removedGroupIds.length > 0) {\n await deleteMembershipRows(input, removedGroupIds);\n }\n}\n\n/**\n * Record each visible group's membership head on its catalog row. A head for\n * a group the catalog does not list cannot be bound and fails the page. The\n * reserved Members head binds to the state row instead; the catalog normally\n * omits Members, so its row is updated only when one exists.\n */\nasync function writeVisibleGroupHeads(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n const memberGroupHead = input.lane.groups.find(\n (group) => group.groupId === input.memberGroupId,\n );\n if (memberGroupHead) {\n await input.tx\n .update(organizationReadModelGroups)\n .set({ membersStateHash: memberGroupHead.stateHash })\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n eq(organizationReadModelGroups.groupId, input.memberGroupId),\n ),\n )\n .run();\n }\n const heads = input.lane.groups.filter(\n (group) => group.groupId !== input.memberGroupId,\n );\n for (\n let index = 0;\n index < heads.length;\n index += GROUP_HEAD_UPDATE_BATCH_SIZE\n ) {\n const batch = heads.slice(index, index + GROUP_HEAD_UPDATE_BATCH_SIZE);\n const arms = sql.join(\n batch.map((head) => sql`WHEN ${head.groupId} THEN ${head.stateHash}`),\n sql` `,\n );\n const updated = await input.tx\n .update(organizationReadModelGroups)\n .set({\n membersStateHash: sql`CASE ${organizationReadModelGroups.groupId} ${arms} END`,\n })\n .where(\n and(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n inArray(\n organizationReadModelGroups.groupId,\n batch.map((head) => head.groupId),\n ),\n ),\n )\n .returning({ groupId: organizationReadModelGroups.groupId });\n if (updated.length !== batch.length) {\n throw membershipCoverageError();\n }\n }\n}\n\nasync function insertMemberRows(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<void> {\n const memberRows = input.lane.groups.flatMap((group) =>\n group.members.map((member, sortOrder) => ({\n organizationId: input.organizationId,\n groupId: group.groupId,\n userId: member.userId,\n sortOrder,\n stateHash: group.stateHash,\n role: member.role,\n })),\n );\n for (\n let index = 0;\n index < memberRows.length;\n index += GROUP_MEMBER_INSERT_BATCH_SIZE\n ) {\n await input.tx\n .insert(organizationReadModelGroupMembers)\n .values(memberRows.slice(index, index + GROUP_MEMBER_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nfunction nextMemberGroupStateHash(\n input: ApplyGroupMembershipsLaneInput,\n): string | null {\n const head = input.lane.groups.find(\n (group) => group.groupId === input.memberGroupId,\n );\n if (head) {\n return head.stateHash;\n }\n return input.replaceAll ||\n input.lane.deletedGroupIds.includes(input.memberGroupId)\n ? null\n : input.currentMemberGroupStateHash;\n}\n\n/**\n * Apply one groupMemberships lane and return the reserved Members head, which\n * the caller persists on the organization state row.\n */\nexport async function applyGroupMembershipsLane(\n input: ApplyGroupMembershipsLaneInput,\n): Promise<string | null> {\n assertUniqueMembershipRows(input.lane);\n await removeExistingMembershipRows(input);\n await writeVisibleGroupHeads(input);\n await insertMemberRows(input);\n return nextMemberGroupStateHash(input);\n}\n\ninterface StoredGroupHead {\n readonly groupId: string;\n readonly memberCount: number | null;\n readonly membersStateHash: string | null;\n readonly stateHash: string | null;\n}\n\nfunction membershipHeadsByGroupId(input: {\n readonly groups: readonly StoredGroupHead[];\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string | null;\n}): Map<string, string> {\n if (input.memberGroupStateHash === null) {\n throw membershipCoverageError();\n }\n const heads = new Map([[input.memberGroupId, input.memberGroupStateHash]]);\n for (const group of input.groups) {\n if (group.membersStateHash === null) {\n continue;\n }\n // A head is expected exactly for stateful visible groups; a listed\n // Members row must carry the same head as the state row.\n const isMemberGroup = group.groupId === input.memberGroupId;\n if (\n group.stateHash === null ||\n (isMemberGroup\n ? group.membersStateHash !== input.memberGroupStateHash\n : heads.has(group.groupId))\n ) {\n throw membershipCoverageError();\n }\n heads.set(group.groupId, group.membersStateHash);\n }\n return heads;\n}\n\nexport async function assertStoredGroupMembershipBindings(input: {\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string | null;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const groups = await input.tx\n .select({\n groupId: organizationReadModelGroups.groupId,\n memberCount: organizationReadModelGroups.memberCount,\n membersStateHash: organizationReadModelGroups.membersStateHash,\n stateHash: organizationReadModelGroups.stateHash,\n })\n .from(organizationReadModelGroups)\n .where(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n );\n const members = await input.tx\n .select({\n groupId: organizationReadModelGroupMembers.groupId,\n stateHash: organizationReadModelGroupMembers.stateHash,\n })\n .from(organizationReadModelGroupMembers)\n .where(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n );\n const headsByGroupId = membershipHeadsByGroupId({ ...input, groups });\n\n const memberCountsByGroupId = new Map<string, number>();\n for (const member of members) {\n if (headsByGroupId.get(member.groupId) !== member.stateHash) {\n throw new OrganizationReadModelBindingError(\n \"Organization group membership member state is inconsistent\",\n );\n }\n memberCountsByGroupId.set(\n member.groupId,\n (memberCountsByGroupId.get(member.groupId) ?? 0) + 1,\n );\n }\n\n for (const group of groups) {\n if (group.stateHash === null) {\n continue;\n }\n if (\n group.membersStateHash !== group.stateHash ||\n group.memberCount === null ||\n group.memberCount !== (memberCountsByGroupId.get(group.groupId) ?? 0)\n ) {\n throw new OrganizationReadModelBindingError(\n \"Organization group membership state hash is inconsistent\",\n );\n }\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { eq } from "drizzle-orm";
2
2
  import { getOrCreatePrincipalPolicyCoordinator } from "../../principals/principalPolicyCoordinator.js";
3
- import { organizationDataUsageTables } from "../../sqlite/organizationDataUsageSchema.js";
4
- import { organizationReadModelDirectoryUsers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/organizationReadModelSchema.js";
5
- import { organizationReadModelTables } from "../../sqlite/schema.js";
3
+ import { organizationReadModelTables } from "../../sqlite/schema/index.js";
4
+ import { organizationDataUsageTables } from "../../sqlite/schema/organizationDataUsageSchema.js";
5
+ import { organizationReadModelDirectoryUsers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/schema/organizationReadModelSchema.js";
6
6
  import { sqliteInsertBatchSize } from "../../sqlite/sqliteBindBudget.js";
7
7
  import { getClientSQLitePersistenceRuntime, } from "../../sqlite/sqlitePersistenceRuntime.js";
8
8
  import { ensureSqlTables } from "../../sqlite/sqlSchema.js";
@@ -1 +1 @@
1
- {"version":3,"file":"organizationReadModelPersistence.js","sourceRoot":"","sources":["organizationReadModelPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ListOrganizationGroupsResponse,\n OrganizationGroupCurrentStateResponse,\n OrganizationReadModelDirectoryResponse,\n OrganizationReadModelResponse,\n} from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport { getOrCreatePrincipalPolicyCoordinator } from \"../../principals/principalPolicyCoordinator\";\nimport { organizationDataUsageTables } from \"../../sqlite/organizationDataUsageSchema\";\nimport {\n organizationReadModelDirectoryUsers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport { sqliteInsertBatchSize } from \"../../sqlite/sqliteBindBudget\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../../sqlite/sqlSchema\";\nimport { clearOrganizationPresentationDenialInTransaction } from \"./organizationPresentationDenialPersistence\";\nimport { applyOrganizationReadModelGrantsLane } from \"./organizationReadModelGrantPersistence\";\nimport {\n applyGroupMembershipsLane,\n assertStoredGroupMembershipBindings,\n OrganizationReadModelBindingError,\n} from \"./organizationReadModelMembershipPersistence\";\nimport {\n loadOrganizationReadModelProjectionInTransaction,\n type OrganizationReadModelProjection,\n} from \"./organizationReadModelProjection\";\nimport {\n loadWithOrganizationReadModelIntegrityPurge,\n pruneInactiveOrganizationRequestersInTransaction,\n purgeOrganizationReadModelProjectionInTransaction,\n} from \"./organizationReadModelPurge\";\nimport { assertOrganizationReadModelResponse } from \"./organizationReadModelResponseAssertions\";\n\nexport type { OrganizationReadModelProjection } from \"./organizationReadModelProjection\";\n\nconst DIRECTORY_INSERT_BATCH_SIZE = sqliteInsertBatchSize(\n organizationReadModelDirectoryUsers,\n);\nconst GROUP_INSERT_BATCH_SIZE = sqliteInsertBatchSize(\n organizationReadModelGroups,\n);\n\ntype ApplyOrganizationReadModelResponseResult =\n | \"already-applied\"\n | \"applied\"\n | \"stale\";\n\ninterface CurrentOrganizationReadModelState {\n readonly cursor: string;\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string;\n readonly organizationHead: OrganizationGroupCurrentStateResponse;\n readonly profileDocumentId: string | null;\n}\n\nasync function replaceDirectoryLane(input: {\n readonly directory: OrganizationReadModelDirectoryResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelDirectoryUsers)\n .where(\n eq(\n organizationReadModelDirectoryUsers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n\n const rows = input.directory.users.map((user, sortOrder) => ({\n organizationId: input.organizationId,\n userId: user.userId,\n sortOrder,\n signingKeyFingerprint: user.signingKeyFingerprint,\n signingPublicKey: user.signingPublicKey,\n encapsulationPublicKey: user.encapsulationPublicKey,\n encapsulationKeyFingerprint: user.encapsulationKeyFingerprint,\n isPersonalOrganizationOwner: user.isPersonalOrganizationOwner,\n createdAt: user.createdAt,\n status: user.status,\n profileDocumentId: user.profileDocumentId,\n joinedAt: user.joinedAt,\n updatedAt: user.updatedAt,\n disabledAt: user.disabledAt,\n disabledByUserId: user.disabledByUserId,\n }));\n for (\n let index = 0;\n index < rows.length;\n index += DIRECTORY_INSERT_BATCH_SIZE\n ) {\n await input.tx\n .insert(organizationReadModelDirectoryUsers)\n .values(rows.slice(index, index + DIRECTORY_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function upsertRequester(input: {\n readonly currentUserId: string;\n readonly isOrgAdmin: boolean;\n readonly now: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const requesterRow = {\n organizationId: input.organizationId,\n userId: input.currentUserId,\n isOrgAdmin: input.isOrgAdmin,\n updatedAt: input.now,\n };\n await input.tx\n .insert(organizationReadModelRequesters)\n .values(requesterRow)\n .onConflictDoUpdate({\n target: [\n organizationReadModelRequesters.organizationId,\n organizationReadModelRequesters.userId,\n ],\n set: {\n isOrgAdmin: requesterRow.isOrgAdmin,\n updatedAt: requesterRow.updatedAt,\n },\n })\n .run();\n // Storing an authoritative response proves access: retire the durable\n // denial marker for this scope in the same transaction.\n await clearOrganizationPresentationDenialInTransaction({\n organizationId: input.organizationId,\n projection: \"readModel\",\n requesterUserId: input.currentUserId,\n tx: input.tx,\n });\n}\n\nasync function replaceGroupsLane(input: {\n readonly groups: ListOrganizationGroupsResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n // Hydrated names and delivered membership heads outlive a catalog\n // replacement; the groupMemberships lane rebinds any head that changed.\n const previousGroups = await input.tx\n .select({\n groupId: organizationReadModelGroups.groupId,\n membersStateHash: organizationReadModelGroups.membersStateHash,\n name: organizationReadModelGroups.name,\n })\n .from(organizationReadModelGroups)\n .where(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n );\n const previousById = new Map(\n previousGroups.map((group) => [group.groupId, group]),\n );\n await input.tx\n .delete(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n\n const rows = input.groups.groups.map((group, sortOrder) => ({\n organizationId: input.organizationId,\n groupId: group.groupId,\n sortOrder,\n name: previousById.get(group.groupId)?.name ?? \"\",\n createdAt: group.createdAt,\n isBuiltin: group.isBuiltin,\n stateHash: group.currentState?.stateHash ?? null,\n stateVersion: group.currentState?.version ?? null,\n keyEpoch: group.currentState?.keyEpoch ?? null,\n keyFingerprint: group.currentState?.keyFingerprint ?? null,\n memberCount: group.currentState?.memberCount ?? null,\n membersStateHash: previousById.get(group.groupId)?.membersStateHash ?? null,\n }));\n for (let index = 0; index < rows.length; index += GROUP_INSERT_BATCH_SIZE) {\n await input.tx\n .insert(organizationReadModelGroups)\n .values(rows.slice(index, index + GROUP_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function loadCurrentState(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<CurrentOrganizationReadModelState | null> {\n const [current] = await tx\n .select({\n cursor: organizationReadModelState.cursor,\n keyEpoch: organizationReadModelState.organizationKeyEpoch,\n keyFingerprint: organizationReadModelState.organizationKeyFingerprint,\n memberCount: organizationReadModelState.organizationMemberCount,\n memberGroupId: organizationReadModelState.memberGroupId,\n memberGroupStateHash: organizationReadModelState.memberGroupStateHash,\n profileDocumentId: organizationReadModelState.profileDocumentId,\n stateHash: organizationReadModelState.organizationStateHash,\n version: organizationReadModelState.organizationStateVersion,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, organizationId))\n .limit(1);\n if (!current) {\n return null;\n }\n const { keyEpoch, keyFingerprint, memberCount, stateHash, version, ...rest } =\n current;\n return {\n ...rest,\n organizationHead: {\n keyEpoch,\n keyFingerprint,\n memberCount,\n stateHash,\n version,\n },\n };\n}\n\nfunction resolveApplyDisposition(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): ApplyOrganizationReadModelResponseResult | null {\n const currentCursor = input.current?.cursor ?? null;\n if (currentCursor !== input.requestedCursor) {\n return currentCursor === input.response.nextCursor\n ? \"already-applied\"\n : \"stale\";\n }\n if (!input.current && input.response.mode !== \"snapshot\") {\n throw new Error(\"Organization read-model delta requires a local snapshot\");\n }\n return null;\n}\n\ninterface ResponseLanesInput {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly memberGroupId: string;\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}\n\n/** Apply every carried lane and return the reserved Members head. */\nasync function replaceResponseLanes(\n input: ResponseLanesInput,\n): Promise<string | null> {\n const { organizationId } = input.response;\n const directory = input.response.lanes.directory;\n if (directory) {\n await replaceDirectoryLane({ directory, organizationId, tx: input.tx });\n }\n const groups = input.response.lanes.groups;\n if (groups) {\n await replaceGroupsLane({ groups, organizationId, tx: input.tx });\n }\n const groupMemberships = input.response.lanes.groupMemberships;\n const memberGroupStateHash = groupMemberships\n ? await applyGroupMembershipsLane({\n currentMemberGroupStateHash:\n input.current?.memberGroupStateHash ?? null,\n lane: groupMemberships,\n memberGroupId: input.memberGroupId,\n organizationId,\n replaceAll: input.response.mode === \"snapshot\",\n tx: input.tx,\n })\n : (input.current?.memberGroupStateHash ?? null);\n const grants = input.response.lanes.grants;\n if (grants) {\n await applyOrganizationReadModelGrantsLane({\n lane: grants,\n organizationId,\n tx: input.tx,\n });\n }\n return memberGroupStateHash;\n}\n\nasync function applyResponseLanes(\n input: ResponseLanesInput & { readonly currentUserId: string },\n): Promise<string | null> {\n const memberGroupStateHash = await replaceResponseLanes(input);\n // The directory lane is the authoritative roster, already persisted above:\n // requester rows for users it no longer lists as active fall with it.\n if (input.response.lanes.directory) {\n await pruneInactiveOrganizationRequestersInTransaction({\n organizationId: input.response.organizationId,\n retainUserId: input.currentUserId,\n tx: input.tx,\n });\n }\n if (input.response.lanes.groups || input.response.lanes.groupMemberships) {\n await assertStoredGroupMembershipBindings({\n memberGroupId: input.memberGroupId,\n memberGroupStateHash,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n return memberGroupStateHash;\n}\n\n/**\n * Write the cursor with the organization policy head and the reserved Members\n * head in one row, so a failure anywhere in the page rolls them back together.\n */\nasync function upsertOrganizationReadModelState(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string | null;\n readonly now: string;\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const organizationHead =\n input.response.lanes.organizationPolicy?.currentState ??\n input.current?.organizationHead;\n if (!organizationHead || input.memberGroupStateHash === null) {\n throw new OrganizationReadModelBindingError(\n \"Organization read-model policy or Members head is missing\",\n );\n }\n const directoryLane = input.response.lanes.directory;\n const values = {\n cursor: input.response.nextCursor,\n profileDocumentId:\n directoryLane !== undefined\n ? directoryLane.profileDocumentId\n : (input.current?.profileDocumentId ?? null),\n memberGroupId: input.memberGroupId,\n memberGroupStateHash: input.memberGroupStateHash,\n organizationStateHash: organizationHead.stateHash,\n organizationStateVersion: organizationHead.version,\n organizationKeyEpoch: organizationHead.keyEpoch,\n organizationKeyFingerprint: organizationHead.keyFingerprint,\n organizationMemberCount: organizationHead.memberCount,\n updatedAt: input.now,\n };\n await input.tx\n .insert(organizationReadModelState)\n .values({ ...values, organizationId: input.response.organizationId })\n .onConflictDoUpdate({\n target: organizationReadModelState.organizationId,\n set: values,\n })\n .run();\n}\n\nfunction requireMemberGroupId(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly response: OrganizationReadModelResponse;\n}): string {\n const memberGroupId =\n input.response.lanes.groups?.memberGroupId ?? input.current?.memberGroupId;\n if (!memberGroupId) {\n throw new Error(\"Organization read-model member group is missing\");\n }\n return memberGroupId;\n}\n\nexport async function loadOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n currentUserId: string,\n): Promise<OrganizationReadModelProjection | null> {\n return loadWithOrganizationReadModelIntegrityPurge({\n execSql,\n organizationId,\n load: (tx) =>\n loadOrganizationReadModelProjectionInTransaction({\n currentUserId,\n organizationId,\n tx,\n }),\n });\n}\n\nexport async function applyOrganizationReadModelResponse(input: {\n readonly currentUserId: string;\n readonly execSql: ExecSql;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): Promise<ApplyOrganizationReadModelResponseResult> {\n assertOrganizationReadModelResponse({\n currentUserId: input.currentUserId,\n response: input.response,\n });\n // The requester prune below also retires pruned users' usage projections.\n await ensureSqlTables(input.execSql, [\n ...organizationReadModelTables,\n ...organizationDataUsageTables,\n ]);\n\n const disposition = await getClientSQLitePersistenceRuntime(\n input.execSql,\n ).transaction(\n async (tx): Promise<ApplyOrganizationReadModelResponseResult> => {\n const current = await loadCurrentState(tx, input.response.organizationId);\n const disposition = resolveApplyDisposition({\n current,\n requestedCursor: input.requestedCursor,\n response: input.response,\n });\n if (disposition === \"stale\") {\n return disposition;\n }\n const now = new Date().toISOString();\n await upsertRequester({\n currentUserId: input.currentUserId,\n isOrgAdmin: input.response.currentUser.isOrgAdmin,\n now,\n organizationId: input.response.organizationId,\n tx,\n });\n if (disposition === \"already-applied\") {\n return disposition;\n }\n const memberGroupId = requireMemberGroupId({\n current,\n response: input.response,\n });\n const memberGroupStateHash = await applyResponseLanes({\n current,\n currentUserId: input.currentUserId,\n memberGroupId,\n response: input.response,\n tx,\n });\n await upsertOrganizationReadModelState({\n current,\n memberGroupId,\n memberGroupStateHash,\n now,\n response: input.response,\n tx,\n });\n\n return \"applied\";\n },\n );\n // An applied change follows an organization hint or mutation; in-flight\n // operations recover the directory again instead of reusing their memo.\n if (disposition === \"applied\")\n getOrCreatePrincipalPolicyCoordinator(input.execSql).invalidateRecovery(\n input.response.organizationId,\n );\n return disposition;\n}\n\nexport async function purgeOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n options: { readonly onlyRequesterUserId?: string } = {},\n): Promise<void> {\n await ensureSqlTables(execSql, organizationReadModelTables);\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (tx) => {\n await purgeOrganizationReadModelProjectionInTransaction({\n onlyRequesterUserId: options.onlyRequesterUserId,\n organizationId,\n tx,\n });\n });\n}\n"]}
1
+ {"version":3,"file":"organizationReadModelPersistence.js","sourceRoot":"","sources":["organizationReadModelPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ListOrganizationGroupsResponse,\n OrganizationGroupCurrentStateResponse,\n OrganizationReadModelDirectoryResponse,\n OrganizationReadModelResponse,\n} from \"@tearleads/validators/response\";\nimport { eq } from \"drizzle-orm\";\nimport { getOrCreatePrincipalPolicyCoordinator } from \"../../principals/principalPolicyCoordinator\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport { organizationDataUsageTables } from \"../../sqlite/schema/organizationDataUsageSchema\";\nimport {\n organizationReadModelDirectoryUsers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/schema/organizationReadModelSchema\";\nimport { sqliteInsertBatchSize } from \"../../sqlite/sqliteBindBudget\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../../sqlite/sqlSchema\";\nimport { clearOrganizationPresentationDenialInTransaction } from \"./organizationPresentationDenialPersistence\";\nimport { applyOrganizationReadModelGrantsLane } from \"./organizationReadModelGrantPersistence\";\nimport {\n applyGroupMembershipsLane,\n assertStoredGroupMembershipBindings,\n OrganizationReadModelBindingError,\n} from \"./organizationReadModelMembershipPersistence\";\nimport {\n loadOrganizationReadModelProjectionInTransaction,\n type OrganizationReadModelProjection,\n} from \"./organizationReadModelProjection\";\nimport {\n loadWithOrganizationReadModelIntegrityPurge,\n pruneInactiveOrganizationRequestersInTransaction,\n purgeOrganizationReadModelProjectionInTransaction,\n} from \"./organizationReadModelPurge\";\nimport { assertOrganizationReadModelResponse } from \"./organizationReadModelResponseAssertions\";\n\nexport type { OrganizationReadModelProjection } from \"./organizationReadModelProjection\";\n\nconst DIRECTORY_INSERT_BATCH_SIZE = sqliteInsertBatchSize(\n organizationReadModelDirectoryUsers,\n);\nconst GROUP_INSERT_BATCH_SIZE = sqliteInsertBatchSize(\n organizationReadModelGroups,\n);\n\ntype ApplyOrganizationReadModelResponseResult =\n | \"already-applied\"\n | \"applied\"\n | \"stale\";\n\ninterface CurrentOrganizationReadModelState {\n readonly cursor: string;\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string;\n readonly organizationHead: OrganizationGroupCurrentStateResponse;\n readonly profileDocumentId: string | null;\n}\n\nasync function replaceDirectoryLane(input: {\n readonly directory: OrganizationReadModelDirectoryResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelDirectoryUsers)\n .where(\n eq(\n organizationReadModelDirectoryUsers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n\n const rows = input.directory.users.map((user, sortOrder) => ({\n organizationId: input.organizationId,\n userId: user.userId,\n sortOrder,\n signingKeyFingerprint: user.signingKeyFingerprint,\n signingPublicKey: user.signingPublicKey,\n encapsulationPublicKey: user.encapsulationPublicKey,\n encapsulationKeyFingerprint: user.encapsulationKeyFingerprint,\n isPersonalOrganizationOwner: user.isPersonalOrganizationOwner,\n createdAt: user.createdAt,\n status: user.status,\n profileDocumentId: user.profileDocumentId,\n joinedAt: user.joinedAt,\n updatedAt: user.updatedAt,\n disabledAt: user.disabledAt,\n disabledByUserId: user.disabledByUserId,\n }));\n for (\n let index = 0;\n index < rows.length;\n index += DIRECTORY_INSERT_BATCH_SIZE\n ) {\n await input.tx\n .insert(organizationReadModelDirectoryUsers)\n .values(rows.slice(index, index + DIRECTORY_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function upsertRequester(input: {\n readonly currentUserId: string;\n readonly isOrgAdmin: boolean;\n readonly now: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const requesterRow = {\n organizationId: input.organizationId,\n userId: input.currentUserId,\n isOrgAdmin: input.isOrgAdmin,\n updatedAt: input.now,\n };\n await input.tx\n .insert(organizationReadModelRequesters)\n .values(requesterRow)\n .onConflictDoUpdate({\n target: [\n organizationReadModelRequesters.organizationId,\n organizationReadModelRequesters.userId,\n ],\n set: {\n isOrgAdmin: requesterRow.isOrgAdmin,\n updatedAt: requesterRow.updatedAt,\n },\n })\n .run();\n // Storing an authoritative response proves access: retire the durable\n // denial marker for this scope in the same transaction.\n await clearOrganizationPresentationDenialInTransaction({\n organizationId: input.organizationId,\n projection: \"readModel\",\n requesterUserId: input.currentUserId,\n tx: input.tx,\n });\n}\n\nasync function replaceGroupsLane(input: {\n readonly groups: ListOrganizationGroupsResponse;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n // Hydrated names and delivered membership heads outlive a catalog\n // replacement; the groupMemberships lane rebinds any head that changed.\n const previousGroups = await input.tx\n .select({\n groupId: organizationReadModelGroups.groupId,\n membersStateHash: organizationReadModelGroups.membersStateHash,\n name: organizationReadModelGroups.name,\n })\n .from(organizationReadModelGroups)\n .where(\n eq(organizationReadModelGroups.organizationId, input.organizationId),\n );\n const previousById = new Map(\n previousGroups.map((group) => [group.groupId, group]),\n );\n await input.tx\n .delete(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n\n const rows = input.groups.groups.map((group, sortOrder) => ({\n organizationId: input.organizationId,\n groupId: group.groupId,\n sortOrder,\n name: previousById.get(group.groupId)?.name ?? \"\",\n createdAt: group.createdAt,\n isBuiltin: group.isBuiltin,\n stateHash: group.currentState?.stateHash ?? null,\n stateVersion: group.currentState?.version ?? null,\n keyEpoch: group.currentState?.keyEpoch ?? null,\n keyFingerprint: group.currentState?.keyFingerprint ?? null,\n memberCount: group.currentState?.memberCount ?? null,\n membersStateHash: previousById.get(group.groupId)?.membersStateHash ?? null,\n }));\n for (let index = 0; index < rows.length; index += GROUP_INSERT_BATCH_SIZE) {\n await input.tx\n .insert(organizationReadModelGroups)\n .values(rows.slice(index, index + GROUP_INSERT_BATCH_SIZE))\n .run();\n }\n}\n\nasync function loadCurrentState(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<CurrentOrganizationReadModelState | null> {\n const [current] = await tx\n .select({\n cursor: organizationReadModelState.cursor,\n keyEpoch: organizationReadModelState.organizationKeyEpoch,\n keyFingerprint: organizationReadModelState.organizationKeyFingerprint,\n memberCount: organizationReadModelState.organizationMemberCount,\n memberGroupId: organizationReadModelState.memberGroupId,\n memberGroupStateHash: organizationReadModelState.memberGroupStateHash,\n profileDocumentId: organizationReadModelState.profileDocumentId,\n stateHash: organizationReadModelState.organizationStateHash,\n version: organizationReadModelState.organizationStateVersion,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, organizationId))\n .limit(1);\n if (!current) {\n return null;\n }\n const { keyEpoch, keyFingerprint, memberCount, stateHash, version, ...rest } =\n current;\n return {\n ...rest,\n organizationHead: {\n keyEpoch,\n keyFingerprint,\n memberCount,\n stateHash,\n version,\n },\n };\n}\n\nfunction resolveApplyDisposition(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): ApplyOrganizationReadModelResponseResult | null {\n const currentCursor = input.current?.cursor ?? null;\n if (currentCursor !== input.requestedCursor) {\n return currentCursor === input.response.nextCursor\n ? \"already-applied\"\n : \"stale\";\n }\n if (!input.current && input.response.mode !== \"snapshot\") {\n throw new Error(\"Organization read-model delta requires a local snapshot\");\n }\n return null;\n}\n\ninterface ResponseLanesInput {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly memberGroupId: string;\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}\n\n/** Apply every carried lane and return the reserved Members head. */\nasync function replaceResponseLanes(\n input: ResponseLanesInput,\n): Promise<string | null> {\n const { organizationId } = input.response;\n const directory = input.response.lanes.directory;\n if (directory) {\n await replaceDirectoryLane({ directory, organizationId, tx: input.tx });\n }\n const groups = input.response.lanes.groups;\n if (groups) {\n await replaceGroupsLane({ groups, organizationId, tx: input.tx });\n }\n const groupMemberships = input.response.lanes.groupMemberships;\n const memberGroupStateHash = groupMemberships\n ? await applyGroupMembershipsLane({\n currentMemberGroupStateHash:\n input.current?.memberGroupStateHash ?? null,\n lane: groupMemberships,\n memberGroupId: input.memberGroupId,\n organizationId,\n replaceAll: input.response.mode === \"snapshot\",\n tx: input.tx,\n })\n : (input.current?.memberGroupStateHash ?? null);\n const grants = input.response.lanes.grants;\n if (grants) {\n await applyOrganizationReadModelGrantsLane({\n lane: grants,\n organizationId,\n tx: input.tx,\n });\n }\n return memberGroupStateHash;\n}\n\nasync function applyResponseLanes(\n input: ResponseLanesInput & { readonly currentUserId: string },\n): Promise<string | null> {\n const memberGroupStateHash = await replaceResponseLanes(input);\n // The directory lane is the authoritative roster, already persisted above:\n // requester rows for users it no longer lists as active fall with it.\n if (input.response.lanes.directory) {\n await pruneInactiveOrganizationRequestersInTransaction({\n organizationId: input.response.organizationId,\n retainUserId: input.currentUserId,\n tx: input.tx,\n });\n }\n if (input.response.lanes.groups || input.response.lanes.groupMemberships) {\n await assertStoredGroupMembershipBindings({\n memberGroupId: input.memberGroupId,\n memberGroupStateHash,\n organizationId: input.response.organizationId,\n tx: input.tx,\n });\n }\n return memberGroupStateHash;\n}\n\n/**\n * Write the cursor with the organization policy head and the reserved Members\n * head in one row, so a failure anywhere in the page rolls them back together.\n */\nasync function upsertOrganizationReadModelState(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly memberGroupId: string;\n readonly memberGroupStateHash: string | null;\n readonly now: string;\n readonly response: OrganizationReadModelResponse;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const organizationHead =\n input.response.lanes.organizationPolicy?.currentState ??\n input.current?.organizationHead;\n if (!organizationHead || input.memberGroupStateHash === null) {\n throw new OrganizationReadModelBindingError(\n \"Organization read-model policy or Members head is missing\",\n );\n }\n const directoryLane = input.response.lanes.directory;\n const values = {\n cursor: input.response.nextCursor,\n profileDocumentId:\n directoryLane !== undefined\n ? directoryLane.profileDocumentId\n : (input.current?.profileDocumentId ?? null),\n memberGroupId: input.memberGroupId,\n memberGroupStateHash: input.memberGroupStateHash,\n organizationStateHash: organizationHead.stateHash,\n organizationStateVersion: organizationHead.version,\n organizationKeyEpoch: organizationHead.keyEpoch,\n organizationKeyFingerprint: organizationHead.keyFingerprint,\n organizationMemberCount: organizationHead.memberCount,\n updatedAt: input.now,\n };\n await input.tx\n .insert(organizationReadModelState)\n .values({ ...values, organizationId: input.response.organizationId })\n .onConflictDoUpdate({\n target: organizationReadModelState.organizationId,\n set: values,\n })\n .run();\n}\n\nfunction requireMemberGroupId(input: {\n readonly current: CurrentOrganizationReadModelState | null;\n readonly response: OrganizationReadModelResponse;\n}): string {\n const memberGroupId =\n input.response.lanes.groups?.memberGroupId ?? input.current?.memberGroupId;\n if (!memberGroupId) {\n throw new Error(\"Organization read-model member group is missing\");\n }\n return memberGroupId;\n}\n\nexport async function loadOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n currentUserId: string,\n): Promise<OrganizationReadModelProjection | null> {\n return loadWithOrganizationReadModelIntegrityPurge({\n execSql,\n organizationId,\n load: (tx) =>\n loadOrganizationReadModelProjectionInTransaction({\n currentUserId,\n organizationId,\n tx,\n }),\n });\n}\n\nexport async function applyOrganizationReadModelResponse(input: {\n readonly currentUserId: string;\n readonly execSql: ExecSql;\n readonly requestedCursor: string | null;\n readonly response: OrganizationReadModelResponse;\n}): Promise<ApplyOrganizationReadModelResponseResult> {\n assertOrganizationReadModelResponse({\n currentUserId: input.currentUserId,\n response: input.response,\n });\n // The requester prune below also retires pruned users' usage projections.\n await ensureSqlTables(input.execSql, [\n ...organizationReadModelTables,\n ...organizationDataUsageTables,\n ]);\n\n const disposition = await getClientSQLitePersistenceRuntime(\n input.execSql,\n ).transaction(\n async (tx): Promise<ApplyOrganizationReadModelResponseResult> => {\n const current = await loadCurrentState(tx, input.response.organizationId);\n const disposition = resolveApplyDisposition({\n current,\n requestedCursor: input.requestedCursor,\n response: input.response,\n });\n if (disposition === \"stale\") {\n return disposition;\n }\n const now = new Date().toISOString();\n await upsertRequester({\n currentUserId: input.currentUserId,\n isOrgAdmin: input.response.currentUser.isOrgAdmin,\n now,\n organizationId: input.response.organizationId,\n tx,\n });\n if (disposition === \"already-applied\") {\n return disposition;\n }\n const memberGroupId = requireMemberGroupId({\n current,\n response: input.response,\n });\n const memberGroupStateHash = await applyResponseLanes({\n current,\n currentUserId: input.currentUserId,\n memberGroupId,\n response: input.response,\n tx,\n });\n await upsertOrganizationReadModelState({\n current,\n memberGroupId,\n memberGroupStateHash,\n now,\n response: input.response,\n tx,\n });\n\n return \"applied\";\n },\n );\n // An applied change follows an organization hint or mutation; in-flight\n // operations recover the directory again instead of reusing their memo.\n if (disposition === \"applied\")\n getOrCreatePrincipalPolicyCoordinator(input.execSql).invalidateRecovery(\n input.response.organizationId,\n );\n return disposition;\n}\n\nexport async function purgeOrganizationReadModelProjection(\n execSql: ExecSql,\n organizationId: string,\n options: { readonly onlyRequesterUserId?: string } = {},\n): Promise<void> {\n await ensureSqlTables(execSql, organizationReadModelTables);\n await getClientSQLitePersistenceRuntime(execSql).transaction(async (tx) => {\n await purgeOrganizationReadModelProjectionInTransaction({\n onlyRequesterUserId: options.onlyRequesterUserId,\n organizationId,\n tx,\n });\n });\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { compareCanonicalStrings } from "../../../internal/crypto/index.js";
2
2
  import { and, asc, eq } from "drizzle-orm";
3
- import { organizationReadModelDirectoryUsers, organizationReadModelGroupMembers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/organizationReadModelSchema.js";
3
+ import { organizationReadModelDirectoryUsers, organizationReadModelGroupMembers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/schema/organizationReadModelSchema.js";
4
4
  import { loadOrganizationReadModelGrantsInTransaction } from "./organizationReadModelGrantPersistence.js";
5
5
  import { ORGANIZATION_READ_MODEL_PROTOCOL_VERSION, OrganizationReadModelIntegrityError, } from "./organizationReadModelProtocol.js";
6
6
  function isOrganizationRosterStatus(value) {
@@ -1 +1 @@
1
- {"version":3,"file":"organizationReadModelProjection.js","sourceRoot":"","sources":["organizationReadModelProjection.ts"],"names":[],"mappings":"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","sourcesContent":["import { compareCanonicalStrings } from \"@tearleads/crypto\";\nimport type {\n ListOrganizationGroupsResponse,\n OrganizationContainerGrantsResponse,\n OrganizationDirectoryResponse,\n OrganizationDirectoryUserResponse,\n OrganizationGroupCurrentStateResponse,\n OrganizationRosterStatus,\n} from \"@tearleads/validators/response\";\nimport { and, asc, eq } from \"drizzle-orm\";\nimport {\n organizationReadModelDirectoryUsers,\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { loadOrganizationReadModelGrantsInTransaction } from \"./organizationReadModelGrantPersistence\";\nimport {\n ORGANIZATION_READ_MODEL_PROTOCOL_VERSION,\n OrganizationReadModelIntegrityError,\n} from \"./organizationReadModelProtocol\";\n\nexport type OrganizationDirectoryProjection = Omit<\n OrganizationDirectoryResponse,\n \"currentUser\"\n>;\n\nexport interface OrganizationReadModelProjection {\n readonly cursor: string;\n readonly directory: OrganizationDirectoryProjection;\n readonly grants: OrganizationContainerGrantsResponse;\n readonly groups: Omit<ListOrganizationGroupsResponse, \"groups\"> & {\n groups: Array<\n ListOrganizationGroupsResponse[\"groups\"][number] & { name: string }\n >;\n };\n readonly membershipEdges: OrganizationReadModelMembershipEdge[];\n readonly organizationId: string;\n readonly policyHeads: readonly OrganizationReadModelPolicyHead[];\n readonly protocolVersion: typeof ORGANIZATION_READ_MODEL_PROTOCOL_VERSION;\n readonly requester: OrganizationDirectoryResponse[\"currentUser\"] | null;\n readonly updatedAt: string;\n}\n\nexport interface OrganizationReadModelPolicyHead {\n readonly keyEpoch: number;\n readonly keyFingerprint: string;\n readonly memberCount: number;\n readonly organizationId: string;\n readonly principalId: string;\n readonly principalType: \"group\" | \"organization\";\n readonly stateHash: string;\n readonly version: number;\n}\n\nexport interface OrganizationReadModelMembershipEdge {\n readonly groupId: string;\n readonly userId: string;\n}\n\ninterface SelectedDirectoryUser {\n readonly createdAt: string;\n readonly disabledAt: string | null;\n readonly disabledByUserId: string | null;\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: string;\n readonly isPersonalOrganizationOwner: boolean;\n readonly joinedAt: string;\n readonly profileDocumentId: string | null;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: string;\n readonly status: string;\n readonly updatedAt: string;\n readonly userId: string;\n}\n\ninterface SelectedGroup {\n readonly createdAt: string;\n readonly groupId: string;\n readonly isBuiltin: boolean;\n readonly keyEpoch: number | null;\n readonly keyFingerprint: string | null;\n readonly memberCount: number | null;\n readonly name: string;\n readonly stateHash: string | null;\n readonly stateVersion: number | null;\n}\n\n/** A stored policy head before validation; `version` is the state version. */\ninterface StoredPolicyHead {\n readonly keyEpoch: number;\n readonly keyFingerprint: string;\n readonly memberCount: number;\n readonly stateHash: string;\n readonly version: number;\n}\n\nfunction isOrganizationRosterStatus(\n value: string,\n): value is OrganizationRosterStatus {\n return value === \"active\" || value === \"disabled\";\n}\n\nfunction toDirectoryUser(\n row: SelectedDirectoryUser,\n currentUserId: string,\n): OrganizationDirectoryUserResponse {\n if (!isOrganizationRosterStatus(row.status)) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization directory status is invalid\",\n );\n }\n\n return {\n userId: row.userId,\n signingKeyFingerprint: row.signingKeyFingerprint,\n signingPublicKey: row.signingPublicKey,\n encapsulationPublicKey: row.encapsulationPublicKey,\n encapsulationKeyFingerprint: row.encapsulationKeyFingerprint,\n createdAt: row.createdAt,\n isPersonalOrganizationOwner: row.isPersonalOrganizationOwner,\n isSelf: row.userId === currentUserId,\n status: row.status,\n profileDocumentId: row.profileDocumentId,\n joinedAt: row.joinedAt,\n updatedAt: row.updatedAt,\n disabledAt: row.disabledAt,\n disabledByUserId: row.disabledByUserId,\n };\n}\n\nfunction isValidPolicyHead(head: StoredPolicyHead): boolean {\n return (\n head.stateHash.length > 0 &&\n Number.isInteger(head.version) &&\n head.version > 0 &&\n Number.isSafeInteger(head.keyEpoch) &&\n head.keyEpoch > 0 &&\n head.keyFingerprint.length > 0 &&\n Number.isInteger(head.memberCount) &&\n head.memberCount >= 0\n );\n}\n\n/** A group's state columns are all null (stateless) or one valid head. */\nfunction toGroupCurrentState(\n row: SelectedGroup,\n): OrganizationGroupCurrentStateResponse | null {\n const values = [\n row.stateHash,\n row.stateVersion,\n row.keyEpoch,\n row.keyFingerprint,\n row.memberCount,\n ];\n if (values.every((value) => value === null)) {\n return null;\n }\n const head =\n row.stateHash === null ||\n row.stateVersion === null ||\n row.keyEpoch === null ||\n row.keyFingerprint === null ||\n row.memberCount === null\n ? null\n : {\n stateHash: row.stateHash,\n version: row.stateVersion,\n keyEpoch: row.keyEpoch,\n keyFingerprint: row.keyFingerprint,\n memberCount: row.memberCount,\n };\n if (!head || !isValidPolicyHead(head)) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group state is invalid\",\n );\n }\n return head;\n}\n\nfunction toOrganizationPolicyHead(\n organizationId: string,\n head: StoredPolicyHead,\n): OrganizationReadModelPolicyHead {\n if (!isValidPolicyHead(head)) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization policy head is invalid\",\n );\n }\n return {\n ...head,\n organizationId,\n principalId: organizationId,\n principalType: \"organization\",\n };\n}\n\n/** The organization head from the state row plus every stateful group head. */\nfunction toProjectionPolicyHeads(input: {\n readonly groups: ReadonlyArray<{\n readonly currentState: OrganizationGroupCurrentStateResponse | null;\n readonly groupId: string;\n }>;\n readonly organizationHead: StoredPolicyHead;\n readonly organizationId: string;\n}): OrganizationReadModelPolicyHead[] {\n const groupHeads = input.groups\n .flatMap((group): OrganizationReadModelPolicyHead[] =>\n group.currentState\n ? [\n {\n ...group.currentState,\n organizationId: input.organizationId,\n principalId: group.groupId,\n principalType: \"group\",\n },\n ]\n : [],\n )\n .sort((left, right) =>\n compareCanonicalStrings(left.principalId, right.principalId),\n );\n // Group heads precede the organization head, ordered by principal ID.\n return [\n ...groupHeads,\n toOrganizationPolicyHead(input.organizationId, input.organizationHead),\n ];\n}\n\nasync function loadDirectoryRows(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<SelectedDirectoryUser[]> {\n return tx\n .select({\n createdAt: organizationReadModelDirectoryUsers.createdAt,\n disabledAt: organizationReadModelDirectoryUsers.disabledAt,\n disabledByUserId: organizationReadModelDirectoryUsers.disabledByUserId,\n encapsulationKeyFingerprint:\n organizationReadModelDirectoryUsers.encapsulationKeyFingerprint,\n encapsulationPublicKey:\n organizationReadModelDirectoryUsers.encapsulationPublicKey,\n joinedAt: organizationReadModelDirectoryUsers.joinedAt,\n isPersonalOrganizationOwner:\n organizationReadModelDirectoryUsers.isPersonalOrganizationOwner,\n profileDocumentId: organizationReadModelDirectoryUsers.profileDocumentId,\n signingKeyFingerprint:\n organizationReadModelDirectoryUsers.signingKeyFingerprint,\n signingPublicKey: organizationReadModelDirectoryUsers.signingPublicKey,\n status: organizationReadModelDirectoryUsers.status,\n updatedAt: organizationReadModelDirectoryUsers.updatedAt,\n userId: organizationReadModelDirectoryUsers.userId,\n })\n .from(organizationReadModelDirectoryUsers)\n .where(\n eq(organizationReadModelDirectoryUsers.organizationId, organizationId),\n )\n .orderBy(\n asc(organizationReadModelDirectoryUsers.sortOrder),\n asc(organizationReadModelDirectoryUsers.userId),\n );\n}\n\nasync function loadGroupRows(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<SelectedGroup[]> {\n return tx\n .select({\n createdAt: organizationReadModelGroups.createdAt,\n groupId: organizationReadModelGroups.groupId,\n isBuiltin: organizationReadModelGroups.isBuiltin,\n keyEpoch: organizationReadModelGroups.keyEpoch,\n keyFingerprint: organizationReadModelGroups.keyFingerprint,\n memberCount: organizationReadModelGroups.memberCount,\n name: organizationReadModelGroups.name,\n stateHash: organizationReadModelGroups.stateHash,\n stateVersion: organizationReadModelGroups.stateVersion,\n })\n .from(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, organizationId))\n .orderBy(\n asc(organizationReadModelGroups.sortOrder),\n asc(organizationReadModelGroups.groupId),\n );\n}\n\nasync function loadMembershipEdges(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<OrganizationReadModelMembershipEdge[]> {\n return tx\n .select({\n groupId: organizationReadModelGroupMembers.groupId,\n userId: organizationReadModelGroupMembers.userId,\n })\n .from(organizationReadModelGroupMembers)\n .where(eq(organizationReadModelGroupMembers.organizationId, organizationId))\n .orderBy(\n asc(organizationReadModelGroupMembers.groupId),\n asc(organizationReadModelGroupMembers.sortOrder),\n asc(organizationReadModelGroupMembers.userId),\n );\n}\n\nexport async function loadOrganizationReadModelProjectionInTransaction(input: {\n readonly currentUserId: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<OrganizationReadModelProjection | null> {\n const [state] = await input.tx\n .select({\n cursor: organizationReadModelState.cursor,\n memberGroupId: organizationReadModelState.memberGroupId,\n organizationKeyEpoch: organizationReadModelState.organizationKeyEpoch,\n organizationKeyFingerprint:\n organizationReadModelState.organizationKeyFingerprint,\n organizationMemberCount:\n organizationReadModelState.organizationMemberCount,\n organizationStateHash: organizationReadModelState.organizationStateHash,\n organizationStateVersion:\n organizationReadModelState.organizationStateVersion,\n profileDocumentId: organizationReadModelState.profileDocumentId,\n updatedAt: organizationReadModelState.updatedAt,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, input.organizationId))\n .limit(1);\n if (!state) {\n return null;\n }\n const [requester] = await input.tx\n .select({ isOrgAdmin: organizationReadModelRequesters.isOrgAdmin })\n .from(organizationReadModelRequesters)\n .where(\n and(\n eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n ),\n eq(organizationReadModelRequesters.userId, input.currentUserId),\n ),\n )\n .limit(1);\n const directoryRows = await loadDirectoryRows(input.tx, input.organizationId);\n const groupRows = await loadGroupRows(input.tx, input.organizationId);\n const grants = await loadOrganizationReadModelGrantsInTransaction(input);\n const membershipEdges = await loadMembershipEdges(\n input.tx,\n input.organizationId,\n );\n const groups = groupRows.map((row) => ({\n groupId: row.groupId,\n organizationId: input.organizationId,\n name: row.name,\n createdAt: row.createdAt,\n isBuiltin: row.isBuiltin,\n currentState: toGroupCurrentState(row),\n }));\n const policyHeads = toProjectionPolicyHeads({\n groups,\n organizationHead: {\n keyEpoch: state.organizationKeyEpoch,\n keyFingerprint: state.organizationKeyFingerprint,\n memberCount: state.organizationMemberCount,\n stateHash: state.organizationStateHash,\n version: state.organizationStateVersion,\n },\n organizationId: input.organizationId,\n });\n\n return {\n cursor: state.cursor,\n directory: {\n organizationId: input.organizationId,\n profileDocumentId: state.profileDocumentId,\n users: directoryRows.map((row) =>\n toDirectoryUser(row, input.currentUserId),\n ),\n },\n grants,\n groups: {\n organizationId: input.organizationId,\n memberGroupId: state.memberGroupId,\n groups,\n },\n membershipEdges,\n organizationId: input.organizationId,\n policyHeads,\n protocolVersion: ORGANIZATION_READ_MODEL_PROTOCOL_VERSION,\n requester: requester ? { isOrgAdmin: requester.isOrgAdmin } : null,\n updatedAt: state.updatedAt,\n };\n}\n"]}
1
+ {"version":3,"file":"organizationReadModelProjection.js","sourceRoot":"","sources":["organizationReadModelProjection.ts"],"names":[],"mappings":"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","sourcesContent":["import { compareCanonicalStrings } from \"@tearleads/crypto\";\nimport type {\n ListOrganizationGroupsResponse,\n OrganizationContainerGrantsResponse,\n OrganizationDirectoryResponse,\n OrganizationDirectoryUserResponse,\n OrganizationGroupCurrentStateResponse,\n OrganizationRosterStatus,\n} from \"@tearleads/validators/response\";\nimport { and, asc, eq } from \"drizzle-orm\";\nimport {\n organizationReadModelDirectoryUsers,\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/schema/organizationReadModelSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { loadOrganizationReadModelGrantsInTransaction } from \"./organizationReadModelGrantPersistence\";\nimport {\n ORGANIZATION_READ_MODEL_PROTOCOL_VERSION,\n OrganizationReadModelIntegrityError,\n} from \"./organizationReadModelProtocol\";\n\nexport type OrganizationDirectoryProjection = Omit<\n OrganizationDirectoryResponse,\n \"currentUser\"\n>;\n\nexport interface OrganizationReadModelProjection {\n readonly cursor: string;\n readonly directory: OrganizationDirectoryProjection;\n readonly grants: OrganizationContainerGrantsResponse;\n readonly groups: Omit<ListOrganizationGroupsResponse, \"groups\"> & {\n groups: Array<\n ListOrganizationGroupsResponse[\"groups\"][number] & { name: string }\n >;\n };\n readonly membershipEdges: OrganizationReadModelMembershipEdge[];\n readonly organizationId: string;\n readonly policyHeads: readonly OrganizationReadModelPolicyHead[];\n readonly protocolVersion: typeof ORGANIZATION_READ_MODEL_PROTOCOL_VERSION;\n readonly requester: OrganizationDirectoryResponse[\"currentUser\"] | null;\n readonly updatedAt: string;\n}\n\nexport interface OrganizationReadModelPolicyHead {\n readonly keyEpoch: number;\n readonly keyFingerprint: string;\n readonly memberCount: number;\n readonly organizationId: string;\n readonly principalId: string;\n readonly principalType: \"group\" | \"organization\";\n readonly stateHash: string;\n readonly version: number;\n}\n\nexport interface OrganizationReadModelMembershipEdge {\n readonly groupId: string;\n readonly userId: string;\n}\n\ninterface SelectedDirectoryUser {\n readonly createdAt: string;\n readonly disabledAt: string | null;\n readonly disabledByUserId: string | null;\n readonly encapsulationKeyFingerprint: string;\n readonly encapsulationPublicKey: string;\n readonly isPersonalOrganizationOwner: boolean;\n readonly joinedAt: string;\n readonly profileDocumentId: string | null;\n readonly signingKeyFingerprint: string;\n readonly signingPublicKey: string;\n readonly status: string;\n readonly updatedAt: string;\n readonly userId: string;\n}\n\ninterface SelectedGroup {\n readonly createdAt: string;\n readonly groupId: string;\n readonly isBuiltin: boolean;\n readonly keyEpoch: number | null;\n readonly keyFingerprint: string | null;\n readonly memberCount: number | null;\n readonly name: string;\n readonly stateHash: string | null;\n readonly stateVersion: number | null;\n}\n\n/** A stored policy head before validation; `version` is the state version. */\ninterface StoredPolicyHead {\n readonly keyEpoch: number;\n readonly keyFingerprint: string;\n readonly memberCount: number;\n readonly stateHash: string;\n readonly version: number;\n}\n\nfunction isOrganizationRosterStatus(\n value: string,\n): value is OrganizationRosterStatus {\n return value === \"active\" || value === \"disabled\";\n}\n\nfunction toDirectoryUser(\n row: SelectedDirectoryUser,\n currentUserId: string,\n): OrganizationDirectoryUserResponse {\n if (!isOrganizationRosterStatus(row.status)) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization directory status is invalid\",\n );\n }\n\n return {\n userId: row.userId,\n signingKeyFingerprint: row.signingKeyFingerprint,\n signingPublicKey: row.signingPublicKey,\n encapsulationPublicKey: row.encapsulationPublicKey,\n encapsulationKeyFingerprint: row.encapsulationKeyFingerprint,\n createdAt: row.createdAt,\n isPersonalOrganizationOwner: row.isPersonalOrganizationOwner,\n isSelf: row.userId === currentUserId,\n status: row.status,\n profileDocumentId: row.profileDocumentId,\n joinedAt: row.joinedAt,\n updatedAt: row.updatedAt,\n disabledAt: row.disabledAt,\n disabledByUserId: row.disabledByUserId,\n };\n}\n\nfunction isValidPolicyHead(head: StoredPolicyHead): boolean {\n return (\n head.stateHash.length > 0 &&\n Number.isInteger(head.version) &&\n head.version > 0 &&\n Number.isSafeInteger(head.keyEpoch) &&\n head.keyEpoch > 0 &&\n head.keyFingerprint.length > 0 &&\n Number.isInteger(head.memberCount) &&\n head.memberCount >= 0\n );\n}\n\n/** A group's state columns are all null (stateless) or one valid head. */\nfunction toGroupCurrentState(\n row: SelectedGroup,\n): OrganizationGroupCurrentStateResponse | null {\n const values = [\n row.stateHash,\n row.stateVersion,\n row.keyEpoch,\n row.keyFingerprint,\n row.memberCount,\n ];\n if (values.every((value) => value === null)) {\n return null;\n }\n const head =\n row.stateHash === null ||\n row.stateVersion === null ||\n row.keyEpoch === null ||\n row.keyFingerprint === null ||\n row.memberCount === null\n ? null\n : {\n stateHash: row.stateHash,\n version: row.stateVersion,\n keyEpoch: row.keyEpoch,\n keyFingerprint: row.keyFingerprint,\n memberCount: row.memberCount,\n };\n if (!head || !isValidPolicyHead(head)) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization group state is invalid\",\n );\n }\n return head;\n}\n\nfunction toOrganizationPolicyHead(\n organizationId: string,\n head: StoredPolicyHead,\n): OrganizationReadModelPolicyHead {\n if (!isValidPolicyHead(head)) {\n throw new OrganizationReadModelIntegrityError(\n \"Stored organization policy head is invalid\",\n );\n }\n return {\n ...head,\n organizationId,\n principalId: organizationId,\n principalType: \"organization\",\n };\n}\n\n/** The organization head from the state row plus every stateful group head. */\nfunction toProjectionPolicyHeads(input: {\n readonly groups: ReadonlyArray<{\n readonly currentState: OrganizationGroupCurrentStateResponse | null;\n readonly groupId: string;\n }>;\n readonly organizationHead: StoredPolicyHead;\n readonly organizationId: string;\n}): OrganizationReadModelPolicyHead[] {\n const groupHeads = input.groups\n .flatMap((group): OrganizationReadModelPolicyHead[] =>\n group.currentState\n ? [\n {\n ...group.currentState,\n organizationId: input.organizationId,\n principalId: group.groupId,\n principalType: \"group\",\n },\n ]\n : [],\n )\n .sort((left, right) =>\n compareCanonicalStrings(left.principalId, right.principalId),\n );\n // Group heads precede the organization head, ordered by principal ID.\n return [\n ...groupHeads,\n toOrganizationPolicyHead(input.organizationId, input.organizationHead),\n ];\n}\n\nasync function loadDirectoryRows(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<SelectedDirectoryUser[]> {\n return tx\n .select({\n createdAt: organizationReadModelDirectoryUsers.createdAt,\n disabledAt: organizationReadModelDirectoryUsers.disabledAt,\n disabledByUserId: organizationReadModelDirectoryUsers.disabledByUserId,\n encapsulationKeyFingerprint:\n organizationReadModelDirectoryUsers.encapsulationKeyFingerprint,\n encapsulationPublicKey:\n organizationReadModelDirectoryUsers.encapsulationPublicKey,\n joinedAt: organizationReadModelDirectoryUsers.joinedAt,\n isPersonalOrganizationOwner:\n organizationReadModelDirectoryUsers.isPersonalOrganizationOwner,\n profileDocumentId: organizationReadModelDirectoryUsers.profileDocumentId,\n signingKeyFingerprint:\n organizationReadModelDirectoryUsers.signingKeyFingerprint,\n signingPublicKey: organizationReadModelDirectoryUsers.signingPublicKey,\n status: organizationReadModelDirectoryUsers.status,\n updatedAt: organizationReadModelDirectoryUsers.updatedAt,\n userId: organizationReadModelDirectoryUsers.userId,\n })\n .from(organizationReadModelDirectoryUsers)\n .where(\n eq(organizationReadModelDirectoryUsers.organizationId, organizationId),\n )\n .orderBy(\n asc(organizationReadModelDirectoryUsers.sortOrder),\n asc(organizationReadModelDirectoryUsers.userId),\n );\n}\n\nasync function loadGroupRows(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<SelectedGroup[]> {\n return tx\n .select({\n createdAt: organizationReadModelGroups.createdAt,\n groupId: organizationReadModelGroups.groupId,\n isBuiltin: organizationReadModelGroups.isBuiltin,\n keyEpoch: organizationReadModelGroups.keyEpoch,\n keyFingerprint: organizationReadModelGroups.keyFingerprint,\n memberCount: organizationReadModelGroups.memberCount,\n name: organizationReadModelGroups.name,\n stateHash: organizationReadModelGroups.stateHash,\n stateVersion: organizationReadModelGroups.stateVersion,\n })\n .from(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, organizationId))\n .orderBy(\n asc(organizationReadModelGroups.sortOrder),\n asc(organizationReadModelGroups.groupId),\n );\n}\n\nasync function loadMembershipEdges(\n tx: ClientSQLiteTransactionScope,\n organizationId: string,\n): Promise<OrganizationReadModelMembershipEdge[]> {\n return tx\n .select({\n groupId: organizationReadModelGroupMembers.groupId,\n userId: organizationReadModelGroupMembers.userId,\n })\n .from(organizationReadModelGroupMembers)\n .where(eq(organizationReadModelGroupMembers.organizationId, organizationId))\n .orderBy(\n asc(organizationReadModelGroupMembers.groupId),\n asc(organizationReadModelGroupMembers.sortOrder),\n asc(organizationReadModelGroupMembers.userId),\n );\n}\n\nexport async function loadOrganizationReadModelProjectionInTransaction(input: {\n readonly currentUserId: string;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<OrganizationReadModelProjection | null> {\n const [state] = await input.tx\n .select({\n cursor: organizationReadModelState.cursor,\n memberGroupId: organizationReadModelState.memberGroupId,\n organizationKeyEpoch: organizationReadModelState.organizationKeyEpoch,\n organizationKeyFingerprint:\n organizationReadModelState.organizationKeyFingerprint,\n organizationMemberCount:\n organizationReadModelState.organizationMemberCount,\n organizationStateHash: organizationReadModelState.organizationStateHash,\n organizationStateVersion:\n organizationReadModelState.organizationStateVersion,\n profileDocumentId: organizationReadModelState.profileDocumentId,\n updatedAt: organizationReadModelState.updatedAt,\n })\n .from(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, input.organizationId))\n .limit(1);\n if (!state) {\n return null;\n }\n const [requester] = await input.tx\n .select({ isOrgAdmin: organizationReadModelRequesters.isOrgAdmin })\n .from(organizationReadModelRequesters)\n .where(\n and(\n eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n ),\n eq(organizationReadModelRequesters.userId, input.currentUserId),\n ),\n )\n .limit(1);\n const directoryRows = await loadDirectoryRows(input.tx, input.organizationId);\n const groupRows = await loadGroupRows(input.tx, input.organizationId);\n const grants = await loadOrganizationReadModelGrantsInTransaction(input);\n const membershipEdges = await loadMembershipEdges(\n input.tx,\n input.organizationId,\n );\n const groups = groupRows.map((row) => ({\n groupId: row.groupId,\n organizationId: input.organizationId,\n name: row.name,\n createdAt: row.createdAt,\n isBuiltin: row.isBuiltin,\n currentState: toGroupCurrentState(row),\n }));\n const policyHeads = toProjectionPolicyHeads({\n groups,\n organizationHead: {\n keyEpoch: state.organizationKeyEpoch,\n keyFingerprint: state.organizationKeyFingerprint,\n memberCount: state.organizationMemberCount,\n stateHash: state.organizationStateHash,\n version: state.organizationStateVersion,\n },\n organizationId: input.organizationId,\n });\n\n return {\n cursor: state.cursor,\n directory: {\n organizationId: input.organizationId,\n profileDocumentId: state.profileDocumentId,\n users: directoryRows.map((row) =>\n toDirectoryUser(row, input.currentUserId),\n ),\n },\n grants,\n groups: {\n organizationId: input.organizationId,\n memberGroupId: state.memberGroupId,\n groups,\n },\n membershipEdges,\n organizationId: input.organizationId,\n policyHeads,\n protocolVersion: ORGANIZATION_READ_MODEL_PROTOCOL_VERSION,\n requester: requester ? { isOrgAdmin: requester.isOrgAdmin } : null,\n updatedAt: state.updatedAt,\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { and, eq, ne, notExists } from "drizzle-orm";
2
- import { organizationDataUsageSnapshots } from "../../sqlite/organizationDataUsageSchema.js";
3
- import { organizationReadModelContainerGrants, organizationReadModelDirectoryUsers, organizationReadModelGroupMembers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/organizationReadModelSchema.js";
4
- import { organizationReadModelTables } from "../../sqlite/schema.js";
2
+ import { organizationReadModelTables } from "../../sqlite/schema/index.js";
3
+ import { organizationDataUsageSnapshots } from "../../sqlite/schema/organizationDataUsageSchema.js";
4
+ import { organizationReadModelContainerGrants, organizationReadModelDirectoryUsers, organizationReadModelGroupMembers, organizationReadModelGroups, organizationReadModelRequesters, organizationReadModelState, } from "../../sqlite/schema/organizationReadModelSchema.js";
5
5
  import { getClientSQLitePersistenceRuntime, } from "../../sqlite/sqlitePersistenceRuntime.js";
6
6
  import { ensureSqlTables } from "../../sqlite/sqlSchema.js";
7
7
  import { notifyOrganizationReadModelInvalidated } from "./organizationReadModelInvalidation.js";
@@ -1 +1 @@
1
- {"version":3,"file":"organizationReadModelPurge.js","sourceRoot":"","sources":["organizationReadModelPurge.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, type Column, eq, ne, notExists, type SQL } from \"drizzle-orm\";\nimport { organizationDataUsageSnapshots } from \"../../sqlite/organizationDataUsageSchema\";\nimport {\n organizationReadModelContainerGrants,\n organizationReadModelDirectoryUsers,\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/organizationReadModelSchema\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../../sqlite/sqlSchema\";\nimport { notifyOrganizationReadModelInvalidated } from \"./organizationReadModelInvalidation\";\nimport { OrganizationReadModelIntegrityError } from \"./organizationReadModelProtocol\";\n\n/**\n * Rows for users the persisted directory does not list as active. The\n * exclusion is one anti-join against the directory rows rather than a bound\n * list, so an organization of any size fits SQLite's bound-variable budget.\n */\nfunction inactiveUserScope(\n input: {\n readonly organizationId: string;\n readonly retainUserId: string;\n readonly tx: ClientSQLiteTransactionScope;\n },\n organizationIdColumn: Column,\n userIdColumn: Column,\n): SQL | undefined {\n const directory = organizationReadModelDirectoryUsers;\n return and(\n eq(organizationIdColumn, input.organizationId),\n ne(userIdColumn, input.retainUserId),\n notExists(\n input.tx\n .select({ userId: directory.userId })\n .from(directory)\n .where(\n and(\n eq(directory.organizationId, input.organizationId),\n eq(directory.userId, userIdColumn),\n eq(directory.status, \"active\"),\n ),\n ),\n ),\n );\n}\n\n/**\n * Retire requester rows — and the requester-scoped usage projections beside\n * them — for users the just-applied authoritative directory no longer lists as\n * active. Without this, a removed member whose identity shares the database\n * keeps presentation access until it personally sees a 403. The applying\n * requester's own rows are never pruned here: the server response that\n * carried this directory already proved that user's access. The caller must\n * have replaced the organization's directory rows earlier in `tx`.\n */\nexport async function pruneInactiveOrganizationRequestersInTransaction(input: {\n readonly organizationId: string;\n readonly retainUserId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelRequesters)\n .where(\n inactiveUserScope(\n input,\n organizationReadModelRequesters.organizationId,\n organizationReadModelRequesters.userId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationDataUsageSnapshots)\n .where(\n inactiveUserScope(\n input,\n organizationDataUsageSnapshots.organizationId,\n organizationDataUsageSnapshots.requesterUserId,\n ),\n )\n .run();\n}\n\n/**\n * Delete the shared projection rows for one organization. By default every\n * requester row falls with them; `onlyRequesterUserId` scopes the requester\n * delete to that user for rebuilds where the shared rows are about to be\n * replaced authoritatively — other local identities keep their rows and read\n * the replacement instead of losing access until their own next reconcile.\n */\nexport async function purgeOrganizationReadModelProjectionInTransaction(input: {\n readonly onlyRequesterUserId?: string | undefined;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelContainerGrants)\n .where(\n eq(\n organizationReadModelContainerGrants.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelGroupMembers)\n .where(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelDirectoryUsers)\n .where(\n eq(\n organizationReadModelDirectoryUsers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n await input.tx\n .delete(organizationReadModelRequesters)\n .where(\n input.onlyRequesterUserId === undefined\n ? eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n )\n : and(\n eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n ),\n eq(\n organizationReadModelRequesters.userId,\n input.onlyRequesterUserId,\n ),\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, input.organizationId))\n .run();\n}\n\n/**\n * The ONE load shell for the durable read-model projection: run `load` in a\n * transaction and, if a stored row fails integrity validation, purge the\n * organization's projection and report null. The projection is a\n * server-refetchable cache, so the next reconcile requests a cursorless\n * snapshot instead of every read and repair pass failing on the same row.\n */\nexport async function loadWithOrganizationReadModelIntegrityPurge<T>(input: {\n readonly execSql: ExecSql;\n readonly load: (tx: ClientSQLiteTransactionScope) => Promise<T | null>;\n readonly organizationId: string;\n}): Promise<T | null> {\n await ensureSqlTables(input.execSql, organizationReadModelTables);\n let purgedInvalidRows = false;\n const result = await getClientSQLitePersistenceRuntime(\n input.execSql,\n ).transaction(async (tx) => {\n try {\n return await input.load(tx);\n } catch (error) {\n if (!(error instanceof OrganizationReadModelIntegrityError)) {\n throw error;\n }\n await purgeOrganizationReadModelProjectionInTransaction({\n organizationId: input.organizationId,\n tx,\n });\n purgedInvalidRows = true;\n return null;\n }\n });\n if (purgedInvalidRows) {\n // Realtime consumers may hold a caught-up lease over rows that no longer\n // exist; the notification lets them drop it and refetch authoritatively.\n notifyOrganizationReadModelInvalidated(input.execSql, input.organizationId);\n }\n return result;\n}\n"]}
1
+ {"version":3,"file":"organizationReadModelPurge.js","sourceRoot":"","sources":["organizationReadModelPurge.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, type Column, eq, ne, notExists, type SQL } from \"drizzle-orm\";\nimport { organizationReadModelTables } from \"../../sqlite/schema\";\nimport { organizationDataUsageSnapshots } from \"../../sqlite/schema/organizationDataUsageSchema\";\nimport {\n organizationReadModelContainerGrants,\n organizationReadModelDirectoryUsers,\n organizationReadModelGroupMembers,\n organizationReadModelGroups,\n organizationReadModelRequesters,\n organizationReadModelState,\n} from \"../../sqlite/schema/organizationReadModelSchema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../../sqlite/sqlSchema\";\nimport { notifyOrganizationReadModelInvalidated } from \"./organizationReadModelInvalidation\";\nimport { OrganizationReadModelIntegrityError } from \"./organizationReadModelProtocol\";\n\n/**\n * Rows for users the persisted directory does not list as active. The\n * exclusion is one anti-join against the directory rows rather than a bound\n * list, so an organization of any size fits SQLite's bound-variable budget.\n */\nfunction inactiveUserScope(\n input: {\n readonly organizationId: string;\n readonly retainUserId: string;\n readonly tx: ClientSQLiteTransactionScope;\n },\n organizationIdColumn: Column,\n userIdColumn: Column,\n): SQL | undefined {\n const directory = organizationReadModelDirectoryUsers;\n return and(\n eq(organizationIdColumn, input.organizationId),\n ne(userIdColumn, input.retainUserId),\n notExists(\n input.tx\n .select({ userId: directory.userId })\n .from(directory)\n .where(\n and(\n eq(directory.organizationId, input.organizationId),\n eq(directory.userId, userIdColumn),\n eq(directory.status, \"active\"),\n ),\n ),\n ),\n );\n}\n\n/**\n * Retire requester rows — and the requester-scoped usage projections beside\n * them — for users the just-applied authoritative directory no longer lists as\n * active. Without this, a removed member whose identity shares the database\n * keeps presentation access until it personally sees a 403. The applying\n * requester's own rows are never pruned here: the server response that\n * carried this directory already proved that user's access. The caller must\n * have replaced the organization's directory rows earlier in `tx`.\n */\nexport async function pruneInactiveOrganizationRequestersInTransaction(input: {\n readonly organizationId: string;\n readonly retainUserId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelRequesters)\n .where(\n inactiveUserScope(\n input,\n organizationReadModelRequesters.organizationId,\n organizationReadModelRequesters.userId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationDataUsageSnapshots)\n .where(\n inactiveUserScope(\n input,\n organizationDataUsageSnapshots.organizationId,\n organizationDataUsageSnapshots.requesterUserId,\n ),\n )\n .run();\n}\n\n/**\n * Delete the shared projection rows for one organization. By default every\n * requester row falls with them; `onlyRequesterUserId` scopes the requester\n * delete to that user for rebuilds where the shared rows are about to be\n * replaced authoritatively — other local identities keep their rows and read\n * the replacement instead of losing access until their own next reconcile.\n */\nexport async function purgeOrganizationReadModelProjectionInTransaction(input: {\n readonly onlyRequesterUserId?: string | undefined;\n readonly organizationId: string;\n readonly tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n await input.tx\n .delete(organizationReadModelContainerGrants)\n .where(\n eq(\n organizationReadModelContainerGrants.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelGroupMembers)\n .where(\n eq(\n organizationReadModelGroupMembers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelDirectoryUsers)\n .where(\n eq(\n organizationReadModelDirectoryUsers.organizationId,\n input.organizationId,\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelGroups)\n .where(eq(organizationReadModelGroups.organizationId, input.organizationId))\n .run();\n await input.tx\n .delete(organizationReadModelRequesters)\n .where(\n input.onlyRequesterUserId === undefined\n ? eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n )\n : and(\n eq(\n organizationReadModelRequesters.organizationId,\n input.organizationId,\n ),\n eq(\n organizationReadModelRequesters.userId,\n input.onlyRequesterUserId,\n ),\n ),\n )\n .run();\n await input.tx\n .delete(organizationReadModelState)\n .where(eq(organizationReadModelState.organizationId, input.organizationId))\n .run();\n}\n\n/**\n * The ONE load shell for the durable read-model projection: run `load` in a\n * transaction and, if a stored row fails integrity validation, purge the\n * organization's projection and report null. The projection is a\n * server-refetchable cache, so the next reconcile requests a cursorless\n * snapshot instead of every read and repair pass failing on the same row.\n */\nexport async function loadWithOrganizationReadModelIntegrityPurge<T>(input: {\n readonly execSql: ExecSql;\n readonly load: (tx: ClientSQLiteTransactionScope) => Promise<T | null>;\n readonly organizationId: string;\n}): Promise<T | null> {\n await ensureSqlTables(input.execSql, organizationReadModelTables);\n let purgedInvalidRows = false;\n const result = await getClientSQLitePersistenceRuntime(\n input.execSql,\n ).transaction(async (tx) => {\n try {\n return await input.load(tx);\n } catch (error) {\n if (!(error instanceof OrganizationReadModelIntegrityError)) {\n throw error;\n }\n await purgeOrganizationReadModelProjectionInTransaction({\n organizationId: input.organizationId,\n tx,\n });\n purgedInvalidRows = true;\n return null;\n }\n });\n if (purgedInvalidRows) {\n // Realtime consumers may hold a caught-up lease over rows that no longer\n // exist; the notification lets them drop it and refetch authoritatively.\n notifyOrganizationReadModelInvalidated(input.execSql, input.organizationId);\n }\n return result;\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { type PrincipalPolicyCheckpoint, type VerifiedPrincipalPolicyCurrent } from "../../internal/crypto/index.js";
2
2
  import { type ExecSql } from "../sqlite/sqlSchema.js";
3
- import { type PrincipalHistoryEvidencePage } from "./principalHistoryEvidencePersistence.js";
4
- import type { PrincipalHistoryPrefix } from "./principalHistoryPrefixPersistence.js";
5
- import type { PrincipalHistoryStage } from "./principalHistoryStagePersistence.js";
3
+ import { type PrincipalHistoryEvidencePage } from "./principalHistory/principalHistoryEvidencePersistence.js";
4
+ import type { PrincipalHistoryPrefix } from "./principalHistory/principalHistoryPrefixPersistence.js";
5
+ import type { PrincipalHistoryStage } from "./principalHistory/principalHistoryStagePersistence.js";
6
6
  /** Owned output of authenticated prefix extension and exact receipt verification. */
7
7
  export interface AcknowledgedPrincipalCurrentPublication {
8
8
  readonly policy: VerifiedPrincipalPolicyCurrent;
@@ -1,18 +1,18 @@
1
1
  import { KeyingVerificationError, verifyPrincipalPolicyCheckpoint, } from "../../internal/crypto/index.js";
2
2
  import { eq } from "drizzle-orm";
3
3
  import { assertProjectionVerificationCurrent } from "../keyingProjectionVerification/types.js";
4
- import { principalHistoryPrefixes } from "../sqlite/principalHistoryEvidenceSchema.js";
5
- import { principalHistoryStages } from "../sqlite/principalHistoryStageSchema.js";
6
- import { keyingCheckpointTables, principalPolicyTables, } from "../sqlite/schema.js";
4
+ import { keyingCheckpointTables, principalPolicyTables, } from "../sqlite/schema/index.js";
5
+ import { principalHistoryPrefixes } from "../sqlite/schema/principalHistoryEvidenceSchema.js";
6
+ import { principalHistoryStages } from "../sqlite/schema/principalHistoryStageSchema.js";
7
7
  import { getClientSQLitePersistenceRuntime, } from "../sqlite/sqlitePersistenceRuntime.js";
8
8
  import { ensureSqlTables } from "../sqlite/sqlSchema.js";
9
- import { loadStoredPrincipalPolicyCheckpoint, principalPolicyKey, upsertPrincipalPolicyCheckpointInTransaction, } from "./keyingCheckpointPersistence.js";
10
- import { storePrincipalGrantRetirements } from "./principalGrantRetirementPersistence.js";
11
- import { writePrincipalHistoryEvidencePage, } from "./principalHistoryEvidencePersistence.js";
12
- import { reclaimPrincipalHistoryNodes } from "./principalHistoryNodeRetention.js";
13
- import { retainPrincipalHistoryRoot } from "./principalHistoryRootOwnership.js";
14
- import { reclaimCompletedPrincipalHistoryStages, touchPrincipalHistoryStage, } from "./principalHistoryStageRetention.js";
15
- import { archivePrincipalHistoryKeyEnvelopes } from "./principalKeyEnvelopeArchivePersistence.js";
9
+ import { loadStoredPrincipalPolicyCheckpoint, principalPolicyKey, upsertPrincipalPolicyCheckpointInTransaction, } from "./keyingCheckpoints/keyingCheckpointPersistence.js";
10
+ import { writePrincipalHistoryEvidencePage, } from "./principalHistory/principalHistoryEvidencePersistence.js";
11
+ import { reclaimPrincipalHistoryNodes } from "./principalHistory/principalHistoryNodeRetention.js";
12
+ import { retainPrincipalHistoryRoot } from "./principalHistory/principalHistoryRootOwnership.js";
13
+ import { reclaimCompletedPrincipalHistoryStages, touchPrincipalHistoryStage, } from "./principalHistory/principalHistoryStageRetention.js";
14
+ import { storePrincipalGrantRetirements } from "./principalKeys/principalGrantRetirementPersistence.js";
15
+ import { archivePrincipalHistoryKeyEnvelopes } from "./principalKeys/principalKeyEnvelopeArchivePersistence.js";
16
16
  /** A local writer won the CAS; retry the same authenticated receipt without HTTP. */
17
17
  export class PrincipalAcknowledgementChangedError extends Error {
18
18
  constructor() {