@tearleads/client-sdk 0.1.37 → 0.1.38
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.
- package/client/organizations/organizationGroupHistory.js +1 -1
- package/client/organizations/organizationGroupHistory.js.map +1 -1
- package/client/organizations/organizationHistory.js +1 -1
- package/client/organizations/organizationHistory.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicyVerification.js +1 -2
- package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
- package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js +39 -51
- package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +1 -1
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/organizations/organizationAccessRevocationPersistence.js +4 -0
- package/data/persistence/organizations/organizationAccessRevocationPersistence.js.map +1 -1
- package/data/persistence/organizations/organizationReadModelPersistence.js +7 -1
- package/data/persistence/organizations/organizationReadModelPersistence.js.map +1 -1
- package/data/principals/principalRecoveryEpoch.js +18 -0
- package/data/principals/principalRecoveryEpoch.js.map +1 -0
- package/package.json +1 -1
- package/workflows/organizations/currentGroupPolicyMutationContext.js +5 -5
- package/workflows/organizations/currentGroupPolicyMutationContext.js.map +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -1
- package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
- package/workflows/principals/principalRecoveryMemo.d.ts +9 -4
- package/workflows/principals/principalRecoveryMemo.js +94 -34
- package/workflows/principals/principalRecoveryMemo.js.map +1 -1
- package/workflows/principals/principalRecoveryMemoValidity.js +33 -0
- package/workflows/principals/principalRecoveryMemoValidity.js.map +1 -0
- package/workflows/principals/principalRecoveryOutage.js +2 -2
- package/workflows/principals/principalRecoveryOutage.js.map +1 -1
- package/workflows/principals/recoverCurrentOrganizationPolicy.js +8 -3
- package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js +42 -8
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverPublicPrincipalHistory.js +5 -5
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +9 -2
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +8 -2
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +4 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/runtimePolicyWarmer.js +12 -4
- package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
|
@@ -2,7 +2,7 @@ import { KeyingVerificationError } from "../../internal/crypto/index.js";
|
|
|
2
2
|
import { ProjectionDependencyUnavailableError } from "../../data/keyingProjectionVerification/dependencyUnavailable.js";
|
|
3
3
|
import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
|
|
4
4
|
import { PrincipalPolicyHistoryReadError } from "./principalHistoryRecoveryTypes.js";
|
|
5
|
-
import {
|
|
5
|
+
import { recoverLeasedScopedPrincipalPolicyHistory, } from "./recoverScopedPrincipalPolicyHistory.js";
|
|
6
6
|
/** Refusals and invalid evidence must never silently select a cached policy. */
|
|
7
7
|
export function isPrincipalRecoveryOutage(error) {
|
|
8
8
|
if (!(error instanceof PrincipalPolicyHistoryReadError))
|
|
@@ -24,7 +24,7 @@ export async function recoverWithPrincipalOutageFallback(recover, options) {
|
|
|
24
24
|
if (options.offline || !isPrincipalRecoveryOutage(error))
|
|
25
25
|
throw error;
|
|
26
26
|
try {
|
|
27
|
-
return await
|
|
27
|
+
return await recoverLeasedScopedPrincipalPolicyHistory({
|
|
28
28
|
...options,
|
|
29
29
|
offline: true,
|
|
30
30
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principalRecoveryOutage.js","sourceRoot":"","sources":["principalRecoveryOutage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,oCAAoC,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,
|
|
1
|
+
{"version":3,"file":"principalRecoveryOutage.js","sourceRoot":"","sources":["principalRecoveryOutage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,oCAAoC,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,+BAA+B,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAEL,yCAAyC,GAE1C,MAAM,uCAAuC,CAAC;AAE/C,gFAAgF;AAChF,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACtD,IAAI,CAAC,CAAC,KAAK,YAAY,+BAA+B,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1B,OAAO,CACL,OAAO,CAAC,IAAI,KAAK,SAAS;QAC1B,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM;YACtB,OAAO,CAAC,MAAM,KAAK,IAAI;YACvB,OAAO,CAAC,MAAM,IAAI,GAAG,CAAC;QACxB,CAAC,OAAO,CAAC,IAAI,KAAK,WAAW;YAC3B,OAAO,CAAC,IAAI,KAAK,qCAAqC,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,OAA2C,EAC3C,OAAmD;IAEnD,IAAI,CAAC;QACH,OAAO,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,OAAO,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QACtE,IAAI,CAAC;YACH,OAAO,MAAM,yCAAyC,CAAC;gBACrD,GAAG,OAAO;gBACV,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,IACE,UAAU,YAAY,uBAAuB;gBAC7C,UAAU,CAAC,IAAI,KAAK,oBAAoB;gBAExC,MAAM,IAAI,oCAAoC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,UAAU,CAAC;QACnB,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { PrincipalPolicyHistoryReadError } from \"./principalHistoryRecoveryTypes\";\nimport {\n type RecoverScopedPrincipalPolicyHistoryOptions,\n recoverLeasedScopedPrincipalPolicyHistory,\n type ScopedPrincipalPolicyRecoveryBatch,\n} from \"./recoverScopedPrincipalPolicyHistory\";\n\n/** Refusals and invalid evidence must never silently select a cached policy. */\nexport function isPrincipalRecoveryOutage(error: unknown): boolean {\n if (!(error instanceof PrincipalPolicyHistoryReadError)) return false;\n const { failure } = error;\n return (\n failure.kind === \"network\" ||\n (failure.kind === \"http\" &&\n failure.status !== null &&\n failure.status >= 500) ||\n (failure.kind === \"cancelled\" &&\n failure.code === \"principal_history_request_timed_out\")\n );\n}\n\nexport async function recoverWithPrincipalOutageFallback(\n recover: ScopedPrincipalPolicyRecoveryBatch,\n options: RecoverScopedPrincipalPolicyHistoryOptions,\n) {\n try {\n return await recover(options);\n } catch (error) {\n assertProjectionVerificationCurrent(options.stillCurrent);\n if (options.offline || !isPrincipalRecoveryOutage(error)) throw error;\n try {\n return await recoverLeasedScopedPrincipalPolicyHistory({\n ...options,\n offline: true,\n });\n } catch (localError) {\n if (\n localError instanceof KeyingVerificationError &&\n localError.code === \"missing_dependency\"\n )\n throw new ProjectionDependencyUnavailableError(localError.message);\n throw localError;\n }\n }\n}\n"]}
|
|
@@ -10,20 +10,25 @@ export async function recoverCurrentOrganizationPolicy(options, memo) {
|
|
|
10
10
|
};
|
|
11
11
|
try {
|
|
12
12
|
let directory;
|
|
13
|
+
let reader = createPrincipalRecoveryReader(input, memo);
|
|
13
14
|
try {
|
|
14
|
-
directory = await
|
|
15
|
+
directory = await reader.directory([]);
|
|
15
16
|
}
|
|
16
17
|
catch (error) {
|
|
17
18
|
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
18
19
|
if (input.offline || !isPrincipalRecoveryOutage(error))
|
|
19
20
|
throw error;
|
|
20
|
-
|
|
21
|
+
reader = createPrincipalRecoveryReader({ ...input, offline: true }, memo);
|
|
22
|
+
directory = await reader.directory([]);
|
|
21
23
|
}
|
|
22
|
-
|
|
24
|
+
// A reused directory keeps its producer's lifetime to the point of use.
|
|
25
|
+
const stillCurrent = () => input.stillCurrent() && reader.stillCurrent();
|
|
26
|
+
assertProjectionVerificationCurrent(stillCurrent);
|
|
23
27
|
return {
|
|
24
28
|
current: directory.current,
|
|
25
29
|
policy: directory.policy,
|
|
26
30
|
dependencies: [],
|
|
31
|
+
stillCurrent,
|
|
27
32
|
};
|
|
28
33
|
}
|
|
29
34
|
finally {
|
|
@@ -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,SAAmC,CAAC;QACxC,IAAI,
|
|
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,MAAM,GAAG,6BAA6B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC;YACH,SAAS,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACzC,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,MAAM,GAAG,6BAA6B,CAAC,EAAE,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;YAC1E,SAAS,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;QACD,wEAAwE;QACxE,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC,YAAY,EAAE,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACzE,mCAAmC,CAAC,YAAY,CAAC,CAAC;QAClD,OAAO;YACL,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,YAAY,EAAE,EAAE;YAChB,YAAY;SACb,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 let reader = createPrincipalRecoveryReader(input, memo);\n try {\n directory = await reader.directory([]);\n } catch (error) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n if (input.offline || !isPrincipalRecoveryOutage(error)) throw error;\n reader = createPrincipalRecoveryReader({ ...input, offline: true }, memo);\n directory = await reader.directory([]);\n }\n // A reused directory keeps its producer's lifetime to the point of use.\n const stillCurrent = () => input.stillCurrent() && reader.stillCurrent();\n assertProjectionVerificationCurrent(stillCurrent);\n return {\n current: directory.current,\n policy: directory.policy,\n dependencies: [],\n stillCurrent,\n };\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n"]}
|
|
@@ -20,6 +20,15 @@ class PrincipalHistoryPrefixDisconnectedError extends Error {
|
|
|
20
20
|
this.name = "PrincipalHistoryPrefixDisconnectedError";
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
/** Stored current artifacts of a completed stage failed their signed-history check. */
|
|
24
|
+
class StoredPrincipalCurrentRejectedError extends Error {
|
|
25
|
+
verificationError;
|
|
26
|
+
constructor(verificationError) {
|
|
27
|
+
super(verificationError.message);
|
|
28
|
+
this.verificationError = verificationError;
|
|
29
|
+
this.name = "StoredPrincipalCurrentRejectedError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
function currentArtifacts(page) {
|
|
24
33
|
return {
|
|
25
34
|
currentState: page.currentState,
|
|
@@ -114,7 +123,7 @@ async function acceptPage(input, stage, response) {
|
|
|
114
123
|
stage.saved = saved;
|
|
115
124
|
stage.complete = complete;
|
|
116
125
|
}
|
|
117
|
-
async function finishRecovery(input, stage, checkpoint) {
|
|
126
|
+
async function finishRecovery(input, stage, checkpoint, storedCurrent) {
|
|
118
127
|
if (!stage.current || !stage.complete)
|
|
119
128
|
throw new KeyingVerificationError("missing_dependency", "Principal history ended before its pinned head");
|
|
120
129
|
const history = stage.verifier.finish(input.expectedHead);
|
|
@@ -130,8 +139,11 @@ async function finishRecovery(input, stage, checkpoint) {
|
|
|
130
139
|
current: stage.current,
|
|
131
140
|
history: selected,
|
|
132
141
|
});
|
|
133
|
-
if (!current.ok)
|
|
142
|
+
if (!current.ok) {
|
|
143
|
+
if (storedCurrent)
|
|
144
|
+
throw new StoredPrincipalCurrentRejectedError(current.error);
|
|
134
145
|
throw current.error;
|
|
146
|
+
}
|
|
135
147
|
verifyPrincipalPolicyCheckpoint({
|
|
136
148
|
chain: current.value.retainedHistory,
|
|
137
149
|
currentState: current.value.state,
|
|
@@ -147,13 +159,32 @@ async function finishRecovery(input, stage, checkpoint) {
|
|
|
147
159
|
assertCurrent(input);
|
|
148
160
|
return { current: stage.current, policy: current.value };
|
|
149
161
|
}
|
|
162
|
+
function completedStageMatchesHead(stage, expectedHead) {
|
|
163
|
+
if (!stage.complete || !stage.current)
|
|
164
|
+
return false;
|
|
165
|
+
try {
|
|
166
|
+
assertExpectedHead(stage.current, expectedHead);
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Returns whether the stage's current artifacts came from local storage. A
|
|
175
|
+
* completed stage already authenticates every signed entry through the exact
|
|
176
|
+
* pinned head, so an online read of that head could only return the pinned
|
|
177
|
+
* bytes or refuse. Server-current freshness belongs to the caller's discovery.
|
|
178
|
+
*/
|
|
150
179
|
async function readRecoveryPages(input, stage) {
|
|
151
180
|
if (input.offline) {
|
|
152
181
|
if (!stage.complete || !stage.current)
|
|
153
182
|
throw new KeyingVerificationError("missing_dependency", "Completed principal history is unavailable offline");
|
|
154
183
|
assertExpectedHead(stage.current, input.expectedHead);
|
|
155
|
-
return;
|
|
184
|
+
return true;
|
|
156
185
|
}
|
|
186
|
+
if (completedStageMatchesHead(stage, input.expectedHead))
|
|
187
|
+
return true;
|
|
157
188
|
let receivedFinalPage = false;
|
|
158
189
|
for await (const result of input.apiClient.getPrincipalPolicyPages(input.expectedHead.principalType, input.expectedHead.principalId, {
|
|
159
190
|
signal: input.signal,
|
|
@@ -179,6 +210,7 @@ async function readRecoveryPages(input, stage) {
|
|
|
179
210
|
}
|
|
180
211
|
if (!receivedFinalPage)
|
|
181
212
|
throw new KeyingVerificationError("missing_dependency", "Principal history transport did not complete");
|
|
213
|
+
return false;
|
|
182
214
|
}
|
|
183
215
|
async function recover(input, allowEvidenceRebuild = true) {
|
|
184
216
|
assertCurrent(input);
|
|
@@ -200,13 +232,15 @@ async function recover(input, allowEvidenceRebuild = true) {
|
|
|
200
232
|
try {
|
|
201
233
|
if (stage.fromCache)
|
|
202
234
|
await validatePrincipalHistoryRecoveryAuthority(input, stage.verifier);
|
|
203
|
-
await readRecoveryPages(input, stage);
|
|
204
|
-
return await finishRecovery(input, stage, checkpoint);
|
|
235
|
+
const stored = await readRecoveryPages(input, stage);
|
|
236
|
+
return await finishRecovery(input, stage, checkpoint, stored && !input.offline);
|
|
205
237
|
}
|
|
206
238
|
catch (error) {
|
|
207
239
|
const lostEvidence = error instanceof PrincipalHistoryEvidenceUnavailableError;
|
|
208
|
-
|
|
209
|
-
|
|
240
|
+
// Disposable stored artifacts never refuse an online reader: replay them.
|
|
241
|
+
const disposable = error instanceof PrincipalHistoryPrefixDisconnectedError ||
|
|
242
|
+
error instanceof StoredPrincipalCurrentRejectedError;
|
|
243
|
+
if (!lostEvidence && !disposable)
|
|
210
244
|
throw error;
|
|
211
245
|
if (stage.saved)
|
|
212
246
|
await discardPrincipalHistoryStage(input.execSql, stage.saved, () => recoveryIsCurrent(input));
|
|
@@ -214,7 +248,7 @@ async function recover(input, allowEvidenceRebuild = true) {
|
|
|
214
248
|
allowEvidenceRebuild &&
|
|
215
249
|
(lostEvidence || stage.fromCache))
|
|
216
250
|
return recover(input, false);
|
|
217
|
-
throw
|
|
251
|
+
throw error.verificationError;
|
|
218
252
|
}
|
|
219
253
|
}
|
|
220
254
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recoverPrincipalPolicyHistory.js","sourceRoot":"","sources":["recoverPrincipalPolicyHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyPageCurrent } from \"@tearleads/api-client\";\nimport {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryInput,\n verifyPrincipalPolicyCheckpoint,\n verifyPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyPageResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalPolicyCheckpoint } from \"../../data/persistence/keyingCheckpointPersistence\";\nimport { preparePrincipalHistoryEvidencePage } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport {\n discardPrincipalHistoryStage,\n savePrincipalHistoryStage,\n} from \"../../data/persistence/principalHistoryStagePersistence\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport { principalHistoryStageProtection } from \"../../data/principals/principalHistoryStageProtection\";\nimport { collectPrincipalPolicySignerPublicKeys } from \"./policyVerification\";\nimport { validatePrincipalHistoryRecoveryAuthority } from \"./principalHistoryRecoveryAuthority\";\nimport { publishReusablePrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport {\n PrincipalHistoryEvidenceUnavailableError,\n type PrincipalHistorySelectionOptions,\n selectRecoveredPrincipalHistory,\n} from \"./principalHistoryRecoveryReferences\";\nimport {\n type PrincipalHistoryRecoveryStage,\n restorePrincipalHistoryRecoveryStage,\n} from \"./principalHistoryRecoveryStage\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n PrincipalPolicyHistoryReadError,\n type RecoveredPrincipalPolicyHistory,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport {\n assertPrincipalHistoryVerificationMode,\n principalHistoryVerificationContext,\n} from \"./principalHistoryRecoveryVerification\";\n\nclass PrincipalHistoryPrefixDisconnectedError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"PrincipalHistoryPrefixDisconnectedError\";\n }\n}\n\nfunction currentArtifacts(\n page: PrincipalPolicyPageResponse,\n): PrincipalPolicyPageCurrent {\n return {\n currentState: page.currentState,\n currentPayload: page.currentPayload,\n currentProjection: page.currentProjection,\n currentGrants: page.currentGrants,\n currentMemberEnvelopes: page.currentMemberEnvelopes,\n };\n}\n\nfunction recoveryIsCurrent(\n input: RecoverPrincipalPolicyHistoryOptions,\n): boolean {\n return !input.signal?.aborted && input.stillCurrent();\n}\n\nfunction assertCurrent(input: RecoverPrincipalPolicyHistoryOptions): void {\n assertProjectionVerificationCurrent(() => recoveryIsCurrent(input));\n}\n\nfunction assertExpectedHead(\n current: PrincipalPolicyPageCurrent,\n expectedHead: RecoverPrincipalPolicyHistoryOptions[\"expectedHead\"],\n): void {\n for (const field of [\n \"principalType\",\n \"principalId\",\n \"version\",\n \"stateHash\",\n \"keyEpoch\",\n \"keyFingerprint\",\n ] as const) {\n if (current.currentState[field] !== expectedHead[field])\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Principal history page does not match its requested head\",\n );\n }\n}\n\nasync function acceptPage(\n input: RecoverPrincipalPolicyHistoryOptions,\n stage: PrincipalHistoryRecoveryStage,\n response: PrincipalPolicyPageResponse,\n): Promise<void> {\n const page = structuredClone(response);\n assertCurrent(input);\n assertExpectedHead(page, input.expectedHead);\n if (stage.complete) {\n if (\n page.previousStates.length !== 0 ||\n page.historyPage.nextAfterVersion !== null\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Completed history returned additional entries\",\n );\n stage.current = currentArtifacts(page);\n return;\n }\n const complete = page.historyPage.nextAfterVersion === null;\n const current = currentArtifacts(page);\n const entries = [...page.previousStates];\n if (complete)\n entries.push({\n state: current.currentState,\n projection: current.currentProjection,\n grants: current.currentGrants,\n });\n assertPrincipalHistoryVerificationMode(input, entries);\n const keys = await collectPrincipalPolicySignerPublicKeys({\n bundle: { ...current, previousStates: page.previousStates },\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (\"error\" in keys)\n throw new KeyingVerificationError(\n keys.error === \"not-found\" ? \"missing_dependency\" : \"signer_mismatch\",\n \"Principal history signer identity could not be authenticated\",\n );\n const externalAuthority = await input.loadExternalAuthority?.(\n entries.flatMap(({ state }) =>\n state.externalAuthority ? [state.externalAuthority] : [],\n ),\n );\n const appended = await stage.verifier.append({\n entries,\n signerPublicKeys: keys.signerPublicKeys,\n ...(externalAuthority ? { externalAuthority } : {}),\n });\n if (!appended.ok) {\n if (appended.error.code === \"stale_predecessor\")\n throw new PrincipalHistoryPrefixDisconnectedError(appended.error);\n throw appended.error;\n }\n const next = {\n id: stage.id,\n organizationId: input.organizationId,\n currentJson: JSON.stringify(current),\n afterVersion: appended.value.throughVersion - (complete ? 1 : 0),\n complete,\n };\n const protectedProgress = await stage.verifier.exportProgress(\n await principalHistoryStageProtection(\n input.protection,\n input.expectedHead,\n next,\n ),\n );\n if (!protectedProgress.ok) throw protectedProgress.error;\n const saved = { ...next, progress: protectedProgress.value };\n await savePrincipalHistoryStage({\n execSql: input.execSql,\n stage: saved,\n evidence: await preparePrincipalHistoryEvidencePage({\n indexRootHash: appended.value.indexRootHash,\n scopeId: stage.scopeId,\n organizationId: input.organizationId,\n entries,\n nodes: appended.value.indexNodes,\n }),\n previousProgress: stage.saved?.progress ?? null,\n stillCurrent: () => recoveryIsCurrent(input),\n });\n stage.current = current;\n stage.saved = saved;\n stage.complete = complete;\n}\n\nasync function finishRecovery(\n input: PrincipalHistorySelectionOptions,\n stage: PrincipalHistoryRecoveryStage,\n checkpoint: PrincipalPolicyCheckpoint | null,\n): Promise<RecoveredPrincipalPolicyHistory> {\n if (!stage.current || !stage.complete)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history ended before its pinned head\",\n );\n const history = stage.verifier.finish(input.expectedHead);\n if (!history.ok) throw history.error;\n const selected = await selectRecoveredPrincipalHistory({\n options: input,\n scopeId: stage.scopeId,\n history: history.value,\n checkpoint,\n });\n const current = await verifyPrincipalPolicyCurrent({\n current: stage.current,\n history: selected,\n });\n if (!current.ok) throw current.error;\n verifyPrincipalPolicyCheckpoint({\n chain: current.value.retainedHistory,\n currentState: current.value.state,\n localCheckpoint: checkpoint,\n });\n const latest = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n input.expectedHead.principalType,\n input.expectedHead.principalId,\n );\n if (\n latest?.version !== checkpoint?.version ||\n latest?.stateHash !== checkpoint?.stateHash\n )\n throw new PrincipalHistoryRecoveryRaceError(\n \"Local principal checkpoint changed during history recovery\",\n );\n assertCurrent(input);\n if (!input.offline)\n await publishReusablePrincipalHistoryPrefix(\n input,\n stage.scopeId,\n stage.verifier,\n stage.current,\n );\n assertCurrent(input);\n return { current: stage.current, policy: current.value };\n}\n\nasync function readRecoveryPages(\n input: RecoverPrincipalPolicyHistoryOptions,\n stage: PrincipalHistoryRecoveryStage,\n): Promise<void> {\n if (input.offline) {\n if (!stage.complete || !stage.current)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Completed principal history is unavailable offline\",\n );\n assertExpectedHead(stage.current, input.expectedHead);\n return;\n }\n let receivedFinalPage = false;\n for await (const result of input.apiClient.getPrincipalPolicyPages(\n input.expectedHead.principalType,\n input.expectedHead.principalId,\n {\n signal: input.signal,\n stateHash: input.expectedHead.stateHash,\n ...(stage.saved && stage.current\n ? {\n resume: {\n current: stage.current,\n afterVersion: stage.saved.afterVersion,\n },\n }\n : { afterVersion: stage.initialAfterVersion }),\n },\n )) {\n if (!result.ok) {\n // A rejected transport pin cannot justify skipping history on retry.\n // Discard only this operation's progress, then let a new call replay it.\n if (result.kind === \"shape\" && stage.saved)\n await discardPrincipalHistoryStage(input.execSql, stage.saved, () =>\n recoveryIsCurrent(input),\n );\n throw new PrincipalPolicyHistoryReadError(result);\n }\n await acceptPage(input, stage, result.data);\n receivedFinalPage = result.data.historyPage.nextAfterVersion === null;\n }\n if (!receivedFinalPage)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history transport did not complete\",\n );\n}\n\nasync function recover(\n input: PrincipalHistorySelectionOptions,\n allowEvidenceRebuild = true,\n): Promise<RecoveredPrincipalPolicyHistory> {\n assertCurrent(input);\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n input.expectedHead.principalType,\n input.expectedHead.principalId,\n );\n if (checkpoint && input.expectedHead.version < checkpoint.version)\n throw new KeyingVerificationError(\n input.offline ? \"missing_dependency\" : \"rollback\",\n \"Requested principal history predates the local checkpoint\",\n );\n // Validate the requested pin/selection before creating any disposable caches.\n createPrincipalPolicyHistoryVerifier({\n principalType: input.expectedHead.principalType,\n principalId: input.expectedHead.principalId,\n localCheckpoint: checkpoint,\n retainedReferences: input.retainedReferences ?? [],\n });\n const historyInput: PrincipalPolicyHistoryInput = {\n principalType: input.expectedHead.principalType,\n principalId: input.expectedHead.principalId,\n };\n const stage = await restorePrincipalHistoryRecoveryStage(\n input,\n historyInput,\n allowEvidenceRebuild,\n );\n try {\n if (stage.fromCache)\n await validatePrincipalHistoryRecoveryAuthority(input, stage.verifier);\n await readRecoveryPages(input, stage);\n return await finishRecovery(input, stage, checkpoint);\n } catch (error) {\n const lostEvidence =\n error instanceof PrincipalHistoryEvidenceUnavailableError;\n const disconnected =\n error instanceof PrincipalHistoryPrefixDisconnectedError;\n if (!lostEvidence && !disconnected) throw error;\n if (stage.saved)\n await discardPrincipalHistoryStage(input.execSql, stage.saved, () =>\n recoveryIsCurrent(input),\n );\n if (\n !input.offline &&\n allowEvidenceRebuild &&\n (lostEvidence || stage.fromCache)\n )\n return recover(input, false);\n throw lostEvidence || disconnected ? error.verificationError : error;\n }\n}\n\n/**\n * Recover one exact head with bounded retained history and durable checked progress.\n * The result is a sparse current-policy capability; this does not advance app checkpoints.\n * Retain organization version 1 when the result will establish founder binding.\n */\nexport function recoverPrincipalPolicyHistory(\n options: RecoverPrincipalPolicyHistoryOptions,\n): Promise<RecoveredPrincipalPolicyHistory> {\n return recoverPrincipalPolicyHistoryWithVersions(options, []);\n}\n\n/** Internal bounded display selection; missing proof rows use the normal single rebuild. */\nexport async function recoverPrincipalPolicyHistoryWithVersions(\n options: RecoverPrincipalPolicyHistoryOptions,\n retainedVersions: readonly number[],\n): Promise<RecoveredPrincipalPolicyHistory> {\n if (\n !Array.isArray(retainedVersions) ||\n retainedVersions.length + (options.retainedReferences?.length ?? 0) >\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT ||\n retainedVersions.some(\n (version) =>\n !Number.isSafeInteger(version) ||\n version < 1 ||\n version > options.expectedHead.version,\n )\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal display history selection exceeds its bounded range\",\n );\n if (options.offline !== undefined && typeof options.offline !== \"boolean\")\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Invalid principal history transport mode\",\n );\n if (\n !options.organizationId ||\n (options.expectedHead.principalType === \"organization\" &&\n options.expectedHead.principalId !== options.organizationId)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Principal history organization scope is invalid\",\n );\n if (\n options.retainedReferences?.some(\n (reference) => reference.version > options.expectedHead.version,\n )\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Requested history reference is beyond the recovery head\",\n );\n const input = {\n ...options,\n historyVerification: options.historyVerification ?? \"standard\",\n expectedHead: structuredClone(options.expectedHead),\n retainedReferences: structuredClone(options.retainedReferences ?? []),\n retainedVersions: [...retainedVersions],\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n input.protection.context = principalHistoryVerificationContext(input);\n return await recover(input);\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recoverPrincipalPolicyHistory.js","sourceRoot":"","sources":["recoverPrincipalPolicyHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { PrincipalPolicyPageCurrent } from \"@tearleads/api-client\";\nimport {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n type PrincipalPolicyCheckpoint,\n type PrincipalPolicyHistoryInput,\n verifyPrincipalPolicyCheckpoint,\n verifyPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyPageResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalPolicyCheckpoint } from \"../../data/persistence/keyingCheckpointPersistence\";\nimport { preparePrincipalHistoryEvidencePage } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport {\n discardPrincipalHistoryStage,\n savePrincipalHistoryStage,\n} from \"../../data/persistence/principalHistoryStagePersistence\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport { principalHistoryStageProtection } from \"../../data/principals/principalHistoryStageProtection\";\nimport { collectPrincipalPolicySignerPublicKeys } from \"./policyVerification\";\nimport { validatePrincipalHistoryRecoveryAuthority } from \"./principalHistoryRecoveryAuthority\";\nimport { publishReusablePrincipalHistoryPrefix } from \"./principalHistoryRecoveryPrefix\";\nimport {\n PrincipalHistoryEvidenceUnavailableError,\n type PrincipalHistorySelectionOptions,\n selectRecoveredPrincipalHistory,\n} from \"./principalHistoryRecoveryReferences\";\nimport {\n type PrincipalHistoryRecoveryStage,\n restorePrincipalHistoryRecoveryStage,\n} from \"./principalHistoryRecoveryStage\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n PrincipalPolicyHistoryReadError,\n type RecoveredPrincipalPolicyHistory,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport {\n assertPrincipalHistoryVerificationMode,\n principalHistoryVerificationContext,\n} from \"./principalHistoryRecoveryVerification\";\n\nclass PrincipalHistoryPrefixDisconnectedError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"PrincipalHistoryPrefixDisconnectedError\";\n }\n}\n\n/** Stored current artifacts of a completed stage failed their signed-history check. */\nclass StoredPrincipalCurrentRejectedError extends Error {\n constructor(readonly verificationError: KeyingVerificationError) {\n super(verificationError.message);\n this.name = \"StoredPrincipalCurrentRejectedError\";\n }\n}\n\nfunction currentArtifacts(\n page: PrincipalPolicyPageResponse,\n): PrincipalPolicyPageCurrent {\n return {\n currentState: page.currentState,\n currentPayload: page.currentPayload,\n currentProjection: page.currentProjection,\n currentGrants: page.currentGrants,\n currentMemberEnvelopes: page.currentMemberEnvelopes,\n };\n}\n\nfunction recoveryIsCurrent(\n input: RecoverPrincipalPolicyHistoryOptions,\n): boolean {\n return !input.signal?.aborted && input.stillCurrent();\n}\n\nfunction assertCurrent(input: RecoverPrincipalPolicyHistoryOptions): void {\n assertProjectionVerificationCurrent(() => recoveryIsCurrent(input));\n}\n\nfunction assertExpectedHead(\n current: PrincipalPolicyPageCurrent,\n expectedHead: RecoverPrincipalPolicyHistoryOptions[\"expectedHead\"],\n): void {\n for (const field of [\n \"principalType\",\n \"principalId\",\n \"version\",\n \"stateHash\",\n \"keyEpoch\",\n \"keyFingerprint\",\n ] as const) {\n if (current.currentState[field] !== expectedHead[field])\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Principal history page does not match its requested head\",\n );\n }\n}\n\nasync function acceptPage(\n input: RecoverPrincipalPolicyHistoryOptions,\n stage: PrincipalHistoryRecoveryStage,\n response: PrincipalPolicyPageResponse,\n): Promise<void> {\n const page = structuredClone(response);\n assertCurrent(input);\n assertExpectedHead(page, input.expectedHead);\n if (stage.complete) {\n if (\n page.previousStates.length !== 0 ||\n page.historyPage.nextAfterVersion !== null\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Completed history returned additional entries\",\n );\n stage.current = currentArtifacts(page);\n return;\n }\n const complete = page.historyPage.nextAfterVersion === null;\n const current = currentArtifacts(page);\n const entries = [...page.previousStates];\n if (complete)\n entries.push({\n state: current.currentState,\n projection: current.currentProjection,\n grants: current.currentGrants,\n });\n assertPrincipalHistoryVerificationMode(input, entries);\n const keys = await collectPrincipalPolicySignerPublicKeys({\n bundle: { ...current, previousStates: page.previousStates },\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n });\n if (\"error\" in keys)\n throw new KeyingVerificationError(\n keys.error === \"not-found\" ? \"missing_dependency\" : \"signer_mismatch\",\n \"Principal history signer identity could not be authenticated\",\n );\n const externalAuthority = await input.loadExternalAuthority?.(\n entries.flatMap(({ state }) =>\n state.externalAuthority ? [state.externalAuthority] : [],\n ),\n );\n const appended = await stage.verifier.append({\n entries,\n signerPublicKeys: keys.signerPublicKeys,\n ...(externalAuthority ? { externalAuthority } : {}),\n });\n if (!appended.ok) {\n if (appended.error.code === \"stale_predecessor\")\n throw new PrincipalHistoryPrefixDisconnectedError(appended.error);\n throw appended.error;\n }\n const next = {\n id: stage.id,\n organizationId: input.organizationId,\n currentJson: JSON.stringify(current),\n afterVersion: appended.value.throughVersion - (complete ? 1 : 0),\n complete,\n };\n const protectedProgress = await stage.verifier.exportProgress(\n await principalHistoryStageProtection(\n input.protection,\n input.expectedHead,\n next,\n ),\n );\n if (!protectedProgress.ok) throw protectedProgress.error;\n const saved = { ...next, progress: protectedProgress.value };\n await savePrincipalHistoryStage({\n execSql: input.execSql,\n stage: saved,\n evidence: await preparePrincipalHistoryEvidencePage({\n indexRootHash: appended.value.indexRootHash,\n scopeId: stage.scopeId,\n organizationId: input.organizationId,\n entries,\n nodes: appended.value.indexNodes,\n }),\n previousProgress: stage.saved?.progress ?? null,\n stillCurrent: () => recoveryIsCurrent(input),\n });\n stage.current = current;\n stage.saved = saved;\n stage.complete = complete;\n}\n\nasync function finishRecovery(\n input: PrincipalHistorySelectionOptions,\n stage: PrincipalHistoryRecoveryStage,\n checkpoint: PrincipalPolicyCheckpoint | null,\n storedCurrent: boolean,\n): Promise<RecoveredPrincipalPolicyHistory> {\n if (!stage.current || !stage.complete)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history ended before its pinned head\",\n );\n const history = stage.verifier.finish(input.expectedHead);\n if (!history.ok) throw history.error;\n const selected = await selectRecoveredPrincipalHistory({\n options: input,\n scopeId: stage.scopeId,\n history: history.value,\n checkpoint,\n });\n const current = await verifyPrincipalPolicyCurrent({\n current: stage.current,\n history: selected,\n });\n if (!current.ok) {\n if (storedCurrent)\n throw new StoredPrincipalCurrentRejectedError(current.error);\n throw current.error;\n }\n verifyPrincipalPolicyCheckpoint({\n chain: current.value.retainedHistory,\n currentState: current.value.state,\n localCheckpoint: checkpoint,\n });\n const latest = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n input.expectedHead.principalType,\n input.expectedHead.principalId,\n );\n if (\n latest?.version !== checkpoint?.version ||\n latest?.stateHash !== checkpoint?.stateHash\n )\n throw new PrincipalHistoryRecoveryRaceError(\n \"Local principal checkpoint changed during history recovery\",\n );\n assertCurrent(input);\n if (!input.offline)\n await publishReusablePrincipalHistoryPrefix(\n input,\n stage.scopeId,\n stage.verifier,\n stage.current,\n );\n assertCurrent(input);\n return { current: stage.current, policy: current.value };\n}\n\nfunction completedStageMatchesHead(\n stage: PrincipalHistoryRecoveryStage,\n expectedHead: RecoverPrincipalPolicyHistoryOptions[\"expectedHead\"],\n): boolean {\n if (!stage.complete || !stage.current) return false;\n try {\n assertExpectedHead(stage.current, expectedHead);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Returns whether the stage's current artifacts came from local storage. A\n * completed stage already authenticates every signed entry through the exact\n * pinned head, so an online read of that head could only return the pinned\n * bytes or refuse. Server-current freshness belongs to the caller's discovery.\n */\nasync function readRecoveryPages(\n input: RecoverPrincipalPolicyHistoryOptions,\n stage: PrincipalHistoryRecoveryStage,\n): Promise<boolean> {\n if (input.offline) {\n if (!stage.complete || !stage.current)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Completed principal history is unavailable offline\",\n );\n assertExpectedHead(stage.current, input.expectedHead);\n return true;\n }\n if (completedStageMatchesHead(stage, input.expectedHead)) return true;\n let receivedFinalPage = false;\n for await (const result of input.apiClient.getPrincipalPolicyPages(\n input.expectedHead.principalType,\n input.expectedHead.principalId,\n {\n signal: input.signal,\n stateHash: input.expectedHead.stateHash,\n ...(stage.saved && stage.current\n ? {\n resume: {\n current: stage.current,\n afterVersion: stage.saved.afterVersion,\n },\n }\n : { afterVersion: stage.initialAfterVersion }),\n },\n )) {\n if (!result.ok) {\n // A rejected transport pin cannot justify skipping history on retry.\n // Discard only this operation's progress, then let a new call replay it.\n if (result.kind === \"shape\" && stage.saved)\n await discardPrincipalHistoryStage(input.execSql, stage.saved, () =>\n recoveryIsCurrent(input),\n );\n throw new PrincipalPolicyHistoryReadError(result);\n }\n await acceptPage(input, stage, result.data);\n receivedFinalPage = result.data.historyPage.nextAfterVersion === null;\n }\n if (!receivedFinalPage)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history transport did not complete\",\n );\n return false;\n}\n\nasync function recover(\n input: PrincipalHistorySelectionOptions,\n allowEvidenceRebuild = true,\n): Promise<RecoveredPrincipalPolicyHistory> {\n assertCurrent(input);\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n input.expectedHead.principalType,\n input.expectedHead.principalId,\n );\n if (checkpoint && input.expectedHead.version < checkpoint.version)\n throw new KeyingVerificationError(\n input.offline ? \"missing_dependency\" : \"rollback\",\n \"Requested principal history predates the local checkpoint\",\n );\n // Validate the requested pin/selection before creating any disposable caches.\n createPrincipalPolicyHistoryVerifier({\n principalType: input.expectedHead.principalType,\n principalId: input.expectedHead.principalId,\n localCheckpoint: checkpoint,\n retainedReferences: input.retainedReferences ?? [],\n });\n const historyInput: PrincipalPolicyHistoryInput = {\n principalType: input.expectedHead.principalType,\n principalId: input.expectedHead.principalId,\n };\n const stage = await restorePrincipalHistoryRecoveryStage(\n input,\n historyInput,\n allowEvidenceRebuild,\n );\n try {\n if (stage.fromCache)\n await validatePrincipalHistoryRecoveryAuthority(input, stage.verifier);\n const stored = await readRecoveryPages(input, stage);\n return await finishRecovery(\n input,\n stage,\n checkpoint,\n stored && !input.offline,\n );\n } catch (error) {\n const lostEvidence =\n error instanceof PrincipalHistoryEvidenceUnavailableError;\n // Disposable stored artifacts never refuse an online reader: replay them.\n const disposable =\n error instanceof PrincipalHistoryPrefixDisconnectedError ||\n error instanceof StoredPrincipalCurrentRejectedError;\n if (!lostEvidence && !disposable) throw error;\n if (stage.saved)\n await discardPrincipalHistoryStage(input.execSql, stage.saved, () =>\n recoveryIsCurrent(input),\n );\n if (\n !input.offline &&\n allowEvidenceRebuild &&\n (lostEvidence || stage.fromCache)\n )\n return recover(input, false);\n throw error.verificationError;\n }\n}\n\n/**\n * Recover one exact head with bounded retained history and durable checked progress.\n * The result is a sparse current-policy capability; this does not advance app checkpoints.\n * Retain organization version 1 when the result will establish founder binding.\n */\nexport function recoverPrincipalPolicyHistory(\n options: RecoverPrincipalPolicyHistoryOptions,\n): Promise<RecoveredPrincipalPolicyHistory> {\n return recoverPrincipalPolicyHistoryWithVersions(options, []);\n}\n\n/** Internal bounded display selection; missing proof rows use the normal single rebuild. */\nexport async function recoverPrincipalPolicyHistoryWithVersions(\n options: RecoverPrincipalPolicyHistoryOptions,\n retainedVersions: readonly number[],\n): Promise<RecoveredPrincipalPolicyHistory> {\n if (\n !Array.isArray(retainedVersions) ||\n retainedVersions.length + (options.retainedReferences?.length ?? 0) >\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT ||\n retainedVersions.some(\n (version) =>\n !Number.isSafeInteger(version) ||\n version < 1 ||\n version > options.expectedHead.version,\n )\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal display history selection exceeds its bounded range\",\n );\n if (options.offline !== undefined && typeof options.offline !== \"boolean\")\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Invalid principal history transport mode\",\n );\n if (\n !options.organizationId ||\n (options.expectedHead.principalType === \"organization\" &&\n options.expectedHead.principalId !== options.organizationId)\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Principal history organization scope is invalid\",\n );\n if (\n options.retainedReferences?.some(\n (reference) => reference.version > options.expectedHead.version,\n )\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Requested history reference is beyond the recovery head\",\n );\n const input = {\n ...options,\n historyVerification: options.historyVerification ?? \"standard\",\n expectedHead: structuredClone(options.expectedHead),\n retainedReferences: structuredClone(options.retainedReferences ?? []),\n retainedVersions: [...retainedVersions],\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n input.protection.context = principalHistoryVerificationContext(input);\n return await recover(input);\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n"]}
|
|
@@ -25,18 +25,18 @@ async function readPublicPages(input, initial) {
|
|
|
25
25
|
const current = () => !input.signal?.aborted && input.stillCurrent();
|
|
26
26
|
let progress = initial;
|
|
27
27
|
let lastPage;
|
|
28
|
-
|
|
28
|
+
// Completed progress already verified every signed entry through the cited
|
|
29
|
+
// head; a read pinned to that head could only repeat it or refuse.
|
|
30
|
+
if (!input.offline && !progress.completedHead) {
|
|
29
31
|
for await (const result of input.apiClient.getProjectionPolicyHistoryPages(input.source, { afterVersion: progress.afterVersion, signal: input.signal })) {
|
|
30
32
|
assertProjectionVerificationCurrent(current);
|
|
31
33
|
if (!result.ok)
|
|
32
34
|
throw new PrincipalPolicyHistoryReadError(result);
|
|
33
35
|
const page = result.data;
|
|
34
36
|
assertPage(input, page, progress.afterVersion);
|
|
35
|
-
if (
|
|
36
|
-
progress = await appendPublicPrincipalHistoryPage(input, progress, page);
|
|
37
|
-
else if (page.previousStates.length ||
|
|
38
|
-
page.historyPage.nextAfterVersion !== null)
|
|
37
|
+
if (progress.completedHead)
|
|
39
38
|
throw new KeyingVerificationError("invalid_shape", "Completed public history returned additional entries");
|
|
39
|
+
progress = await appendPublicPrincipalHistoryPage(input, progress, page);
|
|
40
40
|
lastPage = page;
|
|
41
41
|
}
|
|
42
42
|
if (lastPage?.historyPage.nextAfterVersion !== null)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recoverPublicPrincipalHistory.js","sourceRoot":"","sources":["recoverPublicPrincipalHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n type PrincipalPolicyHistoryReferenceProof,\n serializeKeyingCanonicalJson,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport {\n isPrincipalPolicySnapshotPageResponse,\n type PrincipalPolicySnapshotPageResponse,\n} from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport type { PrincipalHistoryPrefix } from \"../../data/persistence/principalHistoryPrefixPersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport { PrincipalPolicyHistoryReadError } from \"./principalHistoryRecoveryTypes\";\nimport { PublicHistoryAuthorityUnavailableError } from \"./publicPrincipalHistoryAuthority\";\nimport {\n appendPublicPrincipalHistoryPage,\n PublicPrincipalHistoryPrefixDisconnectedError,\n} from \"./publicPrincipalHistoryPage\";\nimport {\n publishPublicPrincipalHistoryPrefix,\n restorePublicPrincipalHistoryProgress,\n} from \"./publicPrincipalHistoryProgress\";\nimport type {\n PublicPrincipalHistoryOptions,\n PublicPrincipalHistoryProgress,\n RecoveredPublicPrincipalHistory,\n} from \"./publicPrincipalHistoryTypes\";\n\nfunction assertPage(\n input: PublicPrincipalHistoryOptions,\n page: PrincipalPolicySnapshotPageResponse,\n after: number,\n): void {\n if (\n !isPrincipalPolicySnapshotPageResponse(page) ||\n !principalHeadMatchesReference(page.currentState, input.source.head) ||\n page.historyPage.afterVersion !== after\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history page does not match its requested head and cursor\",\n );\n const through = after + page.previousStates.length;\n if (\n page.previousStates.some(\n ({ state }, index) => state.version !== after + index + 1,\n ) ||\n through >= input.source.head.version ||\n (page.historyPage.nextAfterVersion === null\n ? through !== input.source.head.version - 1\n : through <= after || page.historyPage.nextAfterVersion !== through)\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Public history page has a gap or invalid continuation\",\n );\n}\n\nasync function readPublicPages(\n input: PublicPrincipalHistoryOptions,\n initial: PublicPrincipalHistoryProgress,\n) {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n let progress = initial;\n let lastPage: PrincipalPolicySnapshotPageResponse | undefined;\n if (!input.offline) {\n for await (const result of input.apiClient.getProjectionPolicyHistoryPages(\n input.source,\n { afterVersion: progress.afterVersion, signal: input.signal },\n )) {\n assertProjectionVerificationCurrent(current);\n if (!result.ok) throw new PrincipalPolicyHistoryReadError(result);\n const page = result.data;\n assertPage(input, page, progress.afterVersion);\n if (!progress.completedHead)\n progress = await appendPublicPrincipalHistoryPage(\n input,\n progress,\n page,\n );\n else if (\n page.previousStates.length ||\n page.historyPage.nextAfterVersion !== null\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Completed public history returned additional entries\",\n );\n lastPage = page;\n }\n if (lastPage?.historyPage.nextAfterVersion !== null)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Public history transport did not complete\",\n );\n }\n return { progress, lastPage };\n}\n\nfunction finishPublicProgress(progress: PublicPrincipalHistoryProgress) {\n if (!progress.completedHead)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Completed public history is unavailable\",\n );\n const finished = progress.verifier.finish(progress.completedHead);\n if (!finished.ok) throw finished.error;\n return finished.value;\n}\n\nasync function recoverAttempt(\n input: PublicPrincipalHistoryOptions,\n allowReuse = true,\n rejectedPrefix: PrincipalHistoryPrefix | null = null,\n): Promise<RecoveredPublicPrincipalHistory> {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const mayReplay = allowReuse && !input.offline;\n const initial = await restorePublicPrincipalHistoryProgress(\n input,\n allowReuse,\n );\n let pages: Awaited<ReturnType<typeof readPublicPages>>;\n try {\n pages = await readPublicPages(input, initial);\n } catch (error) {\n if (!(error instanceof PublicPrincipalHistoryPrefixDisconnectedError))\n throw error;\n // A signed cached candidate need not belong to this requested chain. Only\n // reused progress permits one replay; a fresh disconnected chain fails.\n if (mayReplay && initial.afterVersion > 0)\n return recover(input, false, initial.cachedPrefix);\n throw error.verificationError;\n }\n const { progress, lastPage } = pages;\n const history = finishPublicProgress(progress);\n let proof: PrincipalPolicyHistoryReferenceProof;\n try {\n proof = await loadPrincipalHistoryReference({\n execSql: input.execSql,\n scopeId: progress.scopeId,\n history,\n version: input.source.head.version,\n });\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references: [proof],\n });\n if (!selected.ok) throw selected.error;\n } catch (error) {\n if (error instanceof KeyingVerificationError && mayReplay)\n return recover(input, false, initial.cachedPrefix);\n throw error;\n }\n // Public prefixes memoize signatures; they are not admitted trust pins. A\n // rejected projection may have left a valid but unrelated signed candidate.\n // Rebuild the requested chain once online; callers still check durable pins\n // and object authority before accepting it. Never reuse a mismatch offline.\n if (!principalHeadMatchesReference(proof.entry.state, input.source.head)) {\n if (mayReplay) return recover(input, false, initial.cachedPrefix);\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history source differs from the verified prefix\",\n );\n }\n if (lastPage) {\n const currentProof = {\n ...proof,\n entry: {\n state: lastPage.currentState,\n projection: lastPage.currentProjection,\n grants: lastPage.currentGrants,\n },\n };\n const checked = await verifyPrincipalPolicyHistoryReferences({\n history,\n references: [currentProof],\n });\n if (!checked.ok) throw checked.error;\n }\n assertProjectionVerificationCurrent(current);\n if (!input.offline)\n await publishPublicPrincipalHistoryPrefix(\n input,\n progress,\n history,\n rejectedPrefix,\n );\n assertProjectionVerificationCurrent(current);\n return { scopeId: progress.scopeId, history };\n}\n\nasync function recover(\n input: PublicPrincipalHistoryOptions,\n allowReuse = true,\n rejectedPrefix: PrincipalHistoryPrefix | null = null,\n): Promise<RecoveredPublicPrincipalHistory> {\n try {\n return await recoverAttempt(input, allowReuse, rejectedPrefix);\n } catch (error) {\n if (!(error instanceof PublicHistoryAuthorityUnavailableError)) throw error;\n if (allowReuse && !input.offline)\n return recoverAttempt(input, false, error.rejectedPrefix);\n throw error.verificationError;\n }\n}\n\n/** Private-key-backed public history recovery; never admits a current policy pin. */\nexport async function recoverPublicPrincipalHistory(\n options: PublicPrincipalHistoryOptions,\n): Promise<RecoveredPublicPrincipalHistory> {\n if (\n !options.organizationId ||\n (options.historicalProof !== undefined &&\n typeof options.historicalProof !== \"boolean\") ||\n (options.offline !== undefined && typeof options.offline !== \"boolean\") ||\n (options.strictAdmins !== undefined &&\n typeof options.strictAdmins !== \"boolean\") ||\n (options.strictAdmins &&\n (options.source.head.principalType !== \"group\" ||\n options.loadExternalAuthority))\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Invalid public history verification scope\",\n );\n if (\n options.source.head.principalType === \"organization\" &&\n options.source.head.principalId !== options.organizationId\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public organization history is outside its scope\",\n );\n // Validate the caller's pinned head before any cache or transport access.\n createPrincipalPolicyHistoryVerifier({\n principalType: options.source.head.principalType,\n principalId: options.source.head.principalId,\n retainedReferences: [options.source.head],\n });\n const protection = ownPrincipalHistoryProtection(options.protection);\n protection.context = serializeKeyingCanonicalJson([\n \"tearleads.sdk.public-principal-history.v2\",\n protection.context,\n options.strictAdmins === true,\n options.authorityGroupId ?? null,\n ]);\n const input = {\n ...options,\n source: structuredClone(options.source),\n protection,\n };\n try {\n return await recover(input, options.replay !== true);\n } finally {\n protection.localKey.fill(0);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recoverPublicPrincipalHistory.js","sourceRoot":"","sources":["recoverPublicPrincipalHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n type PrincipalPolicyHistoryReferenceProof,\n serializeKeyingCanonicalJson,\n verifyPrincipalPolicyHistoryReferences,\n} from \"@tearleads/crypto\";\nimport {\n isPrincipalPolicySnapshotPageResponse,\n type PrincipalPolicySnapshotPageResponse,\n} from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { loadPrincipalHistoryReference } from \"../../data/persistence/principalHistoryEvidencePersistence\";\nimport type { PrincipalHistoryPrefix } from \"../../data/persistence/principalHistoryPrefixPersistence\";\nimport { principalHeadMatchesReference } from \"../../data/principals/organizationAuthorityDescriptor\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport { PrincipalPolicyHistoryReadError } from \"./principalHistoryRecoveryTypes\";\nimport { PublicHistoryAuthorityUnavailableError } from \"./publicPrincipalHistoryAuthority\";\nimport {\n appendPublicPrincipalHistoryPage,\n PublicPrincipalHistoryPrefixDisconnectedError,\n} from \"./publicPrincipalHistoryPage\";\nimport {\n publishPublicPrincipalHistoryPrefix,\n restorePublicPrincipalHistoryProgress,\n} from \"./publicPrincipalHistoryProgress\";\nimport type {\n PublicPrincipalHistoryOptions,\n PublicPrincipalHistoryProgress,\n RecoveredPublicPrincipalHistory,\n} from \"./publicPrincipalHistoryTypes\";\n\nfunction assertPage(\n input: PublicPrincipalHistoryOptions,\n page: PrincipalPolicySnapshotPageResponse,\n after: number,\n): void {\n if (\n !isPrincipalPolicySnapshotPageResponse(page) ||\n !principalHeadMatchesReference(page.currentState, input.source.head) ||\n page.historyPage.afterVersion !== after\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history page does not match its requested head and cursor\",\n );\n const through = after + page.previousStates.length;\n if (\n page.previousStates.some(\n ({ state }, index) => state.version !== after + index + 1,\n ) ||\n through >= input.source.head.version ||\n (page.historyPage.nextAfterVersion === null\n ? through !== input.source.head.version - 1\n : through <= after || page.historyPage.nextAfterVersion !== through)\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Public history page has a gap or invalid continuation\",\n );\n}\n\nasync function readPublicPages(\n input: PublicPrincipalHistoryOptions,\n initial: PublicPrincipalHistoryProgress,\n) {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n let progress = initial;\n let lastPage: PrincipalPolicySnapshotPageResponse | undefined;\n // Completed progress already verified every signed entry through the cited\n // head; a read pinned to that head could only repeat it or refuse.\n if (!input.offline && !progress.completedHead) {\n for await (const result of input.apiClient.getProjectionPolicyHistoryPages(\n input.source,\n { afterVersion: progress.afterVersion, signal: input.signal },\n )) {\n assertProjectionVerificationCurrent(current);\n if (!result.ok) throw new PrincipalPolicyHistoryReadError(result);\n const page = result.data;\n assertPage(input, page, progress.afterVersion);\n if (progress.completedHead)\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Completed public history returned additional entries\",\n );\n progress = await appendPublicPrincipalHistoryPage(input, progress, page);\n lastPage = page;\n }\n if (lastPage?.historyPage.nextAfterVersion !== null)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Public history transport did not complete\",\n );\n }\n return { progress, lastPage };\n}\n\nfunction finishPublicProgress(progress: PublicPrincipalHistoryProgress) {\n if (!progress.completedHead)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Completed public history is unavailable\",\n );\n const finished = progress.verifier.finish(progress.completedHead);\n if (!finished.ok) throw finished.error;\n return finished.value;\n}\n\nasync function recoverAttempt(\n input: PublicPrincipalHistoryOptions,\n allowReuse = true,\n rejectedPrefix: PrincipalHistoryPrefix | null = null,\n): Promise<RecoveredPublicPrincipalHistory> {\n const current = () => !input.signal?.aborted && input.stillCurrent();\n assertProjectionVerificationCurrent(current);\n const mayReplay = allowReuse && !input.offline;\n const initial = await restorePublicPrincipalHistoryProgress(\n input,\n allowReuse,\n );\n let pages: Awaited<ReturnType<typeof readPublicPages>>;\n try {\n pages = await readPublicPages(input, initial);\n } catch (error) {\n if (!(error instanceof PublicPrincipalHistoryPrefixDisconnectedError))\n throw error;\n // A signed cached candidate need not belong to this requested chain. Only\n // reused progress permits one replay; a fresh disconnected chain fails.\n if (mayReplay && initial.afterVersion > 0)\n return recover(input, false, initial.cachedPrefix);\n throw error.verificationError;\n }\n const { progress, lastPage } = pages;\n const history = finishPublicProgress(progress);\n let proof: PrincipalPolicyHistoryReferenceProof;\n try {\n proof = await loadPrincipalHistoryReference({\n execSql: input.execSql,\n scopeId: progress.scopeId,\n history,\n version: input.source.head.version,\n });\n const selected = await verifyPrincipalPolicyHistoryReferences({\n history,\n references: [proof],\n });\n if (!selected.ok) throw selected.error;\n } catch (error) {\n if (error instanceof KeyingVerificationError && mayReplay)\n return recover(input, false, initial.cachedPrefix);\n throw error;\n }\n // Public prefixes memoize signatures; they are not admitted trust pins. A\n // rejected projection may have left a valid but unrelated signed candidate.\n // Rebuild the requested chain once online; callers still check durable pins\n // and object authority before accepting it. Never reuse a mismatch offline.\n if (!principalHeadMatchesReference(proof.entry.state, input.source.head)) {\n if (mayReplay) return recover(input, false, initial.cachedPrefix);\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public history source differs from the verified prefix\",\n );\n }\n if (lastPage) {\n const currentProof = {\n ...proof,\n entry: {\n state: lastPage.currentState,\n projection: lastPage.currentProjection,\n grants: lastPage.currentGrants,\n },\n };\n const checked = await verifyPrincipalPolicyHistoryReferences({\n history,\n references: [currentProof],\n });\n if (!checked.ok) throw checked.error;\n }\n assertProjectionVerificationCurrent(current);\n if (!input.offline)\n await publishPublicPrincipalHistoryPrefix(\n input,\n progress,\n history,\n rejectedPrefix,\n );\n assertProjectionVerificationCurrent(current);\n return { scopeId: progress.scopeId, history };\n}\n\nasync function recover(\n input: PublicPrincipalHistoryOptions,\n allowReuse = true,\n rejectedPrefix: PrincipalHistoryPrefix | null = null,\n): Promise<RecoveredPublicPrincipalHistory> {\n try {\n return await recoverAttempt(input, allowReuse, rejectedPrefix);\n } catch (error) {\n if (!(error instanceof PublicHistoryAuthorityUnavailableError)) throw error;\n if (allowReuse && !input.offline)\n return recoverAttempt(input, false, error.rejectedPrefix);\n throw error.verificationError;\n }\n}\n\n/** Private-key-backed public history recovery; never admits a current policy pin. */\nexport async function recoverPublicPrincipalHistory(\n options: PublicPrincipalHistoryOptions,\n): Promise<RecoveredPublicPrincipalHistory> {\n if (\n !options.organizationId ||\n (options.historicalProof !== undefined &&\n typeof options.historicalProof !== \"boolean\") ||\n (options.offline !== undefined && typeof options.offline !== \"boolean\") ||\n (options.strictAdmins !== undefined &&\n typeof options.strictAdmins !== \"boolean\") ||\n (options.strictAdmins &&\n (options.source.head.principalType !== \"group\" ||\n options.loadExternalAuthority))\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Invalid public history verification scope\",\n );\n if (\n options.source.head.principalType === \"organization\" &&\n options.source.head.principalId !== options.organizationId\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Public organization history is outside its scope\",\n );\n // Validate the caller's pinned head before any cache or transport access.\n createPrincipalPolicyHistoryVerifier({\n principalType: options.source.head.principalType,\n principalId: options.source.head.principalId,\n retainedReferences: [options.source.head],\n });\n const protection = ownPrincipalHistoryProtection(options.protection);\n protection.context = serializeKeyingCanonicalJson([\n \"tearleads.sdk.public-principal-history.v2\",\n protection.context,\n options.strictAdmins === true,\n options.authorityGroupId ?? null,\n ]);\n const input = {\n ...options,\n source: structuredClone(options.source),\n protection,\n };\n try {\n return await recover(input, options.replay !== true);\n } finally {\n protection.localKey.fill(0);\n }\n}\n"]}
|
|
@@ -15,6 +15,13 @@ export interface RecoveredScopedPrincipalPolicyHistory extends RecoveredPrincipa
|
|
|
15
15
|
readonly dependencies: readonly VerifiedPrincipalPolicyCurrent[];
|
|
16
16
|
readonly historyPage?: RecoveredPrincipalHistoryPage | undefined;
|
|
17
17
|
}
|
|
18
|
+
/** Internal result: valid only while every evidence producer behind it is. */
|
|
19
|
+
export interface ScopedPrincipalPolicyRecovery extends RecoveredScopedPrincipalPolicyHistory {
|
|
20
|
+
readonly stillCurrent: () => boolean;
|
|
21
|
+
}
|
|
22
|
+
export type ScopedPrincipalPolicyRecoveryBatch = (options: RecoverScopedPrincipalPolicyHistoryOptions) => Promise<ScopedPrincipalPolicyRecovery>;
|
|
18
23
|
export declare function recoverScopedPrincipalPolicyHistory(options: RecoverScopedPrincipalPolicyHistoryOptions): Promise<RecoveredScopedPrincipalPolicyHistory>;
|
|
19
|
-
/** Internal
|
|
20
|
-
export declare
|
|
24
|
+
/** Internal unbatched recovery that keeps its result's lifetime. */
|
|
25
|
+
export declare const recoverLeasedScopedPrincipalPolicyHistory: ScopedPrincipalPolicyRecoveryBatch;
|
|
26
|
+
/** Internal runtime batch: shared results never outlive its operation or caller. */
|
|
27
|
+
export declare function createScopedPrincipalPolicyHistoryBatch(memo?: PrincipalRecoveryMemo): ScopedPrincipalPolicyRecoveryBatch;
|
|
@@ -29,12 +29,15 @@ async function recoverScopedPolicy(input, memo) {
|
|
|
29
29
|
input.reference.principalId !== input.organizationId)
|
|
30
30
|
throw new KeyingVerificationError("object_mismatch", "Requested organization policy is outside its scope");
|
|
31
31
|
const read = createPrincipalRecoveryReader(input, memo);
|
|
32
|
+
// Reused or derived evidence keeps its producers' lifetimes to its use.
|
|
33
|
+
const stillCurrent = () => !input.signal?.aborted && input.stillCurrent() && read.stillCurrent();
|
|
32
34
|
const directory = await read.directory(input.reference.principalType === "organization" ? [input.reference] : []);
|
|
33
35
|
if (input.reference.principalType === "organization")
|
|
34
36
|
return {
|
|
35
37
|
current: directory.current,
|
|
36
38
|
policy: directory.policy,
|
|
37
39
|
dependencies: [],
|
|
40
|
+
stillCurrent,
|
|
38
41
|
...(await selectDisplayHistory(input, {
|
|
39
42
|
...input,
|
|
40
43
|
expectedHead: principalPolicyReferenceFromBundle(directory.current),
|
|
@@ -88,6 +91,7 @@ async function recoverScopedPolicy(input, memo) {
|
|
|
88
91
|
return {
|
|
89
92
|
...recovered,
|
|
90
93
|
dependencies: admins ? [directory.policy, admins] : [directory.policy],
|
|
94
|
+
stillCurrent,
|
|
91
95
|
...(await selectDisplayHistory(input, recoveryOptions)),
|
|
92
96
|
};
|
|
93
97
|
}
|
|
@@ -119,7 +123,7 @@ async function recoverScopedPrincipalPolicyHistoryInBatch(options, memo) {
|
|
|
119
123
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
120
124
|
try {
|
|
121
125
|
const recovered = await recoverScopedPolicy(input, memo);
|
|
122
|
-
assertProjectionVerificationCurrent(
|
|
126
|
+
assertProjectionVerificationCurrent(recovered.stillCurrent);
|
|
123
127
|
return recovered;
|
|
124
128
|
}
|
|
125
129
|
catch (error) {
|
|
@@ -140,6 +144,8 @@ async function recoverScopedPrincipalPolicyHistoryInBatch(options, memo) {
|
|
|
140
144
|
export function recoverScopedPrincipalPolicyHistory(options) {
|
|
141
145
|
return recoverScopedPrincipalPolicyHistoryInBatch(options);
|
|
142
146
|
}
|
|
147
|
+
/** Internal unbatched recovery that keeps its result's lifetime. */
|
|
148
|
+
export const recoverLeasedScopedPrincipalPolicyHistory = (options) => recoverScopedPrincipalPolicyHistoryInBatch(options);
|
|
143
149
|
async function selectDisplayHistory(input, options) {
|
|
144
150
|
if (!input.historyPage)
|
|
145
151
|
return {};
|
|
@@ -147,7 +153,7 @@ async function selectDisplayHistory(input, options) {
|
|
|
147
153
|
historyPage: await recoverPrincipalHistoryPage(options, input.historyPage.beforeVersion ?? input.reference.version + 1),
|
|
148
154
|
};
|
|
149
155
|
}
|
|
150
|
-
/** Internal runtime batch: shared results never outlive
|
|
156
|
+
/** Internal runtime batch: shared results never outlive its operation or caller. */
|
|
151
157
|
export function createScopedPrincipalPolicyHistoryBatch(memo = {
|
|
152
158
|
directories: new Map(),
|
|
153
159
|
admins: new Map(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recoverScopedPrincipalPolicyHistory.js","sourceRoot":"","sources":["recoverScopedPrincipalPolicyHistory.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oCAAoC,EACpC,uBAAuB,GAIxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,mCAAmC,EAAE,MAAM,+CAA+C,CAAC;AACpG,OAAO,EAAE,6BAA6B,EAAE,MAAM,kDAAkD,CAAC;AACjG,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EAAE,kCAAkC,EAAE,MAAM,mDAAmD,CAAC;AAEvG,OAAO,EACL,iCAAiC,GAGlC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAEL,kCAAkC,GAEnC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,6BAA6B,GAE9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,6BAA6B,EAAE,MAAM,iCAAiC,CAAC;AAgBhF,SAAS,SAAS,CAAC,SAAmC,EAAE,WAAmB;IACzE,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAC/C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,WAAW,CAC7C,CAAC;IACF,IAAI,CAAC,IAAI;QACP,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,wDAAwD,CACzD,CAAC;IACJ,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,aAAa,CAAC,KAA8B;IACnD,OAAO;QACL,aAAa,EAAE,OAAgB;QAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,mBAAmB,CAChC,KAAiD,EACjD,IAA4B;IAE5B,IACE,KAAK,CAAC,SAAS,CAAC,aAAa,KAAK,cAAc;QAChD,KAAK,CAAC,SAAS,CAAC,WAAW,KAAK,KAAK,CAAC,cAAc;QAEpD,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,oDAAoD,CACrD,CAAC;IACJ,MAAM,IAAI,GAAG,6BAA6B,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,SAAS,CACpC,KAAK,CAAC,SAAS,CAAC,aAAa,KAAK,cAAc,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAC1E,CAAC;IACF,IAAI,KAAK,CAAC,SAAS,CAAC,aAAa,KAAK,cAAc;QAClD,OAAO;YACL,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,YAAY,EAAE,EAAE;YAChB,GAAG,CAAC,MAAM,oBAAoB,CAAC,KAAK,EAAE;gBACpC,GAAG,KAAK;gBACR,YAAY,EAAE,kCAAkC,CAAC,SAAS,CAAC,OAAO,CAAC;gBACnE,UAAU,EAAE,0BAA0B,CAAC,KAAK,CAAC,UAAU,CAAC;aACzD,CAAC,CAAC;SACJ,CAAC;IACJ,MAAM,YAAY,GAAG,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,GAAG,YAAY,CAAC,OAAO;QAChD,MAAM,IAAI,kCAAkC,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,YAAY,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW,CAAC;IACpE,IAAI,MAAM,GAA0C,IAAI,CAAC;IACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IACjD,CAAC;IACD,MAAM,qBAAqB,GAAG,KAAK,EACjC,SAA6C,EACU,EAAE;QACzD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAmC,CAAC;QAC9D,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YACjC,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,WAAW;gBAChD,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,qDAAqD,CACtD,CAAC;YACJ,IAAI,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO;gBACtC,MAAM,IAAI,kCAAkC,EAAE,CAAC;YACjD,UAAU,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QACvC,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACzE,OAAO;YACL,WAAW,EAAE,SAAS;YACtB,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,CAAC;gBACvE,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC;gBAC1B,UAAU;aACX,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,eAAe,GAAyC;QAC5D,GAAG,KAAK;QACR,YAAY;QACZ,kBAAkB,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;QACrC,mBAAmB,EAAE,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU;QAC5D,GAAG,CAAC,QAAQ;YACV,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC;gBACE,UAAU,EAAE,4BAA4B,CACtC,KAAK,CAAC,UAAU,EAChB,KAAK,CAAC,cAAc,EACpB,SAAS,CAAC,WAAW,CACtB;aACF,CAAC;QACN,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,CAAC;KAC/C,CAAC;IACF,MAAM,SAAS,GAAG,QAAQ;QACxB,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACpD,CAAC,CAAC,MAAM,6BAA6B,CAAC,eAAe,CAAC,CAAC;IACzD,OAAO;QACL,GAAG,SAAS;QACZ,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC;QACtE,GAAG,CAAC,MAAM,oBAAoB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;KACxD,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,KAAK,UAAU,0CAA0C,CACvD,OAAmD,EACnD,IAA4B;IAE5B,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,SAAS;QACvE,MAAM,IAAI,uBAAuB,CAC/B,eAAe,EACf,0CAA0C,CAC3C,CAAC;IACJ,IAAI,CAAC,OAAO,CAAC,cAAc;QACzB,MAAM,IAAI,uBAAuB,CAC/B,iBAAiB,EACjB,mDAAmD,CACpD,CAAC;IACJ,MAAM,KAAK,GAAG;QACZ,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;QAC9D,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,SAAS,CAAC;QAC7C,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QACzE,UAAU,EAAE,6BAA6B,CAAC,OAAO,CAAC,UAAU,CAAC;KAC9D,CAAC;IACF,IAAI,CAAC;QACH,8EAA8E;QAC9E,oCAAoC,CAAC;YACnC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,WAAW;YACxC,aAAa,EAAE,KAAK,CAAC,SAAS,CAAC,aAAa;YAC5C,kBAAkB,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC;SACtC,CAAC,CAAC;QACH,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC;gBACH,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBACzD,mCAAmC,CACjC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,KAAK,CAAC,YAAY,EAAE,CACrD,CAAC;gBACF,OAAO,SAAS,CAAC;YACnB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,CAAC,CAAC,KAAK,YAAY,kCAAkC,CAAC;oBAAE,MAAM,KAAK,CAAC;gBACxE,IAAI,EAAE,WAAW,CAAC,KAAK,EAAE,CAAC;gBAC1B,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;gBACrB,IAAI,KAAK,CAAC,OAAO;oBACf,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,kEAAkE,CACnE,CAAC;YACN,CAAC;QACH,CAAC;QACD,MAAM,IAAI,iCAAiC,CACzC,qEAAqE,CACtE,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,OAAmD;IAEnD,OAAO,0CAA0C,CAAC,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,KAAiD,EACjD,OAA6C;IAE7C,IAAI,CAAC,KAAK,CAAC,WAAW;QAAE,OAAO,EAAE,CAAC;IAClC,OAAO;QACL,WAAW,EAAE,MAAM,2BAA2B,CAC5C,OAAO,EACP,KAAK,CAAC,WAAW,CAAC,aAAa,IAAI,KAAK,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAC/D;KACF,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,uCAAuC,CACrD,OAA8B;IAC5B,WAAW,EAAE,IAAI,GAAG,EAAE;IACtB,MAAM,EAAE,IAAI,GAAG,EAAE;CAClB;IAED,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,0CAA0C,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChF,CAAC","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n type PrincipalPolicyExternalAuthority,\n type ReferencedPrincipalHead,\n type VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport {\n directoryHistoryProtection,\n scopedGroupHistoryProtection,\n} from \"../../data/principals/principalHistoryScopeProtection\";\nimport { principalPolicyReferenceFromBundle } from \"../../data/principals/principalPolicyAdminSigners\";\nimport type { RecoveredPrincipalHistoryPage } from \"./loadRecoveredPrincipalHistoryPage\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n type RecoveredPrincipalPolicyHistory,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport {\n type PrincipalRecoveryContext,\n PrincipalRecoveryDirectoryAdvanced,\n type RecoveredPolicyDirectory,\n} from \"./principalRecoveryDirectory\";\nimport {\n createPrincipalRecoveryReader,\n type PrincipalRecoveryMemo,\n} from \"./principalRecoveryMemo\";\nimport { recoverPrincipalHistoryPage } from \"./recoverPrincipalHistoryPage\";\nimport { recoverPrincipalPolicyHistory } from \"./recoverPrincipalPolicyHistory\";\n\nexport interface RecoverScopedPrincipalPolicyHistoryOptions\n extends PrincipalRecoveryContext {\n readonly reference: ReferencedPrincipalHead;\n /** Optional bounded display history ending before this exclusive version. */\n readonly historyPage?: { readonly beforeVersion?: number } | undefined;\n}\n\nexport interface RecoveredScopedPrincipalPolicyHistory\n extends RecoveredPrincipalPolicyHistory {\n /** Submit these with policy when atomically admitting its organization scope. */\n readonly dependencies: readonly VerifiedPrincipalPolicyCurrent[];\n readonly historyPage?: RecoveredPrincipalHistoryPage | undefined;\n}\n\nfunction groupHead(directory: RecoveredPolicyDirectory, principalId: string) {\n const head = directory.descriptor.groupHeads.find(\n (entry) => entry.principalId === principalId,\n );\n if (!head)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Group is absent from the signed organization directory\",\n );\n return head;\n}\n\nfunction authorityHead(state: ReferencedPrincipalHead) {\n return {\n principalType: \"group\" as const,\n principalId: state.principalId,\n version: state.version,\n stateHash: state.stateHash,\n keyEpoch: state.keyEpoch,\n keyFingerprint: state.keyFingerprint,\n };\n}\n\nasync function recoverScopedPolicy(\n input: RecoverScopedPrincipalPolicyHistoryOptions,\n memo?: PrincipalRecoveryMemo,\n): Promise<RecoveredScopedPrincipalPolicyHistory> {\n if (\n input.reference.principalType === \"organization\" &&\n input.reference.principalId !== input.organizationId\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Requested organization policy is outside its scope\",\n );\n const read = createPrincipalRecoveryReader(input, memo);\n const directory = await read.directory(\n input.reference.principalType === \"organization\" ? [input.reference] : [],\n );\n if (input.reference.principalType === \"organization\")\n return {\n current: directory.current,\n policy: directory.policy,\n dependencies: [],\n ...(await selectDisplayHistory(input, {\n ...input,\n expectedHead: principalPolicyReferenceFromBundle(directory.current),\n protection: directoryHistoryProtection(input.protection),\n })),\n };\n const expectedHead = groupHead(directory, input.reference.principalId);\n if (input.reference.version > expectedHead.version)\n throw new PrincipalRecoveryDirectoryAdvanced();\n const adminHead = groupHead(directory, directory.descriptor.adminGroupId);\n const isAdmins = expectedHead.principalId === adminHead.principalId;\n let admins: VerifiedPrincipalPolicyCurrent | null = null;\n if (!isAdmins) {\n admins = (await read.admins(adminHead)).policy;\n }\n const loadExternalAuthority = async (\n citations: readonly ReferencedPrincipalHead[],\n ): Promise<PrincipalPolicyExternalAuthority | undefined> => {\n const references = new Map<string, ReferencedPrincipalHead>();\n for (const citation of citations) {\n if (citation.principalId !== adminHead.principalId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Group cites another organization's Admins authority\",\n );\n if (citation.version > adminHead.version)\n throw new PrincipalRecoveryDirectoryAdvanced();\n references.set(`${citation.version}:${citation.stateHash}`, citation);\n }\n if (!references.size) return undefined;\n const recovered = await read.admins(adminHead, [...references.values()]);\n return {\n currentHead: adminHead,\n states: recovered.policy.retainedHistory.map(({ state, projection }) => ({\n head: authorityHead(state),\n projection,\n })),\n };\n };\n const recoveryOptions: RecoverPrincipalPolicyHistoryOptions = {\n ...input,\n expectedHead,\n retainedReferences: [input.reference],\n historyVerification: isAdmins ? \"direct-admins\" : \"standard\",\n ...(isAdmins\n ? {}\n : {\n protection: scopedGroupHistoryProtection(\n input.protection,\n input.organizationId,\n adminHead.principalId,\n ),\n }),\n ...(isAdmins ? {} : { loadExternalAuthority }),\n };\n const recovered = isAdmins\n ? await read.admins(expectedHead, [input.reference])\n : await recoverPrincipalPolicyHistory(recoveryOptions);\n return {\n ...recovered,\n dependencies: admins ? [directory.policy, admins] : [directory.policy],\n ...(await selectDisplayHistory(input, recoveryOptions)),\n };\n}\n\n/** Recover signed directory and strict Admins dependencies without full histories. */\nasync function recoverScopedPrincipalPolicyHistoryInBatch(\n options: RecoverScopedPrincipalPolicyHistoryOptions,\n memo?: PrincipalRecoveryMemo,\n): Promise<RecoveredScopedPrincipalPolicyHistory> {\n if (options.offline !== undefined && typeof options.offline !== \"boolean\")\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Invalid principal history transport mode\",\n );\n if (!options.organizationId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Principal recovery requires an organization scope\",\n );\n const input = {\n apiClient: options.apiClient,\n execSql: options.execSql,\n organizationId: options.organizationId,\n offline: options.offline,\n resolveTrustedUserIdentity: options.resolveTrustedUserIdentity,\n signal: options.signal,\n stillCurrent: options.stillCurrent,\n reference: structuredClone(options.reference),\n historyPage: options.historyPage ? { ...options.historyPage } : undefined,\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n // Reject malformed exact citations before any discovery or disposable writes.\n createPrincipalPolicyHistoryVerifier({\n principalId: input.reference.principalId,\n principalType: input.reference.principalType,\n retainedReferences: [input.reference],\n });\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n const recovered = await recoverScopedPolicy(input, memo);\n assertProjectionVerificationCurrent(\n () => !input.signal?.aborted && input.stillCurrent(),\n );\n return recovered;\n } catch (error) {\n if (!(error instanceof PrincipalRecoveryDirectoryAdvanced)) throw error;\n memo?.directories.clear();\n memo?.admins.clear();\n if (input.offline)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Requested principal evidence is newer than the offline directory\",\n );\n }\n }\n throw new PrincipalHistoryRecoveryRaceError(\n \"Organization directory remains behind the requested policy evidence\",\n );\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n\nexport function recoverScopedPrincipalPolicyHistory(\n options: RecoverScopedPrincipalPolicyHistoryOptions,\n): Promise<RecoveredScopedPrincipalPolicyHistory> {\n return recoverScopedPrincipalPolicyHistoryInBatch(options);\n}\n\nasync function selectDisplayHistory(\n input: RecoverScopedPrincipalPolicyHistoryOptions,\n options: RecoverPrincipalPolicyHistoryOptions,\n) {\n if (!input.historyPage) return {};\n return {\n historyPage: await recoverPrincipalHistoryPage(\n options,\n input.historyPage.beforeVersion ?? input.reference.version + 1,\n ),\n };\n}\n\n/** Internal runtime batch: shared results never outlive one caller's collection. */\nexport function createScopedPrincipalPolicyHistoryBatch(\n memo: PrincipalRecoveryMemo = {\n directories: new Map(),\n admins: new Map(),\n },\n): typeof recoverScopedPrincipalPolicyHistory {\n return (options) => recoverScopedPrincipalPolicyHistoryInBatch(options, memo);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"recoverScopedPrincipalPolicyHistory.js","sourceRoot":"","sources":["recoverScopedPrincipalPolicyHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createPrincipalPolicyHistoryVerifier,\n KeyingVerificationError,\n type PrincipalPolicyExternalAuthority,\n type ReferencedPrincipalHead,\n type VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport { ownPrincipalHistoryProtection } from \"../../data/principals/principalHistoryProtection\";\nimport {\n directoryHistoryProtection,\n scopedGroupHistoryProtection,\n} from \"../../data/principals/principalHistoryScopeProtection\";\nimport { principalPolicyReferenceFromBundle } from \"../../data/principals/principalPolicyAdminSigners\";\nimport type { RecoveredPrincipalHistoryPage } from \"./loadRecoveredPrincipalHistoryPage\";\nimport {\n PrincipalHistoryRecoveryRaceError,\n type RecoveredPrincipalPolicyHistory,\n type RecoverPrincipalPolicyHistoryOptions,\n} from \"./principalHistoryRecoveryTypes\";\nimport {\n type PrincipalRecoveryContext,\n PrincipalRecoveryDirectoryAdvanced,\n type RecoveredPolicyDirectory,\n} from \"./principalRecoveryDirectory\";\nimport {\n createPrincipalRecoveryReader,\n type PrincipalRecoveryMemo,\n} from \"./principalRecoveryMemo\";\nimport { recoverPrincipalHistoryPage } from \"./recoverPrincipalHistoryPage\";\nimport { recoverPrincipalPolicyHistory } from \"./recoverPrincipalPolicyHistory\";\n\nexport interface RecoverScopedPrincipalPolicyHistoryOptions\n extends PrincipalRecoveryContext {\n readonly reference: ReferencedPrincipalHead;\n /** Optional bounded display history ending before this exclusive version. */\n readonly historyPage?: { readonly beforeVersion?: number } | undefined;\n}\n\nexport interface RecoveredScopedPrincipalPolicyHistory\n extends RecoveredPrincipalPolicyHistory {\n /** Submit these with policy when atomically admitting its organization scope. */\n readonly dependencies: readonly VerifiedPrincipalPolicyCurrent[];\n readonly historyPage?: RecoveredPrincipalHistoryPage | undefined;\n}\n\n/** Internal result: valid only while every evidence producer behind it is. */\nexport interface ScopedPrincipalPolicyRecovery\n extends RecoveredScopedPrincipalPolicyHistory {\n readonly stillCurrent: () => boolean;\n}\n\nexport type ScopedPrincipalPolicyRecoveryBatch = (\n options: RecoverScopedPrincipalPolicyHistoryOptions,\n) => Promise<ScopedPrincipalPolicyRecovery>;\n\nfunction groupHead(directory: RecoveredPolicyDirectory, principalId: string) {\n const head = directory.descriptor.groupHeads.find(\n (entry) => entry.principalId === principalId,\n );\n if (!head)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Group is absent from the signed organization directory\",\n );\n return head;\n}\n\nfunction authorityHead(state: ReferencedPrincipalHead) {\n return {\n principalType: \"group\" as const,\n principalId: state.principalId,\n version: state.version,\n stateHash: state.stateHash,\n keyEpoch: state.keyEpoch,\n keyFingerprint: state.keyFingerprint,\n };\n}\n\nasync function recoverScopedPolicy(\n input: RecoverScopedPrincipalPolicyHistoryOptions,\n memo?: PrincipalRecoveryMemo,\n): Promise<ScopedPrincipalPolicyRecovery> {\n if (\n input.reference.principalType === \"organization\" &&\n input.reference.principalId !== input.organizationId\n )\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Requested organization policy is outside its scope\",\n );\n const read = createPrincipalRecoveryReader(input, memo);\n // Reused or derived evidence keeps its producers' lifetimes to its use.\n const stillCurrent = () =>\n !input.signal?.aborted && input.stillCurrent() && read.stillCurrent();\n const directory = await read.directory(\n input.reference.principalType === \"organization\" ? [input.reference] : [],\n );\n if (input.reference.principalType === \"organization\")\n return {\n current: directory.current,\n policy: directory.policy,\n dependencies: [],\n stillCurrent,\n ...(await selectDisplayHistory(input, {\n ...input,\n expectedHead: principalPolicyReferenceFromBundle(directory.current),\n protection: directoryHistoryProtection(input.protection),\n })),\n };\n const expectedHead = groupHead(directory, input.reference.principalId);\n if (input.reference.version > expectedHead.version)\n throw new PrincipalRecoveryDirectoryAdvanced();\n const adminHead = groupHead(directory, directory.descriptor.adminGroupId);\n const isAdmins = expectedHead.principalId === adminHead.principalId;\n let admins: VerifiedPrincipalPolicyCurrent | null = null;\n if (!isAdmins) {\n admins = (await read.admins(adminHead)).policy;\n }\n const loadExternalAuthority = async (\n citations: readonly ReferencedPrincipalHead[],\n ): Promise<PrincipalPolicyExternalAuthority | undefined> => {\n const references = new Map<string, ReferencedPrincipalHead>();\n for (const citation of citations) {\n if (citation.principalId !== adminHead.principalId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Group cites another organization's Admins authority\",\n );\n if (citation.version > adminHead.version)\n throw new PrincipalRecoveryDirectoryAdvanced();\n references.set(`${citation.version}:${citation.stateHash}`, citation);\n }\n if (!references.size) return undefined;\n const recovered = await read.admins(adminHead, [...references.values()]);\n return {\n currentHead: adminHead,\n states: recovered.policy.retainedHistory.map(({ state, projection }) => ({\n head: authorityHead(state),\n projection,\n })),\n };\n };\n const recoveryOptions: RecoverPrincipalPolicyHistoryOptions = {\n ...input,\n expectedHead,\n retainedReferences: [input.reference],\n historyVerification: isAdmins ? \"direct-admins\" : \"standard\",\n ...(isAdmins\n ? {}\n : {\n protection: scopedGroupHistoryProtection(\n input.protection,\n input.organizationId,\n adminHead.principalId,\n ),\n }),\n ...(isAdmins ? {} : { loadExternalAuthority }),\n };\n const recovered = isAdmins\n ? await read.admins(expectedHead, [input.reference])\n : await recoverPrincipalPolicyHistory(recoveryOptions);\n return {\n ...recovered,\n dependencies: admins ? [directory.policy, admins] : [directory.policy],\n stillCurrent,\n ...(await selectDisplayHistory(input, recoveryOptions)),\n };\n}\n\n/** Recover signed directory and strict Admins dependencies without full histories. */\nasync function recoverScopedPrincipalPolicyHistoryInBatch(\n options: RecoverScopedPrincipalPolicyHistoryOptions,\n memo?: PrincipalRecoveryMemo,\n): Promise<ScopedPrincipalPolicyRecovery> {\n if (options.offline !== undefined && typeof options.offline !== \"boolean\")\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Invalid principal history transport mode\",\n );\n if (!options.organizationId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Principal recovery requires an organization scope\",\n );\n const input = {\n apiClient: options.apiClient,\n execSql: options.execSql,\n organizationId: options.organizationId,\n offline: options.offline,\n resolveTrustedUserIdentity: options.resolveTrustedUserIdentity,\n signal: options.signal,\n stillCurrent: options.stillCurrent,\n reference: structuredClone(options.reference),\n historyPage: options.historyPage ? { ...options.historyPage } : undefined,\n protection: ownPrincipalHistoryProtection(options.protection),\n };\n try {\n // Reject malformed exact citations before any discovery or disposable writes.\n createPrincipalPolicyHistoryVerifier({\n principalId: input.reference.principalId,\n principalType: input.reference.principalType,\n retainedReferences: [input.reference],\n });\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n const recovered = await recoverScopedPolicy(input, memo);\n assertProjectionVerificationCurrent(recovered.stillCurrent);\n return recovered;\n } catch (error) {\n if (!(error instanceof PrincipalRecoveryDirectoryAdvanced)) throw error;\n memo?.directories.clear();\n memo?.admins.clear();\n if (input.offline)\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Requested principal evidence is newer than the offline directory\",\n );\n }\n }\n throw new PrincipalHistoryRecoveryRaceError(\n \"Organization directory remains behind the requested policy evidence\",\n );\n } finally {\n input.protection.localKey.fill(0);\n }\n}\n\nexport function recoverScopedPrincipalPolicyHistory(\n options: RecoverScopedPrincipalPolicyHistoryOptions,\n): Promise<RecoveredScopedPrincipalPolicyHistory> {\n return recoverScopedPrincipalPolicyHistoryInBatch(options);\n}\n\n/** Internal unbatched recovery that keeps its result's lifetime. */\nexport const recoverLeasedScopedPrincipalPolicyHistory: ScopedPrincipalPolicyRecoveryBatch =\n (options) => recoverScopedPrincipalPolicyHistoryInBatch(options);\n\nasync function selectDisplayHistory(\n input: RecoverScopedPrincipalPolicyHistoryOptions,\n options: RecoverPrincipalPolicyHistoryOptions,\n) {\n if (!input.historyPage) return {};\n return {\n historyPage: await recoverPrincipalHistoryPage(\n options,\n input.historyPage.beforeVersion ?? input.reference.version + 1,\n ),\n };\n}\n\n/** Internal runtime batch: shared results never outlive its operation or caller. */\nexport function createScopedPrincipalPolicyHistoryBatch(\n memo: PrincipalRecoveryMemo = {\n directories: new Map(),\n admins: new Map(),\n },\n): ScopedPrincipalPolicyRecoveryBatch {\n return (options) => recoverScopedPrincipalPolicyHistoryInBatch(options, memo);\n}\n"]}
|
|
@@ -60,13 +60,16 @@ export function createRuntimePrincipalPolicyCurrentResolver(runtime) {
|
|
|
60
60
|
}, input.preferLocalCurrent === true ||
|
|
61
61
|
input.preferLocalHistory === true, input.preferLocalHistory === true)
|
|
62
62
|
: await batch.discover(options);
|
|
63
|
+
// Reused evidence stays bound to every producer lifetime.
|
|
64
|
+
const resultCurrent = () => stillCurrent() && result.stillCurrent();
|
|
65
|
+
assertProjectionVerificationCurrent(resultCurrent);
|
|
63
66
|
return {
|
|
64
67
|
current: result.current,
|
|
65
68
|
organizationId: input.organizationId,
|
|
66
69
|
policy: result.policy,
|
|
67
70
|
dependencies: result.dependencies,
|
|
68
71
|
historyPage: result.historyPage,
|
|
69
|
-
stillCurrent,
|
|
72
|
+
stillCurrent: resultCurrent,
|
|
70
73
|
};
|
|
71
74
|
}
|
|
72
75
|
catch (error) {
|