@tearleads/client-sdk 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/client/organizations/index.js +2 -2
  2. package/client/organizations/index.js.map +1 -1
  3. package/client/organizations/organizationHistory.js +66 -0
  4. package/client/organizations/organizationHistory.js.map +1 -0
  5. package/client/organizations/organizationReadModels.d.ts +1 -1
  6. package/client/organizations/organizationReadModels.js +7 -27
  7. package/client/organizations/organizationReadModels.js.map +1 -1
  8. package/client/organizations/organizationsTypes.d.ts +1 -1
  9. package/client/organizations/organizationsTypes.js.map +1 -1
  10. package/data/containers/shared/types.d.ts +2 -2
  11. package/data/containers/shared/types.js.map +1 -1
  12. package/data/documents/shared/syncSubmitFailure.d.ts +2 -2
  13. package/data/documents/shared/syncSubmitFailure.js.map +1 -1
  14. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js +34 -8
  15. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js.map +1 -1
  16. package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
  17. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js +17 -0
  18. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js.map +1 -0
  19. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js +55 -0
  20. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js.map +1 -0
  21. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js +25 -13
  22. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js.map +1 -1
  23. package/data/keyingProjectionVerification/documentPurgeProofVerification.d.ts +5 -3
  24. package/data/keyingProjectionVerification/documentPurgeProofVerification.js +52 -8
  25. package/data/keyingProjectionVerification/documentPurgeProofVerification.js.map +1 -1
  26. package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
  27. package/data/keyingProjectionVerification/types.d.ts +4 -0
  28. package/data/keyingProjectionVerification/types.js.map +1 -1
  29. package/data/persistence/principalAuthorizationCheckpoints.js +1 -1
  30. package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -1
  31. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +1 -0
  32. package/data/persistence/principalCurrentAcknowledgementPersistence.js +58 -12
  33. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  34. package/data/persistence/principalHistoryEvidencePersistence.d.ts +2 -0
  35. package/data/persistence/principalHistoryEvidencePersistence.js +2 -0
  36. package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -1
  37. package/data/persistence/principalHistoryIncompleteRetention.js +32 -0
  38. package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -0
  39. package/data/persistence/principalHistoryNodeRetention.js +76 -0
  40. package/data/persistence/principalHistoryNodeRetention.js.map +1 -0
  41. package/data/persistence/principalHistoryPrefixPersistence.d.ts +1 -0
  42. package/data/persistence/principalHistoryPrefixPersistence.js +30 -1
  43. package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
  44. package/data/persistence/principalHistoryRootOwnership.js +71 -0
  45. package/data/persistence/principalHistoryRootOwnership.js.map +1 -0
  46. package/data/persistence/principalHistoryStagePersistence.js +45 -0
  47. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  48. package/data/persistence/principalHistoryStageRetention.js +44 -0
  49. package/data/persistence/principalHistoryStageRetention.js.map +1 -0
  50. package/data/persistence/principalHistoryUnpublishedRetention.js +71 -0
  51. package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -0
  52. package/data/persistence/principalKeyEnvelopeArchivePersistence.js +63 -0
  53. package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +1 -0
  54. package/data/persistence/principalKeyEnvelopeCandidates.js +10 -1
  55. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
  56. package/data/sqlite/principalHistoryEvidenceSchema.js +2 -0
  57. package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -1
  58. package/data/sqlite/principalHistoryNodeRetentionSchema.js +30 -0
  59. package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +1 -0
  60. package/data/sqlite/principalHistoryRetentionSchema.js +40 -0
  61. package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -0
  62. package/data/sqlite/principalHistoryStageSchema.js +2 -0
  63. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  64. package/data/sqlite/schema.d.ts +453 -0
  65. package/data/sqlite/schema.js +6 -0
  66. package/data/sqlite/schema.js.map +1 -1
  67. package/data/sqlite/sqliteCommitGuards.js +49 -0
  68. package/data/sqlite/sqliteCommitGuards.js.map +1 -0
  69. package/data/sqlite/sqlitePersistenceRuntime.js +14 -2
  70. package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
  71. package/index.d.ts +3 -1
  72. package/index.js.map +1 -1
  73. package/internal/api-client/ApiClient.d.ts +60 -137
  74. package/internal/api-client/ApiClient.js +7 -5
  75. package/internal/api-client/ApiClient.js.map +1 -1
  76. package/internal/api-client/apiRequestRuntime.js +7 -7
  77. package/internal/api-client/apiRequestRuntime.js.map +1 -1
  78. package/internal/api-client/documentPurge.js +25 -0
  79. package/internal/api-client/documentPurge.js.map +1 -0
  80. package/internal/api-client/organizationPolicyHistory.d.ts +53 -0
  81. package/internal/api-client/organizationPolicyHistory.js +15 -0
  82. package/internal/api-client/organizationPolicyHistory.js.map +1 -0
  83. package/internal/api-client/requestInternals.js +4 -4
  84. package/internal/api-client/requestInternals.js.map +1 -1
  85. package/internal/api-client/types.d.ts +2 -2
  86. package/internal/api-client/types.js.map +1 -1
  87. package/internal/crypto/keying/principalPolicyHistory.js +4 -0
  88. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  89. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
  90. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  91. package/internal/validators/operation/containerMutations.d.ts +448 -6528
  92. package/internal/validators/operation/documentMutations.d.ts +323 -579
  93. package/internal/validators/operation/documentMutations.js +22 -4
  94. package/internal/validators/operation/documentMutations.js.map +1 -1
  95. package/internal/validators/operation/documentSync.d.ts +26 -406
  96. package/internal/validators/operation/organizationPolicyHistory.d.ts +188 -310
  97. package/internal/validators/operation/organizationPolicyHistory.js +17 -3
  98. package/internal/validators/operation/organizationPolicyHistory.js.map +1 -1
  99. package/internal/validators/response/containerMutationError.d.ts +28 -408
  100. package/internal/validators/response/documentMutation.d.ts +232 -544
  101. package/internal/validators/response/documentMutation.js +1 -2
  102. package/internal/validators/response/documentMutation.js.map +1 -1
  103. package/internal/validators/response/documentSyncError.d.ts +26 -406
  104. package/internal/validators/response/documentSyncError.js +4 -3
  105. package/internal/validators/response/documentSyncError.js.map +1 -1
  106. package/internal/validators/response/index.d.ts +1 -1
  107. package/internal/validators/response/index.js +1 -1
  108. package/internal/validators/response/index.js.map +1 -1
  109. package/internal/validators/response/organizationPolicyHistory.d.ts +127 -309
  110. package/internal/validators/response/organizationPolicyHistory.js +10 -4
  111. package/internal/validators/response/organizationPolicyHistory.js.map +1 -1
  112. package/internal/validators/response/principal.d.ts +28 -408
  113. package/internal/validators/response/principal.js +3 -1
  114. package/internal/validators/response/principal.js.map +1 -1
  115. package/internal/validators/util/index.d.ts +1 -1
  116. package/internal/validators/util/index.js +1 -1
  117. package/internal/validators/util/index.js.map +1 -1
  118. package/internal/validators/util/principalHistoryWire.d.ts +2 -0
  119. package/internal/validators/util/principalHistoryWire.js +2 -0
  120. package/internal/validators/util/principalHistoryWire.js.map +1 -1
  121. package/package.json +1 -1
  122. package/workflows/container-contents/container-state/createWithMetadata.js +19 -49
  123. package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
  124. package/workflows/container-contents/container-state/groupGrantVerification.js +29 -0
  125. package/workflows/container-contents/container-state/groupGrantVerification.js.map +1 -1
  126. package/workflows/container-contents/container-state/groupShareEpoch.js +33 -0
  127. package/workflows/container-contents/container-state/groupShareEpoch.js.map +1 -0
  128. package/workflows/container-contents/container-state/remote.js +4 -1
  129. package/workflows/container-contents/container-state/remote.js.map +1 -1
  130. package/workflows/container-contents/container-state/share.js +2 -24
  131. package/workflows/container-contents/container-state/share.js.map +1 -1
  132. package/workflows/container-contents/documentTombstoneEvidence.js +23 -12
  133. package/workflows/container-contents/documentTombstoneEvidence.js.map +1 -1
  134. package/workflows/containers/child/create.js +1 -3
  135. package/workflows/containers/child/create.js.map +1 -1
  136. package/workflows/containers/child/createSubmission.d.ts +1 -3
  137. package/workflows/containers/child/createSubmission.js +13 -15
  138. package/workflows/containers/child/createSubmission.js.map +1 -1
  139. package/workflows/containers/child/currentShareGrantMutation.js +82 -0
  140. package/workflows/containers/child/currentShareGrantMutation.js.map +1 -0
  141. package/workflows/containers/child/currentSharePrincipalPolicy.js +83 -0
  142. package/workflows/containers/child/currentSharePrincipalPolicy.js.map +1 -0
  143. package/workflows/containers/child/mutationSubmit.js +1 -1
  144. package/workflows/containers/child/mutationSubmit.js.map +1 -1
  145. package/workflows/containers/child/runtimeCurrentGroupShare.js +82 -0
  146. package/workflows/containers/child/runtimeCurrentGroupShare.js.map +1 -0
  147. package/workflows/containers/child/share.js +1 -14
  148. package/workflows/containers/child/share.js.map +1 -1
  149. package/workflows/containers/child/shareProjection.js +15 -0
  150. package/workflows/containers/child/shareProjection.js.map +1 -0
  151. package/workflows/documents/purge.d.ts +3 -0
  152. package/workflows/documents/purge.js +13 -0
  153. package/workflows/documents/purge.js.map +1 -1
  154. package/workflows/documents/sync.js +2 -0
  155. package/workflows/documents/sync.js.map +1 -1
  156. package/workflows/documents/syncFailures.js +2 -2
  157. package/workflows/documents/syncFailures.js.map +1 -1
  158. package/workflows/documents/syncPolicyRepair.js +15 -13
  159. package/workflows/documents/syncPolicyRepair.js.map +1 -1
  160. package/workflows/organizations/initialPrincipalCurrentPublication.js +2 -0
  161. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -1
  162. package/workflows/organizations/loadPolicyHistoryDetails.js +31 -32
  163. package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
  164. package/workflows/organizations/organizationPolicyHistoryDetails.js +37 -15
  165. package/workflows/organizations/organizationPolicyHistoryDetails.js.map +1 -1
  166. package/workflows/organizations/organizationPolicyHistoryVerification.js +56 -69
  167. package/workflows/organizations/organizationPolicyHistoryVerification.js.map +1 -1
  168. package/workflows/organizations/policyHistoryCache.js +5 -2
  169. package/workflows/organizations/policyHistoryCache.js.map +1 -1
  170. package/workflows/organizations/policyHistoryTypes.d.ts +1 -0
  171. package/workflows/organizations/policyHistoryTypes.js.map +1 -1
  172. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +4 -1
  173. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
  174. package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +0 -1
  175. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +1 -2
  176. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -1
  177. package/workflows/principals/policyRepair.js +38 -0
  178. package/workflows/principals/policyRepair.js.map +1 -0
  179. package/workflows/principals/policyRepairBudget.d.ts +2 -2
  180. package/workflows/principals/policyRepairBudget.js +3 -3
  181. package/workflows/principals/policyRepairBudget.js.map +1 -1
  182. package/workflows/principals/principalHistoryRecoveryPrefix.js +4 -0
  183. package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -1
  184. package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
  185. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
  186. package/workflows/principals/publicPrincipalHistoryPage.js +1 -0
  187. package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -1
  188. package/workflows/principals/publicPrincipalHistoryProgress.js +1 -0
  189. package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -1
  190. package/workflows/principals/publicPrincipalHistoryTypes.d.ts +2 -0
  191. package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -1
  192. package/workflows/principals/publicProjectionPrincipal.js +1 -0
  193. package/workflows/principals/publicProjectionPrincipal.js.map +1 -1
  194. package/workflows/principals/recoverPrincipalHistoryPage.js +2 -1
  195. package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -1
  196. package/workflows/principals/recoverPrincipalPolicyHistory.js +1 -0
  197. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  198. package/workflows/principals/recoverPublicPrincipalHistory.js +2 -0
  199. package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
  200. package/workflows/principals/runtimePolicyRecovery.js +2 -1
  201. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  202. package/workflows/principals/selectPublicPrincipalHistory.js +21 -15
  203. package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -1
  204. package/workflows/sync/remoteResetPrincipalScope.js +6 -0
  205. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  206. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js +0 -208
  207. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js.map +0 -1
  208. package/data/keyingProjectionVerification/snapshotVerificationCache.js +0 -39
  209. package/data/keyingProjectionVerification/snapshotVerificationCache.js.map +0 -1
  210. package/workflows/containers/child/policyRepair.js +0 -23
  211. package/workflows/containers/child/policyRepair.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"principalHistoryPrefixPersistence.js","sourceRoot":"","sources":["principalHistoryPrefixPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { assertProjectionVerificationCurrent } from \"../keyingProjectionVerification/types\";\nimport {\n principalHistoryEvidenceTables,\n principalHistoryPrefixes,\n} from \"../sqlite/principalHistoryEvidenceSchema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nexport type PrincipalHistoryPrefix =\n typeof principalHistoryPrefixes.$inferSelect;\n\nexport async function loadPrincipalHistoryPrefix(\n execSql: ExecSql,\n scopeId: string,\n) {\n await ensureSqlTables(execSql, principalHistoryEvidenceTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [prefix] = await db\n .select()\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, scopeId))\n .limit(1);\n return prefix ?? null;\n}\n\n/** Keep the newest prefix unless replay replaces the exact rejected candidate. */\nexport async function savePrincipalHistoryPrefix(input: {\n readonly execSql: ExecSql;\n readonly prefix: PrincipalHistoryPrefix;\n readonly stillCurrent: () => boolean;\n readonly rejectedPrefix?: PrincipalHistoryPrefix | null;\n}): Promise<void> {\n const prefix = { ...input.prefix };\n const rejected = input.rejectedPrefix ? { ...input.rejectedPrefix } : null;\n await ensureSqlTables(input.execSql, principalHistoryEvidenceTables);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n const [previous] = await tx\n .select()\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, prefix.scopeId))\n .limit(1);\n if (\n previous &&\n previous.version > prefix.version &&\n !(\n rejected?.scopeId === previous.scopeId &&\n rejected.progress === previous.progress\n )\n )\n return;\n await tx\n .insert(principalHistoryPrefixes)\n .values(prefix)\n .onConflictDoUpdate({\n target: principalHistoryPrefixes.scopeId,\n set: prefix,\n })\n .run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n\n/** Invalid hints are disposable, but a losing reader must preserve a newer hint. */\nexport async function discardPrincipalHistoryPrefix(input: {\n readonly execSql: ExecSql;\n readonly prefix: PrincipalHistoryPrefix;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const prefix = { ...input.prefix };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n await tx\n .delete(principalHistoryPrefixes)\n .where(\n and(\n eq(principalHistoryPrefixes.scopeId, prefix.scopeId),\n eq(principalHistoryPrefixes.progress, prefix.progress),\n ),\n )\n .run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n"]}
