@tearleads/client-sdk 0.1.15 → 0.1.17

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 (244) hide show
  1. package/client/Tearleads.d.ts +2 -0
  2. package/client/Tearleads.js +1 -0
  3. package/client/Tearleads.js.map +1 -1
  4. package/client/index.d.ts +1 -1
  5. package/client/index.js.map +1 -1
  6. package/client/organizations/currentPrincipalMutations.js +96 -0
  7. package/client/organizations/currentPrincipalMutations.js.map +1 -0
  8. package/client/organizations/index.d.ts +4 -42
  9. package/client/organizations/index.js +17 -3
  10. package/client/organizations/index.js.map +1 -1
  11. package/client/organizations/organizationGroupHistory.js +44 -0
  12. package/client/organizations/organizationGroupHistory.js.map +1 -0
  13. package/client/organizations/organizationGroupNameHydration.js +14 -1
  14. package/client/organizations/organizationGroupNameHydration.js.map +1 -1
  15. package/client/organizations/organizationGroupPresentation.d.ts +1 -0
  16. package/client/organizations/organizationGroupPresentation.js +16 -2
  17. package/client/organizations/organizationGroupPresentation.js.map +1 -1
  18. package/client/organizations/organizationReadModels.d.ts +1 -1
  19. package/client/organizations/organizationReadModels.js +11 -1
  20. package/client/organizations/organizationReadModels.js.map +1 -1
  21. package/client/organizations/organizationsTypes.d.ts +50 -0
  22. package/client/organizations/organizationsTypes.js +2 -0
  23. package/client/organizations/organizationsTypes.js.map +1 -0
  24. package/client/organizations/principalContainerMutations.js +2 -0
  25. package/client/organizations/principalContainerMutations.js.map +1 -1
  26. package/client/organizations/principalMutationRecovery.d.ts +16 -0
  27. package/client/organizations/principalMutationRecovery.js +23 -0
  28. package/client/organizations/principalMutationRecovery.js.map +1 -0
  29. package/client/organizations/principalMutationScope.js +7 -2
  30. package/client/organizations/principalMutationScope.js.map +1 -1
  31. package/client/organizations/principalMutations.d.ts +4 -308
  32. package/client/organizations/principalMutations.js +165 -87
  33. package/client/organizations/principalMutations.js.map +1 -1
  34. package/client/principalMutationApi.d.ts +24 -0
  35. package/client/principalMutationApi.js +108 -0
  36. package/client/principalMutationApi.js.map +1 -0
  37. package/client/principalMutationDeadline.js +23 -0
  38. package/client/principalMutationDeadline.js.map +1 -0
  39. package/client/workflowRuntime.d.ts +3 -1
  40. package/client/workflowRuntime.js +44 -5
  41. package/client/workflowRuntime.js.map +1 -1
  42. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +27 -0
  43. package/data/persistence/principalCurrentAcknowledgementPersistence.js +116 -0
  44. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -0
  45. package/data/persistence/principalGrantRetirementPersistence.d.ts +3 -3
  46. package/data/persistence/principalGrantRetirementPersistence.js +4 -1
  47. package/data/persistence/principalGrantRetirementPersistence.js.map +1 -1
  48. package/data/persistence/principalKeyEnvelopeCandidates.js +12 -1
  49. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
  50. package/data/persistence/principalMutationJournalPersistence.d.ts +19 -0
  51. package/data/persistence/principalMutationJournalPersistence.js +53 -0
  52. package/data/persistence/principalMutationJournalPersistence.js.map +1 -0
  53. package/data/persistence/verifiedPrincipalPolicyBundle.js +7 -51
  54. package/data/persistence/verifiedPrincipalPolicyBundle.js.map +1 -1
  55. package/data/persistence/verifiedPrincipalPolicyCurrent.js +56 -0
  56. package/data/persistence/verifiedPrincipalPolicyCurrent.js.map +1 -0
  57. package/data/principals/currentPolicyReferenceResolver.js +2 -0
  58. package/data/principals/currentPolicyReferenceResolver.js.map +1 -0
  59. package/data/principals/principalHistoryScopeProtection.js +23 -0
  60. package/data/principals/principalHistoryScopeProtection.js.map +1 -0
  61. package/data/principals/principalMutationJournal.d.ts +26 -0
  62. package/data/principals/principalMutationJournal.js +90 -0
  63. package/data/principals/principalMutationJournal.js.map +1 -0
  64. package/data/principals/principalMutationJournalRecord.d.ts +8 -0
  65. package/data/principals/principalMutationJournalRecord.js +25 -0
  66. package/data/principals/principalMutationJournalRecord.js.map +1 -0
  67. package/data/principals/principalPolicyAdminSigners.js.map +1 -1
  68. package/data/sqlite/principalHistoryStageSchema.js +3 -0
  69. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  70. package/data/sqlite/principalMutationJournalSchema.d.ts +85 -0
  71. package/data/sqlite/principalMutationJournalSchema.js +13 -0
  72. package/data/sqlite/principalMutationJournalSchema.js.map +1 -0
  73. package/data/sqlite/schema.d.ts +83 -0
  74. package/data/sqlite/schema.js +3 -0
  75. package/data/sqlite/schema.js.map +1 -1
  76. package/index.d.ts +3 -3
  77. package/index.js +1 -1
  78. package/index.js.map +1 -1
  79. package/internal/crypto/index.d.ts +1 -1
  80. package/internal/crypto/index.js +1 -1
  81. package/internal/crypto/index.js.map +1 -1
  82. package/internal/crypto/keying/index.d.ts +3 -0
  83. package/internal/crypto/keying/index.js +3 -0
  84. package/internal/crypto/keying/index.js.map +1 -1
  85. package/internal/crypto/keying/principalPolicyCurrent.d.ts +1 -1
  86. package/internal/crypto/keying/principalPolicyCurrent.js +3 -3
  87. package/internal/crypto/keying/principalPolicyCurrent.js.map +1 -1
  88. package/internal/crypto/keying/principalPolicyCurrentEvidence.js +16 -0
  89. package/internal/crypto/keying/principalPolicyCurrentEvidence.js.map +1 -0
  90. package/internal/crypto/keying/principalPolicyCurrentMutation.d.ts +10 -0
  91. package/internal/crypto/keying/principalPolicyCurrentMutation.js +51 -0
  92. package/internal/crypto/keying/principalPolicyCurrentMutation.js.map +1 -0
  93. package/internal/crypto/keying/principalPolicyCurrentPredecessorReferences.d.ts +8 -0
  94. package/internal/crypto/keying/principalPolicyCurrentPredecessorReferences.js +46 -0
  95. package/internal/crypto/keying/principalPolicyCurrentPredecessorReferences.js.map +1 -0
  96. package/internal/crypto/keying/principalPolicyCurrentSuccessor.d.ts +10 -0
  97. package/internal/crypto/keying/principalPolicyCurrentSuccessor.js +60 -0
  98. package/internal/crypto/keying/principalPolicyCurrentSuccessor.js.map +1 -0
  99. package/internal/crypto/keying/principalPolicyHistory.js +4 -1
  100. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  101. package/internal/crypto/keying/principalPolicyHistoryReferences.js +1 -1
  102. package/internal/crypto/keying/principalPolicyHistoryReferences.js.map +1 -1
  103. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +5 -2
  104. package/internal/crypto/keying/principalPolicyHistoryTypes.js +6 -3
  105. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  106. package/package.json +1 -1
  107. package/workflows/containers/child/carriedDescendantRekeys.js +9 -1
  108. package/workflows/containers/child/carriedDescendantRekeys.js.map +1 -1
  109. package/workflows/containers/child/replacementPrincipalPolicyReferences.js +19 -0
  110. package/workflows/containers/child/replacementPrincipalPolicyReferences.js.map +1 -0
  111. package/workflows/containers/child/share.js +4 -0
  112. package/workflows/containers/child/share.js.map +1 -1
  113. package/workflows/containers/child/sharePrincipalPolicy.d.ts +1 -0
  114. package/workflows/containers/child/sharePrincipalPolicy.js.map +1 -1
  115. package/workflows/organizations/acknowledgedDirectoryBindings.js +18 -0
  116. package/workflows/organizations/acknowledgedDirectoryBindings.js.map +1 -0
  117. package/workflows/organizations/commitCurrentGroupPolicyMutation.js +72 -0
  118. package/workflows/organizations/commitCurrentGroupPolicyMutation.js.map +1 -0
  119. package/workflows/organizations/createCurrentOrganizationGroup.js +85 -0
  120. package/workflows/organizations/createCurrentOrganizationGroup.js.map +1 -0
  121. package/workflows/organizations/currentGroupMetadataAuthority.js +53 -0
  122. package/workflows/organizations/currentGroupMetadataAuthority.js.map +1 -0
  123. package/workflows/organizations/currentGroupMutationReferences.js +35 -0
  124. package/workflows/organizations/currentGroupMutationReferences.js.map +1 -0
  125. package/workflows/organizations/currentGroupPolicyMutationContext.js +79 -0
  126. package/workflows/organizations/currentGroupPolicyMutationContext.js.map +1 -0
  127. package/workflows/organizations/currentOrganizationAuthority.js +88 -0
  128. package/workflows/organizations/currentOrganizationAuthority.js.map +1 -0
  129. package/workflows/organizations/currentOrganizationGroupNames.js +72 -0
  130. package/workflows/organizations/currentOrganizationGroupNames.js.map +1 -0
  131. package/workflows/organizations/currentOrganizationMutationAuthority.js +16 -0
  132. package/workflows/organizations/currentOrganizationMutationAuthority.js.map +1 -0
  133. package/workflows/organizations/currentOrganizationMutationRetention.js +53 -0
  134. package/workflows/organizations/currentOrganizationMutationRetention.js.map +1 -0
  135. package/workflows/organizations/currentPolicyMutationAcknowledgement.js +65 -0
  136. package/workflows/organizations/currentPolicyMutationAcknowledgement.js.map +1 -0
  137. package/workflows/organizations/currentPrincipalMutationLease.js +38 -0
  138. package/workflows/organizations/currentPrincipalMutationLease.js.map +1 -0
  139. package/workflows/organizations/deleteCurrentOrganizationGroup.js +35 -0
  140. package/workflows/organizations/deleteCurrentOrganizationGroup.js.map +1 -0
  141. package/workflows/organizations/deleteOrganizationGroup.d.ts +1 -0
  142. package/workflows/organizations/deleteOrganizationGroup.js +11 -0
  143. package/workflows/organizations/deleteOrganizationGroup.js.map +1 -1
  144. package/workflows/organizations/groupCreation.d.ts +1 -0
  145. package/workflows/organizations/groupCreation.js +9 -0
  146. package/workflows/organizations/groupCreation.js.map +1 -1
  147. package/workflows/organizations/groupMembershipName.d.ts +1 -1
  148. package/workflows/organizations/groupMembershipName.js.map +1 -1
  149. package/workflows/organizations/groupMetadataAccess.d.ts +2 -2
  150. package/workflows/organizations/groupMetadataAccess.js +1 -1
  151. package/workflows/organizations/groupMetadataAccess.js.map +1 -1
  152. package/workflows/organizations/groupMetadataBinding.js.map +1 -1
  153. package/workflows/organizations/groupMetadataContainerAuthority.js +2 -47
  154. package/workflows/organizations/groupMetadataContainerAuthority.js.map +1 -1
  155. package/workflows/organizations/groupMetadataRootBinding.js +51 -0
  156. package/workflows/organizations/groupMetadataRootBinding.js.map +1 -0
  157. package/workflows/organizations/groupMetadataRuntime.js +26 -10
  158. package/workflows/organizations/groupMetadataRuntime.js.map +1 -1
  159. package/workflows/organizations/groupMutationAuthorization.js.map +1 -1
  160. package/workflows/organizations/groupNameUniqueness.js +1 -1
  161. package/workflows/organizations/groupNameUniqueness.js.map +1 -1
  162. package/workflows/organizations/groupPolicyHistoryPage.js +31 -0
  163. package/workflows/organizations/groupPolicyHistoryPage.js.map +1 -0
  164. package/workflows/organizations/groupPolicyMutationAcknowledgement.js +10 -75
  165. package/workflows/organizations/groupPolicyMutationAcknowledgement.js.map +1 -1
  166. package/workflows/organizations/groupPolicyMutationContext.d.ts +23 -13
  167. package/workflows/organizations/groupPolicyMutationContext.js +2 -1
  168. package/workflows/organizations/groupPolicyMutationContext.js.map +1 -1
  169. package/workflows/organizations/groupPolicyMutationEvidence.d.ts +26 -0
  170. package/workflows/organizations/groupPolicyMutationEvidence.js +64 -0
  171. package/workflows/organizations/groupPolicyMutationEvidence.js.map +1 -0
  172. package/workflows/organizations/groupPolicyMutationHead.js.map +1 -1
  173. package/workflows/organizations/groupPolicyRequests.js +69 -63
  174. package/workflows/organizations/groupPolicyRequests.js.map +1 -1
  175. package/workflows/organizations/index.d.ts +6 -0
  176. package/workflows/organizations/index.js +5 -0
  177. package/workflows/organizations/index.js.map +1 -1
  178. package/workflows/organizations/initialPrincipalCurrentPublication.js +83 -0
  179. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -0
  180. package/workflows/organizations/organizationGroupDirectory.js +6 -0
  181. package/workflows/organizations/organizationGroupDirectory.js.map +1 -1
  182. package/workflows/organizations/organizationGroupNames.js +7 -0
  183. package/workflows/organizations/organizationGroupNames.js.map +1 -1
  184. package/workflows/organizations/policyHistoryTypes.d.ts +2 -0
  185. package/workflows/organizations/policyHistoryTypes.js.map +1 -1
  186. package/workflows/organizations/principalContainerRematerialization.js +12 -2
  187. package/workflows/organizations/principalContainerRematerialization.js.map +1 -1
  188. package/workflows/organizations/principalContainerRematerializationPlanning.js +1 -0
  189. package/workflows/organizations/principalContainerRematerializationPlanning.js.map +1 -1
  190. package/workflows/organizations/principalContainerRematerializationTargets.js.map +1 -1
  191. package/workflows/organizations/principalCurrentPublicationSeal.js +51 -0
  192. package/workflows/organizations/principalCurrentPublicationSeal.js.map +1 -0
  193. package/workflows/organizations/principalMutationJournalLane.js +26 -0
  194. package/workflows/organizations/principalMutationJournalLane.js.map +1 -0
  195. package/workflows/organizations/principalMutationJournalManagement.d.ts +26 -0
  196. package/workflows/organizations/principalMutationJournalManagement.js +104 -0
  197. package/workflows/organizations/principalMutationJournalManagement.js.map +1 -0
  198. package/workflows/organizations/principalMutationJournalSession.d.ts +26 -0
  199. package/workflows/organizations/principalMutationJournalSession.js +85 -0
  200. package/workflows/organizations/principalMutationJournalSession.js.map +1 -0
  201. package/workflows/organizations/principalMutationReceipt.js +21 -0
  202. package/workflows/organizations/principalMutationReceipt.js.map +1 -0
  203. package/workflows/organizations/principalPolicyReceiptArtifacts.js +74 -0
  204. package/workflows/organizations/principalPolicyReceiptArtifacts.js.map +1 -0
  205. package/workflows/organizations/principalPolicyRequest.d.ts +5 -4
  206. package/workflows/organizations/principalPolicyRequest.js.map +1 -1
  207. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.d.ts +23 -0
  208. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +159 -0
  209. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -0
  210. package/workflows/organizations/runtimeCurrentGroupMutation.js +85 -0
  211. package/workflows/organizations/runtimeCurrentGroupMutation.js.map +1 -0
  212. package/workflows/organizations/runtimeCurrentOrganizationMutation.js +48 -0
  213. package/workflows/organizations/runtimeCurrentOrganizationMutation.js.map +1 -0
  214. package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +11 -0
  215. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +120 -0
  216. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -0
  217. package/workflows/principals/principalCurrentRecoveryBatch.js +14 -0
  218. package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -0
  219. package/workflows/principals/principalHistoryRecoveryReferences.js +8 -0
  220. package/workflows/principals/principalHistoryRecoveryReferences.js.map +1 -1
  221. package/workflows/principals/principalRecoveryDirectory.d.ts +1 -1
  222. package/workflows/principals/principalRecoveryDirectory.js +32 -12
  223. package/workflows/principals/principalRecoveryDirectory.js.map +1 -1
  224. package/workflows/principals/principalRecoveryDiscoveryPage.js +36 -0
  225. package/workflows/principals/principalRecoveryDiscoveryPage.js.map +1 -0
  226. package/workflows/principals/principalRecoveryLocalPreference.js +29 -0
  227. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -0
  228. package/workflows/principals/principalRecoveryMemo.d.ts +16 -0
  229. package/workflows/principals/principalRecoveryMemo.js +88 -16
  230. package/workflows/principals/principalRecoveryMemo.js.map +1 -1
  231. package/workflows/principals/recoverCurrentOrganizationPolicy.js +33 -0
  232. package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -0
  233. package/workflows/principals/recoverPrincipalHistoryPage.js +30 -0
  234. package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -0
  235. package/workflows/principals/recoverPrincipalPolicyHistory.d.ts +2 -0
  236. package/workflows/principals/recoverPrincipalPolicyHistory.js +14 -2
  237. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  238. package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +8 -1
  239. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +30 -20
  240. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
  241. package/workflows/principals/runtimePolicyRecovery.js +36 -9
  242. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  243. package/workflows/principals/runtimePolicyWarmer.js +2 -2
  244. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
