@tearleads/client-sdk 0.1.15 → 0.1.16

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 (166) 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/index.d.ts +4 -42
  7. package/client/organizations/index.js +13 -0
  8. package/client/organizations/index.js.map +1 -1
  9. package/client/organizations/organizationGroupNameHydration.js +8 -1
  10. package/client/organizations/organizationGroupNameHydration.js.map +1 -1
  11. package/client/organizations/organizationsTypes.d.ts +47 -0
  12. package/client/organizations/organizationsTypes.js +2 -0
  13. package/client/organizations/organizationsTypes.js.map +1 -0
  14. package/client/organizations/principalMutationRecovery.d.ts +16 -0
  15. package/client/organizations/principalMutationRecovery.js +23 -0
  16. package/client/organizations/principalMutationRecovery.js.map +1 -0
  17. package/client/organizations/principalMutationScope.js +7 -2
  18. package/client/organizations/principalMutationScope.js.map +1 -1
  19. package/client/principalMutationApi.d.ts +24 -0
  20. package/client/principalMutationApi.js +108 -0
  21. package/client/principalMutationApi.js.map +1 -0
  22. package/client/principalMutationDeadline.js +23 -0
  23. package/client/principalMutationDeadline.js.map +1 -0
  24. package/client/workflowRuntime.d.ts +3 -1
  25. package/client/workflowRuntime.js +44 -5
  26. package/client/workflowRuntime.js.map +1 -1
  27. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +27 -0
  28. package/data/persistence/principalCurrentAcknowledgementPersistence.js +109 -0
  29. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -0
  30. package/data/persistence/principalGrantRetirementPersistence.d.ts +3 -3
  31. package/data/persistence/principalGrantRetirementPersistence.js +4 -1
  32. package/data/persistence/principalGrantRetirementPersistence.js.map +1 -1
  33. package/data/persistence/principalKeyEnvelopeCandidates.js +12 -1
  34. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
  35. package/data/persistence/principalMutationJournalPersistence.d.ts +19 -0
  36. package/data/persistence/principalMutationJournalPersistence.js +53 -0
  37. package/data/persistence/principalMutationJournalPersistence.js.map +1 -0
  38. package/data/persistence/verifiedPrincipalPolicyBundle.js +7 -51
  39. package/data/persistence/verifiedPrincipalPolicyBundle.js.map +1 -1
  40. package/data/persistence/verifiedPrincipalPolicyCurrent.js +56 -0
  41. package/data/persistence/verifiedPrincipalPolicyCurrent.js.map +1 -0
  42. package/data/principals/principalMutationJournal.d.ts +26 -0
  43. package/data/principals/principalMutationJournal.js +90 -0
  44. package/data/principals/principalMutationJournal.js.map +1 -0
  45. package/data/principals/principalMutationJournalRecord.d.ts +8 -0
  46. package/data/principals/principalMutationJournalRecord.js +25 -0
  47. package/data/principals/principalMutationJournalRecord.js.map +1 -0
  48. package/data/sqlite/principalHistoryStageSchema.js +3 -0
  49. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  50. package/data/sqlite/principalMutationJournalSchema.d.ts +85 -0
  51. package/data/sqlite/principalMutationJournalSchema.js +13 -0
  52. package/data/sqlite/principalMutationJournalSchema.js.map +1 -0
  53. package/data/sqlite/schema.d.ts +83 -0
  54. package/data/sqlite/schema.js +3 -0
  55. package/data/sqlite/schema.js.map +1 -1
  56. package/index.d.ts +3 -3
  57. package/index.js +1 -1
  58. package/index.js.map +1 -1
  59. package/internal/crypto/index.d.ts +1 -1
  60. package/internal/crypto/index.js +1 -1
  61. package/internal/crypto/index.js.map +1 -1
  62. package/internal/crypto/keying/index.d.ts +2 -0
  63. package/internal/crypto/keying/index.js +2 -0
  64. package/internal/crypto/keying/index.js.map +1 -1
  65. package/internal/crypto/keying/principalPolicyCurrent.d.ts +1 -1
  66. package/internal/crypto/keying/principalPolicyCurrent.js +3 -3
  67. package/internal/crypto/keying/principalPolicyCurrent.js.map +1 -1
  68. package/internal/crypto/keying/principalPolicyCurrentEvidence.js +16 -0
  69. package/internal/crypto/keying/principalPolicyCurrentEvidence.js.map +1 -0
  70. package/internal/crypto/keying/principalPolicyCurrentMutation.d.ts +10 -0
  71. package/internal/crypto/keying/principalPolicyCurrentMutation.js +51 -0
  72. package/internal/crypto/keying/principalPolicyCurrentMutation.js.map +1 -0
  73. package/internal/crypto/keying/principalPolicyCurrentSuccessor.d.ts +10 -0
  74. package/internal/crypto/keying/principalPolicyCurrentSuccessor.js +60 -0
  75. package/internal/crypto/keying/principalPolicyCurrentSuccessor.js.map +1 -0
  76. package/internal/crypto/keying/principalPolicyHistory.js +4 -1
  77. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  78. package/internal/crypto/keying/principalPolicyHistoryReferences.js +1 -1
  79. package/internal/crypto/keying/principalPolicyHistoryReferences.js.map +1 -1
  80. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +5 -2
  81. package/internal/crypto/keying/principalPolicyHistoryTypes.js +6 -3
  82. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  83. package/package.json +1 -1
  84. package/workflows/containers/child/share.js +4 -0
  85. package/workflows/containers/child/share.js.map +1 -1
  86. package/workflows/containers/child/sharePrincipalPolicy.d.ts +1 -0
  87. package/workflows/containers/child/sharePrincipalPolicy.js.map +1 -1
  88. package/workflows/organizations/acknowledgedDirectoryBindings.js +18 -0
  89. package/workflows/organizations/acknowledgedDirectoryBindings.js.map +1 -0
  90. package/workflows/organizations/currentGroupMetadataAuthority.js +32 -0
  91. package/workflows/organizations/currentGroupMetadataAuthority.js.map +1 -0
  92. package/workflows/organizations/currentOrganizationAuthority.js +88 -0
  93. package/workflows/organizations/currentOrganizationAuthority.js.map +1 -0
  94. package/workflows/organizations/currentOrganizationGroupNames.js +68 -0
  95. package/workflows/organizations/currentOrganizationGroupNames.js.map +1 -0
  96. package/workflows/organizations/currentPolicyMutationAcknowledgement.js +65 -0
  97. package/workflows/organizations/currentPolicyMutationAcknowledgement.js.map +1 -0
  98. package/workflows/organizations/deleteOrganizationGroup.js +1 -0
  99. package/workflows/organizations/deleteOrganizationGroup.js.map +1 -1
  100. package/workflows/organizations/groupCreation.js +1 -0
  101. package/workflows/organizations/groupCreation.js.map +1 -1
  102. package/workflows/organizations/groupMetadataAccess.d.ts +2 -2
  103. package/workflows/organizations/groupMetadataAccess.js +1 -1
  104. package/workflows/organizations/groupMetadataAccess.js.map +1 -1
  105. package/workflows/organizations/groupMetadataBinding.js.map +1 -1
  106. package/workflows/organizations/groupMetadataContainerAuthority.js +2 -47
  107. package/workflows/organizations/groupMetadataContainerAuthority.js.map +1 -1
  108. package/workflows/organizations/groupMetadataRootBinding.js +51 -0
  109. package/workflows/organizations/groupMetadataRootBinding.js.map +1 -0
  110. package/workflows/organizations/groupMetadataRuntime.js +20 -9
  111. package/workflows/organizations/groupMetadataRuntime.js.map +1 -1
  112. package/workflows/organizations/groupMutationAuthorization.js.map +1 -1
  113. package/workflows/organizations/groupPolicyMutationAcknowledgement.js +9 -75
  114. package/workflows/organizations/groupPolicyMutationAcknowledgement.js.map +1 -1
  115. package/workflows/organizations/groupPolicyMutationContext.d.ts +5 -13
  116. package/workflows/organizations/groupPolicyMutationContext.js +1 -0
  117. package/workflows/organizations/groupPolicyMutationContext.js.map +1 -1
  118. package/workflows/organizations/groupPolicyMutationEvidence.d.ts +26 -0
  119. package/workflows/organizations/groupPolicyMutationEvidence.js +64 -0
  120. package/workflows/organizations/groupPolicyMutationEvidence.js.map +1 -0
  121. package/workflows/organizations/groupPolicyMutationHead.js.map +1 -1
  122. package/workflows/organizations/groupPolicyRequests.js +69 -63
  123. package/workflows/organizations/groupPolicyRequests.js.map +1 -1
  124. package/workflows/organizations/index.d.ts +6 -0
  125. package/workflows/organizations/index.js +5 -0
  126. package/workflows/organizations/index.js.map +1 -1
  127. package/workflows/organizations/organizationGroupNames.js +7 -0
  128. package/workflows/organizations/organizationGroupNames.js.map +1 -1
  129. package/workflows/organizations/principalCurrentPublicationSeal.js +51 -0
  130. package/workflows/organizations/principalCurrentPublicationSeal.js.map +1 -0
  131. package/workflows/organizations/principalMutationJournalLane.js +26 -0
  132. package/workflows/organizations/principalMutationJournalLane.js.map +1 -0
  133. package/workflows/organizations/principalMutationJournalManagement.d.ts +26 -0
  134. package/workflows/organizations/principalMutationJournalManagement.js +104 -0
  135. package/workflows/organizations/principalMutationJournalManagement.js.map +1 -0
  136. package/workflows/organizations/principalMutationJournalSession.d.ts +26 -0
  137. package/workflows/organizations/principalMutationJournalSession.js +85 -0
  138. package/workflows/organizations/principalMutationJournalSession.js.map +1 -0
  139. package/workflows/organizations/principalMutationReceipt.js +21 -0
  140. package/workflows/organizations/principalMutationReceipt.js.map +1 -0
  141. package/workflows/organizations/principalPolicyReceiptArtifacts.js +74 -0
  142. package/workflows/organizations/principalPolicyReceiptArtifacts.js.map +1 -0
  143. package/workflows/organizations/principalPolicyRequest.d.ts +5 -4
  144. package/workflows/organizations/principalPolicyRequest.js.map +1 -1
  145. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.d.ts +21 -0
  146. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +155 -0
  147. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -0
  148. package/workflows/principals/principalCurrentRecoveryBatch.js +14 -0
  149. package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -0
  150. package/workflows/principals/principalRecoveryDirectory.d.ts +1 -1
  151. package/workflows/principals/principalRecoveryDirectory.js +29 -4
  152. package/workflows/principals/principalRecoveryDirectory.js.map +1 -1
  153. package/workflows/principals/principalRecoveryDiscoveryPage.js +36 -0
  154. package/workflows/principals/principalRecoveryDiscoveryPage.js.map +1 -0
  155. package/workflows/principals/principalRecoveryLocalPreference.js +28 -0
  156. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -0
  157. package/workflows/principals/principalRecoveryMemo.d.ts +16 -0
  158. package/workflows/principals/principalRecoveryMemo.js +88 -16
  159. package/workflows/principals/principalRecoveryMemo.js.map +1 -1
  160. package/workflows/principals/recoverCurrentOrganizationPolicy.js +33 -0
  161. package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -0
  162. package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +2 -1
  163. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +13 -15
  164. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
  165. package/workflows/principals/runtimePolicyRecovery.js +14 -8
  166. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groupMetadataRootBinding.js","sourceRoot":"","sources":["groupMetadataRootBinding.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type ContainerAccessManifestState,\n KeyingVerificationError,\n type PrincipalPolicyAuthorization,\n} from \"@tearleads/crypto\";\nimport {\n type OrganizationAuthorityDescriptor,\n principalHeadMatchesReference,\n requireOrganizationGroupHead,\n} from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { principalPolicyEvidenceEntries } from \"../../data/principals/principalPolicyEvidence\";\nimport { MetadataRootBehindDirectoryError } from \"./groupMetadataErrors\";\n\n/** Root bindings consume verified current grants and explicitly retained predecessor citations. */\nexport function assertMetadataRootBinding(input: {\n readonly authority: {\n readonly descriptor: OrganizationAuthorityDescriptor;\n readonly adminGroupId: string;\n readonly memberGroupId: string;\n readonly adminPolicy: PrincipalPolicyAuthorization;\n };\n readonly members: { readonly policy: PrincipalPolicyAuthorization };\n readonly organizationId: string;\n readonly state: ContainerAccessManifestState;\n}): void {\n const { authority, state } = input;\n const expected = [\n {\n policy: authority.adminPolicy,\n id: authority.adminGroupId,\n level: \"admin\",\n grants: authority.adminPolicy.grants,\n },\n {\n policy: input.members.policy,\n id: authority.memberGroupId,\n level: \"read\",\n grants: input.members.policy.grants,\n },\n ];\n const cited = (groupId: string) =>\n state.referencedPrincipalHeads.find(\n (head) => head.principalType === \"group\" && head.principalId === groupId,\n );\n const unbound = new KeyingVerificationError(\n \"object_mismatch\",\n \"Organization metadata root is not bound to the reserved group grants\",\n );\n if (\n state.organizationId !== input.organizationId ||\n state.parentContainerId !== null ||\n state.directGrants.length !== 2 ||\n state.referencedPrincipalHeads.length !== 2 ||\n expected.some(\n (role) =>\n !principalHeadMatchesReference(\n role.policy.state,\n requireOrganizationGroupHead(authority.descriptor, role.id),\n ) ||\n !role.grants.some(\n (grant) =>\n grant.containerId === state.containerId &&\n grant.accessLevel === role.level,\n ) ||\n !state.directGrants.some(\n (grant) =>\n grant.subjectType === \"group\" &&\n grant.subjectId === role.id &&\n grant.accessLevel === role.level,\n ) ||\n !cited(role.id),\n )\n )\n throw unbound;\n const superseded = expected.flatMap((role) => {\n const head = cited(role.id);\n return head &&\n !principalHeadMatchesReference(\n head,\n requireOrganizationGroupHead(authority.descriptor, role.id),\n )\n ? [{ policy: role.policy, head }]\n : [];\n });\n if (superseded.length === 0) return;\n // A root read before a reserved-group commit cites a verified predecessor\n // of the directory's head; any other head is not an honest race.\n if (\n superseded.every(({ policy, head }) =>\n principalPolicyEvidenceEntries(policy).some(({ state }) =>\n principalHeadMatchesReference(state, head),\n ),\n )\n )\n throw new MetadataRootBehindDirectoryError();\n throw unbound;\n}\n"]}
