@tearleads/client-sdk 0.1.16 → 0.1.18

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 (158) hide show
  1. package/client/index.d.ts +1 -1
  2. package/client/index.js.map +1 -1
  3. package/client/organizations/currentPrincipalMutations.js +96 -0
  4. package/client/organizations/currentPrincipalMutations.js.map +1 -0
  5. package/client/organizations/index.d.ts +1 -1
  6. package/client/organizations/index.js +4 -3
  7. package/client/organizations/index.js.map +1 -1
  8. package/client/organizations/organizationGroupHistory.js +44 -0
  9. package/client/organizations/organizationGroupHistory.js.map +1 -0
  10. package/client/organizations/organizationGroupNameHydration.js +7 -1
  11. package/client/organizations/organizationGroupNameHydration.js.map +1 -1
  12. package/client/organizations/organizationGroupPresentation.d.ts +1 -0
  13. package/client/organizations/organizationGroupPresentation.js +16 -2
  14. package/client/organizations/organizationGroupPresentation.js.map +1 -1
  15. package/client/organizations/organizationReadModels.d.ts +1 -1
  16. package/client/organizations/organizationReadModels.js +11 -1
  17. package/client/organizations/organizationReadModels.js.map +1 -1
  18. package/client/organizations/organizationsTypes.d.ts +8 -5
  19. package/client/organizations/organizationsTypes.js.map +1 -1
  20. package/client/organizations/principalContainerMutations.js +2 -0
  21. package/client/organizations/principalContainerMutations.js.map +1 -1
  22. package/client/organizations/principalMutations.d.ts +4 -308
  23. package/client/organizations/principalMutations.js +165 -87
  24. package/client/organizations/principalMutations.js.map +1 -1
  25. package/client/principalMutationApi.d.ts +1 -1
  26. package/client/principalMutationApi.js +5 -13
  27. package/client/principalMutationApi.js.map +1 -1
  28. package/client/principalMutationDispatch.js +54 -0
  29. package/client/principalMutationDispatch.js.map +1 -0
  30. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +2 -2
  31. package/data/persistence/principalCurrentAcknowledgementPersistence.js +21 -14
  32. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  33. package/data/principals/currentPolicyReferenceResolver.js +2 -0
  34. package/data/principals/currentPolicyReferenceResolver.js.map +1 -0
  35. package/data/principals/principalHistoryScopeProtection.js +23 -0
  36. package/data/principals/principalHistoryScopeProtection.js.map +1 -0
  37. package/data/principals/principalMutationJournal.d.ts +2 -5
  38. package/data/principals/principalMutationJournal.js +3 -20
  39. package/data/principals/principalMutationJournal.js.map +1 -1
  40. package/data/principals/principalMutationJournalShape.d.ts +26 -0
  41. package/data/principals/principalMutationJournalShape.js +46 -0
  42. package/data/principals/principalMutationJournalShape.js.map +1 -0
  43. package/data/principals/principalPolicyAdminSigners.js.map +1 -1
  44. package/index.d.ts +2 -2
  45. package/index.js.map +1 -1
  46. package/internal/api-client/ApiClient.d.ts +267 -3
  47. package/internal/api-client/ApiClient.js +11 -29
  48. package/internal/api-client/ApiClient.js.map +1 -1
  49. package/internal/api-client/principalPolicyRequests.d.ts +266 -1
  50. package/internal/api-client/principalPolicyRequests.js +43 -1
  51. package/internal/api-client/principalPolicyRequests.js.map +1 -1
  52. package/internal/crypto/index.d.ts +1 -1
  53. package/internal/crypto/index.js +1 -1
  54. package/internal/crypto/index.js.map +1 -1
  55. package/internal/crypto/keying/index.d.ts +1 -0
  56. package/internal/crypto/keying/index.js +1 -0
  57. package/internal/crypto/keying/index.js.map +1 -1
  58. package/internal/crypto/keying/principalPolicyCurrentPredecessorReferences.d.ts +8 -0
  59. package/internal/crypto/keying/principalPolicyCurrentPredecessorReferences.js +46 -0
  60. package/internal/crypto/keying/principalPolicyCurrentPredecessorReferences.js.map +1 -0
  61. package/internal/validators/operation/organizations.d.ts +54 -0
  62. package/internal/validators/operation/organizations.js +19 -4
  63. package/internal/validators/operation/organizations.js.map +1 -1
  64. package/package.json +1 -1
  65. package/workflows/containers/child/carriedDescendantRekeys.js +9 -1
  66. package/workflows/containers/child/carriedDescendantRekeys.js.map +1 -1
  67. package/workflows/containers/child/replacementPrincipalPolicyReferences.js +19 -0
  68. package/workflows/containers/child/replacementPrincipalPolicyReferences.js.map +1 -0
  69. package/workflows/organizations/commitCurrentGroupPolicyMutation.js +72 -0
  70. package/workflows/organizations/commitCurrentGroupPolicyMutation.js.map +1 -0
  71. package/workflows/organizations/createCurrentOrganizationGroup.js +85 -0
  72. package/workflows/organizations/createCurrentOrganizationGroup.js.map +1 -0
  73. package/workflows/organizations/currentGroupMetadataAuthority.js +24 -3
  74. package/workflows/organizations/currentGroupMetadataAuthority.js.map +1 -1
  75. package/workflows/organizations/currentGroupMutationReferences.js +35 -0
  76. package/workflows/organizations/currentGroupMutationReferences.js.map +1 -0
  77. package/workflows/organizations/currentGroupPolicyMutationContext.js +79 -0
  78. package/workflows/organizations/currentGroupPolicyMutationContext.js.map +1 -0
  79. package/workflows/organizations/currentOrganizationGroupNames.js +5 -1
  80. package/workflows/organizations/currentOrganizationGroupNames.js.map +1 -1
  81. package/workflows/organizations/currentOrganizationMutationAuthority.js +16 -0
  82. package/workflows/organizations/currentOrganizationMutationAuthority.js.map +1 -0
  83. package/workflows/organizations/currentOrganizationMutationRetention.js +53 -0
  84. package/workflows/organizations/currentOrganizationMutationRetention.js.map +1 -0
  85. package/workflows/organizations/currentPrincipalMutationLease.js +38 -0
  86. package/workflows/organizations/currentPrincipalMutationLease.js.map +1 -0
  87. package/workflows/organizations/deleteCurrentOrganizationGroup.js +35 -0
  88. package/workflows/organizations/deleteCurrentOrganizationGroup.js.map +1 -0
  89. package/workflows/organizations/deleteOrganizationGroup.d.ts +1 -0
  90. package/workflows/organizations/deleteOrganizationGroup.js +10 -0
  91. package/workflows/organizations/deleteOrganizationGroup.js.map +1 -1
  92. package/workflows/organizations/groupCreation.d.ts +1 -0
  93. package/workflows/organizations/groupCreation.js +8 -0
  94. package/workflows/organizations/groupCreation.js.map +1 -1
  95. package/workflows/organizations/groupMembershipName.d.ts +1 -1
  96. package/workflows/organizations/groupMembershipName.js.map +1 -1
  97. package/workflows/organizations/groupMetadataRuntime.js +14 -9
  98. package/workflows/organizations/groupMetadataRuntime.js.map +1 -1
  99. package/workflows/organizations/groupNameUniqueness.js +1 -1
  100. package/workflows/organizations/groupNameUniqueness.js.map +1 -1
  101. package/workflows/organizations/groupPolicyHistoryPage.js +31 -0
  102. package/workflows/organizations/groupPolicyHistoryPage.js.map +1 -0
  103. package/workflows/organizations/groupPolicyMutationAcknowledgement.js +1 -0
  104. package/workflows/organizations/groupPolicyMutationAcknowledgement.js.map +1 -1
  105. package/workflows/organizations/groupPolicyMutationContext.d.ts +18 -0
  106. package/workflows/organizations/groupPolicyMutationContext.js +1 -1
  107. package/workflows/organizations/groupPolicyMutationContext.js.map +1 -1
  108. package/workflows/organizations/index.d.ts +1 -0
  109. package/workflows/organizations/index.js.map +1 -1
  110. package/workflows/organizations/initialPrincipalCurrentPublication.js +83 -0
  111. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -0
  112. package/workflows/organizations/organizationGroupDirectory.js +6 -0
  113. package/workflows/organizations/organizationGroupDirectory.js.map +1 -1
  114. package/workflows/organizations/organizationGroupNames.js.map +1 -1
  115. package/workflows/organizations/policyHistoryTypes.d.ts +2 -0
  116. package/workflows/organizations/policyHistoryTypes.js.map +1 -1
  117. package/workflows/organizations/principalContainerRematerialization.js +12 -2
  118. package/workflows/organizations/principalContainerRematerialization.js.map +1 -1
  119. package/workflows/organizations/principalContainerRematerializationPlanning.js +1 -0
  120. package/workflows/organizations/principalContainerRematerializationPlanning.js.map +1 -1
  121. package/workflows/organizations/principalContainerRematerializationTargets.js.map +1 -1
  122. package/workflows/organizations/principalMutationJournalSession.d.ts +3 -3
  123. package/workflows/organizations/principalMutationJournalSession.js +2 -2
  124. package/workflows/organizations/principalMutationJournalSession.js.map +1 -1
  125. package/workflows/organizations/principalMutationReceipt.js +13 -12
  126. package/workflows/organizations/principalMutationReceipt.js.map +1 -1
  127. package/workflows/organizations/principalOperationReceipt.d.ts +5 -0
  128. package/workflows/organizations/principalOperationReceipt.js +36 -0
  129. package/workflows/organizations/principalOperationReceipt.js.map +1 -0
  130. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.d.ts +2 -0
  131. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +5 -1
  132. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
  133. package/workflows/organizations/runtimeCurrentGroupMutation.js +85 -0
  134. package/workflows/organizations/runtimeCurrentGroupMutation.js.map +1 -0
  135. package/workflows/organizations/runtimeCurrentOrganizationMutation.js +48 -0
  136. package/workflows/organizations/runtimeCurrentOrganizationMutation.js.map +1 -0
  137. package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +11 -0
  138. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +120 -0
  139. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -0
  140. package/workflows/principals/principalHistoryRecoveryReferences.js +8 -0
  141. package/workflows/principals/principalHistoryRecoveryReferences.js.map +1 -1
  142. package/workflows/principals/principalRecoveryDirectory.js +3 -8
  143. package/workflows/principals/principalRecoveryDirectory.js.map +1 -1
  144. package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
  145. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
  146. package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -1
  147. package/workflows/principals/recoverPrincipalHistoryPage.js +30 -0
  148. package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -0
  149. package/workflows/principals/recoverPrincipalPolicyHistory.d.ts +2 -0
  150. package/workflows/principals/recoverPrincipalPolicyHistory.js +14 -2
  151. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  152. package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +6 -0
  153. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +31 -19
  154. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
  155. package/workflows/principals/runtimePolicyRecovery.js +25 -4
  156. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  157. package/workflows/principals/runtimePolicyWarmer.js +2 -2
  158. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