1
+ {"version":3,"file":"principalHistoryPrefixPersistence.js","sourceRoot":"","sources":["principalHistoryPrefixPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { assertProjectionVerificationCurrent } from \"../keyingProjectionVerification/types\";\nimport {\n principalHistoryEvidenceTables,\n principalHistoryPrefixes,\n} from \"../sqlite/principalHistoryEvidenceSchema\";\nimport { principalHistoryStageTables } from \"../sqlite/principalHistoryStageSchema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport { reclaimPrincipalHistoryNodes } from \"./principalHistoryNodeRetention\";\nimport {\n releasePrincipalHistoryRoot,\n retainPrincipalHistoryRoot,\n} from \"./principalHistoryRootOwnership\";\nimport { reclaimCompletedPrincipalHistoryStages } from \"./principalHistoryStageRetention\";\nimport { archivePrincipalHistoryKeyEnvelopes } from \"./principalKeyEnvelopeArchivePersistence\";\n\nexport type PrincipalHistoryPrefix =\n typeof principalHistoryPrefixes.$inferSelect;\n\nexport async function loadPrincipalHistoryPrefix(\n execSql: ExecSql,\n scopeId: string,\n) {\n await ensureSqlTables(execSql, principalHistoryEvidenceTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [prefix] = await db\n .select()\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, scopeId))\n .limit(1);\n return prefix ?? null;\n}\n\n/** Keep the newest prefix unless replay replaces the exact rejected candidate. */\nexport async function savePrincipalHistoryPrefix(input: {\n readonly execSql: ExecSql;\n readonly prefix: PrincipalHistoryPrefix;\n readonly indexRootHash: string;\n readonly stillCurrent: () => boolean;\n readonly rejectedPrefix?: PrincipalHistoryPrefix | null;\n}): Promise<void> {\n const prefix = { ...input.prefix };\n const indexRootHash = input.indexRootHash;\n const rejected = input.rejectedPrefix ? { ...input.rejectedPrefix } : null;\n await ensureSqlTables(input.execSql, [\n ...principalHistoryEvidenceTables,\n ...principalHistoryStageTables,\n ]);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n const [previous] = await tx\n .select()\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, prefix.scopeId))\n .limit(1);\n if (\n previous &&\n previous.version > prefix.version &&\n !(\n rejected?.scopeId === previous.scopeId &&\n rejected.progress === previous.progress\n )\n )\n return;\n if (previous) await archivePrincipalHistoryKeyEnvelopes(tx, previous);\n await archivePrincipalHistoryKeyEnvelopes(tx, prefix);\n await tx\n .insert(principalHistoryPrefixes)\n .values(prefix)\n .onConflictDoUpdate({\n target: principalHistoryPrefixes.scopeId,\n set: prefix,\n })\n .run();\n await reclaimCompletedPrincipalHistoryStages(tx, prefix);\n await retainPrincipalHistoryRoot(tx, {\n id: `prefix:${prefix.scopeId}`,\n scopeId: prefix.scopeId,\n organizationId: prefix.organizationId,\n rootHash: indexRootHash,\n });\n await reclaimPrincipalHistoryNodes(tx, prefix);\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n\n/** Invalid hints are disposable, but a losing reader must preserve a newer hint. */\nexport async function discardPrincipalHistoryPrefix(input: {\n readonly execSql: ExecSql;\n readonly prefix: PrincipalHistoryPrefix;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const prefix = { ...input.prefix };\n await ensureSqlTables(input.execSql, principalHistoryEvidenceTables);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n const [current] = await tx\n .select({ progress: principalHistoryPrefixes.progress })\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, prefix.scopeId))\n .limit(1);\n if (current?.progress !== prefix.progress) return;\n await releasePrincipalHistoryRoot(tx, `prefix:${prefix.scopeId}`);\n await tx\n .delete(principalHistoryPrefixes)\n .where(\n and(\n eq(principalHistoryPrefixes.scopeId, prefix.scopeId),\n eq(principalHistoryPrefixes.progress, prefix.progress),\n ),\n )\n .run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import { and, eq, sql } from "drizzle-orm";
2
+ import { principalHistoryNodeReferences, principalHistoryRootOwners, } from "../sqlite/principalHistoryNodeRetentionSchema.js";
3
+ export async function incrementPrincipalHistoryNodeReference(tx, scope, hash) {
4
+ await tx
5
+ .insert(principalHistoryNodeReferences)
6
+ .values({
7
+ ...scope,
8
+ hash,
9
+ referenceCount: 1,
10
+ managed: false,
11
+ leftHash: null,
12
+ rightHash: null,
13
+ })
14
+ .onConflictDoUpdate({
15
+ target: [
16
+ principalHistoryNodeReferences.scopeId,
17
+ principalHistoryNodeReferences.hash,
18
+ ],
19
+ set: {
20
+ referenceCount: sql `${principalHistoryNodeReferences.referenceCount} + 1`,
21
+ },
22
+ })
23
+ .run();
24
+ }
25
+ export async function decrementPrincipalHistoryNodeReference(tx, scope, hash) {
26
+ await tx
27
+ .update(principalHistoryNodeReferences)
28
+ .set({
29
+ referenceCount: sql `max(${principalHistoryNodeReferences.referenceCount} - 1, 0)`,
30
+ })
31
+ .where(and(eq(principalHistoryNodeReferences.scopeId, scope.scopeId), eq(principalHistoryNodeReferences.organizationId, scope.organizationId), eq(principalHistoryNodeReferences.hash, hash)))
32
+ .run();
33
+ }
34
+ /** Caller commits ownership together with the exact saved progress it describes. */
35
+ export async function retainPrincipalHistoryRoot(tx, input) {
36
+ const [previous] = await tx
37
+ .select()
38
+ .from(principalHistoryRootOwners)
39
+ .where(eq(principalHistoryRootOwners.id, input.id))
40
+ .limit(1);
41
+ if (previous?.scopeId === input.scopeId &&
42
+ previous.organizationId === input.organizationId &&
43
+ previous.rootHash === input.rootHash)
44
+ return;
45
+ await incrementPrincipalHistoryNodeReference(tx, input, input.rootHash);
46
+ await tx
47
+ .insert(principalHistoryRootOwners)
48
+ .values(input)
49
+ .onConflictDoUpdate({
50
+ target: principalHistoryRootOwners.id,
51
+ set: input,
52
+ })
53
+ .run();
54
+ if (previous)
55
+ await decrementPrincipalHistoryNodeReference(tx, previous, previous.rootHash);
56
+ }
57
+ export async function releasePrincipalHistoryRoot(tx, id) {
58
+ const [previous] = await tx
59
+ .select()
60
+ .from(principalHistoryRootOwners)
61
+ .where(eq(principalHistoryRootOwners.id, id))
62
+ .limit(1);
63
+ if (!previous)
64
+ return;
65
+ await tx
66
+ .delete(principalHistoryRootOwners)
67
+ .where(eq(principalHistoryRootOwners.id, id))
68
+ .run();
69
+ await decrementPrincipalHistoryNodeReference(tx, previous, previous.rootHash);
70
+ }
71
+ //# sourceMappingURL=principalHistoryRootOwnership.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalHistoryRootOwnership.js","sourceRoot":"","sources":["principalHistoryRootOwnership.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, sql } from \"drizzle-orm\";\nimport {\n principalHistoryNodeReferences,\n principalHistoryRootOwners,\n} from \"../sqlite/principalHistoryNodeRetentionSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\n\nexport interface PrincipalHistoryNodeScope {\n /** Evidence scope hashes include organizationId; one scope belongs to one organization. */\n readonly scopeId: string;\n readonly organizationId: string;\n}\n\nexport async function incrementPrincipalHistoryNodeReference(\n tx: ClientSQLiteTransactionScope,\n scope: PrincipalHistoryNodeScope,\n hash: string,\n) {\n await tx\n .insert(principalHistoryNodeReferences)\n .values({\n ...scope,\n hash,\n referenceCount: 1,\n managed: false,\n leftHash: null,\n rightHash: null,\n })\n .onConflictDoUpdate({\n target: [\n principalHistoryNodeReferences.scopeId,\n principalHistoryNodeReferences.hash,\n ],\n set: {\n referenceCount: sql`${principalHistoryNodeReferences.referenceCount} + 1`,\n },\n })\n .run();\n}\n\nexport async function decrementPrincipalHistoryNodeReference(\n tx: ClientSQLiteTransactionScope,\n scope: PrincipalHistoryNodeScope,\n hash: string,\n) {\n await tx\n .update(principalHistoryNodeReferences)\n .set({\n referenceCount: sql`max(${principalHistoryNodeReferences.referenceCount} - 1, 0)`,\n })\n .where(\n and(\n eq(principalHistoryNodeReferences.scopeId, scope.scopeId),\n eq(principalHistoryNodeReferences.organizationId, scope.organizationId),\n eq(principalHistoryNodeReferences.hash, hash),\n ),\n )\n .run();\n}\n\n/** Caller commits ownership together with the exact saved progress it describes. */\nexport async function retainPrincipalHistoryRoot(\n tx: ClientSQLiteTransactionScope,\n input: PrincipalHistoryNodeScope & {\n readonly id: string;\n readonly rootHash: string;\n },\n) {\n const [previous] = await tx\n .select()\n .from(principalHistoryRootOwners)\n .where(eq(principalHistoryRootOwners.id, input.id))\n .limit(1);\n if (\n previous?.scopeId === input.scopeId &&\n previous.organizationId === input.organizationId &&\n previous.rootHash === input.rootHash\n )\n return;\n await incrementPrincipalHistoryNodeReference(tx, input, input.rootHash);\n await tx\n .insert(principalHistoryRootOwners)\n .values(input)\n .onConflictDoUpdate({\n target: principalHistoryRootOwners.id,\n set: input,\n })\n .run();\n if (previous)\n await decrementPrincipalHistoryNodeReference(\n tx,\n previous,\n previous.rootHash,\n );\n}\n\nexport async function releasePrincipalHistoryRoot(\n tx: ClientSQLiteTransactionScope,\n id: string,\n) {\n const [previous] = await tx\n .select()\n .from(principalHistoryRootOwners)\n .where(eq(principalHistoryRootOwners.id, id))\n .limit(1);\n if (!previous) return;\n await tx\n .delete(principalHistoryRootOwners)\n .where(eq(principalHistoryRootOwners.id, id))\n .run();\n await decrementPrincipalHistoryNodeReference(tx, previous, previous.rootHash);\n}\n"]}
@@ -1,10 +1,17 @@
1
1
  import { and, eq } from "drizzle-orm";
2
2
  import { assertProjectionVerificationCurrent } from "../keyingProjectionVerification/types.js";
3
3
  import { principalHistoryEvidenceTables } from "../sqlite/principalHistoryEvidenceSchema.js";
4
+ import { principalHistoryNodeRetentionTables } from "../sqlite/principalHistoryNodeRetentionSchema.js";
5
+ import { principalHistoryStageScopes } from "../sqlite/principalHistoryRetentionSchema.js";
4
6
  import { principalHistoryStages, principalHistoryStageTables, } from "../sqlite/principalHistoryStageSchema.js";
5
7
  import { getClientSQLitePersistenceRuntime } from "../sqlite/sqlitePersistenceRuntime.js";
6
8
  import { ensureSqlTables } from "../sqlite/sqlSchema.js";
7
9
  import { writePrincipalHistoryEvidencePage, } from "./principalHistoryEvidencePersistence.js";
10
+ import { reclaimIncompletePrincipalHistoryStages } from "./principalHistoryIncompleteRetention.js";
11
+ import { reclaimPrincipalHistoryNodes } from "./principalHistoryNodeRetention.js";
12
+ import { releasePrincipalHistoryRoot, retainPrincipalHistoryRoot, } from "./principalHistoryRootOwnership.js";
13
+ import { recordPrincipalHistoryStageScope } from "./principalHistoryStageRetention.js";
14
+ import { reclaimUnpublishedPrincipalHistoryStages } from "./principalHistoryUnpublishedRetention.js";
8
15
  class PrincipalHistoryStageChangedError extends Error {
9
16
  code = "principal_history_stage_changed";
10
17
  constructor() {
@@ -45,16 +52,54 @@ export async function savePrincipalHistoryStage(input) {
45
52
  .values(stage)
46
53
  .onConflictDoUpdate({ target: principalHistoryStages.id, set: stage })
47
54
  .run();
55
+ await recordPrincipalHistoryStageScope(tx, {
56
+ id: stage.id,
57
+ afterVersion: stage.afterVersion,
58
+ complete: stage.complete,
59
+ organizationId: stage.organizationId,
60
+ scopeId: evidence.scopeId,
61
+ });
62
+ await retainPrincipalHistoryRoot(tx, {
63
+ id: `stage:${stage.id}`,
64
+ scopeId: evidence.scopeId,
65
+ organizationId: stage.organizationId,
66
+ rootHash: evidence.indexRootHash,
67
+ });
68
+ await reclaimIncompletePrincipalHistoryStages(tx, {
69
+ ...stage,
70
+ scopeId: evidence.scopeId,
71
+ });
72
+ await reclaimUnpublishedPrincipalHistoryStages(tx, {
73
+ ...stage,
74
+ scopeId: evidence.scopeId,
75
+ });
76
+ await reclaimPrincipalHistoryNodes(tx, evidence);
48
77
  }, input.stillCurrent, { behavior: "immediate" });
49
78
  assertProjectionVerificationCurrent(() => saved.committed);
50
79
  }
51
80
  export async function discardPrincipalHistoryStage(execSql, stage, stillCurrent) {
81
+ await ensureSqlTables(execSql, [
82
+ ...principalHistoryStageTables,
83
+ ...principalHistoryNodeRetentionTables,
84
+ ]);
52
85
  const runtime = getClientSQLitePersistenceRuntime(execSql);
53
86
  const discarded = await runtime.guardedTransaction(async (db) => {
87
+ const [current] = await db
88
+ .select({ progress: principalHistoryStages.progress })
89
+ .from(principalHistoryStages)
90
+ .where(eq(principalHistoryStages.id, stage.id))
91
+ .limit(1);
92
+ if (current?.progress !== stage.progress)
93
+ return;
94
+ await releasePrincipalHistoryRoot(db, `stage:${stage.id}`);
54
95
  await db
55
96
  .delete(principalHistoryStages)
56
97
  .where(and(eq(principalHistoryStages.id, stage.id), eq(principalHistoryStages.progress, stage.progress)))
57
98
  .run();
99
+ await db
100
+ .delete(principalHistoryStageScopes)
101
+ .where(eq(principalHistoryStageScopes.id, stage.id))
102
+ .run();
58
103
  }, stillCurrent, { behavior: "immediate" });
59
104
  assertProjectionVerificationCurrent(() => discarded.committed);
60
105
  }
@@ -1 +1 @@
1
- {"version":3,"file":"principalHistoryStagePersistence.js","sourceRoot":"","sources":["principalHistoryStagePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { assertProjectionVerificationCurrent } from \"../keyingProjectionVerification/types\";\nimport { principalHistoryEvidenceTables } from \"../sqlite/principalHistoryEvidenceSchema\";\nimport {\n principalHistoryStages,\n principalHistoryStageTables,\n} from \"../sqlite/principalHistoryStageSchema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport {\n type PrincipalHistoryEvidencePage,\n writePrincipalHistoryEvidencePage,\n} from \"./principalHistoryEvidencePersistence\";\n\nexport type PrincipalHistoryStage = typeof principalHistoryStages.$inferSelect;\n\nclass PrincipalHistoryStageChangedError extends Error {\n readonly code = \"principal_history_stage_changed\";\n constructor() {\n super(\n \"Another operation changed the saved principal history; resume from its current state\",\n );\n this.name = \"PrincipalHistoryStageChangedError\";\n }\n}\n\nexport async function loadPrincipalHistoryStage(execSql: ExecSql, id: string) {\n await ensureSqlTables(execSql, principalHistoryStageTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [row] = await db\n .select()\n .from(principalHistoryStages)\n .where(eq(principalHistoryStages.id, id))\n .limit(1);\n return row ?? null;\n}\n\n/** Publish accepted entries and index nodes atomically with authenticated progress. */\nexport async function savePrincipalHistoryStage(input: {\n readonly execSql: ExecSql;\n readonly stage: PrincipalHistoryStage;\n readonly evidence: PrincipalHistoryEvidencePage;\n readonly previousProgress: string | null;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const stage = { ...input.stage };\n const evidence = structuredClone(input.evidence);\n await ensureSqlTables(input.execSql, [\n ...principalHistoryStageTables,\n ...principalHistoryEvidenceTables,\n ]);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const saved = await runtime.guardedTransaction(\n async (tx) => {\n const [previous] = await tx\n .select({ progress: principalHistoryStages.progress })\n .from(principalHistoryStages)\n .where(eq(principalHistoryStages.id, stage.id))\n .limit(1);\n if ((previous?.progress ?? null) !== input.previousProgress)\n throw new PrincipalHistoryStageChangedError();\n await writePrincipalHistoryEvidencePage(tx, evidence);\n await tx\n .insert(principalHistoryStages)\n .values(stage)\n .onConflictDoUpdate({ target: principalHistoryStages.id, set: stage })\n .run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => saved.committed);\n}\n\nexport async function discardPrincipalHistoryStage(\n execSql: ExecSql,\n stage: PrincipalHistoryStage,\n stillCurrent: () => boolean,\n) {\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const discarded = await runtime.guardedTransaction(\n async (db) => {\n await db\n .delete(principalHistoryStages)\n .where(\n and(\n eq(principalHistoryStages.id, stage.id),\n eq(principalHistoryStages.progress, stage.progress),\n ),\n )\n .run();\n },\n stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => discarded.committed);\n}\n"]}
1
+ {"version":3,"file":"principalHistoryStagePersistence.js","sourceRoot":"","sources":["principalHistoryStagePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { assertProjectionVerificationCurrent } from \"../keyingProjectionVerification/types\";\nimport { principalHistoryEvidenceTables } from \"../sqlite/principalHistoryEvidenceSchema\";\nimport { principalHistoryNodeRetentionTables } from \"../sqlite/principalHistoryNodeRetentionSchema\";\nimport { principalHistoryStageScopes } from \"../sqlite/principalHistoryRetentionSchema\";\nimport {\n principalHistoryStages,\n principalHistoryStageTables,\n} from \"../sqlite/principalHistoryStageSchema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport {\n type PrincipalHistoryEvidencePage,\n writePrincipalHistoryEvidencePage,\n} from \"./principalHistoryEvidencePersistence\";\nimport { reclaimIncompletePrincipalHistoryStages } from \"./principalHistoryIncompleteRetention\";\nimport { reclaimPrincipalHistoryNodes } from \"./principalHistoryNodeRetention\";\nimport {\n releasePrincipalHistoryRoot,\n retainPrincipalHistoryRoot,\n} from \"./principalHistoryRootOwnership\";\nimport { recordPrincipalHistoryStageScope } from \"./principalHistoryStageRetention\";\nimport { reclaimUnpublishedPrincipalHistoryStages } from \"./principalHistoryUnpublishedRetention\";\n\nexport type PrincipalHistoryStage = typeof principalHistoryStages.$inferSelect;\n\nclass PrincipalHistoryStageChangedError extends Error {\n readonly code = \"principal_history_stage_changed\";\n constructor() {\n super(\n \"Another operation changed the saved principal history; resume from its current state\",\n );\n this.name = \"PrincipalHistoryStageChangedError\";\n }\n}\n\nexport async function loadPrincipalHistoryStage(execSql: ExecSql, id: string) {\n await ensureSqlTables(execSql, principalHistoryStageTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [row] = await db\n .select()\n .from(principalHistoryStages)\n .where(eq(principalHistoryStages.id, id))\n .limit(1);\n return row ?? null;\n}\n\n/** Publish accepted entries and index nodes atomically with authenticated progress. */\nexport async function savePrincipalHistoryStage(input: {\n readonly execSql: ExecSql;\n readonly stage: PrincipalHistoryStage;\n readonly evidence: PrincipalHistoryEvidencePage;\n readonly previousProgress: string | null;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const stage = { ...input.stage };\n const evidence = structuredClone(input.evidence);\n await ensureSqlTables(input.execSql, [\n ...principalHistoryStageTables,\n ...principalHistoryEvidenceTables,\n ]);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const saved = await runtime.guardedTransaction(\n async (tx) => {\n const [previous] = await tx\n .select({ progress: principalHistoryStages.progress })\n .from(principalHistoryStages)\n .where(eq(principalHistoryStages.id, stage.id))\n .limit(1);\n if ((previous?.progress ?? null) !== input.previousProgress)\n throw new PrincipalHistoryStageChangedError();\n await writePrincipalHistoryEvidencePage(tx, evidence);\n await tx\n .insert(principalHistoryStages)\n .values(stage)\n .onConflictDoUpdate({ target: principalHistoryStages.id, set: stage })\n .run();\n await recordPrincipalHistoryStageScope(tx, {\n id: stage.id,\n afterVersion: stage.afterVersion,\n complete: stage.complete,\n organizationId: stage.organizationId,\n scopeId: evidence.scopeId,\n });\n await retainPrincipalHistoryRoot(tx, {\n id: `stage:${stage.id}`,\n scopeId: evidence.scopeId,\n organizationId: stage.organizationId,\n rootHash: evidence.indexRootHash,\n });\n await reclaimIncompletePrincipalHistoryStages(tx, {\n ...stage,\n scopeId: evidence.scopeId,\n });\n await reclaimUnpublishedPrincipalHistoryStages(tx, {\n ...stage,\n scopeId: evidence.scopeId,\n });\n await reclaimPrincipalHistoryNodes(tx, evidence);\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => saved.committed);\n}\n\nexport async function discardPrincipalHistoryStage(\n execSql: ExecSql,\n stage: PrincipalHistoryStage,\n stillCurrent: () => boolean,\n) {\n await ensureSqlTables(execSql, [\n ...principalHistoryStageTables,\n ...principalHistoryNodeRetentionTables,\n ]);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const discarded = await runtime.guardedTransaction(\n async (db) => {\n const [current] = await db\n .select({ progress: principalHistoryStages.progress })\n .from(principalHistoryStages)\n .where(eq(principalHistoryStages.id, stage.id))\n .limit(1);\n if (current?.progress !== stage.progress) return;\n await releasePrincipalHistoryRoot(db, `stage:${stage.id}`);\n await db\n .delete(principalHistoryStages)\n .where(\n and(\n eq(principalHistoryStages.id, stage.id),\n eq(principalHistoryStages.progress, stage.progress),\n ),\n )\n .run();\n await db\n .delete(principalHistoryStageScopes)\n .where(eq(principalHistoryStageScopes.id, stage.id))\n .run();\n },\n stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => discarded.committed);\n}\n"]}
@@ -0,0 +1,44 @@
1
+ import { and, asc, desc, eq, lt } from "drizzle-orm";
2
+ import { principalHistoryStageScopes } from "../sqlite/principalHistoryRetentionSchema.js";
3
+ import { principalHistoryStages } from "../sqlite/principalHistoryStageSchema.js";
4
+ import { releasePrincipalHistoryRoot } from "./principalHistoryRootOwnership.js";
5
+ import { archivePrincipalHistoryKeyEnvelopes } from "./principalKeyEnvelopeArchivePersistence.js";
6
+ /** Each publication reclaims at most this many obsolete completed heads. */
7
+ export const PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT = 16;
8
+ export async function recordPrincipalHistoryStageScope(tx, input) {
9
+ const row = { ...input, touchedAt: Date.now() };
10
+ await tx
11
+ .insert(principalHistoryStageScopes)
12
+ .values(row)
13
+ .onConflictDoUpdate({ target: principalHistoryStageScopes.id, set: row })
14
+ .run();
15
+ }
16
+ /** The prefix and its key candidates must be published in this transaction. */
17
+ export async function reclaimCompletedPrincipalHistoryStages(tx, prefix) {
18
+ const obsolete = await tx
19
+ .select({ stage: principalHistoryStages })
20
+ .from(principalHistoryStageScopes)
21
+ .innerJoin(principalHistoryStages, eq(principalHistoryStageScopes.id, principalHistoryStages.id))
22
+ .where(and(eq(principalHistoryStageScopes.scopeId, prefix.scopeId), eq(principalHistoryStageScopes.organizationId, prefix.organizationId), eq(principalHistoryStageScopes.complete, true), lt(principalHistoryStageScopes.afterVersion, prefix.version), eq(principalHistoryStages.organizationId, prefix.organizationId), eq(principalHistoryStages.complete, true), lt(principalHistoryStages.afterVersion, prefix.version)))
23
+ .orderBy(desc(principalHistoryStageScopes.afterVersion), desc(principalHistoryStageScopes.touchedAt), asc(principalHistoryStageScopes.id))
24
+ // Keep the current completed head and its newest completed predecessor.
25
+ // This also preserves the prefix-only predecessor restored after an ack.
26
+ .offset(2)
27
+ .limit(PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT);
28
+ for (const { stage } of obsolete) {
29
+ await releasePrincipalHistoryRoot(tx, `stage:${stage.id}`);
30
+ await archivePrincipalHistoryKeyEnvelopes(tx, {
31
+ ...stage,
32
+ version: stage.afterVersion + 1,
33
+ });
34
+ await tx
35
+ .delete(principalHistoryStages)
36
+ .where(eq(principalHistoryStages.id, stage.id))
37
+ .run();
38
+ await tx
39
+ .delete(principalHistoryStageScopes)
40
+ .where(eq(principalHistoryStageScopes.id, stage.id))
41
+ .run();
42
+ }
43
+ }
44
+ //# sourceMappingURL=principalHistoryStageRetention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalHistoryStageRetention.js","sourceRoot":"","sources":["principalHistoryStageRetention.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, asc, desc, eq, lt } from \"drizzle-orm\";\nimport { principalHistoryStageScopes } from \"../sqlite/principalHistoryRetentionSchema\";\nimport { principalHistoryStages } from \"../sqlite/principalHistoryStageSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { releasePrincipalHistoryRoot } from \"./principalHistoryRootOwnership\";\nimport { archivePrincipalHistoryKeyEnvelopes } from \"./principalKeyEnvelopeArchivePersistence\";\n\n/** Each publication reclaims at most this many obsolete completed heads. */\nexport const PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT = 16;\n\nexport async function recordPrincipalHistoryStageScope(\n tx: ClientSQLiteTransactionScope,\n input: {\n readonly id: string;\n readonly organizationId: string;\n readonly scopeId: string;\n readonly afterVersion: number;\n readonly complete: boolean;\n },\n) {\n const row = { ...input, touchedAt: Date.now() };\n await tx\n .insert(principalHistoryStageScopes)\n .values(row)\n .onConflictDoUpdate({ target: principalHistoryStageScopes.id, set: row })\n .run();\n}\n\n/** The prefix and its key candidates must be published in this transaction. */\nexport async function reclaimCompletedPrincipalHistoryStages(\n tx: ClientSQLiteTransactionScope,\n prefix: {\n readonly scopeId: string;\n readonly organizationId: string;\n readonly version: number;\n },\n) {\n const obsolete = await tx\n .select({ stage: principalHistoryStages })\n .from(principalHistoryStageScopes)\n .innerJoin(\n principalHistoryStages,\n eq(principalHistoryStageScopes.id, principalHistoryStages.id),\n )\n .where(\n and(\n eq(principalHistoryStageScopes.scopeId, prefix.scopeId),\n eq(principalHistoryStageScopes.organizationId, prefix.organizationId),\n eq(principalHistoryStageScopes.complete, true),\n lt(principalHistoryStageScopes.afterVersion, prefix.version),\n eq(principalHistoryStages.organizationId, prefix.organizationId),\n eq(principalHistoryStages.complete, true),\n lt(principalHistoryStages.afterVersion, prefix.version),\n ),\n )\n .orderBy(\n desc(principalHistoryStageScopes.afterVersion),\n desc(principalHistoryStageScopes.touchedAt),\n asc(principalHistoryStageScopes.id),\n )\n // Keep the current completed head and its newest completed predecessor.\n // This also preserves the prefix-only predecessor restored after an ack.\n .offset(2)\n .limit(PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT);\n for (const { stage } of obsolete) {\n await releasePrincipalHistoryRoot(tx, `stage:${stage.id}`);\n await archivePrincipalHistoryKeyEnvelopes(tx, {\n ...stage,\n version: stage.afterVersion + 1,\n });\n await tx\n .delete(principalHistoryStages)\n .where(eq(principalHistoryStages.id, stage.id))\n .run();\n await tx\n .delete(principalHistoryStageScopes)\n .where(eq(principalHistoryStageScopes.id, stage.id))\n .run();\n }\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import { and, asc, desc, eq, inArray, lt, notInArray } from "drizzle-orm";
2
+ import { principalHistoryPrefixes } from "../sqlite/principalHistoryEvidenceSchema.js";
3
+ import { principalHistoryStageScopes } from "../sqlite/principalHistoryRetentionSchema.js";
4
+ import { principalHistoryStages } from "../sqlite/principalHistoryStageSchema.js";
5
+ import { releasePrincipalHistoryRoot } from "./principalHistoryRootOwnership.js";
6
+ import { PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT } from "./principalHistoryStageRetention.js";
7
+ import { archivePrincipalHistoryKeyEnvelopes } from "./principalKeyEnvelopeArchivePersistence.js";
8
+ const COMPLETED_STAGE_LIMIT = 8;
9
+ function matchingCompletedStages(current) {
10
+ return and(eq(principalHistoryStageScopes.scopeId, current.scopeId), eq(principalHistoryStageScopes.organizationId, current.organizationId), eq(principalHistoryStageScopes.complete, true), eq(principalHistoryStages.organizationId, current.organizationId), eq(principalHistoryStages.complete, true), eq(principalHistoryStages.afterVersion, principalHistoryStageScopes.afterVersion));
11
+ }
12
+ async function protectedPublishedStages(tx, current) {
13
+ const [prefix] = await tx
14
+ .select({ version: principalHistoryPrefixes.version })
15
+ .from(principalHistoryPrefixes)
16
+ .where(and(eq(principalHistoryPrefixes.scopeId, current.scopeId), eq(principalHistoryPrefixes.organizationId, current.organizationId)))
17
+ .limit(1);
18
+ if (!prefix)
19
+ return [];
20
+ return tx
21
+ .select({ id: principalHistoryStages.id })
22
+ .from(principalHistoryStageScopes)
23
+ .innerJoin(principalHistoryStages, eq(principalHistoryStageScopes.id, principalHistoryStages.id))
24
+ .where(and(matchingCompletedStages(current), lt(principalHistoryStageScopes.afterVersion, prefix.version)))
25
+ .orderBy(desc(principalHistoryStageScopes.afterVersion), desc(principalHistoryStageScopes.touchedAt), asc(principalHistoryStageScopes.id))
26
+ .limit(2);
27
+ }
28
+ /** Bound completed attempts even when current-artifact verification never publishes. */
29
+ export async function reclaimUnpublishedPrincipalHistoryStages(tx, current) {
30
+ if (!current.complete)
31
+ return;
32
+ const published = await protectedPublishedStages(tx, current);
33
+ const protectedIds = [
34
+ ...new Set([current.id, ...published.map(({ id }) => id)]),
35
+ ];
36
+ const obsolete = await tx
37
+ .select({
38
+ stage: {
39
+ id: principalHistoryStages.id,
40
+ organizationId: principalHistoryStages.organizationId,
41
+ currentJson: principalHistoryStages.currentJson,
42
+ afterVersion: principalHistoryStages.afterVersion,
43
+ },
44
+ })
45
+ .from(principalHistoryStageScopes)
46
+ .innerJoin(principalHistoryStages, eq(principalHistoryStageScopes.id, principalHistoryStages.id))
47
+ .where(and(matchingCompletedStages(current), notInArray(principalHistoryStages.id, protectedIds)))
48
+ // The existing "incomplete" index also covers completed scoped recency.
49
+ .orderBy(desc(principalHistoryStageScopes.touchedAt), asc(principalHistoryStageScopes.id))
50
+ .offset(COMPLETED_STAGE_LIMIT - protectedIds.length)
51
+ .limit(PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT);
52
+ if (obsolete.length === 0)
53
+ return;
54
+ for (const { stage } of obsolete)
55
+ await archivePrincipalHistoryKeyEnvelopes(tx, {
56
+ ...stage,
57
+ version: stage.afterVersion + 1,
58
+ });
59
+ const ids = obsolete.map(({ stage }) => stage.id);
60
+ for (const id of ids)
61
+ await releasePrincipalHistoryRoot(tx, `stage:${id}`);
62
+ await tx
63
+ .delete(principalHistoryStages)
64
+ .where(inArray(principalHistoryStages.id, ids))
65
+ .run();
66
+ await tx
67
+ .delete(principalHistoryStageScopes)
68
+ .where(inArray(principalHistoryStageScopes.id, ids))
69
+ .run();
70
+ }
71
+ //# sourceMappingURL=principalHistoryUnpublishedRetention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalHistoryUnpublishedRetention.js","sourceRoot":"","sources":["principalHistoryUnpublishedRetention.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, asc, desc, eq, inArray, lt, notInArray } from \"drizzle-orm\";\nimport { principalHistoryPrefixes } from \"../sqlite/principalHistoryEvidenceSchema\";\nimport { principalHistoryStageScopes } from \"../sqlite/principalHistoryRetentionSchema\";\nimport { principalHistoryStages } from \"../sqlite/principalHistoryStageSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { releasePrincipalHistoryRoot } from \"./principalHistoryRootOwnership\";\nimport { PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT } from \"./principalHistoryStageRetention\";\nimport { archivePrincipalHistoryKeyEnvelopes } from \"./principalKeyEnvelopeArchivePersistence\";\n\nconst COMPLETED_STAGE_LIMIT = 8;\n\ninterface CompletedWriter {\n readonly id: string;\n readonly scopeId: string;\n readonly organizationId: string;\n readonly complete: boolean;\n}\n\nfunction matchingCompletedStages(current: CompletedWriter) {\n return and(\n eq(principalHistoryStageScopes.scopeId, current.scopeId),\n eq(principalHistoryStageScopes.organizationId, current.organizationId),\n eq(principalHistoryStageScopes.complete, true),\n eq(principalHistoryStages.organizationId, current.organizationId),\n eq(principalHistoryStages.complete, true),\n eq(\n principalHistoryStages.afterVersion,\n principalHistoryStageScopes.afterVersion,\n ),\n );\n}\n\nasync function protectedPublishedStages(\n tx: ClientSQLiteTransactionScope,\n current: CompletedWriter,\n) {\n const [prefix] = await tx\n .select({ version: principalHistoryPrefixes.version })\n .from(principalHistoryPrefixes)\n .where(\n and(\n eq(principalHistoryPrefixes.scopeId, current.scopeId),\n eq(principalHistoryPrefixes.organizationId, current.organizationId),\n ),\n )\n .limit(1);\n if (!prefix) return [];\n return tx\n .select({ id: principalHistoryStages.id })\n .from(principalHistoryStageScopes)\n .innerJoin(\n principalHistoryStages,\n eq(principalHistoryStageScopes.id, principalHistoryStages.id),\n )\n .where(\n and(\n matchingCompletedStages(current),\n lt(principalHistoryStageScopes.afterVersion, prefix.version),\n ),\n )\n .orderBy(\n desc(principalHistoryStageScopes.afterVersion),\n desc(principalHistoryStageScopes.touchedAt),\n asc(principalHistoryStageScopes.id),\n )\n .limit(2);\n}\n\n/** Bound completed attempts even when current-artifact verification never publishes. */\nexport async function reclaimUnpublishedPrincipalHistoryStages(\n tx: ClientSQLiteTransactionScope,\n current: CompletedWriter,\n) {\n if (!current.complete) return;\n const published = await protectedPublishedStages(tx, current);\n const protectedIds = [\n ...new Set([current.id, ...published.map(({ id }) => id)]),\n ];\n const obsolete = await tx\n .select({\n stage: {\n id: principalHistoryStages.id,\n organizationId: principalHistoryStages.organizationId,\n currentJson: principalHistoryStages.currentJson,\n afterVersion: principalHistoryStages.afterVersion,\n },\n })\n .from(principalHistoryStageScopes)\n .innerJoin(\n principalHistoryStages,\n eq(principalHistoryStageScopes.id, principalHistoryStages.id),\n )\n .where(\n and(\n matchingCompletedStages(current),\n notInArray(principalHistoryStages.id, protectedIds),\n ),\n )\n // The existing \"incomplete\" index also covers completed scoped recency.\n .orderBy(\n desc(principalHistoryStageScopes.touchedAt),\n asc(principalHistoryStageScopes.id),\n )\n .offset(COMPLETED_STAGE_LIMIT - protectedIds.length)\n .limit(PRINCIPAL_HISTORY_STAGE_RECLAIM_LIMIT);\n if (obsolete.length === 0) return;\n for (const { stage } of obsolete)\n await archivePrincipalHistoryKeyEnvelopes(tx, {\n ...stage,\n version: stage.afterVersion + 1,\n });\n const ids = obsolete.map(({ stage }) => stage.id);\n for (const id of ids) await releasePrincipalHistoryRoot(tx, `stage:${id}`);\n await tx\n .delete(principalHistoryStages)\n .where(inArray(principalHistoryStages.id, ids))\n .run();\n await tx\n .delete(principalHistoryStageScopes)\n .where(inArray(principalHistoryStageScopes.id, ids))\n .run();\n}\n"]}
@@ -0,0 +1,63 @@
1
+ import { computePrincipalMemberEnvelopesRoot } from "../../internal/crypto/index.js";
2
+ import { isPrincipalPolicyPageResponse } from "../../internal/validators/response/index.js";
3
+ import { lte } from "drizzle-orm";
4
+ import { principalKeyEnvelopeArchive } from "../sqlite/principalHistoryRetentionSchema.js";
5
+ /**
6
+ * Preserve untrusted encrypted candidates, never history or authorization.
7
+ * The caller replaces progress in this same transaction. Public-history hints
8
+ * carry no private artifacts and deliberately contribute no candidates.
9
+ */
10
+ export async function archivePrincipalHistoryKeyEnvelopes(tx, input) {
11
+ let current;
12
+ try {
13
+ current = JSON.parse(input.currentJson);
14
+ }
15
+ catch {
16
+ return;
17
+ }
18
+ if (!current || typeof current !== "object" || Array.isArray(current))
19
+ return;
20
+ const page = {
21
+ ...current,
22
+ previousStates: [],
23
+ historyPage: { afterVersion: input.version - 1, nextAfterVersion: null },
24
+ };
25
+ if (!isPrincipalPolicyPageResponse(page) ||
26
+ page.currentState.version !== input.version ||
27
+ page.currentState.stateHash !== page.currentMemberEnvelopes.stateHash ||
28
+ page.currentState.principalId !== page.currentMemberEnvelopes.principalId ||
29
+ page.currentState.principalType !==
30
+ page.currentMemberEnvelopes.principalType ||
31
+ page.currentState.keyEpoch !== page.currentMemberEnvelopes.epoch)
32
+ return;
33
+ try {
34
+ if ((await computePrincipalMemberEnvelopesRoot(page.currentMemberEnvelopes.envelopes)) !== page.currentState.memberEnvelopesRoot)
35
+ return;
36
+ }
37
+ catch {
38
+ return;
39
+ }
40
+ const row = {
41
+ organizationId: input.organizationId,
42
+ principalId: page.currentState.principalId,
43
+ principalType: page.currentState.principalType,
44
+ keyFingerprint: page.currentState.keyFingerprint,
45
+ version: input.version,
46
+ envelopesJson: JSON.stringify(page.currentMemberEnvelopes),
47
+ };
48
+ await tx
49
+ .insert(principalKeyEnvelopeArchive)
50
+ .values(row)
51
+ .onConflictDoUpdate({
52
+ target: [
53
+ principalKeyEnvelopeArchive.organizationId,
54
+ principalKeyEnvelopeArchive.principalType,
55
+ principalKeyEnvelopeArchive.principalId,
56
+ principalKeyEnvelopeArchive.keyFingerprint,
57
+ ],
58
+ set: row,
59
+ setWhere: lte(principalKeyEnvelopeArchive.version, row.version),
60
+ })
61
+ .run();
62
+ }
63
+ //# sourceMappingURL=principalKeyEnvelopeArchivePersistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalKeyEnvelopeArchivePersistence.js","sourceRoot":"","sources":["principalKeyEnvelopeArchivePersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,mBAAmB,CAAC;AACxE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC/E,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,2BAA2B,EAAE,MAAM,2CAA2C,CAAC;AAGxF;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,EAAgC,EAChC,KAIC;IAED,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO;IAC9E,MAAM,IAAI,GAAG;QACX,GAAG,OAAO;QACV,cAAc,EAAE,EAAE;QAClB,WAAW,EAAE,EAAE,YAAY,EAAE,KAAK,CAAC,OAAO,GAAG,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE;KACzE,CAAC;IACF,IACE,CAAC,6BAA6B,CAAC,IAAI,CAAC;QACpC,IAAI,CAAC,YAAY,CAAC,OAAO,KAAK,KAAK,CAAC,OAAO;QAC3C,IAAI,CAAC,YAAY,CAAC,SAAS,KAAK,IAAI,CAAC,sBAAsB,CAAC,SAAS;QACrE,IAAI,CAAC,YAAY,CAAC,WAAW,KAAK,IAAI,CAAC,sBAAsB,CAAC,WAAW;QACzE,IAAI,CAAC,YAAY,CAAC,aAAa;YAC7B,IAAI,CAAC,sBAAsB,CAAC,aAAa;QAC3C,IAAI,CAAC,YAAY,CAAC,QAAQ,KAAK,IAAI,CAAC,sBAAsB,CAAC,KAAK;QAEhE,OAAO;IACT,IAAI,CAAC;QACH,IACE,CAAC,MAAM,mCAAmC,CACxC,IAAI,CAAC,sBAAsB,CAAC,SAAS,CACtC,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,mBAAmB;YAE5C,OAAO;IACX,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,MAAM,GAAG,GAAG;QACV,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,WAAW;QAC1C,aAAa,EAAE,IAAI,CAAC,YAAY,CAAC,aAAa;QAC9C,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc;QAChD,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,sBAAsB,CAAC;KAC3D,CAAC;IACF,MAAM,EAAE;SACL,MAAM,CAAC,2BAA2B,CAAC;SACnC,MAAM,CAAC,GAAG,CAAC;SACX,kBAAkB,CAAC;QAClB,MAAM,EAAE;YACN,2BAA2B,CAAC,cAAc;YAC1C,2BAA2B,CAAC,aAAa;YACzC,2BAA2B,CAAC,WAAW;YACvC,2BAA2B,CAAC,cAAc;SAC3C;QACD,GAAG,EAAE,GAAG;QACR,QAAQ,EAAE,GAAG,CAAC,2BAA2B,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC;KAChE,CAAC;SACD,GAAG,EAAE,CAAC;AACX,CAAC","sourcesContent":["import { computePrincipalMemberEnvelopesRoot } from \"@tearleads/crypto\";\nimport { isPrincipalPolicyPageResponse } from \"@tearleads/validators/response\";\nimport { lte } from \"drizzle-orm\";\nimport { principalKeyEnvelopeArchive } from \"../sqlite/principalHistoryRetentionSchema\";\nimport type { ClientSQLiteTransactionScope } from \"../sqlite/sqlitePersistenceRuntime\";\n\n/**\n * Preserve untrusted encrypted candidates, never history or authorization.\n * The caller replaces progress in this same transaction. Public-history hints\n * carry no private artifacts and deliberately contribute no candidates.\n */\nexport async function archivePrincipalHistoryKeyEnvelopes(\n tx: ClientSQLiteTransactionScope,\n input: {\n readonly organizationId: string;\n readonly currentJson: string;\n readonly version: number;\n },\n) {\n let current: unknown;\n try {\n current = JSON.parse(input.currentJson);\n } catch {\n return;\n }\n if (!current || typeof current !== \"object\" || Array.isArray(current)) return;\n const page = {\n ...current,\n previousStates: [],\n historyPage: { afterVersion: input.version - 1, nextAfterVersion: null },\n };\n if (\n !isPrincipalPolicyPageResponse(page) ||\n page.currentState.version !== input.version ||\n page.currentState.stateHash !== page.currentMemberEnvelopes.stateHash ||\n page.currentState.principalId !== page.currentMemberEnvelopes.principalId ||\n page.currentState.principalType !==\n page.currentMemberEnvelopes.principalType ||\n page.currentState.keyEpoch !== page.currentMemberEnvelopes.epoch\n )\n return;\n try {\n if (\n (await computePrincipalMemberEnvelopesRoot(\n page.currentMemberEnvelopes.envelopes,\n )) !== page.currentState.memberEnvelopesRoot\n )\n return;\n } catch {\n return;\n }\n const row = {\n organizationId: input.organizationId,\n principalId: page.currentState.principalId,\n principalType: page.currentState.principalType,\n keyFingerprint: page.currentState.keyFingerprint,\n version: input.version,\n envelopesJson: JSON.stringify(page.currentMemberEnvelopes),\n };\n await tx\n .insert(principalKeyEnvelopeArchive)\n .values(row)\n .onConflictDoUpdate({\n target: [\n principalKeyEnvelopeArchive.organizationId,\n principalKeyEnvelopeArchive.principalType,\n principalKeyEnvelopeArchive.principalId,\n principalKeyEnvelopeArchive.keyFingerprint,\n ],\n set: row,\n setWhere: lte(principalKeyEnvelopeArchive.version, row.version),\n })\n .run();\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { isCurrentPrincipalMemberEnvelopesResponse, } from "../../internal/validators/response/index.js";
2
2
  import { and, desc, eq, sql } from "drizzle-orm";
3
3
  import { principalHistoryEvidenceTables, principalHistoryPrefixes, } from "../sqlite/principalHistoryEvidenceSchema.js";
4
+ import { principalKeyEnvelopeArchive } from "../sqlite/principalHistoryRetentionSchema.js";
4
5
  import { principalHistoryStages } from "../sqlite/principalHistoryStageSchema.js";
5
6
  import { principalCurrentFingerprintJson, principalStateFingerprintJson, } from "../sqlite/principalKeyFingerprintJson.js";
6
7
  import { principalPolicies, principalPolicyBundleHistory, } from "../sqlite/principalPolicySchema.js";
@@ -22,6 +23,14 @@ export async function loadPrincipalKeyEnvelopeCandidates(execSql, fingerprints)
22
23
  const candidates = [];
23
24
  for (const fingerprint of new Set(fingerprints)) {
24
25
  const encoded = [];
26
+ const [archived] = await db
27
+ .select({ envelopes: principalKeyEnvelopeArchive.envelopesJson })
28
+ .from(principalKeyEnvelopeArchive)
29
+ .where(eq(principalKeyEnvelopeArchive.keyFingerprint, fingerprint))
30
+ .orderBy(desc(principalKeyEnvelopeArchive.version))
31
+ .limit(1);
32
+ if (archived)
33
+ encoded.push(archived.envelopes);
25
34
  for (const table of [principalPolicies, principalPolicyBundleHistory]) {
26
35
  const [row] = await db
27
36
  .select({ envelopes: table.currentMemberEnvelopesJson })
@@ -52,7 +61,7 @@ export async function loadPrincipalKeyEnvelopeCandidates(execSql, fingerprints)
52
61
  .limit(1);
53
62
  if (stage)
54
63
  encoded.push(stage.envelopes);
55
- for (const json of encoded) {
64
+ for (const json of new Set(encoded)) {
56
65
  let envelopes;
57
66
  try {
58
67
  envelopes = JSON.parse(json);
@@ -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 { 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"]}
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 { principalKeyEnvelopeArchive } from \"../sqlite/principalHistoryRetentionSchema\";\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 const [archived] = await db\n .select({ envelopes: principalKeyEnvelopeArchive.envelopesJson })\n .from(principalKeyEnvelopeArchive)\n .where(eq(principalKeyEnvelopeArchive.keyFingerprint, fingerprint))\n .orderBy(desc(principalKeyEnvelopeArchive.version))\n .limit(1);\n if (archived) encoded.push(archived.envelopes);\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 new Set(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,5 +1,6 @@
1
1
  import { desc } from "drizzle-orm";
2
2
  import { index, integer, primaryKey, sqliteTable, text, } from "drizzle-orm/sqlite-core";
3
+ import { principalHistoryNodeRetentionTables } from "./principalHistoryNodeRetentionSchema.js";
3
4
  import { principalCurrentFingerprintJson } from "./principalKeyFingerprintJson.js";
4
5
  import { defineSqlTableSchema } from "./sqlTableSchema.js";
5
6
  /** A completed, locally authenticated prefix; never an application trust pin. */
@@ -36,6 +37,7 @@ export const principalHistoryNodes = sqliteTable("principal_history_nodes", {
36
37
  index("principal_history_nodes_organization_idx").on(table.organizationId),
37
38
  ]);
38
39
  export const principalHistoryEvidenceTables = [
40
+ ...principalHistoryNodeRetentionTables,
39
41
  {
40
42
  ...defineSqlTableSchema(principalHistoryPrefixes),
41
43
  requiredColumns: ["current_json"],
@@ -1 +1 @@
1
- {"version":3,"file":"principalHistoryEvidenceSchema.js","sourceRoot":"","sources":["principalHistoryEvidenceSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { desc } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\nimport { principalCurrentFingerprintJson } from \"./principalKeyFingerprintJson\";\nimport { defineSqlTableSchema } from \"./sqlTableSchema\";\n\n/** A completed, locally authenticated prefix; never an application trust pin. */\nexport const principalHistoryPrefixes = sqliteTable(\n \"principal_history_prefixes\",\n {\n scopeId: text(\"scope_id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n version: integer(\"version\").notNull(),\n headJson: text(\"head_json\").notNull(),\n currentJson: text(\"current_json\").notNull(),\n progress: text(\"progress\").notNull(),\n },\n (table) => [\n index(\"principal_history_prefixes_key_fingerprint_idx\").on(\n principalCurrentFingerprintJson(table.currentJson),\n desc(table.version),\n ),\n index(\"principal_history_prefixes_organization_idx\").on(\n table.organizationId,\n ),\n ],\n);\n\n/** Entries are selected by their exact signed leaf, including signature bytes. */\nexport const principalHistoryEntries = sqliteTable(\n \"principal_history_entries\",\n {\n scopeId: text(\"scope_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n leafHash: text(\"leaf_hash\").notNull(),\n entryJson: text(\"entry_json\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.scopeId, table.leafHash] }),\n index(\"principal_history_entries_organization_idx\").on(\n table.organizationId,\n ),\n ],\n);\n\n/** Untrusted proof material, checked against a locally restored private root. */\nexport const principalHistoryNodes = sqliteTable(\n \"principal_history_nodes\",\n {\n scopeId: text(\"scope_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n hash: text(\"hash\").notNull(),\n leftHash: text(\"left_hash\").notNull(),\n rightHash: text(\"right_hash\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.scopeId, table.hash] }),\n index(\"principal_history_nodes_organization_idx\").on(table.organizationId),\n ],\n);\n\nexport const principalHistoryEvidenceTables = [\n {\n ...defineSqlTableSchema(principalHistoryPrefixes),\n requiredColumns: [\"current_json\"],\n },\n defineSqlTableSchema(principalHistoryEntries),\n defineSqlTableSchema(principalHistoryNodes),\n];\n"]}
1
+ {"version":3,"file":"principalHistoryEvidenceSchema.js","sourceRoot":"","sources":["principalHistoryEvidenceSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { desc } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\nimport { principalHistoryNodeRetentionTables } from \"./principalHistoryNodeRetentionSchema\";\nimport { principalCurrentFingerprintJson } from \"./principalKeyFingerprintJson\";\nimport { defineSqlTableSchema } from \"./sqlTableSchema\";\n\n/** A completed, locally authenticated prefix; never an application trust pin. */\nexport const principalHistoryPrefixes = sqliteTable(\n \"principal_history_prefixes\",\n {\n scopeId: text(\"scope_id\").primaryKey(),\n organizationId: text(\"organization_id\").notNull(),\n version: integer(\"version\").notNull(),\n headJson: text(\"head_json\").notNull(),\n currentJson: text(\"current_json\").notNull(),\n progress: text(\"progress\").notNull(),\n },\n (table) => [\n index(\"principal_history_prefixes_key_fingerprint_idx\").on(\n principalCurrentFingerprintJson(table.currentJson),\n desc(table.version),\n ),\n index(\"principal_history_prefixes_organization_idx\").on(\n table.organizationId,\n ),\n ],\n);\n\n/** Entries are selected by their exact signed leaf, including signature bytes. */\nexport const principalHistoryEntries = sqliteTable(\n \"principal_history_entries\",\n {\n scopeId: text(\"scope_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n leafHash: text(\"leaf_hash\").notNull(),\n entryJson: text(\"entry_json\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.scopeId, table.leafHash] }),\n index(\"principal_history_entries_organization_idx\").on(\n table.organizationId,\n ),\n ],\n);\n\n/** Untrusted proof material, checked against a locally restored private root. */\nexport const principalHistoryNodes = sqliteTable(\n \"principal_history_nodes\",\n {\n scopeId: text(\"scope_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n hash: text(\"hash\").notNull(),\n leftHash: text(\"left_hash\").notNull(),\n rightHash: text(\"right_hash\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.scopeId, table.hash] }),\n index(\"principal_history_nodes_organization_idx\").on(table.organizationId),\n ],\n);\n\nexport const principalHistoryEvidenceTables = [\n ...principalHistoryNodeRetentionTables,\n {\n ...defineSqlTableSchema(principalHistoryPrefixes),\n requiredColumns: [\"current_json\"],\n },\n defineSqlTableSchema(principalHistoryEntries),\n defineSqlTableSchema(principalHistoryNodes),\n];\n"]}
@@ -0,0 +1,30 @@
1
+ import { index, integer, primaryKey, sqliteTable, text, } from "drizzle-orm/sqlite-core";
2
+ import { defineSqlTableSchema } from "./sqlTableSchema.js";
3
+ /** Disposable graph liveness hints. Proof verification still authenticates every node. */
4
+ export const principalHistoryNodeReferences = sqliteTable("principal_history_node_references", {
5
+ scopeId: text("scope_id").notNull(),
6
+ organizationId: text("organization_id").notNull(),
7
+ hash: text("hash").notNull(),
8
+ referenceCount: integer("reference_count").notNull(),
9
+ managed: integer("managed", { mode: "boolean" }).notNull(),
10
+ leftHash: text("left_hash"),
11
+ rightHash: text("right_hash"),
12
+ }, (table) => [
13
+ primaryKey({ columns: [table.scopeId, table.hash] }),
14
+ index("principal_history_node_references_reclaim_idx").on(table.scopeId, table.organizationId, table.managed, table.referenceCount, table.hash),
15
+ index("principal_history_node_references_organization_idx").on(table.organizationId),
16
+ ]);
17
+ /** A saved stage or prefix keeps its proof root live until its guarded replacement. */
18
+ export const principalHistoryRootOwners = sqliteTable("principal_history_root_owners", {
19
+ id: text("id").primaryKey(),
20
+ scopeId: text("scope_id").notNull(),
21
+ organizationId: text("organization_id").notNull(),
22
+ rootHash: text("root_hash").notNull(),
23
+ }, (table) => [
24
+ index("principal_history_root_owners_organization_idx").on(table.organizationId),
25
+ ]);
26
+ export const principalHistoryNodeRetentionTables = [
27
+ defineSqlTableSchema(principalHistoryNodeReferences),
28
+ defineSqlTableSchema(principalHistoryRootOwners),
29
+ ];
30
+ //# sourceMappingURL=principalHistoryNodeRetentionSchema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalHistoryNodeRetentionSchema.js","sourceRoot":"","sources":["principalHistoryNodeRetentionSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,IAAI,GACL,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,0FAA0F;AAC1F,MAAM,CAAC,MAAM,8BAA8B,GAAG,WAAW,CACvD,mCAAmC,EACnC;IACE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,cAAc,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACpD,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE;IAC1D,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC;CAC9B,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACpD,KAAK,CAAC,+CAA+C,CAAC,CAAC,EAAE,CACvD,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,IAAI,CACX;IACD,KAAK,CAAC,oDAAoD,CAAC,CAAC,EAAE,CAC5D,KAAK,CAAC,cAAc,CACrB;CACF,CACF,CAAC;AAEF,uFAAuF;AACvF,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CACnD,+BAA+B,EAC/B;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,EAAE;CACtC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,KAAK,CAAC,gDAAgD,CAAC,CAAC,EAAE,CACxD,KAAK,CAAC,cAAc,CACrB;CACF,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,mCAAmC,GAAG;IACjD,oBAAoB,CAAC,8BAA8B,CAAC;IACpD,oBAAoB,CAAC,0BAA0B,CAAC;CACjD,CAAC","sourcesContent":["import {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema } from \"./sqlTableSchema\";\n\n/** Disposable graph liveness hints. Proof verification still authenticates every node. */\nexport const principalHistoryNodeReferences = sqliteTable(\n \"principal_history_node_references\",\n {\n scopeId: text(\"scope_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n hash: text(\"hash\").notNull(),\n referenceCount: integer(\"reference_count\").notNull(),\n managed: integer(\"managed\", { mode: \"boolean\" }).notNull(),\n leftHash: text(\"left_hash\"),\n rightHash: text(\"right_hash\"),\n },\n (table) => [\n primaryKey({ columns: [table.scopeId, table.hash] }),\n index(\"principal_history_node_references_reclaim_idx\").on(\n table.scopeId,\n table.organizationId,\n table.managed,\n table.referenceCount,\n table.hash,\n ),\n index(\"principal_history_node_references_organization_idx\").on(\n table.organizationId,\n ),\n ],\n);\n\n/** A saved stage or prefix keeps its proof root live until its guarded replacement. */\nexport const principalHistoryRootOwners = sqliteTable(\n \"principal_history_root_owners\",\n {\n id: text(\"id\").primaryKey(),\n scopeId: text(\"scope_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n rootHash: text(\"root_hash\").notNull(),\n },\n (table) => [\n index(\"principal_history_root_owners_organization_idx\").on(\n table.organizationId,\n ),\n ],\n);\n\nexport const principalHistoryNodeRetentionTables = [\n defineSqlTableSchema(principalHistoryNodeReferences),\n defineSqlTableSchema(principalHistoryRootOwners),\n];\n"]}