@@ -1,21 +1,32 @@
1
1
  import { createProjectionUserKeyResolver } from "../../data/keyingProjectionVerification/userKeyResolver.js";
2
+ import { createRuntimePrincipalPolicyCurrentResolver, } from "../principals/runtimePolicyRecovery.js";
2
3
  import { createRuntimePrincipalPolicyWarmer } from "../principals/runtimePolicyWarmer.js";
4
+ import { createCurrentGroupMetadataContainerVerifier } from "./currentGroupMetadataAuthority.js";
3
5
  import { createGroupMetadataAccess, } from "./groupMetadataAccess.js";
4
6
  import { createGroupMetadataContainerVerifier } from "./groupMetadataContainerAuthority.js";
5
- export function createRuntimeGroupMetadataAccess(runtime, organizationId, stillCurrent) {
7
+ export function createRuntimeGroupMetadataAccess(runtime, organizationId, stillCurrent, currentRecovery) {
6
8
  const targetSecretKey = runtime.crypto.encapsulationKeyPair?.secretKey;
7
9
  if (!targetSecretKey)
8
10
  throw new Error("Group metadata identity is locked");
9
11
  const warmer = createRuntimePrincipalPolicyWarmer(runtime);
12
+ const resolveCurrentPolicy = currentRecovery?.resolveCurrentPolicy ??
13
+ createRuntimePrincipalPolicyCurrentResolver(runtime);
14
+ const authorityInput = {
15
+ apiClient: runtime.apiClient,
16
+ execSql: runtime.infra.execSql,
17
+ organizationId,
18
+ reportSecurityIncident: runtime.util.reportSecurityIncident,
19
+ resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,
20
+ stillCurrent: stillCurrent ?? (() => true),
21
+ };
10
22
  return createGroupMetadataAccess({
11
- verifyMetadataContainer: createGroupMetadataContainerVerifier({
12
- apiClient: runtime.apiClient,
13
- execSql: runtime.infra.execSql,
14
- organizationId,
15
- reportSecurityIncident: runtime.util.reportSecurityIncident,
16
- resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,
17
- stillCurrent: stillCurrent ?? (() => true),
18
- }),
23
+ verifyMetadataContainer: resolveCurrentPolicy
24
+ ? createCurrentGroupMetadataContainerVerifier({
25
+ ...authorityInput,
26
+ resolveCurrentPolicy,
27
+ recoveryBatch: currentRecovery?.recoveryBatch,
28
+ })
29
+ : createGroupMetadataContainerVerifier(authorityInput),
19
30
  apiClient: runtime.apiClient,
20
31
  execSql: runtime.infra.execSql,
21
32
  organizationId,
@@ -1 +1 @@
1
- {"version":3,"file":"groupMetadataRuntime.js","sourceRoot":"","sources":["groupMetadataRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,yDAAyD,CAAC;AAI1G,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EACL,yBAAyB,GAE1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oCAAoC,EAAE,MAAM,mCAAmC,CAAC;AAiBzF,MAAM,UAAU,gCAAgC,CAC9C,OAA6B,EAC7B,cAAsB,EACtB,YAA4B;IAE5B,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,SAAS,CAAC;IACvE,IAAI,CAAC,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,kCAAkC,CAAC,OAAO,CAAC,CAAC;IAC3D,OAAO,yBAAyB,CAAC;QAC/B,uBAAuB,EAAE,oCAAoC,CAAC;YAC5D,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;YAC9B,cAAc;YACd,sBAAsB,EAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB;YAC3D,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;YAC9D,YAAY,EAAE,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SAC3C,CAAC;QACF,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9B,cAAc;QACd,wBAAwB,EAAE,+BAA+B,CAAC,OAAO,CAAC;QAClE,eAAe;QACf,YAAY;QACZ,+BAA+B,EAAE,MAAM;KACxC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { EncapsulationKeyPair } from \"@tearleads/crypto\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../data/trustedUserIdentity\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../principals/runtimePolicyWarmer\";\nimport {\n createGroupMetadataAccess,\n type GroupMetadataAccessInput,\n} from \"./groupMetadataAccess\";\nimport { createGroupMetadataContainerVerifier } from \"./groupMetadataContainerAuthority\";\nimport type { PrincipalPolicyReadApi } from \"./groupPolicyMutationContext\";\n\ninterface GroupMetadataRuntime {\n readonly apiClient: GroupMetadataAccessInput[\"apiClient\"] &\n PrincipalPolicyReadApi;\n readonly crypto: {\n readonly encapsulationKeyPair: EncapsulationKeyPair | null;\n };\n readonly infra: { readonly execSql: ExecSql };\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly util: {\n readonly log: (message: string) => void;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n };\n}\n\nexport function createRuntimeGroupMetadataAccess(\n runtime: GroupMetadataRuntime,\n organizationId: string,\n stillCurrent?: () => boolean,\n) {\n const targetSecretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!targetSecretKey) throw new Error(\"Group metadata identity is locked\");\n const warmer = createRuntimePrincipalPolicyWarmer(runtime);\n return createGroupMetadataAccess({\n verifyMetadataContainer: createGroupMetadataContainerVerifier({\n apiClient: runtime.apiClient,\n execSql: runtime.infra.execSql,\n organizationId,\n reportSecurityIncident: runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n stillCurrent: stillCurrent ?? (() => true),\n }),\n apiClient: runtime.apiClient,\n execSql: runtime.infra.execSql,\n organizationId,\n resolveProjectionUserKey: createProjectionUserKeyResolver(runtime),\n targetSecretKey,\n stillCurrent,\n warmReferencedPrincipalPolicies: warmer,\n });\n}\n"]}
1
+ {"version":3,"file":"groupMetadataRuntime.js","sourceRoot":"","sources":["groupMetadataRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,yDAAyD,CAAC;AAI1G,OAAO,EACL,2CAA2C,GAE5C,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,kCAAkC,EAAE,MAAM,mCAAmC,CAAC;AACvF,OAAO,EAAE,2CAA2C,EAAE,MAAM,iCAAiC,CAAC;AAC9F,OAAO,EACL,yBAAyB,GAE1B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,oCAAoC,EAAE,MAAM,mCAAmC,CAAC;AAmBzF,MAAM,UAAU,gCAAgC,CAC9C,OAA6B,EAC7B,cAAsB,EACtB,YAA4B,EAC5B,eAKC;IAED,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,SAAS,CAAC;IACvE,IAAI,CAAC,eAAe;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,kCAAkC,CAAC,OAAO,CAAC,CAAC;IAC3D,MAAM,oBAAoB,GACxB,eAAe,EAAE,oBAAoB;QACrC,2CAA2C,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG;QACrB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9B,cAAc;QACd,sBAAsB,EAAE,OAAO,CAAC,IAAI,CAAC,sBAAsB;QAC3D,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;QAC9D,YAAY,EAAE,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KAC3C,CAAC;IACF,OAAO,yBAAyB,CAAC;QAC/B,uBAAuB,EAAE,oBAAoB;YAC3C,CAAC,CAAC,2CAA2C,CAAC;gBAC1C,GAAG,cAAc;gBACjB,oBAAoB;gBACpB,aAAa,EAAE,eAAe,EAAE,aAAa;aAC9C,CAAC;YACJ,CAAC,CAAC,oCAAoC,CAAC,cAAc,CAAC;QACxD,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9B,cAAc;QACd,wBAAwB,EAAE,+BAA+B,CAAC,OAAO,CAAC;QAClE,eAAe;QACf,YAAY;QACZ,+BAA+B,EAAE,MAAM;KACxC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { EncapsulationKeyPair } from \"@tearleads/crypto\";\nimport { createProjectionUserKeyResolver } from \"../../data/keyingProjectionVerification/userKeyResolver\";\nimport type { SecurityIncidentReporter } from \"../../data/securityIncidents\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../data/trustedUserIdentity\";\nimport {\n createRuntimePrincipalPolicyCurrentResolver,\n type PrincipalPolicyRecoveryRuntime,\n} from \"../principals/runtimePolicyRecovery\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../principals/runtimePolicyWarmer\";\nimport { createCurrentGroupMetadataContainerVerifier } from \"./currentGroupMetadataAuthority\";\nimport {\n createGroupMetadataAccess,\n type GroupMetadataAccessInput,\n} from \"./groupMetadataAccess\";\nimport { createGroupMetadataContainerVerifier } from \"./groupMetadataContainerAuthority\";\nimport type { PrincipalPolicyReadApi } from \"./groupPolicyMutationContext\";\n\ninterface GroupMetadataRuntime {\n readonly state?: PrincipalPolicyRecoveryRuntime[\"state\"];\n readonly apiClient: GroupMetadataAccessInput[\"apiClient\"] &\n PrincipalPolicyReadApi &\n PrincipalPolicyRecoveryRuntime[\"apiClient\"];\n readonly crypto: {\n readonly encapsulationKeyPair: EncapsulationKeyPair | null;\n };\n readonly infra: { readonly execSql: ExecSql };\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly util: {\n readonly log: (message: string) => void;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n };\n}\n\nexport function createRuntimeGroupMetadataAccess(\n runtime: GroupMetadataRuntime,\n organizationId: string,\n stillCurrent?: () => boolean,\n currentRecovery?: {\n readonly resolveCurrentPolicy: ReturnType<\n typeof createRuntimePrincipalPolicyCurrentResolver\n >;\n readonly recoveryBatch: object;\n },\n) {\n const targetSecretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!targetSecretKey) throw new Error(\"Group metadata identity is locked\");\n const warmer = createRuntimePrincipalPolicyWarmer(runtime);\n const resolveCurrentPolicy =\n currentRecovery?.resolveCurrentPolicy ??\n createRuntimePrincipalPolicyCurrentResolver(runtime);\n const authorityInput = {\n apiClient: runtime.apiClient,\n execSql: runtime.infra.execSql,\n organizationId,\n reportSecurityIncident: runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n stillCurrent: stillCurrent ?? (() => true),\n };\n return createGroupMetadataAccess({\n verifyMetadataContainer: resolveCurrentPolicy\n ? createCurrentGroupMetadataContainerVerifier({\n ...authorityInput,\n resolveCurrentPolicy,\n recoveryBatch: currentRecovery?.recoveryBatch,\n })\n : createGroupMetadataContainerVerifier(authorityInput),\n apiClient: runtime.apiClient,\n execSql: runtime.infra.execSql,\n organizationId,\n resolveProjectionUserKey: createProjectionUserKeyResolver(runtime),\n targetSecretKey,\n stillCurrent,\n warmReferencedPrincipalPolicies: warmer,\n });\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"groupMutationAuthorization.js","sourceRoot":"","sources":["groupMutationAuthorization.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAChC,MAAqC,EACrC,MAAc;IAEd,OAAO,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAClC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,CAChE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,MAAqC,EACrC,wBAA2C,EAC3C,YAAoB;IAEpB,IACE,CAAC,wBAAwB,CAAC,QAAQ,CAAC,YAAY,CAAC;QAChD,CAAC,kBAAkB,CAAC,MAAM,EAAE,YAAY,CAAC,EACzC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC","sourcesContent":["import type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\n\nexport function isDirectGroupAdmin(\n policy: PrincipalPolicyBundleResponse,\n userId: string,\n): boolean {\n return policy.currentProjection.some(\n (member) => member.userId === userId && member.role === \"admin\",\n );\n}\n\nexport function requireSignerCanManageGroup(\n policy: PrincipalPolicyBundleResponse,\n organizationAdminUserIds: readonly string[],\n signerUserId: string,\n): void {\n if (\n !organizationAdminUserIds.includes(signerUserId) &&\n !isDirectGroupAdmin(policy, signerUserId)\n ) {\n throw new Error(\"Group admin membership is required\");\n }\n}\n"]}
1
+ {"version":3,"file":"groupMutationAuthorization.js","sourceRoot":"","sources":["groupMutationAuthorization.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,kBAAkB,CAChC,MAAgE,EAChE,MAAc;IAEd,OAAO,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAClC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,CAChE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,2BAA2B,CACzC,MAAgE,EAChE,wBAA2C,EAC3C,YAAoB;IAEpB,IACE,CAAC,wBAAwB,CAAC,QAAQ,CAAC,YAAY,CAAC;QAChD,CAAC,kBAAkB,CAAC,MAAM,EAAE,YAAY,CAAC,EACzC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC","sourcesContent":["import type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\n\nexport function isDirectGroupAdmin(\n policy: Pick<PrincipalPolicyBundleResponse, \"currentProjection\">,\n userId: string,\n): boolean {\n return policy.currentProjection.some(\n (member) => member.userId === userId && member.role === \"admin\",\n );\n}\n\nexport function requireSignerCanManageGroup(\n policy: Pick<PrincipalPolicyBundleResponse, \"currentProjection\">,\n organizationAdminUserIds: readonly string[],\n signerUserId: string,\n): void {\n if (\n !organizationAdminUserIds.includes(signerUserId) &&\n !isDirectGroupAdmin(policy, signerUserId)\n ) {\n throw new Error(\"Group admin membership is required\");\n }\n}\n"]}
@@ -1,47 +1,8 @@
1
- import { computePrincipalContainerGrantRoot, computePrincipalMemberEnvelopesRoot, computePrincipalMembershipRoot, computePrincipalProjectionRoot, computePrincipalStatePayloadCiphertextHash, makeVerifiedPrincipalPolicy, normalizePrincipalContainerGrants, normalizePrincipalProjectionMembers, } from "../../internal/crypto/index.js";
1
+ import { computePrincipalContainerGrantRoot, computePrincipalMemberEnvelopesRoot, computePrincipalMembershipRoot, computePrincipalProjectionRoot, computePrincipalStatePayloadCiphertextHash, makeVerifiedPrincipalPolicy, normalizePrincipalProjectionMembers, } from "../../internal/crypto/index.js";
2
2
  import { canonicalKeyingJsonString } from "../../data/keyingCanonicalJson.js";
3
- function sortedCanonicalValues(values, label) {
4
- return [...values].sort((left, right) => canonicalKeyingJsonString(left, label).localeCompare(canonicalKeyingJsonString(right, label)));
5
- }
6
- export function assertGroupPolicyEnvelopesMatchAcknowledgement(expected, observed) {
7
- const normalized = (value) => ({
8
- ...value,
9
- envelopes: sortedCanonicalValues(value.envelopes, "principal member envelope"),
10
- });
11
- if (canonicalKeyingJsonString(normalized(expected), "acknowledged group member envelopes") !==
12
- canonicalKeyingJsonString(normalized(observed), "observed group member envelopes")) {
13
- throw new Error("Group member envelopes changed after acknowledgement");
14
- }
15
- }
16
- function assertContainerMutationAcknowledgements(input) {
17
- if (!input.responses || input.responses.length !== input.requests.length) {
18
- throw new Error("Group policy container acknowledgement batch is incomplete");
19
- }
20
- for (const [index, request] of input.requests.entries()) {
21
- const response = input.responses[index];
22
- if (!response) {
23
- throw new Error("Group policy container acknowledgement batch is incomplete");
24
- }
25
- const expected = {
26
- body: request.body,
27
- event: request.event,
28
- keyEpoch: request.keyEpoch,
29
- manifest: request.manifest,
30
- wraps: sortedCanonicalValues(request.wraps, "authored container wrap"),
31
- };
32
- const observed = {
33
- body: response.accessManifest.event.body,
34
- event: response.accessManifest.event.event,
35
- keyEpoch: response.containerKek.keyEpoch,
36
- manifest: response.accessManifest.manifest,
37
- wraps: sortedCanonicalValues(response.containerKek.wraps, "stored container wrap"),
38
- };
39
- if (canonicalKeyingJsonString(observed, "stored group policy container mutation") !==
40
- canonicalKeyingJsonString(expected, "authored group policy container mutation")) {
41
- throw new Error("Group policy container acknowledgement mismatch");
42
- }
43
- }
44
- }
3
+ import { verifyCurrentPolicyMutation, } from "./currentPolicyMutationAcknowledgement.js";
4
+ import { assertPrincipalPolicyReceiptArtifacts } from "./principalPolicyReceiptArtifacts.js";
5
+ export { assertGroupPolicyEnvelopesMatchAcknowledgement } from "./principalPolicyReceiptArtifacts.js";
45
6
  function historyWithCurrent(bundle) {
46
7
  return [
47
8
  ...bundle.previousStates,
@@ -64,32 +25,7 @@ function isAuthoredSuccessorConsistent(state, expectedHead, previous) {
64
25
  state.prevStateHash === previous.stateHash);
65
26
  }
66
27
  export function buildAcknowledgedGroupPolicyBundle(input) {
67
- assertContainerMutationAcknowledgements({
68
- requests: input.request.containerMutations ?? [],
69
- responses: input.response.containerMutations,
70
- });
71
- const { createdAt: _payloadCreatedAt, ...observedPayload } = input.response.currentPayload;
72
- const expectedPayload = {
73
- principalType: input.request.state.principalType,
74
- principalId: input.request.state.principalId,
75
- stateHash: input.expectedHead.stateHash,
76
- ...input.request.encryptedPayload,
77
- };
78
- if (canonicalKeyingJsonString(observedPayload, "stored group policy payload") !==
79
- canonicalKeyingJsonString(expectedPayload, "authored group policy payload") ||
80
- canonicalKeyingJsonString(normalizePrincipalProjectionMembers(input.response.currentProjection), "stored group policy projection") !==
81
- canonicalKeyingJsonString(normalizePrincipalProjectionMembers(input.request.projection), "authored group policy projection") ||
82
- canonicalKeyingJsonString(normalizePrincipalContainerGrants(input.response.currentGrants), "stored group policy grants") !==
83
- canonicalKeyingJsonString(normalizePrincipalContainerGrants(input.request.grants), "authored group policy grants")) {
84
- throw new Error("Group policy bundle acknowledgement mismatch");
85
- }
86
- assertGroupPolicyEnvelopesMatchAcknowledgement({
87
- principalType: input.request.state.principalType,
88
- principalId: input.request.state.principalId,
89
- stateHash: input.expectedHead.stateHash,
90
- epoch: input.request.state.keyEpoch,
91
- envelopes: input.request.memberEnvelopes,
92
- }, input.response.currentMemberEnvelopes);
28
+ assertPrincipalPolicyReceiptArtifacts(input);
93
29
  return {
94
30
  ...input.response,
95
31
  previousStates: historyWithCurrent(input.currentPolicy),
@@ -146,6 +82,8 @@ function verifiedPolicy(input) {
146
82
  });
147
83
  }
148
84
  export async function acknowledgeGroupPolicyState(input) {
85
+ if (input.verifiedCurrentPolicy !== undefined)
86
+ return verifyCurrentPolicyMutation(input, input.response);
149
87
  await assertPolicyRequestCommitments(input.request);
150
88
  const { createdAt: _createdAt, stateHash, ...responseState } = input.response;
151
89
  const previous = input.currentPolicy.currentState;
@@ -162,13 +100,9 @@ export async function acknowledgeGroupPolicyState(input) {
162
100
  state: input.response,
163
101
  });
164
102
  }
165
- /**
166
- * Materialize the locally signed successor before submission so dependent
167
- * container mutations can wrap to the exact head that will commit with it.
168
- * The server still performs the authoritative signature, transition, and
169
- * authorization checks inside the combined transaction.
170
- */
171
103
  export async function prepareAuthoredGroupPolicy(input) {
104
+ if (input.verifiedCurrentPolicy !== undefined)
105
+ return verifyCurrentPolicyMutation(input);
172
106
  await assertPolicyRequestCommitments(input.request);
173
107
  const previous = input.currentPolicy.currentState;
174
108
  const state = input.request.state;
@@ -1 +1 @@
1
- {"version":3,"file":"groupPolicyMutationAcknowledgement.js","sourceRoot":"","sources":["groupPolicyMutationAcknowledgement.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computePrincipalContainerGrantRoot,\n computePrincipalMemberEnvelopesRoot,\n computePrincipalMembershipRoot,\n computePrincipalProjectionRoot,\n computePrincipalStatePayloadCiphertextHash,\n makeVerifiedPrincipalPolicy,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n type ReferencedPrincipalHead,\n type VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type {\n CreateOrganizationGroupRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n ContainerMutationResponse,\n CurrentPrincipalMemberEnvelopesResponse,\n OrganizationGroupSummaryResponse,\n PrincipalPolicyBundleResponse,\n PrincipalPolicyMutationResponse,\n PrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../../data/keyingCanonicalJson\";\n\nfunction sortedCanonicalValues<T>(values: readonly T[], label: string): T[] {\n return [...values].sort((left, right) =>\n canonicalKeyingJsonString(left, label).localeCompare(\n canonicalKeyingJsonString(right, label),\n ),\n );\n}\n\nexport function assertGroupPolicyEnvelopesMatchAcknowledgement(\n expected: CurrentPrincipalMemberEnvelopesResponse,\n observed: CurrentPrincipalMemberEnvelopesResponse,\n): void {\n const normalized = (value: CurrentPrincipalMemberEnvelopesResponse) => ({\n ...value,\n envelopes: sortedCanonicalValues(\n value.envelopes,\n \"principal member envelope\",\n ),\n });\n if (\n canonicalKeyingJsonString(\n normalized(expected),\n \"acknowledged group member envelopes\",\n ) !==\n canonicalKeyingJsonString(\n normalized(observed),\n \"observed group member envelopes\",\n )\n ) {\n throw new Error(\"Group member envelopes changed after acknowledgement\");\n }\n}\n\nfunction assertContainerMutationAcknowledgements(input: {\n readonly requests: readonly NonNullable<\n PutPrincipalPolicyRequest[\"containerMutations\"]\n >[number][];\n readonly responses: readonly ContainerMutationResponse[] | undefined;\n}): void {\n if (!input.responses || input.responses.length !== input.requests.length) {\n throw new Error(\n \"Group policy container acknowledgement batch is incomplete\",\n );\n }\n for (const [index, request] of input.requests.entries()) {\n const response = input.responses[index];\n if (!response) {\n throw new Error(\n \"Group policy container acknowledgement batch is incomplete\",\n );\n }\n const expected = {\n body: request.body,\n event: request.event,\n keyEpoch: request.keyEpoch,\n manifest: request.manifest,\n wraps: sortedCanonicalValues(request.wraps, \"authored container wrap\"),\n };\n const observed = {\n body: response.accessManifest.event.body,\n event: response.accessManifest.event.event,\n keyEpoch: response.containerKek.keyEpoch,\n manifest: response.accessManifest.manifest,\n wraps: sortedCanonicalValues(\n response.containerKek.wraps,\n \"stored container wrap\",\n ),\n };\n if (\n canonicalKeyingJsonString(\n observed,\n \"stored group policy container mutation\",\n ) !==\n canonicalKeyingJsonString(\n expected,\n \"authored group policy container mutation\",\n )\n ) {\n throw new Error(\"Group policy container acknowledgement mismatch\");\n }\n }\n}\n\nfunction historyWithCurrent(\n bundle: PrincipalPolicyBundleResponse,\n): PrincipalPolicyBundleResponse[\"previousStates\"] {\n return [\n ...bundle.previousStates,\n {\n state: bundle.currentState,\n projection: bundle.currentProjection,\n grants: bundle.currentGrants,\n },\n ];\n}\n\nfunction isAuthoredSuccessorConsistent(\n state: Pick<\n PrincipalStateResponse,\n | \"keyEpoch\"\n | \"keyFingerprint\"\n | \"prevStateHash\"\n | \"principalId\"\n | \"principalType\"\n | \"version\"\n >,\n expectedHead: ReferencedPrincipalHead,\n previous: PrincipalStateResponse,\n): boolean {\n return (\n state.principalType === expectedHead.principalType &&\n state.principalId === expectedHead.principalId &&\n state.version === expectedHead.version &&\n state.keyEpoch === expectedHead.keyEpoch &&\n state.keyFingerprint === expectedHead.keyFingerprint &&\n state.principalType === previous.principalType &&\n state.principalId === previous.principalId &&\n state.version === previous.version + 1 &&\n state.prevStateHash === previous.stateHash\n );\n}\n\nexport function buildAcknowledgedGroupPolicyBundle(input: {\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly request: PutPrincipalPolicyRequest;\n readonly response: PrincipalPolicyMutationResponse;\n}): PrincipalPolicyBundleResponse & PrincipalPolicyMutationResponse {\n assertContainerMutationAcknowledgements({\n requests: input.request.containerMutations ?? [],\n responses: input.response.containerMutations,\n });\n const { createdAt: _payloadCreatedAt, ...observedPayload } =\n input.response.currentPayload;\n const expectedPayload = {\n principalType: input.request.state.principalType,\n principalId: input.request.state.principalId,\n stateHash: input.expectedHead.stateHash,\n ...input.request.encryptedPayload,\n };\n\n if (\n canonicalKeyingJsonString(\n observedPayload,\n \"stored group policy payload\",\n ) !==\n canonicalKeyingJsonString(\n expectedPayload,\n \"authored group policy payload\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(input.response.currentProjection),\n \"stored group policy projection\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(input.request.projection),\n \"authored group policy projection\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(input.response.currentGrants),\n \"stored group policy grants\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(input.request.grants),\n \"authored group policy grants\",\n )\n ) {\n throw new Error(\"Group policy bundle acknowledgement mismatch\");\n }\n\n assertGroupPolicyEnvelopesMatchAcknowledgement(\n {\n principalType: input.request.state.principalType,\n principalId: input.request.state.principalId,\n stateHash: input.expectedHead.stateHash,\n epoch: input.request.state.keyEpoch,\n envelopes: input.request.memberEnvelopes,\n },\n input.response.currentMemberEnvelopes,\n );\n return {\n ...input.response,\n previousStates: historyWithCurrent(input.currentPolicy),\n };\n}\n\nasync function assertPolicyRequestCommitments(\n request: PutPrincipalPolicyRequest,\n): Promise<void> {\n const projection = normalizePrincipalProjectionMembers(request.projection);\n const members = projection.map((member) => ({ userId: member.userId }));\n const [\n membershipRoot,\n memberEnvelopesRoot,\n projectionRoot,\n payloadCiphertextHash,\n grantRoot,\n ] = await Promise.all([\n computePrincipalMembershipRoot(members),\n computePrincipalMemberEnvelopesRoot(request.memberEnvelopes),\n computePrincipalProjectionRoot(projection),\n computePrincipalStatePayloadCiphertextHash(\n request.encryptedPayload.ciphertext,\n ),\n computePrincipalContainerGrantRoot(request.grants),\n ]);\n if (\n request.state.membershipRoot !== membershipRoot ||\n request.state.memberEnvelopesRoot !== memberEnvelopesRoot ||\n request.state.projectionRoot !== projectionRoot ||\n request.state.memberCount !== projection.length ||\n request.state.grantRoot !== grantRoot ||\n request.state.grantCount !== request.grants.length ||\n request.encryptedPayload.ciphertextHash !== payloadCiphertextHash ||\n request.state.payloadCiphertextHash !== payloadCiphertextHash\n ) {\n throw new Error(\"Authored group policy commitments are invalid\");\n }\n}\n\nfunction verifiedPolicy(input: {\n currentPolicy?: PrincipalPolicyBundleResponse | undefined;\n projection: PutPrincipalPolicyRequest[\"projection\"];\n grants: PutPrincipalPolicyRequest[\"grants\"];\n state: PrincipalStateResponse;\n}): VerifiedPrincipalPolicy {\n const previousStates = input.currentPolicy\n ? historyWithCurrent(input.currentPolicy)\n : [];\n return makeVerifiedPrincipalPolicy({\n checkpoint: {\n principalId: input.state.principalId,\n principalType: input.state.principalType,\n stateHash: input.state.stateHash,\n version: input.state.version,\n },\n history: [\n ...previousStates,\n {\n state: input.state,\n projection: input.projection,\n grants: input.grants,\n },\n ],\n keyEpoch: input.state.keyEpoch,\n principalId: input.state.principalId,\n principalType: input.state.principalType,\n projection: input.projection,\n grants: input.grants,\n state: input.state,\n stateHash: input.state.stateHash,\n version: input.state.version,\n });\n}\n\nexport async function acknowledgeGroupPolicyState(input: {\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly request: PutPrincipalPolicyRequest;\n readonly response: PrincipalStateResponse;\n}): Promise<VerifiedPrincipalPolicy> {\n await assertPolicyRequestCommitments(input.request);\n const { createdAt: _createdAt, stateHash, ...responseState } = input.response;\n const previous = input.currentPolicy.currentState;\n if (\n stateHash !== input.expectedHead.stateHash ||\n !isAuthoredSuccessorConsistent(\n input.response,\n input.expectedHead,\n previous,\n ) ||\n canonicalKeyingJsonString(responseState, \"stored group policy state\") !==\n canonicalKeyingJsonString(\n input.request.state,\n \"authored group policy state\",\n )\n ) {\n throw new Error(\"Group policy state acknowledgement mismatch\");\n }\n return verifiedPolicy({\n currentPolicy: input.currentPolicy,\n projection: input.request.projection,\n grants: input.request.grants,\n state: input.response,\n });\n}\n\n/**\n * Materialize the locally signed successor before submission so dependent\n * container mutations can wrap to the exact head that will commit with it.\n * The server still performs the authoritative signature, transition, and\n * authorization checks inside the combined transaction.\n */\nexport async function prepareAuthoredGroupPolicy(input: {\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly request: PutPrincipalPolicyRequest;\n}): Promise<VerifiedPrincipalPolicy> {\n await assertPolicyRequestCommitments(input.request);\n const previous = input.currentPolicy.currentState;\n const state = input.request.state;\n if (!isAuthoredSuccessorConsistent(state, input.expectedHead, previous)) {\n throw new Error(\"Authored group policy successor is inconsistent\");\n }\n return verifiedPolicy({\n currentPolicy: input.currentPolicy,\n projection: input.request.projection,\n grants: input.request.grants,\n state: {\n ...state,\n stateHash: input.expectedHead.stateHash,\n createdAt: state.signedAt,\n },\n });\n}\n\nexport async function acknowledgeInitialGroupPolicy(input: {\n readonly organizationId: string;\n readonly request: CreateOrganizationGroupRequest;\n readonly response: OrganizationGroupSummaryResponse;\n readonly stateHash: string;\n}): Promise<{\n readonly bundle: PrincipalPolicyBundleResponse;\n readonly policy: VerifiedPrincipalPolicy;\n}> {\n await assertPolicyRequestCommitments(input.request.initialGroupPolicy);\n const state = input.request.initialGroupPolicy.state;\n if (\n input.response.groupId !== input.request.groupId ||\n input.response.organizationId !== input.organizationId ||\n input.response.isBuiltin ||\n input.response.currentState?.stateHash !== input.stateHash ||\n input.response.currentState.version !== state.version ||\n input.response.currentState.keyEpoch !== state.keyEpoch ||\n input.response.currentState.memberCount !== state.memberCount ||\n state.principalType !== \"group\" ||\n state.principalId !== input.request.groupId ||\n state.version !== 1 ||\n state.prevStateHash !== null\n ) {\n throw new Error(\"Created group policy acknowledgement mismatch\");\n }\n const storedState = {\n ...state,\n createdAt: input.response.createdAt,\n stateHash: input.stateHash,\n };\n const bundle: PrincipalPolicyBundleResponse = {\n currentMemberEnvelopes: {\n envelopes: input.request.initialGroupPolicy.memberEnvelopes,\n epoch: state.keyEpoch,\n principalId: state.principalId,\n principalType: state.principalType,\n stateHash: input.stateHash,\n },\n currentPayload: {\n principalId: state.principalId,\n principalType: state.principalType,\n stateHash: input.stateHash,\n ...input.request.initialGroupPolicy.encryptedPayload,\n createdAt: input.response.createdAt,\n },\n currentProjection: input.request.initialGroupPolicy.projection,\n currentGrants: input.request.initialGroupPolicy.grants,\n currentState: storedState,\n previousStates: [],\n };\n return {\n bundle,\n policy: verifiedPolicy({\n projection: input.request.initialGroupPolicy.projection,\n grants: input.request.initialGroupPolicy.grants,\n state: storedState,\n }),\n };\n}\n"]}
1
+ {"version":3,"file":"groupPolicyMutationAcknowledgement.js","sourceRoot":"","sources":["groupPolicyMutationAcknowledgement.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computePrincipalContainerGrantRoot,\n computePrincipalMemberEnvelopesRoot,\n computePrincipalMembershipRoot,\n computePrincipalProjectionRoot,\n computePrincipalStatePayloadCiphertextHash,\n makeVerifiedPrincipalPolicy,\n normalizePrincipalProjectionMembers,\n type ReferencedPrincipalHead,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type {\n CreateOrganizationGroupRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n OrganizationGroupSummaryResponse,\n PrincipalPolicyBundleResponse,\n PrincipalPolicyMutationResponse,\n PrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../../data/keyingCanonicalJson\";\nimport {\n type CurrentPolicyMutationInput,\n verifyCurrentPolicyMutation,\n} from \"./currentPolicyMutationAcknowledgement\";\nimport { assertPrincipalPolicyReceiptArtifacts } from \"./principalPolicyReceiptArtifacts\";\n\nexport { assertGroupPolicyEnvelopesMatchAcknowledgement } from \"./principalPolicyReceiptArtifacts\";\n\nfunction historyWithCurrent(\n bundle: PrincipalPolicyBundleResponse,\n): PrincipalPolicyBundleResponse[\"previousStates\"] {\n return [\n ...bundle.previousStates,\n {\n state: bundle.currentState,\n projection: bundle.currentProjection,\n grants: bundle.currentGrants,\n },\n ];\n}\n\nfunction isAuthoredSuccessorConsistent(\n state: Pick<\n PrincipalStateResponse,\n | \"keyEpoch\"\n | \"keyFingerprint\"\n | \"prevStateHash\"\n | \"principalId\"\n | \"principalType\"\n | \"version\"\n >,\n expectedHead: ReferencedPrincipalHead,\n previous: PrincipalStateResponse,\n): boolean {\n return (\n state.principalType === expectedHead.principalType &&\n state.principalId === expectedHead.principalId &&\n state.version === expectedHead.version &&\n state.keyEpoch === expectedHead.keyEpoch &&\n state.keyFingerprint === expectedHead.keyFingerprint &&\n state.principalType === previous.principalType &&\n state.principalId === previous.principalId &&\n state.version === previous.version + 1 &&\n state.prevStateHash === previous.stateHash\n );\n}\n\nexport function buildAcknowledgedGroupPolicyBundle(input: {\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly request: PutPrincipalPolicyRequest;\n readonly response: PrincipalPolicyMutationResponse;\n}): PrincipalPolicyBundleResponse & PrincipalPolicyMutationResponse {\n assertPrincipalPolicyReceiptArtifacts(input);\n return {\n ...input.response,\n previousStates: historyWithCurrent(input.currentPolicy),\n };\n}\n\nasync function assertPolicyRequestCommitments(\n request: PutPrincipalPolicyRequest,\n): Promise<void> {\n const projection = normalizePrincipalProjectionMembers(request.projection);\n const members = projection.map((member) => ({ userId: member.userId }));\n const [\n membershipRoot,\n memberEnvelopesRoot,\n projectionRoot,\n payloadCiphertextHash,\n grantRoot,\n ] = await Promise.all([\n computePrincipalMembershipRoot(members),\n computePrincipalMemberEnvelopesRoot(request.memberEnvelopes),\n computePrincipalProjectionRoot(projection),\n computePrincipalStatePayloadCiphertextHash(\n request.encryptedPayload.ciphertext,\n ),\n computePrincipalContainerGrantRoot(request.grants),\n ]);\n if (\n request.state.membershipRoot !== membershipRoot ||\n request.state.memberEnvelopesRoot !== memberEnvelopesRoot ||\n request.state.projectionRoot !== projectionRoot ||\n request.state.memberCount !== projection.length ||\n request.state.grantRoot !== grantRoot ||\n request.state.grantCount !== request.grants.length ||\n request.encryptedPayload.ciphertextHash !== payloadCiphertextHash ||\n request.state.payloadCiphertextHash !== payloadCiphertextHash\n ) {\n throw new Error(\"Authored group policy commitments are invalid\");\n }\n}\n\nfunction verifiedPolicy(input: {\n currentPolicy?: PrincipalPolicyBundleResponse | undefined;\n projection: PutPrincipalPolicyRequest[\"projection\"];\n grants: PutPrincipalPolicyRequest[\"grants\"];\n state: PrincipalStateResponse;\n}): VerifiedPrincipalPolicy {\n const previousStates = input.currentPolicy\n ? historyWithCurrent(input.currentPolicy)\n : [];\n return makeVerifiedPrincipalPolicy({\n checkpoint: {\n principalId: input.state.principalId,\n principalType: input.state.principalType,\n stateHash: input.state.stateHash,\n version: input.state.version,\n },\n history: [\n ...previousStates,\n {\n state: input.state,\n projection: input.projection,\n grants: input.grants,\n },\n ],\n keyEpoch: input.state.keyEpoch,\n principalId: input.state.principalId,\n principalType: input.state.principalType,\n projection: input.projection,\n grants: input.grants,\n state: input.state,\n stateHash: input.state.stateHash,\n version: input.state.version,\n });\n}\n\ninterface FullPolicyMutationInput {\n readonly verifiedCurrentPolicy?: never;\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly request: PutPrincipalPolicyRequest;\n}\n\nexport function acknowledgeGroupPolicyState(\n input: CurrentPolicyMutationInput & {\n readonly response: PrincipalStateResponse;\n },\n): Promise<VerifiedPrincipalPolicyCurrent>;\nexport function acknowledgeGroupPolicyState(\n input: FullPolicyMutationInput & {\n readonly response: PrincipalStateResponse;\n },\n): Promise<VerifiedPrincipalPolicy>;\nexport async function acknowledgeGroupPolicyState(\n input: (FullPolicyMutationInput | CurrentPolicyMutationInput) & {\n readonly response: PrincipalStateResponse;\n },\n): Promise<VerifiedPrincipalPolicy | VerifiedPrincipalPolicyCurrent> {\n if (input.verifiedCurrentPolicy !== undefined)\n return verifyCurrentPolicyMutation(input, input.response);\n await assertPolicyRequestCommitments(input.request);\n const { createdAt: _createdAt, stateHash, ...responseState } = input.response;\n const previous = input.currentPolicy.currentState;\n if (\n stateHash !== input.expectedHead.stateHash ||\n !isAuthoredSuccessorConsistent(\n input.response,\n input.expectedHead,\n previous,\n ) ||\n canonicalKeyingJsonString(responseState, \"stored group policy state\") !==\n canonicalKeyingJsonString(\n input.request.state,\n \"authored group policy state\",\n )\n ) {\n throw new Error(\"Group policy state acknowledgement mismatch\");\n }\n return verifiedPolicy({\n currentPolicy: input.currentPolicy,\n projection: input.request.projection,\n grants: input.request.grants,\n state: input.response,\n });\n}\n\n/**\n * Materialize the locally signed successor before submission so dependent\n * container mutations can wrap to the exact head that will commit with it.\n * The server still performs the authoritative signature, transition, and\n * authorization checks inside the combined transaction.\n */\nexport function prepareAuthoredGroupPolicy(\n input: CurrentPolicyMutationInput,\n): Promise<VerifiedPrincipalPolicyCurrent>;\nexport function prepareAuthoredGroupPolicy(\n input: FullPolicyMutationInput,\n): Promise<VerifiedPrincipalPolicy>;\nexport async function prepareAuthoredGroupPolicy(\n input: FullPolicyMutationInput | CurrentPolicyMutationInput,\n): Promise<VerifiedPrincipalPolicy | VerifiedPrincipalPolicyCurrent> {\n if (input.verifiedCurrentPolicy !== undefined)\n return verifyCurrentPolicyMutation(input);\n await assertPolicyRequestCommitments(input.request);\n const previous = input.currentPolicy.currentState;\n const state = input.request.state;\n if (!isAuthoredSuccessorConsistent(state, input.expectedHead, previous)) {\n throw new Error(\"Authored group policy successor is inconsistent\");\n }\n return verifiedPolicy({\n currentPolicy: input.currentPolicy,\n projection: input.request.projection,\n grants: input.request.grants,\n state: {\n ...state,\n stateHash: input.expectedHead.stateHash,\n createdAt: state.signedAt,\n },\n });\n}\n\nexport async function acknowledgeInitialGroupPolicy(input: {\n readonly organizationId: string;\n readonly request: CreateOrganizationGroupRequest;\n readonly response: OrganizationGroupSummaryResponse;\n readonly stateHash: string;\n}): Promise<{\n readonly bundle: PrincipalPolicyBundleResponse;\n readonly policy: VerifiedPrincipalPolicy;\n}> {\n await assertPolicyRequestCommitments(input.request.initialGroupPolicy);\n const state = input.request.initialGroupPolicy.state;\n if (\n input.response.groupId !== input.request.groupId ||\n input.response.organizationId !== input.organizationId ||\n input.response.isBuiltin ||\n input.response.currentState?.stateHash !== input.stateHash ||\n input.response.currentState.version !== state.version ||\n input.response.currentState.keyEpoch !== state.keyEpoch ||\n input.response.currentState.memberCount !== state.memberCount ||\n state.principalType !== \"group\" ||\n state.principalId !== input.request.groupId ||\n state.version !== 1 ||\n state.prevStateHash !== null\n ) {\n throw new Error(\"Created group policy acknowledgement mismatch\");\n }\n const storedState = {\n ...state,\n createdAt: input.response.createdAt,\n stateHash: input.stateHash,\n };\n const bundle: PrincipalPolicyBundleResponse = {\n currentMemberEnvelopes: {\n envelopes: input.request.initialGroupPolicy.memberEnvelopes,\n epoch: state.keyEpoch,\n principalId: state.principalId,\n principalType: state.principalType,\n stateHash: input.stateHash,\n },\n currentPayload: {\n principalId: state.principalId,\n principalType: state.principalType,\n stateHash: input.stateHash,\n ...input.request.initialGroupPolicy.encryptedPayload,\n createdAt: input.response.createdAt,\n },\n currentProjection: input.request.initialGroupPolicy.projection,\n currentGrants: input.request.initialGroupPolicy.grants,\n currentState: storedState,\n previousStates: [],\n };\n return {\n bundle,\n policy: verifiedPolicy({\n projection: input.request.initialGroupPolicy.projection,\n grants: input.request.initialGroupPolicy.grants,\n state: storedState,\n }),\n };\n}\n"]}
@@ -1,11 +1,14 @@
1
1
  import type { RequestFailureKind } from "../../internal/api-client/index.js";
2
- import type { PrincipalPolicyCheckpoint, PrincipalPolicyExternalAuthority, PrincipalPolicySignerPublicKey, ReferencedPrincipalHead, SigningKeyPair } from "../../internal/crypto/index.js";
2
+ import type { PrincipalPolicyCheckpoint, PrincipalPolicyExternalAuthority, ReferencedPrincipalHead, SigningKeyPair } from "../../internal/crypto/index.js";
3
3
  import type { CommitOrganizationGroupPolicyRequest, ContainerMutationRequest, CreateOrganizationGroupWithPolicyRequest, PutPrincipalPolicyRequest } from "../../internal/validators/request/index.js";
4
4
  import { type CommitOrganizationGroupPolicyResponse, type CreateOrganizationGroupResponse, type CurrentPrincipalMemberEnvelopesResponse, type PrincipalPolicyBundleResponse, type PrincipalPolicyMutationResponse } from "../../internal/validators/response/index.js";
5
5
  import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
6
6
  import type { TrustedUserIdentityResolver } from "../../data/trustedUserIdentity/index.js";
7
7
  import { type VerifiedExternalAdminPolicy } from "../principals/externalAdminPolicy.js";
8
+ import type { FullGroupMembershipMutationInput } from "./groupPolicyMutationEvidence.js";
8
9
  export interface PrincipalPolicyReadApi {
10
+ /** Resolve authored work before reading the state for a new mutation. */
11
+ readonly recoverPendingPrincipalMutation?: ((organizationId: string) => Promise<void>) | undefined;
9
12
  getCurrentPrincipalPolicy: (principalType: "group" | "organization", principalId: string) => Promise<PrincipalPolicyBundleResponse | null>;
10
13
  }
11
14
  export interface PrincipalPolicyReadWriteApi extends PrincipalPolicyReadApi {
@@ -33,18 +36,7 @@ export interface PrincipalPolicyReadWriteApi extends PrincipalPolicyReadApi {
33
36
  export interface OrganizationPrincipalPolicyApi extends PrincipalPolicyReadApi {
34
37
  createOrganizationGroup: (organizationId: string, input: CreateOrganizationGroupWithPolicyRequest) => Promise<CreateOrganizationGroupResponse | null>;
35
38
  }
36
- export interface BuildGroupMembershipMutationInput {
37
- readonly currentPolicy: PrincipalPolicyBundleResponse;
38
- readonly currentPolicySignerPublicKeys: readonly PrincipalPolicySignerPublicKey[];
39
- readonly currentOrgAdminUserIds?: readonly string[] | undefined;
40
- readonly externalAuthority?: PrincipalPolicyExternalAuthority | undefined;
41
- readonly isOrganizationAdminsGroup?: boolean | undefined;
42
- readonly localPolicyCheckpoint?: PrincipalPolicyCheckpoint | null;
43
- readonly signerUserId: string;
44
- readonly signingFingerprint: string;
45
- readonly signingKeyPair: SigningKeyPair;
46
- }
47
- interface LoadedGroupPolicyMutationContext extends BuildGroupMembershipMutationInput {
39
+ interface LoadedGroupPolicyMutationContext extends FullGroupMembershipMutationInput {
48
40
  readonly adminGroupId: string;
49
41
  readonly adminPolicyBundle: PrincipalPolicyBundleResponse;
50
42
  readonly currentOrgAdminUserIds: readonly string[];
@@ -41,6 +41,7 @@ export async function cacheGroupPolicy(input) {
41
41
  return bundle;
42
42
  }
43
43
  export async function loadGroupPolicyMutationContext(input) {
44
+ await input.apiClient.recoverPendingPrincipalMutation?.(input.organizationId);
44
45
  const adminPolicy = await loadOrganizationExternalAdminPolicy({
45
46
  execSql: input.execSql,
46
47
  getCurrentPrincipalPolicy: (principalType, principalId) => input.apiClient.getCurrentPrincipalPolicy(principalType, principalId),
@@ -1 +1 @@
1
- {"version":3,"file":"groupPolicyMutationContext.js","sourceRoot":"","sources":["groupPolicyMutationContext.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RequestFailureKind } from \"@tearleads/api-client\";\nimport type {\n PrincipalPolicyCheckpoint,\n PrincipalPolicyExternalAuthority,\n PrincipalPolicySignerPublicKey,\n ReferencedPrincipalHead,\n SigningKeyPair,\n} from \"@tearleads/crypto\";\nimport type {\n CommitOrganizationGroupPolicyRequest,\n ContainerMutationRequest,\n CreateOrganizationGroupWithPolicyRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport {\n CONTAINER_MUTATION_ERROR_CODES,\n type CommitOrganizationGroupPolicyResponse,\n type CreateOrganizationGroupResponse,\n type CurrentPrincipalMemberEnvelopesResponse,\n type PrincipalPolicyBundleResponse,\n type PrincipalPolicyMutationResponse,\n} from \"@tearleads/validators/response\";\nimport { persistVerifiedPrincipalPolicyBundlesAtomically } from \"../../data/persistence/keyingCheckpointAdvancePersistence\";\nimport { retainLocallyAcknowledgedPrincipalPolicyBundles } from \"../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport { requireOrganizationGroupHead } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../data/trustedUserIdentity\";\nimport {\n externalAdminPolicyPersistenceEntries,\n loadOrganizationExternalAdminPolicy,\n type VerifiedExternalAdminPolicy,\n} from \"../principals/externalAdminPolicy\";\nimport { assertGroupMetadataBinding } from \"./groupMetadataBinding\";\nimport { requireSignerCanManageGroup } from \"./groupMutationAuthorization\";\nimport {\n acknowledgeGroupPolicyState,\n assertGroupPolicyEnvelopesMatchAcknowledgement,\n buildAcknowledgedGroupPolicyBundle,\n} from \"./groupPolicyMutationAcknowledgement\";\nimport {\n assertPrincipalPolicyCurrentStateMatchesHead,\n groupPolicyMutationHead,\n} from \"./groupPolicyMutationHead\";\nimport {\n collectGroupPolicySignerPublicKeys,\n prepareGroupPolicyVerification,\n verifyGroupPolicy,\n verifyGroupPolicyWithExternalOrganizationAdmins,\n} from \"./groupPolicyVerification\";\n\nexport interface PrincipalPolicyReadApi {\n getCurrentPrincipalPolicy: (\n principalType: \"group\" | \"organization\",\n principalId: string,\n ) => Promise<PrincipalPolicyBundleResponse | null>;\n}\n\nexport interface PrincipalPolicyReadWriteApi extends PrincipalPolicyReadApi {\n commitOrganizationGroupPolicy: (\n organizationId: string,\n groupId: string,\n input: CommitOrganizationGroupPolicyRequest,\n ) => Promise<CommitOrganizationGroupPolicyResponse | null>;\n /**\n * Optional status-bearing variant. A rematerialized rotation the server\n * refuses for stranding a granted path names the descendant rekeys the batch\n * must carry; without this the refusal is a plain failure.\n */\n commitOrganizationGroupPolicyResult?: (\n organizationId: string,\n groupId: string,\n input: CommitOrganizationGroupPolicyRequest,\n options?: { readonly reportErrors?: boolean | undefined },\n ) => Promise<\n | {\n readonly ok: true;\n readonly data: CommitOrganizationGroupPolicyResponse;\n }\n | {\n readonly ok: false;\n readonly kind?: RequestFailureKind | undefined;\n readonly message?: string | undefined;\n readonly code?: string | undefined;\n readonly report?: (() => void) | undefined;\n readonly requiredContainerIds?: readonly string[] | undefined;\n readonly status: number | null;\n }\n >;\n}\n\nexport interface OrganizationPrincipalPolicyApi extends PrincipalPolicyReadApi {\n createOrganizationGroup: (\n organizationId: string,\n input: CreateOrganizationGroupWithPolicyRequest,\n ) => Promise<CreateOrganizationGroupResponse | null>;\n}\n\nexport interface BuildGroupMembershipMutationInput {\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly currentPolicySignerPublicKeys: readonly PrincipalPolicySignerPublicKey[];\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\ninterface LoadedGroupPolicyMutationContext\n extends BuildGroupMembershipMutationInput {\n readonly adminGroupId: string;\n readonly adminPolicyBundle: PrincipalPolicyBundleResponse;\n readonly currentOrgAdminUserIds: readonly string[];\n readonly organizationDescriptor: VerifiedExternalAdminPolicy[\"descriptor\"];\n readonly organizationPolicyBundle: PrincipalPolicyBundleResponse;\n readonly memberGroupId: string;\n}\n\nexport async function cacheGroupPolicy(input: {\n readonly acknowledgedMemberEnvelopes?:\n | CurrentPrincipalMemberEnvelopesResponse\n | undefined;\n readonly apiClient: PrincipalPolicyReadApi;\n readonly externalAuthority?: PrincipalPolicyExternalAuthority | undefined;\n readonly execSql: ExecSql;\n readonly expectedCurrentHead?: ReferencedPrincipalHead | undefined;\n readonly groupId: string;\n readonly localPolicyCheckpoint?: PrincipalPolicyCheckpoint | null;\n readonly organizationId: string;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<PrincipalPolicyBundleResponse> {\n const bundle = await input.apiClient.getCurrentPrincipalPolicy(\n \"group\",\n input.groupId,\n );\n\n if (!bundle) {\n throw new Error(\"Updated group policy could not be loaded\");\n }\n\n const signerPublicKeys = await collectGroupPolicySignerPublicKeys({\n bundle,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n const verified = await verifyGroupPolicy({\n currentPolicy: bundle,\n ...(input.externalAuthority\n ? { externalAuthority: input.externalAuthority }\n : {}),\n localPolicyCheckpoint: input.localPolicyCheckpoint ?? null,\n signerPublicKeys,\n });\n if (input.expectedCurrentHead) {\n assertPrincipalPolicyCurrentStateMatchesHead(\n bundle.currentState,\n input.expectedCurrentHead,\n );\n }\n if (input.acknowledgedMemberEnvelopes) {\n assertGroupPolicyEnvelopesMatchAcknowledgement(\n input.acknowledgedMemberEnvelopes,\n bundle.currentMemberEnvelopes,\n );\n }\n await persistVerifiedPrincipalPolicyBundlesAtomically({\n entries: [{ bundle, policy: verified }],\n execSql: input.execSql,\n organizationId: input.organizationId,\n stillCurrent: input.stillCurrent,\n updatedAt: new Date().toISOString(),\n });\n return bundle;\n}\n\nexport async function loadGroupPolicyMutationContext(input: {\n readonly apiClient: PrincipalPolicyReadApi;\n readonly execSql: ExecSql;\n readonly groupId: string;\n readonly organizationId: string;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<LoadedGroupPolicyMutationContext> {\n const adminPolicy = await loadOrganizationExternalAdminPolicy({\n execSql: input.execSql,\n getCurrentPrincipalPolicy: (principalType, principalId) =>\n input.apiClient.getCurrentPrincipalPolicy(principalType, principalId),\n organizationId: input.organizationId,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (!adminPolicy) {\n throw new Error(\"Organization admin authority could not be verified\");\n }\n const expectedGroupHead = requireOrganizationGroupHead(\n adminPolicy.descriptor,\n input.groupId,\n );\n const currentPolicy =\n input.groupId === adminPolicy.adminGroupId\n ? adminPolicy.adminBundle\n : await input.apiClient.getCurrentPrincipalPolicy(\"group\", input.groupId);\n if (!currentPolicy) {\n throw new Error(\"Group policy could not be loaded\");\n }\n assertPrincipalPolicyCurrentStateMatchesHead(\n currentPolicy.currentState,\n expectedGroupHead,\n );\n const verification = await prepareGroupPolicyVerification({\n currentPolicy,\n execSql: input.execSql,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n const isOrganizationAdminsGroup = adminPolicy.adminGroupId === input.groupId;\n const currentOrgAdminUserIds = adminPolicy.signerUserIds;\n const externalAuthority = adminPolicy.externalAuthority;\n if (!currentOrgAdminUserIds.includes(input.signerUserId)) {\n throw new Error(\"Organization admin authority is required\");\n }\n const verified = isOrganizationAdminsGroup\n ? await verifyGroupPolicy({\n currentPolicy,\n localPolicyCheckpoint: verification.localPolicyCheckpoint,\n signerPublicKeys: verification.currentPolicySignerPublicKeys,\n })\n : await verifyGroupPolicyWithExternalOrganizationAdmins({\n currentPolicy,\n loadExternalAuthority: async () => externalAuthority,\n localPolicyCheckpoint: verification.localPolicyCheckpoint,\n signerPublicKeys: verification.currentPolicySignerPublicKeys,\n });\n assertGroupMetadataBinding(currentPolicy, adminPolicy.descriptor);\n requireSignerCanManageGroup(\n currentPolicy,\n currentOrgAdminUserIds,\n input.signerUserId,\n );\n await persistVerifiedPrincipalPolicyBundlesAtomically({\n entries: [\n ...externalAdminPolicyPersistenceEntries(adminPolicy).filter(\n (entry) =>\n entry.policy.principalType !== verified.principalType ||\n entry.policy.principalId !== verified.principalId,\n ),\n { bundle: currentPolicy, policy: verified },\n ],\n execSql: input.execSql,\n organizationId: input.organizationId,\n updatedAt: new Date().toISOString(),\n });\n\n return {\n adminGroupId: adminPolicy.adminGroupId,\n adminPolicyBundle: adminPolicy.adminBundle,\n currentPolicy,\n currentOrgAdminUserIds,\n externalAuthority,\n isOrganizationAdminsGroup,\n memberGroupId: adminPolicy.memberGroupId,\n organizationDescriptor: adminPolicy.descriptor,\n organizationPolicyBundle: adminPolicy.bundle,\n ...verification,\n localPolicyCheckpoint: verified.checkpoint,\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n };\n}\n\n/**\n * Commit, answering one refusal: a rematerialized rekey or revoke that would\n * strand a level above a directly granted container is refused with the\n * descendant rekeys it must carry. The refused attempt rolled back whole, so\n * the served heads still stand; the batch is signed again with the named\n * levels woven in, replaces the container mutations, and the commit is retried\n * once. A second refusal means the tree moved underneath, and the caller's own\n * retry starts from a fresh policy.\n */\nasync function submitGroupPolicyCommit(input: {\n readonly apiClient: PrincipalPolicyReadWriteApi;\n readonly carryDescendantRekeys?:\n | ((\n requiredContainerIds: readonly string[],\n ) => Promise<readonly ContainerMutationRequest[]>)\n | undefined;\n readonly groupId: string;\n readonly organizationId: string;\n readonly organizationRequest: PutPrincipalPolicyRequest;\n readonly request: PutPrincipalPolicyRequest;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<CommitOrganizationGroupPolicyResponse | null> {\n const body = () => ({\n groupPolicy: input.request,\n organizationPolicy: input.organizationRequest,\n });\n const { commitOrganizationGroupPolicyResult } = input.apiClient;\n if (!commitOrganizationGroupPolicyResult) {\n return input.apiClient.commitOrganizationGroupPolicy(\n input.organizationId,\n input.groupId,\n body(),\n );\n }\n const first = await commitOrganizationGroupPolicyResult.call(\n input.apiClient,\n input.organizationId,\n input.groupId,\n body(),\n { reportErrors: false },\n );\n if (first.ok) return first.data;\n if (first.kind === \"cancelled\") return null;\n if (first.kind === \"outcome-unknown\")\n throw new Error(\n first.message ??\n \"Policy request may have committed; refresh before retrying\",\n );\n if (\n !input.carryDescendantRekeys ||\n first.code !== CONTAINER_MUTATION_ERROR_CODES.descendantRekeysRequired ||\n !first.requiredContainerIds?.length\n ) {\n first.report?.();\n return null;\n }\n let carried: readonly ContainerMutationRequest[];\n try {\n carried = await input.carryDescendantRekeys(first.requiredContainerIds);\n } catch (error) {\n // The refusal was answerable, and the answer failed: surface both. Once\n // the generation that owned the attempt is gone, only the failure is\n // surfaced; a superseded refusal is not an error.\n if (input.stillCurrent?.() !== false) first.report?.();\n throw error;\n }\n if (input.stillCurrent?.() === false) return null;\n // Nothing signed means the same refusal again; report the one already had.\n if (carried.length === 0) {\n first.report?.();\n return null;\n }\n input.request.containerMutations = [...carried];\n const second = await commitOrganizationGroupPolicyResult.call(\n input.apiClient,\n input.organizationId,\n input.groupId,\n body(),\n { reportErrors: false },\n );\n if (!second.ok) {\n if (second.kind === \"cancelled\") return null;\n if (second.kind === \"outcome-unknown\")\n throw new Error(\n second.message ??\n \"Policy request may have committed; refresh before retrying\",\n );\n second.report?.();\n return null;\n }\n return second.data;\n}\n\nexport async function commitGroupPolicyMutation(input: {\n readonly retiredContainerIds?: (() => readonly string[]) | undefined;\n readonly apiClient: PrincipalPolicyReadWriteApi;\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly execSql: ExecSql;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly groupId: string;\n readonly organizationId: string;\n readonly organizationPolicy: PrincipalPolicyBundleResponse;\n readonly organizationRequest: PutPrincipalPolicyRequest;\n /**\n * Re-sign the batch with the descendant rekeys a refusal named woven in; the\n * result replaces `containerMutations` and the commit is retried once.\n */\n readonly carryDescendantRekeys?:\n | ((\n requiredContainerIds: readonly string[],\n ) => Promise<readonly ContainerMutationRequest[]>)\n | undefined;\n readonly request: PutPrincipalPolicyRequest;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<PrincipalPolicyBundleResponse & PrincipalPolicyMutationResponse> {\n const stored = await submitGroupPolicyCommit(input);\n if (!stored) {\n throw new Error(\"Group policy update failed\");\n }\n const storedPolicy = stored.groupPolicy;\n const acknowledgedPolicy = await acknowledgeGroupPolicyState({\n currentPolicy: input.currentPolicy,\n expectedHead: input.expectedHead,\n request: input.request,\n response: storedPolicy.currentState,\n });\n const groupBundle = buildAcknowledgedGroupPolicyBundle({\n currentPolicy: input.currentPolicy,\n expectedHead: input.expectedHead,\n request: input.request,\n response: storedPolicy,\n });\n const organizationHead = await groupPolicyMutationHead(\n input.organizationRequest,\n );\n const acknowledgedOrganization = await acknowledgeGroupPolicyState({\n currentPolicy: input.organizationPolicy,\n expectedHead: organizationHead,\n request: input.organizationRequest,\n response: stored.organizationPolicy.currentState,\n });\n const organizationBundle = buildAcknowledgedGroupPolicyBundle({\n currentPolicy: input.organizationPolicy,\n expectedHead: organizationHead,\n request: input.organizationRequest,\n response: stored.organizationPolicy,\n });\n await retainLocallyAcknowledgedPrincipalPolicyBundles({\n retiredContainers: {\n containerIds: input.retiredContainerIds?.() ?? [],\n organizationId: input.organizationId,\n policy: acknowledgedPolicy,\n },\n entries: [\n { bundle: groupBundle, policy: acknowledgedPolicy },\n {\n bundle: organizationBundle,\n policy: acknowledgedOrganization,\n },\n ],\n execSql: input.execSql,\n organizationId: input.organizationId,\n stillCurrent: input.stillCurrent,\n updatedAt: new Date().toISOString(),\n });\n return groupBundle;\n}\n"]}
1
+ {"version":3,"file":"groupPolicyMutationContext.js","sourceRoot":"","sources":["groupPolicyMutationContext.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RequestFailureKind } from \"@tearleads/api-client\";\nimport type {\n PrincipalPolicyCheckpoint,\n PrincipalPolicyExternalAuthority,\n ReferencedPrincipalHead,\n SigningKeyPair,\n} from \"@tearleads/crypto\";\nimport type {\n CommitOrganizationGroupPolicyRequest,\n ContainerMutationRequest,\n CreateOrganizationGroupWithPolicyRequest,\n PutPrincipalPolicyRequest,\n} from \"@tearleads/validators/request\";\nimport {\n CONTAINER_MUTATION_ERROR_CODES,\n type CommitOrganizationGroupPolicyResponse,\n type CreateOrganizationGroupResponse,\n type CurrentPrincipalMemberEnvelopesResponse,\n type PrincipalPolicyBundleResponse,\n type PrincipalPolicyMutationResponse,\n} from \"@tearleads/validators/response\";\nimport { persistVerifiedPrincipalPolicyBundlesAtomically } from \"../../data/persistence/keyingCheckpointAdvancePersistence\";\nimport { retainLocallyAcknowledgedPrincipalPolicyBundles } from \"../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport { requireOrganizationGroupHead } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../data/trustedUserIdentity\";\nimport {\n externalAdminPolicyPersistenceEntries,\n loadOrganizationExternalAdminPolicy,\n type VerifiedExternalAdminPolicy,\n} from \"../principals/externalAdminPolicy\";\nimport { assertGroupMetadataBinding } from \"./groupMetadataBinding\";\nimport { requireSignerCanManageGroup } from \"./groupMutationAuthorization\";\nimport {\n acknowledgeGroupPolicyState,\n assertGroupPolicyEnvelopesMatchAcknowledgement,\n buildAcknowledgedGroupPolicyBundle,\n} from \"./groupPolicyMutationAcknowledgement\";\nimport type { FullGroupMembershipMutationInput } from \"./groupPolicyMutationEvidence\";\nimport {\n assertPrincipalPolicyCurrentStateMatchesHead,\n groupPolicyMutationHead,\n} from \"./groupPolicyMutationHead\";\nimport {\n collectGroupPolicySignerPublicKeys,\n prepareGroupPolicyVerification,\n verifyGroupPolicy,\n verifyGroupPolicyWithExternalOrganizationAdmins,\n} from \"./groupPolicyVerification\";\n\nexport interface PrincipalPolicyReadApi {\n /** Resolve authored work before reading the state for a new mutation. */\n readonly recoverPendingPrincipalMutation?:\n | ((organizationId: string) => Promise<void>)\n | undefined;\n getCurrentPrincipalPolicy: (\n principalType: \"group\" | \"organization\",\n principalId: string,\n ) => Promise<PrincipalPolicyBundleResponse | null>;\n}\n\nexport interface PrincipalPolicyReadWriteApi extends PrincipalPolicyReadApi {\n commitOrganizationGroupPolicy: (\n organizationId: string,\n groupId: string,\n input: CommitOrganizationGroupPolicyRequest,\n ) => Promise<CommitOrganizationGroupPolicyResponse | null>;\n /**\n * Optional status-bearing variant. A rematerialized rotation the server\n * refuses for stranding a granted path names the descendant rekeys the batch\n * must carry; without this the refusal is a plain failure.\n */\n commitOrganizationGroupPolicyResult?: (\n organizationId: string,\n groupId: string,\n input: CommitOrganizationGroupPolicyRequest,\n options?: { readonly reportErrors?: boolean | undefined },\n ) => Promise<\n | {\n readonly ok: true;\n readonly data: CommitOrganizationGroupPolicyResponse;\n }\n | {\n readonly ok: false;\n readonly kind?: RequestFailureKind | undefined;\n readonly message?: string | undefined;\n readonly code?: string | undefined;\n readonly report?: (() => void) | undefined;\n readonly requiredContainerIds?: readonly string[] | undefined;\n readonly status: number | null;\n }\n >;\n}\n\nexport interface OrganizationPrincipalPolicyApi extends PrincipalPolicyReadApi {\n createOrganizationGroup: (\n organizationId: string,\n input: CreateOrganizationGroupWithPolicyRequest,\n ) => Promise<CreateOrganizationGroupResponse | null>;\n}\n\ninterface LoadedGroupPolicyMutationContext\n extends FullGroupMembershipMutationInput {\n readonly adminGroupId: string;\n readonly adminPolicyBundle: PrincipalPolicyBundleResponse;\n readonly currentOrgAdminUserIds: readonly string[];\n readonly organizationDescriptor: VerifiedExternalAdminPolicy[\"descriptor\"];\n readonly organizationPolicyBundle: PrincipalPolicyBundleResponse;\n readonly memberGroupId: string;\n}\n\nexport async function cacheGroupPolicy(input: {\n readonly acknowledgedMemberEnvelopes?:\n | CurrentPrincipalMemberEnvelopesResponse\n | undefined;\n readonly apiClient: PrincipalPolicyReadApi;\n readonly externalAuthority?: PrincipalPolicyExternalAuthority | undefined;\n readonly execSql: ExecSql;\n readonly expectedCurrentHead?: ReferencedPrincipalHead | undefined;\n readonly groupId: string;\n readonly localPolicyCheckpoint?: PrincipalPolicyCheckpoint | null;\n readonly organizationId: string;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<PrincipalPolicyBundleResponse> {\n const bundle = await input.apiClient.getCurrentPrincipalPolicy(\n \"group\",\n input.groupId,\n );\n\n if (!bundle) {\n throw new Error(\"Updated group policy could not be loaded\");\n }\n\n const signerPublicKeys = await collectGroupPolicySignerPublicKeys({\n bundle,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n const verified = await verifyGroupPolicy({\n currentPolicy: bundle,\n ...(input.externalAuthority\n ? { externalAuthority: input.externalAuthority }\n : {}),\n localPolicyCheckpoint: input.localPolicyCheckpoint ?? null,\n signerPublicKeys,\n });\n if (input.expectedCurrentHead) {\n assertPrincipalPolicyCurrentStateMatchesHead(\n bundle.currentState,\n input.expectedCurrentHead,\n );\n }\n if (input.acknowledgedMemberEnvelopes) {\n assertGroupPolicyEnvelopesMatchAcknowledgement(\n input.acknowledgedMemberEnvelopes,\n bundle.currentMemberEnvelopes,\n );\n }\n await persistVerifiedPrincipalPolicyBundlesAtomically({\n entries: [{ bundle, policy: verified }],\n execSql: input.execSql,\n organizationId: input.organizationId,\n stillCurrent: input.stillCurrent,\n updatedAt: new Date().toISOString(),\n });\n return bundle;\n}\n\nexport async function loadGroupPolicyMutationContext(input: {\n readonly apiClient: PrincipalPolicyReadApi;\n readonly execSql: ExecSql;\n readonly groupId: string;\n readonly organizationId: string;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<LoadedGroupPolicyMutationContext> {\n await input.apiClient.recoverPendingPrincipalMutation?.(input.organizationId);\n const adminPolicy = await loadOrganizationExternalAdminPolicy({\n execSql: input.execSql,\n getCurrentPrincipalPolicy: (principalType, principalId) =>\n input.apiClient.getCurrentPrincipalPolicy(principalType, principalId),\n organizationId: input.organizationId,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (!adminPolicy) {\n throw new Error(\"Organization admin authority could not be verified\");\n }\n const expectedGroupHead = requireOrganizationGroupHead(\n adminPolicy.descriptor,\n input.groupId,\n );\n const currentPolicy =\n input.groupId === adminPolicy.adminGroupId\n ? adminPolicy.adminBundle\n : await input.apiClient.getCurrentPrincipalPolicy(\"group\", input.groupId);\n if (!currentPolicy) {\n throw new Error(\"Group policy could not be loaded\");\n }\n assertPrincipalPolicyCurrentStateMatchesHead(\n currentPolicy.currentState,\n expectedGroupHead,\n );\n const verification = await prepareGroupPolicyVerification({\n currentPolicy,\n execSql: input.execSql,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n const isOrganizationAdminsGroup = adminPolicy.adminGroupId === input.groupId;\n const currentOrgAdminUserIds = adminPolicy.signerUserIds;\n const externalAuthority = adminPolicy.externalAuthority;\n if (!currentOrgAdminUserIds.includes(input.signerUserId)) {\n throw new Error(\"Organization admin authority is required\");\n }\n const verified = isOrganizationAdminsGroup\n ? await verifyGroupPolicy({\n currentPolicy,\n localPolicyCheckpoint: verification.localPolicyCheckpoint,\n signerPublicKeys: verification.currentPolicySignerPublicKeys,\n })\n : await verifyGroupPolicyWithExternalOrganizationAdmins({\n currentPolicy,\n loadExternalAuthority: async () => externalAuthority,\n localPolicyCheckpoint: verification.localPolicyCheckpoint,\n signerPublicKeys: verification.currentPolicySignerPublicKeys,\n });\n assertGroupMetadataBinding(currentPolicy, adminPolicy.descriptor);\n requireSignerCanManageGroup(\n currentPolicy,\n currentOrgAdminUserIds,\n input.signerUserId,\n );\n await persistVerifiedPrincipalPolicyBundlesAtomically({\n entries: [\n ...externalAdminPolicyPersistenceEntries(adminPolicy).filter(\n (entry) =>\n entry.policy.principalType !== verified.principalType ||\n entry.policy.principalId !== verified.principalId,\n ),\n { bundle: currentPolicy, policy: verified },\n ],\n execSql: input.execSql,\n organizationId: input.organizationId,\n updatedAt: new Date().toISOString(),\n });\n\n return {\n adminGroupId: adminPolicy.adminGroupId,\n adminPolicyBundle: adminPolicy.adminBundle,\n currentPolicy,\n currentOrgAdminUserIds,\n externalAuthority,\n isOrganizationAdminsGroup,\n memberGroupId: adminPolicy.memberGroupId,\n organizationDescriptor: adminPolicy.descriptor,\n organizationPolicyBundle: adminPolicy.bundle,\n ...verification,\n localPolicyCheckpoint: verified.checkpoint,\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n };\n}\n\n/**\n * Commit, answering one refusal: a rematerialized rekey or revoke that would\n * strand a level above a directly granted container is refused with the\n * descendant rekeys it must carry. The refused attempt rolled back whole, so\n * the served heads still stand; the batch is signed again with the named\n * levels woven in, replaces the container mutations, and the commit is retried\n * once. A second refusal means the tree moved underneath, and the caller's own\n * retry starts from a fresh policy.\n */\nasync function submitGroupPolicyCommit(input: {\n readonly apiClient: PrincipalPolicyReadWriteApi;\n readonly carryDescendantRekeys?:\n | ((\n requiredContainerIds: readonly string[],\n ) => Promise<readonly ContainerMutationRequest[]>)\n | undefined;\n readonly groupId: string;\n readonly organizationId: string;\n readonly organizationRequest: PutPrincipalPolicyRequest;\n readonly request: PutPrincipalPolicyRequest;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<CommitOrganizationGroupPolicyResponse | null> {\n const body = () => ({\n groupPolicy: input.request,\n organizationPolicy: input.organizationRequest,\n });\n const { commitOrganizationGroupPolicyResult } = input.apiClient;\n if (!commitOrganizationGroupPolicyResult) {\n return input.apiClient.commitOrganizationGroupPolicy(\n input.organizationId,\n input.groupId,\n body(),\n );\n }\n const first = await commitOrganizationGroupPolicyResult.call(\n input.apiClient,\n input.organizationId,\n input.groupId,\n body(),\n { reportErrors: false },\n );\n if (first.ok) return first.data;\n if (first.kind === \"cancelled\") return null;\n if (first.kind === \"outcome-unknown\")\n throw new Error(\n first.message ??\n \"Policy request may have committed; refresh before retrying\",\n );\n if (\n !input.carryDescendantRekeys ||\n first.code !== CONTAINER_MUTATION_ERROR_CODES.descendantRekeysRequired ||\n !first.requiredContainerIds?.length\n ) {\n first.report?.();\n return null;\n }\n let carried: readonly ContainerMutationRequest[];\n try {\n carried = await input.carryDescendantRekeys(first.requiredContainerIds);\n } catch (error) {\n // The refusal was answerable, and the answer failed: surface both. Once\n // the generation that owned the attempt is gone, only the failure is\n // surfaced; a superseded refusal is not an error.\n if (input.stillCurrent?.() !== false) first.report?.();\n throw error;\n }\n if (input.stillCurrent?.() === false) return null;\n // Nothing signed means the same refusal again; report the one already had.\n if (carried.length === 0) {\n first.report?.();\n return null;\n }\n input.request.containerMutations = [...carried];\n const second = await commitOrganizationGroupPolicyResult.call(\n input.apiClient,\n input.organizationId,\n input.groupId,\n body(),\n { reportErrors: false },\n );\n if (!second.ok) {\n if (second.kind === \"cancelled\") return null;\n if (second.kind === \"outcome-unknown\")\n throw new Error(\n second.message ??\n \"Policy request may have committed; refresh before retrying\",\n );\n second.report?.();\n return null;\n }\n return second.data;\n}\n\nexport async function commitGroupPolicyMutation(input: {\n readonly retiredContainerIds?: (() => readonly string[]) | undefined;\n readonly apiClient: PrincipalPolicyReadWriteApi;\n readonly currentPolicy: PrincipalPolicyBundleResponse;\n readonly execSql: ExecSql;\n readonly expectedHead: ReferencedPrincipalHead;\n readonly groupId: string;\n readonly organizationId: string;\n readonly organizationPolicy: PrincipalPolicyBundleResponse;\n readonly organizationRequest: PutPrincipalPolicyRequest;\n /**\n * Re-sign the batch with the descendant rekeys a refusal named woven in; the\n * result replaces `containerMutations` and the commit is retried once.\n */\n readonly carryDescendantRekeys?:\n | ((\n requiredContainerIds: readonly string[],\n ) => Promise<readonly ContainerMutationRequest[]>)\n | undefined;\n readonly request: PutPrincipalPolicyRequest;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<PrincipalPolicyBundleResponse & PrincipalPolicyMutationResponse> {\n const stored = await submitGroupPolicyCommit(input);\n if (!stored) {\n throw new Error(\"Group policy update failed\");\n }\n const storedPolicy = stored.groupPolicy;\n const acknowledgedPolicy = await acknowledgeGroupPolicyState({\n currentPolicy: input.currentPolicy,\n expectedHead: input.expectedHead,\n request: input.request,\n response: storedPolicy.currentState,\n });\n const groupBundle = buildAcknowledgedGroupPolicyBundle({\n currentPolicy: input.currentPolicy,\n expectedHead: input.expectedHead,\n request: input.request,\n response: storedPolicy,\n });\n const organizationHead = await groupPolicyMutationHead(\n input.organizationRequest,\n );\n const acknowledgedOrganization = await acknowledgeGroupPolicyState({\n currentPolicy: input.organizationPolicy,\n expectedHead: organizationHead,\n request: input.organizationRequest,\n response: stored.organizationPolicy.currentState,\n });\n const organizationBundle = buildAcknowledgedGroupPolicyBundle({\n currentPolicy: input.organizationPolicy,\n expectedHead: organizationHead,\n request: input.organizationRequest,\n response: stored.organizationPolicy,\n });\n await retainLocallyAcknowledgedPrincipalPolicyBundles({\n retiredContainers: {\n containerIds: input.retiredContainerIds?.() ?? [],\n organizationId: input.organizationId,\n policy: acknowledgedPolicy,\n },\n entries: [\n { bundle: groupBundle, policy: acknowledgedPolicy },\n {\n bundle: organizationBundle,\n policy: acknowledgedOrganization,\n },\n ],\n execSql: input.execSql,\n organizationId: input.organizationId,\n stillCurrent: input.stillCurrent,\n updatedAt: new Date().toISOString(),\n });\n return groupBundle;\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import type { PrincipalPolicyPageCurrent } from "../../internal/api-client/index.js";
2
+ import { type PrincipalPolicyCheckpoint, type PrincipalPolicyExternalAuthority, type PrincipalPolicySignerPublicKey, type SigningKeyPair, type VerifiedPrincipalPolicyCurrent } from "../../internal/crypto/index.js";
3
+ import type { PutPrincipalPolicyRequest } from "../../internal/validators/request/index.js";
4
+ import type { PrincipalPolicyBundleResponse } from "../../internal/validators/response/index.js";
5
+ interface GroupMembershipSigningInput {
6
+ readonly currentOrgAdminUserIds?: readonly string[] | undefined;
7
+ readonly externalAuthority?: PrincipalPolicyExternalAuthority | undefined;
8
+ readonly isOrganizationAdminsGroup?: boolean | undefined;
9
+ readonly localPolicyCheckpoint?: PrincipalPolicyCheckpoint | null;
10
+ readonly signerUserId: string;
11
+ readonly signingFingerprint: string;
12
+ readonly signingKeyPair: SigningKeyPair;
13
+ }
14
+ export interface FullGroupMembershipMutationInput extends GroupMembershipSigningInput {
15
+ readonly currentPolicy: PrincipalPolicyBundleResponse;
16
+ readonly currentPolicySignerPublicKeys: readonly PrincipalPolicySignerPublicKey[];
17
+ }
18
+ interface CurrentGroupMembershipMutationInput extends GroupMembershipSigningInput {
19
+ readonly currentPolicy: PrincipalPolicyPageCurrent;
20
+ readonly verifiedCurrentPolicy: VerifiedPrincipalPolicyCurrent;
21
+ readonly stillCurrent: () => boolean;
22
+ }
23
+ export type BuildGroupMembershipMutationInput = FullGroupMembershipMutationInput | CurrentGroupMembershipMutationInput;
24
+ /** Current artifacts require their verified evidence; omitted history is never a bundle. */
25
+ export declare function withVerifiedGroupMutation<T extends BuildGroupMembershipMutationInput>(input: T, work: (owned: T) => Promise<PutPrincipalPolicyRequest>): Promise<PutPrincipalPolicyRequest>;
26
+ export {};
@@ -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"]}