@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
@@ -1 +1 @@
1
- {"version":3,"file":"principalGrantRetirementPersistence.js","sourceRoot":"","sources":["principalGrantRetirementPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AASrF,MAAM,CAAC,KAAK,UAAU,8BAA8B,CAClD,EAAgC,EAChC,UAAiD,EACjD,QAA4C,EAC5C,cAAkC;IAElC,IACE,CAAC,QAAQ,CAAC,IAAI,CACZ,CAAC,MAAM,EAAE,EAAE,CACT,MAAM,CAAC,WAAW,KAAK,UAAU,CAAC,MAAM,CAAC,WAAW;QACpD,MAAM,CAAC,aAAa,KAAK,UAAU,CAAC,MAAM,CAAC,aAAa;QACxD,MAAM,CAAC,SAAS,KAAK,UAAU,CAAC,MAAM,CAAC,SAAS,CACnD,EACD,CAAC;QACD,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,mDAAmD,CACpD,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAC9C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,KAAK,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAC3E,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,CAAC,GAAG,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAC5D,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAC7B,CACF,CAAC;IACF,IACE,UAAU,CAAC,cAAc,KAAK,cAAc;QAC5C,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EACtD,CAAC;QACD,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,uEAAuE,CACxE,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,WAAW,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3D,MAAM,EAAE;aACL,MAAM,CAAC,yBAAyB,CAAC;aACjC,MAAM,CAAC;YACN,cAAc,EAAE,UAAU,CAAC,cAAc;YACzC,WAAW;YACX,WAAW,EAAE,UAAU,CAAC,MAAM,CAAC,WAAW;YAC1C,eAAe,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS;SAC7C,CAAC;aACD,mBAAmB,EAAE;aACrB,GAAG,EAAE,CAAC;IACX,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,EAAgC,EAChC,UAAoC;IAEpC,IAAI,UAAU,CAAC,UAAU,KAAK,WAAW;QAAE,OAAO;IAClD,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,EAAE;SACvB,MAAM,CAAC,EAAE,WAAW,EAAE,yBAAyB,CAAC,WAAW,EAAE,CAAC;SAC9D,IAAI,CAAC,yBAAyB,CAAC;SAC/B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,yBAAyB,CAAC,cAAc,EAAE,UAAU,CAAC,cAAc,CAAC,EACvE,EAAE,CAAC,yBAAyB,CAAC,WAAW,EAAE,UAAU,CAAC,QAAQ,CAAC,CAC/D,CACF;SACA,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,IAAI,OAAO;QACT,MAAM,IAAI,uBAAuB,CAC/B,cAAc,EACd,aAAa,UAAU,CAAC,QAAQ,wCAAwC,CACzE,CAAC;AACN,CAAC","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport { and, eq } from \"drizzle-orm\";\nimport { principalGrantRetirements } from \"../sqlite/principalGrantRetirementSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\n\nexport interface AcknowledgedPrincipalGrantRetirements {\n readonly containerIds: readonly string[];\n readonly organizationId: string;\n readonly policy: VerifiedPrincipalPolicy;\n}\n\nexport async function storePrincipalGrantRetirements(\n tx: ClientSQLiteTransactionScope,\n retirement: AcknowledgedPrincipalGrantRetirements,\n policies: readonly VerifiedPrincipalPolicy[],\n organizationId: string | undefined,\n): Promise<void> {\n if (\n !policies.some(\n (policy) =>\n policy.principalId === retirement.policy.principalId &&\n policy.principalType === retirement.policy.principalType &&\n policy.stateHash === retirement.policy.stateHash,\n )\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Retirement must accompany its acknowledged policy\",\n );\n }\n const previous = retirement.policy.history?.find(\n (entry) => entry.state.stateHash === retirement.policy.state.prevStateHash,\n );\n const granted = new Set(\n [...retirement.policy.grants, ...(previous?.grants ?? [])].map(\n (grant) => grant.containerId,\n ),\n );\n if (\n retirement.organizationId !== organizationId ||\n retirement.containerIds.some((id) => !granted.has(id))\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Retirement must match the acknowledged organization and signed grants\",\n );\n }\n for (const containerId of new Set(retirement.containerIds)) {\n await tx\n .insert(principalGrantRetirements)\n .values({\n organizationId: retirement.organizationId,\n containerId,\n principalId: retirement.policy.principalId,\n policyStateHash: retirement.policy.stateHash,\n })\n .onConflictDoNothing()\n .run();\n }\n}\n\nexport async function assertContainerNotRetired(\n tx: ClientSQLiteTransactionScope,\n checkpoint: AccessManifestCheckpoint,\n): Promise<void> {\n if (checkpoint.objectKind !== \"container\") return;\n const [retired] = await tx\n .select({ containerId: principalGrantRetirements.containerId })\n .from(principalGrantRetirements)\n .where(\n and(\n eq(principalGrantRetirements.organizationId, checkpoint.organizationId),\n eq(principalGrantRetirements.containerId, checkpoint.objectId),\n ),\n )\n .limit(1);\n if (retired)\n throw new KeyingVerificationError(\n \"equivocation\",\n `Container ${checkpoint.objectId} was retired during principal rotation`,\n );\n}\n"]}
1
+ {"version":3,"file":"principalGrantRetirementPersistence.js","sourceRoot":"","sources":["principalGrantRetirementPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n KeyingVerificationError,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport { and, eq } from \"drizzle-orm\";\nimport { principalGrantRetirements } from \"../sqlite/principalGrantRetirementSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\n\nexport interface AcknowledgedPrincipalGrantRetirements {\n readonly containerIds: readonly string[];\n readonly organizationId: string;\n readonly policy: VerifiedPrincipalPolicy | VerifiedPrincipalPolicyCurrent;\n}\n\nexport async function storePrincipalGrantRetirements(\n tx: ClientSQLiteTransactionScope,\n retirement: AcknowledgedPrincipalGrantRetirements,\n policies: readonly (\n | VerifiedPrincipalPolicy\n | VerifiedPrincipalPolicyCurrent\n )[],\n organizationId: string | undefined,\n): Promise<void> {\n if (\n !policies.some(\n (policy) =>\n policy.principalId === retirement.policy.principalId &&\n policy.principalType === retirement.policy.principalType &&\n policy.stateHash === retirement.policy.stateHash,\n )\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Retirement must accompany its acknowledged policy\",\n );\n }\n const history =\n \"retainedHistory\" in retirement.policy\n ? retirement.policy.retainedHistory\n : retirement.policy.history;\n const previous = history?.find(\n (entry) => entry.state.stateHash === retirement.policy.state.prevStateHash,\n );\n const granted = new Set(\n [...retirement.policy.grants, ...(previous?.grants ?? [])].map(\n (grant) => grant.containerId,\n ),\n );\n if (\n retirement.organizationId !== organizationId ||\n retirement.containerIds.some((id) => !granted.has(id))\n ) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Retirement must match the acknowledged organization and signed grants\",\n );\n }\n for (const containerId of new Set(retirement.containerIds)) {\n await tx\n .insert(principalGrantRetirements)\n .values({\n organizationId: retirement.organizationId,\n containerId,\n principalId: retirement.policy.principalId,\n policyStateHash: retirement.policy.stateHash,\n })\n .onConflictDoNothing()\n .run();\n }\n}\n\nexport async function assertContainerNotRetired(\n tx: ClientSQLiteTransactionScope,\n checkpoint: AccessManifestCheckpoint,\n): Promise<void> {\n if (checkpoint.objectKind !== \"container\") return;\n const [retired] = await tx\n .select({ containerId: principalGrantRetirements.containerId })\n .from(principalGrantRetirements)\n .where(\n and(\n eq(principalGrantRetirements.organizationId, checkpoint.organizationId),\n eq(principalGrantRetirements.containerId, checkpoint.objectId),\n ),\n )\n .limit(1);\n if (retired)\n throw new KeyingVerificationError(\n \"equivocation\",\n `Container ${checkpoint.objectId} was retired during principal rotation`,\n );\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { isCurrentPrincipalMemberEnvelopesResponse, } from "../../internal/validators/response/index.js";
2
- import { desc, eq, sql } from "drizzle-orm";
2
+ import { and, desc, eq, sql } from "drizzle-orm";
3
3
  import { principalHistoryEvidenceTables, principalHistoryPrefixes, } from "../sqlite/principalHistoryEvidenceSchema.js";
4
+ import { principalHistoryStages } from "../sqlite/principalHistoryStageSchema.js";
4
5
  import { principalCurrentFingerprintJson, principalStateFingerprintJson, } from "../sqlite/principalKeyFingerprintJson.js";
5
6
  import { principalPolicies, principalPolicyBundleHistory, } from "../sqlite/principalPolicySchema.js";
6
7
  import { principalPolicyTables } from "../sqlite/schema.js";
@@ -41,6 +42,16 @@ export async function loadPrincipalKeyEnvelopeCandidates(execSql, fingerprints)
41
42
  .limit(1);
42
43
  if (prefix)
43
44
  encoded.push(prefix.envelopes);
45
+ const [stage] = await db
46
+ .select({
47
+ envelopes: sql `json_extract(${principalHistoryStages.currentJson}, '$.currentMemberEnvelopes')`,
48
+ })
49
+ .from(principalHistoryStages)
50
+ .where(and(eq(principalCurrentFingerprintJson(principalHistoryStages.currentJson), fingerprint), eq(principalHistoryStages.complete, true)))
51
+ .orderBy(desc(principalHistoryStages.afterVersion))
52
+ .limit(1);
53
+ if (stage)
54
+ encoded.push(stage.envelopes);
44
55
  for (const json of encoded) {
45
56
  let envelopes;
46
57
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"principalKeyEnvelopeCandidates.js","sourceRoot":"","sources":["principalKeyEnvelopeCandidates.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type CurrentPrincipalMemberEnvelopesResponse,\n isCurrentPrincipalMemberEnvelopesResponse,\n} from \"@tearleads/validators/response\";\nimport { desc, eq, sql } from \"drizzle-orm\";\nimport {\n principalHistoryEvidenceTables,\n principalHistoryPrefixes,\n} from \"../sqlite/principalHistoryEvidenceSchema\";\nimport {\n principalCurrentFingerprintJson,\n principalStateFingerprintJson,\n} from \"../sqlite/principalKeyFingerprintJson\";\nimport {\n principalPolicies,\n principalPolicyBundleHistory,\n} from \"../sqlite/principalPolicySchema\";\nimport { principalPolicyTables } from \"../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nexport interface PrincipalKeyEnvelopeCandidate {\n readonly currentState: {\n readonly principalType: \"group\" | \"organization\";\n readonly principalId: string;\n readonly stateHash: string;\n readonly keyFingerprint: string;\n };\n readonly currentMemberEnvelopes: CurrentPrincipalMemberEnvelopesResponse;\n}\n\n/**\n * Untrusted encrypted key candidates, never authorization evidence. The actual\n * private key must open the requested recipient wrap; the projection verifier\n * separately checks the signed KEK material identity and all policy authority.\n * Read only envelopes for the requested fingerprints, never signed histories.\n */\nexport async function loadPrincipalKeyEnvelopeCandidates(\n execSql: ExecSql,\n fingerprints: readonly string[],\n): Promise<PrincipalKeyEnvelopeCandidate[]> {\n await ensureSqlTables(execSql, [\n ...principalPolicyTables,\n ...principalHistoryEvidenceTables,\n ]);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const candidates: PrincipalKeyEnvelopeCandidate[] = [];\n for (const fingerprint of new Set(fingerprints)) {\n const encoded: string[] = [];\n for (const table of [principalPolicies, principalPolicyBundleHistory]) {\n const [row] = await db\n .select({ envelopes: table.currentMemberEnvelopesJson })\n .from(table)\n .where(\n eq(\n principalStateFingerprintJson(table.currentStateJson),\n fingerprint,\n ),\n )\n .orderBy(desc(table.updatedAt))\n .limit(1);\n if (row) encoded.push(row.envelopes);\n }\n const [prefix] = await db\n .select({\n envelopes: sql<string>`json_extract(${principalHistoryPrefixes.currentJson}, '$.currentMemberEnvelopes')`,\n })\n .from(principalHistoryPrefixes)\n .where(\n eq(\n principalCurrentFingerprintJson(principalHistoryPrefixes.currentJson),\n fingerprint,\n ),\n )\n .orderBy(desc(principalHistoryPrefixes.version))\n .limit(1);\n if (prefix) encoded.push(prefix.envelopes);\n for (const json of encoded) {\n let envelopes: unknown;\n try {\n envelopes = JSON.parse(json);\n } catch {\n continue;\n }\n if (!isCurrentPrincipalMemberEnvelopesResponse(envelopes)) continue;\n candidates.push({\n currentState: {\n principalType: envelopes.principalType,\n principalId: envelopes.principalId,\n stateHash: envelopes.stateHash,\n keyFingerprint: fingerprint,\n },\n currentMemberEnvelopes: envelopes,\n });\n }\n }\n return candidates;\n}\n"]}
1
+ {"version":3,"file":"principalKeyEnvelopeCandidates.js","sourceRoot":"","sources":["principalKeyEnvelopeCandidates.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type CurrentPrincipalMemberEnvelopesResponse,\n isCurrentPrincipalMemberEnvelopesResponse,\n} from \"@tearleads/validators/response\";\nimport { and, desc, eq, sql } from \"drizzle-orm\";\nimport {\n principalHistoryEvidenceTables,\n principalHistoryPrefixes,\n} from \"../sqlite/principalHistoryEvidenceSchema\";\nimport { principalHistoryStages } from \"../sqlite/principalHistoryStageSchema\";\nimport {\n principalCurrentFingerprintJson,\n principalStateFingerprintJson,\n} from \"../sqlite/principalKeyFingerprintJson\";\nimport {\n principalPolicies,\n principalPolicyBundleHistory,\n} from \"../sqlite/principalPolicySchema\";\nimport { principalPolicyTables } from \"../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nexport interface PrincipalKeyEnvelopeCandidate {\n readonly currentState: {\n readonly principalType: \"group\" | \"organization\";\n readonly principalId: string;\n readonly stateHash: string;\n readonly keyFingerprint: string;\n };\n readonly currentMemberEnvelopes: CurrentPrincipalMemberEnvelopesResponse;\n}\n\n/**\n * Untrusted encrypted key candidates, never authorization evidence. The actual\n * private key must open the requested recipient wrap; the projection verifier\n * separately checks the signed KEK material identity and all policy authority.\n * Read only envelopes for the requested fingerprints, never signed histories.\n */\nexport async function loadPrincipalKeyEnvelopeCandidates(\n execSql: ExecSql,\n fingerprints: readonly string[],\n): Promise<PrincipalKeyEnvelopeCandidate[]> {\n await ensureSqlTables(execSql, [\n ...principalPolicyTables,\n ...principalHistoryEvidenceTables,\n ]);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const candidates: PrincipalKeyEnvelopeCandidate[] = [];\n for (const fingerprint of new Set(fingerprints)) {\n const encoded: string[] = [];\n for (const table of [principalPolicies, principalPolicyBundleHistory]) {\n const [row] = await db\n .select({ envelopes: table.currentMemberEnvelopesJson })\n .from(table)\n .where(\n eq(\n principalStateFingerprintJson(table.currentStateJson),\n fingerprint,\n ),\n )\n .orderBy(desc(table.updatedAt))\n .limit(1);\n if (row) encoded.push(row.envelopes);\n }\n const [prefix] = await db\n .select({\n envelopes: sql<string>`json_extract(${principalHistoryPrefixes.currentJson}, '$.currentMemberEnvelopes')`,\n })\n .from(principalHistoryPrefixes)\n .where(\n eq(\n principalCurrentFingerprintJson(principalHistoryPrefixes.currentJson),\n fingerprint,\n ),\n )\n .orderBy(desc(principalHistoryPrefixes.version))\n .limit(1);\n if (prefix) encoded.push(prefix.envelopes);\n const [stage] = await db\n .select({\n envelopes: sql<string>`json_extract(${principalHistoryStages.currentJson}, '$.currentMemberEnvelopes')`,\n })\n .from(principalHistoryStages)\n .where(\n and(\n eq(\n principalCurrentFingerprintJson(principalHistoryStages.currentJson),\n fingerprint,\n ),\n eq(principalHistoryStages.complete, true),\n ),\n )\n .orderBy(desc(principalHistoryStages.afterVersion))\n .limit(1);\n if (stage) encoded.push(stage.envelopes);\n for (const json of encoded) {\n let envelopes: unknown;\n try {\n envelopes = JSON.parse(json);\n } catch {\n continue;\n }\n if (!isCurrentPrincipalMemberEnvelopesResponse(envelopes)) continue;\n candidates.push({\n currentState: {\n principalType: envelopes.principalType,\n principalId: envelopes.principalId,\n stateHash: envelopes.stateHash,\n keyFingerprint: fingerprint,\n },\n currentMemberEnvelopes: envelopes,\n });\n }\n }\n return candidates;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { principalMutationJournal } from "../sqlite/principalMutationJournalSchema.js";
2
+ import { type ExecSql } from "../sqlite/sqlSchema.js";
3
+ export type PrincipalMutationJournalRow = typeof principalMutationJournal.$inferSelect;
4
+ export declare class PendingPrincipalMutationError extends Error {
5
+ constructor();
6
+ }
7
+ export declare function loadPrincipalMutationJournal(execSql: ExecSql, scopeId: string): Promise<PrincipalMutationJournalRow | null>;
8
+ /** Claim the organization lane before dispatch; never overwrite unresolved work. */
9
+ export declare function claimPrincipalMutationJournal(input: {
10
+ readonly execSql: ExecSql;
11
+ readonly row: PrincipalMutationJournalRow;
12
+ readonly stillCurrent: () => boolean;
13
+ }): Promise<void>;
14
+ /** A late acknowledgement cannot retire another operation's journal entry. */
15
+ export declare function clearPrincipalMutationJournal(input: {
16
+ readonly execSql: ExecSql;
17
+ readonly row: PrincipalMutationJournalRow;
18
+ readonly stillCurrent: () => boolean;
19
+ }): Promise<boolean>;
@@ -0,0 +1,53 @@
1
+ import { and, eq } from "drizzle-orm";
2
+ import { assertProjectionVerificationCurrent } from "../keyingProjectionVerification/types.js";
3
+ import { principalMutationJournal, principalMutationJournalTables, } from "../sqlite/principalMutationJournalSchema.js";
4
+ import { getClientSQLitePersistenceRuntime } from "../sqlite/sqlitePersistenceRuntime.js";
5
+ import { ensureSqlTables } from "../sqlite/sqlSchema.js";
6
+ export class PendingPrincipalMutationError extends Error {
7
+ constructor() {
8
+ super("Resolve the pending principal mutation or explicitly abandon its retry before submitting another");
9
+ this.name = "PendingPrincipalMutationError";
10
+ }
11
+ }
12
+ export async function loadPrincipalMutationJournal(execSql, scopeId) {
13
+ await ensureSqlTables(execSql, principalMutationJournalTables);
14
+ const { db } = getClientSQLitePersistenceRuntime(execSql);
15
+ const [row] = await db
16
+ .select()
17
+ .from(principalMutationJournal)
18
+ .where(eq(principalMutationJournal.scopeId, scopeId))
19
+ .limit(1);
20
+ return row ?? null;
21
+ }
22
+ /** Claim the organization lane before dispatch; never overwrite unresolved work. */
23
+ export async function claimPrincipalMutationJournal(input) {
24
+ const row = { ...input.row };
25
+ await ensureSqlTables(input.execSql, principalMutationJournalTables);
26
+ const runtime = getClientSQLitePersistenceRuntime(input.execSql);
27
+ const result = await runtime.guardedTransaction(async (tx) => {
28
+ const [existing] = await tx
29
+ .select({ scopeId: principalMutationJournal.scopeId })
30
+ .from(principalMutationJournal)
31
+ .where(eq(principalMutationJournal.scopeId, row.scopeId))
32
+ .limit(1);
33
+ if (existing)
34
+ throw new PendingPrincipalMutationError();
35
+ await tx.insert(principalMutationJournal).values(row).run();
36
+ }, input.stillCurrent, { behavior: "immediate" });
37
+ assertProjectionVerificationCurrent(() => result.committed);
38
+ }
39
+ /** A late acknowledgement cannot retire another operation's journal entry. */
40
+ export async function clearPrincipalMutationJournal(input) {
41
+ const row = { ...input.row };
42
+ const runtime = getClientSQLitePersistenceRuntime(input.execSql);
43
+ const result = await runtime.guardedTransaction(async (tx) => {
44
+ const deleted = await tx
45
+ .delete(principalMutationJournal)
46
+ .where(and(eq(principalMutationJournal.scopeId, row.scopeId), eq(principalMutationJournal.organizationId, row.organizationId), eq(principalMutationJournal.serializedRequest, row.serializedRequest), eq(principalMutationJournal.signature, row.signature)))
47
+ .returning({ scopeId: principalMutationJournal.scopeId });
48
+ return deleted.length > 0;
49
+ }, input.stillCurrent, { behavior: "immediate" });
50
+ assertProjectionVerificationCurrent(() => result.committed);
51
+ return result.result === true;
52
+ }
53
+ //# sourceMappingURL=principalMutationJournalPersistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalMutationJournalPersistence.js","sourceRoot":"","sources":["principalMutationJournalPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { assertProjectionVerificationCurrent } from \"../keyingProjectionVerification/types\";\nimport {\n principalMutationJournal,\n principalMutationJournalTables,\n} from \"../sqlite/principalMutationJournalSchema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nexport type PrincipalMutationJournalRow =\n typeof principalMutationJournal.$inferSelect;\n\nexport class PendingPrincipalMutationError extends Error {\n constructor() {\n super(\n \"Resolve the pending principal mutation or explicitly abandon its retry before submitting another\",\n );\n this.name = \"PendingPrincipalMutationError\";\n }\n}\n\nexport async function loadPrincipalMutationJournal(\n execSql: ExecSql,\n scopeId: string,\n): Promise<PrincipalMutationJournalRow | null> {\n await ensureSqlTables(execSql, principalMutationJournalTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [row] = await db\n .select()\n .from(principalMutationJournal)\n .where(eq(principalMutationJournal.scopeId, scopeId))\n .limit(1);\n return row ?? null;\n}\n\n/** Claim the organization lane before dispatch; never overwrite unresolved work. */\nexport async function claimPrincipalMutationJournal(input: {\n readonly execSql: ExecSql;\n readonly row: PrincipalMutationJournalRow;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const row = { ...input.row };\n await ensureSqlTables(input.execSql, principalMutationJournalTables);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n const [existing] = await tx\n .select({ scopeId: principalMutationJournal.scopeId })\n .from(principalMutationJournal)\n .where(eq(principalMutationJournal.scopeId, row.scopeId))\n .limit(1);\n if (existing) throw new PendingPrincipalMutationError();\n await tx.insert(principalMutationJournal).values(row).run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n\n/** A late acknowledgement cannot retire another operation's journal entry. */\nexport async function clearPrincipalMutationJournal(input: {\n readonly execSql: ExecSql;\n readonly row: PrincipalMutationJournalRow;\n readonly stillCurrent: () => boolean;\n}): Promise<boolean> {\n const row = { ...input.row };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n const deleted = await tx\n .delete(principalMutationJournal)\n .where(\n and(\n eq(principalMutationJournal.scopeId, row.scopeId),\n eq(principalMutationJournal.organizationId, row.organizationId),\n eq(\n principalMutationJournal.serializedRequest,\n row.serializedRequest,\n ),\n eq(principalMutationJournal.signature, row.signature),\n ),\n )\n .returning({ scopeId: principalMutationJournal.scopeId });\n return deleted.length > 0;\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n return result.result === true;\n}\n"]}
@@ -1,55 +1,8 @@
1
- import { computePrincipalMemberEnvelopesRoot, computePrincipalStatePayloadCiphertextHash, KeyingVerificationError, normalizePrincipalContainerGrants, normalizePrincipalProjectionMembers, PrincipalMemberEnvelopeValidationError, } from "../../internal/crypto/index.js";
1
+ import { KeyingVerificationError, normalizePrincipalContainerGrants, normalizePrincipalProjectionMembers, } from "../../internal/crypto/index.js";
2
2
  import { canonicalKeyingJsonString } from "../keyingCanonicalJson.js";
3
- function bundleMismatch(message) {
4
- throw new KeyingVerificationError("equivocation", message);
5
- }
6
- async function memberEnvelopesRoot(bundle) {
7
- try {
8
- return await computePrincipalMemberEnvelopesRoot(bundle.currentMemberEnvelopes.envelopes);
9
- }
10
- catch (error) {
11
- if (error instanceof PrincipalMemberEnvelopeValidationError) {
12
- throw new KeyingVerificationError("invalid_shape", error.message);
13
- }
14
- throw error;
15
- }
16
- }
17
- async function assertBundlePayloadMatches(input) {
18
- const { bundle, policy } = input;
19
- const payloadHash = await computePrincipalStatePayloadCiphertextHash(bundle.currentPayload.ciphertext);
20
- const envelopesRoot = await memberEnvelopesRoot(bundle);
21
- if (bundle.currentPayload.principalType !== policy.principalType ||
22
- bundle.currentPayload.principalId !== policy.principalId ||
23
- bundle.currentPayload.stateHash !== policy.stateHash ||
24
- bundle.currentPayload.ciphertextHash !== payloadHash ||
25
- policy.state.payloadCiphertextHash !== payloadHash ||
26
- bundle.currentMemberEnvelopes.principalType !== policy.principalType ||
27
- bundle.currentMemberEnvelopes.principalId !== policy.principalId ||
28
- bundle.currentMemberEnvelopes.stateHash !== policy.stateHash ||
29
- bundle.currentMemberEnvelopes.epoch !== policy.keyEpoch ||
30
- envelopesRoot !== policy.state.memberEnvelopesRoot) {
31
- bundleMismatch("Verified principal policy bundle payload mismatch");
32
- }
33
- }
3
+ import { assertCurrentMatchesVerifiedPolicy } from "./verifiedPrincipalPolicyCurrent.js";
34
4
  export async function assertBundleMatchesVerifiedPolicy(input) {
35
5
  const { bundle, policy } = input;
36
- if (bundle.currentState.principalType !== policy.principalType ||
37
- bundle.currentState.principalId !== policy.principalId ||
38
- bundle.currentState.version !== policy.version ||
39
- bundle.currentState.keyEpoch !== policy.keyEpoch ||
40
- bundle.currentState.stateHash !== policy.stateHash ||
41
- policy.checkpoint.version !== policy.version ||
42
- policy.checkpoint.stateHash !== policy.stateHash) {
43
- bundleMismatch("Verified principal policy bundle head mismatch");
44
- }
45
- if (canonicalKeyingJsonString(bundle.currentState, "principal policy bundle state") !==
46
- canonicalKeyingJsonString(policy.state, "verified principal policy state") ||
47
- canonicalKeyingJsonString(normalizePrincipalProjectionMembers(bundle.currentProjection), "principal policy bundle projection") !==
48
- canonicalKeyingJsonString(normalizePrincipalProjectionMembers(policy.projection), "verified principal policy projection") ||
49
- canonicalKeyingJsonString(normalizePrincipalContainerGrants(bundle.currentGrants), "principal policy bundle grants") !==
50
- canonicalKeyingJsonString(normalizePrincipalContainerGrants(policy.grants), "verified principal policy grants")) {
51
- bundleMismatch("Verified principal policy bundle content mismatch");
52
- }
53
6
  const history = policy.history ?? [];
54
7
  const expectedChain = [
55
8
  ...bundle.previousStates,
@@ -70,8 +23,11 @@ export async function assertBundleMatchesVerifiedPolicy(input) {
70
23
  }));
71
24
  if (canonicalKeyingJsonString(expectedChain, "principal policy bundle history") !==
72
25
  canonicalKeyingJsonString(verifiedHistory, "verified principal policy history")) {
73
- bundleMismatch("Verified principal policy bundle history mismatch");
26
+ throw new KeyingVerificationError("equivocation", "Verified principal policy bundle history mismatch");
74
27
  }
75
- await assertBundlePayloadMatches(input);
28
+ await assertCurrentMatchesVerifiedPolicy({
29
+ current: input.bundle,
30
+ policy: input.policy,
31
+ });
76
32
  }
77
33
  //# sourceMappingURL=verifiedPrincipalPolicyBundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"verifiedPrincipalPolicyBundle.js","sourceRoot":"","sources":["verifiedPrincipalPolicyBundle.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computePrincipalMemberEnvelopesRoot,\n computePrincipalStatePayloadCiphertextHash,\n KeyingVerificationError,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n PrincipalMemberEnvelopeValidationError,\n type VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../keyingCanonicalJson\";\n\nfunction bundleMismatch(message: string): never {\n throw new KeyingVerificationError(\"equivocation\", message);\n}\n\nasync function memberEnvelopesRoot(\n bundle: PrincipalPolicyBundleResponse,\n): Promise<string> {\n try {\n return await computePrincipalMemberEnvelopesRoot(\n bundle.currentMemberEnvelopes.envelopes,\n );\n } catch (error) {\n if (error instanceof PrincipalMemberEnvelopeValidationError) {\n throw new KeyingVerificationError(\"invalid_shape\", error.message);\n }\n throw error;\n }\n}\n\nasync function assertBundlePayloadMatches(input: {\n bundle: PrincipalPolicyBundleResponse;\n policy: VerifiedPrincipalPolicy;\n}): Promise<void> {\n const { bundle, policy } = input;\n const payloadHash = await computePrincipalStatePayloadCiphertextHash(\n bundle.currentPayload.ciphertext,\n );\n const envelopesRoot = await memberEnvelopesRoot(bundle);\n if (\n bundle.currentPayload.principalType !== policy.principalType ||\n bundle.currentPayload.principalId !== policy.principalId ||\n bundle.currentPayload.stateHash !== policy.stateHash ||\n bundle.currentPayload.ciphertextHash !== payloadHash ||\n policy.state.payloadCiphertextHash !== payloadHash ||\n bundle.currentMemberEnvelopes.principalType !== policy.principalType ||\n bundle.currentMemberEnvelopes.principalId !== policy.principalId ||\n bundle.currentMemberEnvelopes.stateHash !== policy.stateHash ||\n bundle.currentMemberEnvelopes.epoch !== policy.keyEpoch ||\n envelopesRoot !== policy.state.memberEnvelopesRoot\n ) {\n bundleMismatch(\"Verified principal policy bundle payload mismatch\");\n }\n}\n\nexport async function assertBundleMatchesVerifiedPolicy(input: {\n bundle: PrincipalPolicyBundleResponse;\n policy: VerifiedPrincipalPolicy;\n}): Promise<void> {\n const { bundle, policy } = input;\n if (\n bundle.currentState.principalType !== policy.principalType ||\n bundle.currentState.principalId !== policy.principalId ||\n bundle.currentState.version !== policy.version ||\n bundle.currentState.keyEpoch !== policy.keyEpoch ||\n bundle.currentState.stateHash !== policy.stateHash ||\n policy.checkpoint.version !== policy.version ||\n policy.checkpoint.stateHash !== policy.stateHash\n ) {\n bundleMismatch(\"Verified principal policy bundle head mismatch\");\n }\n if (\n canonicalKeyingJsonString(\n bundle.currentState,\n \"principal policy bundle state\",\n ) !==\n canonicalKeyingJsonString(\n policy.state,\n \"verified principal policy state\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(bundle.currentProjection),\n \"principal policy bundle projection\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(policy.projection),\n \"verified principal policy projection\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(bundle.currentGrants),\n \"principal policy bundle grants\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(policy.grants),\n \"verified principal policy grants\",\n )\n ) {\n bundleMismatch(\"Verified principal policy bundle content mismatch\");\n }\n\n const history = policy.history ?? [];\n const expectedChain = [\n ...bundle.previousStates,\n {\n state: bundle.currentState,\n projection: bundle.currentProjection,\n grants: bundle.currentGrants,\n },\n ].map((entry) => ({\n ...entry,\n projection: normalizePrincipalProjectionMembers(entry.projection),\n grants: normalizePrincipalContainerGrants(entry.grants),\n }));\n const verifiedHistory = history.map((entry) => ({\n ...entry,\n projection: normalizePrincipalProjectionMembers(entry.projection),\n grants: normalizePrincipalContainerGrants(entry.grants),\n }));\n if (\n canonicalKeyingJsonString(\n expectedChain,\n \"principal policy bundle history\",\n ) !==\n canonicalKeyingJsonString(\n verifiedHistory,\n \"verified principal policy history\",\n )\n ) {\n bundleMismatch(\"Verified principal policy bundle history mismatch\");\n }\n await assertBundlePayloadMatches(input);\n}\n"]}
1
+ {"version":3,"file":"verifiedPrincipalPolicyBundle.js","sourceRoot":"","sources":["verifiedPrincipalPolicyBundle.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,iCAAiC,EACjC,mCAAmC,GAEpC,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,kCAAkC,EAAE,MAAM,kCAAkC,CAAC;AAEtF,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAGvD;IACC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IACrC,MAAM,aAAa,GAAG;QACpB,GAAG,MAAM,CAAC,cAAc;QACxB;YACE,KAAK,EAAE,MAAM,CAAC,YAAY;YAC1B,UAAU,EAAE,MAAM,CAAC,iBAAiB;YACpC,MAAM,EAAE,MAAM,CAAC,aAAa;SAC7B;KACF,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAChB,GAAG,KAAK;QACR,UAAU,EAAE,mCAAmC,CAAC,KAAK,CAAC,UAAU,CAAC;QACjE,MAAM,EAAE,iCAAiC,CAAC,KAAK,CAAC,MAAM,CAAC;KACxD,CAAC,CAAC,CAAC;IACJ,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC9C,GAAG,KAAK;QACR,UAAU,EAAE,mCAAmC,CAAC,KAAK,CAAC,UAAU,CAAC;QACjE,MAAM,EAAE,iCAAiC,CAAC,KAAK,CAAC,MAAM,CAAC;KACxD,CAAC,CAAC,CAAC;IACJ,IACE,yBAAyB,CACvB,aAAa,EACb,iCAAiC,CAClC;QACD,yBAAyB,CACvB,eAAe,EACf,mCAAmC,CACpC,EACD,CAAC;QACD,MAAM,IAAI,uBAAuB,CAC/B,cAAc,EACd,mDAAmD,CACpD,CAAC;IACJ,CAAC;IACD,MAAM,kCAAkC,CAAC;QACvC,OAAO,EAAE,KAAK,CAAC,MAAM;QACrB,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n type VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { canonicalKeyingJsonString } from \"../keyingCanonicalJson\";\nimport { assertCurrentMatchesVerifiedPolicy } from \"./verifiedPrincipalPolicyCurrent\";\n\nexport async function assertBundleMatchesVerifiedPolicy(input: {\n bundle: PrincipalPolicyBundleResponse;\n policy: VerifiedPrincipalPolicy;\n}): Promise<void> {\n const { bundle, policy } = input;\n const history = policy.history ?? [];\n const expectedChain = [\n ...bundle.previousStates,\n {\n state: bundle.currentState,\n projection: bundle.currentProjection,\n grants: bundle.currentGrants,\n },\n ].map((entry) => ({\n ...entry,\n projection: normalizePrincipalProjectionMembers(entry.projection),\n grants: normalizePrincipalContainerGrants(entry.grants),\n }));\n const verifiedHistory = history.map((entry) => ({\n ...entry,\n projection: normalizePrincipalProjectionMembers(entry.projection),\n grants: normalizePrincipalContainerGrants(entry.grants),\n }));\n if (\n canonicalKeyingJsonString(\n expectedChain,\n \"principal policy bundle history\",\n ) !==\n canonicalKeyingJsonString(\n verifiedHistory,\n \"verified principal policy history\",\n )\n ) {\n throw new KeyingVerificationError(\n \"equivocation\",\n \"Verified principal policy bundle history mismatch\",\n );\n }\n await assertCurrentMatchesVerifiedPolicy({\n current: input.bundle,\n policy: input.policy,\n });\n}\n"]}
@@ -0,0 +1,56 @@
1
+ import { computePrincipalMemberEnvelopesRoot, computePrincipalStatePayloadCiphertextHash, KeyingVerificationError, normalizePrincipalContainerGrants, normalizePrincipalProjectionMembers, PrincipalMemberEnvelopeValidationError, } from "../../internal/crypto/index.js";
2
+ import { canonicalKeyingJsonString } from "../keyingCanonicalJson.js";
3
+ function currentMismatch(message) {
4
+ throw new KeyingVerificationError("equivocation", message);
5
+ }
6
+ async function memberEnvelopesRoot(current) {
7
+ try {
8
+ return await computePrincipalMemberEnvelopesRoot(current.currentMemberEnvelopes.envelopes);
9
+ }
10
+ catch (error) {
11
+ if (error instanceof PrincipalMemberEnvelopeValidationError) {
12
+ throw new KeyingVerificationError("invalid_shape", error.message);
13
+ }
14
+ throw error;
15
+ }
16
+ }
17
+ async function assertCurrentPayloadMatches(input) {
18
+ const { current, policy } = input;
19
+ const payloadHash = await computePrincipalStatePayloadCiphertextHash(current.currentPayload.ciphertext);
20
+ const envelopesRoot = await memberEnvelopesRoot(current);
21
+ if (current.currentPayload.principalType !== policy.principalType ||
22
+ current.currentPayload.principalId !== policy.principalId ||
23
+ current.currentPayload.stateHash !== policy.stateHash ||
24
+ current.currentPayload.ciphertextHash !== payloadHash ||
25
+ policy.state.payloadCiphertextHash !== payloadHash ||
26
+ current.currentMemberEnvelopes.principalType !== policy.principalType ||
27
+ current.currentMemberEnvelopes.principalId !== policy.principalId ||
28
+ current.currentMemberEnvelopes.stateHash !== policy.stateHash ||
29
+ current.currentMemberEnvelopes.epoch !== policy.keyEpoch ||
30
+ envelopesRoot !== policy.state.memberEnvelopesRoot) {
31
+ currentMismatch("Verified principal policy current payload mismatch");
32
+ }
33
+ }
34
+ /** Bind current wire artifacts to already verified policy evidence; never authenticate history. */
35
+ export async function assertCurrentMatchesVerifiedPolicy(input) {
36
+ const { current, policy } = input;
37
+ if (current.currentState.principalType !== policy.principalType ||
38
+ current.currentState.principalId !== policy.principalId ||
39
+ current.currentState.version !== policy.version ||
40
+ current.currentState.keyEpoch !== policy.keyEpoch ||
41
+ current.currentState.stateHash !== policy.stateHash ||
42
+ policy.checkpoint.version !== policy.version ||
43
+ policy.checkpoint.stateHash !== policy.stateHash) {
44
+ currentMismatch("Verified principal policy current head mismatch");
45
+ }
46
+ if (canonicalKeyingJsonString(current.currentState, "principal policy current state") !==
47
+ canonicalKeyingJsonString(policy.state, "verified principal policy state") ||
48
+ canonicalKeyingJsonString(normalizePrincipalProjectionMembers(current.currentProjection), "principal policy current projection") !==
49
+ canonicalKeyingJsonString(normalizePrincipalProjectionMembers(policy.projection), "verified principal policy projection") ||
50
+ canonicalKeyingJsonString(normalizePrincipalContainerGrants(current.currentGrants), "principal policy current grants") !==
51
+ canonicalKeyingJsonString(normalizePrincipalContainerGrants(policy.grants), "verified principal policy grants")) {
52
+ currentMismatch("Verified principal policy current content mismatch");
53
+ }
54
+ await assertCurrentPayloadMatches(input);
55
+ }
56
+ //# sourceMappingURL=verifiedPrincipalPolicyCurrent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifiedPrincipalPolicyCurrent.js","sourceRoot":"","sources":["verifiedPrincipalPolicyCurrent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyPageCurrent } from \"@tearleads/api-client\";\nimport {\n computePrincipalMemberEnvelopesRoot,\n computePrincipalStatePayloadCiphertextHash,\n KeyingVerificationError,\n normalizePrincipalContainerGrants,\n normalizePrincipalProjectionMembers,\n PrincipalMemberEnvelopeValidationError,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport { canonicalKeyingJsonString } from \"../keyingCanonicalJson\";\n\ntype VerifiedCurrentPolicy =\n | VerifiedPrincipalPolicy\n | VerifiedPrincipalPolicyCurrent;\n\nfunction currentMismatch(message: string): never {\n throw new KeyingVerificationError(\"equivocation\", message);\n}\n\nasync function memberEnvelopesRoot(\n current: PrincipalPolicyPageCurrent,\n): Promise<string> {\n try {\n return await computePrincipalMemberEnvelopesRoot(\n current.currentMemberEnvelopes.envelopes,\n );\n } catch (error) {\n if (error instanceof PrincipalMemberEnvelopeValidationError) {\n throw new KeyingVerificationError(\"invalid_shape\", error.message);\n }\n throw error;\n }\n}\n\nasync function assertCurrentPayloadMatches(input: {\n current: PrincipalPolicyPageCurrent;\n policy: VerifiedCurrentPolicy;\n}): Promise<void> {\n const { current, policy } = input;\n const payloadHash = await computePrincipalStatePayloadCiphertextHash(\n current.currentPayload.ciphertext,\n );\n const envelopesRoot = await memberEnvelopesRoot(current);\n if (\n current.currentPayload.principalType !== policy.principalType ||\n current.currentPayload.principalId !== policy.principalId ||\n current.currentPayload.stateHash !== policy.stateHash ||\n current.currentPayload.ciphertextHash !== payloadHash ||\n policy.state.payloadCiphertextHash !== payloadHash ||\n current.currentMemberEnvelopes.principalType !== policy.principalType ||\n current.currentMemberEnvelopes.principalId !== policy.principalId ||\n current.currentMemberEnvelopes.stateHash !== policy.stateHash ||\n current.currentMemberEnvelopes.epoch !== policy.keyEpoch ||\n envelopesRoot !== policy.state.memberEnvelopesRoot\n ) {\n currentMismatch(\"Verified principal policy current payload mismatch\");\n }\n}\n\n/** Bind current wire artifacts to already verified policy evidence; never authenticate history. */\nexport async function assertCurrentMatchesVerifiedPolicy(input: {\n current: PrincipalPolicyPageCurrent;\n policy: VerifiedCurrentPolicy;\n}): Promise<void> {\n const { current, policy } = input;\n if (\n current.currentState.principalType !== policy.principalType ||\n current.currentState.principalId !== policy.principalId ||\n current.currentState.version !== policy.version ||\n current.currentState.keyEpoch !== policy.keyEpoch ||\n current.currentState.stateHash !== policy.stateHash ||\n policy.checkpoint.version !== policy.version ||\n policy.checkpoint.stateHash !== policy.stateHash\n ) {\n currentMismatch(\"Verified principal policy current head mismatch\");\n }\n if (\n canonicalKeyingJsonString(\n current.currentState,\n \"principal policy current state\",\n ) !==\n canonicalKeyingJsonString(\n policy.state,\n \"verified principal policy state\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(current.currentProjection),\n \"principal policy current projection\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalProjectionMembers(policy.projection),\n \"verified principal policy projection\",\n ) ||\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(current.currentGrants),\n \"principal policy current grants\",\n ) !==\n canonicalKeyingJsonString(\n normalizePrincipalContainerGrants(policy.grants),\n \"verified principal policy grants\",\n )\n ) {\n currentMismatch(\"Verified principal policy current content mismatch\");\n }\n\n await assertCurrentPayloadMatches(input);\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { type SigningKeyPair } from "../../internal/crypto/index.js";
2
+ import { type CommitOrganizationGroupPolicyRequest } from "../../internal/validators/request/index.js";
3
+ import type { PrincipalMutationJournalRow } from "../persistence/principalMutationJournalPersistence.js";
4
+ export interface PrincipalMutationJournalScope {
5
+ readonly identityTrustDomain: string;
6
+ readonly organizationId: string;
7
+ readonly userId: string;
8
+ readonly signingFingerprint: string;
9
+ }
10
+ export interface AuthoredPrincipalMutation {
11
+ readonly groupId: string;
12
+ readonly request: CommitOrganizationGroupPolicyRequest;
13
+ }
14
+ export declare function principalMutationJournalScopeId(scope: PrincipalMutationJournalScope): Promise<string>;
15
+ /** Sign the complete wire body, including artifacts outside policy signatures. */
16
+ export declare function sealPrincipalMutation(input: {
17
+ readonly scope: PrincipalMutationJournalScope;
18
+ readonly mutation: AuthoredPrincipalMutation;
19
+ readonly signingKeyPair: SigningKeyPair;
20
+ }): Promise<PrincipalMutationJournalRow>;
21
+ /** Authentication precedes parsing or submission; corrupt authored work is retained. */
22
+ export declare function openPrincipalMutation(input: {
23
+ readonly scope: PrincipalMutationJournalScope;
24
+ readonly row: PrincipalMutationJournalRow;
25
+ readonly signingPublicKey: Uint8Array;
26
+ }): Promise<AuthoredPrincipalMutation>;
@@ -0,0 +1,90 @@
1
+ import { KeyingVerificationError, sign, toFingerprint, verify, } from "../../internal/crypto/index.js";
2
+ import { base64ToBytes, bytesToBase64 } from "../../internal/encoding/index.js";
3
+ import { CommitOrganizationGroupPolicyRequestSchema, } from "../../internal/validators/request/index.js";
4
+ import { canonicalKeyingJsonString } from "../keyingCanonicalJson.js";
5
+ const journalDomain = "tearleads.sdk.principal-mutation.v1";
6
+ const encoder = new TextEncoder();
7
+ function scopeJson(scope) {
8
+ const values = [
9
+ scope.identityTrustDomain,
10
+ scope.organizationId,
11
+ scope.userId,
12
+ scope.signingFingerprint,
13
+ ];
14
+ if (values.some((value) => typeof value !== "string" || value.length === 0))
15
+ throw new Error("Principal mutation journal requires a complete scope");
16
+ return JSON.stringify([journalDomain, ...values]);
17
+ }
18
+ export async function principalMutationJournalScopeId(scope) {
19
+ return bytesToBase64(new Uint8Array(await crypto.subtle.digest("SHA-256", encoder.encode(scopeJson(scope)))));
20
+ }
21
+ function readMutation(value, scope) {
22
+ if (typeof value !== "object" || value === null)
23
+ throw new Error("Principal mutation journal payload is invalid");
24
+ const groupId = Reflect.get(value, "groupId");
25
+ const request = CommitOrganizationGroupPolicyRequestSchema.parse(Reflect.get(value, "request"));
26
+ const group = request.groupPolicy.state;
27
+ const organization = request.organizationPolicy.state;
28
+ if (typeof groupId !== "string" ||
29
+ group.principalType !== "group" ||
30
+ group.principalId !== groupId ||
31
+ organization.principalType !== "organization" ||
32
+ organization.principalId !== scope.organizationId ||
33
+ [group, organization].some((state) => state.signerUserId !== scope.userId ||
34
+ state.signerUserKeyFingerprint !== scope.signingFingerprint))
35
+ throw new Error("Principal mutation journal target or signer differs");
36
+ return { groupId, request };
37
+ }
38
+ function signedBytes(scope, request) {
39
+ // The domain-tagged scope and JSON tuple separate these identity-key
40
+ // signatures from policy state signatures and other authored formats.
41
+ return encoder.encode(JSON.stringify([scopeJson(scope), request]));
42
+ }
43
+ /** Sign the complete wire body, including artifacts outside policy signatures. */
44
+ export async function sealPrincipalMutation(input) {
45
+ const scope = { ...input.scope };
46
+ const mutation = readMutation(JSON.parse(JSON.stringify(input.mutation)), scope);
47
+ const serializedRequest = canonicalKeyingJsonString(mutation, "authored principal mutation");
48
+ const publicKey = new Uint8Array(input.signingKeyPair.signingPublicKey);
49
+ const privateKey = new Uint8Array(input.signingKeyPair.signingPrivateKey);
50
+ try {
51
+ if ((await toFingerprint(publicKey)) !== scope.signingFingerprint)
52
+ throw new Error("Principal mutation journal signing key differs");
53
+ const bytes = signedBytes(scope, serializedRequest);
54
+ const signature = sign(bytes, privateKey);
55
+ if (!verify(signature, bytes, publicKey))
56
+ throw new KeyingVerificationError("signer_mismatch", "Principal mutation journal signing key pair differs");
57
+ return {
58
+ scopeId: await principalMutationJournalScopeId(scope),
59
+ organizationId: scope.organizationId,
60
+ serializedRequest,
61
+ signature: bytesToBase64(signature),
62
+ };
63
+ }
64
+ finally {
65
+ privateKey.fill(0);
66
+ }
67
+ }
68
+ /** Authentication precedes parsing or submission; corrupt authored work is retained. */
69
+ export async function openPrincipalMutation(input) {
70
+ const scope = { ...input.scope };
71
+ const row = { ...input.row };
72
+ const publicKey = new Uint8Array(input.signingPublicKey);
73
+ try {
74
+ if (row.organizationId !== scope.organizationId ||
75
+ row.scopeId !== (await principalMutationJournalScopeId(scope)) ||
76
+ (await toFingerprint(publicKey)) !== scope.signingFingerprint ||
77
+ !verify(base64ToBytes(row.signature), signedBytes(scope, row.serializedRequest), publicKey))
78
+ throw new Error("Principal mutation journal authentication failed");
79
+ }
80
+ catch {
81
+ throw new KeyingVerificationError("signature_mismatch", "Saved principal mutation could not be authenticated");
82
+ }
83
+ try {
84
+ return readMutation(JSON.parse(row.serializedRequest), scope);
85
+ }
86
+ catch {
87
+ throw new KeyingVerificationError("invalid_shape", "Authenticated principal mutation has an unsupported or invalid format");
88
+ }
89
+ }
90
+ //# sourceMappingURL=principalMutationJournal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalMutationJournal.js","sourceRoot":"","sources":["principalMutationJournal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EAEvB,IAAI,EACJ,aAAa,EACb,MAAM,GACP,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAEL,0CAA0C,GAC3C,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAenE,MAAM,aAAa,GAAG,qCAAqC,CAAC;AAC5D,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,SAAS,SAAS,CAAC,KAAoC;IACrD,MAAM,MAAM,GAAG;QACb,KAAK,CAAC,mBAAmB;QACzB,KAAK,CAAC,cAAc;QACpB,KAAK,CAAC,MAAM;QACZ,KAAK,CAAC,kBAAkB;KACzB,CAAC;IACF,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;QACzE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,aAAa,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,KAAoC;IAEpC,OAAO,aAAa,CAClB,IAAI,UAAU,CACZ,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CACxE,CACF,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CACnB,KAAc,EACd,KAAoC;IAEpC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAC7C,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,MAAM,OAAO,GAAY,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,0CAA0C,CAAC,KAAK,CAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAC9B,CAAC;IACF,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC;IACxC,MAAM,YAAY,GAAG,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC;IACtD,IACE,OAAO,OAAO,KAAK,QAAQ;QAC3B,KAAK,CAAC,aAAa,KAAK,OAAO;QAC/B,KAAK,CAAC,WAAW,KAAK,OAAO;QAC7B,YAAY,CAAC,aAAa,KAAK,cAAc;QAC7C,YAAY,CAAC,WAAW,KAAK,KAAK,CAAC,cAAc;QACjD,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,IAAI,CACxB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,MAAM;YACnC,KAAK,CAAC,wBAAwB,KAAK,KAAK,CAAC,kBAAkB,CAC9D;QAED,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,WAAW,CAAC,KAAoC,EAAE,OAAe;IACxE,qEAAqE;IACrE,sEAAsE;IACtE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAI3C;IACC,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IACjC,MAAM,QAAQ,GAAG,YAAY,CAC3B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAC1C,KAAK,CACN,CAAC;IACF,MAAM,iBAAiB,GAAG,yBAAyB,CACjD,QAAQ,EACR,6BAA6B,CAC9B,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACxE,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IAC1E,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,KAAK,CAAC,kBAAkB;YAC/D,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,SAAS,CAAC;YACtC,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,qDAAqD,CACtD,CAAC;QACJ,OAAO;YACL,OAAO,EAAE,MAAM,+BAA+B,CAAC,KAAK,CAAC;YACrD,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,iBAAiB;YACjB,SAAS,EAAE,aAAa,CAAC,SAAS,CAAC;SACpC,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,KAI3C;IACC,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IACjC,MAAM,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,IACE,GAAG,CAAC,cAAc,KAAK,KAAK,CAAC,cAAc;YAC3C,GAAG,CAAC,OAAO,KAAK,CAAC,MAAM,+BAA+B,CAAC,KAAK,CAAC,CAAC;YAC9D,CAAC,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC,KAAK,KAAK,CAAC,kBAAkB;YAC7D,CAAC,MAAM,CACL,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,EAC5B,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,iBAAiB,CAAC,EACzC,SAAS,CACV;YAED,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,qDAAqD,CACtD,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,uBAAuB,CAC/B,eAAe,EACf,uEAAuE,CACxE,CAAC;IACJ,CAAC;AACH,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n type SigningKeyPair,\n sign,\n toFingerprint,\n verify,\n} from \"@tearleads/crypto\";\nimport { base64ToBytes, bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n type CommitOrganizationGroupPolicyRequest,\n CommitOrganizationGroupPolicyRequestSchema,\n} from \"@tearleads/validators/request\";\nimport { canonicalKeyingJsonString } from \"../keyingCanonicalJson\";\nimport type { PrincipalMutationJournalRow } from \"../persistence/principalMutationJournalPersistence\";\n\nexport interface PrincipalMutationJournalScope {\n readonly identityTrustDomain: string;\n readonly organizationId: string;\n readonly userId: string;\n readonly signingFingerprint: string;\n}\n\nexport interface AuthoredPrincipalMutation {\n readonly groupId: string;\n readonly request: CommitOrganizationGroupPolicyRequest;\n}\n\nconst journalDomain = \"tearleads.sdk.principal-mutation.v1\";\nconst encoder = new TextEncoder();\n\nfunction scopeJson(scope: PrincipalMutationJournalScope): string {\n const values = [\n scope.identityTrustDomain,\n scope.organizationId,\n scope.userId,\n scope.signingFingerprint,\n ];\n if (values.some((value) => typeof value !== \"string\" || value.length === 0))\n throw new Error(\"Principal mutation journal requires a complete scope\");\n return JSON.stringify([journalDomain, ...values]);\n}\n\nexport async function principalMutationJournalScopeId(\n scope: PrincipalMutationJournalScope,\n): Promise<string> {\n return bytesToBase64(\n new Uint8Array(\n await crypto.subtle.digest(\"SHA-256\", encoder.encode(scopeJson(scope))),\n ),\n );\n}\n\nfunction readMutation(\n value: unknown,\n scope: PrincipalMutationJournalScope,\n): AuthoredPrincipalMutation {\n if (typeof value !== \"object\" || value === null)\n throw new Error(\"Principal mutation journal payload is invalid\");\n const groupId: unknown = Reflect.get(value, \"groupId\");\n const request = CommitOrganizationGroupPolicyRequestSchema.parse(\n Reflect.get(value, \"request\"),\n );\n const group = request.groupPolicy.state;\n const organization = request.organizationPolicy.state;\n if (\n typeof groupId !== \"string\" ||\n group.principalType !== \"group\" ||\n group.principalId !== groupId ||\n organization.principalType !== \"organization\" ||\n organization.principalId !== scope.organizationId ||\n [group, organization].some(\n (state) =>\n state.signerUserId !== scope.userId ||\n state.signerUserKeyFingerprint !== scope.signingFingerprint,\n )\n )\n throw new Error(\"Principal mutation journal target or signer differs\");\n return { groupId, request };\n}\n\nfunction signedBytes(scope: PrincipalMutationJournalScope, request: string) {\n // The domain-tagged scope and JSON tuple separate these identity-key\n // signatures from policy state signatures and other authored formats.\n return encoder.encode(JSON.stringify([scopeJson(scope), request]));\n}\n\n/** Sign the complete wire body, including artifacts outside policy signatures. */\nexport async function sealPrincipalMutation(input: {\n readonly scope: PrincipalMutationJournalScope;\n readonly mutation: AuthoredPrincipalMutation;\n readonly signingKeyPair: SigningKeyPair;\n}): Promise<PrincipalMutationJournalRow> {\n const scope = { ...input.scope };\n const mutation = readMutation(\n JSON.parse(JSON.stringify(input.mutation)),\n scope,\n );\n const serializedRequest = canonicalKeyingJsonString(\n mutation,\n \"authored principal mutation\",\n );\n const publicKey = new Uint8Array(input.signingKeyPair.signingPublicKey);\n const privateKey = new Uint8Array(input.signingKeyPair.signingPrivateKey);\n try {\n if ((await toFingerprint(publicKey)) !== scope.signingFingerprint)\n throw new Error(\"Principal mutation journal signing key differs\");\n const bytes = signedBytes(scope, serializedRequest);\n const signature = sign(bytes, privateKey);\n if (!verify(signature, bytes, publicKey))\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Principal mutation journal signing key pair differs\",\n );\n return {\n scopeId: await principalMutationJournalScopeId(scope),\n organizationId: scope.organizationId,\n serializedRequest,\n signature: bytesToBase64(signature),\n };\n } finally {\n privateKey.fill(0);\n }\n}\n\n/** Authentication precedes parsing or submission; corrupt authored work is retained. */\nexport async function openPrincipalMutation(input: {\n readonly scope: PrincipalMutationJournalScope;\n readonly row: PrincipalMutationJournalRow;\n readonly signingPublicKey: Uint8Array;\n}): Promise<AuthoredPrincipalMutation> {\n const scope = { ...input.scope };\n const row = { ...input.row };\n const publicKey = new Uint8Array(input.signingPublicKey);\n try {\n if (\n row.organizationId !== scope.organizationId ||\n row.scopeId !== (await principalMutationJournalScopeId(scope)) ||\n (await toFingerprint(publicKey)) !== scope.signingFingerprint ||\n !verify(\n base64ToBytes(row.signature),\n signedBytes(scope, row.serializedRequest),\n publicKey,\n )\n )\n throw new Error(\"Principal mutation journal authentication failed\");\n } catch {\n throw new KeyingVerificationError(\n \"signature_mismatch\",\n \"Saved principal mutation could not be authenticated\",\n );\n }\n try {\n return readMutation(JSON.parse(row.serializedRequest), scope);\n } catch {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Authenticated principal mutation has an unsupported or invalid format\",\n );\n }\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type { PrincipalMutationJournalRow } from "../persistence/principalMutationJournalPersistence.js";
2
+ /** Identifies exact local bytes for an acknowledged discard, never for replay. */
3
+ export declare function principalMutationJournalRecordId(row: PrincipalMutationJournalRow): Promise<string>;
4
+ export declare class UnreadablePrincipalMutationError extends Error {
5
+ readonly recordId: string;
6
+ readonly reason: "authentication" | "format";
7
+ constructor(recordId: string, reason: "authentication" | "format");
8
+ }
@@ -0,0 +1,25 @@
1
+ import { bytesToBase64 } from "../../internal/encoding/index.js";
2
+ /** Identifies exact local bytes for an acknowledged discard, never for replay. */
3
+ export async function principalMutationJournalRecordId(row) {
4
+ const bytes = new TextEncoder().encode(JSON.stringify([
5
+ "tearleads.sdk.unreadable-principal-mutation.v1",
6
+ row.scopeId,
7
+ row.organizationId,
8
+ row.serializedRequest,
9
+ row.signature,
10
+ ]));
11
+ return bytesToBase64(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)));
12
+ }
13
+ export class UnreadablePrincipalMutationError extends Error {
14
+ recordId;
15
+ reason;
16
+ constructor(recordId, reason) {
17
+ super(reason === "authentication"
18
+ ? "Saved principal mutation could not be authenticated"
19
+ : "Saved principal mutation has an unsupported or invalid format");
20
+ this.recordId = recordId;
21
+ this.reason = reason;
22
+ this.name = "UnreadablePrincipalMutationError";
23
+ }
24
+ }
25
+ //# sourceMappingURL=principalMutationJournalRecord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalMutationJournalRecord.js","sourceRoot":"","sources":["principalMutationJournalRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,GAAgC;IAEhC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CACpC,IAAI,CAAC,SAAS,CAAC;QACb,gDAAgD;QAChD,GAAG,CAAC,OAAO;QACX,GAAG,CAAC,cAAc;QAClB,GAAG,CAAC,iBAAiB;QACrB,GAAG,CAAC,SAAS;KACd,CAAC,CACH,CAAC;IACF,OAAO,aAAa,CAClB,IAAI,UAAU,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAC7D,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,gCAAiC,SAAQ,KAAK;IAE9C;IACA;IAFX,YACW,QAAgB,EAChB,MAAmC;QAE5C,KAAK,CACH,MAAM,KAAK,gBAAgB;YACzB,CAAC,CAAC,qDAAqD;YACvD,CAAC,CAAC,+DAA+D,CACpE,CAAC;QAPO,aAAQ,GAAR,QAAQ,CAAQ;QAChB,WAAM,GAAN,MAAM,CAA6B;QAO5C,IAAI,CAAC,IAAI,GAAG,kCAAkC,CAAC;IACjD,CAAC;CACF","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport type { PrincipalMutationJournalRow } from \"../persistence/principalMutationJournalPersistence\";\n\n/** Identifies exact local bytes for an acknowledged discard, never for replay. */\nexport async function principalMutationJournalRecordId(\n row: PrincipalMutationJournalRow,\n): Promise<string> {\n const bytes = new TextEncoder().encode(\n JSON.stringify([\n \"tearleads.sdk.unreadable-principal-mutation.v1\",\n row.scopeId,\n row.organizationId,\n row.serializedRequest,\n row.signature,\n ]),\n );\n return bytesToBase64(\n new Uint8Array(await crypto.subtle.digest(\"SHA-256\", bytes)),\n );\n}\n\nexport class UnreadablePrincipalMutationError extends Error {\n constructor(\n readonly recordId: string,\n readonly reason: \"authentication\" | \"format\",\n ) {\n super(\n reason === \"authentication\"\n ? \"Saved principal mutation could not be authenticated\"\n : \"Saved principal mutation has an unsupported or invalid format\",\n );\n this.name = \"UnreadablePrincipalMutationError\";\n }\n}\n"]}
@@ -1,4 +1,6 @@
1
+ import { desc } from "drizzle-orm";
1
2
  import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
3
+ import { principalCurrentFingerprintJson } from "./principalKeyFingerprintJson.js";
2
4
  import { defineSqlTableSchema } from "./sqlTableSchema.js";
3
5
  /** Provisional, locally authenticated verification work; never an app checkpoint. */
4
6
  export const principalHistoryStages = sqliteTable("principal_history_stages", {
@@ -9,6 +11,7 @@ export const principalHistoryStages = sqliteTable("principal_history_stages", {
9
11
  complete: integer("complete", { mode: "boolean" }).notNull(),
10
12
  progress: text("progress").notNull(),
11
13
  }, (table) => [
14
+ index("principal_history_stages_key_fingerprint_idx").on(principalCurrentFingerprintJson(table.currentJson), table.complete, desc(table.afterVersion)),
12
15
  index("principal_history_stages_organization_idx").on(table.organizationId),
13
16
  ]);
14
17
  export const principalHistoryStageTables = [
@@ -1 +1 @@
1
- {"version":3,"file":"principalHistoryStageSchema.js","sourceRoot":"","sources":["principalHistoryStageSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,qFAAqF;AACrF,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAC/C,0BAA0B,EAC1B;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC3C,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE;IAChD,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IAC5D,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;CACrC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,KAAK,CAAC,2CAA2C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;CAC5E,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,oBAAoB,CAAC,sBAAsB,CAAC;CAC7C,CAAC","sourcesContent":["import { index, integer, sqliteTable, text } from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema } from \"./sqlTableSchema\";\n\n/** Provisional, locally authenticated verification work; never an app checkpoint. */\nexport const principalHistoryStages = sqliteTable(\n \"principal_history_stages\",\n {\n id: text(\"id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n currentJson: text(\"current_json\").notNull(),\n afterVersion: integer(\"after_version\").notNull(),\n complete: integer(\"complete\", { mode: \"boolean\" }).notNull(),\n progress: text(\"progress\").notNull(),\n },\n (table) => [\n index(\"principal_history_stages_organization_idx\").on(table.organizationId),\n ],\n);\n\nexport const principalHistoryStageTables = [\n defineSqlTableSchema(principalHistoryStages),\n];\n"]}
1
+ {"version":3,"file":"principalHistoryStageSchema.js","sourceRoot":"","sources":["principalHistoryStageSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,EAAE,+BAA+B,EAAE,MAAM,+BAA+B,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,qFAAqF;AACrF,MAAM,CAAC,MAAM,sBAAsB,GAAG,WAAW,CAC/C,0BAA0B,EAC1B;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC3C,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE;IAChD,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IAC5D,QAAQ,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;CACrC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,KAAK,CAAC,8CAA8C,CAAC,CAAC,EAAE,CACtD,+BAA+B,CAAC,KAAK,CAAC,WAAW,CAAC,EAClD,KAAK,CAAC,QAAQ,EACd,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CACzB;IACD,KAAK,CAAC,2CAA2C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC;CAC5E,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,oBAAoB,CAAC,sBAAsB,CAAC;CAC7C,CAAC","sourcesContent":["import { desc } from \"drizzle-orm\";\nimport { index, integer, sqliteTable, text } from \"drizzle-orm/sqlite-core\";\nimport { principalCurrentFingerprintJson } from \"./principalKeyFingerprintJson\";\nimport { defineSqlTableSchema } from \"./sqlTableSchema\";\n\n/** Provisional, locally authenticated verification work; never an app checkpoint. */\nexport const principalHistoryStages = sqliteTable(\n \"principal_history_stages\",\n {\n id: text(\"id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n currentJson: text(\"current_json\").notNull(),\n afterVersion: integer(\"after_version\").notNull(),\n complete: integer(\"complete\", { mode: \"boolean\" }).notNull(),\n progress: text(\"progress\").notNull(),\n },\n (table) => [\n index(\"principal_history_stages_key_fingerprint_idx\").on(\n principalCurrentFingerprintJson(table.currentJson),\n table.complete,\n desc(table.afterVersion),\n ),\n index(\"principal_history_stages_organization_idx\").on(table.organizationId),\n ],\n);\n\nexport const principalHistoryStageTables = [\n defineSqlTableSchema(principalHistoryStages),\n];\n"]}