@@ -0,0 +1,64 @@
1
+ import { verifyPrincipalPolicyCheckpoint, verifyPrincipalPolicyCurrentMutation, } from "../../internal/crypto/index.js";
2
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
3
+ import { assertCurrentMatchesVerifiedPolicy } from "../../data/persistence/verifiedPrincipalPolicyCurrent.js";
4
+ import { requireSignerCanManageGroup } from "./groupMutationAuthorization.js";
5
+ import { verifyGroupPolicy } from "./groupPolicyVerification.js";
6
+ /** Current artifacts require their verified evidence; omitted history is never a bundle. */
7
+ export async function withVerifiedGroupMutation(input, work) {
8
+ input = {
9
+ ...input,
10
+ currentPolicy: structuredClone(input.currentPolicy),
11
+ ...("currentPolicySignerPublicKeys" in input
12
+ ? {
13
+ currentPolicySignerPublicKeys: structuredClone(input.currentPolicySignerPublicKeys),
14
+ }
15
+ : {}),
16
+ currentOrgAdminUserIds: structuredClone(input.currentOrgAdminUserIds),
17
+ externalAuthority: structuredClone(input.externalAuthority),
18
+ localPolicyCheckpoint: structuredClone(input.localPolicyCheckpoint),
19
+ signingKeyPair: structuredClone(input.signingKeyPair),
20
+ };
21
+ try {
22
+ const current = () => !("verifiedCurrentPolicy" in input) || input.stillCurrent();
23
+ assertProjectionVerificationCurrent(current);
24
+ if ("verifiedCurrentPolicy" in input) {
25
+ await assertCurrentMatchesVerifiedPolicy({
26
+ current: input.currentPolicy,
27
+ policy: input.verifiedCurrentPolicy,
28
+ });
29
+ requireSignerCanManageGroup(input.currentPolicy, input.currentOrgAdminUserIds ?? [], input.signerUserId);
30
+ const verified = await verifyPrincipalPolicyCurrentMutation({
31
+ current: input.currentPolicy,
32
+ policy: input.verifiedCurrentPolicy,
33
+ signerUserId: input.signerUserId,
34
+ externalAuthority: input.externalAuthority,
35
+ });
36
+ if (!verified.ok)
37
+ throw verified.error;
38
+ verifyPrincipalPolicyCheckpoint({
39
+ chain: verified.value.retainedHistory,
40
+ currentState: verified.value.state,
41
+ localCheckpoint: input.localPolicyCheckpoint,
42
+ });
43
+ }
44
+ else {
45
+ await verifyGroupPolicy({
46
+ currentPolicy: input.currentPolicy,
47
+ ...(input.externalAuthority
48
+ ? { externalAuthority: input.externalAuthority }
49
+ : {}),
50
+ localPolicyCheckpoint: input.localPolicyCheckpoint ?? null,
51
+ signerPublicKeys: input.currentPolicySignerPublicKeys,
52
+ });
53
+ }
54
+ assertProjectionVerificationCurrent(current);
55
+ requireSignerCanManageGroup(input.currentPolicy, input.currentOrgAdminUserIds ?? [], input.signerUserId);
56
+ const result = await work(input);
57
+ assertProjectionVerificationCurrent(current);
58
+ return result;
59
+ }
60
+ finally {
61
+ input.signingKeyPair.signingPrivateKey.fill(0);
62
+ }
63
+ }
64
+ //# sourceMappingURL=groupPolicyMutationEvidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groupPolicyMutationEvidence.js","sourceRoot":"","sources":["groupPolicyMutationEvidence.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyPageCurrent } from \"@tearleads/api-client\";\nimport {\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyExternalAuthority,\n type PrincipalPolicySignerPublicKey,\n type SigningKeyPair,\n type VerifiedPrincipalPolicyCurrent,\n verifyPrincipalPolicyCheckpoint,\n verifyPrincipalPolicyCurrentMutation,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { assertCurrentMatchesVerifiedPolicy } from \"../../data/persistence/verifiedPrincipalPolicyCurrent\";\nimport { requireSignerCanManageGroup } from \"./groupMutationAuthorization\";\nimport { verifyGroupPolicy } from \"./groupPolicyVerification\";\n\ninterface GroupMembershipSigningInput {\n readonly currentOrgAdminUserIds?: readonly string[] | undefined;\n readonly externalAuthority?: PrincipalPolicyExternalAuthority | undefined;\n readonly isOrganizationAdminsGroup?: boolean | undefined;\n readonly localPolicyCheckpoint?: PrincipalPolicyCheckpoint | null;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}\n\nexport interface FullGroupMembershipMutationInput\n extends GroupMembershipSigningInput {\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly currentPolicySignerPublicKeys: readonly PrincipalPolicySignerPublicKey[];\n}\n\ninterface CurrentGroupMembershipMutationInput\n extends GroupMembershipSigningInput {\n readonly currentPolicy: PrincipalPolicyPageCurrent;\n readonly verifiedCurrentPolicy: VerifiedPrincipalPolicyCurrent;\n readonly stillCurrent: () => boolean;\n}\n\nexport type BuildGroupMembershipMutationInput =\n | FullGroupMembershipMutationInput\n | CurrentGroupMembershipMutationInput;\n\n/** Current artifacts require their verified evidence; omitted history is never a bundle. */\nexport async function withVerifiedGroupMutation<\n T extends BuildGroupMembershipMutationInput,\n>(\n input: T,\n work: (owned: T) => Promise<PutPrincipalPolicyRequest>,\n): Promise<PutPrincipalPolicyRequest> {\n input = {\n ...input,\n currentPolicy: structuredClone(input.currentPolicy),\n ...(\"currentPolicySignerPublicKeys\" in input\n ? {\n currentPolicySignerPublicKeys: structuredClone(\n input.currentPolicySignerPublicKeys,\n ),\n }\n : {}),\n currentOrgAdminUserIds: structuredClone(input.currentOrgAdminUserIds),\n externalAuthority: structuredClone(input.externalAuthority),\n localPolicyCheckpoint: structuredClone(input.localPolicyCheckpoint),\n signingKeyPair: structuredClone(input.signingKeyPair),\n };\n try {\n const current = () =>\n !(\"verifiedCurrentPolicy\" in input) || input.stillCurrent();\n assertProjectionVerificationCurrent(current);\n if (\"verifiedCurrentPolicy\" in input) {\n await assertCurrentMatchesVerifiedPolicy({\n current: input.currentPolicy,\n policy: input.verifiedCurrentPolicy,\n });\n requireSignerCanManageGroup(\n input.currentPolicy,\n input.currentOrgAdminUserIds ?? [],\n input.signerUserId,\n );\n const verified = await verifyPrincipalPolicyCurrentMutation({\n current: input.currentPolicy,\n policy: input.verifiedCurrentPolicy,\n signerUserId: input.signerUserId,\n externalAuthority: input.externalAuthority,\n });\n if (!verified.ok) throw verified.error;\n verifyPrincipalPolicyCheckpoint({\n chain: verified.value.retainedHistory,\n currentState: verified.value.state,\n localCheckpoint: input.localPolicyCheckpoint,\n });\n } else {\n await verifyGroupPolicy({\n currentPolicy: input.currentPolicy,\n ...(input.externalAuthority\n ? { externalAuthority: input.externalAuthority }\n : {}),\n localPolicyCheckpoint: input.localPolicyCheckpoint ?? null,\n signerPublicKeys: input.currentPolicySignerPublicKeys,\n });\n }\n assertProjectionVerificationCurrent(current);\n requireSignerCanManageGroup(\n input.currentPolicy,\n input.currentOrgAdminUserIds ?? [],\n input.signerUserId,\n );\n const result = await work(input);\n assertProjectionVerificationCurrent(current);\n return result;\n } finally {\n input.signingKeyPair.signingPrivateKey.fill(0);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"groupPolicyMutationHead.js","sourceRoot":"","sources":["groupPolicyMutationHead.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAE1B,MAAM,mBAAmB,CAAC;AAI3B,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAkC;IAElC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,MAAM,yBAAyB,CAAC,KAAK,CAAC;QACjD,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,sCAAsC,CAC7C,KAAoD,EACpD,IAA6B;IAE7B,OAAO,CACL,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC,aAAa;QAC1C,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;QACtC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;QAC9B,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;QAChC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;QAClC,KAAK,CAAC,cAAc,KAAK,IAAI,CAAC,cAAc,CAC7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4CAA4C,CAC1D,KAAoD,EACpD,IAA6B;IAE7B,IAAI,CAAC,sCAAsC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;AACH,CAAC","sourcesContent":["import {\n computePrincipalStateHash,\n type ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\n\nexport async function groupPolicyMutationHead(\n request: PutPrincipalPolicyRequest,\n): Promise<ReferencedPrincipalHead> {\n const state = request.state;\n return {\n principalType: state.principalType,\n principalId: state.principalId,\n version: state.version,\n keyEpoch: state.keyEpoch,\n stateHash: await computePrincipalStateHash(state),\n keyFingerprint: state.keyFingerprint,\n };\n}\n\nfunction principalPolicyCurrentStateMatchesHead(\n state: PrincipalPolicyBundleResponse[\"currentState\"],\n head: ReferencedPrincipalHead,\n): boolean {\n return (\n state.principalType === head.principalType &&\n state.principalId === head.principalId &&\n state.version === head.version &&\n state.keyEpoch === head.keyEpoch &&\n state.stateHash === head.stateHash &&\n state.keyFingerprint === head.keyFingerprint\n );\n}\n\nexport function assertPrincipalPolicyCurrentStateMatchesHead(\n state: PrincipalPolicyBundleResponse[\"currentState\"],\n head: ReferencedPrincipalHead,\n): void {\n if (!principalPolicyCurrentStateMatchesHead(state, head)) {\n throw new Error(\"Updated group policy advanced during root re-wrap\");\n }\n}\n"]}
1
+ {"version":3,"file":"groupPolicyMutationHead.js","sourceRoot":"","sources":["groupPolicyMutationHead.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,GAE1B,MAAM,mBAAmB,CAAC;AAG3B,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAkC;IAElC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;IAC5B,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,aAAa;QAClC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,MAAM,yBAAyB,CAAC,KAAK,CAAC;QACjD,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC;AACJ,CAAC;AAED,SAAS,sCAAsC,CAC7C,KAA8B,EAC9B,IAA6B;IAE7B,OAAO,CACL,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC,aAAa;QAC1C,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW;QACtC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,OAAO;QAC9B,KAAK,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ;QAChC,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;QAClC,KAAK,CAAC,cAAc,KAAK,IAAI,CAAC,cAAc,CAC7C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4CAA4C,CAC1D,KAA8B,EAC9B,IAA6B;IAE7B,IAAI,CAAC,sCAAsC,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;AACH,CAAC","sourcesContent":["import {\n computePrincipalStateHash,\n type ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\n\nexport async function groupPolicyMutationHead(\n request: PutPrincipalPolicyRequest,\n): Promise<ReferencedPrincipalHead> {\n const state = request.state;\n return {\n principalType: state.principalType,\n principalId: state.principalId,\n version: state.version,\n keyEpoch: state.keyEpoch,\n stateHash: await computePrincipalStateHash(state),\n keyFingerprint: state.keyFingerprint,\n };\n}\n\nfunction principalPolicyCurrentStateMatchesHead(\n state: ReferencedPrincipalHead,\n head: ReferencedPrincipalHead,\n): boolean {\n return (\n state.principalType === head.principalType &&\n state.principalId === head.principalId &&\n state.version === head.version &&\n state.keyEpoch === head.keyEpoch &&\n state.stateHash === head.stateHash &&\n state.keyFingerprint === head.keyFingerprint\n );\n}\n\nexport function assertPrincipalPolicyCurrentStateMatchesHead(\n state: ReferencedPrincipalHead,\n head: ReferencedPrincipalHead,\n): void {\n if (!principalPolicyCurrentStateMatchesHead(state, head)) {\n throw new Error(\"Updated group policy advanced during root re-wrap\");\n }\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import { generateKemSeedAndKeyPair, KeyingVerificationError, toFingerprint, unwrapDek, wrapDekForRecipients, } from "../../internal/crypto/index.js";
2
2
  import { bytesToBase64 } from "../../internal/encoding/index.js";
3
3
  import { principalSecretKeyMatchesState } from "../../data/principals/principalKeyValidation.js";
4
- import { isDirectGroupAdmin, requireSignerCanManageGroup, } from "./groupMutationAuthorization.js";
5
- import { verifyGroupPolicy } from "./groupPolicyVerification.js";
4
+ import { isDirectGroupAdmin } from "./groupMutationAuthorization.js";
5
+ import { withVerifiedGroupMutation, } from "./groupPolicyMutationEvidence.js";
6
6
  import { rewrapProjectionMemberEnvelopes, toRecipientEntries, } from "./principalPolicyRecipients.js";
7
7
  import { signedGroupPolicyRequest, userProjectionMember, } from "./principalPolicyRequest.js";
8
8
  /**
@@ -33,17 +33,6 @@ function requireExternalAuthority(authority) {
33
33
  }
34
34
  return authority;
35
35
  }
36
- async function verifyAndAuthorizeGroupMutation(input) {
37
- await verifyGroupPolicy({
38
- currentPolicy: input.currentPolicy,
39
- ...(input.externalAuthority
40
- ? { externalAuthority: input.externalAuthority }
41
- : {}),
42
- localPolicyCheckpoint: input.localPolicyCheckpoint ?? null,
43
- signerPublicKeys: input.currentPolicySignerPublicKeys,
44
- });
45
- requireSignerCanManageGroup(input.currentPolicy, input.currentOrgAdminUserIds ?? [], input.signerUserId);
46
- }
47
36
  async function buildRotatedKeyGroupPolicyRequest(input, projection, users, grants = input.currentPolicy.currentGrants) {
48
37
  const groupKem = generateKemSeedAndKeyPair();
49
38
  const memberEnvelopes = await rewrapProjectionMemberEnvelopes({
@@ -112,64 +101,81 @@ async function buildDirectAdminAddGroupUserPolicyRequest(input, projection, targ
112
101
  });
113
102
  }
114
103
  export async function buildAddGroupUserPolicyRequest(input) {
115
- await verifyAndAuthorizeGroupMutation(input);
116
- const targetKey = input.targetUser.userId;
117
- const currentProjection = input.currentPolicy.currentProjection;
118
- if (currentProjection.some((member) => member.userId === targetKey)) {
119
- throw new Error("User is already a group member");
104
+ input = {
105
+ ...input,
106
+ currentUsers: structuredClone(input.currentUsers),
107
+ currentUserSecretKey: input.currentUserSecretKey.slice(),
108
+ targetUser: structuredClone(input.targetUser),
109
+ };
110
+ try {
111
+ return await withVerifiedGroupMutation(input, async (input) => {
112
+ const targetKey = input.targetUser.userId;
113
+ const currentProjection = input.currentPolicy.currentProjection;
114
+ if (currentProjection.some((member) => member.userId === targetKey)) {
115
+ throw new Error("User is already a group member");
116
+ }
117
+ const projection = [
118
+ ...currentProjection,
119
+ userProjectionMember(input.targetUser.userId, input.isOrganizationAdminsGroup ? "admin" : "member"),
120
+ ];
121
+ return isDirectGroupAdmin(input.currentPolicy, input.signerUserId)
122
+ ? buildDirectAdminAddGroupUserPolicyRequest(input, projection, targetKey)
123
+ : buildRotatedKeyGroupPolicyRequest(input, projection, [
124
+ ...input.currentUsers,
125
+ input.targetUser,
126
+ ]);
127
+ });
128
+ }
129
+ finally {
130
+ input.currentUserSecretKey.fill(0);
120
131
  }
121
- const projection = [
122
- ...currentProjection,
123
- userProjectionMember(input.targetUser.userId, input.isOrganizationAdminsGroup ? "admin" : "member"),
124
- ];
125
- return isDirectGroupAdmin(input.currentPolicy, input.signerUserId)
126
- ? buildDirectAdminAddGroupUserPolicyRequest(input, projection, targetKey)
127
- : buildRotatedKeyGroupPolicyRequest(input, projection, [
128
- ...input.currentUsers,
129
- input.targetUser,
130
- ]);
131
132
  }
132
133
  export async function buildRemoveGroupUserPolicyRequest(input) {
133
- await verifyAndAuthorizeGroupMutation(input);
134
- const key = input.removedUserId;
135
- const projection = input.currentPolicy.currentProjection.filter((member) => member.userId !== key);
136
- if (projection.length === input.currentPolicy.currentProjection.length) {
137
- throw new Error("User is not a group member");
138
- }
139
- if (hasAdmin(input.currentPolicy.currentProjection) &&
140
- !hasAdmin(projection)) {
141
- throw new Error("Cannot remove the last group admin");
142
- }
143
- return buildRotatedKeyGroupPolicyRequest(input, projection, input.remainingUsers);
134
+ input = { ...input, remainingUsers: structuredClone(input.remainingUsers) };
135
+ return withVerifiedGroupMutation(input, async (input) => {
136
+ const key = input.removedUserId;
137
+ const projection = input.currentPolicy.currentProjection.filter((member) => member.userId !== key);
138
+ if (projection.length === input.currentPolicy.currentProjection.length) {
139
+ throw new Error("User is not a group member");
140
+ }
141
+ if (hasAdmin(input.currentPolicy.currentProjection) &&
142
+ !hasAdmin(projection)) {
143
+ throw new Error("Cannot remove the last group admin");
144
+ }
145
+ return buildRotatedKeyGroupPolicyRequest(input, projection, input.remainingUsers);
146
+ });
144
147
  }
145
148
  export async function buildGroupAccessSetShrinkPolicyRequest(input) {
146
- await verifyAndAuthorizeGroupMutation(input);
147
- return buildRotatedKeyGroupPolicyRequest(input, [...input.currentPolicy.currentProjection], input.currentUsers, input.currentPolicy.currentGrants.filter((grant) => grant.containerId !== input.revokedContainerId));
149
+ input = { ...input, currentUsers: structuredClone(input.currentUsers) };
150
+ return withVerifiedGroupMutation(input, async (input) => {
151
+ return buildRotatedKeyGroupPolicyRequest(input, [...input.currentPolicy.currentProjection], input.currentUsers, input.currentPolicy.currentGrants.filter((grant) => grant.containerId !== input.revokedContainerId));
152
+ });
148
153
  }
149
154
  /** Signs a complete successor grant projection without rotating group key material. */
150
155
  export async function buildSetGroupContainerGrantPolicyRequest(input) {
151
- await verifyAndAuthorizeGroupMutation(input);
152
- const grants = [
153
- ...input.currentPolicy.currentGrants.filter((grant) => grant.containerId !== input.containerId),
154
- { accessLevel: input.accessLevel, containerId: input.containerId },
155
- ];
156
- return signedGroupPolicyRequest({
157
- currentPolicy: input.currentPolicy,
158
- encapsulationPublicKey: input.currentPolicy.currentState.encapsulationPublicKey,
159
- externalAuthority: isDirectGroupAdmin(input.currentPolicy, input.signerUserId)
160
- ? null
161
- : requireExternalAuthority(input.externalAuthority).currentHead,
162
- keyEpoch: input.currentPolicy.currentState.keyEpoch,
163
- keyFingerprint: input.currentPolicy.currentState.keyFingerprint,
164
- grants,
165
- memberEnvelopes: input.currentPolicy.currentMemberEnvelopes.envelopes,
166
- payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,
167
- principalId: input.currentPolicy.currentState.principalId,
168
- projection: input.currentPolicy.currentProjection,
169
- signedAt: new Date().toISOString(),
170
- signerUserId: input.signerUserId,
171
- signingFingerprint: input.signingFingerprint,
172
- signingKeyPair: input.signingKeyPair,
156
+ return withVerifiedGroupMutation(input, async (input) => {
157
+ const grants = [
158
+ ...input.currentPolicy.currentGrants.filter((grant) => grant.containerId !== input.containerId),
159
+ { accessLevel: input.accessLevel, containerId: input.containerId },
160
+ ];
161
+ return signedGroupPolicyRequest({
162
+ currentPolicy: input.currentPolicy,
163
+ encapsulationPublicKey: input.currentPolicy.currentState.encapsulationPublicKey,
164
+ externalAuthority: isDirectGroupAdmin(input.currentPolicy, input.signerUserId)
165
+ ? null
166
+ : requireExternalAuthority(input.externalAuthority).currentHead,
167
+ keyEpoch: input.currentPolicy.currentState.keyEpoch,
168
+ keyFingerprint: input.currentPolicy.currentState.keyFingerprint,
169
+ grants,
170
+ memberEnvelopes: input.currentPolicy.currentMemberEnvelopes.envelopes,
171
+ payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,
172
+ principalId: input.currentPolicy.currentState.principalId,
173
+ projection: input.currentPolicy.currentProjection,
174
+ signedAt: new Date().toISOString(),
175
+ signerUserId: input.signerUserId,
176
+ signingFingerprint: input.signingFingerprint,
177
+ signingKeyPair: input.signingKeyPair,
178
+ });
173
179
  });
174
180
  }
175
181
  //# sourceMappingURL=groupPolicyRequests.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"groupPolicyRequests.js","sourceRoot":"","sources":["groupPolicyRequests.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n generateKemSeedAndKeyPair,\n KeyingVerificationError,\n type PrincipalPolicyExternalAuthority,\n toFingerprint,\n unwrapDek,\n wrapDekForRecipients,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type {\n PrincipalContainerGrantRequest,\n PrincipalProjectionMemberRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport { principalSecretKeyMatchesState } from \"../../data/principals/principalKeyValidation\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\nimport type { TrustedUserIdentity } from \"../../data/trustedUserIdentity\";\nimport {\n isDirectGroupAdmin,\n requireSignerCanManageGroup,\n} from \"./groupMutationAuthorization\";\nimport type { BuildGroupMembershipMutationInput } from \"./groupPolicyMutationContext\";\nimport { verifyGroupPolicy } from \"./groupPolicyVerification\";\nimport {\n rewrapProjectionMemberEnvelopes,\n toRecipientEntries,\n} from \"./principalPolicyRecipients\";\nimport {\n signedGroupPolicyRequest,\n userProjectionMember,\n} from \"./principalPolicyRequest\";\n\ntype BuildAddGroupUserPolicyInput = BuildGroupMembershipMutationInput & {\n readonly currentUsers: ReadonlyArray<TrustedUserIdentity>;\n readonly currentUserSecretKey: Uint8Array;\n readonly reportSecurityIncident?: SecurityIncidentReporter | undefined;\n readonly targetUser: TrustedUserIdentity;\n};\n\n/**\n * The signed policy commits both the group's public key and the member\n * envelopes that are supposed to wrap its secret. An envelope that unwraps to\n * a different secret means a prior admin (or the server) published a policy\n * whose envelopes do not match its signed key. Rotating repairs the group, but\n * the mismatch is evidence and is recorded before the repair proceeds.\n */\nasync function reportPrincipalEnvelopeMismatch(\n input: BuildAddGroupUserPolicyInput,\n): Promise<void> {\n const state = input.currentPolicy.currentState;\n await input.reportSecurityIncident?.(\n new KeyingVerificationError(\n \"object_mismatch\",\n \"Group member envelope does not unwrap the signed principal key\",\n ),\n {\n evidenceHashes: {\n principalKeyFingerprint: state.keyFingerprint,\n principalStateHash: state.stateHash,\n },\n objectId: state.principalId,\n objectKind: \"principal\",\n operation: \"group.policy.envelope_mismatch\",\n },\n );\n}\n\nfunction hasAdmin(\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n): boolean {\n return projection.some((member) => member.role === \"admin\");\n}\n\nfunction requireExternalAuthority(\n authority: PrincipalPolicyExternalAuthority | undefined,\n): PrincipalPolicyExternalAuthority {\n if (!authority) {\n throw new Error(\"External principal authority could not be verified\");\n }\n return authority;\n}\n\nasync function verifyAndAuthorizeGroupMutation(\n input: BuildGroupMembershipMutationInput,\n): Promise<void> {\n await verifyGroupPolicy({\n currentPolicy: input.currentPolicy,\n ...(input.externalAuthority\n ? { externalAuthority: input.externalAuthority }\n : {}),\n localPolicyCheckpoint: input.localPolicyCheckpoint ?? null,\n signerPublicKeys: input.currentPolicySignerPublicKeys,\n });\n requireSignerCanManageGroup(\n input.currentPolicy,\n input.currentOrgAdminUserIds ?? [],\n input.signerUserId,\n );\n}\n\nasync function buildRotatedKeyGroupPolicyRequest(\n input: BuildGroupMembershipMutationInput,\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n users: ReadonlyArray<TrustedUserIdentity>,\n grants = input.currentPolicy.currentGrants,\n): Promise<PutPrincipalPolicyRequest> {\n const groupKem = generateKemSeedAndKeyPair();\n const memberEnvelopes = await rewrapProjectionMemberEnvelopes({\n projection,\n secretKey: groupKem.secretKey,\n users,\n });\n return signedGroupPolicyRequest({\n currentPolicy: input.currentPolicy,\n encapsulationPublicKey: bytesToBase64(groupKem.publicKey),\n externalAuthority: isDirectGroupAdmin(\n input.currentPolicy,\n input.signerUserId,\n )\n ? null\n : requireExternalAuthority(input.externalAuthority).currentHead,\n keyEpoch: input.currentPolicy.currentState.keyEpoch + 1,\n keyFingerprint: await toFingerprint(groupKem.publicKey),\n grants,\n memberEnvelopes,\n payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,\n principalId: input.currentPolicy.currentState.principalId,\n projection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n\nasync function buildDirectAdminAddGroupUserPolicyRequest(\n input: BuildAddGroupUserPolicyInput,\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n targetKey: string,\n): Promise<PutPrincipalPolicyRequest> {\n const groupSecretKey = await unwrapDek(\n toRecipientEntries(input.currentPolicy.currentMemberEnvelopes.envelopes),\n input.currentUserSecretKey,\n );\n if (\n !(await principalSecretKeyMatchesState(\n groupSecretKey,\n input.currentPolicy.currentState,\n ))\n ) {\n await reportPrincipalEnvelopeMismatch(input);\n return buildRotatedKeyGroupPolicyRequest(input, projection, [\n ...input.currentUsers,\n input.targetUser,\n ]);\n }\n const [targetEnvelope] = await wrapDekForRecipients(groupSecretKey, [\n input.targetUser.encapsulationPublicKey,\n ]);\n\n if (!targetEnvelope) {\n throw new Error(\"Failed to wrap group key for target user\");\n }\n\n const memberEnvelopes = [\n ...input.currentPolicy.currentMemberEnvelopes.envelopes.filter(\n (envelope) => envelope.userId !== targetKey,\n ),\n {\n userId: input.targetUser.userId,\n memberKeyFingerprint: input.targetUser.encapsulationKeyFingerprint,\n kemCipherText: bytesToBase64(targetEnvelope.kemCipherText),\n wrappedKey: bytesToBase64(targetEnvelope.wrappedKey),\n },\n ];\n return signedGroupPolicyRequest({\n currentPolicy: input.currentPolicy,\n encapsulationPublicKey:\n input.currentPolicy.currentState.encapsulationPublicKey,\n externalAuthority: null,\n keyEpoch: input.currentPolicy.currentState.keyEpoch,\n keyFingerprint: input.currentPolicy.currentState.keyFingerprint,\n grants: input.currentPolicy.currentGrants,\n memberEnvelopes,\n payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,\n principalId: input.currentPolicy.currentState.principalId,\n projection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n\nexport async function buildAddGroupUserPolicyRequest(\n input: BuildAddGroupUserPolicyInput,\n): Promise<PutPrincipalPolicyRequest> {\n await verifyAndAuthorizeGroupMutation(input);\n\n const targetKey = input.targetUser.userId;\n const currentProjection = input.currentPolicy.currentProjection;\n if (currentProjection.some((member) => member.userId === targetKey)) {\n throw new Error(\"User is already a group member\");\n }\n\n const projection = [\n ...currentProjection,\n userProjectionMember(\n input.targetUser.userId,\n input.isOrganizationAdminsGroup ? \"admin\" : \"member\",\n ),\n ];\n\n return isDirectGroupAdmin(input.currentPolicy, input.signerUserId)\n ? buildDirectAdminAddGroupUserPolicyRequest(input, projection, targetKey)\n : buildRotatedKeyGroupPolicyRequest(input, projection, [\n ...input.currentUsers,\n input.targetUser,\n ]);\n}\n\nexport async function buildRemoveGroupUserPolicyRequest(\n input: BuildGroupMembershipMutationInput & {\n readonly remainingUsers: ReadonlyArray<TrustedUserIdentity>;\n readonly removedUserId: string;\n },\n): Promise<PutPrincipalPolicyRequest> {\n await verifyAndAuthorizeGroupMutation(input);\n\n const key = input.removedUserId;\n const projection = input.currentPolicy.currentProjection.filter(\n (member) => member.userId !== key,\n );\n\n if (projection.length === input.currentPolicy.currentProjection.length) {\n throw new Error(\"User is not a group member\");\n }\n\n if (\n hasAdmin(input.currentPolicy.currentProjection) &&\n !hasAdmin(projection)\n ) {\n throw new Error(\"Cannot remove the last group admin\");\n }\n\n return buildRotatedKeyGroupPolicyRequest(\n input,\n projection,\n input.remainingUsers,\n );\n}\n\nexport async function buildGroupAccessSetShrinkPolicyRequest(\n input: BuildGroupMembershipMutationInput & {\n readonly currentUsers: ReadonlyArray<TrustedUserIdentity>;\n readonly revokedContainerId: string;\n },\n): Promise<PutPrincipalPolicyRequest> {\n await verifyAndAuthorizeGroupMutation(input);\n\n return buildRotatedKeyGroupPolicyRequest(\n input,\n [...input.currentPolicy.currentProjection],\n input.currentUsers,\n input.currentPolicy.currentGrants.filter(\n (grant) => grant.containerId !== input.revokedContainerId,\n ),\n );\n}\n\n/** Signs a complete successor grant projection without rotating group key material. */\nexport async function buildSetGroupContainerGrantPolicyRequest(\n input: BuildGroupMembershipMutationInput & {\n readonly accessLevel: PrincipalContainerGrantRequest[\"accessLevel\"];\n readonly containerId: string;\n },\n): Promise<PutPrincipalPolicyRequest> {\n await verifyAndAuthorizeGroupMutation(input);\n const grants = [\n ...input.currentPolicy.currentGrants.filter(\n (grant) => grant.containerId !== input.containerId,\n ),\n { accessLevel: input.accessLevel, containerId: input.containerId },\n ];\n return signedGroupPolicyRequest({\n currentPolicy: input.currentPolicy,\n encapsulationPublicKey:\n input.currentPolicy.currentState.encapsulationPublicKey,\n externalAuthority: isDirectGroupAdmin(\n input.currentPolicy,\n input.signerUserId,\n )\n ? null\n : requireExternalAuthority(input.externalAuthority).currentHead,\n keyEpoch: input.currentPolicy.currentState.keyEpoch,\n keyFingerprint: input.currentPolicy.currentState.keyFingerprint,\n grants,\n memberEnvelopes: input.currentPolicy.currentMemberEnvelopes.envelopes,\n payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,\n principalId: input.currentPolicy.currentState.principalId,\n projection: input.currentPolicy.currentProjection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n"]}
1
+ {"version":3,"file":"groupPolicyRequests.js","sourceRoot":"","sources":["groupPolicyRequests.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n generateKemSeedAndKeyPair,\n KeyingVerificationError,\n type PrincipalPolicyExternalAuthority,\n toFingerprint,\n unwrapDek,\n wrapDekForRecipients,\n} from \"@tearleads/crypto\";\nimport { bytesToBase64 } from \"@tearleads/encoding\";\nimport type {\n PrincipalContainerGrantRequest,\n PrincipalProjectionMemberRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport { principalSecretKeyMatchesState } from \"../../data/principals/principalKeyValidation\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\nimport type { TrustedUserIdentity } from \"../../data/trustedUserIdentity\";\nimport { isDirectGroupAdmin } from \"./groupMutationAuthorization\";\nimport {\n type BuildGroupMembershipMutationInput,\n withVerifiedGroupMutation,\n} from \"./groupPolicyMutationEvidence\";\nimport {\n rewrapProjectionMemberEnvelopes,\n toRecipientEntries,\n} from \"./principalPolicyRecipients\";\nimport {\n signedGroupPolicyRequest,\n userProjectionMember,\n} from \"./principalPolicyRequest\";\n\ntype BuildAddGroupUserPolicyInput = BuildGroupMembershipMutationInput & {\n readonly currentUsers: ReadonlyArray<TrustedUserIdentity>;\n readonly currentUserSecretKey: Uint8Array;\n readonly reportSecurityIncident?: SecurityIncidentReporter | undefined;\n readonly targetUser: TrustedUserIdentity;\n};\n\n/**\n * The signed policy commits both the group's public key and the member\n * envelopes that are supposed to wrap its secret. An envelope that unwraps to\n * a different secret means a prior admin (or the server) published a policy\n * whose envelopes do not match its signed key. Rotating repairs the group, but\n * the mismatch is evidence and is recorded before the repair proceeds.\n */\nasync function reportPrincipalEnvelopeMismatch(\n input: BuildAddGroupUserPolicyInput,\n): Promise<void> {\n const state = input.currentPolicy.currentState;\n await input.reportSecurityIncident?.(\n new KeyingVerificationError(\n \"object_mismatch\",\n \"Group member envelope does not unwrap the signed principal key\",\n ),\n {\n evidenceHashes: {\n principalKeyFingerprint: state.keyFingerprint,\n principalStateHash: state.stateHash,\n },\n objectId: state.principalId,\n objectKind: \"principal\",\n operation: \"group.policy.envelope_mismatch\",\n },\n );\n}\n\nfunction hasAdmin(\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n): boolean {\n return projection.some((member) => member.role === \"admin\");\n}\n\nfunction requireExternalAuthority(\n authority: PrincipalPolicyExternalAuthority | undefined,\n): PrincipalPolicyExternalAuthority {\n if (!authority) {\n throw new Error(\"External principal authority could not be verified\");\n }\n return authority;\n}\n\nasync function buildRotatedKeyGroupPolicyRequest(\n input: BuildGroupMembershipMutationInput,\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n users: ReadonlyArray<TrustedUserIdentity>,\n grants = input.currentPolicy.currentGrants,\n): Promise<PutPrincipalPolicyRequest> {\n const groupKem = generateKemSeedAndKeyPair();\n const memberEnvelopes = await rewrapProjectionMemberEnvelopes({\n projection,\n secretKey: groupKem.secretKey,\n users,\n });\n return signedGroupPolicyRequest({\n currentPolicy: input.currentPolicy,\n encapsulationPublicKey: bytesToBase64(groupKem.publicKey),\n externalAuthority: isDirectGroupAdmin(\n input.currentPolicy,\n input.signerUserId,\n )\n ? null\n : requireExternalAuthority(input.externalAuthority).currentHead,\n keyEpoch: input.currentPolicy.currentState.keyEpoch + 1,\n keyFingerprint: await toFingerprint(groupKem.publicKey),\n grants,\n memberEnvelopes,\n payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,\n principalId: input.currentPolicy.currentState.principalId,\n projection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n\nasync function buildDirectAdminAddGroupUserPolicyRequest(\n input: BuildAddGroupUserPolicyInput,\n projection: ReadonlyArray<PrincipalProjectionMemberRequest>,\n targetKey: string,\n): Promise<PutPrincipalPolicyRequest> {\n const groupSecretKey = await unwrapDek(\n toRecipientEntries(input.currentPolicy.currentMemberEnvelopes.envelopes),\n input.currentUserSecretKey,\n );\n if (\n !(await principalSecretKeyMatchesState(\n groupSecretKey,\n input.currentPolicy.currentState,\n ))\n ) {\n await reportPrincipalEnvelopeMismatch(input);\n return buildRotatedKeyGroupPolicyRequest(input, projection, [\n ...input.currentUsers,\n input.targetUser,\n ]);\n }\n const [targetEnvelope] = await wrapDekForRecipients(groupSecretKey, [\n input.targetUser.encapsulationPublicKey,\n ]);\n\n if (!targetEnvelope) {\n throw new Error(\"Failed to wrap group key for target user\");\n }\n\n const memberEnvelopes = [\n ...input.currentPolicy.currentMemberEnvelopes.envelopes.filter(\n (envelope) => envelope.userId !== targetKey,\n ),\n {\n userId: input.targetUser.userId,\n memberKeyFingerprint: input.targetUser.encapsulationKeyFingerprint,\n kemCipherText: bytesToBase64(targetEnvelope.kemCipherText),\n wrappedKey: bytesToBase64(targetEnvelope.wrappedKey),\n },\n ];\n return signedGroupPolicyRequest({\n currentPolicy: input.currentPolicy,\n encapsulationPublicKey:\n input.currentPolicy.currentState.encapsulationPublicKey,\n externalAuthority: null,\n keyEpoch: input.currentPolicy.currentState.keyEpoch,\n keyFingerprint: input.currentPolicy.currentState.keyFingerprint,\n grants: input.currentPolicy.currentGrants,\n memberEnvelopes,\n payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,\n principalId: input.currentPolicy.currentState.principalId,\n projection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n\nexport async function buildAddGroupUserPolicyRequest(\n input: BuildAddGroupUserPolicyInput,\n): Promise<PutPrincipalPolicyRequest> {\n input = {\n ...input,\n currentUsers: structuredClone(input.currentUsers),\n currentUserSecretKey: input.currentUserSecretKey.slice(),\n targetUser: structuredClone(input.targetUser),\n };\n try {\n return await withVerifiedGroupMutation(input, async (input) => {\n const targetKey = input.targetUser.userId;\n const currentProjection = input.currentPolicy.currentProjection;\n if (currentProjection.some((member) => member.userId === targetKey)) {\n throw new Error(\"User is already a group member\");\n }\n\n const projection = [\n ...currentProjection,\n userProjectionMember(\n input.targetUser.userId,\n input.isOrganizationAdminsGroup ? \"admin\" : \"member\",\n ),\n ];\n\n return isDirectGroupAdmin(input.currentPolicy, input.signerUserId)\n ? buildDirectAdminAddGroupUserPolicyRequest(\n input,\n projection,\n targetKey,\n )\n : buildRotatedKeyGroupPolicyRequest(input, projection, [\n ...input.currentUsers,\n input.targetUser,\n ]);\n });\n } finally {\n input.currentUserSecretKey.fill(0);\n }\n}\n\nexport async function buildRemoveGroupUserPolicyRequest(\n input: BuildGroupMembershipMutationInput & {\n readonly remainingUsers: ReadonlyArray<TrustedUserIdentity>;\n readonly removedUserId: string;\n },\n): Promise<PutPrincipalPolicyRequest> {\n input = { ...input, remainingUsers: structuredClone(input.remainingUsers) };\n return withVerifiedGroupMutation(input, async (input) => {\n const key = input.removedUserId;\n const projection = input.currentPolicy.currentProjection.filter(\n (member) => member.userId !== key,\n );\n\n if (projection.length === input.currentPolicy.currentProjection.length) {\n throw new Error(\"User is not a group member\");\n }\n\n if (\n hasAdmin(input.currentPolicy.currentProjection) &&\n !hasAdmin(projection)\n ) {\n throw new Error(\"Cannot remove the last group admin\");\n }\n\n return buildRotatedKeyGroupPolicyRequest(\n input,\n projection,\n input.remainingUsers,\n );\n });\n}\n\nexport async function buildGroupAccessSetShrinkPolicyRequest(\n input: BuildGroupMembershipMutationInput & {\n readonly currentUsers: ReadonlyArray<TrustedUserIdentity>;\n readonly revokedContainerId: string;\n },\n): Promise<PutPrincipalPolicyRequest> {\n input = { ...input, currentUsers: structuredClone(input.currentUsers) };\n return withVerifiedGroupMutation(input, async (input) => {\n return buildRotatedKeyGroupPolicyRequest(\n input,\n [...input.currentPolicy.currentProjection],\n input.currentUsers,\n input.currentPolicy.currentGrants.filter(\n (grant) => grant.containerId !== input.revokedContainerId,\n ),\n );\n });\n}\n\n/** Signs a complete successor grant projection without rotating group key material. */\nexport async function buildSetGroupContainerGrantPolicyRequest(\n input: BuildGroupMembershipMutationInput & {\n readonly accessLevel: PrincipalContainerGrantRequest[\"accessLevel\"];\n readonly containerId: string;\n },\n): Promise<PutPrincipalPolicyRequest> {\n return withVerifiedGroupMutation(input, async (input) => {\n const grants = [\n ...input.currentPolicy.currentGrants.filter(\n (grant) => grant.containerId !== input.containerId,\n ),\n { accessLevel: input.accessLevel, containerId: input.containerId },\n ];\n return signedGroupPolicyRequest({\n currentPolicy: input.currentPolicy,\n encapsulationPublicKey:\n input.currentPolicy.currentState.encapsulationPublicKey,\n externalAuthority: isDirectGroupAdmin(\n input.currentPolicy,\n input.signerUserId,\n )\n ? null\n : requireExternalAuthority(input.externalAuthority).currentHead,\n keyEpoch: input.currentPolicy.currentState.keyEpoch,\n keyFingerprint: input.currentPolicy.currentState.keyFingerprint,\n grants,\n memberEnvelopes: input.currentPolicy.currentMemberEnvelopes.envelopes,\n payloadCiphertext: input.currentPolicy.currentPayload.ciphertext,\n principalId: input.currentPolicy.currentState.principalId,\n projection: input.currentPolicy.currentProjection,\n signedAt: new Date().toISOString(),\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n });\n}\n"]}
@@ -1,4 +1,7 @@
1
1
  export { type OrganizationReadModelInvalidationListener, subscribeOrganizationReadModelInvalidation, } from "../../data/persistence/organizations/organizationReadModelInvalidation.js";
2
+ export { PendingPrincipalMutationError } from "../../data/persistence/principalMutationJournalPersistence.js";
3
+ export type { AuthoredPrincipalMutation, PrincipalMutationJournalScope, } from "../../data/principals/principalMutationJournal.js";
4
+ export { UnreadablePrincipalMutationError } from "../../data/principals/principalMutationJournalRecord.js";
2
5
  export { cancelStripeSubscription, checkNativePurchaseEligibility, claimNativeOrganizationSubscription, createStripeCheckout, createStripeCheckoutSession, loadOrganizationBilling, loadOrganizationBillingHistory, loadOrganizationBillingManagementUrl, loadStripeCheckoutOptions, type OrganizationBilling, type OrganizationBillingHistory, type OrganizationBillingHistoryEntry, type OrganizationBillingManagementUrl, type OrganizationBillingView, type OrganizationNativePurchaseEligibility, resolveOrganizationBillingView, type StripeCheckoutIntent, type StripeCheckoutOptions, startOrganizationTrial, } from "./billing.js";
3
6
  export { revokeOrganizationContainerGrant } from "./containerGrantRevocation.js";
4
7
  export { type CreateOrganizationApi, type CreateOrganizationInput, createOrganization, } from "./createOrganization.js";
@@ -9,7 +12,10 @@ export { type LocalOrganizationSummary, listLocalOrganizations, } from "./listLo
9
12
  export { loadLocalOrganizationContainerGrants, loadLocalOrganizationGroupContainers, loadLocalOrganizationGroupPolicyHistory, loadLocalOrganizationPolicyHistory, loadLocalOrganizationPolicyReference, loadLocalOrganizationUserDetail, } from "./localReadModelDetails.js";
10
13
  export { buildOrganizationProfileDocumentPatch, createInitializedOrganizationProfileDocument, DEFAULT_PERSONAL_ORGANIZATION_PROFILE_NAME, getOrganizationProfileDocumentLocalId, ORGANIZATION_PROFILE_DOCUMENT_KIND, readOrganizationProfileName, } from "./organizationProfile.js";
11
14
  export { type ImportedOrganizationUser, importOrganizationUser, } from "./organizationUserImport.js";
15
+ export { abandonJournaledPrincipalMutation, discardUnreadableJournaledPrincipalMutation, readJournaledPrincipalMutation, } from "./principalMutationJournalManagement.js";
16
+ export { type PrincipalMutationJournalContext, PrincipalMutationOutcomeUnknownError, recoverJournaledPrincipalMutation, submitJournaledPrincipalMutation, } from "./principalMutationJournalSession.js";
12
17
  export { addOrganizationGroupUser, buildInitialGroupPolicyRequest, buildInitialMemberGroupPolicyRequest, createOrganizationGroup, removeOrganizationGroupUser, rotateOrganizationGroupForAccessSetShrink, } from "./principalPolicy.js";
13
18
  export { buildOrganizationGroupPolicyHistory, type OrganizationContainerGrant, type OrganizationContainerGrants, type OrganizationDirectory, type OrganizationDirectoryAndGroups, type OrganizationDirectoryUser, type OrganizationGroupContainer, type OrganizationGroupContainers, type OrganizationGroupDetails, type OrganizationGroupMember, type OrganizationGroupMembers, type OrganizationGroupPolicyHistory, type OrganizationGroupPolicyHistoryEntry, type OrganizationGroupSummary, type OrganizationPolicyGrantChange, type OrganizationPolicyGroupChange, type OrganizationPolicyHistory, type OrganizationPolicyHistoryEntry, type OrganizationPrincipalMemberChange, type OrganizationPrincipalMemberChangeType, type OrganizationPrincipalPolicyHistory, type OrganizationPrincipalPolicyHistoryEntry, type OrganizationProfile, type OrganizationUserDetail, updateOrganizationProfile, updateOrganizationRosterEntry, } from "./readModel.js";
14
19
  export { loadLocalOrganizationDirectoryAndGroups, loadLocalOrganizationGroupMembers, type ReconcileOrganizationDirectoryAndGroupsInput, reconcileOrganizationDirectoryAndGroups, } from "./readModelProjection.js";
20
+ export { type AcknowledgedPrincipalCurrentInput, type AcknowledgedPrincipalCurrentRetirement, retainAcknowledgedPrincipalCurrents, } from "./retainAcknowledgedPrincipalCurrents.js";
15
21
  export { buildRosterProfileDocumentPatch, createInitializedRosterProfileDocument, deriveOrganizationMetadataContainerSystemSlot, deriveOrganizationRosterProfileContainerSystemSlot, getRosterProfileDocumentLocalId, ORGANIZATION_METADATA_CONTAINER_NAME, ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME, ROSTER_PROFILE_DOCUMENT_KIND, } from "./rosterProfileContainer.js";
@@ -1,4 +1,6 @@
1
1
  export { subscribeOrganizationReadModelInvalidation, } from "../../data/persistence/organizations/organizationReadModelInvalidation.js";
2
+ export { PendingPrincipalMutationError } from "../../data/persistence/principalMutationJournalPersistence.js";
3
+ export { UnreadablePrincipalMutationError } from "../../data/principals/principalMutationJournalRecord.js";
2
4
  export { cancelStripeSubscription, checkNativePurchaseEligibility, claimNativeOrganizationSubscription, createStripeCheckout, createStripeCheckoutSession, loadOrganizationBilling, loadOrganizationBillingHistory, loadOrganizationBillingManagementUrl, loadStripeCheckoutOptions, resolveOrganizationBillingView, startOrganizationTrial, } from "./billing.js";
3
5
  export { revokeOrganizationContainerGrant } from "./containerGrantRevocation.js";
4
6
  export { createOrganization, } from "./createOrganization.js";
@@ -9,8 +11,11 @@ export { listLocalOrganizations, } from "./listLocalOrganizations.js";
9
11
  export { loadLocalOrganizationContainerGrants, loadLocalOrganizationGroupContainers, loadLocalOrganizationGroupPolicyHistory, loadLocalOrganizationPolicyHistory, loadLocalOrganizationPolicyReference, loadLocalOrganizationUserDetail, } from "./localReadModelDetails.js";
10
12
  export { buildOrganizationProfileDocumentPatch, createInitializedOrganizationProfileDocument, DEFAULT_PERSONAL_ORGANIZATION_PROFILE_NAME, getOrganizationProfileDocumentLocalId, ORGANIZATION_PROFILE_DOCUMENT_KIND, readOrganizationProfileName, } from "./organizationProfile.js";
11
13
  export { importOrganizationUser, } from "./organizationUserImport.js";
14
+ export { abandonJournaledPrincipalMutation, discardUnreadableJournaledPrincipalMutation, readJournaledPrincipalMutation, } from "./principalMutationJournalManagement.js";
15
+ export { PrincipalMutationOutcomeUnknownError, recoverJournaledPrincipalMutation, submitJournaledPrincipalMutation, } from "./principalMutationJournalSession.js";
12
16
  export { addOrganizationGroupUser, buildInitialGroupPolicyRequest, buildInitialMemberGroupPolicyRequest, createOrganizationGroup, removeOrganizationGroupUser, rotateOrganizationGroupForAccessSetShrink, } from "./principalPolicy.js";
13
17
  export { buildOrganizationGroupPolicyHistory, updateOrganizationProfile, updateOrganizationRosterEntry, } from "./readModel.js";
14
18
  export { loadLocalOrganizationDirectoryAndGroups, loadLocalOrganizationGroupMembers, reconcileOrganizationDirectoryAndGroups, } from "./readModelProjection.js";
19
+ export { retainAcknowledgedPrincipalCurrents, } from "./retainAcknowledgedPrincipalCurrents.js";
15
20
  export { buildRosterProfileDocumentPatch, createInitializedRosterProfileDocument, deriveOrganizationMetadataContainerSystemSlot, deriveOrganizationRosterProfileContainerSystemSlot, getRosterProfileDocumentLocalId, ORGANIZATION_METADATA_CONTAINER_NAME, ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME, ROSTER_PROFILE_DOCUMENT_KIND, } from "./rosterProfileContainer.js";
16
21
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,0CAA0C,GAC3C,MAAM,wEAAwE,CAAC;AAChF,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,mCAAmC,EACnC,oBAAoB,EACpB,2BAA2B,EAC3B,uBAAuB,EACvB,8BAA8B,EAC9B,oCAAoC,EACpC,yBAAyB,EAOzB,8BAA8B,EAG9B,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAGL,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,8BAA8B,EAG9B,8BAA8B,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAEL,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,oCAAoC,EACpC,oCAAoC,EACpC,uCAAuC,EACvC,kCAAkC,EAClC,oCAAoC,EACpC,+BAA+B,GAChC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qCAAqC,EACrC,4CAA4C,EAC5C,0CAA0C,EAC1C,qCAAqC,EACrC,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,oCAAoC,EACpC,uBAAuB,EACvB,2BAA2B,EAC3B,yCAAyC,GAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mCAAmC,EAwBnC,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uCAAuC,EACvC,iCAAiC,EAEjC,uCAAuC,GACxC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,+BAA+B,EAC/B,sCAAsC,EACtC,6CAA6C,EAC7C,kDAAkD,EAClD,+BAA+B,EAC/B,oCAAoC,EACpC,0CAA0C,EAC1C,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n type OrganizationReadModelInvalidationListener,\n subscribeOrganizationReadModelInvalidation,\n} from \"../../data/persistence/organizations/organizationReadModelInvalidation\";\nexport {\n cancelStripeSubscription,\n checkNativePurchaseEligibility,\n claimNativeOrganizationSubscription,\n createStripeCheckout,\n createStripeCheckoutSession,\n loadOrganizationBilling,\n loadOrganizationBillingHistory,\n loadOrganizationBillingManagementUrl,\n loadStripeCheckoutOptions,\n type OrganizationBilling,\n type OrganizationBillingHistory,\n type OrganizationBillingHistoryEntry,\n type OrganizationBillingManagementUrl,\n type OrganizationBillingView,\n type OrganizationNativePurchaseEligibility,\n resolveOrganizationBillingView,\n type StripeCheckoutIntent,\n type StripeCheckoutOptions,\n startOrganizationTrial,\n} from \"./billing\";\nexport { revokeOrganizationContainerGrant } from \"./containerGrantRevocation\";\nexport {\n type CreateOrganizationApi,\n type CreateOrganizationInput,\n createOrganization,\n} from \"./createOrganization\";\nexport {\n loadLocalOrganizationDataUsage,\n type OrganizationDataUsage,\n type ReconcileOrganizationDataUsageInput,\n reconcileOrganizationDataUsage,\n} from \"./dataUsageReadModel\";\nexport { deleteOrganizationGroup } from \"./deleteOrganizationGroup\";\nexport { GroupMembershipNameMismatchError } from \"./groupMembershipName\";\nexport {\n type LocalOrganizationSummary,\n listLocalOrganizations,\n} from \"./listLocalOrganizations\";\nexport {\n loadLocalOrganizationContainerGrants,\n loadLocalOrganizationGroupContainers,\n loadLocalOrganizationGroupPolicyHistory,\n loadLocalOrganizationPolicyHistory,\n loadLocalOrganizationPolicyReference,\n loadLocalOrganizationUserDetail,\n} from \"./localReadModelDetails\";\nexport {\n buildOrganizationProfileDocumentPatch,\n createInitializedOrganizationProfileDocument,\n DEFAULT_PERSONAL_ORGANIZATION_PROFILE_NAME,\n getOrganizationProfileDocumentLocalId,\n ORGANIZATION_PROFILE_DOCUMENT_KIND,\n readOrganizationProfileName,\n} from \"./organizationProfile\";\nexport {\n type ImportedOrganizationUser,\n importOrganizationUser,\n} from \"./organizationUserImport\";\nexport {\n addOrganizationGroupUser,\n buildInitialGroupPolicyRequest,\n buildInitialMemberGroupPolicyRequest,\n createOrganizationGroup,\n removeOrganizationGroupUser,\n rotateOrganizationGroupForAccessSetShrink,\n} from \"./principalPolicy\";\nexport {\n buildOrganizationGroupPolicyHistory,\n type OrganizationContainerGrant,\n type OrganizationContainerGrants,\n type OrganizationDirectory,\n type OrganizationDirectoryAndGroups,\n type OrganizationDirectoryUser,\n type OrganizationGroupContainer,\n type OrganizationGroupContainers,\n type OrganizationGroupDetails,\n type OrganizationGroupMember,\n type OrganizationGroupMembers,\n type OrganizationGroupPolicyHistory,\n type OrganizationGroupPolicyHistoryEntry,\n type OrganizationGroupSummary,\n type OrganizationPolicyGrantChange,\n type OrganizationPolicyGroupChange,\n type OrganizationPolicyHistory,\n type OrganizationPolicyHistoryEntry,\n type OrganizationPrincipalMemberChange,\n type OrganizationPrincipalMemberChangeType,\n type OrganizationPrincipalPolicyHistory,\n type OrganizationPrincipalPolicyHistoryEntry,\n type OrganizationProfile,\n type OrganizationUserDetail,\n updateOrganizationProfile,\n updateOrganizationRosterEntry,\n} from \"./readModel\";\nexport {\n loadLocalOrganizationDirectoryAndGroups,\n loadLocalOrganizationGroupMembers,\n type ReconcileOrganizationDirectoryAndGroupsInput,\n reconcileOrganizationDirectoryAndGroups,\n} from \"./readModelProjection\";\nexport {\n buildRosterProfileDocumentPatch,\n createInitializedRosterProfileDocument,\n deriveOrganizationMetadataContainerSystemSlot,\n deriveOrganizationRosterProfileContainerSystemSlot,\n getRosterProfileDocumentLocalId,\n ORGANIZATION_METADATA_CONTAINER_NAME,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n ROSTER_PROFILE_DOCUMENT_KIND,\n} from \"./rosterProfileContainer\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,0CAA0C,GAC3C,MAAM,wEAAwE,CAAC;AAChF,OAAO,EAAE,6BAA6B,EAAE,MAAM,4DAA4D,CAAC;AAK3G,OAAO,EAAE,gCAAgC,EAAE,MAAM,sDAAsD,CAAC;AACxG,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,mCAAmC,EACnC,oBAAoB,EACpB,2BAA2B,EAC3B,uBAAuB,EACvB,8BAA8B,EAC9B,oCAAoC,EACpC,yBAAyB,EAOzB,8BAA8B,EAG9B,sBAAsB,GACvB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,gCAAgC,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EAGL,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,8BAA8B,EAG9B,8BAA8B,GAC/B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAEL,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,oCAAoC,EACpC,oCAAoC,EACpC,uCAAuC,EACvC,kCAAkC,EAClC,oCAAoC,EACpC,+BAA+B,GAChC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qCAAqC,EACrC,4CAA4C,EAC5C,0CAA0C,EAC1C,qCAAqC,EACrC,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,iCAAiC,EACjC,2CAA2C,EAC3C,8BAA8B,GAC/B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAEL,oCAAoC,EACpC,iCAAiC,EACjC,gCAAgC,GACjC,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,wBAAwB,EACxB,8BAA8B,EAC9B,oCAAoC,EACpC,uBAAuB,EACvB,2BAA2B,EAC3B,yCAAyC,GAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mCAAmC,EAwBnC,yBAAyB,EACzB,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uCAAuC,EACvC,iCAAiC,EAEjC,uCAAuC,GACxC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,mCAAmC,GACpC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACL,+BAA+B,EAC/B,sCAAsC,EACtC,6CAA6C,EAC7C,kDAAkD,EAClD,+BAA+B,EAC/B,oCAAoC,EACpC,0CAA0C,EAC1C,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC","sourcesContent":["export {\n type OrganizationReadModelInvalidationListener,\n subscribeOrganizationReadModelInvalidation,\n} from \"../../data/persistence/organizations/organizationReadModelInvalidation\";\nexport { PendingPrincipalMutationError } from \"../../data/persistence/principalMutationJournalPersistence\";\nexport type {\n AuthoredPrincipalMutation,\n PrincipalMutationJournalScope,\n} from \"../../data/principals/principalMutationJournal\";\nexport { UnreadablePrincipalMutationError } from \"../../data/principals/principalMutationJournalRecord\";\nexport {\n cancelStripeSubscription,\n checkNativePurchaseEligibility,\n claimNativeOrganizationSubscription,\n createStripeCheckout,\n createStripeCheckoutSession,\n loadOrganizationBilling,\n loadOrganizationBillingHistory,\n loadOrganizationBillingManagementUrl,\n loadStripeCheckoutOptions,\n type OrganizationBilling,\n type OrganizationBillingHistory,\n type OrganizationBillingHistoryEntry,\n type OrganizationBillingManagementUrl,\n type OrganizationBillingView,\n type OrganizationNativePurchaseEligibility,\n resolveOrganizationBillingView,\n type StripeCheckoutIntent,\n type StripeCheckoutOptions,\n startOrganizationTrial,\n} from \"./billing\";\nexport { revokeOrganizationContainerGrant } from \"./containerGrantRevocation\";\nexport {\n type CreateOrganizationApi,\n type CreateOrganizationInput,\n createOrganization,\n} from \"./createOrganization\";\nexport {\n loadLocalOrganizationDataUsage,\n type OrganizationDataUsage,\n type ReconcileOrganizationDataUsageInput,\n reconcileOrganizationDataUsage,\n} from \"./dataUsageReadModel\";\nexport { deleteOrganizationGroup } from \"./deleteOrganizationGroup\";\nexport { GroupMembershipNameMismatchError } from \"./groupMembershipName\";\nexport {\n type LocalOrganizationSummary,\n listLocalOrganizations,\n} from \"./listLocalOrganizations\";\nexport {\n loadLocalOrganizationContainerGrants,\n loadLocalOrganizationGroupContainers,\n loadLocalOrganizationGroupPolicyHistory,\n loadLocalOrganizationPolicyHistory,\n loadLocalOrganizationPolicyReference,\n loadLocalOrganizationUserDetail,\n} from \"./localReadModelDetails\";\nexport {\n buildOrganizationProfileDocumentPatch,\n createInitializedOrganizationProfileDocument,\n DEFAULT_PERSONAL_ORGANIZATION_PROFILE_NAME,\n getOrganizationProfileDocumentLocalId,\n ORGANIZATION_PROFILE_DOCUMENT_KIND,\n readOrganizationProfileName,\n} from \"./organizationProfile\";\nexport {\n type ImportedOrganizationUser,\n importOrganizationUser,\n} from \"./organizationUserImport\";\nexport {\n abandonJournaledPrincipalMutation,\n discardUnreadableJournaledPrincipalMutation,\n readJournaledPrincipalMutation,\n} from \"./principalMutationJournalManagement\";\nexport {\n type PrincipalMutationJournalContext,\n PrincipalMutationOutcomeUnknownError,\n recoverJournaledPrincipalMutation,\n submitJournaledPrincipalMutation,\n} from \"./principalMutationJournalSession\";\nexport {\n addOrganizationGroupUser,\n buildInitialGroupPolicyRequest,\n buildInitialMemberGroupPolicyRequest,\n createOrganizationGroup,\n removeOrganizationGroupUser,\n rotateOrganizationGroupForAccessSetShrink,\n} from \"./principalPolicy\";\nexport {\n buildOrganizationGroupPolicyHistory,\n type OrganizationContainerGrant,\n type OrganizationContainerGrants,\n type OrganizationDirectory,\n type OrganizationDirectoryAndGroups,\n type OrganizationDirectoryUser,\n type OrganizationGroupContainer,\n type OrganizationGroupContainers,\n type OrganizationGroupDetails,\n type OrganizationGroupMember,\n type OrganizationGroupMembers,\n type OrganizationGroupPolicyHistory,\n type OrganizationGroupPolicyHistoryEntry,\n type OrganizationGroupSummary,\n type OrganizationPolicyGrantChange,\n type OrganizationPolicyGroupChange,\n type OrganizationPolicyHistory,\n type OrganizationPolicyHistoryEntry,\n type OrganizationPrincipalMemberChange,\n type OrganizationPrincipalMemberChangeType,\n type OrganizationPrincipalPolicyHistory,\n type OrganizationPrincipalPolicyHistoryEntry,\n type OrganizationProfile,\n type OrganizationUserDetail,\n updateOrganizationProfile,\n updateOrganizationRosterEntry,\n} from \"./readModel\";\nexport {\n loadLocalOrganizationDirectoryAndGroups,\n loadLocalOrganizationGroupMembers,\n type ReconcileOrganizationDirectoryAndGroupsInput,\n reconcileOrganizationDirectoryAndGroups,\n} from \"./readModelProjection\";\nexport {\n type AcknowledgedPrincipalCurrentInput,\n type AcknowledgedPrincipalCurrentRetirement,\n retainAcknowledgedPrincipalCurrents,\n} from \"./retainAcknowledgedPrincipalCurrents\";\nexport {\n buildRosterProfileDocumentPatch,\n createInitializedRosterProfileDocument,\n deriveOrganizationMetadataContainerSystemSlot,\n deriveOrganizationRosterProfileContainerSystemSlot,\n getRosterProfileDocumentLocalId,\n ORGANIZATION_METADATA_CONTAINER_NAME,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n ROSTER_PROFILE_DOCUMENT_KIND,\n} from \"./rosterProfileContainer\";\n"]}
@@ -0,0 +1,83 @@
1
+ import { createPrincipalPolicyHistoryVerifier, KeyingVerificationError, verifyPrincipalPolicyCurrent, } from "../../internal/crypto/index.js";
2
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
3
+ import { preparePrincipalHistoryEvidencePage } from "../../data/persistence/principalHistoryEvidencePersistence.js";
4
+ import { principalHeadMatchesReference } from "../../data/principals/organizationAuthorityDescriptor.js";
5
+ import { principalHistoryEvidenceScopeId } from "../../data/principals/principalHistoryPrefixProtection.js";
6
+ import { collectPrincipalPolicySignerPublicKeys } from "../principals/policyVerification.js";
7
+ import { assertPrincipalHistoryVerificationMode, principalHistoryVerificationContext, } from "../principals/principalHistoryRecoveryVerification.js";
8
+ import { groupPolicyMutationHead } from "./groupPolicyMutationHead.js";
9
+ import { sealPrincipalCurrentPublication } from "./principalCurrentPublicationSeal.js";
10
+ import { assertPrincipalPolicyReceiptArtifacts } from "./principalPolicyReceiptArtifacts.js";
11
+ /** Verify a newly authored group from genesis before its atomic directory publication. */
12
+ export async function prepareInitialGroupCurrentPublication(input, request, response) {
13
+ const current = () => !input.signal?.aborted && input.stillCurrent();
14
+ assertProjectionVerificationCurrent(current);
15
+ const expectedHead = await groupPolicyMutationHead(request);
16
+ if (request.state.principalType !== "group" ||
17
+ request.state.version !== 1 ||
18
+ request.state.prevStateHash !== null ||
19
+ !principalHeadMatchesReference(expectedHead, input.expectedHead))
20
+ throw new KeyingVerificationError("object_mismatch", "Initial group publication must begin at its exact genesis");
21
+ assertPrincipalPolicyReceiptArtifacts({ expectedHead, request, response });
22
+ const keys = await collectPrincipalPolicySignerPublicKeys({
23
+ bundle: { currentState: response.currentState, previousStates: [] },
24
+ resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,
25
+ });
26
+ if ("error" in keys)
27
+ throw new KeyingVerificationError("signer_mismatch", "Initial group signer could not be authenticated");
28
+ const externalAuthority = await input.loadExternalAuthority?.(request.state.externalAuthority ? [request.state.externalAuthority] : []);
29
+ assertProjectionVerificationCurrent(current);
30
+ const verifier = createPrincipalPolicyHistoryVerifier({
31
+ principalType: "group",
32
+ principalId: expectedHead.principalId,
33
+ });
34
+ const entry = {
35
+ state: response.currentState,
36
+ projection: response.currentProjection,
37
+ grants: response.currentGrants,
38
+ };
39
+ assertPrincipalHistoryVerificationMode(input, [entry]);
40
+ const appended = await verifier.append({
41
+ entries: [entry],
42
+ signerPublicKeys: keys.signerPublicKeys,
43
+ ...(externalAuthority ? { externalAuthority } : {}),
44
+ });
45
+ if (!appended.ok)
46
+ throw appended.error;
47
+ const history = verifier.finish(expectedHead);
48
+ if (!history.ok)
49
+ throw history.error;
50
+ const policy = await verifyPrincipalPolicyCurrent({
51
+ current: response,
52
+ history: history.value,
53
+ });
54
+ if (!policy.ok)
55
+ throw policy.error;
56
+ const options = {
57
+ ...input,
58
+ protection: {
59
+ ...input.protection,
60
+ context: principalHistoryVerificationContext(input),
61
+ },
62
+ };
63
+ const scopeId = await principalHistoryEvidenceScopeId({
64
+ organizationId: input.organizationId,
65
+ head: expectedHead,
66
+ protection: options.protection,
67
+ });
68
+ const sealed = await sealPrincipalCurrentPublication(options, scopeId, expectedHead, verifier, response);
69
+ assertProjectionVerificationCurrent(current);
70
+ return {
71
+ ...sealed,
72
+ policy: policy.value,
73
+ predecessorStage: null,
74
+ previousPrefixProgress: null,
75
+ evidence: await preparePrincipalHistoryEvidencePage({
76
+ scopeId,
77
+ organizationId: input.organizationId,
78
+ entries: [entry],
79
+ nodes: appended.value.indexNodes,
80
+ }),
81
+ };
82
+ }
83
+ //# sourceMappingURL=initialPrincipalCurrentPublication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"initialPrincipalCurrentPublication.js","sourceRoot":"","sources":["initialPrincipalCurrentPublication.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n verifyPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyMutationResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { AcknowledgedPrincipalCurrentPublication } from \"../../data/persistence/principalCurrentAcknowledgementPersistence\";\nimport { preparePrincipalHistoryEvidencePage } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { principalHistoryEvidenceScopeId } from \"../../data/principals/principalHistoryPrefixProtection\";\nimport { collectPrincipalPolicySignerPublicKeys } from \"../principals/policyVerification\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"../principals/principalHistoryRecoveryTypes\";\nimport {\n assertPrincipalHistoryVerificationMode,\n principalHistoryVerificationContext,\n} from \"../principals/principalHistoryRecoveryVerification\";\nimport { groupPolicyMutationHead } from \"./groupPolicyMutationHead\";\nimport { sealPrincipalCurrentPublication } from \"./principalCurrentPublicationSeal\";\nimport { assertPrincipalPolicyReceiptArtifacts } from \"./principalPolicyReceiptArtifacts\";\n\n/** Verify a newly authored group from genesis before its atomic directory publication. */\nexport async function prepareInitialGroupCurrentPublication(\n input: RecoverPrincipalPolicyHistoryOptions,\n request: PutPrincipalPolicyRequest,\n response: PrincipalPolicyMutationResponse,\n): Promise<AcknowledgedPrincipalCurrentPublication> {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const expectedHead = await groupPolicyMutationHead(request);\n if (\n request.state.principalType !== \"group\" ||\n request.state.version !== 1 ||\n request.state.prevStateHash !== null ||\n !principalHeadMatchesReference(expectedHead, input.expectedHead)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Initial group publication must begin at its exact genesis\",\n );\n assertPrincipalPolicyReceiptArtifacts({ expectedHead, request, response });\n const keys = await collectPrincipalPolicySignerPublicKeys({\n bundle: { currentState: response.currentState, previousStates: [] },\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (\"error\" in keys)\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Initial group signer could not be authenticated\",\n );\n const externalAuthority = await input.loadExternalAuthority?.(\n request.state.externalAuthority ? [request.state.externalAuthority] : [],\n );\n assertProjectionVerificationCurrent(current);\n const verifier = createPrincipalPolicyHistoryVerifier({\n principalType: \"group\",\n principalId: expectedHead.principalId,\n });\n const entry = {\n state: response.currentState,\n projection: response.currentProjection,\n grants: response.currentGrants,\n };\n assertPrincipalHistoryVerificationMode(input, [entry]);\n const appended = await verifier.append({\n entries: [entry],\n signerPublicKeys: keys.signerPublicKeys,\n ...(externalAuthority ? { externalAuthority } : {}),\n });\n if (!appended.ok) throw appended.error;\n const history = verifier.finish(expectedHead);\n if (!history.ok) throw history.error;\n const policy = await verifyPrincipalPolicyCurrent({\n current: response,\n history: history.value,\n });\n if (!policy.ok) throw policy.error;\n const options = {\n ...input,\n protection: {\n ...input.protection,\n context: principalHistoryVerificationContext(input),\n },\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: input.organizationId,\n head: expectedHead,\n protection: options.protection,\n });\n const sealed = await sealPrincipalCurrentPublication(\n options,\n scopeId,\n expectedHead,\n verifier,\n response,\n );\n assertProjectionVerificationCurrent(current);\n return {\n ...sealed,\n policy: policy.value,\n predecessorStage: null,\n previousPrefixProgress: null,\n evidence: await preparePrincipalHistoryEvidencePage({\n scopeId,\n organizationId: input.organizationId,\n entries: [entry],\n nodes: appended.value.indexNodes,\n }),\n };\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { buildPrincipalStateSigningInput, generateKemSeedAndKeyPair, normalizePrincipalProjectionMembers, signPrincipalState, toFingerprint, } from "../../internal/crypto/index.js";
2
2
  import { bytesToBase64 } from "../../internal/encoding/index.js";
3
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
3
4
  import { persistLocallyAcknowledgedPrincipalPolicyBundles } from "../../data/persistence/locallyAcknowledgedCheckpointPersistence.js";
4
5
  import { encodeOrganizationAuthorityDescriptor, normalizeOrganizationGroupHeads, } from "../../data/principals/organizationAuthorityDescriptor.js";
5
6
  import { assertGroupNameUniqueInDirectory } from "./groupNameUniqueness.js";
@@ -78,6 +79,7 @@ export async function buildOrganizationGroupDirectoryPolicyRequest(input) {
78
79
  };
79
80
  }
80
81
  export async function commitCreatedGroupToDirectory(input) {
82
+ assertProjectionVerificationCurrent(input.stillCurrent);
81
83
  // Signed group names are unique per organization; refuse a collision before
82
84
  // anything reaches the server.
83
85
  await assertGroupNameUniqueInDirectory({
@@ -110,7 +112,9 @@ export async function commitCreatedGroupToDirectory(input) {
110
112
  signingFingerprint: input.signingFingerprint,
111
113
  signingKeyPair: input.signingKeyPair,
112
114
  });
115
+ assertProjectionVerificationCurrent(input.stillCurrent);
113
116
  const stored = await input.apiClient.createOrganizationGroup(input.organizationId, { ...input.request, organizationPolicy: organizationRequest });
117
+ assertProjectionVerificationCurrent(input.stillCurrent);
114
118
  if (!stored) {
115
119
  throw new Error("Group could not be created");
116
120
  }
@@ -141,7 +145,9 @@ export async function commitCreatedGroupToDirectory(input) {
141
145
  execSql: input.execSql,
142
146
  organizationId: input.organizationId,
143
147
  updatedAt: new Date().toISOString(),
148
+ stillCurrent: input.stillCurrent,
144
149
  });
150
+ assertProjectionVerificationCurrent(input.stillCurrent);
145
151
  return { group: stored.group, head: expectedHead };
146
152
  }
147
153
  //# sourceMappingURL=organizationGroupDirectory.js.map