@@ -0,0 +1,85 @@
1
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
2
+ import { scopedGroupHistoryProtection } from "../../data/principals/principalHistoryScopeProtection.js";
3
+ import { principalPolicyReferenceFromBundle } from "../../data/principals/principalPolicyAdminSigners.js";
4
+ import { resolveCurrentGroupMutationReferences } from "./currentGroupMutationReferences.js";
5
+ import { loadCurrentGroupPolicyMutationContext } from "./currentGroupPolicyMutationContext.js";
6
+ import { createCurrentPrincipalMutationLease } from "./currentPrincipalMutationLease.js";
7
+ import { retainAcknowledgedPrincipalCurrents, } from "./retainAcknowledgedPrincipalCurrents.js";
8
+ /** Keep private prefix custody inside the entire mutation and its acknowledgement. */
9
+ export function createRuntimeCurrentGroupMutation(runtime) {
10
+ const lease = createCurrentPrincipalMutationLease(runtime);
11
+ if (!lease)
12
+ return undefined;
13
+ return async (input, work) => {
14
+ input = { ...input };
15
+ return lease(input.stillCurrent, async ({ protection, stillCurrent, resolveCurrentPolicy, readPages, directoryRecovery, }) => {
16
+ const context = await loadCurrentGroupPolicyMutationContext({
17
+ ...input,
18
+ execSql: runtime.infra.execSql,
19
+ resolveCurrentPolicy,
20
+ recoverPendingPrincipalMutation: (organizationId) => runtime.apiClient.recoverPendingPrincipalMutation(organizationId),
21
+ stillCurrent,
22
+ });
23
+ const result = await work({
24
+ ...context,
25
+ resolveAuthoredPolicyReferences: (current, references) => resolveCurrentGroupMutationReferences({
26
+ current,
27
+ predecessor: context.verifiedCurrentPolicy,
28
+ references,
29
+ readPredecessorReference: context.readPredecessorReference,
30
+ stillCurrent: context.stillCurrent,
31
+ }),
32
+ retainAcknowledged: createCurrentMutationRetention(runtime, input, context, protection, readPages, directoryRecovery(context.organizationCurrent.current)),
33
+ });
34
+ assertProjectionVerificationCurrent(context.stillCurrent);
35
+ return result;
36
+ });
37
+ };
38
+ }
39
+ function createCurrentMutationRetention(runtime, input, context, protection, readPages, directoryRecovery) {
40
+ const common = {
41
+ apiClient: { getPrincipalPolicyPages: readPages },
42
+ resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,
43
+ };
44
+ const groupRecovery = {
45
+ ...common,
46
+ expectedHead: principalPolicyReferenceFromBundle(context.currentPolicy),
47
+ protection: context.isOrganizationAdminsGroup
48
+ ? protection
49
+ : scopedGroupHistoryProtection(protection, input.organizationId, context.adminGroupId),
50
+ historyVerification: context.isOrganizationAdminsGroup
51
+ ? "direct-admins"
52
+ : "standard",
53
+ ...(context.isOrganizationAdminsGroup
54
+ ? {}
55
+ : { loadExternalAuthority: async () => context.externalAuthority }),
56
+ };
57
+ return async (receipt) => {
58
+ assertProjectionVerificationCurrent(context.stillCurrent);
59
+ await retainAcknowledgedPrincipalCurrents({
60
+ execSql: runtime.infra.execSql,
61
+ organizationId: input.organizationId,
62
+ entries: [
63
+ {
64
+ recovery: groupRecovery,
65
+ request: receipt.request,
66
+ response: receipt.response.groupPolicy,
67
+ },
68
+ {
69
+ recovery: directoryRecovery,
70
+ request: receipt.organizationRequest,
71
+ response: receipt.response.organizationPolicy,
72
+ },
73
+ ],
74
+ retirements: [
75
+ {
76
+ principalId: input.groupId,
77
+ principalType: "group",
78
+ containerIds: receipt.retiredContainerIds ?? [],
79
+ },
80
+ ],
81
+ stillCurrent: context.stillCurrent,
82
+ });
83
+ };
84
+ }
85
+ //# sourceMappingURL=runtimeCurrentGroupMutation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeCurrentGroupMutation.js","sourceRoot":"","sources":["runtimeCurrentGroupMutation.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { PrincipalPolicyHistoryProgressOptions } from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { CommitOrganizationGroupPolicyResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { CurrentPolicyReferenceResolver } from \"../../data/principals/currentPolicyReferenceResolver\";\nimport { scopedGroupHistoryProtection } from \"../../data/principals/principalHistoryScopeProtection\";\nimport { principalPolicyReferenceFromBundle } from \"../../data/principals/principalPolicyAdminSigners\";\nimport type { PrincipalPolicyRecoveryRuntime } from \"../principals/runtimePolicyRecovery\";\nimport { resolveCurrentGroupMutationReferences } from \"./currentGroupMutationReferences\";\nimport { loadCurrentGroupPolicyMutationContext } from \"./currentGroupPolicyMutationContext\";\nimport { createCurrentPrincipalMutationLease } from \"./currentPrincipalMutationLease\";\nimport type { PrincipalMutationRecoveryApi } from \"./principalMutationJournalManagement\";\nimport {\n type AcknowledgedPrincipalCurrentInput,\n retainAcknowledgedPrincipalCurrents,\n} from \"./retainAcknowledgedPrincipalCurrents\";\n\ntype MutationRuntime = PrincipalPolicyRecoveryRuntime & {\n readonly apiClient: PrincipalPolicyRecoveryRuntime[\"apiClient\"] &\n Pick<PrincipalMutationRecoveryApi, \"recoverPendingPrincipalMutation\">;\n};\n\ntype CurrentMutationContext = Awaited<\n ReturnType<typeof loadCurrentGroupPolicyMutationContext>\n>;\n\nexport type RuntimeCurrentGroupMutationContext = CurrentMutationContext & {\n readonly resolveAuthoredPolicyReferences: CurrentPolicyReferenceResolver;\n readonly retainAcknowledged: (\n receipt: CurrentMutationReceipt,\n ) => Promise<void>;\n};\n\ninterface CurrentMutationReceipt {\n readonly request: PutPrincipalPolicyRequest;\n readonly organizationRequest: PutPrincipalPolicyRequest;\n readonly response: CommitOrganizationGroupPolicyResponse;\n readonly retiredContainerIds?: readonly string[] | undefined;\n}\n\ninterface MutationInput {\n readonly groupId: string;\n readonly organizationId: string;\n readonly signerUserId: string;\n readonly stillCurrent: () => boolean;\n}\n\n/** Keep private prefix custody inside the entire mutation and its acknowledgement. */\nexport function createRuntimeCurrentGroupMutation(runtime: MutationRuntime) {\n const lease = createCurrentPrincipalMutationLease(runtime);\n if (!lease) return undefined;\n return async <T>(\n input: MutationInput,\n work: (context: RuntimeCurrentGroupMutationContext) => Promise<T>,\n ): Promise<T> => {\n input = { ...input };\n return lease(\n input.stillCurrent,\n async ({\n protection,\n stillCurrent,\n resolveCurrentPolicy,\n readPages,\n directoryRecovery,\n }) => {\n const context = await loadCurrentGroupPolicyMutationContext({\n ...input,\n execSql: runtime.infra.execSql,\n resolveCurrentPolicy,\n recoverPendingPrincipalMutation: (organizationId) =>\n runtime.apiClient.recoverPendingPrincipalMutation(organizationId),\n stillCurrent,\n });\n const result = await work({\n ...context,\n resolveAuthoredPolicyReferences: (current, references) =>\n resolveCurrentGroupMutationReferences({\n current,\n predecessor: context.verifiedCurrentPolicy,\n references,\n readPredecessorReference: context.readPredecessorReference,\n stillCurrent: context.stillCurrent,\n }),\n retainAcknowledged: createCurrentMutationRetention(\n runtime,\n input,\n context,\n protection,\n readPages,\n directoryRecovery(context.organizationCurrent.current),\n ),\n });\n assertProjectionVerificationCurrent(context.stillCurrent);\n return result;\n },\n );\n };\n}\n\nfunction createCurrentMutationRetention(\n runtime: MutationRuntime,\n input: MutationInput,\n context: CurrentMutationContext,\n protection: PrincipalPolicyHistoryProgressOptions,\n readPages: ApiClient[\"getPrincipalPolicyPages\"],\n directoryRecovery: AcknowledgedPrincipalCurrentInput[\"recovery\"],\n) {\n const common = {\n apiClient: { getPrincipalPolicyPages: readPages },\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n };\n const groupRecovery: AcknowledgedPrincipalCurrentInput[\"recovery\"] = {\n ...common,\n expectedHead: principalPolicyReferenceFromBundle(context.currentPolicy),\n protection: context.isOrganizationAdminsGroup\n ? protection\n : scopedGroupHistoryProtection(\n protection,\n input.organizationId,\n context.adminGroupId,\n ),\n historyVerification: context.isOrganizationAdminsGroup\n ? \"direct-admins\"\n : \"standard\",\n ...(context.isOrganizationAdminsGroup\n ? {}\n : { loadExternalAuthority: async () => context.externalAuthority }),\n };\n return async (receipt: CurrentMutationReceipt): Promise<void> => {\n assertProjectionVerificationCurrent(context.stillCurrent);\n await retainAcknowledgedPrincipalCurrents({\n execSql: runtime.infra.execSql,\n organizationId: input.organizationId,\n entries: [\n {\n recovery: groupRecovery,\n request: receipt.request,\n response: receipt.response.groupPolicy,\n },\n {\n recovery: directoryRecovery,\n request: receipt.organizationRequest,\n response: receipt.response.organizationPolicy,\n },\n ],\n retirements: [\n {\n principalId: input.groupId,\n principalType: \"group\",\n containerIds: receipt.retiredContainerIds ?? [],\n },\n ],\n stillCurrent: context.stillCurrent,\n });\n };\n}\n"]}
@@ -0,0 +1,48 @@
1
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
2
+ import { advanceKeyingCheckpointsAtomically } from "../../data/persistence/keyingCheckpointAdvancePersistence.js";
3
+ import { loadCurrentOrganizationMutationAuthority } from "./currentOrganizationMutationAuthority.js";
4
+ import { createCurrentOrganizationMutationRetention } from "./currentOrganizationMutationRetention.js";
5
+ import { createCurrentPrincipalMutationLease } from "./currentPrincipalMutationLease.js";
6
+ /** Keep directory authoring and exact acknowledgement inside one private lease. */
7
+ export function createRuntimeCurrentOrganizationMutation(runtime) {
8
+ const lease = createCurrentPrincipalMutationLease(runtime);
9
+ if (!lease)
10
+ return undefined;
11
+ return async (input, work) => {
12
+ const owned = { ...input };
13
+ return lease(owned.stillCurrent, async ({ protection, readPages, stillCurrent, resolveCurrentPolicy, directoryRecovery, }) => {
14
+ const { authority } = await loadCurrentOrganizationMutationAuthority({
15
+ execSql: runtime.infra.execSql,
16
+ organizationId: owned.organizationId,
17
+ signerUserId: owned.signerUserId,
18
+ recoverPendingPrincipalMutation: (organizationId) => runtime.apiClient.recoverPendingPrincipalMutation(organizationId),
19
+ resolveCurrentPolicy,
20
+ stillCurrent,
21
+ });
22
+ const current = () => stillCurrent() && authority.stillCurrent();
23
+ await advanceKeyingCheckpointsAtomically({
24
+ access: [],
25
+ execSql: runtime.infra.execSql,
26
+ organizationId: owned.organizationId,
27
+ policies: [authority.directory.policy, authority.admins.policy],
28
+ stillCurrent: current,
29
+ });
30
+ const result = await work({
31
+ ...authority,
32
+ stillCurrent: current,
33
+ ...createCurrentOrganizationMutationRetention({
34
+ runtime,
35
+ authority,
36
+ protection,
37
+ readPages,
38
+ organizationId: owned.organizationId,
39
+ directoryRecovery: directoryRecovery(authority.directory.current),
40
+ stillCurrent: current,
41
+ }),
42
+ });
43
+ assertProjectionVerificationCurrent(current);
44
+ return result;
45
+ });
46
+ };
47
+ }
48
+ //# sourceMappingURL=runtimeCurrentOrganizationMutation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtimeCurrentOrganizationMutation.js","sourceRoot":"","sources":["runtimeCurrentOrganizationMutation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,kCAAkC,EAAE,MAAM,2DAA2D,CAAC;AAG/G,OAAO,EAAE,wCAAwC,EAAE,MAAM,wCAAwC,CAAC;AAClG,OAAO,EAAE,0CAA0C,EAAE,MAAM,wCAAwC,CAAC;AACpG,OAAO,EAAE,mCAAmC,EAAE,MAAM,iCAAiC,CAAC;AAmBtF,mFAAmF;AACnF,MAAM,UAAU,wCAAwC,CAAC,OAAgB;IACvE,MAAM,KAAK,GAAG,mCAAmC,CAAC,OAAO,CAAC,CAAC;IAC3D,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,OAAO,KAAK,EACV,KAAY,EACZ,IAAiE,EACrD,EAAE;QACd,MAAM,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;QAC3B,OAAO,KAAK,CACV,KAAK,CAAC,YAAY,EAClB,KAAK,EAAE,EACL,UAAU,EACV,SAAS,EACT,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,GAClB,EAAE,EAAE;YACH,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,wCAAwC,CAAC;gBACnE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;gBAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,+BAA+B,EAAE,CAAC,cAAc,EAAE,EAAE,CAClD,OAAO,CAAC,SAAS,CAAC,+BAA+B,CAAC,cAAc,CAAC;gBACnE,oBAAoB;gBACpB,YAAY;aACb,CAAC,CAAC;YACH,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;YACjE,MAAM,kCAAkC,CAAC;gBACvC,MAAM,EAAE,EAAE;gBACV,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;gBAC9B,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,QAAQ,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;gBAC/D,YAAY,EAAE,OAAO;aACtB,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC;gBACxB,GAAG,SAAS;gBACZ,YAAY,EAAE,OAAO;gBACrB,GAAG,0CAA0C,CAAC;oBAC5C,OAAO;oBACP,SAAS;oBACT,UAAU;oBACV,SAAS;oBACT,cAAc,EAAE,KAAK,CAAC,cAAc;oBACpC,iBAAiB,EAAE,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC;oBACjE,YAAY,EAAE,OAAO;iBACtB,CAAC;aACH,CAAC,CAAC;YACH,mCAAmC,CAAC,OAAO,CAAC,CAAC;YAC7C,OAAO,MAAM,CAAC;QAChB,CAAC,CACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { advanceKeyingCheckpointsAtomically } from \"../../data/persistence/keyingCheckpointAdvancePersistence\";\nimport type { PrincipalPolicyRecoveryRuntime } from \"../principals/runtimePolicyRecovery\";\nimport type { loadCurrentOrganizationAuthority } from \"./currentOrganizationAuthority\";\nimport { loadCurrentOrganizationMutationAuthority } from \"./currentOrganizationMutationAuthority\";\nimport { createCurrentOrganizationMutationRetention } from \"./currentOrganizationMutationRetention\";\nimport { createCurrentPrincipalMutationLease } from \"./currentPrincipalMutationLease\";\nimport type { PrincipalMutationRecoveryApi } from \"./principalMutationJournalManagement\";\n\ntype Runtime = PrincipalPolicyRecoveryRuntime & {\n readonly apiClient: PrincipalPolicyRecoveryRuntime[\"apiClient\"] &\n Pick<PrincipalMutationRecoveryApi, \"recoverPendingPrincipalMutation\">;\n};\n\ninterface Input {\n readonly organizationId: string;\n readonly signerUserId: string;\n readonly stillCurrent: () => boolean;\n}\n\ntype Authority = Awaited<ReturnType<typeof loadCurrentOrganizationAuthority>>;\n\nexport type CurrentOrganizationMutationContext = Authority &\n ReturnType<typeof createCurrentOrganizationMutationRetention>;\n\n/** Keep directory authoring and exact acknowledgement inside one private lease. */\nexport function createRuntimeCurrentOrganizationMutation(runtime: Runtime) {\n const lease = createCurrentPrincipalMutationLease(runtime);\n if (!lease) return undefined;\n return async <T>(\n input: Input,\n work: (context: CurrentOrganizationMutationContext) => Promise<T>,\n ): Promise<T> => {\n const owned = { ...input };\n return lease(\n owned.stillCurrent,\n async ({\n protection,\n readPages,\n stillCurrent,\n resolveCurrentPolicy,\n directoryRecovery,\n }) => {\n const { authority } = await loadCurrentOrganizationMutationAuthority({\n execSql: runtime.infra.execSql,\n organizationId: owned.organizationId,\n signerUserId: owned.signerUserId,\n recoverPendingPrincipalMutation: (organizationId) =>\n runtime.apiClient.recoverPendingPrincipalMutation(organizationId),\n resolveCurrentPolicy,\n stillCurrent,\n });\n const current = () => stillCurrent() && authority.stillCurrent();\n await advanceKeyingCheckpointsAtomically({\n access: [],\n execSql: runtime.infra.execSql,\n organizationId: owned.organizationId,\n policies: [authority.directory.policy, authority.admins.policy],\n stillCurrent: current,\n });\n const result = await work({\n ...authority,\n stillCurrent: current,\n ...createCurrentOrganizationMutationRetention({\n runtime,\n authority,\n protection,\n readPages,\n organizationId: owned.organizationId,\n directoryRecovery: directoryRecovery(authority.directory.current),\n stillCurrent: current,\n }),\n });\n assertProjectionVerificationCurrent(current);\n return result;\n },\n );\n };\n}\n"]}
@@ -0,0 +1,11 @@
1
+ import { type PrincipalPolicyStateChainEntryResponse } from "../../internal/validators/response/index.js";
2
+ import { type RecoverPrincipalPolicyHistoryOptions } from "./principalHistoryRecoveryTypes.js";
3
+ export declare const PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE = 32;
4
+ export interface RecoveredPrincipalHistoryPage {
5
+ /** Ascending entries, with the immediate predecessor kept separately for diffs. */
6
+ readonly entries: readonly PrincipalPolicyStateChainEntryResponse[];
7
+ readonly predecessor: PrincipalPolicyStateChainEntryResponse | null;
8
+ readonly nextBeforeVersion: number | null;
9
+ }
10
+ /** Read a bounded historical window from an already recovered, exact private root. */
11
+ export declare function loadRecoveredPrincipalHistoryPage(options: RecoverPrincipalPolicyHistoryOptions, beforeVersion?: number): Promise<RecoveredPrincipalHistoryPage>;
@@ -0,0 +1,120 @@
1
+ import { KeyingVerificationError, verifyPrincipalPolicyHistoryReferences, } from "../../internal/crypto/index.js";
2
+ import { isPrincipalPolicyStateChainEntryResponse, } from "../../internal/validators/response/index.js";
3
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
4
+ import { loadPrincipalPolicyCheckpoint } from "../../data/persistence/keyingCheckpointPersistence.js";
5
+ import { loadPrincipalHistoryReference } from "../../data/persistence/principalHistoryEvidencePersistence.js";
6
+ import { principalHistoryEvidenceScopeId } from "../../data/principals/principalHistoryPrefixProtection.js";
7
+ import { ownPrincipalHistoryProtection } from "../../data/principals/principalHistoryProtection.js";
8
+ import { loadVerifiedPrincipalHistoryPrefix } from "./principalHistoryRecoveryPrefix.js";
9
+ import { PrincipalHistoryEvidenceUnavailableError } from "./principalHistoryRecoveryReferences.js";
10
+ import { PrincipalHistoryRecoveryRaceError, } from "./principalHistoryRecoveryTypes.js";
11
+ import { principalHistoryVerificationContext } from "./principalHistoryRecoveryVerification.js";
12
+ export const PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE = 32;
13
+ /** Read a bounded historical window from an already recovered, exact private root. */
14
+ export async function loadRecoveredPrincipalHistoryPage(options, beforeVersion = options.expectedHead.version + 1) {
15
+ const owned = {
16
+ ...options,
17
+ expectedHead: structuredClone(options.expectedHead),
18
+ protection: ownPrincipalHistoryProtection(options.protection),
19
+ };
20
+ try {
21
+ return await readPage(owned, beforeVersion);
22
+ }
23
+ finally {
24
+ owned.protection.localKey.fill(0);
25
+ }
26
+ }
27
+ async function readPage(options, beforeVersion) {
28
+ if (!Number.isSafeInteger(beforeVersion) ||
29
+ beforeVersion <= 1 ||
30
+ beforeVersion > options.expectedHead.version + 1)
31
+ throw new KeyingVerificationError("invalid_shape", "Principal history page cursor is outside the selected history");
32
+ const current = () => !options.signal?.aborted && options.stillCurrent();
33
+ assertProjectionVerificationCurrent(current);
34
+ const { scopeId, history } = await restoreReadRoot(options, current);
35
+ const checkpoint = await loadPrincipalPolicyCheckpoint(options.execSql, options.expectedHead.principalType, options.expectedHead.principalId);
36
+ if (checkpoint && checkpoint.version > options.expectedHead.version)
37
+ throw new PrincipalHistoryRecoveryRaceError("Principal checkpoint advanced beyond the selected display history");
38
+ const load = (version) => loadPageReference({
39
+ execSql: options.execSql,
40
+ scopeId,
41
+ history,
42
+ version,
43
+ });
44
+ const firstVersion = Math.max(1, beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE);
45
+ const references = [];
46
+ for (let version = Math.max(1, firstVersion - 1); version < beforeVersion; version += 1) {
47
+ assertProjectionVerificationCurrent(current);
48
+ references.push(await load(version));
49
+ }
50
+ const checkpointReference = checkpoint
51
+ ? await load(checkpoint.version)
52
+ : undefined;
53
+ if (checkpointReference &&
54
+ checkpointReference.reference.stateHash !== checkpoint?.stateHash)
55
+ throw new KeyingVerificationError("equivocation", "Principal history page conflicts with its durable checkpoint");
56
+ const selected = await verifyPrincipalPolicyHistoryReferences({
57
+ history,
58
+ references,
59
+ checkpointReference,
60
+ });
61
+ if (!selected.ok)
62
+ throw new PrincipalHistoryEvidenceUnavailableError(selected.error);
63
+ await assertDisplayCheckpointCurrent(options, checkpoint);
64
+ assertProjectionVerificationCurrent(current);
65
+ // These exact rows passed inclusion and commitment verification above. Keep
66
+ // their display-only server timestamps, which the private current strips.
67
+ const retained = references.map(({ entry }) => responseEntry(entry));
68
+ return {
69
+ entries: retained.filter(({ state }) => state.version >= firstVersion && state.version < beforeVersion),
70
+ predecessor: retained.find(({ state }) => state.version === firstVersion - 1) ?? null,
71
+ nextBeforeVersion: firstVersion > 1 ? firstVersion : null,
72
+ };
73
+ }
74
+ async function assertDisplayCheckpointCurrent(options, checkpoint) {
75
+ const latest = await loadPrincipalPolicyCheckpoint(options.execSql, options.expectedHead.principalType, options.expectedHead.principalId);
76
+ if (latest?.version !== checkpoint?.version ||
77
+ latest?.stateHash !== checkpoint?.stateHash)
78
+ throw new PrincipalHistoryRecoveryRaceError("Principal checkpoint changed while reading display history");
79
+ }
80
+ async function loadPageReference(input) {
81
+ try {
82
+ return await loadPrincipalHistoryReference(input);
83
+ }
84
+ catch (error) {
85
+ if (error instanceof KeyingVerificationError)
86
+ throw new PrincipalHistoryEvidenceUnavailableError(error);
87
+ throw error;
88
+ }
89
+ }
90
+ function responseEntry(entry) {
91
+ if (!isPrincipalPolicyStateChainEntryResponse(entry))
92
+ throw new KeyingVerificationError("missing_dependency", "Principal history display metadata is unavailable");
93
+ return entry;
94
+ }
95
+ async function restoreReadRoot(options, current) {
96
+ const normalized = {
97
+ ...options,
98
+ protection: {
99
+ ...options.protection,
100
+ context: principalHistoryVerificationContext(options),
101
+ },
102
+ };
103
+ const scopeId = await principalHistoryEvidenceScopeId({
104
+ organizationId: options.organizationId,
105
+ head: options.expectedHead,
106
+ protection: normalized.protection,
107
+ });
108
+ const prefix = await loadVerifiedPrincipalHistoryPrefix(normalized, {
109
+ principalType: options.expectedHead.principalType,
110
+ principalId: options.expectedHead.principalId,
111
+ }, scopeId);
112
+ assertProjectionVerificationCurrent(current);
113
+ if (!prefix)
114
+ throw new KeyingVerificationError("missing_dependency", "Principal history page requires a recovered private prefix");
115
+ const finished = prefix.verifier.finish(options.expectedHead);
116
+ if (!finished.ok)
117
+ throw finished.error;
118
+ return { scopeId, history: finished.value };
119
+ }
120
+ //# sourceMappingURL=loadRecoveredPrincipalHistoryPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadRecoveredPrincipalHistoryPage.js","sourceRoot":"","sources":["loadRecoveredPrincipalHistoryPage.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyHistoryReferenceProof,\n type PrincipalPolicyStateChainEntry,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport {\n isPrincipalPolicyStateChainEntryResponse,\n type PrincipalPolicyStateChainEntryResponse,\n} from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalPolicyCheckpoint } from \"../../data/persistence/keyingCheckpointPersistence\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport { principalHistoryEvidenceScopeId } from \"../../data/principals/principalHistoryPrefixProtection\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport { loadVerifiedPrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport { PrincipalHistoryEvidenceUnavailableError } from \"./principalHistoryRecoveryReferences\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport { principalHistoryVerificationContext } from \"./principalHistoryRecoveryVerification\";\n\nexport const PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE = 32;\n\nexport interface RecoveredPrincipalHistoryPage {\n /** Ascending entries, with the immediate predecessor kept separately for diffs. */\n readonly entries: readonly PrincipalPolicyStateChainEntryResponse[];\n readonly predecessor: PrincipalPolicyStateChainEntryResponse | null;\n readonly nextBeforeVersion: number | null;\n}\n\n/** Read a bounded historical window from an already recovered, exact private root. */\nexport async function loadRecoveredPrincipalHistoryPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion = options.expectedHead.version + 1,\n): Promise<RecoveredPrincipalHistoryPage> {\n const owned = {\n ...options,\n expectedHead: structuredClone(options.expectedHead),\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n return await readPage(owned, beforeVersion);\n } finally {\n owned.protection.localKey.fill(0);\n }\n}\n\nasync function readPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion: number,\n): Promise<RecoveredPrincipalHistoryPage> {\n if (\n !Number.isSafeInteger(beforeVersion) ||\n beforeVersion <= 1 ||\n beforeVersion > options.expectedHead.version + 1\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal history page cursor is outside the selected history\",\n );\n const current = () => !options.signal?.aborted && options.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const { scopeId, history } = await restoreReadRoot(options, current);\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n options.execSql,\n options.expectedHead.principalType,\n options.expectedHead.principalId,\n );\n if (checkpoint && checkpoint.version > options.expectedHead.version)\n throw new PrincipalHistoryRecoveryRaceError(\n \"Principal checkpoint advanced beyond the selected display history\",\n );\n const load = (version: number) =>\n loadPageReference({\n execSql: options.execSql,\n scopeId,\n history,\n version,\n });\n const firstVersion = Math.max(\n 1,\n beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE,\n );\n const references: PrincipalPolicyHistoryReferenceProof[] = [];\n for (\n let version = Math.max(1, firstVersion - 1);\n version < beforeVersion;\n version += 1\n ) {\n assertProjectionVerificationCurrent(current);\n references.push(await load(version));\n }\n const checkpointReference = checkpoint\n ? await load(checkpoint.version)\n : undefined;\n if (\n checkpointReference &&\n checkpointReference.reference.stateHash !== checkpoint?.stateHash\n )\n throw new KeyingVerificationError(\n \"equivocation\",\n \"Principal history page conflicts with its durable checkpoint\",\n );\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok)\n throw new PrincipalHistoryEvidenceUnavailableError(selected.error);\n await assertDisplayCheckpointCurrent(options, checkpoint);\n assertProjectionVerificationCurrent(current);\n // These exact rows passed inclusion and commitment verification above. Keep\n // their display-only server timestamps, which the private current strips.\n const retained = references.map(({ entry }) => responseEntry(entry));\n return {\n entries: retained.filter(\n ({ state }) =>\n state.version >= firstVersion && state.version < beforeVersion,\n ),\n predecessor:\n retained.find(({ state }) => state.version === firstVersion - 1) ?? null,\n nextBeforeVersion: firstVersion > 1 ? firstVersion : null,\n };\n}\n\nasync function assertDisplayCheckpointCurrent(\n options: RecoverPrincipalPolicyHistoryOptions,\n checkpoint: Awaited<ReturnType<typeof loadPrincipalPolicyCheckpoint>>,\n) {\n const latest = await loadPrincipalPolicyCheckpoint(\n options.execSql,\n options.expectedHead.principalType,\n options.expectedHead.principalId,\n );\n if (\n latest?.version !== checkpoint?.version ||\n latest?.stateHash !== checkpoint?.stateHash\n )\n throw new PrincipalHistoryRecoveryRaceError(\n \"Principal checkpoint changed while reading display history\",\n );\n}\n\nasync function loadPageReference(\n input: Parameters<typeof loadPrincipalHistoryReference>[0],\n) {\n try {\n return await loadPrincipalHistoryReference(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n}\n\nfunction responseEntry(\n entry: PrincipalPolicyStateChainEntry,\n): PrincipalPolicyStateChainEntryResponse {\n if (!isPrincipalPolicyStateChainEntryResponse(entry))\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history display metadata is unavailable\",\n );\n return entry;\n}\n\nasync function restoreReadRoot(\n options: RecoverPrincipalPolicyHistoryOptions,\n current: () => boolean,\n) {\n const normalized = {\n ...options,\n protection: {\n ...options.protection,\n context: principalHistoryVerificationContext(options),\n },\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: options.organizationId,\n head: options.expectedHead,\n protection: normalized.protection,\n });\n const prefix = await loadVerifiedPrincipalHistoryPrefix(\n normalized,\n {\n principalType: options.expectedHead.principalType,\n principalId: options.expectedHead.principalId,\n },\n scopeId,\n );\n assertProjectionVerificationCurrent(current);\n if (!prefix)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history page requires a recovered private prefix\",\n );\n const finished = prefix.verifier.finish(options.expectedHead);\n if (!finished.ok) throw finished.error;\n return { scopeId, history: finished.value };\n}\n"]}
@@ -22,6 +22,14 @@ async function selectReferences(input) {
22
22
  version: reference.version,
23
23
  }));
