@tearleads/client-sdk 0.1.19 → 0.1.21
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/index.js +2 -2
- package/client/organizations/index.js.map +1 -1
- package/client/organizations/organizationHistory.js +66 -0
- package/client/organizations/organizationHistory.js.map +1 -0
- package/client/organizations/organizationReadModels.d.ts +1 -1
- package/client/organizations/organizationReadModels.js +7 -27
- package/client/organizations/organizationReadModels.js.map +1 -1
- package/client/organizations/organizationsTypes.d.ts +1 -1
- package/client/organizations/organizationsTypes.js.map +1 -1
- package/data/containers/shared/types.d.ts +2 -2
- package/data/containers/shared/types.js.map +1 -1
- package/data/documents/shared/syncSubmitFailure.d.ts +2 -2
- package/data/documents/shared/syncSubmitFailure.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js +34 -8
- package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js +17 -0
- package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js.map +1 -0
- package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js +55 -0
- package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js.map +1 -0
- package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js +25 -13
- package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/documentPurgeProofVerification.d.ts +5 -3
- package/data/keyingProjectionVerification/documentPurgeProofVerification.js +52 -8
- package/data/keyingProjectionVerification/documentPurgeProofVerification.js.map +1 -1
- package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +4 -0
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/organizations/organizationReadModelProjection.js +2 -2
- package/data/persistence/organizations/organizationReadModelProjection.js.map +1 -1
- package/data/persistence/principalAuthorizationCheckpoints.js +1 -1
- package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -1
- package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +1 -0
- package/data/persistence/principalCurrentAcknowledgementPersistence.js +58 -12
- package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
- package/data/persistence/principalHistoryEvidencePersistence.d.ts +2 -0
- package/data/persistence/principalHistoryEvidencePersistence.js +2 -0
- package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -1
- package/data/persistence/principalHistoryIncompleteRetention.js +32 -0
- package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -0
- package/data/persistence/principalHistoryNodeRetention.js +76 -0
- package/data/persistence/principalHistoryNodeRetention.js.map +1 -0
- package/data/persistence/principalHistoryPrefixPersistence.d.ts +1 -0
- package/data/persistence/principalHistoryPrefixPersistence.js +30 -1
- package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
- package/data/persistence/principalHistoryRootOwnership.js +71 -0
- package/data/persistence/principalHistoryRootOwnership.js.map +1 -0
- package/data/persistence/principalHistoryStagePersistence.js +45 -0
- package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
- package/data/persistence/principalHistoryStageRetention.js +44 -0
- package/data/persistence/principalHistoryStageRetention.js.map +1 -0
- package/data/persistence/principalHistoryUnpublishedRetention.js +71 -0
- package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -0
- package/data/persistence/principalKeyEnvelopeArchivePersistence.js +63 -0
- package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +1 -0
- package/data/persistence/principalKeyEnvelopeCandidates.js +10 -1
- package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
- package/data/persistence/principalPolicyReferencePersistence.js +2 -2
- package/data/persistence/principalPolicyReferencePersistence.js.map +1 -1
- package/data/sqlite/principalHistoryEvidenceSchema.js +2 -0
- package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -1
- package/data/sqlite/principalHistoryNodeRetentionSchema.js +30 -0
- package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +1 -0
- package/data/sqlite/principalHistoryRetentionSchema.js +40 -0
- package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -0
- package/data/sqlite/principalHistoryStageSchema.js +2 -0
- package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
- package/data/sqlite/schema.d.ts +453 -0
- package/data/sqlite/schema.js +6 -0
- package/data/sqlite/schema.js.map +1 -1
- package/data/sqlite/sqliteCommitGuards.js +49 -0
- package/data/sqlite/sqliteCommitGuards.js.map +1 -0
- package/data/sqlite/sqlitePersistenceRuntime.js +14 -2
- package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
- package/index.d.ts +3 -1
- package/index.js.map +1 -1
- package/internal/api-client/ApiClient.d.ts +60 -137
- package/internal/api-client/ApiClient.js +7 -5
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/apiRequestRuntime.js +7 -7
- package/internal/api-client/apiRequestRuntime.js.map +1 -1
- package/internal/api-client/documentPurge.js +25 -0
- package/internal/api-client/documentPurge.js.map +1 -0
- package/internal/api-client/organizationPolicyHistory.d.ts +53 -0
- package/internal/api-client/organizationPolicyHistory.js +15 -0
- package/internal/api-client/organizationPolicyHistory.js.map +1 -0
- package/internal/api-client/requestInternals.js +4 -4
- package/internal/api-client/requestInternals.js.map +1 -1
- package/internal/api-client/types.d.ts +2 -2
- package/internal/api-client/types.js.map +1 -1
- package/internal/crypto/keying/accessEvent.js +11 -9
- package/internal/crypto/keying/accessEvent.js.map +1 -1
- package/internal/crypto/keying/principalPolicyChainEntry.js +3 -0
- package/internal/crypto/keying/principalPolicyChainEntry.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistory.js +4 -0
- package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
- package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
- package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
- package/internal/crypto/keying/principalPolicyTransition.d.ts +2 -1
- package/internal/crypto/keying/principalPolicyTransition.js +5 -0
- package/internal/crypto/keying/principalPolicyTransition.js.map +1 -1
- package/internal/crypto/principalState.js +2 -2
- package/internal/crypto/principalState.js.map +1 -1
- package/internal/validators/operation/containerMutations.d.ts +448 -6528
- package/internal/validators/operation/documentMutations.d.ts +323 -579
- package/internal/validators/operation/documentMutations.js +22 -4
- package/internal/validators/operation/documentMutations.js.map +1 -1
- package/internal/validators/operation/documentSync.d.ts +26 -406
- package/internal/validators/operation/organizationPolicyHistory.d.ts +188 -310
- package/internal/validators/operation/organizationPolicyHistory.js +17 -3
- package/internal/validators/operation/organizationPolicyHistory.js.map +1 -1
- package/internal/validators/operation/organizations.d.ts +2 -2
- package/internal/validators/request/principal.js +2 -2
- package/internal/validators/request/principal.js.map +1 -1
- package/internal/validators/response/containerMutationError.d.ts +28 -408
- package/internal/validators/response/documentMutation.d.ts +232 -544
- package/internal/validators/response/documentMutation.js +1 -2
- package/internal/validators/response/documentMutation.js.map +1 -1
- package/internal/validators/response/documentSyncError.d.ts +26 -406
- package/internal/validators/response/documentSyncError.js +4 -3
- package/internal/validators/response/documentSyncError.js.map +1 -1
- package/internal/validators/response/index.d.ts +1 -1
- package/internal/validators/response/index.js +1 -1
- package/internal/validators/response/index.js.map +1 -1
- package/internal/validators/response/organization.d.ts +1 -1
- package/internal/validators/response/organization.js +1 -1
- package/internal/validators/response/organization.js.map +1 -1
- package/internal/validators/response/organizationPolicyHistory.d.ts +127 -309
- package/internal/validators/response/organizationPolicyHistory.js +10 -4
- package/internal/validators/response/organizationPolicyHistory.js.map +1 -1
- package/internal/validators/response/organizationReadModel.d.ts +5 -5
- package/internal/validators/response/principal.d.ts +28 -408
- package/internal/validators/response/principal.js +3 -1
- package/internal/validators/response/principal.js.map +1 -1
- package/internal/validators/response/principalReference.d.ts +1 -1
- package/internal/validators/response/principalReference.js +1 -1
- package/internal/validators/response/principalReference.js.map +1 -1
- package/internal/validators/response/principalSnapshot.js +4 -4
- package/internal/validators/response/principalSnapshot.js.map +1 -1
- package/internal/validators/util/index.d.ts +1 -1
- package/internal/validators/util/index.js +1 -1
- package/internal/validators/util/index.js.map +1 -1
- package/internal/validators/util/principalHistoryWire.d.ts +2 -0
- package/internal/validators/util/principalHistoryWire.js +2 -0
- package/internal/validators/util/principalHistoryWire.js.map +1 -1
- package/package.json +1 -1
- package/workflows/container-contents/container-state/createWithMetadata.js +19 -49
- package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
- package/workflows/container-contents/container-state/groupGrantVerification.js +29 -0
- package/workflows/container-contents/container-state/groupGrantVerification.js.map +1 -1
- package/workflows/container-contents/container-state/groupShareEpoch.js +33 -0
- package/workflows/container-contents/container-state/groupShareEpoch.js.map +1 -0
- package/workflows/container-contents/container-state/remote.js +4 -1
- package/workflows/container-contents/container-state/remote.js.map +1 -1
- package/workflows/container-contents/container-state/share.js +2 -24
- package/workflows/container-contents/container-state/share.js.map +1 -1
- package/workflows/container-contents/documentTombstoneEvidence.js +23 -12
- package/workflows/container-contents/documentTombstoneEvidence.js.map +1 -1
- package/workflows/containers/child/create.js +1 -3
- package/workflows/containers/child/create.js.map +1 -1
- package/workflows/containers/child/createSubmission.d.ts +1 -3
- package/workflows/containers/child/createSubmission.js +13 -15
- package/workflows/containers/child/createSubmission.js.map +1 -1
- package/workflows/containers/child/currentShareGrantMutation.js +82 -0
- package/workflows/containers/child/currentShareGrantMutation.js.map +1 -0
- package/workflows/containers/child/currentSharePrincipalPolicy.js +83 -0
- package/workflows/containers/child/currentSharePrincipalPolicy.js.map +1 -0
- package/workflows/containers/child/mutationSubmit.js +1 -1
- package/workflows/containers/child/mutationSubmit.js.map +1 -1
- package/workflows/containers/child/runtimeCurrentGroupShare.js +82 -0
- package/workflows/containers/child/runtimeCurrentGroupShare.js.map +1 -0
- package/workflows/containers/child/share.js +1 -14
- package/workflows/containers/child/share.js.map +1 -1
- package/workflows/containers/child/shareProjection.js +15 -0
- package/workflows/containers/child/shareProjection.js.map +1 -0
- package/workflows/containers/mutationResponse.js +1 -1
- package/workflows/containers/mutationResponse.js.map +1 -1
- package/workflows/documents/purge.d.ts +3 -0
- package/workflows/documents/purge.js +13 -0
- package/workflows/documents/purge.js.map +1 -1
- package/workflows/documents/sync.js +2 -0
- package/workflows/documents/sync.js.map +1 -1
- package/workflows/documents/syncFailures.js +2 -2
- package/workflows/documents/syncFailures.js.map +1 -1
- package/workflows/documents/syncPolicyRepair.js +15 -13
- package/workflows/documents/syncPolicyRepair.js.map +1 -1
- package/workflows/organizations/initialPrincipalCurrentPublication.js +2 -0
- package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -1
- package/workflows/organizations/loadPolicyHistoryDetails.js +31 -32
- package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
- package/workflows/organizations/organizationPolicyHistoryDetails.js +37 -15
- package/workflows/organizations/organizationPolicyHistoryDetails.js.map +1 -1
- package/workflows/organizations/organizationPolicyHistoryVerification.js +56 -69
- package/workflows/organizations/organizationPolicyHistoryVerification.js.map +1 -1
- package/workflows/organizations/policyHistoryCache.js +5 -2
- package/workflows/organizations/policyHistoryCache.js.map +1 -1
- package/workflows/organizations/policyHistoryTypes.d.ts +1 -0
- package/workflows/organizations/policyHistoryTypes.js.map +1 -1
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +4 -1
- package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
- package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +0 -1
- package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +1 -2
- package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -1
- package/workflows/principals/policyRepair.js +38 -0
- package/workflows/principals/policyRepair.js.map +1 -0
- package/workflows/principals/policyRepairBudget.d.ts +2 -2
- package/workflows/principals/policyRepairBudget.js +3 -3
- package/workflows/principals/policyRepairBudget.js.map +1 -1
- package/workflows/principals/principalHistoryRecoveryPrefix.js +4 -0
- package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -1
- package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
- package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryPage.js +1 -0
- package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryProgress.js +1 -0
- package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -1
- package/workflows/principals/publicPrincipalHistoryTypes.d.ts +2 -0
- package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -1
- package/workflows/principals/publicProjectionPrincipal.js +1 -0
- package/workflows/principals/publicProjectionPrincipal.js.map +1 -1
- package/workflows/principals/recoverPrincipalHistoryPage.js +2 -1
- package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js +1 -0
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverPublicPrincipalHistory.js +2 -0
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +2 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/selectPublicPrincipalHistory.js +21 -15
- package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -1
- package/workflows/sync/remoteResetPrincipalScope.js +6 -0
- package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js +0 -208
- package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js.map +0 -1
- package/data/keyingProjectionVerification/snapshotVerificationCache.js +0 -39
- package/data/keyingProjectionVerification/snapshotVerificationCache.js.map +0 -1
- package/workflows/containers/child/policyRepair.js +0 -23
- package/workflows/containers/child/policyRepair.js.map +0 -1
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import { KeyingVerificationError, principalPolicyMatchesReference, toFingerprint, verifyPrincipalPolicyCheckpoint, } from "../../internal/crypto/index.js";
|
|
2
|
-
import { loadPrincipalPolicyCheckpoint } from "../persistence/keyingCheckpointPersistence.js";
|
|
3
|
-
import { loadPrincipalPolicyBundleForReference } from "../persistence/principalPolicyReferencePersistence.js";
|
|
4
|
-
import { ProjectionDependencyUnavailableError } from "./dependencyUnavailable.js";
|
|
5
|
-
import { verifyReceivedPolicySnapshot } from "./snapshotVerificationCache.js";
|
|
6
|
-
function identityKey(input) {
|
|
7
|
-
return `${input.principalType}:${input.principalId}`;
|
|
8
|
-
}
|
|
9
|
-
function snapshotStates(snapshot) {
|
|
10
|
-
return [
|
|
11
|
-
...snapshot.previousStates.map((entry) => entry.state),
|
|
12
|
-
snapshot.currentState,
|
|
13
|
-
];
|
|
14
|
-
}
|
|
15
|
-
function snapshotReference(snapshot) {
|
|
16
|
-
const state = snapshot.currentState;
|
|
17
|
-
return {
|
|
18
|
-
principalType: state.principalType,
|
|
19
|
-
principalId: state.principalId,
|
|
20
|
-
version: state.version,
|
|
21
|
-
keyEpoch: state.keyEpoch,
|
|
22
|
-
stateHash: state.stateHash,
|
|
23
|
-
keyFingerprint: state.keyFingerprint,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
async function signerPublicKeys(input) {
|
|
27
|
-
const keys = new Map();
|
|
28
|
-
for (const state of snapshotStates(input.snapshot)) {
|
|
29
|
-
const key = `${state.signerUserId}:${state.signerUserKeyFingerprint}`;
|
|
30
|
-
if (keys.has(key)) {
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
const identity = await input.resolveUserKey(state.signerUserId);
|
|
34
|
-
if (!identity) {
|
|
35
|
-
throw new ProjectionDependencyUnavailableError(`Principal policy snapshot signer ${state.signerUserId} is unavailable`);
|
|
36
|
-
}
|
|
37
|
-
const fingerprint = await toFingerprint(identity.signingPublicKey);
|
|
38
|
-
if (fingerprint !== state.signerUserKeyFingerprint) {
|
|
39
|
-
throw new KeyingVerificationError("signer_mismatch", "Principal policy snapshot signer fingerprint mismatch");
|
|
40
|
-
}
|
|
41
|
-
keys.set(key, {
|
|
42
|
-
userId: state.signerUserId,
|
|
43
|
-
signingKeyFingerprint: fingerprint,
|
|
44
|
-
signingPublicKey: identity.signingPublicKey,
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
return [...keys.values()];
|
|
48
|
-
}
|
|
49
|
-
function authorityReference(snapshot) {
|
|
50
|
-
const references = snapshotStates(snapshot).flatMap((state) => state.externalAuthority ? [state.externalAuthority] : []);
|
|
51
|
-
if (references.length === 0) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
const [first] = references;
|
|
55
|
-
if (!first ||
|
|
56
|
-
references.some((reference) => reference.principalId !== first.principalId ||
|
|
57
|
-
reference.principalType !== first.principalType)) {
|
|
58
|
-
throw new KeyingVerificationError("invalid_shape", "Principal policy snapshot cites inconsistent external authority");
|
|
59
|
-
}
|
|
60
|
-
return references.reduce((latest, reference) => reference.version > latest.version ? reference : latest);
|
|
61
|
-
}
|
|
62
|
-
function externalAuthority(policy) {
|
|
63
|
-
const states = policy.history.map((entry) => {
|
|
64
|
-
if (entry.state.principalType !== "group" ||
|
|
65
|
-
entry.projection.length === 0 ||
|
|
66
|
-
entry.projection.some((member) => member.role !== "admin")) {
|
|
67
|
-
throw new KeyingVerificationError("unauthorized", "Principal policy snapshot authority is invalid");
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
head: {
|
|
71
|
-
principalType: "group",
|
|
72
|
-
principalId: entry.state.principalId,
|
|
73
|
-
version: entry.state.version,
|
|
74
|
-
keyEpoch: entry.state.keyEpoch,
|
|
75
|
-
stateHash: entry.state.stateHash,
|
|
76
|
-
keyFingerprint: entry.state.keyFingerprint,
|
|
77
|
-
},
|
|
78
|
-
projection: entry.projection,
|
|
79
|
-
};
|
|
80
|
-
});
|
|
81
|
-
const current = states.at(-1);
|
|
82
|
-
if (!current) {
|
|
83
|
-
throw new KeyingVerificationError("missing_dependency", "Principal policy snapshot authority is empty");
|
|
84
|
-
}
|
|
85
|
-
return { currentHead: current.head, states };
|
|
86
|
-
}
|
|
87
|
-
async function verifySnapshotAuthorization(input) {
|
|
88
|
-
const reference = snapshotReference(input.snapshot);
|
|
89
|
-
const authorityHead = authorityReference(input.snapshot);
|
|
90
|
-
if (reference.principalType === "organization" && authorityHead) {
|
|
91
|
-
throw new KeyingVerificationError("unauthorized", "organization states cannot cite external authority");
|
|
92
|
-
}
|
|
93
|
-
if (!authorityHead) {
|
|
94
|
-
const direct = await verifyReceivedPolicySnapshot({
|
|
95
|
-
expectedReference: reference,
|
|
96
|
-
signerPublicKeys: input.signerPublicKeys,
|
|
97
|
-
snapshot: input.snapshot,
|
|
98
|
-
});
|
|
99
|
-
if (!direct.ok)
|
|
100
|
-
throw direct.error;
|
|
101
|
-
return direct.value;
|
|
102
|
-
}
|
|
103
|
-
const authorityPolicy = await input.resolveAuthority(authorityHead);
|
|
104
|
-
if (!principalPolicyMatchesReference({
|
|
105
|
-
policy: authorityPolicy,
|
|
106
|
-
reference: authorityHead,
|
|
107
|
-
})) {
|
|
108
|
-
throw new KeyingVerificationError("missing_dependency", "Principal policy snapshot authority omits the referenced head");
|
|
109
|
-
}
|
|
110
|
-
const verified = await verifyReceivedPolicySnapshot({
|
|
111
|
-
expectedReference: reference,
|
|
112
|
-
externalAuthority: externalAuthority(authorityPolicy),
|
|
113
|
-
signerPublicKeys: input.signerPublicKeys,
|
|
114
|
-
snapshot: input.snapshot,
|
|
115
|
-
});
|
|
116
|
-
if (!verified.ok) {
|
|
117
|
-
throw verified.error;
|
|
118
|
-
}
|
|
119
|
-
return verified.value;
|
|
120
|
-
}
|
|
121
|
-
async function enforceSnapshotCheckpoint(input) {
|
|
122
|
-
const checkpoint = await loadPrincipalPolicyCheckpoint(input.execSql, input.reference.principalType, input.reference.principalId);
|
|
123
|
-
if (!checkpoint)
|
|
124
|
-
return true;
|
|
125
|
-
if (input.policy.version >= checkpoint.version) {
|
|
126
|
-
verifyPrincipalPolicyCheckpoint({
|
|
127
|
-
chain: input.policy.history,
|
|
128
|
-
currentState: input.policy.state,
|
|
129
|
-
localCheckpoint: checkpoint,
|
|
130
|
-
});
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
const localDescendant = await loadPrincipalPolicyBundleForReference(input.execSql, input.reference, checkpoint);
|
|
134
|
-
if (!localDescendant) {
|
|
135
|
-
throw new KeyingVerificationError("rollback", "Principal policy snapshot cannot be connected to the newer local checkpoint");
|
|
136
|
-
}
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
export async function verifyPrincipalPolicySnapshots(input) {
|
|
140
|
-
const snapshotsByPrincipal = new Map();
|
|
141
|
-
for (const snapshot of input.snapshots) {
|
|
142
|
-
const key = identityKey(snapshot.currentState);
|
|
143
|
-
if (snapshotsByPrincipal.has(key)) {
|
|
144
|
-
throw new KeyingVerificationError("invalid_shape", "Principal policy snapshots contain a duplicate principal");
|
|
145
|
-
}
|
|
146
|
-
snapshotsByPrincipal.set(key, snapshot);
|
|
147
|
-
}
|
|
148
|
-
const verifiedByPrincipal = new Map();
|
|
149
|
-
const visiting = new Set();
|
|
150
|
-
const verifyOne = async (snapshot) => {
|
|
151
|
-
const key = identityKey(snapshot.currentState);
|
|
152
|
-
const cached = verifiedByPrincipal.get(key);
|
|
153
|
-
if (cached) {
|
|
154
|
-
return cached;
|
|
155
|
-
}
|
|
156
|
-
if (visiting.has(key)) {
|
|
157
|
-
throw new KeyingVerificationError("invalid_shape", "Principal policy snapshot authority contains a cycle");
|
|
158
|
-
}
|
|
159
|
-
visiting.add(key);
|
|
160
|
-
try {
|
|
161
|
-
const publicKeys = await signerPublicKeys({
|
|
162
|
-
resolveUserKey: input.resolveUserKey,
|
|
163
|
-
snapshot,
|
|
164
|
-
});
|
|
165
|
-
const policy = await verifySnapshotAuthorization({
|
|
166
|
-
resolveAuthority: async (reference) => {
|
|
167
|
-
const authoritySnapshot = snapshotsByPrincipal.get(identityKey(reference));
|
|
168
|
-
if (!authoritySnapshot) {
|
|
169
|
-
throw new KeyingVerificationError("missing_dependency", "Principal policy snapshot authority is missing");
|
|
170
|
-
}
|
|
171
|
-
return verifyOne(authoritySnapshot);
|
|
172
|
-
},
|
|
173
|
-
signerPublicKeys: publicKeys,
|
|
174
|
-
snapshot,
|
|
175
|
-
});
|
|
176
|
-
verifiedByPrincipal.set(key, policy);
|
|
177
|
-
return policy;
|
|
178
|
-
}
|
|
179
|
-
finally {
|
|
180
|
-
visiting.delete(key);
|
|
181
|
-
}
|
|
182
|
-
};
|
|
183
|
-
for (const snapshot of input.snapshots) {
|
|
184
|
-
await verifyOne(snapshot);
|
|
185
|
-
}
|
|
186
|
-
return [...verifiedByPrincipal.values()];
|
|
187
|
-
}
|
|
188
|
-
export async function enforcePrincipalPolicySnapshotCheckpoints(input) {
|
|
189
|
-
const policiesToPin = [];
|
|
190
|
-
for (const policy of input.policies) {
|
|
191
|
-
const shouldPin = await enforceSnapshotCheckpoint({
|
|
192
|
-
execSql: input.execSql,
|
|
193
|
-
policy,
|
|
194
|
-
reference: {
|
|
195
|
-
principalType: policy.state.principalType,
|
|
196
|
-
principalId: policy.state.principalId,
|
|
197
|
-
version: policy.state.version,
|
|
198
|
-
keyEpoch: policy.state.keyEpoch,
|
|
199
|
-
stateHash: policy.state.stateHash,
|
|
200
|
-
keyFingerprint: policy.state.keyFingerprint,
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
if (shouldPin)
|
|
204
|
-
policiesToPin.push(policy);
|
|
205
|
-
}
|
|
206
|
-
return policiesToPin;
|
|
207
|
-
}
|
|
208
|
-
//# sourceMappingURL=principalPolicySnapshotVerification.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"principalPolicySnapshotVerification.js","sourceRoot":"","sources":["principalPolicySnapshotVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PrincipalPolicyExternalAuthority,\n PrincipalPolicySignerPublicKey,\n ReferencedPrincipalHead,\n VerifiedPrincipalPolicySnapshot,\n} from \"@tearleads/crypto\";\nimport {\n KeyingVerificationError,\n principalPolicyMatchesReference,\n toFingerprint,\n verifyPrincipalPolicyCheckpoint,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicySnapshotResponse } from \"@tearleads/validators/response\";\nimport { loadPrincipalPolicyCheckpoint } from \"../persistence/keyingCheckpointPersistence\";\nimport { loadPrincipalPolicyBundleForReference } from \"../persistence/principalPolicyReferencePersistence\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { verifyReceivedPolicySnapshot } from \"./snapshotVerificationCache\";\nimport type { ProjectionUserKeyResolver } from \"./types\";\n\nfunction identityKey(input: {\n readonly principalId: string;\n readonly principalType: string;\n}): string {\n return `${input.principalType}:${input.principalId}`;\n}\n\nfunction snapshotStates(snapshot: PrincipalPolicySnapshotResponse) {\n return [\n ...snapshot.previousStates.map((entry) => entry.state),\n snapshot.currentState,\n ];\n}\n\nfunction snapshotReference(\n snapshot: PrincipalPolicySnapshotResponse,\n): ReferencedPrincipalHead {\n const state = snapshot.currentState;\n return {\n principalType: state.principalType,\n principalId: state.principalId,\n version: state.version,\n keyEpoch: state.keyEpoch,\n stateHash: state.stateHash,\n keyFingerprint: state.keyFingerprint,\n };\n}\n\nasync function signerPublicKeys(input: {\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly snapshot: PrincipalPolicySnapshotResponse;\n}): Promise<PrincipalPolicySignerPublicKey[]> {\n const keys = new Map<string, PrincipalPolicySignerPublicKey>();\n for (const state of snapshotStates(input.snapshot)) {\n const key = `${state.signerUserId}:${state.signerUserKeyFingerprint}`;\n if (keys.has(key)) {\n continue;\n }\n const identity = await input.resolveUserKey(state.signerUserId);\n if (!identity) {\n throw new ProjectionDependencyUnavailableError(\n `Principal policy snapshot signer ${state.signerUserId} is unavailable`,\n );\n }\n const fingerprint = await toFingerprint(identity.signingPublicKey);\n if (fingerprint !== state.signerUserKeyFingerprint) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n \"Principal policy snapshot signer fingerprint mismatch\",\n );\n }\n keys.set(key, {\n userId: state.signerUserId,\n signingKeyFingerprint: fingerprint,\n signingPublicKey: identity.signingPublicKey,\n });\n }\n return [...keys.values()];\n}\n\nfunction authorityReference(\n snapshot: PrincipalPolicySnapshotResponse,\n): ReferencedPrincipalHead | null {\n const references = snapshotStates(snapshot).flatMap((state) =>\n state.externalAuthority ? [state.externalAuthority] : [],\n );\n if (references.length === 0) {\n return null;\n }\n const [first] = references;\n if (\n !first ||\n references.some(\n (reference) =>\n reference.principalId !== first.principalId ||\n reference.principalType !== first.principalType,\n )\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal policy snapshot cites inconsistent external authority\",\n );\n }\n return references.reduce((latest, reference) =>\n reference.version > latest.version ? reference : latest,\n );\n}\n\nfunction externalAuthority(\n policy: VerifiedPrincipalPolicySnapshot,\n): PrincipalPolicyExternalAuthority {\n const states = policy.history.map((entry) => {\n if (\n entry.state.principalType !== \"group\" ||\n entry.projection.length === 0 ||\n entry.projection.some((member) => member.role !== \"admin\")\n ) {\n throw new KeyingVerificationError(\n \"unauthorized\",\n \"Principal policy snapshot authority is invalid\",\n );\n }\n return {\n head: {\n principalType: \"group\" as const,\n principalId: entry.state.principalId,\n version: entry.state.version,\n keyEpoch: entry.state.keyEpoch,\n stateHash: entry.state.stateHash,\n keyFingerprint: entry.state.keyFingerprint,\n },\n projection: entry.projection,\n };\n });\n const current = states.at(-1);\n if (!current) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal policy snapshot authority is empty\",\n );\n }\n return { currentHead: current.head, states };\n}\n\nasync function verifySnapshotAuthorization(input: {\n readonly resolveAuthority: (\n reference: ReferencedPrincipalHead,\n ) => Promise<VerifiedPrincipalPolicySnapshot>;\n readonly signerPublicKeys: readonly PrincipalPolicySignerPublicKey[];\n readonly snapshot: PrincipalPolicySnapshotResponse;\n}): Promise<VerifiedPrincipalPolicySnapshot> {\n const reference = snapshotReference(input.snapshot);\n const authorityHead = authorityReference(input.snapshot);\n if (reference.principalType === \"organization\" && authorityHead) {\n throw new KeyingVerificationError(\n \"unauthorized\",\n \"organization states cannot cite external authority\",\n );\n }\n if (!authorityHead) {\n const direct = await verifyReceivedPolicySnapshot({\n expectedReference: reference,\n signerPublicKeys: input.signerPublicKeys,\n snapshot: input.snapshot,\n });\n if (!direct.ok) throw direct.error;\n return direct.value;\n }\n const authorityPolicy = await input.resolveAuthority(authorityHead);\n if (\n !principalPolicyMatchesReference({\n policy: authorityPolicy,\n reference: authorityHead,\n })\n ) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal policy snapshot authority omits the referenced head\",\n );\n }\n const verified = await verifyReceivedPolicySnapshot({\n expectedReference: reference,\n externalAuthority: externalAuthority(authorityPolicy),\n signerPublicKeys: input.signerPublicKeys,\n snapshot: input.snapshot,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n return verified.value;\n}\n\nasync function enforceSnapshotCheckpoint(input: {\n readonly execSql: ExecSql;\n readonly policy: VerifiedPrincipalPolicySnapshot;\n readonly reference: ReferencedPrincipalHead;\n}): Promise<boolean> {\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n input.reference.principalType,\n input.reference.principalId,\n );\n if (!checkpoint) return true;\n if (input.policy.version >= checkpoint.version) {\n verifyPrincipalPolicyCheckpoint({\n chain: input.policy.history,\n currentState: input.policy.state,\n localCheckpoint: checkpoint,\n });\n return true;\n }\n const localDescendant = await loadPrincipalPolicyBundleForReference(\n input.execSql,\n input.reference,\n checkpoint,\n );\n if (!localDescendant) {\n throw new KeyingVerificationError(\n \"rollback\",\n \"Principal policy snapshot cannot be connected to the newer local checkpoint\",\n );\n }\n return false;\n}\n\nexport async function verifyPrincipalPolicySnapshots(input: {\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly snapshots: readonly PrincipalPolicySnapshotResponse[];\n}): Promise<VerifiedPrincipalPolicySnapshot[]> {\n const snapshotsByPrincipal = new Map<\n string,\n PrincipalPolicySnapshotResponse\n >();\n for (const snapshot of input.snapshots) {\n const key = identityKey(snapshot.currentState);\n if (snapshotsByPrincipal.has(key)) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal policy snapshots contain a duplicate principal\",\n );\n }\n snapshotsByPrincipal.set(key, snapshot);\n }\n const verifiedByPrincipal = new Map<\n string,\n VerifiedPrincipalPolicySnapshot\n >();\n const visiting = new Set<string>();\n\n const verifyOne = async (\n snapshot: PrincipalPolicySnapshotResponse,\n ): Promise<VerifiedPrincipalPolicySnapshot> => {\n const key = identityKey(snapshot.currentState);\n const cached = verifiedByPrincipal.get(key);\n if (cached) {\n return cached;\n }\n if (visiting.has(key)) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal policy snapshot authority contains a cycle\",\n );\n }\n visiting.add(key);\n try {\n const publicKeys = await signerPublicKeys({\n resolveUserKey: input.resolveUserKey,\n snapshot,\n });\n const policy = await verifySnapshotAuthorization({\n resolveAuthority: async (reference) => {\n const authoritySnapshot = snapshotsByPrincipal.get(\n identityKey(reference),\n );\n if (!authoritySnapshot) {\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal policy snapshot authority is missing\",\n );\n }\n return verifyOne(authoritySnapshot);\n },\n signerPublicKeys: publicKeys,\n snapshot,\n });\n verifiedByPrincipal.set(key, policy);\n return policy;\n } finally {\n visiting.delete(key);\n }\n };\n\n for (const snapshot of input.snapshots) {\n await verifyOne(snapshot);\n }\n return [...verifiedByPrincipal.values()];\n}\n\nexport async function enforcePrincipalPolicySnapshotCheckpoints(input: {\n readonly execSql: ExecSql;\n readonly policies: readonly VerifiedPrincipalPolicySnapshot[];\n}): Promise<VerifiedPrincipalPolicySnapshot[]> {\n const policiesToPin: VerifiedPrincipalPolicySnapshot[] = [];\n for (const policy of input.policies) {\n const shouldPin = await enforceSnapshotCheckpoint({\n execSql: input.execSql,\n policy,\n reference: {\n principalType: policy.state.principalType,\n principalId: policy.state.principalId,\n version: policy.state.version,\n keyEpoch: policy.state.keyEpoch,\n stateHash: policy.state.stateHash,\n keyFingerprint: policy.state.keyFingerprint,\n },\n });\n if (shouldPin) policiesToPin.push(policy);\n }\n return policiesToPin;\n}\n"]}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { bytesToHex, createIncrementalSha256, verifyPrincipalPolicySnapshot, } from "../../internal/crypto/index.js";
|
|
2
|
-
// Bind independently decoded responses to their actual bytes, reference, trusted
|
|
3
|
-
// signer keys and external authority. Checkpoints remain checked by the caller.
|
|
4
|
-
const verified = new Map();
|
|
5
|
-
const MAX_CACHED_SOURCE_CHARACTERS = 4_000_000;
|
|
6
|
-
const MAX_ENTRIES = 16;
|
|
7
|
-
function freezeResult(value) {
|
|
8
|
-
for (const child of Object.values(value)) {
|
|
9
|
-
if (typeof child === "object" && child !== null && !Object.isFrozen(child))
|
|
10
|
-
freezeResult(child);
|
|
11
|
-
}
|
|
12
|
-
Object.freeze(value);
|
|
13
|
-
}
|
|
14
|
-
export async function verifyReceivedPolicySnapshot(input) {
|
|
15
|
-
const source = JSON.stringify(input);
|
|
16
|
-
if (source.length > MAX_CACHED_SOURCE_CHARACTERS)
|
|
17
|
-
return verifyPrincipalPolicySnapshot(input);
|
|
18
|
-
const hash = createIncrementalSha256();
|
|
19
|
-
hash.update(new TextEncoder().encode(source));
|
|
20
|
-
const key = bytesToHex(hash.digest());
|
|
21
|
-
const cached = verified.get(key);
|
|
22
|
-
if (cached) {
|
|
23
|
-
verified.delete(key);
|
|
24
|
-
verified.set(key, cached);
|
|
25
|
-
return cached;
|
|
26
|
-
}
|
|
27
|
-
const result = await verifyPrincipalPolicySnapshot(structuredClone(input));
|
|
28
|
-
if (result.ok) {
|
|
29
|
-
freezeResult(result);
|
|
30
|
-
verified.set(key, result);
|
|
31
|
-
while (verified.size > MAX_ENTRIES) {
|
|
32
|
-
const oldest = verified.keys().next().value;
|
|
33
|
-
if (oldest !== undefined)
|
|
34
|
-
verified.delete(oldest);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
//# sourceMappingURL=snapshotVerificationCache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"snapshotVerificationCache.js","sourceRoot":"","sources":["snapshotVerificationCache.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,mBAAmB,CAAC;AAK3B,iFAAiF;AACjF,gFAAgF;AAChF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;AACnD,MAAM,4BAA4B,GAAG,SAAS,CAAC;AAC/C,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,SAAS,YAAY,CAAC,KAAa;IACjC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YACxE,YAAY,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,KAAoB;IAEpB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,MAAM,CAAC,MAAM,GAAG,4BAA4B;QAC9C,OAAO,6BAA6B,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1B,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,6BAA6B,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IAC3E,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,YAAY,CAAC,MAAM,CAAC,CAAC;QACrB,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1B,OAAO,QAAQ,CAAC,IAAI,GAAG,WAAW,EAAE,CAAC;YACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAC5C,IAAI,MAAM,KAAK,SAAS;gBAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import {\n bytesToHex,\n createIncrementalSha256,\n verifyPrincipalPolicySnapshot,\n} from \"@tearleads/crypto\";\n\ntype SnapshotInput = Parameters<typeof verifyPrincipalPolicySnapshot>[0];\ntype SnapshotResult = Awaited<ReturnType<typeof verifyPrincipalPolicySnapshot>>;\n\n// Bind independently decoded responses to their actual bytes, reference, trusted\n// signer keys and external authority. Checkpoints remain checked by the caller.\nconst verified = new Map<string, SnapshotResult>();\nconst MAX_CACHED_SOURCE_CHARACTERS = 4_000_000;\nconst MAX_ENTRIES = 16;\n\nfunction freezeResult(value: object): void {\n for (const child of Object.values(value)) {\n if (typeof child === \"object\" && child !== null && !Object.isFrozen(child))\n freezeResult(child);\n }\n Object.freeze(value);\n}\n\nexport async function verifyReceivedPolicySnapshot(\n input: SnapshotInput,\n): Promise<SnapshotResult> {\n const source = JSON.stringify(input);\n if (source.length > MAX_CACHED_SOURCE_CHARACTERS)\n return verifyPrincipalPolicySnapshot(input);\n const hash = createIncrementalSha256();\n hash.update(new TextEncoder().encode(source));\n const key = bytesToHex(hash.digest());\n const cached = verified.get(key);\n if (cached) {\n verified.delete(key);\n verified.set(key, cached);\n return cached;\n }\n const result = await verifyPrincipalPolicySnapshot(structuredClone(input));\n if (result.ok) {\n freezeResult(result);\n verified.set(key, result);\n while (verified.size > MAX_ENTRIES) {\n const oldest = verified.keys().next().value;\n if (oldest !== undefined) verified.delete(oldest);\n }\n }\n return result;\n}\n"]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { cachePrincipalPolicyBundles } from "../../principals/policyCache.js";
|
|
2
|
-
export async function cacheRemoteContainerCreatePolicyRepair(input) {
|
|
3
|
-
const bundles = input.failure.stalePrincipalPolicies;
|
|
4
|
-
if (!input.execSql ||
|
|
5
|
-
!bundles ||
|
|
6
|
-
bundles.length === 0 ||
|
|
7
|
-
input.stillCurrent?.() === false) {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
// The server supplied fresh signed policy bundles with the 409. Verify and
|
|
11
|
-
// cache them locally before rebuilding the signed create request.
|
|
12
|
-
await cachePrincipalPolicyBundles({
|
|
13
|
-
bundles,
|
|
14
|
-
execSql: input.execSql,
|
|
15
|
-
getCurrentPrincipalPolicy: input.apiClient.getCurrentPrincipalPolicy.bind(input.apiClient),
|
|
16
|
-
organizationId: input.organizationId,
|
|
17
|
-
reportSecurityIncident: input.reportSecurityIncident,
|
|
18
|
-
resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,
|
|
19
|
-
stillCurrent: input.stillCurrent,
|
|
20
|
-
});
|
|
21
|
-
return input.stillCurrent?.() !== false;
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=policyRepair.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"policyRepair.js","sourceRoot":"","sources":["policyRepair.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAE3E,MAAM,CAAC,KAAK,UAAU,sCAAsC,CAAC,KAQ5D;IACC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,sBAAsB,CAAC;IACrD,IACE,CAAC,KAAK,CAAC,OAAO;QACd,CAAC,OAAO;QACR,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,EAChC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2EAA2E;IAC3E,kEAAkE;IAClE,MAAM,2BAA2B,CAAC;QAChC,OAAO;QACP,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,yBAAyB,EAAE,KAAK,CAAC,SAAS,CAAC,yBAAyB,CAAC,IAAI,CACvE,KAAK,CAAC,SAAS,CAChB;QACD,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,sBAAsB,EAAE,KAAK,CAAC,sBAAsB;QACpD,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;QAC5D,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,CAAC;AAC1C,CAAC","sourcesContent":["import type {\n ContainerCreateApi,\n ContainerMutationSubmitFailure,\n} from \"../../../data/containers/shared/types\";\nimport type { SecurityIncidentReporter } from \"../../../data/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport { cachePrincipalPolicyBundles } from \"../../principals/policyCache\";\n\nexport async function cacheRemoteContainerCreatePolicyRepair(input: {\n readonly apiClient: ContainerCreateApi;\n readonly execSql: ExecSql | undefined;\n readonly failure: ContainerMutationSubmitFailure;\n readonly organizationId: string;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n const bundles = input.failure.stalePrincipalPolicies;\n if (\n !input.execSql ||\n !bundles ||\n bundles.length === 0 ||\n input.stillCurrent?.() === false\n ) {\n return false;\n }\n\n // The server supplied fresh signed policy bundles with the 409. Verify and\n // cache them locally before rebuilding the signed create request.\n await cachePrincipalPolicyBundles({\n bundles,\n execSql: input.execSql,\n getCurrentPrincipalPolicy: input.apiClient.getCurrentPrincipalPolicy.bind(\n input.apiClient,\n ),\n organizationId: input.organizationId,\n reportSecurityIncident: input.reportSecurityIncident,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n return input.stillCurrent?.() !== false;\n}\n"]}
|