24
24
  }
25
+ const versions = new Set((options.retainedReferences ?? []).map((reference) => reference.version));
26
+ for (const version of options.retainedVersions ?? []) {
27
+ if (versions.has(version))
28
+ continue;
29
+ versions.add(version);
30
+ assertProjectionVerificationCurrent(current);
31
+ references.push(await loadPrincipalHistoryReference({ ...base, version }));
32
+ }
25
33
  assertProjectionVerificationCurrent(current);
26
34
  const checkpointReference = input.checkpoint
27
35
  ? await loadPrincipalHistoryReference({
@@ -1 +1 @@
1
- {"version":3,"file":"principalHistoryRecoveryReferences.js","sourceRoot":"","sources":["principalHistoryRecoveryReferences.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EAIvB,sCAAsC,GACvC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,4DAA4D,CAAC;AAC3G,OAAO,EAAE,6BAA6B,EAAE,MAAM,uDAAuD,CAAC;AAGtG,MAAM,OAAO,wCAAyC,SAAQ,KAAK;IAC5C;IAArB,YAAqB,iBAA0C;QAC7D,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QADd,sBAAiB,GAAjB,iBAAiB,CAAyB;QAE7D,IAAI,CAAC,IAAI,GAAG,0CAA0C,CAAC;IACzD,CAAC;CACF;AAED,KAAK,UAAU,gBAAgB,CAAC,KAK/B;IACC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC5C,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IACzE,MAAM,IAAI,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;IAC5D,MAAM,UAAU,GAA2C,EAAE,CAAC;IAC9D,KAAK,MAAM,SAAS,IAAI,OAAO,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC;QACzD,mCAAmC,CAAC,OAAO,CAAC,CAAC;QAC7C,UAAU,CAAC,IAAI,CACb,MAAM,6BAA6B,CAAC;YAClC,GAAG,IAAI;YACP,OAAO,EAAE,SAAS,CAAC,OAAO;SAC3B,CAAC,CACH,CAAC;IACJ,CAAC;IACD,mCAAmC,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,mBAAmB,GAAG,KAAK,CAAC,UAAU;QAC1C,CAAC,CAAC,MAAM,6BAA6B,CAAC;YAClC,GAAG,IAAI;YACP,OAAO,EAAE,KAAK,CAAC,UAAU,CAAC,OAAO;SAClC,CAAC;QACJ,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,QAAQ,GAAG,MAAM,sCAAsC,CAAC;QAC5D,OAAO;QACP,UAAU;QACV,mBAAmB;KACpB,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,QAAQ,CAAC,KAAK,CAAC;IACvC,mCAAmC,CAAC,OAAO,CAAC,CAAC;IAC7C,OAAO,QAAQ,CAAC,KAAK,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,KAA6C;IAE7C,IAAI,QAAwC,CAAC;IAC7C,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,uBAAuB;YAC1C,MAAM,IAAI,wCAAwC,CAAC,KAAK,CAAC,CAAC;QAC5D,MAAM,KAAK,CAAC;IACd,CAAC;IACD,0EAA0E;IAC1E,gFAAgF;IAChF,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC;QAC/D,IACE,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAC3C,6BAA6B,CAAC,KAAK,EAAE,SAAS,CAAC,CAChD;YAED,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,kEAAkE,CACnE,CAAC;IACN,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryReferenceProof,\n type VerifiedPrincipalPolicyHistory,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"./principalHistoryRecoveryTypes\";\n\nexport class PrincipalHistoryEvidenceUnavailableError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"PrincipalHistoryEvidenceUnavailableError\";\n }\n}\n\nasync function selectReferences(input: {\n readonly options: RecoverPrincipalPolicyHistoryOptions;\n readonly scopeId: string;\n readonly history: VerifiedPrincipalPolicyHistory;\n readonly checkpoint: PrincipalPolicyCheckpoint | null;\n}): Promise<VerifiedPrincipalPolicyHistory> {\n const { options, scopeId, history } = input;\n const current = () => !options.signal?.aborted && options.stillCurrent();\n const base = { execSql: options.execSql, scopeId, history };\n const references: PrincipalPolicyHistoryReferenceProof[] = [];\n for (const reference of options.retainedReferences ?? []) {\n assertProjectionVerificationCurrent(current);\n references.push(\n await loadPrincipalHistoryReference({\n ...base,\n version: reference.version,\n }),\n );\n }\n assertProjectionVerificationCurrent(current);\n const checkpointReference = input.checkpoint\n ? await loadPrincipalHistoryReference({\n ...base,\n version: input.checkpoint.version,\n })\n : undefined;\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok) throw selected.error;\n assertProjectionVerificationCurrent(current);\n return selected.value;\n}\n\nexport async function selectRecoveredPrincipalHistory(\n input: Parameters<typeof selectReferences>[0],\n): Promise<VerifiedPrincipalPolicyHistory> {\n let selected: VerifiedPrincipalPolicyHistory;\n try {\n selected = await selectReferences(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n // First authenticate the stored entry against the private root. Only then\n // compare the caller's citation, so a bad request is not treated as cache loss.\n for (const reference of input.options.retainedReferences ?? []) {\n if (\n !selected.retainedEntries.some(({ state }) =>\n principalHeadMatchesReference(state, reference),\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Requested citation does not match the verified principal history\",\n );\n }\n return selected;\n}\n"]}
1
+ {"version":3,"file":"principalHistoryRecoveryReferences.js","sourceRoot":"","sources":["principalHistoryRecoveryReferences.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryReferenceProof,\n type VerifiedPrincipalPolicyHistory,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"./principalHistoryRecoveryTypes\";\n\nexport interface PrincipalHistorySelectionOptions\n extends RecoverPrincipalPolicyHistoryOptions {\n /** Internal page selection by version; every selected row still needs a private-root proof. */\n readonly retainedVersions?: readonly number[] | undefined;\n}\n\nexport class PrincipalHistoryEvidenceUnavailableError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"PrincipalHistoryEvidenceUnavailableError\";\n }\n}\n\nasync function selectReferences(input: {\n readonly options: PrincipalHistorySelectionOptions;\n readonly scopeId: string;\n readonly history: VerifiedPrincipalPolicyHistory;\n readonly checkpoint: PrincipalPolicyCheckpoint | null;\n}): Promise<VerifiedPrincipalPolicyHistory> {\n const { options, scopeId, history } = input;\n const current = () => !options.signal?.aborted && options.stillCurrent();\n const base = { execSql: options.execSql, scopeId, history };\n const references: PrincipalPolicyHistoryReferenceProof[] = [];\n for (const reference of options.retainedReferences ?? []) {\n assertProjectionVerificationCurrent(current);\n references.push(\n await loadPrincipalHistoryReference({\n ...base,\n version: reference.version,\n }),\n );\n }\n const versions = new Set(\n (options.retainedReferences ?? []).map((reference) => reference.version),\n );\n for (const version of options.retainedVersions ?? []) {\n if (versions.has(version)) continue;\n versions.add(version);\n assertProjectionVerificationCurrent(current);\n references.push(await loadPrincipalHistoryReference({ ...base, version }));\n }\n assertProjectionVerificationCurrent(current);\n const checkpointReference = input.checkpoint\n ? await loadPrincipalHistoryReference({\n ...base,\n version: input.checkpoint.version,\n })\n : undefined;\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references,\n checkpointReference,\n });\n if (!selected.ok) throw selected.error;\n assertProjectionVerificationCurrent(current);\n return selected.value;\n}\n\nexport async function selectRecoveredPrincipalHistory(\n input: Parameters<typeof selectReferences>[0],\n): Promise<VerifiedPrincipalPolicyHistory> {\n let selected: VerifiedPrincipalPolicyHistory;\n try {\n selected = await selectReferences(input);\n } catch (error) {\n if (error instanceof KeyingVerificationError)\n throw new PrincipalHistoryEvidenceUnavailableError(error);\n throw error;\n }\n // First authenticate the stored entry against the private root. Only then\n // compare the caller's citation, so a bad request is not treated as cache loss.\n for (const reference of input.options.retainedReferences ?? []) {\n if (\n !selected.retainedEntries.some(({ state }) =>\n principalHeadMatchesReference(state, reference),\n )\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Requested citation does not match the verified principal history\",\n );\n }\n return selected;\n}\n"]}
@@ -1,8 +1,9 @@
1
- import { KeyingVerificationError, serializeKeyingCanonicalJson, verifyPrincipalPolicyHistoryReferences, } from "../../internal/crypto/index.js";
1
+ import { KeyingVerificationError, verifyPrincipalPolicyHistoryReferences, } from "../../internal/crypto/index.js";
2
2
  import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
3
3
  import { loadPrincipalHistoryReference } from "../../data/persistence/principalHistoryEvidencePersistence.js";
4
4
  import { parseOrganizationAuthorityDescriptor, } from "../../data/principals/organizationAuthorityDescriptor.js";
5
5
  import { principalHistoryEvidenceScopeId } from "../../data/principals/principalHistoryPrefixProtection.js";
6
+ import { directoryHistoryProtection } from "../../data/principals/principalHistoryScopeProtection.js";
6
7
  import { loadVerifiedPrincipalHistoryPrefix } from "./principalHistoryRecoveryPrefix.js";
7
8
  import { PrincipalPolicyHistoryReadError, } from "./principalHistoryRecoveryTypes.js";
8
9
  import { reusePrincipalDiscoveryPage } from "./principalRecoveryDiscoveryPage.js";
@@ -91,13 +92,7 @@ async function discoverDirectoryHead(input) {
91
92
  export async function recoverPolicyDirectory(input, references, selected) {
92
93
  const scoped = {
93
94
  ...input,
94
- protection: {
95
- localKey: input.protection.localKey,
96
- context: serializeKeyingCanonicalJson([
97
- "tearleads.sdk.principal-history.directory.v1",
98
- input.protection.context,
99
- ]),
100
- },
95
+ protection: directoryHistoryProtection(input.protection),
101
96
  };
102
97
  const { head: expectedHead, genesis, apiClient, } = selected
103
98
  ? {
@@ -1 +1 @@
1
- {"version":3,"file":"principalRecoveryDirectory.js","sourceRoot":"","sources":["principalRecoveryDirectory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type ReferencedPrincipalHead,\n serializeKeyingCanonicalJson,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport {\n type OrganizationAuthorityDescriptor,\n parseOrganizationAuthorityDescriptor,\n} from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { principalHistoryEvidenceScopeId } from \"../../data/principals/principalHistoryPrefixProtection\";\nimport { loadVerifiedPrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport {\n PrincipalPolicyHistoryReadError,\n type RecoveredPrincipalPolicyHistory,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport { reusePrincipalDiscoveryPage } from \"./principalRecoveryDiscoveryPage\";\nimport { recoverPrincipalPolicyHistory } from \"./recoverPrincipalPolicyHistory\";\n\nexport type PrincipalRecoveryContext = Omit<\n RecoverPrincipalPolicyHistoryOptions,\n | \"expectedHead\"\n | \"retainedReferences\"\n | \"historyVerification\"\n | \"loadExternalAuthority\"\n>;\n\nexport interface RecoveredPolicyDirectory\n extends RecoveredPrincipalPolicyHistory {\n readonly descriptor: OrganizationAuthorityDescriptor;\n}\n\nexport class PrincipalRecoveryDirectoryAdvanced extends Error {}\n\nfunction exactHead(state: ReferencedPrincipalHead): ReferencedPrincipalHead {\n return {\n principalType: state.principalType,\n principalId: state.principalId,\n version: state.version,\n stateHash: state.stateHash,\n keyEpoch: state.keyEpoch,\n keyFingerprint: state.keyFingerprint,\n };\n}\n\n/** An unverified discovery read chooses a pin; recovery must authenticate it. */\nasync function discoverDirectoryHead(input: PrincipalRecoveryContext): Promise<{\n head: ReferencedPrincipalHead;\n genesis: ReferencedPrincipalHead;\n apiClient: PrincipalRecoveryContext[\"apiClient\"];\n}> {\n assertProjectionVerificationCurrent(\n () => !input.signal?.aborted && input.stillCurrent(),\n );\n if (input.offline) {\n const principal = {\n principalType: \"organization\" as const,\n principalId: input.organizationId,\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: input.organizationId,\n head: principal,\n protection: input.protection,\n });\n const prefix = await loadVerifiedPrincipalHistoryPrefix(\n input,\n principal,\n scopeId,\n );\n if (!prefix)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory is unavailable offline\",\n );\n const history = prefix.verifier.finish(prefix.head);\n if (!history.ok) throw history.error;\n const genesis = await loadPrincipalHistoryReference({\n execSql: input.execSql,\n scopeId,\n history: history.value,\n version: 1,\n });\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history: history.value,\n references: [genesis],\n });\n if (!selected.ok) throw selected.error;\n return {\n head: prefix.head,\n genesis: genesis.reference,\n apiClient: input.apiClient,\n };\n }\n for await (const result of input.apiClient.getPrincipalPolicyPages(\n \"organization\",\n input.organizationId,\n { signal: input.signal },\n )) {\n if (!result.ok) throw new PrincipalPolicyHistoryReadError(result);\n assertProjectionVerificationCurrent(\n () => !input.signal?.aborted && input.stillCurrent(),\n );\n const state = result.data.currentState;\n const first = result.data.previousStates[0]?.state ?? state;\n if (\n first.version !== 1 ||\n first.principalType !== \"organization\" ||\n first.principalId !== input.organizationId\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory discovery requires genesis\",\n );\n return {\n apiClient: reusePrincipalDiscoveryPage(input.apiClient, result),\n genesis: {\n principalType: first.principalType,\n principalId: first.principalId,\n version: first.version,\n stateHash: first.stateHash,\n keyEpoch: first.keyEpoch,\n keyFingerprint: first.keyFingerprint,\n },\n head: {\n principalType: \"organization\",\n principalId: input.organizationId,\n version: state.version,\n stateHash: state.stateHash,\n keyEpoch: state.keyEpoch,\n keyFingerprint: state.keyFingerprint,\n },\n };\n }\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory head is unavailable\",\n );\n}\n\nexport async function recoverPolicyDirectory(\n input: PrincipalRecoveryContext,\n references: readonly ReferencedPrincipalHead[],\n selected?: RecoveredPolicyDirectory,\n): Promise<RecoveredPolicyDirectory> {\n const scoped = {\n ...input,\n protection: {\n localKey: input.protection.localKey,\n context: serializeKeyingCanonicalJson([\n \"tearleads.sdk.principal-history.directory.v1\",\n input.protection.context,\n ]),\n },\n };\n const {\n head: expectedHead,\n genesis,\n apiClient,\n } = selected\n ? {\n head: exactHead(selected.policy.state),\n genesis: selected.policy.retainedHistory[0]?.state,\n apiClient: input.apiClient,\n }\n : await discoverDirectoryHead(scoped);\n if (genesis?.version !== 1)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory recovery requires verified genesis\",\n );\n if (references.some((reference) => reference.version > expectedHead.version))\n throw new PrincipalRecoveryDirectoryAdvanced();\n const recovered = await recoverPrincipalPolicyHistory({\n ...scoped,\n apiClient,\n expectedHead,\n retainedReferences: references.some((reference) => reference.version === 1)\n ? references\n : [exactHead(genesis), ...references],\n });\n let descriptor: OrganizationAuthorityDescriptor;\n try {\n descriptor = parseOrganizationAuthorityDescriptor(\n recovered.current.currentPayload.ciphertext,\n );\n } catch {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Organization directory payload is invalid\",\n );\n }\n if (descriptor.organizationId !== input.organizationId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Organization directory scope does not match\",\n );\n return { ...recovered, descriptor };\n}\n"]}
1
+ {"version":3,"file":"principalRecoveryDirectory.js","sourceRoot":"","sources":["principalRecoveryDirectory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type ReferencedPrincipalHead,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport {\n type OrganizationAuthorityDescriptor,\n parseOrganizationAuthorityDescriptor,\n} from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { principalHistoryEvidenceScopeId } from \"../../data/principals/principalHistoryPrefixProtection\";\nimport { directoryHistoryProtection } from \"../../data/principals/principalHistoryScopeProtection\";\nimport { loadVerifiedPrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport {\n PrincipalPolicyHistoryReadError,\n type RecoveredPrincipalPolicyHistory,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport { reusePrincipalDiscoveryPage } from \"./principalRecoveryDiscoveryPage\";\nimport { recoverPrincipalPolicyHistory } from \"./recoverPrincipalPolicyHistory\";\n\nexport type PrincipalRecoveryContext = Omit<\n RecoverPrincipalPolicyHistoryOptions,\n | \"expectedHead\"\n | \"retainedReferences\"\n | \"historyVerification\"\n | \"loadExternalAuthority\"\n>;\n\nexport interface RecoveredPolicyDirectory\n extends RecoveredPrincipalPolicyHistory {\n readonly descriptor: OrganizationAuthorityDescriptor;\n}\n\nexport class PrincipalRecoveryDirectoryAdvanced extends Error {}\n\nfunction exactHead(state: ReferencedPrincipalHead): ReferencedPrincipalHead {\n return {\n principalType: state.principalType,\n principalId: state.principalId,\n version: state.version,\n stateHash: state.stateHash,\n keyEpoch: state.keyEpoch,\n keyFingerprint: state.keyFingerprint,\n };\n}\n\n/** An unverified discovery read chooses a pin; recovery must authenticate it. */\nasync function discoverDirectoryHead(input: PrincipalRecoveryContext): Promise<{\n head: ReferencedPrincipalHead;\n genesis: ReferencedPrincipalHead;\n apiClient: PrincipalRecoveryContext[\"apiClient\"];\n}> {\n assertProjectionVerificationCurrent(\n () => !input.signal?.aborted && input.stillCurrent(),\n );\n if (input.offline) {\n const principal = {\n principalType: \"organization\" as const,\n principalId: input.organizationId,\n };\n const scopeId = await principalHistoryEvidenceScopeId({\n organizationId: input.organizationId,\n head: principal,\n protection: input.protection,\n });\n const prefix = await loadVerifiedPrincipalHistoryPrefix(\n input,\n principal,\n scopeId,\n );\n if (!prefix)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory is unavailable offline\",\n );\n const history = prefix.verifier.finish(prefix.head);\n if (!history.ok) throw history.error;\n const genesis = await loadPrincipalHistoryReference({\n execSql: input.execSql,\n scopeId,\n history: history.value,\n version: 1,\n });\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history: history.value,\n references: [genesis],\n });\n if (!selected.ok) throw selected.error;\n return {\n head: prefix.head,\n genesis: genesis.reference,\n apiClient: input.apiClient,\n };\n }\n for await (const result of input.apiClient.getPrincipalPolicyPages(\n \"organization\",\n input.organizationId,\n { signal: input.signal },\n )) {\n if (!result.ok) throw new PrincipalPolicyHistoryReadError(result);\n assertProjectionVerificationCurrent(\n () => !input.signal?.aborted && input.stillCurrent(),\n );\n const state = result.data.currentState;\n const first = result.data.previousStates[0]?.state ?? state;\n if (\n first.version !== 1 ||\n first.principalType !== \"organization\" ||\n first.principalId !== input.organizationId\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory discovery requires genesis\",\n );\n return {\n apiClient: reusePrincipalDiscoveryPage(input.apiClient, result),\n genesis: {\n principalType: first.principalType,\n principalId: first.principalId,\n version: first.version,\n stateHash: first.stateHash,\n keyEpoch: first.keyEpoch,\n keyFingerprint: first.keyFingerprint,\n },\n head: {\n principalType: \"organization\",\n principalId: input.organizationId,\n version: state.version,\n stateHash: state.stateHash,\n keyEpoch: state.keyEpoch,\n keyFingerprint: state.keyFingerprint,\n },\n };\n }\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory head is unavailable\",\n );\n}\n\nexport async function recoverPolicyDirectory(\n input: PrincipalRecoveryContext,\n references: readonly ReferencedPrincipalHead[],\n selected?: RecoveredPolicyDirectory,\n): Promise<RecoveredPolicyDirectory> {\n const scoped = {\n ...input,\n protection: directoryHistoryProtection(input.protection),\n };\n const {\n head: expectedHead,\n genesis,\n apiClient,\n } = selected\n ? {\n head: exactHead(selected.policy.state),\n genesis: selected.policy.retainedHistory[0]?.state,\n apiClient: input.apiClient,\n }\n : await discoverDirectoryHead(scoped);\n if (genesis?.version !== 1)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization directory recovery requires verified genesis\",\n );\n if (references.some((reference) => reference.version > expectedHead.version))\n throw new PrincipalRecoveryDirectoryAdvanced();\n const recovered = await recoverPrincipalPolicyHistory({\n ...scoped,\n apiClient,\n expectedHead,\n retainedReferences: references.some((reference) => reference.version === 1)\n ? references\n : [exactHead(genesis), ...references],\n });\n let descriptor: OrganizationAuthorityDescriptor;\n try {\n descriptor = parseOrganizationAuthorityDescriptor(\n recovered.current.currentPayload.ciphertext,\n );\n } catch {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Organization directory payload is invalid\",\n );\n }\n if (descriptor.organizationId !== input.organizationId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Organization directory scope does not match\",\n );\n return { ...recovered, descriptor };\n}\n"]}
@@ -3,7 +3,7 @@ import { assertProjectionVerificationCurrent } from "../../data/keyingProjection
3
3
  import { principalHeadMatchesReference } from "../../data/principals/organizationAuthorityDescriptor.js";
4
4
  import { PrincipalHistoryRecoveryRaceError } from "./principalHistoryRecoveryTypes.js";
5
5
  import { recoverWithPrincipalOutageFallback } from "./principalRecoveryOutage.js";
6
- /** Reuse authenticated local artifacts only for the exact current head a caller selected. */
6
+ /** Reuse exact current artifacts, or a proved historical page within a newer prefix. */
7
7
  export async function recoverWithPrincipalLocalPreference(recover, options, preferLocalCurrent) {
8
8
  if (preferLocalCurrent && !options.offline) {
9
9
  try {
@@ -12,7 +12,8 @@ export async function recoverWithPrincipalLocalPreference(recover, options, pref
12
12
  offline: true,
13
13
  });
14
14
  assertProjectionVerificationCurrent(options.stillCurrent);
15
- if (principalHeadMatchesReference(local.policy.state, options.reference))
15
+ if (options.historyPage ||
16
+ principalHeadMatchesReference(local.policy.state, options.reference))
16
17
  return local;
17
18
  }
18
19
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"principalRecoveryLocalPreference.js","sourceRoot":"","sources":["principalRecoveryLocalPreference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,kCAAkC,EAAE,MAAM,2BAA2B,CAAC;AAG/E,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,OAAmD,EACnD,OAAkE,EAClE,kBAA2B;IAE3B,IAAI,kBAAkB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC;gBAC1B,GAAG,OAAO;gBACV,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YACH,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC1D,IAAI,6BAA6B,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC;gBACtE,OAAO,KAAK,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC1D,IACE,CAAC,CAAC,KAAK,YAAY,iCAAiC,CAAC;gBACrD,CAAC,CACC,KAAK,YAAY,uBAAuB;oBACxC,KAAK,CAAC,IAAI,KAAK,oBAAoB,CACpC;gBAED,MAAM,KAAK,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,kCAAkC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { PrincipalHistoryRecoveryRaceError } from \"./principalHistoryRecoveryTypes\";\nimport { recoverWithPrincipalOutageFallback } from \"./principalRecoveryOutage\";\nimport type { recoverScopedPrincipalPolicyHistory } from \"./recoverScopedPrincipalPolicyHistory\";\n\n/** Reuse authenticated local artifacts only for the exact current head a caller selected. */\nexport async function recoverWithPrincipalLocalPreference(\n recover: typeof recoverScopedPrincipalPolicyHistory,\n options: Parameters<typeof recoverScopedPrincipalPolicyHistory>[0],\n preferLocalCurrent: boolean,\n) {\n if (preferLocalCurrent && !options.offline) {\n try {\n const local = await recover({\n ...options,\n offline: true,\n });\n assertProjectionVerificationCurrent(options.stillCurrent);\n if (principalHeadMatchesReference(local.policy.state, options.reference))\n return local;\n } catch (error) {\n assertProjectionVerificationCurrent(options.stillCurrent);\n if (\n !(error instanceof PrincipalHistoryRecoveryRaceError) &&\n !(\n error instanceof KeyingVerificationError &&\n error.code === \"missing_dependency\"\n )\n )\n throw error;\n }\n }\n return recoverWithPrincipalOutageFallback(recover, options);\n}\n"]}
1
+ {"version":3,"file":"principalRecoveryLocalPreference.js","sourceRoot":"","sources":["principalRecoveryLocalPreference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAAE,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,kCAAkC,EAAE,MAAM,2BAA2B,CAAC;AAG/E,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,mCAAmC,CACvD,OAAmD,EACnD,OAAkE,EAClE,kBAA2B;IAE3B,IAAI,kBAAkB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC;gBAC1B,GAAG,OAAO;gBACV,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YACH,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC1D,IACE,OAAO,CAAC,WAAW;gBACnB,6BAA6B,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC;gBAEpE,OAAO,KAAK,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC1D,IACE,CAAC,CAAC,KAAK,YAAY,iCAAiC,CAAC;gBACrD,CAAC,CACC,KAAK,YAAY,uBAAuB;oBACxC,KAAK,CAAC,IAAI,KAAK,oBAAoB,CACpC;gBAED,MAAM,KAAK,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,kCAAkC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { PrincipalHistoryRecoveryRaceError } from \"./principalHistoryRecoveryTypes\";\nimport { recoverWithPrincipalOutageFallback } from \"./principalRecoveryOutage\";\nimport type { recoverScopedPrincipalPolicyHistory } from \"./recoverScopedPrincipalPolicyHistory\";\n\n/** Reuse exact current artifacts, or a proved historical page within a newer prefix. */\nexport async function recoverWithPrincipalLocalPreference(\n recover: typeof recoverScopedPrincipalPolicyHistory,\n options: Parameters<typeof recoverScopedPrincipalPolicyHistory>[0],\n preferLocalCurrent: boolean,\n) {\n if (preferLocalCurrent && !options.offline) {\n try {\n const local = await recover({\n ...options,\n offline: true,\n });\n assertProjectionVerificationCurrent(options.stillCurrent);\n if (\n options.historyPage ||\n principalHeadMatchesReference(local.policy.state, options.reference)\n )\n return local;\n } catch (error) {\n assertProjectionVerificationCurrent(options.stillCurrent);\n if (\n !(error instanceof PrincipalHistoryRecoveryRaceError) &&\n !(\n error instanceof KeyingVerificationError &&\n error.code === \"missing_dependency\"\n )\n )\n throw error;\n }\n }\n return recoverWithPrincipalOutageFallback(recover, options);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"recoverCurrentOrganizationPolicy.js","sourceRoot":"","sources":["recoverCurrentOrganizationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,kDAAkD,CAAC;AAKjG,OAAO,EACL,6BAA6B,GAE9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,OAAiC,EACjC,IAA4B;IAE5B,MAAM,KAAK,GAAG;QACZ,GAAG,OAAO;QACV,UAAU,EAAE,6BAA6B,CAAC,OAAO,CAAC,UAAU,CAAC;KAC9D,CAAC;IACF,IAAI,CAAC;QACH,IAAI,SAA6D,CAAC;QAClE,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,6BAA6B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,CACpE,EAAE,CACH,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mCAAmC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACxD,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YACpE,SAAS,GAAG,MAAM,6BAA6B,CAC7C,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAC3B,IAAI,CACL,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QACD,mCAAmC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxD,OAAO;YACL,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;AACH,CAAC","sourcesContent":["import { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport type {\n PrincipalRecoveryContext,\n recoverPolicyDirectory,\n} from \"./principalRecoveryDirectory\";\nimport {\n createPrincipalRecoveryReader,\n type PrincipalRecoveryMemo,\n} from \"./principalRecoveryMemo\";\nimport { isPrincipalRecoveryOutage } from \"./principalRecoveryOutage\";\n\n/** Discover and verify current directory artifacts, including protected offline recovery. */\nexport async function recoverCurrentOrganizationPolicy(\n options: PrincipalRecoveryContext,\n memo?: PrincipalRecoveryMemo,\n) {\n const input = {\n ...options,\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n let directory: Awaited<ReturnType<typeof recoverPolicyDirectory>>;\n try {\n directory = await createPrincipalRecoveryReader(input, memo).directory(\n [],\n );\n } catch (error) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (input.offline || !isPrincipalRecoveryOutage(error)) throw error;\n directory = await createPrincipalRecoveryReader(\n { ...input, offline: true },\n memo,\n ).directory([]);\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n return {\n current: directory.current,\n policy: directory.policy,\n dependencies: [],\n };\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n"]}
1
+ {"version":3,"file":"recoverCurrentOrganizationPolicy.js","sourceRoot":"","sources":["recoverCurrentOrganizationPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,kDAAkD,CAAC;AAKjG,OAAO,EACL,6BAA6B,GAE9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,OAAiC,EACjC,IAA4B;IAE5B,MAAM,KAAK,GAAG;QACZ,GAAG,OAAO;QACV,UAAU,EAAE,6BAA6B,CAAC,OAAO,CAAC,UAAU,CAAC;KAC9D,CAAC;IACF,IAAI,CAAC;QACH,IAAI,SAAmC,CAAC;QACxC,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,6BAA6B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,SAAS,CACpE,EAAE,CACH,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,mCAAmC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACxD,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YACpE,SAAS,GAAG,MAAM,6BAA6B,CAC7C,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAC3B,IAAI,CACL,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;QACD,mCAAmC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QACxD,OAAO;YACL,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;AACH,CAAC","sourcesContent":["import { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport type {\n PrincipalRecoveryContext,\n RecoveredPolicyDirectory,\n} from \"./principalRecoveryDirectory\";\nimport {\n createPrincipalRecoveryReader,\n type PrincipalRecoveryMemo,\n} from \"./principalRecoveryMemo\";\nimport { isPrincipalRecoveryOutage } from \"./principalRecoveryOutage\";\n\n/** Discover and verify current directory artifacts, including protected offline recovery. */\nexport async function recoverCurrentOrganizationPolicy(\n options: PrincipalRecoveryContext,\n memo?: PrincipalRecoveryMemo,\n) {\n const input = {\n ...options,\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n let directory: RecoveredPolicyDirectory;\n try {\n directory = await createPrincipalRecoveryReader(input, memo).directory(\n [],\n );\n } catch (error) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (input.offline || !isPrincipalRecoveryOutage(error)) throw error;\n directory = await createPrincipalRecoveryReader(\n { ...input, offline: true },\n memo,\n ).directory([]);\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n return {\n current: directory.current,\n policy: directory.policy,\n dependencies: [],\n };\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import { KeyingVerificationError } from "../../internal/crypto/index.js";
2
+ import { loadRecoveredPrincipalHistoryPage, PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE, } from "./loadRecoveredPrincipalHistoryPage.js";
3
+ import { PrincipalHistoryEvidenceUnavailableError } from "./principalHistoryRecoveryReferences.js";
4
+ import { recoverPrincipalPolicyHistoryWithVersions } from "./recoverPrincipalPolicyHistory.js";
5
+ /** Disposable page proof loss may replay signed pages once online, preserving durable pins. */
6
+ export async function recoverPrincipalHistoryPage(options, beforeVersion) {
7
+ try {
8
+ return await loadRecoveredPrincipalHistoryPage(options, beforeVersion);
9
+ }
10
+ catch (error) {
11
+ if (!(error instanceof PrincipalHistoryEvidenceUnavailableError))
12
+ throw error;
13
+ // A local-first display read must distinguish disposable proof damage
14
+ // from a durable fork or an invalid caller citation, which are not wrapped.
15
+ // Preserve that distinction so the online caller can replay signed pages.
16
+ if (options.offline)
17
+ throw new KeyingVerificationError("missing_dependency", "Principal history display proof is unavailable");
18
+ }
19
+ const first = Math.max(1, beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE - 1);
20
+ await recoverPrincipalPolicyHistoryWithVersions(options, Array.from({ length: beforeVersion - first }, (_, index) => first + index));
21
+ try {
22
+ return await loadRecoveredPrincipalHistoryPage(options, beforeVersion);
23
+ }
24
+ catch (error) {
25
+ throw error instanceof PrincipalHistoryEvidenceUnavailableError
26
+ ? error.verificationError
27
+ : error;
28
+ }
29
+ }
30
+ //# sourceMappingURL=recoverPrincipalHistoryPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recoverPrincipalHistoryPage.js","sourceRoot":"","sources":["recoverPrincipalHistoryPage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EACL,iCAAiC,EACjC,mCAAmC,GACpC,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,wCAAwC,EAAE,MAAM,sCAAsC,CAAC;AAEhG,OAAO,EAAE,yCAAyC,EAAE,MAAM,iCAAiC,CAAC;AAE5F,+FAA+F;AAC/F,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,OAA6C,EAC7C,aAAqB;IAErB,IAAI,CAAC;QACH,OAAO,MAAM,iCAAiC,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,CAAC,KAAK,YAAY,wCAAwC,CAAC;YAC9D,MAAM,KAAK,CAAC;QACd,sEAAsE;QACtE,4EAA4E;QAC5E,0EAA0E;QAC1E,IAAI,OAAO,CAAC,OAAO;YACjB,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,gDAAgD,CACjD,CAAC;IACN,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CACpB,CAAC,EACD,aAAa,GAAG,mCAAmC,GAAG,CAAC,CACxD,CAAC;IACF,MAAM,yCAAyC,CAC7C,OAAO,EACP,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,aAAa,GAAG,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,CAC3E,CAAC;IACF,IAAI,CAAC;QACH,OAAO,MAAM,iCAAiC,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACzE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,YAAY,wCAAwC;YAC7D,CAAC,CAAC,KAAK,CAAC,iBAAiB;YACzB,CAAC,CAAC,KAAK,CAAC;IACZ,CAAC;AACH,CAAC","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport {\n loadRecoveredPrincipalHistoryPage,\n PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE,\n} from \"./loadRecoveredPrincipalHistoryPage\";\nimport { PrincipalHistoryEvidenceUnavailableError } from \"./principalHistoryRecoveryReferences\";\nimport type { RecoverPrincipalPolicyHistoryOptions } from \"./principalHistoryRecoveryTypes\";\nimport { recoverPrincipalPolicyHistoryWithVersions } from \"./recoverPrincipalPolicyHistory\";\n\n/** Disposable page proof loss may replay signed pages once online, preserving durable pins. */\nexport async function recoverPrincipalHistoryPage(\n options: RecoverPrincipalPolicyHistoryOptions,\n beforeVersion: number,\n) {\n try {\n return await loadRecoveredPrincipalHistoryPage(options, beforeVersion);\n } catch (error) {\n if (!(error instanceof PrincipalHistoryEvidenceUnavailableError))\n throw error;\n // A local-first display read must distinguish disposable proof damage\n // from a durable fork or an invalid caller citation, which are not wrapped.\n // Preserve that distinction so the online caller can replay signed pages.\n if (options.offline)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history display proof is unavailable\",\n );\n }\n const first = Math.max(\n 1,\n beforeVersion - PRINCIPAL_DISPLAY_HISTORY_PAGE_SIZE - 1,\n );\n await recoverPrincipalPolicyHistoryWithVersions(\n options,\n Array.from({ length: beforeVersion - first }, (_, index) => first + index),\n );\n try {\n return await loadRecoveredPrincipalHistoryPage(options, beforeVersion);\n } catch (error) {\n throw error instanceof PrincipalHistoryEvidenceUnavailableError\n ? error.verificationError\n : error;\n }\n}\n"]}
@@ -5,3 +5,5 @@ import { type RecoveredPrincipalPolicyHistory, type RecoverPrincipalPolicyHistor
5
5
  * Retain organization version 1 when the result will establish founder binding.
6
6
  */
7
7
  export declare function recoverPrincipalPolicyHistory(options: RecoverPrincipalPolicyHistoryOptions): Promise<RecoveredPrincipalPolicyHistory>;
8
+ /** Internal bounded display selection; missing proof rows use the normal single rebuild. */
9
+ export declare function recoverPrincipalPolicyHistoryWithVersions(options: RecoverPrincipalPolicyHistoryOptions, retainedVersions: readonly number[]): Promise<RecoveredPrincipalPolicyHistory>;
@@ -1,4 +1,4 @@
1
- import { createPrincipalPolicyHistoryVerifier, KeyingVerificationError, verifyPrincipalPolicyCheckpoint, verifyPrincipalPolicyCurrent, } from "../../internal/crypto/index.js";
1
+ import { createPrincipalPolicyHistoryVerifier, KeyingVerificationError, PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT, verifyPrincipalPolicyCheckpoint, verifyPrincipalPolicyCurrent, } from "../../internal/crypto/index.js";
2
2
  import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
3
3
  import { loadPrincipalPolicyCheckpoint } from "../../data/persistence/keyingCheckpointPersistence.js";
4
4
  import { preparePrincipalHistoryEvidencePage } from "../../data/persistence/principalHistoryEvidencePersistence.js";
@@ -221,7 +221,18 @@ async function recover(input, allowEvidenceRebuild = true) {
221
221
  * The result is a sparse current-policy capability; this does not advance app checkpoints.
222
222
  * Retain organization version 1 when the result will establish founder binding.
223
223
  */
224
- export async function recoverPrincipalPolicyHistory(options) {
224
+ export function recoverPrincipalPolicyHistory(options) {
225
+ return recoverPrincipalPolicyHistoryWithVersions(options, []);
226
+ }
227
+ /** Internal bounded display selection; missing proof rows use the normal single rebuild. */
228
+ export async function recoverPrincipalPolicyHistoryWithVersions(options, retainedVersions) {
229
+ if (!Array.isArray(retainedVersions) ||
230
+ retainedVersions.length + (options.retainedReferences?.length ?? 0) >
231
+ PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT ||
232
+ retainedVersions.some((version) => !Number.isSafeInteger(version) ||
233
+ version < 1 ||
234
+ version > options.expectedHead.version))
235
+ throw new KeyingVerificationError("invalid_shape", "Principal display history selection exceeds its bounded range");
225
236
  if (options.offline !== undefined && typeof options.offline !== "boolean")
226
237
  throw new KeyingVerificationError("invalid_shape", "Invalid principal history transport mode");
227
238
  if (!options.organizationId ||
@@ -235,6 +246,7 @@ export async function recoverPrincipalPolicyHistory(options) {
235
246
  historyVerification: options.historyVerification ?? "standard",
236
247
  expectedHead: structuredClone(options.expectedHead),
237
248
  retainedReferences: structuredClone(options.retainedReferences ?? []),
249
+ retainedVersions: [...retainedVersions],
238
250
  protection: ownPrincipalHistoryProtection(options.protection),
239
251
  };
240
252
  try {