@learncard/sss-key-manager 0.1.24 → 0.2.1
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/README.md +25 -95
- package/dist/api-client.d.ts +44 -7
- package/dist/api-client.d.ts.map +1 -1
- package/dist/atomic-operations.d.ts +10 -2
- package/dist/atomic-operations.d.ts.map +1 -1
- package/dist/email-relay-crypto.d.ts +49 -0
- package/dist/email-relay-crypto.d.ts.map +1 -0
- package/dist/escrow-attestation.d.ts +12 -0
- package/dist/escrow-attestation.d.ts.map +1 -0
- package/dist/escrow-crypto.d.ts +52 -0
- package/dist/escrow-crypto.d.ts.map +1 -0
- package/dist/escrow-nitro-attestation.d.ts +32 -0
- package/dist/escrow-nitro-attestation.d.ts.map +1 -0
- package/dist/escrow-pin.d.ts +22 -0
- package/dist/escrow-pin.d.ts.map +1 -0
- package/dist/index.d.ts +15 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/key-manager.d.ts +2 -0
- package/dist/key-manager.d.ts.map +1 -1
- package/dist/qr-login.d.ts.map +1 -1
- package/dist/recovery-phrase.d.ts +6 -0
- package/dist/recovery-phrase.d.ts.map +1 -1
- package/dist/sss-key-manager.cjs.development.js +5564 -353
- package/dist/sss-key-manager.cjs.development.js.map +4 -4
- package/dist/sss-key-manager.cjs.production.min.js +33 -33
- package/dist/sss-key-manager.cjs.production.min.js.map +4 -4
- package/dist/sss-key-manager.esm.js +3494 -354
- package/dist/sss-key-manager.esm.js.map +4 -4
- package/dist/sss-strategy.d.ts +74 -4
- package/dist/sss-strategy.d.ts.map +1 -1
- package/dist/storage.d.ts +1 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/types.d.ts +98 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -3
- package/src/__fixtures__/escrow-vectors-rust.json +82 -0
- package/src/__fixtures__/escrow-vectors.json +103 -0
- package/src/__fixtures__/nitro-attestation/bad-signature.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/debug-zero-pcrs.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/legacy-user-data.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/manifest.json +60 -0
- package/src/__fixtures__/nitro-attestation/nonce-mismatch.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/root.pem +12 -0
- package/src/__fixtures__/nitro-attestation/stale-timestamp.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/tampered-previous-key-ids.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/truncated-chain.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/valid.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/wrong-pcr0.cbor.b64 +1 -0
- package/src/__fixtures__/nitro-attestation/wrong-root.cbor.b64 +1 -0
- package/src/api-client.test.ts +122 -0
- package/src/api-client.ts +107 -116
- package/src/atomic-operations.test.ts +56 -16
- package/src/atomic-operations.ts +55 -19
- package/src/critical-paths.test.ts +51 -1
- package/src/email-relay-crypto.test.ts +87 -0
- package/src/email-relay-crypto.ts +293 -0
- package/src/escrow-attestation.test.ts +90 -0
- package/src/escrow-attestation.ts +125 -0
- package/src/escrow-crypto.test.ts +381 -0
- package/src/escrow-crypto.ts +319 -0
- package/src/escrow-nitro-attestation.test.ts +204 -0
- package/src/escrow-nitro-attestation.ts +286 -0
- package/src/escrow-pin.test.ts +119 -0
- package/src/escrow-pin.ts +83 -0
- package/src/escrow-vectors.test.ts +198 -0
- package/src/index.ts +70 -1
- package/src/key-manager.ts +4 -9
- package/src/qr-login.ts +22 -15
- package/src/recovery-phrase.ts +40 -0
- package/src/sss-session-writes.test.ts +109 -0
- package/src/sss-strategy.test.ts +2736 -111
- package/src/sss-strategy.ts +2226 -224
- package/src/storage.test.ts +66 -8
- package/src/storage.ts +41 -29
- package/src/types.ts +118 -6
|
@@ -6,7 +6,11 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
6
6
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
8
|
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
-
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
10
14
|
};
|
|
11
15
|
var __copyProps = (to, from, except, desc) => {
|
|
12
16
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
@@ -56,6 +60,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
56
60
|
AchievementSubjectValidator: /* @__PURE__ */ __name(() => AchievementSubjectValidator, "AchievementSubjectValidator"),
|
|
57
61
|
AchievementTypeValidator: /* @__PURE__ */ __name(() => AchievementTypeValidator, "AchievementTypeValidator"),
|
|
58
62
|
AchievementValidator: /* @__PURE__ */ __name(() => AchievementValidator, "AchievementValidator"),
|
|
63
|
+
AcknowledgeViewInputValidator: /* @__PURE__ */ __name(() => AcknowledgeViewInputValidator, "AcknowledgeViewInputValidator"),
|
|
64
|
+
AcknowledgeViewOutputValidator: /* @__PURE__ */ __name(() => AcknowledgeViewOutputValidator, "AcknowledgeViewOutputValidator"),
|
|
59
65
|
AddTagInputValidator: /* @__PURE__ */ __name(() => AddTagInputValidator, "AddTagInputValidator"),
|
|
60
66
|
AddressValidator: /* @__PURE__ */ __name(() => AddressValidator, "AddressValidator"),
|
|
61
67
|
AgeRatingValidator: /* @__PURE__ */ __name(() => AgeRatingValidator, "AgeRatingValidator"),
|
|
@@ -71,6 +77,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
71
77
|
AppEventResponseValidator: /* @__PURE__ */ __name(() => AppEventResponseValidator, "AppEventResponseValidator"),
|
|
72
78
|
AppEventValidator: /* @__PURE__ */ __name(() => AppEventValidator, "AppEventValidator"),
|
|
73
79
|
AppListingStatusValidator: /* @__PURE__ */ __name(() => AppListingStatusValidator, "AppListingStatusValidator"),
|
|
80
|
+
AppManifestDiffValidator: /* @__PURE__ */ __name(() => AppManifestDiffValidator, "AppManifestDiffValidator"),
|
|
81
|
+
AppManifestTemplateChangeValidator: /* @__PURE__ */ __name(() => AppManifestTemplateChangeValidator, "AppManifestTemplateChangeValidator"),
|
|
82
|
+
AppManifestTemplateRefValidator: /* @__PURE__ */ __name(() => AppManifestTemplateRefValidator, "AppManifestTemplateRefValidator"),
|
|
83
|
+
AppManifestValidator: /* @__PURE__ */ __name(() => AppManifestValidator, "AppManifestValidator"),
|
|
84
|
+
AppManifestVersionStatusValidator: /* @__PURE__ */ __name(() => AppManifestVersionStatusValidator, "AppManifestVersionStatusValidator"),
|
|
85
|
+
AppManifestVersionValidator: /* @__PURE__ */ __name(() => AppManifestVersionValidator, "AppManifestVersionValidator"),
|
|
74
86
|
AppStoreListingCreateValidator: /* @__PURE__ */ __name(() => AppStoreListingCreateValidator, "AppStoreListingCreateValidator"),
|
|
75
87
|
AppStoreListingSubmitterValidator: /* @__PURE__ */ __name(() => AppStoreListingSubmitterValidator, "AppStoreListingSubmitterValidator"),
|
|
76
88
|
AppStoreListingUpdateValidator: /* @__PURE__ */ __name(() => AppStoreListingUpdateValidator, "AppStoreListingUpdateValidator"),
|
|
@@ -92,6 +104,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
92
104
|
BoostRecipientValidator: /* @__PURE__ */ __name(() => BoostRecipientValidator, "BoostRecipientValidator"),
|
|
93
105
|
BoostRecipientWithChildrenValidator: /* @__PURE__ */ __name(() => BoostRecipientWithChildrenValidator, "BoostRecipientWithChildrenValidator"),
|
|
94
106
|
BoostValidator: /* @__PURE__ */ __name(() => BoostValidator, "BoostValidator"),
|
|
107
|
+
CapturedConsentRecordValidator: /* @__PURE__ */ __name(() => CapturedConsentRecordValidator, "CapturedConsentRecordValidator"),
|
|
108
|
+
CapturedTemplateRecordValidator: /* @__PURE__ */ __name(() => CapturedTemplateRecordValidator, "CapturedTemplateRecordValidator"),
|
|
95
109
|
CheckCredentialEventValidator: /* @__PURE__ */ __name(() => CheckCredentialEventValidator, "CheckCredentialEventValidator"),
|
|
96
110
|
CheckIssuanceStatusEventValidator: /* @__PURE__ */ __name(() => CheckIssuanceStatusEventValidator, "CheckIssuanceStatusEventValidator"),
|
|
97
111
|
ClaimHookQueryValidator: /* @__PURE__ */ __name(() => ClaimHookQueryValidator, "ClaimHookQueryValidator"),
|
|
@@ -113,6 +127,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
113
127
|
ConsentFlowDataForDidQueryValidator: /* @__PURE__ */ __name(() => ConsentFlowDataForDidQueryValidator, "ConsentFlowDataForDidQueryValidator"),
|
|
114
128
|
ConsentFlowDataQueryValidator: /* @__PURE__ */ __name(() => ConsentFlowDataQueryValidator, "ConsentFlowDataQueryValidator"),
|
|
115
129
|
ConsentFlowGuardianApprovalValidator: /* @__PURE__ */ __name(() => ConsentFlowGuardianApprovalValidator, "ConsentFlowGuardianApprovalValidator"),
|
|
130
|
+
ConsentFlowReferralValidator: /* @__PURE__ */ __name(() => ConsentFlowReferralValidator, "ConsentFlowReferralValidator"),
|
|
116
131
|
ConsentFlowTermValidator: /* @__PURE__ */ __name(() => ConsentFlowTermValidator, "ConsentFlowTermValidator"),
|
|
117
132
|
ConsentFlowTermsQueryValidator: /* @__PURE__ */ __name(() => ConsentFlowTermsQueryValidator, "ConsentFlowTermsQueryValidator"),
|
|
118
133
|
ConsentFlowTermsStatusValidator: /* @__PURE__ */ __name(() => ConsentFlowTermsStatusValidator, "ConsentFlowTermsStatusValidator"),
|
|
@@ -120,6 +135,10 @@ var require_types_cjs_development = __commonJS({
|
|
|
120
135
|
ConsentFlowTransactionActionValidator: /* @__PURE__ */ __name(() => ConsentFlowTransactionActionValidator, "ConsentFlowTransactionActionValidator"),
|
|
121
136
|
ConsentFlowTransactionValidator: /* @__PURE__ */ __name(() => ConsentFlowTransactionValidator, "ConsentFlowTransactionValidator"),
|
|
122
137
|
ConsentFlowTransactionsQueryValidator: /* @__PURE__ */ __name(() => ConsentFlowTransactionsQueryValidator, "ConsentFlowTransactionsQueryValidator"),
|
|
138
|
+
ConsentFlowWebhookMetadataValidator: /* @__PURE__ */ __name(() => ConsentFlowWebhookMetadataValidator, "ConsentFlowWebhookMetadataValidator"),
|
|
139
|
+
ConsentRequestPersonalFieldValidator: /* @__PURE__ */ __name(() => ConsentRequestPersonalFieldValidator, "ConsentRequestPersonalFieldValidator"),
|
|
140
|
+
ConsentRequestValidator: /* @__PURE__ */ __name(() => ConsentRequestValidator, "ConsentRequestValidator"),
|
|
141
|
+
ConsentRequestWalletCategoryValidator: /* @__PURE__ */ __name(() => ConsentRequestWalletCategoryValidator, "ConsentRequestWalletCategoryValidator"),
|
|
123
142
|
ContactMethodCreateValidator: /* @__PURE__ */ __name(() => ContactMethodCreateValidator, "ContactMethodCreateValidator"),
|
|
124
143
|
ContactMethodQueryValidator: /* @__PURE__ */ __name(() => ContactMethodQueryValidator, "ContactMethodQueryValidator"),
|
|
125
144
|
ContactMethodValidator: /* @__PURE__ */ __name(() => ContactMethodValidator, "ContactMethodValidator"),
|
|
@@ -127,12 +146,14 @@ var require_types_cjs_development = __commonJS({
|
|
|
127
146
|
ContactMethodVerificationValidator: /* @__PURE__ */ __name(() => ContactMethodVerificationValidator, "ContactMethodVerificationValidator"),
|
|
128
147
|
ContextValidator: /* @__PURE__ */ __name(() => ContextValidator, "ContextValidator"),
|
|
129
148
|
ContractCredentialValidator: /* @__PURE__ */ __name(() => ContractCredentialValidator, "ContractCredentialValidator"),
|
|
149
|
+
ContractRequestFieldsValidator: /* @__PURE__ */ __name(() => ContractRequestFieldsValidator, "ContractRequestFieldsValidator"),
|
|
130
150
|
CountSkillsInputValidator: /* @__PURE__ */ __name(() => CountSkillsInputValidator, "CountSkillsInputValidator"),
|
|
131
151
|
CountSkillsResultValidator: /* @__PURE__ */ __name(() => CountSkillsResultValidator, "CountSkillsResultValidator"),
|
|
132
152
|
CreateContactMethodSessionResponseValidator: /* @__PURE__ */ __name(() => CreateContactMethodSessionResponseValidator, "CreateContactMethodSessionResponseValidator"),
|
|
133
153
|
CreateContactMethodSessionValidator: /* @__PURE__ */ __name(() => CreateContactMethodSessionValidator, "CreateContactMethodSessionValidator"),
|
|
134
154
|
CreateManagedFrameworkBatchInputValidator: /* @__PURE__ */ __name(() => CreateManagedFrameworkBatchInputValidator, "CreateManagedFrameworkBatchInputValidator"),
|
|
135
155
|
CreateManagedFrameworkInputValidator: /* @__PURE__ */ __name(() => CreateManagedFrameworkInputValidator, "CreateManagedFrameworkInputValidator"),
|
|
156
|
+
CreateShareLinkInputValidator: /* @__PURE__ */ __name(() => CreateShareLinkInputValidator, "CreateShareLinkInputValidator"),
|
|
136
157
|
CreateSkillInputValidator: /* @__PURE__ */ __name(() => CreateSkillInputValidator, "CreateSkillInputValidator"),
|
|
137
158
|
CreateSkillsBatchInputValidator: /* @__PURE__ */ __name(() => CreateSkillsBatchInputValidator, "CreateSkillsBatchInputValidator"),
|
|
138
159
|
CredentialActivityEventTypeValidator: /* @__PURE__ */ __name(() => CredentialActivityEventTypeValidator, "CredentialActivityEventTypeValidator"),
|
|
@@ -161,13 +182,19 @@ var require_types_cjs_development = __commonJS({
|
|
|
161
182
|
CriteriaValidator: /* @__PURE__ */ __name(() => CriteriaValidator, "CriteriaValidator"),
|
|
162
183
|
DEFAULT_BITSTRING_STATUS_LIST_SIZE: /* @__PURE__ */ __name(() => DEFAULT_BITSTRING_STATUS_LIST_SIZE, "DEFAULT_BITSTRING_STATUS_LIST_SIZE"),
|
|
163
184
|
DeleteFrameworkInputValidator: /* @__PURE__ */ __name(() => DeleteFrameworkInputValidator, "DeleteFrameworkInputValidator"),
|
|
185
|
+
DeleteShareLinkAttachmentChunksInputValidator: /* @__PURE__ */ __name(() => DeleteShareLinkAttachmentChunksInputValidator, "DeleteShareLinkAttachmentChunksInputValidator"),
|
|
186
|
+
DeleteShareLinkAttachmentChunksOutputValidator: /* @__PURE__ */ __name(() => DeleteShareLinkAttachmentChunksOutputValidator, "DeleteShareLinkAttachmentChunksOutputValidator"),
|
|
164
187
|
DeleteSkillInputValidator: /* @__PURE__ */ __name(() => DeleteSkillInputValidator, "DeleteSkillInputValidator"),
|
|
165
188
|
DidDocumentValidator: /* @__PURE__ */ __name(() => DidDocumentValidator, "DidDocumentValidator"),
|
|
166
189
|
EMPTY_IN_APP_MESSAGES_FLAG: /* @__PURE__ */ __name(() => EMPTY_IN_APP_MESSAGES_FLAG, "EMPTY_IN_APP_MESSAGES_FLAG"),
|
|
190
|
+
ESCROW_PIN_LOCKED_MESSAGE: /* @__PURE__ */ __name(() => ESCROW_PIN_LOCKED_MESSAGE2, "ESCROW_PIN_LOCKED_MESSAGE"),
|
|
191
|
+
ESCROW_PIN_MISMATCH_PATTERN: /* @__PURE__ */ __name(() => ESCROW_PIN_MISMATCH_PATTERN2, "ESCROW_PIN_MISMATCH_PATTERN"),
|
|
192
|
+
ESCROW_PIN_UNAVAILABLE_MESSAGE: /* @__PURE__ */ __name(() => ESCROW_PIN_UNAVAILABLE_MESSAGE2, "ESCROW_PIN_UNAVAILABLE_MESSAGE"),
|
|
167
193
|
EncryptedCredentialRecordValidator: /* @__PURE__ */ __name(() => EncryptedCredentialRecordValidator, "EncryptedCredentialRecordValidator"),
|
|
168
194
|
EncryptedRecordValidator: /* @__PURE__ */ __name(() => EncryptedRecordValidator, "EncryptedRecordValidator"),
|
|
169
195
|
EndorsementCredentialValidator: /* @__PURE__ */ __name(() => EndorsementCredentialValidator, "EndorsementCredentialValidator"),
|
|
170
196
|
EndorsementSubjectValidator: /* @__PURE__ */ __name(() => EndorsementSubjectValidator, "EndorsementSubjectValidator"),
|
|
197
|
+
EscrowPinStatusValidator: /* @__PURE__ */ __name(() => EscrowPinStatusValidator, "EscrowPinStatusValidator"),
|
|
171
198
|
EvidenceValidator: /* @__PURE__ */ __name(() => EvidenceValidator, "EvidenceValidator"),
|
|
172
199
|
FlatAuthGrantValidator: /* @__PURE__ */ __name(() => FlatAuthGrantValidator, "FlatAuthGrantValidator"),
|
|
173
200
|
FrameworkWithSkillsValidator: /* @__PURE__ */ __name(() => FrameworkWithSkillsValidator, "FrameworkWithSkillsValidator"),
|
|
@@ -179,6 +206,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
179
206
|
GetCredentialRefreshHistoryResultValidator: /* @__PURE__ */ __name(() => GetCredentialRefreshHistoryResultValidator, "GetCredentialRefreshHistoryResultValidator"),
|
|
180
207
|
GetFullSkillTreeInputValidator: /* @__PURE__ */ __name(() => GetFullSkillTreeInputValidator, "GetFullSkillTreeInputValidator"),
|
|
181
208
|
GetFullSkillTreeResultValidator: /* @__PURE__ */ __name(() => GetFullSkillTreeResultValidator, "GetFullSkillTreeResultValidator"),
|
|
209
|
+
GetShareLinkAttachmentChunkInputValidator: /* @__PURE__ */ __name(() => GetShareLinkAttachmentChunkInputValidator, "GetShareLinkAttachmentChunkInputValidator"),
|
|
182
210
|
GetSkillPathInputValidator: /* @__PURE__ */ __name(() => GetSkillPathInputValidator, "GetSkillPathInputValidator"),
|
|
183
211
|
GetSkillPathResultValidator: /* @__PURE__ */ __name(() => GetSkillPathResultValidator, "GetSkillPathResultValidator"),
|
|
184
212
|
GetTemplateRecipientsEventValidator: /* @__PURE__ */ __name(() => GetTemplateRecipientsEventValidator, "GetTemplateRecipientsEventValidator"),
|
|
@@ -196,6 +224,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
196
224
|
InboxCredentialRefreshReceiptValidator: /* @__PURE__ */ __name(() => InboxCredentialRefreshReceiptValidator, "InboxCredentialRefreshReceiptValidator"),
|
|
197
225
|
InboxCredentialValidator: /* @__PURE__ */ __name(() => InboxCredentialValidator, "InboxCredentialValidator"),
|
|
198
226
|
IncrementCounterEventValidator: /* @__PURE__ */ __name(() => IncrementCounterEventValidator, "IncrementCounterEventValidator"),
|
|
227
|
+
InlineAlignmentValidator: /* @__PURE__ */ __name(() => InlineAlignmentValidator, "InlineAlignmentValidator"),
|
|
228
|
+
InlineCredentialTemplateValidator: /* @__PURE__ */ __name(() => InlineCredentialTemplateValidator, "InlineCredentialTemplateValidator"),
|
|
229
|
+
InlineEvidenceValidator: /* @__PURE__ */ __name(() => InlineEvidenceValidator, "InlineEvidenceValidator"),
|
|
230
|
+
InlineSendCredentialEventValidator: /* @__PURE__ */ __name(() => InlineSendCredentialEventValidator, "InlineSendCredentialEventValidator"),
|
|
231
|
+
InlineWalletCategoryValidator: /* @__PURE__ */ __name(() => InlineWalletCategoryValidator, "InlineWalletCategoryValidator"),
|
|
232
|
+
InlineWalletSkillTagValidator: /* @__PURE__ */ __name(() => InlineWalletSkillTagValidator, "InlineWalletSkillTagValidator"),
|
|
199
233
|
InstalledAppValidator: /* @__PURE__ */ __name(() => InstalledAppValidator, "InstalledAppValidator"),
|
|
200
234
|
IssueInboxCredentialBatchItemResultValidator: /* @__PURE__ */ __name(() => IssueInboxCredentialBatchItemResultValidator, "IssueInboxCredentialBatchItemResultValidator"),
|
|
201
235
|
IssueInboxCredentialBatchItemValidator: /* @__PURE__ */ __name(() => IssueInboxCredentialBatchItemValidator, "IssueInboxCredentialBatchItemValidator"),
|
|
@@ -248,9 +282,19 @@ var require_types_cjs_development = __commonJS({
|
|
|
248
282
|
LCNVisibleProfileValidator: /* @__PURE__ */ __name(() => LCNVisibleProfileValidator, "LCNVisibleProfileValidator"),
|
|
249
283
|
LaunchTypeValidator: /* @__PURE__ */ __name(() => LaunchTypeValidator, "LaunchTypeValidator"),
|
|
250
284
|
LearnCardRefreshAuthorizationValidator: /* @__PURE__ */ __name(() => LearnCardRefreshAuthorizationValidator, "LearnCardRefreshAuthorizationValidator"),
|
|
285
|
+
LegacySendCredentialEventValidator: /* @__PURE__ */ __name(() => LegacySendCredentialEventValidator, "LegacySendCredentialEventValidator"),
|
|
251
286
|
LinkProviderFrameworkInputValidator: /* @__PURE__ */ __name(() => LinkProviderFrameworkInputValidator, "LinkProviderFrameworkInputValidator"),
|
|
287
|
+
ListShareLinksInputValidator: /* @__PURE__ */ __name(() => ListShareLinksInputValidator, "ListShareLinksInputValidator"),
|
|
288
|
+
MAX_ENDORSEMENTS: /* @__PURE__ */ __name(() => MAX_ENDORSEMENTS, "MAX_ENDORSEMENTS"),
|
|
289
|
+
MAX_SELECTED_CREDENTIALS: /* @__PURE__ */ __name(() => MAX_SELECTED_CREDENTIALS, "MAX_SELECTED_CREDENTIALS"),
|
|
290
|
+
MAX_SHARE_CIPHERTEXT_BYTES: /* @__PURE__ */ __name(() => MAX_SHARE_CIPHERTEXT_BYTES, "MAX_SHARE_CIPHERTEXT_BYTES"),
|
|
291
|
+
MAX_SHARE_LINK_REQUEST_BYTES: /* @__PURE__ */ __name(() => MAX_SHARE_LINK_REQUEST_BYTES, "MAX_SHARE_LINK_REQUEST_BYTES"),
|
|
292
|
+
MAX_SHARE_RECOVERY_JWE_BYTES: /* @__PURE__ */ __name(() => MAX_SHARE_RECOVERY_JWE_BYTES, "MAX_SHARE_RECOVERY_JWE_BYTES"),
|
|
293
|
+
MAX_SHARE_SOURCE_URI_CHARS: /* @__PURE__ */ __name(() => MAX_SHARE_SOURCE_URI_CHARS, "MAX_SHARE_SOURCE_URI_CHARS"),
|
|
294
|
+
MAX_VP_MEMBERS: /* @__PURE__ */ __name(() => MAX_VP_MEMBERS, "MAX_VP_MEMBERS"),
|
|
252
295
|
ManagedCredentialRefreshReceiptValidator: /* @__PURE__ */ __name(() => ManagedCredentialRefreshReceiptValidator, "ManagedCredentialRefreshReceiptValidator"),
|
|
253
296
|
ManagedCredentialRefreshServiceValidator: /* @__PURE__ */ __name(() => ManagedCredentialRefreshServiceValidator, "ManagedCredentialRefreshServiceValidator"),
|
|
297
|
+
NormalizedConsentScopesValidator: /* @__PURE__ */ __name(() => NormalizedConsentScopesValidator, "NormalizedConsentScopesValidator"),
|
|
254
298
|
PaginatedAppStoreListingsValidator: /* @__PURE__ */ __name(() => PaginatedAppStoreListingsValidator, "PaginatedAppStoreListingsValidator"),
|
|
255
299
|
PaginatedBoostRecipientsValidator: /* @__PURE__ */ __name(() => PaginatedBoostRecipientsValidator, "PaginatedBoostRecipientsValidator"),
|
|
256
300
|
PaginatedBoostRecipientsWithChildrenValidator: /* @__PURE__ */ __name(() => PaginatedBoostRecipientsWithChildrenValidator, "PaginatedBoostRecipientsWithChildrenValidator"),
|
|
@@ -271,11 +315,14 @@ var require_types_cjs_development = __commonJS({
|
|
|
271
315
|
PaginatedLCNProfileManagersValidator: /* @__PURE__ */ __name(() => PaginatedLCNProfileManagersValidator, "PaginatedLCNProfileManagersValidator"),
|
|
272
316
|
PaginatedLCNProfilesAndManagersValidator: /* @__PURE__ */ __name(() => PaginatedLCNProfilesAndManagersValidator, "PaginatedLCNProfilesAndManagersValidator"),
|
|
273
317
|
PaginatedLCNProfilesValidator: /* @__PURE__ */ __name(() => PaginatedLCNProfilesValidator, "PaginatedLCNProfilesValidator"),
|
|
318
|
+
PaginatedShareLinksValidator: /* @__PURE__ */ __name(() => PaginatedShareLinksValidator, "PaginatedShareLinksValidator"),
|
|
274
319
|
PaginatedSkillFrameworksValidator: /* @__PURE__ */ __name(() => PaginatedSkillFrameworksValidator, "PaginatedSkillFrameworksValidator"),
|
|
275
320
|
PaginatedSkillTreeValidator: /* @__PURE__ */ __name(() => PaginatedSkillTreeValidator, "PaginatedSkillTreeValidator"),
|
|
276
321
|
PaginatedVisibleLCNProfilesValidator: /* @__PURE__ */ __name(() => PaginatedVisibleLCNProfilesValidator, "PaginatedVisibleLCNProfilesValidator"),
|
|
277
322
|
PaginationOptionsValidator: /* @__PURE__ */ __name(() => PaginationOptionsValidator, "PaginationOptionsValidator"),
|
|
278
323
|
PaginationResponseValidator: /* @__PURE__ */ __name(() => PaginationResponseValidator, "PaginationResponseValidator"),
|
|
324
|
+
PendingListingUpdateStatusValidator: /* @__PURE__ */ __name(() => PendingListingUpdateStatusValidator, "PendingListingUpdateStatusValidator"),
|
|
325
|
+
PendingListingUpdateValidator: /* @__PURE__ */ __name(() => PendingListingUpdateValidator, "PendingListingUpdateValidator"),
|
|
279
326
|
PrepareRefreshableSendInputValidator: /* @__PURE__ */ __name(() => PrepareRefreshableSendInputValidator, "PrepareRefreshableSendInputValidator"),
|
|
280
327
|
PrepareRefreshableSendResultValidator: /* @__PURE__ */ __name(() => PrepareRefreshableSendResultValidator, "PrepareRefreshableSendResultValidator"),
|
|
281
328
|
ProfileValidator: /* @__PURE__ */ __name(() => ProfileValidator, "ProfileValidator"),
|
|
@@ -288,6 +335,9 @@ var require_types_cjs_development = __commonJS({
|
|
|
288
335
|
PublishCredentialRefreshResultValidator: /* @__PURE__ */ __name(() => PublishCredentialRefreshResultValidator, "PublishCredentialRefreshResultValidator"),
|
|
289
336
|
PublishIssuerSignedRefreshValidator: /* @__PURE__ */ __name(() => PublishIssuerSignedRefreshValidator, "PublishIssuerSignedRefreshValidator"),
|
|
290
337
|
PublishSigningAuthorityRefreshValidator: /* @__PURE__ */ __name(() => PublishSigningAuthorityRefreshValidator, "PublishSigningAuthorityRefreshValidator"),
|
|
338
|
+
PutShareLinkAttachmentChunkInputValidator: /* @__PURE__ */ __name(() => PutShareLinkAttachmentChunkInputValidator, "PutShareLinkAttachmentChunkInputValidator"),
|
|
339
|
+
PutShareLinkAttachmentChunkOutputValidator: /* @__PURE__ */ __name(() => PutShareLinkAttachmentChunkOutputValidator, "PutShareLinkAttachmentChunkOutputValidator"),
|
|
340
|
+
RawInlineCredentialTemplateValidator: /* @__PURE__ */ __name(() => RawInlineCredentialTemplateValidator, "RawInlineCredentialTemplateValidator"),
|
|
291
341
|
RefreshServiceValidator: /* @__PURE__ */ __name(() => RefreshServiceValidator, "RefreshServiceValidator"),
|
|
292
342
|
RegExpValidator: /* @__PURE__ */ __name(() => RegExpValidator, "RegExpValidator"),
|
|
293
343
|
RelatedValidator: /* @__PURE__ */ __name(() => RelatedValidator, "RelatedValidator"),
|
|
@@ -295,16 +345,26 @@ var require_types_cjs_development = __commonJS({
|
|
|
295
345
|
ReplaceSkillFrameworkSkillsInputValidator: /* @__PURE__ */ __name(() => ReplaceSkillFrameworkSkillsInputValidator, "ReplaceSkillFrameworkSkillsInputValidator"),
|
|
296
346
|
ReplaceSkillFrameworkSkillsResultValidator: /* @__PURE__ */ __name(() => ReplaceSkillFrameworkSkillsResultValidator, "ReplaceSkillFrameworkSkillsResultValidator"),
|
|
297
347
|
RequestLearnerContextEventValidator: /* @__PURE__ */ __name(() => RequestLearnerContextEventValidator, "RequestLearnerContextEventValidator"),
|
|
348
|
+
ResolveShareLinkInputValidator: /* @__PURE__ */ __name(() => ResolveShareLinkInputValidator, "ResolveShareLinkInputValidator"),
|
|
298
349
|
ResultDescriptionValidator: /* @__PURE__ */ __name(() => ResultDescriptionValidator, "ResultDescriptionValidator"),
|
|
299
350
|
ResultStatusTypeValidator: /* @__PURE__ */ __name(() => ResultStatusTypeValidator, "ResultStatusTypeValidator"),
|
|
300
351
|
ResultTypeValidator: /* @__PURE__ */ __name(() => ResultTypeValidator, "ResultTypeValidator"),
|
|
301
352
|
ResultValidator: /* @__PURE__ */ __name(() => ResultValidator, "ResultValidator"),
|
|
302
353
|
RubricCriterionValidator: /* @__PURE__ */ __name(() => RubricCriterionValidator, "RubricCriterionValidator"),
|
|
354
|
+
SHARE_AAD_PREFIX: /* @__PURE__ */ __name(() => SHARE_AAD_PREFIX, "SHARE_AAD_PREFIX"),
|
|
355
|
+
SHARE_CONTENT_KEY_BYTES: /* @__PURE__ */ __name(() => SHARE_CONTENT_KEY_BYTES, "SHARE_CONTENT_KEY_BYTES"),
|
|
356
|
+
SHARE_IV_BYTES: /* @__PURE__ */ __name(() => SHARE_IV_BYTES, "SHARE_IV_BYTES"),
|
|
357
|
+
SHARE_LINK_ID_BYTES: /* @__PURE__ */ __name(() => SHARE_LINK_ID_BYTES, "SHARE_LINK_ID_BYTES"),
|
|
358
|
+
SHARE_LINK_PROTOCOL: /* @__PURE__ */ __name(() => SHARE_LINK_PROTOCOL, "SHARE_LINK_PROTOCOL"),
|
|
359
|
+
SHARE_RECOVERY_PROTOCOL: /* @__PURE__ */ __name(() => SHARE_RECOVERY_PROTOCOL, "SHARE_RECOVERY_PROTOCOL"),
|
|
360
|
+
SHARE_TAG_BYTES: /* @__PURE__ */ __name(() => SHARE_TAG_BYTES, "SHARE_TAG_BYTES"),
|
|
361
|
+
SHARE_VIEW_RECEIPT_TTL_SECONDS: /* @__PURE__ */ __name(() => SHARE_VIEW_RECEIPT_TTL_SECONDS, "SHARE_VIEW_RECEIPT_TTL_SECONDS"),
|
|
303
362
|
SendAiSessionCredentialEventValidator: /* @__PURE__ */ __name(() => SendAiSessionCredentialEventValidator, "SendAiSessionCredentialEventValidator"),
|
|
304
363
|
SendBoostInputValidator: /* @__PURE__ */ __name(() => SendBoostInputValidator, "SendBoostInputValidator"),
|
|
305
364
|
SendBoostResponseValidator: /* @__PURE__ */ __name(() => SendBoostResponseValidator, "SendBoostResponseValidator"),
|
|
306
365
|
SendBoostTemplateValidator: /* @__PURE__ */ __name(() => SendBoostTemplateValidator, "SendBoostTemplateValidator"),
|
|
307
366
|
SendBrandingOptionsValidator: /* @__PURE__ */ __name(() => SendBrandingOptionsValidator, "SendBrandingOptionsValidator"),
|
|
367
|
+
SendContractRequestValidator: /* @__PURE__ */ __name(() => SendContractRequestValidator, "SendContractRequestValidator"),
|
|
308
368
|
SendCredentialEventValidator: /* @__PURE__ */ __name(() => SendCredentialEventValidator, "SendCredentialEventValidator"),
|
|
309
369
|
SendInboxResponseValidator: /* @__PURE__ */ __name(() => SendInboxResponseValidator, "SendInboxResponseValidator"),
|
|
310
370
|
SendInputValidator: /* @__PURE__ */ __name(() => SendInputValidator, "SendInputValidator"),
|
|
@@ -314,6 +374,36 @@ var require_types_cjs_development = __commonJS({
|
|
|
314
374
|
SentCredentialInfoValidator: /* @__PURE__ */ __name(() => SentCredentialInfoValidator, "SentCredentialInfoValidator"),
|
|
315
375
|
ServiceValidator: /* @__PURE__ */ __name(() => ServiceValidator, "ServiceValidator"),
|
|
316
376
|
SetPrimaryContactMethodValidator: /* @__PURE__ */ __name(() => SetPrimaryContactMethodValidator, "SetPrimaryContactMethodValidator"),
|
|
377
|
+
ShareCiphertextValidator: /* @__PURE__ */ __name(() => ShareCiphertextValidator, "ShareCiphertextValidator"),
|
|
378
|
+
ShareContentKeyValidator: /* @__PURE__ */ __name(() => ShareContentKeyValidator, "ShareContentKeyValidator"),
|
|
379
|
+
ShareContentStateValidator: /* @__PURE__ */ __name(() => ShareContentStateValidator, "ShareContentStateValidator"),
|
|
380
|
+
ShareEndorsementEntryValidator: /* @__PURE__ */ __name(() => ShareEndorsementEntryValidator, "ShareEndorsementEntryValidator"),
|
|
381
|
+
ShareEnvelopeValidator: /* @__PURE__ */ __name(() => ShareEnvelopeValidator, "ShareEnvelopeValidator"),
|
|
382
|
+
ShareIvValidator: /* @__PURE__ */ __name(() => ShareIvValidator, "ShareIvValidator"),
|
|
383
|
+
ShareLinkAttachmentChunkEnvelopeValidator: /* @__PURE__ */ __name(() => ShareLinkAttachmentChunkEnvelopeValidator, "ShareLinkAttachmentChunkEnvelopeValidator"),
|
|
384
|
+
ShareLinkAttachmentChunkOutputValidator: /* @__PURE__ */ __name(() => ShareLinkAttachmentChunkOutputValidator, "ShareLinkAttachmentChunkOutputValidator"),
|
|
385
|
+
ShareLinkAttachmentValidator: /* @__PURE__ */ __name(() => ShareLinkAttachmentValidator, "ShareLinkAttachmentValidator"),
|
|
386
|
+
ShareLinkIdInputValidator: /* @__PURE__ */ __name(() => ShareLinkIdInputValidator, "ShareLinkIdInputValidator"),
|
|
387
|
+
ShareLinkIdValidator: /* @__PURE__ */ __name(() => ShareLinkIdValidator, "ShareLinkIdValidator"),
|
|
388
|
+
ShareLinkOperationKeyInputValidator: /* @__PURE__ */ __name(() => ShareLinkOperationKeyInputValidator, "ShareLinkOperationKeyInputValidator"),
|
|
389
|
+
ShareLinkOwnerCommitOutputValidator: /* @__PURE__ */ __name(() => ShareLinkOwnerCommitOutputValidator, "ShareLinkOwnerCommitOutputValidator"),
|
|
390
|
+
ShareLinkOwnerContentOutputValidator: /* @__PURE__ */ __name(() => ShareLinkOwnerContentOutputValidator, "ShareLinkOwnerContentOutputValidator"),
|
|
391
|
+
ShareLinkOwnerRecoveryOutputValidator: /* @__PURE__ */ __name(() => ShareLinkOwnerRecoveryOutputValidator, "ShareLinkOwnerRecoveryOutputValidator"),
|
|
392
|
+
ShareLinkOwnerStatusOutputValidator: /* @__PURE__ */ __name(() => ShareLinkOwnerStatusOutputValidator, "ShareLinkOwnerStatusOutputValidator"),
|
|
393
|
+
ShareLinkPublicContentViewValidator: /* @__PURE__ */ __name(() => ShareLinkPublicContentViewValidator, "ShareLinkPublicContentViewValidator"),
|
|
394
|
+
ShareLinkPublicStateValidator: /* @__PURE__ */ __name(() => ShareLinkPublicStateValidator, "ShareLinkPublicStateValidator"),
|
|
395
|
+
ShareLinkStatusValidator: /* @__PURE__ */ __name(() => ShareLinkStatusValidator, "ShareLinkStatusValidator"),
|
|
396
|
+
ShareLinkValidator: /* @__PURE__ */ __name(() => ShareLinkValidator, "ShareLinkValidator"),
|
|
397
|
+
ShareManifestPresentationValidator: /* @__PURE__ */ __name(() => ShareManifestPresentationValidator, "ShareManifestPresentationValidator"),
|
|
398
|
+
ShareOwnerRecoveryValidator: /* @__PURE__ */ __name(() => ShareOwnerRecoveryValidator, "ShareOwnerRecoveryValidator"),
|
|
399
|
+
SharePayloadValidator: /* @__PURE__ */ __name(() => SharePayloadValidator, "SharePayloadValidator"),
|
|
400
|
+
SharePayloadValidatorShape: /* @__PURE__ */ __name(() => SharePayloadValidatorShape, "SharePayloadValidatorShape"),
|
|
401
|
+
ShareRecoveryEndorsementValidator: /* @__PURE__ */ __name(() => ShareRecoveryEndorsementValidator, "ShareRecoveryEndorsementValidator"),
|
|
402
|
+
ShareRecoveryPlaintextValidator: /* @__PURE__ */ __name(() => ShareRecoveryPlaintextValidator, "ShareRecoveryPlaintextValidator"),
|
|
403
|
+
ShareRecoverySelectionValidator: /* @__PURE__ */ __name(() => ShareRecoverySelectionValidator, "ShareRecoverySelectionValidator"),
|
|
404
|
+
ShareSelectionEntryValidator: /* @__PURE__ */ __name(() => ShareSelectionEntryValidator, "ShareSelectionEntryValidator"),
|
|
405
|
+
ShareSharerValidator: /* @__PURE__ */ __name(() => ShareSharerValidator, "ShareSharerValidator"),
|
|
406
|
+
SimpleInlineCredentialTemplateValidator: /* @__PURE__ */ __name(() => SimpleInlineCredentialTemplateValidator, "SimpleInlineCredentialTemplateValidator"),
|
|
317
407
|
SkillDeletionStrategyValidator: /* @__PURE__ */ __name(() => SkillDeletionStrategyValidator, "SkillDeletionStrategyValidator"),
|
|
318
408
|
SkillFrameworkAdminInputValidator: /* @__PURE__ */ __name(() => SkillFrameworkAdminInputValidator, "SkillFrameworkAdminInputValidator"),
|
|
319
409
|
SkillFrameworkAdminsValidator: /* @__PURE__ */ __name(() => SkillFrameworkAdminsValidator, "SkillFrameworkAdminsValidator"),
|
|
@@ -344,8 +434,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
344
434
|
UnsignedClrCredentialValidator: /* @__PURE__ */ __name(() => UnsignedClrCredentialValidator, "UnsignedClrCredentialValidator"),
|
|
345
435
|
UnsignedVCValidator: /* @__PURE__ */ __name(() => UnsignedVCValidator, "UnsignedVCValidator"),
|
|
346
436
|
UnsignedVPValidator: /* @__PURE__ */ __name(() => UnsignedVPValidator, "UnsignedVPValidator"),
|
|
437
|
+
UnsupportedSignInOperationError: /* @__PURE__ */ __name(() => UnsupportedSignInOperationError, "UnsupportedSignInOperationError"),
|
|
347
438
|
UpdateFrameworkInputValidator: /* @__PURE__ */ __name(() => UpdateFrameworkInputValidator, "UpdateFrameworkInputValidator"),
|
|
439
|
+
UpdateShareLinkInputValidator: /* @__PURE__ */ __name(() => UpdateShareLinkInputValidator, "UpdateShareLinkInputValidator"),
|
|
348
440
|
UpdateSkillInputValidator: /* @__PURE__ */ __name(() => UpdateSkillInputValidator, "UpdateSkillInputValidator"),
|
|
441
|
+
UpsertConsentContractEventValidator: /* @__PURE__ */ __name(() => UpsertConsentContractEventValidator, "UpsertConsentContractEventValidator"),
|
|
442
|
+
UpsertConsentContractResponseValidator: /* @__PURE__ */ __name(() => UpsertConsentContractResponseValidator, "UpsertConsentContractResponseValidator"),
|
|
349
443
|
VC2EvidenceValidator: /* @__PURE__ */ __name(() => VC2EvidenceValidator, "VC2EvidenceValidator"),
|
|
350
444
|
VCValidator: /* @__PURE__ */ __name(() => VCValidator, "VCValidator"),
|
|
351
445
|
VPValidator: /* @__PURE__ */ __name(() => VPValidator, "VPValidator"),
|
|
@@ -356,7 +450,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
356
450
|
VerificationStatusValidator: /* @__PURE__ */ __name(() => VerificationStatusValidator, "VerificationStatusValidator"),
|
|
357
451
|
appStoreActionValidator: /* @__PURE__ */ __name(() => appStoreActionValidator, "appStoreActionValidator"),
|
|
358
452
|
capgoUpdateActionValidator: /* @__PURE__ */ __name(() => capgoUpdateActionValidator, "capgoUpdateActionValidator"),
|
|
453
|
+
classifyShareManifest: /* @__PURE__ */ __name(() => classifyShareManifest, "classifyShareManifest"),
|
|
454
|
+
decodeBase64Url: /* @__PURE__ */ __name(() => decodeBase64Url, "decodeBase64Url"),
|
|
455
|
+
decodedBase64UrlByteLength: /* @__PURE__ */ __name(() => decodedBase64UrlByteLength, "decodedBase64UrlByteLength"),
|
|
359
456
|
dismissActionValidator: /* @__PURE__ */ __name(() => dismissActionValidator, "dismissActionValidator"),
|
|
457
|
+
encodeBase64Url: /* @__PURE__ */ __name(() => encodeBase64Url, "encodeBase64Url"),
|
|
458
|
+
escrowPinMismatchMessage: /* @__PURE__ */ __name(() => escrowPinMismatchMessage, "escrowPinMismatchMessage"),
|
|
360
459
|
externalLinkActionValidator: /* @__PURE__ */ __name(() => externalLinkActionValidator, "externalLinkActionValidator"),
|
|
361
460
|
inAppMessageActionStyleValidator: /* @__PURE__ */ __name(() => inAppMessageActionStyleValidator, "inAppMessageActionStyleValidator"),
|
|
362
461
|
inAppMessageActionTargetValidator: /* @__PURE__ */ __name(() => inAppMessageActionTargetValidator, "inAppMessageActionTargetValidator"),
|
|
@@ -371,10 +470,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
371
470
|
inAppMessageVersionSourceValidator: /* @__PURE__ */ __name(() => inAppMessageVersionSourceValidator, "inAppMessageVersionSourceValidator"),
|
|
372
471
|
inAppMessagesFlagValidator: /* @__PURE__ */ __name(() => inAppMessagesFlagValidator, "inAppMessagesFlagValidator"),
|
|
373
472
|
internalLinkActionValidator: /* @__PURE__ */ __name(() => internalLinkActionValidator, "internalLinkActionValidator"),
|
|
473
|
+
isCanonicalBase64Url: /* @__PURE__ */ __name(() => isCanonicalBase64Url, "isCanonicalBase64Url"),
|
|
374
474
|
isStoredCredentialEnvelope: /* @__PURE__ */ __name(() => isStoredCredentialEnvelope, "isStoredCredentialEnvelope"),
|
|
375
475
|
parseInAppMessagesFlag: /* @__PURE__ */ __name(() => parseInAppMessagesFlag, "parseInAppMessagesFlag"),
|
|
376
476
|
platformPredicateValidator: /* @__PURE__ */ __name(() => platformPredicateValidator, "platformPredicateValidator"),
|
|
377
477
|
rolePredicateValidator: /* @__PURE__ */ __name(() => rolePredicateValidator, "rolePredicateValidator"),
|
|
478
|
+
utf8ByteLength: /* @__PURE__ */ __name(() => utf8ByteLength, "utf8ByteLength"),
|
|
378
479
|
versionPredicateValidator: /* @__PURE__ */ __name(() => versionPredicateValidator, "versionPredicateValidator")
|
|
379
480
|
});
|
|
380
481
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -484,14 +585,14 @@ var require_types_cjs_development = __commonJS({
|
|
|
484
585
|
cuid2: /* @__PURE__ */ __name(() => cuid22, "cuid2"),
|
|
485
586
|
custom: /* @__PURE__ */ __name(() => custom, "custom"),
|
|
486
587
|
date: /* @__PURE__ */ __name(() => date3, "date"),
|
|
487
|
-
decode: /* @__PURE__ */ __name(() =>
|
|
588
|
+
decode: /* @__PURE__ */ __name(() => decode22, "decode"),
|
|
488
589
|
decodeAsync: /* @__PURE__ */ __name(() => decodeAsync2, "decodeAsync"),
|
|
489
590
|
describe: /* @__PURE__ */ __name(() => describe2, "describe"),
|
|
490
591
|
discriminatedUnion: /* @__PURE__ */ __name(() => discriminatedUnion, "discriminatedUnion"),
|
|
491
592
|
e164: /* @__PURE__ */ __name(() => e1642, "e164"),
|
|
492
593
|
email: /* @__PURE__ */ __name(() => email2, "email"),
|
|
493
594
|
emoji: /* @__PURE__ */ __name(() => emoji2, "emoji"),
|
|
494
|
-
encode: /* @__PURE__ */ __name(() =>
|
|
595
|
+
encode: /* @__PURE__ */ __name(() => encode22, "encode"),
|
|
495
596
|
encodeAsync: /* @__PURE__ */ __name(() => encodeAsync2, "encodeAsync"),
|
|
496
597
|
endsWith: /* @__PURE__ */ __name(() => _endsWith, "endsWith"),
|
|
497
598
|
enum: /* @__PURE__ */ __name(() => _enum2, "enum"),
|
|
@@ -509,7 +610,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
509
610
|
gte: /* @__PURE__ */ __name(() => _gte, "gte"),
|
|
510
611
|
guid: /* @__PURE__ */ __name(() => guid2, "guid"),
|
|
511
612
|
hash: /* @__PURE__ */ __name(() => hash, "hash"),
|
|
512
|
-
hex: /* @__PURE__ */ __name(() =>
|
|
613
|
+
hex: /* @__PURE__ */ __name(() => hex22, "hex"),
|
|
513
614
|
hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
|
|
514
615
|
httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
|
|
515
616
|
includes: /* @__PURE__ */ __name(() => _includes, "includes"),
|
|
@@ -536,7 +637,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
536
637
|
lt: /* @__PURE__ */ __name(() => _lt, "lt"),
|
|
537
638
|
lte: /* @__PURE__ */ __name(() => _lte, "lte"),
|
|
538
639
|
mac: /* @__PURE__ */ __name(() => mac2, "mac"),
|
|
539
|
-
map: /* @__PURE__ */ __name(() =>
|
|
640
|
+
map: /* @__PURE__ */ __name(() => map2, "map"),
|
|
540
641
|
maxLength: /* @__PURE__ */ __name(() => _maxLength, "maxLength"),
|
|
541
642
|
maxSize: /* @__PURE__ */ __name(() => _maxSize, "maxSize"),
|
|
542
643
|
meta: /* @__PURE__ */ __name(() => meta2, "meta"),
|
|
@@ -861,10 +962,10 @@ var require_types_cjs_development = __commonJS({
|
|
|
861
962
|
config: /* @__PURE__ */ __name(() => config, "config"),
|
|
862
963
|
createStandardJSONSchemaMethod: /* @__PURE__ */ __name(() => createStandardJSONSchemaMethod, "createStandardJSONSchemaMethod"),
|
|
863
964
|
createToJSONSchemaMethod: /* @__PURE__ */ __name(() => createToJSONSchemaMethod, "createToJSONSchemaMethod"),
|
|
864
|
-
decode: /* @__PURE__ */ __name(() =>
|
|
965
|
+
decode: /* @__PURE__ */ __name(() => decode2, "decode"),
|
|
865
966
|
decodeAsync: /* @__PURE__ */ __name(() => decodeAsync, "decodeAsync"),
|
|
866
967
|
describe: /* @__PURE__ */ __name(() => describe, "describe"),
|
|
867
|
-
encode: /* @__PURE__ */ __name(() =>
|
|
968
|
+
encode: /* @__PURE__ */ __name(() => encode2, "encode"),
|
|
868
969
|
encodeAsync: /* @__PURE__ */ __name(() => encodeAsync, "encodeAsync"),
|
|
869
970
|
extractDefs: /* @__PURE__ */ __name(() => extractDefs, "extractDefs"),
|
|
870
971
|
finalize: /* @__PURE__ */ __name(() => finalize, "finalize"),
|
|
@@ -1750,18 +1851,18 @@ var require_types_cjs_development = __commonJS({
|
|
|
1750
1851
|
__name2(cleanEnum, "cleanEnum");
|
|
1751
1852
|
function base64ToUint8Array(base643) {
|
|
1752
1853
|
const binaryString = atob(base643);
|
|
1753
|
-
const
|
|
1854
|
+
const bytes2 = new Uint8Array(binaryString.length);
|
|
1754
1855
|
for (let i = 0; i < binaryString.length; i++) {
|
|
1755
|
-
|
|
1856
|
+
bytes2[i] = binaryString.charCodeAt(i);
|
|
1756
1857
|
}
|
|
1757
|
-
return
|
|
1858
|
+
return bytes2;
|
|
1758
1859
|
}
|
|
1759
1860
|
__name(base64ToUint8Array, "base64ToUint8Array");
|
|
1760
1861
|
__name2(base64ToUint8Array, "base64ToUint8Array");
|
|
1761
|
-
function uint8ArrayToBase64(
|
|
1862
|
+
function uint8ArrayToBase64(bytes2) {
|
|
1762
1863
|
let binaryString = "";
|
|
1763
|
-
for (let i = 0; i <
|
|
1764
|
-
binaryString += String.fromCharCode(
|
|
1864
|
+
for (let i = 0; i < bytes2.length; i++) {
|
|
1865
|
+
binaryString += String.fromCharCode(bytes2[i]);
|
|
1765
1866
|
}
|
|
1766
1867
|
return btoa(binaryString);
|
|
1767
1868
|
}
|
|
@@ -1774,8 +1875,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
1774
1875
|
}
|
|
1775
1876
|
__name(base64urlToUint8Array, "base64urlToUint8Array");
|
|
1776
1877
|
__name2(base64urlToUint8Array, "base64urlToUint8Array");
|
|
1777
|
-
function uint8ArrayToBase64url(
|
|
1778
|
-
return uint8ArrayToBase64(
|
|
1878
|
+
function uint8ArrayToBase64url(bytes2) {
|
|
1879
|
+
return uint8ArrayToBase64(bytes2).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
1779
1880
|
}
|
|
1780
1881
|
__name(uint8ArrayToBase64url, "uint8ArrayToBase64url");
|
|
1781
1882
|
__name2(uint8ArrayToBase64url, "uint8ArrayToBase64url");
|
|
@@ -1784,16 +1885,16 @@ var require_types_cjs_development = __commonJS({
|
|
|
1784
1885
|
if (cleanHex.length % 2 !== 0) {
|
|
1785
1886
|
throw new Error("Invalid hex string length");
|
|
1786
1887
|
}
|
|
1787
|
-
const
|
|
1888
|
+
const bytes2 = new Uint8Array(cleanHex.length / 2);
|
|
1788
1889
|
for (let i = 0; i < cleanHex.length; i += 2) {
|
|
1789
|
-
|
|
1890
|
+
bytes2[i / 2] = Number.parseInt(cleanHex.slice(i, i + 2), 16);
|
|
1790
1891
|
}
|
|
1791
|
-
return
|
|
1892
|
+
return bytes2;
|
|
1792
1893
|
}
|
|
1793
1894
|
__name(hexToUint8Array, "hexToUint8Array");
|
|
1794
1895
|
__name2(hexToUint8Array, "hexToUint8Array");
|
|
1795
|
-
function uint8ArrayToHex(
|
|
1796
|
-
return Array.from(
|
|
1896
|
+
function uint8ArrayToHex(bytes2) {
|
|
1897
|
+
return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1797
1898
|
}
|
|
1798
1899
|
__name(uint8ArrayToHex, "uint8ArrayToHex");
|
|
1799
1900
|
__name2(uint8ArrayToHex, "uint8ArrayToHex");
|
|
@@ -2008,11 +2109,11 @@ var require_types_cjs_development = __commonJS({
|
|
|
2008
2109
|
const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
|
|
2009
2110
|
return _parse(_Err)(schema, value, ctx);
|
|
2010
2111
|
}, "_encode");
|
|
2011
|
-
var
|
|
2112
|
+
var encode2 = /* @__PURE__ */ _encode($ZodRealError);
|
|
2012
2113
|
var _decode = /* @__PURE__ */ __name2((_Err) => (schema, value, _ctx) => {
|
|
2013
2114
|
return _parse(_Err)(schema, value, _ctx);
|
|
2014
2115
|
}, "_decode");
|
|
2015
|
-
var
|
|
2116
|
+
var decode2 = /* @__PURE__ */ _decode($ZodRealError);
|
|
2016
2117
|
var _encodeAsync = /* @__PURE__ */ __name2((_Err) => async (schema, value, _ctx) => {
|
|
2017
2118
|
const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
|
|
2018
2119
|
return _parseAsync(_Err)(schema, value, ctx);
|
|
@@ -2060,7 +2161,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2060
2161
|
emoji: /* @__PURE__ */ __name(() => emoji, "emoji"),
|
|
2061
2162
|
extendedDuration: /* @__PURE__ */ __name(() => extendedDuration, "extendedDuration"),
|
|
2062
2163
|
guid: /* @__PURE__ */ __name(() => guid, "guid"),
|
|
2063
|
-
hex: /* @__PURE__ */ __name(() =>
|
|
2164
|
+
hex: /* @__PURE__ */ __name(() => hex2, "hex"),
|
|
2064
2165
|
hostname: /* @__PURE__ */ __name(() => hostname, "hostname"),
|
|
2065
2166
|
html5Email: /* @__PURE__ */ __name(() => html5Email, "html5Email"),
|
|
2066
2167
|
httpProtocol: /* @__PURE__ */ __name(() => httpProtocol, "httpProtocol"),
|
|
@@ -2183,7 +2284,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
2183
2284
|
var _undefined = /^undefined$/i;
|
|
2184
2285
|
var lowercase = /^[^A-Z]*$/;
|
|
2185
2286
|
var uppercase = /^[^a-z]*$/;
|
|
2186
|
-
var
|
|
2287
|
+
var hex2 = /^[0-9a-fA-F]*$/;
|
|
2187
2288
|
function fixedBase64(bodyLength, padding) {
|
|
2188
2289
|
return new RegExp(`^[A-Za-z0-9+/]{${bodyLength}}${padding}$`);
|
|
2189
2290
|
}
|
|
@@ -3887,19 +3988,19 @@ var require_types_cjs_development = __commonJS({
|
|
|
3887
3988
|
});
|
|
3888
3989
|
const disc = cached(() => {
|
|
3889
3990
|
const opts = def.options;
|
|
3890
|
-
const
|
|
3991
|
+
const map22 = /* @__PURE__ */ new Map();
|
|
3891
3992
|
for (const o of opts) {
|
|
3892
3993
|
const values = o._zod.propValues?.[def.discriminator];
|
|
3893
3994
|
if (!values || values.size === 0)
|
|
3894
3995
|
throw new Error(`Invalid discriminated union option at index "${def.options.indexOf(o)}"`);
|
|
3895
3996
|
for (const v of values) {
|
|
3896
|
-
if (
|
|
3997
|
+
if (map22.has(v)) {
|
|
3897
3998
|
throw new Error(`Duplicate discriminator value "${String(v)}"`);
|
|
3898
3999
|
}
|
|
3899
|
-
|
|
4000
|
+
map22.set(v, o);
|
|
3900
4001
|
}
|
|
3901
4002
|
}
|
|
3902
|
-
return
|
|
4003
|
+
return map22;
|
|
3903
4004
|
});
|
|
3904
4005
|
inst._zod.parse = (payload, ctx) => {
|
|
3905
4006
|
const input = payload.value;
|
|
@@ -13416,7 +13517,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13416
13517
|
function: /* @__PURE__ */ __name(() => _function, "function"),
|
|
13417
13518
|
guid: /* @__PURE__ */ __name(() => guid2, "guid"),
|
|
13418
13519
|
hash: /* @__PURE__ */ __name(() => hash, "hash"),
|
|
13419
|
-
hex: /* @__PURE__ */ __name(() =>
|
|
13520
|
+
hex: /* @__PURE__ */ __name(() => hex22, "hex"),
|
|
13420
13521
|
hostname: /* @__PURE__ */ __name(() => hostname2, "hostname"),
|
|
13421
13522
|
httpUrl: /* @__PURE__ */ __name(() => httpUrl, "httpUrl"),
|
|
13422
13523
|
instanceof: /* @__PURE__ */ __name(() => _instanceof, "instanceof"),
|
|
@@ -13436,7 +13537,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13436
13537
|
looseObject: /* @__PURE__ */ __name(() => looseObject, "looseObject"),
|
|
13437
13538
|
looseRecord: /* @__PURE__ */ __name(() => looseRecord, "looseRecord"),
|
|
13438
13539
|
mac: /* @__PURE__ */ __name(() => mac2, "mac"),
|
|
13439
|
-
map: /* @__PURE__ */ __name(() =>
|
|
13540
|
+
map: /* @__PURE__ */ __name(() => map2, "map"),
|
|
13440
13541
|
meta: /* @__PURE__ */ __name(() => meta2, "meta"),
|
|
13441
13542
|
nan: /* @__PURE__ */ __name(() => nan, "nan"),
|
|
13442
13543
|
nanoid: /* @__PURE__ */ __name(() => nanoid2, "nanoid"),
|
|
@@ -13604,8 +13705,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13604
13705
|
var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
13605
13706
|
var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
13606
13707
|
var safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
13607
|
-
var
|
|
13608
|
-
var
|
|
13708
|
+
var encode22 = /* @__PURE__ */ _encode(ZodRealError);
|
|
13709
|
+
var decode22 = /* @__PURE__ */ _decode(ZodRealError);
|
|
13609
13710
|
var encodeAsync2 = /* @__PURE__ */ _encodeAsync(ZodRealError);
|
|
13610
13711
|
var decodeAsync2 = /* @__PURE__ */ _decodeAsync(ZodRealError);
|
|
13611
13712
|
var safeEncode2 = /* @__PURE__ */ _safeEncode(ZodRealError);
|
|
@@ -13668,8 +13769,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13668
13769
|
inst.parseAsync = async (data, params) => parseAsync2(inst, data, params, { callee: inst.parseAsync });
|
|
13669
13770
|
inst.safeParseAsync = async (data, params) => safeParseAsync2(inst, data, params);
|
|
13670
13771
|
inst.spa = inst.safeParseAsync;
|
|
13671
|
-
inst.encode = (data, params) =>
|
|
13672
|
-
inst.decode = (data, params) =>
|
|
13772
|
+
inst.encode = (data, params) => encode22(inst, data, params);
|
|
13773
|
+
inst.decode = (data, params) => decode22(inst, data, params);
|
|
13673
13774
|
inst.encodeAsync = async (data, params) => encodeAsync2(inst, data, params);
|
|
13674
13775
|
inst.decodeAsync = async (data, params) => decodeAsync2(inst, data, params);
|
|
13675
13776
|
inst.safeEncode = (data, params) => safeEncode2(inst, data, params);
|
|
@@ -14094,11 +14195,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14094
14195
|
}
|
|
14095
14196
|
__name(hostname2, "hostname2");
|
|
14096
14197
|
__name2(hostname2, "hostname");
|
|
14097
|
-
function
|
|
14198
|
+
function hex22(_params) {
|
|
14098
14199
|
return /* @__PURE__ */ _stringFormat(ZodCustomStringFormat, "hex", regexes_exports.hex, _params);
|
|
14099
14200
|
}
|
|
14100
|
-
__name(
|
|
14101
|
-
__name2(
|
|
14201
|
+
__name(hex22, "hex2");
|
|
14202
|
+
__name2(hex22, "hex");
|
|
14102
14203
|
function hash(alg, params) {
|
|
14103
14204
|
const enc = params?.enc ?? "hex";
|
|
14104
14205
|
const format = `${alg}_${enc}`;
|
|
@@ -14590,7 +14691,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14590
14691
|
inst.max = (...args) => inst.check(/* @__PURE__ */ _maxSize(...args));
|
|
14591
14692
|
inst.size = (...args) => inst.check(/* @__PURE__ */ _size(...args));
|
|
14592
14693
|
});
|
|
14593
|
-
function
|
|
14694
|
+
function map2(keyType, valueType, params) {
|
|
14594
14695
|
return new ZodMap({
|
|
14595
14696
|
type: "map",
|
|
14596
14697
|
keyType,
|
|
@@ -14598,8 +14699,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14598
14699
|
...util_exports.normalizeParams(params)
|
|
14599
14700
|
});
|
|
14600
14701
|
}
|
|
14601
|
-
__name(
|
|
14602
|
-
__name2(
|
|
14702
|
+
__name(map2, "map");
|
|
14703
|
+
__name2(map2, "map");
|
|
14603
14704
|
var ZodSet = /* @__PURE__ */ $constructor("ZodSet", (inst, def) => {
|
|
14604
14705
|
$ZodSet.init(inst, def);
|
|
14605
14706
|
ZodType.init(inst, def);
|
|
@@ -15099,9 +15200,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15099
15200
|
invalid_value: "invalid_value",
|
|
15100
15201
|
custom: "custom"
|
|
15101
15202
|
};
|
|
15102
|
-
function setErrorMap(
|
|
15203
|
+
function setErrorMap(map22) {
|
|
15103
15204
|
config({
|
|
15104
|
-
customError:
|
|
15205
|
+
customError: map22
|
|
15105
15206
|
});
|
|
15106
15207
|
}
|
|
15107
15208
|
__name(setErrorMap, "setErrorMap");
|
|
@@ -16059,7 +16160,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16059
16160
|
"replacedBy"
|
|
16060
16161
|
]).or(external_exports.string());
|
|
16061
16162
|
var AssociationValidator = external_exports.object({
|
|
16062
|
-
|
|
16163
|
+
// Accept compacted scalars while retaining the existing permissive array contract.
|
|
16164
|
+
type: external_exports.string().min(1).or(external_exports.string().array().nonempty()),
|
|
16063
16165
|
associationType: AssociationTypeValidator,
|
|
16064
16166
|
sourceId: external_exports.string().optional(),
|
|
16065
16167
|
targetId: external_exports.string()
|
|
@@ -16882,11 +16984,48 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16882
16984
|
updatedAt: external_exports.string(),
|
|
16883
16985
|
expiresAt: external_exports.string().optional(),
|
|
16884
16986
|
autoBoosts: external_exports.string().array().optional(),
|
|
16885
|
-
writers: external_exports.array(LCNProfileValidator).optional()
|
|
16987
|
+
writers: external_exports.array(LCNProfileValidator).optional(),
|
|
16988
|
+
recipients: external_exports.array(LCNPublicProfileValidator.extend({ did: external_exports.string() })).optional(),
|
|
16989
|
+
audienceVersion: external_exports.number().int().nonnegative().optional()
|
|
16886
16990
|
});
|
|
16887
|
-
var ConsentFlowContractRequestStatusValidator = external_exports.enum(["pending", "accepted", "denied"]).nullable();
|
|
16991
|
+
var ConsentFlowContractRequestStatusValidator = external_exports.enum(["pending", "accepted", "denied", "cancelled"]).nullable();
|
|
16888
16992
|
var ConsentFlowContractRequestReadStatusValidator = external_exports.enum(["unseen", "seen"]).nullable();
|
|
16889
|
-
var
|
|
16993
|
+
var ConsentFlowReferralValidator = external_exports.object({
|
|
16994
|
+
requestId: external_exports.string(),
|
|
16995
|
+
requestedBy: external_exports.string(),
|
|
16996
|
+
externalReferenceId: external_exports.string().max(256).optional()
|
|
16997
|
+
});
|
|
16998
|
+
var ContractRequestFieldsValidator = ConsentFlowReferralValidator.partial().extend({
|
|
16999
|
+
requestedAt: external_exports.string().optional(),
|
|
17000
|
+
message: external_exports.string().max(500).optional()
|
|
17001
|
+
});
|
|
17002
|
+
var SendContractRequestValidator = external_exports.object({
|
|
17003
|
+
contractUri: external_exports.string(),
|
|
17004
|
+
targetProfileId: external_exports.string(),
|
|
17005
|
+
externalReferenceId: external_exports.string().trim().min(1).max(256).optional(),
|
|
17006
|
+
message: external_exports.string().trim().max(500).optional()
|
|
17007
|
+
});
|
|
17008
|
+
var ConsentFlowWebhookMetadataValidator = external_exports.object({
|
|
17009
|
+
eventId: external_exports.string(),
|
|
17010
|
+
deliveryKey: external_exports.string(),
|
|
17011
|
+
event: external_exports.enum([
|
|
17012
|
+
"request_sent",
|
|
17013
|
+
"request_accepted",
|
|
17014
|
+
"request_denied",
|
|
17015
|
+
"request_cancelled",
|
|
17016
|
+
"consent_created",
|
|
17017
|
+
"consent_updated",
|
|
17018
|
+
"consent_withdrawn",
|
|
17019
|
+
"credentials_synced"
|
|
17020
|
+
]),
|
|
17021
|
+
contractUri: external_exports.string(),
|
|
17022
|
+
termsUri: external_exports.string().optional(),
|
|
17023
|
+
requestId: external_exports.string().optional(),
|
|
17024
|
+
requestedBy: external_exports.string().optional(),
|
|
17025
|
+
externalReferenceId: external_exports.string().optional(),
|
|
17026
|
+
recipientRole: external_exports.enum(["owner", "recipient", "requester", "target"])
|
|
17027
|
+
});
|
|
17028
|
+
var ConsentFlowContractRequestForProfileValidator = ContractRequestFieldsValidator.extend({
|
|
16890
17029
|
profile: LCNProfileValidator,
|
|
16891
17030
|
status: ConsentFlowContractRequestStatusValidator,
|
|
16892
17031
|
readStatus: ConsentFlowContractRequestReadStatusValidator.optional()
|
|
@@ -16932,6 +17071,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16932
17071
|
expiresAt: external_exports.string().optional(),
|
|
16933
17072
|
oneTime: external_exports.boolean().optional(),
|
|
16934
17073
|
terms: ConsentFlowTermsValidator,
|
|
17074
|
+
referral: ConsentFlowReferralValidator.optional(),
|
|
16935
17075
|
contract: ConsentFlowContractDetailsValidator,
|
|
16936
17076
|
uri: external_exports.string(),
|
|
16937
17077
|
consenter: LCNProfileValidator,
|
|
@@ -17027,6 +17167,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17027
17167
|
oneTime: external_exports.boolean().optional(),
|
|
17028
17168
|
terms: ConsentFlowTermsValidator.optional(),
|
|
17029
17169
|
guardianApproval: ConsentFlowGuardianApprovalValidator.optional(),
|
|
17170
|
+
referral: ConsentFlowReferralValidator.optional(),
|
|
17030
17171
|
id: external_exports.string(),
|
|
17031
17172
|
action: ConsentFlowTransactionActionValidator,
|
|
17032
17173
|
date: external_exports.string(),
|
|
@@ -17037,6 +17178,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17037
17178
|
status: ConsentFlowTermsStatusValidator,
|
|
17038
17179
|
contract: ConsentFlowContractDetailsValidator,
|
|
17039
17180
|
terms: ConsentFlowTermsValidator,
|
|
17181
|
+
referral: ConsentFlowReferralValidator.optional(),
|
|
17040
17182
|
transactions: ConsentFlowTransactionValidator.array()
|
|
17041
17183
|
});
|
|
17042
17184
|
var HolderExportMetadataValidator = external_exports.object({
|
|
@@ -17773,7 +17915,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17773
17915
|
displayName: external_exports.string(),
|
|
17774
17916
|
email: external_exports.string().optional()
|
|
17775
17917
|
});
|
|
17776
|
-
var
|
|
17918
|
+
var AppStoreListingFieldsValidator = external_exports.object({
|
|
17777
17919
|
listing_id: external_exports.string(),
|
|
17778
17920
|
slug: external_exports.string().optional(),
|
|
17779
17921
|
display_name: external_exports.string(),
|
|
@@ -17799,15 +17941,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17799
17941
|
submitter: AppStoreListingSubmitterValidator.optional(),
|
|
17800
17942
|
contact_email: external_exports.string().email().optional()
|
|
17801
17943
|
});
|
|
17944
|
+
var PendingListingUpdateStatusValidator = external_exports.enum(["DRAFT", "PENDING_REVIEW"]);
|
|
17945
|
+
var PendingListingUpdateValidator = external_exports.object({
|
|
17946
|
+
status: PendingListingUpdateStatusValidator,
|
|
17947
|
+
submitted_at: external_exports.string().optional(),
|
|
17948
|
+
changes: AppStoreListingFieldsValidator.omit({
|
|
17949
|
+
listing_id: true,
|
|
17950
|
+
app_listing_status: true,
|
|
17951
|
+
promotion_level: true,
|
|
17952
|
+
submitted_at: true,
|
|
17953
|
+
submitter: true
|
|
17954
|
+
}).partial(),
|
|
17955
|
+
manifest_version: external_exports.number().int().min(1).optional()
|
|
17956
|
+
});
|
|
17957
|
+
var AppStoreListingValidator = AppStoreListingFieldsValidator.extend({
|
|
17958
|
+
pending_update: PendingListingUpdateValidator.optional()
|
|
17959
|
+
});
|
|
17802
17960
|
var AppStoreListingCreateValidator = AppStoreListingValidator.omit({
|
|
17803
17961
|
listing_id: true,
|
|
17804
17962
|
app_listing_status: true,
|
|
17805
|
-
promotion_level: true
|
|
17963
|
+
promotion_level: true,
|
|
17964
|
+
pending_update: true
|
|
17806
17965
|
});
|
|
17807
17966
|
var AppStoreListingUpdateValidator = AppStoreListingValidator.partial().omit({
|
|
17808
17967
|
listing_id: true,
|
|
17809
17968
|
app_listing_status: true,
|
|
17810
|
-
promotion_level: true
|
|
17969
|
+
promotion_level: true,
|
|
17970
|
+
pending_update: true
|
|
17811
17971
|
});
|
|
17812
17972
|
var InstalledAppValidator = AppStoreListingValidator.extend({
|
|
17813
17973
|
installed_at: external_exports.string()
|
|
@@ -17822,12 +17982,87 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17822
17982
|
templateAlias: external_exports.string().min(1).max(50).regex(/^[a-z0-9-]+$/),
|
|
17823
17983
|
boostUri: external_exports.string()
|
|
17824
17984
|
});
|
|
17825
|
-
var
|
|
17985
|
+
var InlineWalletCategoryValidator = external_exports.enum([
|
|
17986
|
+
"Achievement",
|
|
17987
|
+
"Skill",
|
|
17988
|
+
"ID",
|
|
17989
|
+
"Learning History",
|
|
17990
|
+
"Work History",
|
|
17991
|
+
"Social Badges",
|
|
17992
|
+
"Membership",
|
|
17993
|
+
"Accomplishment",
|
|
17994
|
+
"Experiences",
|
|
17995
|
+
"Accommodation",
|
|
17996
|
+
"Family"
|
|
17997
|
+
]);
|
|
17998
|
+
var InlineAlignmentValidator = external_exports.object({
|
|
17999
|
+
name: external_exports.string(),
|
|
18000
|
+
url: external_exports.string(),
|
|
18001
|
+
framework: external_exports.string().optional(),
|
|
18002
|
+
code: external_exports.string().optional()
|
|
18003
|
+
}).passthrough();
|
|
18004
|
+
var InlineEvidenceValidator = external_exports.object({
|
|
18005
|
+
id: external_exports.string().optional(),
|
|
18006
|
+
name: external_exports.string().optional(),
|
|
18007
|
+
narrative: external_exports.string().optional()
|
|
18008
|
+
}).passthrough();
|
|
18009
|
+
var InlineWalletSkillTagValidator = external_exports.object({
|
|
18010
|
+
frameworkId: external_exports.string(),
|
|
18011
|
+
id: external_exports.string(),
|
|
18012
|
+
proficiencyLevel: external_exports.string().optional()
|
|
18013
|
+
}).passthrough();
|
|
18014
|
+
var SimpleInlineCredentialTemplateValidator = external_exports.object({
|
|
18015
|
+
rawCredential: external_exports.undefined().optional(),
|
|
18016
|
+
name: external_exports.string(),
|
|
18017
|
+
description: external_exports.string().optional(),
|
|
18018
|
+
image: external_exports.string().optional(),
|
|
18019
|
+
issuerName: external_exports.string().optional(),
|
|
18020
|
+
achievementType: external_exports.string().optional(),
|
|
18021
|
+
category: InlineWalletCategoryValidator.optional(),
|
|
18022
|
+
criteria: external_exports.object({
|
|
18023
|
+
narrative: external_exports.string().optional(),
|
|
18024
|
+
url: external_exports.string().optional()
|
|
18025
|
+
}).passthrough().optional(),
|
|
18026
|
+
alignments: external_exports.array(InlineAlignmentValidator).optional(),
|
|
18027
|
+
tags: external_exports.array(external_exports.string()).optional(),
|
|
18028
|
+
activity: external_exports.object({
|
|
18029
|
+
startDate: external_exports.string().optional(),
|
|
18030
|
+
endDate: external_exports.string().optional()
|
|
18031
|
+
}).passthrough().optional(),
|
|
18032
|
+
credits: external_exports.object({
|
|
18033
|
+
earned: external_exports.union([external_exports.number(), external_exports.string()]).optional(),
|
|
18034
|
+
available: external_exports.union([external_exports.number(), external_exports.string()]).optional()
|
|
18035
|
+
}).passthrough().optional(),
|
|
18036
|
+
validUntil: external_exports.string().optional(),
|
|
18037
|
+
evidence: external_exports.array(InlineEvidenceValidator).optional(),
|
|
18038
|
+
walletSkills: external_exports.array(InlineWalletSkillTagValidator).optional()
|
|
18039
|
+
}).passthrough();
|
|
18040
|
+
var RawInlineCredentialTemplateValidator = external_exports.object({
|
|
18041
|
+
rawCredential: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
18042
|
+
category: InlineWalletCategoryValidator.optional(),
|
|
18043
|
+
walletSkills: external_exports.array(InlineWalletSkillTagValidator).optional()
|
|
18044
|
+
}).passthrough();
|
|
18045
|
+
var InlineCredentialTemplateValidator = external_exports.union([
|
|
18046
|
+
RawInlineCredentialTemplateValidator,
|
|
18047
|
+
SimpleInlineCredentialTemplateValidator
|
|
18048
|
+
]);
|
|
18049
|
+
var LegacySendCredentialEventValidator = external_exports.object({
|
|
17826
18050
|
type: external_exports.literal("send-credential"),
|
|
17827
18051
|
templateAlias: external_exports.string(),
|
|
17828
18052
|
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
17829
18053
|
preventDuplicateClaim: external_exports.boolean().optional()
|
|
17830
18054
|
});
|
|
18055
|
+
var InlineSendCredentialEventValidator = external_exports.object({
|
|
18056
|
+
type: external_exports.literal("send-credential"),
|
|
18057
|
+
alias: external_exports.string(),
|
|
18058
|
+
template: InlineCredentialTemplateValidator,
|
|
18059
|
+
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
18060
|
+
preventDuplicateClaim: external_exports.boolean().optional()
|
|
18061
|
+
});
|
|
18062
|
+
var SendCredentialEventValidator = external_exports.union([
|
|
18063
|
+
LegacySendCredentialEventValidator,
|
|
18064
|
+
InlineSendCredentialEventValidator
|
|
18065
|
+
]);
|
|
17831
18066
|
var CheckCredentialEventValidator = external_exports.object({
|
|
17832
18067
|
type: external_exports.literal("check-credential"),
|
|
17833
18068
|
templateAlias: external_exports.string().optional(),
|
|
@@ -17922,7 +18157,119 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17922
18157
|
type: external_exports.literal("get-counters"),
|
|
17923
18158
|
keys: external_exports.array(counterKeyValidator).min(1).max(50).optional()
|
|
17924
18159
|
});
|
|
17925
|
-
var
|
|
18160
|
+
var ConsentRequestWalletCategoryValidator = external_exports.enum([
|
|
18161
|
+
"Achievement",
|
|
18162
|
+
"Skill",
|
|
18163
|
+
"ID",
|
|
18164
|
+
"Learning History",
|
|
18165
|
+
"Work History",
|
|
18166
|
+
"Social Badges",
|
|
18167
|
+
"Membership",
|
|
18168
|
+
"Accomplishment",
|
|
18169
|
+
"Experiences",
|
|
18170
|
+
"Accommodation",
|
|
18171
|
+
"Family"
|
|
18172
|
+
]);
|
|
18173
|
+
var ConsentRequestPersonalFieldValidator = external_exports.enum([
|
|
18174
|
+
"name",
|
|
18175
|
+
"email",
|
|
18176
|
+
"phone",
|
|
18177
|
+
"birthDate",
|
|
18178
|
+
"country",
|
|
18179
|
+
"avatar"
|
|
18180
|
+
]);
|
|
18181
|
+
var ConsentRequestValidator = external_exports.object({
|
|
18182
|
+
read: external_exports.object({
|
|
18183
|
+
credentialCategories: external_exports.array(ConsentRequestWalletCategoryValidator).optional(),
|
|
18184
|
+
personalFields: external_exports.array(ConsentRequestPersonalFieldValidator).optional()
|
|
18185
|
+
}).optional(),
|
|
18186
|
+
write: external_exports.object({
|
|
18187
|
+
credentialCategories: external_exports.array(ConsentRequestWalletCategoryValidator).optional()
|
|
18188
|
+
}).optional(),
|
|
18189
|
+
reason: external_exports.string().optional()
|
|
18190
|
+
});
|
|
18191
|
+
var NormalizedConsentScopesValidator = external_exports.object({
|
|
18192
|
+
read: external_exports.object({
|
|
18193
|
+
credentialCategories: external_exports.array(ConsentRequestWalletCategoryValidator).default([]),
|
|
18194
|
+
personalFields: external_exports.array(ConsentRequestPersonalFieldValidator).default([])
|
|
18195
|
+
}),
|
|
18196
|
+
write: external_exports.object({
|
|
18197
|
+
credentialCategories: external_exports.array(ConsentRequestWalletCategoryValidator).default([])
|
|
18198
|
+
})
|
|
18199
|
+
});
|
|
18200
|
+
var CapturedTemplateRecordValidator = external_exports.object({
|
|
18201
|
+
alias: external_exports.string(),
|
|
18202
|
+
template: InlineCredentialTemplateValidator,
|
|
18203
|
+
version: external_exports.number().int().min(1),
|
|
18204
|
+
lastUsedAt: external_exports.string()
|
|
18205
|
+
}).passthrough();
|
|
18206
|
+
var CapturedConsentRecordValidator = external_exports.object({
|
|
18207
|
+
scopes: NormalizedConsentScopesValidator,
|
|
18208
|
+
reason: external_exports.string().optional(),
|
|
18209
|
+
lastUsedAt: external_exports.string()
|
|
18210
|
+
}).passthrough();
|
|
18211
|
+
var AppManifestValidator = external_exports.object({
|
|
18212
|
+
manifestVersion: external_exports.literal(1),
|
|
18213
|
+
appUrl: external_exports.string(),
|
|
18214
|
+
appKey: external_exports.string().max(200).optional(),
|
|
18215
|
+
suggestedName: external_exports.string().optional(),
|
|
18216
|
+
suggestedIconUrl: external_exports.string().optional(),
|
|
18217
|
+
permissions: external_exports.array(external_exports.string()).default([]),
|
|
18218
|
+
templates: external_exports.array(CapturedTemplateRecordValidator).default([]),
|
|
18219
|
+
consentRequests: external_exports.array(CapturedConsentRecordValidator).default([]),
|
|
18220
|
+
usedConsentContract: external_exports.boolean().optional(),
|
|
18221
|
+
featuresLaunched: external_exports.array(external_exports.string()).default([]),
|
|
18222
|
+
counterKeys: external_exports.array(external_exports.string()).default([]),
|
|
18223
|
+
usedLearnerContext: external_exports.boolean(),
|
|
18224
|
+
usedNotifications: external_exports.boolean(),
|
|
18225
|
+
firstCapturedAt: external_exports.string(),
|
|
18226
|
+
lastUpdatedAt: external_exports.string()
|
|
18227
|
+
}).passthrough();
|
|
18228
|
+
var AppManifestVersionStatusValidator = external_exports.enum(["draft", "active", "superseded"]);
|
|
18229
|
+
var AppManifestVersionValidator = external_exports.object({
|
|
18230
|
+
id: external_exports.string(),
|
|
18231
|
+
version: external_exports.number().int().min(1),
|
|
18232
|
+
manifestHash: external_exports.string(),
|
|
18233
|
+
manifest: AppManifestValidator,
|
|
18234
|
+
status: AppManifestVersionStatusValidator,
|
|
18235
|
+
createdAt: external_exports.string(),
|
|
18236
|
+
activatedAt: external_exports.string().optional()
|
|
18237
|
+
});
|
|
18238
|
+
var AppManifestStringDiffValidator = external_exports.object({
|
|
18239
|
+
added: external_exports.array(external_exports.string()),
|
|
18240
|
+
removed: external_exports.array(external_exports.string()),
|
|
18241
|
+
changed: external_exports.array(external_exports.string())
|
|
18242
|
+
});
|
|
18243
|
+
var AppManifestTemplateRefValidator = external_exports.object({
|
|
18244
|
+
alias: external_exports.string(),
|
|
18245
|
+
version: external_exports.number().int().min(1)
|
|
18246
|
+
});
|
|
18247
|
+
var AppManifestTemplateChangeValidator = external_exports.object({
|
|
18248
|
+
alias: external_exports.string(),
|
|
18249
|
+
fromVersion: external_exports.number().int().min(1),
|
|
18250
|
+
toVersion: external_exports.number().int().min(1)
|
|
18251
|
+
});
|
|
18252
|
+
var AppManifestDiffValidator = external_exports.object({
|
|
18253
|
+
permissions: AppManifestStringDiffValidator,
|
|
18254
|
+
templates: external_exports.object({
|
|
18255
|
+
added: external_exports.array(AppManifestTemplateRefValidator),
|
|
18256
|
+
removed: external_exports.array(AppManifestTemplateRefValidator),
|
|
18257
|
+
changed: external_exports.array(AppManifestTemplateChangeValidator)
|
|
18258
|
+
}),
|
|
18259
|
+
consentScopes: AppManifestStringDiffValidator,
|
|
18260
|
+
featurePaths: AppManifestStringDiffValidator,
|
|
18261
|
+
counterKeys: AppManifestStringDiffValidator,
|
|
18262
|
+
requiresReview: external_exports.boolean()
|
|
18263
|
+
});
|
|
18264
|
+
var UpsertConsentContractEventValidator = external_exports.object({
|
|
18265
|
+
type: external_exports.literal("upsert-consent-contract"),
|
|
18266
|
+
scopes: ConsentRequestValidator
|
|
18267
|
+
});
|
|
18268
|
+
var UpsertConsentContractResponseValidator = external_exports.object({
|
|
18269
|
+
contractUri: external_exports.string(),
|
|
18270
|
+
created: external_exports.boolean()
|
|
18271
|
+
});
|
|
18272
|
+
var AppEventValidator = external_exports.union([
|
|
17926
18273
|
SendCredentialEventValidator,
|
|
17927
18274
|
CheckCredentialEventValidator,
|
|
17928
18275
|
CheckIssuanceStatusEventValidator,
|
|
@@ -17932,7 +18279,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17932
18279
|
SendNotificationEventValidator,
|
|
17933
18280
|
IncrementCounterEventValidator,
|
|
17934
18281
|
GetCounterEventValidator,
|
|
17935
|
-
GetCountersEventValidator
|
|
18282
|
+
GetCountersEventValidator,
|
|
18283
|
+
UpsertConsentContractEventValidator
|
|
17936
18284
|
]);
|
|
17937
18285
|
var AppEventInputValidator = external_exports.object({
|
|
17938
18286
|
listingId: external_exports.string(),
|
|
@@ -18011,6 +18359,30 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18011
18359
|
__name2(this, "AuthSessionError");
|
|
18012
18360
|
}
|
|
18013
18361
|
};
|
|
18362
|
+
var UnsupportedSignInOperationError = class extends Error {
|
|
18363
|
+
static {
|
|
18364
|
+
__name(this, "UnsupportedSignInOperationError");
|
|
18365
|
+
}
|
|
18366
|
+
constructor(operation, providerType) {
|
|
18367
|
+
super(`${operation} is not supported by ${providerType}`);
|
|
18368
|
+
this.operation = operation;
|
|
18369
|
+
this.providerType = providerType;
|
|
18370
|
+
this.name = "UnsupportedSignInOperationError";
|
|
18371
|
+
}
|
|
18372
|
+
static {
|
|
18373
|
+
__name2(this, "UnsupportedSignInOperationError");
|
|
18374
|
+
}
|
|
18375
|
+
};
|
|
18376
|
+
var ESCROW_PIN_LOCKED_MESSAGE2 = "Too many incorrect PIN attempts. You can still recover by waiting.";
|
|
18377
|
+
var ESCROW_PIN_UNAVAILABLE_MESSAGE2 = "PIN recovery is not available for this account.";
|
|
18378
|
+
var ESCROW_PIN_MISMATCH_PATTERN2 = /^Incorrect PIN\. (\d+) attempts left\.$/;
|
|
18379
|
+
var escrowPinMismatchMessage = /* @__PURE__ */ __name2((attemptsRemaining) => `Incorrect PIN. ${attemptsRemaining} attempts left.`, "escrowPinMismatchMessage");
|
|
18380
|
+
var EscrowPinStatusValidator = external_exports.object({
|
|
18381
|
+
state: external_exports.enum(["none", "enabled", "locked", "stale"]),
|
|
18382
|
+
enabled: external_exports.boolean(),
|
|
18383
|
+
attemptsRemaining: external_exports.number().int().nonnegative(),
|
|
18384
|
+
salt: external_exports.string().optional()
|
|
18385
|
+
});
|
|
18014
18386
|
var BITSTRING_STATUS_PURPOSES = ["revocation", "suspension"];
|
|
18015
18387
|
var DEFAULT_BITSTRING_STATUS_LIST_SIZE = 131072;
|
|
18016
18388
|
var BitstringStatusPurposeValidator = external_exports.enum(BITSTRING_STATUS_PURPOSES);
|
|
@@ -18125,6 +18497,502 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18125
18497
|
const result = inAppMessagesFlagValidator.safeParse(raw);
|
|
18126
18498
|
return result.success ? result.data : EMPTY_IN_APP_MESSAGES_FLAG;
|
|
18127
18499
|
}, "parseInAppMessagesFlag");
|
|
18500
|
+
var SHARE_LINK_ID_BYTES = 16;
|
|
18501
|
+
var SHARE_CONTENT_KEY_BYTES = 32;
|
|
18502
|
+
var SHARE_IV_BYTES = 12;
|
|
18503
|
+
var SHARE_TAG_BYTES = 16;
|
|
18504
|
+
var MAX_SHARE_CIPHERTEXT_BYTES = 512 * 1024;
|
|
18505
|
+
var MAX_SHARE_RECOVERY_JWE_BYTES = 64 * 1024;
|
|
18506
|
+
var MAX_SELECTED_CREDENTIALS = 50;
|
|
18507
|
+
var MAX_ENDORSEMENTS = 200;
|
|
18508
|
+
var MAX_VP_MEMBERS = MAX_SELECTED_CREDENTIALS + MAX_ENDORSEMENTS;
|
|
18509
|
+
var MAX_SHARE_SOURCE_URI_CHARS = 2048;
|
|
18510
|
+
var MAX_SHARE_LINK_REQUEST_BYTES = 1024 * 1024;
|
|
18511
|
+
var SHARE_LINK_PROTOCOL = "lc-share/v1";
|
|
18512
|
+
var SHARE_RECOVERY_PROTOCOL = "lc-share-recovery/v1";
|
|
18513
|
+
var SHARE_AAD_PREFIX = "lc-share:v1";
|
|
18514
|
+
var BASE64URL_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
18515
|
+
var BASE64URL_LOOKUP = (() => {
|
|
18516
|
+
const table = new Int16Array(128).fill(-1);
|
|
18517
|
+
for (let index = 0; index < BASE64URL_ALPHABET.length; index += 1) {
|
|
18518
|
+
table[BASE64URL_ALPHABET.charCodeAt(index)] = index;
|
|
18519
|
+
}
|
|
18520
|
+
return table;
|
|
18521
|
+
})();
|
|
18522
|
+
var encodeBase64Url = /* @__PURE__ */ __name2((bytes2) => {
|
|
18523
|
+
let output = "";
|
|
18524
|
+
for (let index = 0; index < bytes2.length; index += 3) {
|
|
18525
|
+
const first = bytes2[index];
|
|
18526
|
+
const second = bytes2[index + 1];
|
|
18527
|
+
const third = bytes2[index + 2];
|
|
18528
|
+
output += BASE64URL_ALPHABET[first >> 2];
|
|
18529
|
+
output += BASE64URL_ALPHABET[(first & 3) << 4 | (second ?? 0) >> 4];
|
|
18530
|
+
if (second === void 0) break;
|
|
18531
|
+
output += BASE64URL_ALPHABET[(second & 15) << 2 | (third ?? 0) >> 6];
|
|
18532
|
+
if (third === void 0) break;
|
|
18533
|
+
output += BASE64URL_ALPHABET[third & 63];
|
|
18534
|
+
}
|
|
18535
|
+
return output;
|
|
18536
|
+
}, "encodeBase64Url");
|
|
18537
|
+
var decodeBase64Url = /* @__PURE__ */ __name2((value) => {
|
|
18538
|
+
if (typeof value !== "string") return null;
|
|
18539
|
+
const output = new Uint8Array(Math.floor(value.length * 6 / 8));
|
|
18540
|
+
let bits = 0;
|
|
18541
|
+
let bitCount = 0;
|
|
18542
|
+
let outputIndex = 0;
|
|
18543
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
18544
|
+
const code = value.charCodeAt(index);
|
|
18545
|
+
const digit = code < 128 ? BASE64URL_LOOKUP[code] : -1;
|
|
18546
|
+
if (digit < 0) return null;
|
|
18547
|
+
bits = bits << 6 | digit;
|
|
18548
|
+
bitCount += 6;
|
|
18549
|
+
if (bitCount >= 8) {
|
|
18550
|
+
bitCount -= 8;
|
|
18551
|
+
output[outputIndex] = bits >> bitCount & 255;
|
|
18552
|
+
outputIndex += 1;
|
|
18553
|
+
}
|
|
18554
|
+
}
|
|
18555
|
+
return output;
|
|
18556
|
+
}, "decodeBase64Url");
|
|
18557
|
+
var isCanonicalBase64Url = /* @__PURE__ */ __name2((value, expectedBytes) => {
|
|
18558
|
+
if (typeof value !== "string") return false;
|
|
18559
|
+
if (expectedBytes !== void 0 && value.length !== Math.ceil(expectedBytes * 4 / 3))
|
|
18560
|
+
return false;
|
|
18561
|
+
const decoded = decodeBase64Url(value);
|
|
18562
|
+
if (decoded === null) return false;
|
|
18563
|
+
if (expectedBytes !== void 0 && decoded.length !== expectedBytes) return false;
|
|
18564
|
+
return encodeBase64Url(decoded) === value;
|
|
18565
|
+
}, "isCanonicalBase64Url");
|
|
18566
|
+
var decodedBase64UrlByteLength = /* @__PURE__ */ __name2((value) => decodeBase64Url(value)?.length ?? null, "decodedBase64UrlByteLength");
|
|
18567
|
+
var utf8ByteLength = /* @__PURE__ */ __name2((value) => new TextEncoder().encode(value).length, "utf8ByteLength");
|
|
18568
|
+
var canonicalBase64Url = /* @__PURE__ */ __name2((bytes2) => external_exports.string().refine((value) => isCanonicalBase64Url(value, bytes2), {
|
|
18569
|
+
message: `must be canonical base64url for exactly ${bytes2} bytes`
|
|
18570
|
+
}), "canonicalBase64Url");
|
|
18571
|
+
var ShareLinkIdValidator = canonicalBase64Url(SHARE_LINK_ID_BYTES);
|
|
18572
|
+
var ShareContentKeyValidator = canonicalBase64Url(SHARE_CONTENT_KEY_BYTES);
|
|
18573
|
+
var ShareIvValidator = canonicalBase64Url(SHARE_IV_BYTES);
|
|
18574
|
+
var ShareCiphertextValidator = external_exports.string().refine(
|
|
18575
|
+
(value) => {
|
|
18576
|
+
if (value.length > Math.ceil(MAX_SHARE_CIPHERTEXT_BYTES * 4 / 3)) return false;
|
|
18577
|
+
const decoded = decodeBase64Url(value);
|
|
18578
|
+
if (decoded === null) return false;
|
|
18579
|
+
if (encodeBase64Url(decoded) !== value) return false;
|
|
18580
|
+
return decoded.length >= SHARE_TAG_BYTES && decoded.length <= MAX_SHARE_CIPHERTEXT_BYTES;
|
|
18581
|
+
},
|
|
18582
|
+
{
|
|
18583
|
+
message: `must be canonical base64url decoding to ${SHARE_TAG_BYTES}..${MAX_SHARE_CIPHERTEXT_BYTES} bytes`
|
|
18584
|
+
}
|
|
18585
|
+
);
|
|
18586
|
+
var ShareEnvelopeValidator = external_exports.object({
|
|
18587
|
+
v: external_exports.literal(1),
|
|
18588
|
+
alg: external_exports.literal("A256GCM"),
|
|
18589
|
+
iv: ShareIvValidator,
|
|
18590
|
+
ct: ShareCiphertextValidator
|
|
18591
|
+
}).strict();
|
|
18592
|
+
var safeVersion = external_exports.number().int().min(1).max(2 ** 31 - 1);
|
|
18593
|
+
var safeCredentialIndex = external_exports.number().int().min(0).max(MAX_VP_MEMBERS - 1);
|
|
18594
|
+
var ShareSelectionEntryValidator = external_exports.object({ credentialIndex: safeCredentialIndex }).strict();
|
|
18595
|
+
var ShareEndorsementEntryValidator = external_exports.object({ credentialIndex: safeCredentialIndex, targetCredentialIndex: safeCredentialIndex }).strict();
|
|
18596
|
+
var ShareSharerValidator = external_exports.object({
|
|
18597
|
+
profileId: external_exports.string().min(1).max(128),
|
|
18598
|
+
displayName: external_exports.string().min(1).max(120),
|
|
18599
|
+
avatar: external_exports.string().max(2048).optional()
|
|
18600
|
+
}).strict();
|
|
18601
|
+
var presentationShape = VPValidator.extend({
|
|
18602
|
+
verifiableCredential: VCValidator.array().min(1).max(MAX_VP_MEMBERS)
|
|
18603
|
+
});
|
|
18604
|
+
var hasBoundedPresentation = /* @__PURE__ */ __name2((value) => {
|
|
18605
|
+
let credentialCount = 0;
|
|
18606
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
18607
|
+
const visit = /* @__PURE__ */ __name2((node, depth) => {
|
|
18608
|
+
if (node === null || typeof node !== "object") return true;
|
|
18609
|
+
if (depth > 32 || ancestors.has(node)) return false;
|
|
18610
|
+
ancestors.add(node);
|
|
18611
|
+
try {
|
|
18612
|
+
for (const [key, child] of Object.entries(node)) {
|
|
18613
|
+
if (key === "verifiableCredential") {
|
|
18614
|
+
credentialCount += Array.isArray(child) ? child.length : 1;
|
|
18615
|
+
if (credentialCount > MAX_VP_MEMBERS) return false;
|
|
18616
|
+
}
|
|
18617
|
+
if (!visit(child, depth + 1)) return false;
|
|
18618
|
+
}
|
|
18619
|
+
return true;
|
|
18620
|
+
} finally {
|
|
18621
|
+
ancestors.delete(node);
|
|
18622
|
+
}
|
|
18623
|
+
}, "visit");
|
|
18624
|
+
return visit(value, 0);
|
|
18625
|
+
}, "hasBoundedPresentation");
|
|
18626
|
+
var ShareManifestPresentationValidator = external_exports.custom(
|
|
18627
|
+
(value) => hasBoundedPresentation(value) && presentationShape.safeParse(value).success,
|
|
18628
|
+
{ message: "invalid share presentation" }
|
|
18629
|
+
);
|
|
18630
|
+
var SharePayloadValidatorShape = external_exports.object({
|
|
18631
|
+
protocol: external_exports.literal(SHARE_LINK_PROTOCOL),
|
|
18632
|
+
shareId: ShareLinkIdValidator,
|
|
18633
|
+
contentVersion: safeVersion,
|
|
18634
|
+
createdAt: external_exports.iso.datetime(),
|
|
18635
|
+
sharer: ShareSharerValidator,
|
|
18636
|
+
presentation: ShareManifestPresentationValidator,
|
|
18637
|
+
selection: ShareSelectionEntryValidator.array().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
18638
|
+
endorsements: ShareEndorsementEntryValidator.array().max(MAX_ENDORSEMENTS).default([])
|
|
18639
|
+
}).strict();
|
|
18640
|
+
var classificationFailure = /* @__PURE__ */ __name2((code, message, path = []) => ({ ok: false, code, message, path }), "classificationFailure");
|
|
18641
|
+
var readSignedClaimId = /* @__PURE__ */ __name2((member) => {
|
|
18642
|
+
if (member === null || typeof member !== "object") return void 0;
|
|
18643
|
+
const record2 = member;
|
|
18644
|
+
const claim = record2.credentialSubject ?? record2.endorsement;
|
|
18645
|
+
if (claim === null || typeof claim !== "object") return void 0;
|
|
18646
|
+
const claimRecord = claim;
|
|
18647
|
+
const nested = claimRecord.endorsement;
|
|
18648
|
+
const nestedId = nested !== null && typeof nested === "object" ? nested.id : void 0;
|
|
18649
|
+
return claimRecord.id ?? nestedId;
|
|
18650
|
+
}, "readSignedClaimId");
|
|
18651
|
+
var classifyShareManifest = /* @__PURE__ */ __name2((payload) => {
|
|
18652
|
+
const members = payload.presentation?.verifiableCredential;
|
|
18653
|
+
if (!Array.isArray(members) || members.length === 0) {
|
|
18654
|
+
return classificationFailure("NO_PRESENTATION_MEMBERS", "presentation has no credentials");
|
|
18655
|
+
}
|
|
18656
|
+
if (members.length > MAX_VP_MEMBERS) {
|
|
18657
|
+
return classificationFailure(
|
|
18658
|
+
"TOO_MANY_VP_MEMBERS",
|
|
18659
|
+
`presentation has ${members.length} members, over the ${MAX_VP_MEMBERS} bound`
|
|
18660
|
+
);
|
|
18661
|
+
}
|
|
18662
|
+
const selection = payload.selection;
|
|
18663
|
+
const endorsements = payload.endorsements ?? [];
|
|
18664
|
+
if (!Array.isArray(selection) || selection.length < 1 || selection.length > MAX_SELECTED_CREDENTIALS) {
|
|
18665
|
+
return classificationFailure("BAD_SELECTION", "selection must contain 1..50 entries");
|
|
18666
|
+
}
|
|
18667
|
+
if (!Array.isArray(endorsements) || endorsements.length > MAX_ENDORSEMENTS) {
|
|
18668
|
+
return classificationFailure(
|
|
18669
|
+
"BAD_ENDORSEMENTS",
|
|
18670
|
+
"endorsements must contain at most 200 entries"
|
|
18671
|
+
);
|
|
18672
|
+
}
|
|
18673
|
+
const selectedIndices = [];
|
|
18674
|
+
const selected = /* @__PURE__ */ new Set();
|
|
18675
|
+
for (let index = 0; index < selection.length; index += 1) {
|
|
18676
|
+
const entry = selection[index];
|
|
18677
|
+
const credentialIndex = entry?.credentialIndex;
|
|
18678
|
+
if (!Number.isSafeInteger(credentialIndex) || credentialIndex < 0 || credentialIndex >= members.length) {
|
|
18679
|
+
return classificationFailure(
|
|
18680
|
+
"SELECTION_INDEX_OUT_OF_BOUNDS",
|
|
18681
|
+
`selection[${index}].credentialIndex is out of bounds`,
|
|
18682
|
+
["selection", index, "credentialIndex"]
|
|
18683
|
+
);
|
|
18684
|
+
}
|
|
18685
|
+
if (selected.has(credentialIndex)) {
|
|
18686
|
+
return classificationFailure(
|
|
18687
|
+
"SELECTION_INDEX_DUPLICATE",
|
|
18688
|
+
`selection[${index}].credentialIndex is duplicated`,
|
|
18689
|
+
["selection", index, "credentialIndex"]
|
|
18690
|
+
);
|
|
18691
|
+
}
|
|
18692
|
+
selected.add(credentialIndex);
|
|
18693
|
+
selectedIndices.push(credentialIndex);
|
|
18694
|
+
}
|
|
18695
|
+
const classified = new Set(selected);
|
|
18696
|
+
const endorsementIndices = [];
|
|
18697
|
+
for (let index = 0; index < endorsements.length; index += 1) {
|
|
18698
|
+
const entry = endorsements[index];
|
|
18699
|
+
const credentialIndex = entry?.credentialIndex;
|
|
18700
|
+
const targetIndex = entry?.targetCredentialIndex;
|
|
18701
|
+
if (!Number.isSafeInteger(credentialIndex) || credentialIndex < 0 || credentialIndex >= members.length) {
|
|
18702
|
+
return classificationFailure(
|
|
18703
|
+
"ENDORSEMENT_INDEX_OUT_OF_BOUNDS",
|
|
18704
|
+
`endorsements[${index}].credentialIndex is out of bounds`,
|
|
18705
|
+
["endorsements", index, "credentialIndex"]
|
|
18706
|
+
);
|
|
18707
|
+
}
|
|
18708
|
+
if (classified.has(credentialIndex)) {
|
|
18709
|
+
return classificationFailure(
|
|
18710
|
+
"VP_MEMBER_CLASSIFIED_TWICE",
|
|
18711
|
+
`endorsements[${index}].credentialIndex was already classified`,
|
|
18712
|
+
["endorsements", index, "credentialIndex"]
|
|
18713
|
+
);
|
|
18714
|
+
}
|
|
18715
|
+
if (!selected.has(targetIndex)) {
|
|
18716
|
+
return classificationFailure(
|
|
18717
|
+
"ENDORSEMENT_TARGET_NOT_SELECTED",
|
|
18718
|
+
`endorsements[${index}].targetCredentialIndex must reference a selected credential`,
|
|
18719
|
+
["endorsements", index, "targetCredentialIndex"]
|
|
18720
|
+
);
|
|
18721
|
+
}
|
|
18722
|
+
const referenced = readSignedClaimId(members[credentialIndex]);
|
|
18723
|
+
const target = members[targetIndex];
|
|
18724
|
+
const targetId = target !== null && typeof target === "object" ? target.id : void 0;
|
|
18725
|
+
if (typeof referenced !== "string" || typeof targetId !== "string" || referenced !== targetId) {
|
|
18726
|
+
return classificationFailure(
|
|
18727
|
+
"ENDORSEMENT_TARGET_UNBOUND",
|
|
18728
|
+
`endorsements[${index}] claim does not reference the target credential id`,
|
|
18729
|
+
["endorsements", index]
|
|
18730
|
+
);
|
|
18731
|
+
}
|
|
18732
|
+
classified.add(credentialIndex);
|
|
18733
|
+
endorsementIndices.push(credentialIndex);
|
|
18734
|
+
}
|
|
18735
|
+
if (classified.size !== members.length) {
|
|
18736
|
+
return classificationFailure(
|
|
18737
|
+
"UNCLASSIFIED_VP_MEMBER",
|
|
18738
|
+
"every presentation member must be classified exactly once",
|
|
18739
|
+
["presentation", "verifiableCredential"]
|
|
18740
|
+
);
|
|
18741
|
+
}
|
|
18742
|
+
return {
|
|
18743
|
+
ok: true,
|
|
18744
|
+
classification: { selectedIndices, endorsementIndices, memberCount: members.length }
|
|
18745
|
+
};
|
|
18746
|
+
}, "classifyShareManifest");
|
|
18747
|
+
var SharePayloadValidator = SharePayloadValidatorShape.superRefine((payload, ctx) => {
|
|
18748
|
+
const result = classifyShareManifest(payload);
|
|
18749
|
+
if (!result.ok) {
|
|
18750
|
+
ctx.addIssue({
|
|
18751
|
+
code: "custom",
|
|
18752
|
+
message: result.message,
|
|
18753
|
+
path: result.path,
|
|
18754
|
+
params: { shareLinkCode: result.code }
|
|
18755
|
+
});
|
|
18756
|
+
}
|
|
18757
|
+
});
|
|
18758
|
+
var ShareRecoverySelectionValidator = external_exports.object({
|
|
18759
|
+
ref: external_exports.string().min(1).max(MAX_SHARE_SOURCE_URI_CHARS),
|
|
18760
|
+
order: external_exports.number().int().min(0).max(MAX_SELECTED_CREDENTIALS - 1)
|
|
18761
|
+
}).strict();
|
|
18762
|
+
var ShareRecoveryEndorsementValidator = external_exports.object({ targetRef: external_exports.string().min(1).max(MAX_SHARE_SOURCE_URI_CHARS) }).strict();
|
|
18763
|
+
var ShareRecoveryPlaintextValidator = external_exports.object({
|
|
18764
|
+
protocol: external_exports.literal(SHARE_RECOVERY_PROTOCOL),
|
|
18765
|
+
shareId: ShareLinkIdValidator,
|
|
18766
|
+
ownerProfileId: external_exports.string().min(1).max(128),
|
|
18767
|
+
createdAt: external_exports.iso.datetime(),
|
|
18768
|
+
latest: external_exports.object({ contentVersion: safeVersion, key: ShareContentKeyValidator }).strict(),
|
|
18769
|
+
selection: ShareRecoverySelectionValidator.array().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
18770
|
+
endorsements: ShareRecoveryEndorsementValidator.array().max(MAX_ENDORSEMENTS).default([])
|
|
18771
|
+
}).strict().superRefine((recovery, ctx) => {
|
|
18772
|
+
const orders = /* @__PURE__ */ new Set();
|
|
18773
|
+
recovery.selection.forEach((entry, index) => {
|
|
18774
|
+
if (entry.order >= recovery.selection.length) {
|
|
18775
|
+
ctx.addIssue({
|
|
18776
|
+
code: "custom",
|
|
18777
|
+
message: "order must be within the selection bounds",
|
|
18778
|
+
path: ["selection", index, "order"]
|
|
18779
|
+
});
|
|
18780
|
+
}
|
|
18781
|
+
if (orders.has(entry.order)) {
|
|
18782
|
+
ctx.addIssue({
|
|
18783
|
+
code: "custom",
|
|
18784
|
+
message: "order must be unique within the selection",
|
|
18785
|
+
path: ["selection", index, "order"]
|
|
18786
|
+
});
|
|
18787
|
+
}
|
|
18788
|
+
orders.add(entry.order);
|
|
18789
|
+
});
|
|
18790
|
+
});
|
|
18791
|
+
var ShareOwnerRecoveryValidator = JWEValidator.refine(
|
|
18792
|
+
(value) => utf8ByteLength(JSON.stringify(value)) <= MAX_SHARE_RECOVERY_JWE_BYTES,
|
|
18793
|
+
{ message: `serialized recovery JWE must be at most ${MAX_SHARE_RECOVERY_JWE_BYTES} bytes` }
|
|
18794
|
+
);
|
|
18795
|
+
var ShareLinkStatusValidator = external_exports.enum(["pending", "active", "stopped"]);
|
|
18796
|
+
var ShareContentStateValidator = external_exports.enum(["staging", "finalized", "content_missing"]);
|
|
18797
|
+
var ShareLinkValidator = external_exports.object({
|
|
18798
|
+
id: ShareLinkIdValidator,
|
|
18799
|
+
title: external_exports.string().min(1).max(120),
|
|
18800
|
+
note: external_exports.string().max(500).optional(),
|
|
18801
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
18802
|
+
version: safeVersion,
|
|
18803
|
+
contentVersion: safeVersion,
|
|
18804
|
+
status: ShareLinkStatusValidator,
|
|
18805
|
+
attachmentId: external_exports.string().uuid().nullable().optional(),
|
|
18806
|
+
attachmentChunkCount: external_exports.number().int().min(1).max(16).nullable().optional(),
|
|
18807
|
+
contentState: ShareContentStateValidator,
|
|
18808
|
+
createdAt: external_exports.iso.datetime(),
|
|
18809
|
+
updatedAt: external_exports.iso.datetime(),
|
|
18810
|
+
expiresAt: external_exports.iso.datetime().nullable(),
|
|
18811
|
+
stoppedAt: external_exports.iso.datetime().nullable(),
|
|
18812
|
+
lastViewedAt: external_exports.iso.datetime().nullable(),
|
|
18813
|
+
viewCount: external_exports.number().int().min(0).optional(),
|
|
18814
|
+
passcodeProtected: external_exports.boolean(),
|
|
18815
|
+
notifyOnView: external_exports.boolean(),
|
|
18816
|
+
minorPolicy: external_exports.object({
|
|
18817
|
+
isMinor: external_exports.boolean().nullable(),
|
|
18818
|
+
policyResolved: external_exports.boolean(),
|
|
18819
|
+
defaultExpiryDays: external_exports.union([external_exports.literal(30), external_exports.literal(365)]),
|
|
18820
|
+
viewCountingEnabled: external_exports.boolean()
|
|
18821
|
+
}),
|
|
18822
|
+
/**
|
|
18823
|
+
* Guarded application/API URL for the content. Optional because owner APIs in
|
|
18824
|
+
* D1 have no public resolve/content endpoint yet; it must never be a
|
|
18825
|
+
* LearnCloud object URL or carry a fabricated decryption key.
|
|
18826
|
+
*/
|
|
18827
|
+
contentUrl: external_exports.string().optional()
|
|
18828
|
+
});
|
|
18829
|
+
var clientRequestId = external_exports.string().uuid();
|
|
18830
|
+
var ShareLinkAttachmentValidator = external_exports.object({
|
|
18831
|
+
id: external_exports.string().uuid(),
|
|
18832
|
+
chunkCount: external_exports.number().int().min(1).max(16)
|
|
18833
|
+
}).strict();
|
|
18834
|
+
var attachmentChunkKey = {
|
|
18835
|
+
id: ShareLinkIdValidator,
|
|
18836
|
+
contentVersion: safeVersion,
|
|
18837
|
+
attachmentId: external_exports.string().uuid(),
|
|
18838
|
+
chunkIndex: external_exports.number().int().min(0).max(15)
|
|
18839
|
+
};
|
|
18840
|
+
var ShareLinkAttachmentChunkEnvelopeValidator = ShareEnvelopeValidator.refine(
|
|
18841
|
+
(value) => (decodedBase64UrlByteLength(value.ct) ?? Infinity) <= 256 * 1024 + SHARE_TAG_BYTES
|
|
18842
|
+
);
|
|
18843
|
+
var PutShareLinkAttachmentChunkInputValidator = external_exports.object({
|
|
18844
|
+
...attachmentChunkKey,
|
|
18845
|
+
chunkCount: external_exports.number().int().min(1).max(16),
|
|
18846
|
+
envelope: ShareLinkAttachmentChunkEnvelopeValidator,
|
|
18847
|
+
ownerEncryptedRecovery: ShareOwnerRecoveryValidator
|
|
18848
|
+
}).strict().refine((value) => value.chunkIndex < value.chunkCount);
|
|
18849
|
+
var GetShareLinkAttachmentChunkInputValidator = external_exports.object({
|
|
18850
|
+
...attachmentChunkKey,
|
|
18851
|
+
passcode: external_exports.string().min(4).max(64).optional(),
|
|
18852
|
+
accessToken: external_exports.string().min(1).max(2048).optional()
|
|
18853
|
+
}).strict();
|
|
18854
|
+
var ShareLinkAttachmentChunkOutputValidator = external_exports.object({
|
|
18855
|
+
...attachmentChunkKey,
|
|
18856
|
+
envelope: ShareLinkAttachmentChunkEnvelopeValidator,
|
|
18857
|
+
accessToken: external_exports.string().min(1).max(2048).optional()
|
|
18858
|
+
}).strict();
|
|
18859
|
+
var DeleteShareLinkAttachmentChunksInputValidator = external_exports.object({
|
|
18860
|
+
id: ShareLinkIdValidator,
|
|
18861
|
+
contentVersion: safeVersion,
|
|
18862
|
+
attachmentId: external_exports.string().uuid(),
|
|
18863
|
+
chunkCount: external_exports.number().int().min(1).max(16)
|
|
18864
|
+
}).strict();
|
|
18865
|
+
var PutShareLinkAttachmentChunkOutputValidator = external_exports.object({ ok: external_exports.literal(true) }).strict();
|
|
18866
|
+
var DeleteShareLinkAttachmentChunksOutputValidator = external_exports.object({ ok: external_exports.boolean() }).strict();
|
|
18867
|
+
var CreateShareLinkInputValidator = external_exports.object({
|
|
18868
|
+
id: ShareLinkIdValidator,
|
|
18869
|
+
clientRequestId,
|
|
18870
|
+
title: external_exports.string().min(1).max(120),
|
|
18871
|
+
note: external_exports.string().max(500).optional(),
|
|
18872
|
+
expiresAt: external_exports.iso.datetime().nullable().optional(),
|
|
18873
|
+
passcode: external_exports.string().min(8).max(64).optional(),
|
|
18874
|
+
notifyOnView: external_exports.boolean().default(false),
|
|
18875
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
18876
|
+
contentVersion: external_exports.literal(1),
|
|
18877
|
+
envelope: ShareEnvelopeValidator,
|
|
18878
|
+
ownerEncryptedRecovery: ShareOwnerRecoveryValidator,
|
|
18879
|
+
attachment: ShareLinkAttachmentValidator.optional()
|
|
18880
|
+
}).strict();
|
|
18881
|
+
var UpdateShareLinkInputValidator = external_exports.object({
|
|
18882
|
+
id: ShareLinkIdValidator,
|
|
18883
|
+
expectedVersion: safeVersion,
|
|
18884
|
+
clientRequestId,
|
|
18885
|
+
title: external_exports.string().min(1).max(120).optional(),
|
|
18886
|
+
note: external_exports.string().max(500).nullable().optional(),
|
|
18887
|
+
expiresAt: external_exports.iso.datetime().nullable().optional(),
|
|
18888
|
+
/** Omitted preserves the current passcode, null removes it, and a string replaces it. */
|
|
18889
|
+
passcode: external_exports.string().min(8).max(64).nullable().optional(),
|
|
18890
|
+
notifyOnView: external_exports.boolean().optional(),
|
|
18891
|
+
contentVersion: safeVersion.optional(),
|
|
18892
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS).optional(),
|
|
18893
|
+
envelope: ShareEnvelopeValidator.optional(),
|
|
18894
|
+
ownerEncryptedRecovery: ShareOwnerRecoveryValidator.optional(),
|
|
18895
|
+
attachment: ShareLinkAttachmentValidator.optional()
|
|
18896
|
+
}).strict().superRefine((value, ctx) => {
|
|
18897
|
+
const provided = [
|
|
18898
|
+
value.contentVersion,
|
|
18899
|
+
value.selectedCount,
|
|
18900
|
+
value.envelope,
|
|
18901
|
+
value.ownerEncryptedRecovery
|
|
18902
|
+
].filter((field) => field !== void 0).length;
|
|
18903
|
+
if (provided !== 0 && provided !== 4) {
|
|
18904
|
+
ctx.addIssue({
|
|
18905
|
+
code: "custom",
|
|
18906
|
+
message: "content replacement requires contentVersion, selectedCount, envelope and ownerEncryptedRecovery together"
|
|
18907
|
+
});
|
|
18908
|
+
}
|
|
18909
|
+
if (value.attachment !== void 0 && provided !== 4) {
|
|
18910
|
+
ctx.addIssue({ code: "custom", message: "attachment requires a content replacement" });
|
|
18911
|
+
}
|
|
18912
|
+
});
|
|
18913
|
+
var ShareLinkIdInputValidator = external_exports.object({ id: ShareLinkIdValidator }).strict();
|
|
18914
|
+
var ShareLinkOperationKeyInputValidator = external_exports.object({ id: ShareLinkIdValidator, operationId: external_exports.string().uuid() }).strict();
|
|
18915
|
+
var ShareLinkOwnerCommitOutputValidator = external_exports.discriminatedUnion("status", [
|
|
18916
|
+
external_exports.object({ status: external_exports.literal("completed"), share: ShareLinkValidator }).strict(),
|
|
18917
|
+
external_exports.object({
|
|
18918
|
+
status: external_exports.literal("pending"),
|
|
18919
|
+
id: ShareLinkIdValidator,
|
|
18920
|
+
operationId: external_exports.string().uuid()
|
|
18921
|
+
}).strict()
|
|
18922
|
+
]);
|
|
18923
|
+
var ShareLinkOwnerStatusOutputValidator = external_exports.discriminatedUnion("status", [
|
|
18924
|
+
external_exports.object({ status: external_exports.literal("found"), share: ShareLinkValidator }).strict(),
|
|
18925
|
+
external_exports.object({
|
|
18926
|
+
status: external_exports.literal("pending"),
|
|
18927
|
+
id: ShareLinkIdValidator,
|
|
18928
|
+
operationId: external_exports.string().uuid()
|
|
18929
|
+
}).strict(),
|
|
18930
|
+
external_exports.object({ status: external_exports.literal("not_found"), id: ShareLinkIdValidator }).strict()
|
|
18931
|
+
]);
|
|
18932
|
+
var ShareLinkOwnerRecoveryOutputValidator = external_exports.object({ recovery: ShareOwnerRecoveryValidator }).strict();
|
|
18933
|
+
var ShareLinkOwnerContentOutputValidator = external_exports.object({
|
|
18934
|
+
id: ShareLinkIdValidator,
|
|
18935
|
+
contentVersion: safeVersion,
|
|
18936
|
+
envelope: ShareEnvelopeValidator
|
|
18937
|
+
}).strict();
|
|
18938
|
+
var ResolveShareLinkInputValidator = external_exports.object({
|
|
18939
|
+
id: ShareLinkIdValidator,
|
|
18940
|
+
/** Sent only in a POST body; it must never be placed in a share URL. */
|
|
18941
|
+
passcode: external_exports.string().min(4).max(64).optional()
|
|
18942
|
+
}).strict();
|
|
18943
|
+
var ShareLinkPublicStateValidator = external_exports.discriminatedUnion("state", [
|
|
18944
|
+
external_exports.object({
|
|
18945
|
+
state: external_exports.literal("passcode_required"),
|
|
18946
|
+
id: ShareLinkIdValidator
|
|
18947
|
+
}).strict(),
|
|
18948
|
+
external_exports.object({ state: external_exports.literal("try_later"), id: ShareLinkIdValidator }).strict(),
|
|
18949
|
+
external_exports.object({
|
|
18950
|
+
state: external_exports.literal("active"),
|
|
18951
|
+
id: ShareLinkIdValidator,
|
|
18952
|
+
title: external_exports.string().max(120),
|
|
18953
|
+
note: external_exports.string().max(500).optional(),
|
|
18954
|
+
selectedCount: external_exports.number().int().min(1).max(MAX_SELECTED_CREDENTIALS),
|
|
18955
|
+
contentVersion: safeVersion,
|
|
18956
|
+
contentUrl: external_exports.string(),
|
|
18957
|
+
sharer: external_exports.object({
|
|
18958
|
+
displayName: external_exports.string().max(120),
|
|
18959
|
+
avatar: external_exports.string().max(2048).optional()
|
|
18960
|
+
}),
|
|
18961
|
+
createdAt: external_exports.iso.datetime(),
|
|
18962
|
+
updatedAt: external_exports.iso.datetime(),
|
|
18963
|
+
expiresAt: external_exports.iso.datetime().nullable()
|
|
18964
|
+
}).strict(),
|
|
18965
|
+
external_exports.object({
|
|
18966
|
+
state: external_exports.literal("expired"),
|
|
18967
|
+
id: ShareLinkIdValidator,
|
|
18968
|
+
expiresAt: external_exports.iso.datetime()
|
|
18969
|
+
}).strict(),
|
|
18970
|
+
external_exports.object({
|
|
18971
|
+
state: external_exports.literal("stopped"),
|
|
18972
|
+
id: ShareLinkIdValidator,
|
|
18973
|
+
stoppedAt: external_exports.iso.datetime()
|
|
18974
|
+
}).strict(),
|
|
18975
|
+
external_exports.object({ state: external_exports.literal("not_found"), id: ShareLinkIdValidator }).strict()
|
|
18976
|
+
]);
|
|
18977
|
+
var ListShareLinksInputValidator = external_exports.object({
|
|
18978
|
+
limit: external_exports.number().int().min(1).max(50).default(25),
|
|
18979
|
+
cursor: external_exports.string().max(512).optional()
|
|
18980
|
+
}).strict();
|
|
18981
|
+
var PaginatedShareLinksValidator = PaginationResponseValidator.extend({
|
|
18982
|
+
records: ShareLinkValidator.array()
|
|
18983
|
+
});
|
|
18984
|
+
var AcknowledgeViewInputValidator = external_exports.object({
|
|
18985
|
+
receipt: external_exports.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/)
|
|
18986
|
+
}).strict();
|
|
18987
|
+
var AcknowledgeViewOutputValidator = external_exports.object({ ok: external_exports.literal(true) }).strict();
|
|
18988
|
+
var SHARE_VIEW_RECEIPT_TTL_SECONDS = 10 * 60;
|
|
18989
|
+
var ShareLinkPublicContentViewValidator = external_exports.object({
|
|
18990
|
+
id: ShareLinkIdValidator,
|
|
18991
|
+
contentVersion: safeVersion,
|
|
18992
|
+
envelope: ShareEnvelopeValidator,
|
|
18993
|
+
contentUrl: external_exports.string(),
|
|
18994
|
+
receipt: external_exports.string().min(22).max(128).regex(/^[A-Za-z0-9_-]+$/)
|
|
18995
|
+
}).strict();
|
|
18128
18996
|
}
|
|
18129
18997
|
});
|
|
18130
18998
|
|
|
@@ -18141,6 +19009,10 @@ var require_dist = __commonJS({
|
|
|
18141
19009
|
});
|
|
18142
19010
|
|
|
18143
19011
|
// src/api-client.ts
|
|
19012
|
+
var DID_CHALLENGE_REQUIRED_ERROR = "This operation requires the DID-challenge flow; use createSSSStrategy";
|
|
19013
|
+
var throwDidChallengeRequired = /* @__PURE__ */ __name(() => {
|
|
19014
|
+
throw new Error(DID_CHALLENGE_REQUIRED_ERROR);
|
|
19015
|
+
}, "throwDidChallengeRequired");
|
|
18144
19016
|
var SSSApiClient = class {
|
|
18145
19017
|
static {
|
|
18146
19018
|
__name(this, "SSSApiClient");
|
|
@@ -18153,20 +19025,9 @@ var SSSApiClient = class {
|
|
|
18153
19025
|
const token = await this.authProvider.getIdToken();
|
|
18154
19026
|
return {
|
|
18155
19027
|
"Content-Type": "application/json",
|
|
18156
|
-
|
|
19028
|
+
"X-Auth-Token": token
|
|
18157
19029
|
};
|
|
18158
19030
|
}
|
|
18159
|
-
async getContactMethodFromUser() {
|
|
18160
|
-
const user = await this.authProvider.getCurrentUser();
|
|
18161
|
-
if (!user) return null;
|
|
18162
|
-
if (user.email) {
|
|
18163
|
-
return { type: "email", value: user.email.toLowerCase() };
|
|
18164
|
-
}
|
|
18165
|
-
if (user.phone) {
|
|
18166
|
-
return { type: "phone", value: user.phone };
|
|
18167
|
-
}
|
|
18168
|
-
return null;
|
|
18169
|
-
}
|
|
18170
19031
|
async getAuthShare() {
|
|
18171
19032
|
const headers = await this.getAuthHeaders();
|
|
18172
19033
|
const providerType = this.authProvider.getProviderType();
|
|
@@ -18183,52 +19044,24 @@ var SSSApiClient = class {
|
|
|
18183
19044
|
}
|
|
18184
19045
|
return response.json();
|
|
18185
19046
|
}
|
|
18186
|
-
|
|
18187
|
-
|
|
18188
|
-
|
|
18189
|
-
const response = await fetch(`${this.serverUrl}/keys/auth-share`, {
|
|
18190
|
-
method: "PUT",
|
|
18191
|
-
headers,
|
|
18192
|
-
body: JSON.stringify({
|
|
18193
|
-
...input,
|
|
18194
|
-
providerType
|
|
18195
|
-
})
|
|
18196
|
-
});
|
|
18197
|
-
if (!response.ok) {
|
|
18198
|
-
throw new Error(`Failed to store auth share: ${response.statusText}`);
|
|
18199
|
-
}
|
|
19047
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19048
|
+
async storeAuthShare(_input) {
|
|
19049
|
+
throwDidChallengeRequired();
|
|
18200
19050
|
}
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18204
|
-
const response = await fetch(`${this.serverUrl}/keys/recovery`, {
|
|
18205
|
-
method: "POST",
|
|
18206
|
-
headers,
|
|
18207
|
-
body: JSON.stringify({
|
|
18208
|
-
...input,
|
|
18209
|
-
providerType
|
|
18210
|
-
})
|
|
18211
|
-
});
|
|
18212
|
-
if (!response.ok) {
|
|
18213
|
-
throw new Error(`Failed to add recovery method: ${response.statusText}`);
|
|
18214
|
-
}
|
|
19051
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19052
|
+
async addRecoveryMethod(_input) {
|
|
19053
|
+
throwDidChallengeRequired();
|
|
18215
19054
|
}
|
|
18216
19055
|
async getRecoveryShare(type, credentialId) {
|
|
18217
19056
|
const token = await this.authProvider.getIdToken();
|
|
18218
19057
|
const providerType = this.authProvider.getProviderType();
|
|
18219
|
-
const params = new URLSearchParams({
|
|
18220
|
-
type,
|
|
18221
|
-
providerType,
|
|
18222
|
-
authToken: token
|
|
18223
|
-
});
|
|
19058
|
+
const params = new URLSearchParams({ type, providerType });
|
|
18224
19059
|
if (credentialId) {
|
|
18225
19060
|
params.append("credentialId", credentialId);
|
|
18226
19061
|
}
|
|
18227
19062
|
const response = await fetch(`${this.serverUrl}/keys/recovery?${params}`, {
|
|
18228
19063
|
method: "GET",
|
|
18229
|
-
headers: {
|
|
18230
|
-
"Content-Type": "application/json"
|
|
18231
|
-
}
|
|
19064
|
+
headers: { "Content-Type": "application/json", "X-Auth-Token": token }
|
|
18232
19065
|
});
|
|
18233
19066
|
if (!response.ok) {
|
|
18234
19067
|
if (response.status === 404) {
|
|
@@ -18238,81 +19071,81 @@ var SSSApiClient = class {
|
|
|
18238
19071
|
}
|
|
18239
19072
|
return response.json();
|
|
18240
19073
|
}
|
|
18241
|
-
async
|
|
18242
|
-
const
|
|
18243
|
-
const providerType = this.authProvider.getProviderType();
|
|
18244
|
-
const response = await fetch(`${this.serverUrl}/keys/migrate`, {
|
|
19074
|
+
async startIdentityRecovery(email) {
|
|
19075
|
+
const response = await fetch(`${this.serverUrl}/keys/recovery-session/start`, {
|
|
18245
19076
|
method: "POST",
|
|
18246
|
-
headers,
|
|
18247
|
-
body: JSON.stringify({
|
|
19077
|
+
headers: { "Content-Type": "application/json" },
|
|
19078
|
+
body: JSON.stringify({ email })
|
|
18248
19079
|
});
|
|
18249
19080
|
if (!response.ok) {
|
|
18250
|
-
throw new Error(`Failed to
|
|
19081
|
+
throw new Error(`Failed to send recovery code: ${response.statusText}`);
|
|
18251
19082
|
}
|
|
18252
19083
|
}
|
|
18253
|
-
async
|
|
18254
|
-
const
|
|
18255
|
-
const providerType = this.authProvider.getProviderType();
|
|
18256
|
-
let email = overrideEmail;
|
|
18257
|
-
if (!email) {
|
|
18258
|
-
const user = await this.authProvider.getCurrentUser();
|
|
18259
|
-
email = user?.email;
|
|
18260
|
-
}
|
|
18261
|
-
if (!email) {
|
|
18262
|
-
console.warn("Cannot send email backup share: no email address available");
|
|
18263
|
-
return;
|
|
18264
|
-
}
|
|
18265
|
-
const response = await fetch(`${this.serverUrl}/keys/email-backup`, {
|
|
19084
|
+
async verifyIdentityRecovery(email, code) {
|
|
19085
|
+
const response = await fetch(`${this.serverUrl}/keys/recovery-session/verify`, {
|
|
18266
19086
|
method: "POST",
|
|
18267
|
-
headers,
|
|
18268
|
-
body: JSON.stringify({
|
|
18269
|
-
providerType,
|
|
18270
|
-
emailShare,
|
|
18271
|
-
email
|
|
18272
|
-
})
|
|
19087
|
+
headers: { "Content-Type": "application/json" },
|
|
19088
|
+
body: JSON.stringify({ email, code })
|
|
18273
19089
|
});
|
|
18274
19090
|
if (!response.ok) {
|
|
18275
|
-
|
|
19091
|
+
throw new Error(`Failed to verify recovery code: ${response.statusText}`);
|
|
18276
19092
|
}
|
|
19093
|
+
return response.json();
|
|
18277
19094
|
}
|
|
18278
|
-
async
|
|
18279
|
-
const
|
|
18280
|
-
const providerType = this.authProvider.getProviderType();
|
|
18281
|
-
const response = await fetch(`${this.serverUrl}/keys/recovery-email/add`, {
|
|
19095
|
+
async useIdentityRecoverySession(recoverySessionToken, type, credentialId) {
|
|
19096
|
+
const response = await fetch(`${this.serverUrl}/keys/recovery-session/recover`, {
|
|
18282
19097
|
method: "POST",
|
|
18283
19098
|
headers: { "Content-Type": "application/json" },
|
|
18284
|
-
body: JSON.stringify({
|
|
19099
|
+
body: JSON.stringify({ recoverySessionToken, type, credentialId })
|
|
18285
19100
|
});
|
|
18286
19101
|
if (!response.ok) {
|
|
18287
|
-
|
|
18288
|
-
throw new Error(data?.message || `Failed to add recovery email: ${response.statusText}`);
|
|
19102
|
+
throw new Error(`Failed to retrieve recovery data: ${response.statusText}`);
|
|
18289
19103
|
}
|
|
19104
|
+
return response.json();
|
|
18290
19105
|
}
|
|
18291
|
-
async
|
|
18292
|
-
const
|
|
18293
|
-
const providerType = this.authProvider.getProviderType();
|
|
18294
|
-
const response = await fetch(`${this.serverUrl}/keys/recovery-email/verify`, {
|
|
19106
|
+
async completeIdentityRecoveryRebind(input) {
|
|
19107
|
+
const response = await fetch(`${this.serverUrl}/keys/recovery-session/rebind`, {
|
|
18295
19108
|
method: "POST",
|
|
18296
|
-
headers: {
|
|
18297
|
-
|
|
19109
|
+
headers: {
|
|
19110
|
+
"Content-Type": "application/json",
|
|
19111
|
+
Authorization: `Bearer ${input.didAuthVp}`,
|
|
19112
|
+
"X-Auth-Token": input.newAuthToken
|
|
19113
|
+
},
|
|
19114
|
+
body: JSON.stringify({
|
|
19115
|
+
recoverySessionToken: input.recoverySessionToken,
|
|
19116
|
+
providerType: input.providerType,
|
|
19117
|
+
primaryDid: input.primaryDid,
|
|
19118
|
+
authShare: input.authShare
|
|
19119
|
+
})
|
|
18298
19120
|
});
|
|
18299
19121
|
if (!response.ok) {
|
|
18300
|
-
|
|
18301
|
-
throw new Error(data?.message || `Failed to verify recovery email: ${response.statusText}`);
|
|
19122
|
+
throw new Error(`Failed to bind the new sign-in: ${response.statusText}`);
|
|
18302
19123
|
}
|
|
18303
19124
|
return response.json();
|
|
18304
19125
|
}
|
|
19126
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19127
|
+
async markMigrated() {
|
|
19128
|
+
throwDidChallengeRequired();
|
|
19129
|
+
}
|
|
19130
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19131
|
+
async activate() {
|
|
19132
|
+
throwDidChallengeRequired();
|
|
19133
|
+
}
|
|
19134
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19135
|
+
async sendEmailBackupShare(_emailShare, _overrideEmail) {
|
|
19136
|
+
throwDidChallengeRequired();
|
|
19137
|
+
}
|
|
19138
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19139
|
+
async addRecoveryEmail(_email) {
|
|
19140
|
+
throwDidChallengeRequired();
|
|
19141
|
+
}
|
|
19142
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
19143
|
+
async verifyRecoveryEmail(_code) {
|
|
19144
|
+
return throwDidChallengeRequired();
|
|
19145
|
+
}
|
|
19146
|
+
/** @deprecated Requires DID-challenge authorization. Use `createSSSStrategy`. */
|
|
18305
19147
|
async deleteUserKey() {
|
|
18306
|
-
|
|
18307
|
-
const providerType = this.authProvider.getProviderType();
|
|
18308
|
-
const response = await fetch(`${this.serverUrl}/keys`, {
|
|
18309
|
-
method: "DELETE",
|
|
18310
|
-
headers,
|
|
18311
|
-
body: JSON.stringify({ providerType })
|
|
18312
|
-
});
|
|
18313
|
-
if (!response.ok) {
|
|
18314
|
-
throw new Error(`Failed to delete user key: ${response.statusText}`);
|
|
18315
|
-
}
|
|
19148
|
+
throwDidChallengeRequired();
|
|
18316
19149
|
}
|
|
18317
19150
|
};
|
|
18318
19151
|
|
|
@@ -18332,33 +19165,33 @@ var DEFAULT_KDF_PARAMS = {
|
|
|
18332
19165
|
parallelism: ARGON2_PARALLELISM
|
|
18333
19166
|
};
|
|
18334
19167
|
function bufferToBase64(buf) {
|
|
18335
|
-
const
|
|
19168
|
+
const bytes2 = new Uint8Array(buf);
|
|
18336
19169
|
let binary = "";
|
|
18337
|
-
for (let i = 0; i <
|
|
18338
|
-
binary += String.fromCharCode(
|
|
19170
|
+
for (let i = 0; i < bytes2.byteLength; i++) {
|
|
19171
|
+
binary += String.fromCharCode(bytes2[i]);
|
|
18339
19172
|
}
|
|
18340
19173
|
return btoa(binary);
|
|
18341
19174
|
}
|
|
18342
19175
|
__name(bufferToBase64, "bufferToBase64");
|
|
18343
19176
|
function base64ToBuffer(b64) {
|
|
18344
19177
|
const binary = atob(b64);
|
|
18345
|
-
const
|
|
19178
|
+
const bytes2 = new Uint8Array(binary.length);
|
|
18346
19179
|
for (let i = 0; i < binary.length; i++) {
|
|
18347
|
-
|
|
19180
|
+
bytes2[i] = binary.charCodeAt(i);
|
|
18348
19181
|
}
|
|
18349
|
-
return
|
|
19182
|
+
return bytes2;
|
|
18350
19183
|
}
|
|
18351
19184
|
__name(base64ToBuffer, "base64ToBuffer");
|
|
18352
|
-
function hexToBytes(
|
|
18353
|
-
const
|
|
18354
|
-
for (let i = 0; i <
|
|
18355
|
-
|
|
19185
|
+
function hexToBytes(hex2) {
|
|
19186
|
+
const bytes2 = new Uint8Array(hex2.length / 2);
|
|
19187
|
+
for (let i = 0; i < hex2.length; i += 2) {
|
|
19188
|
+
bytes2[i / 2] = parseInt(hex2.slice(i, i + 2), 16);
|
|
18356
19189
|
}
|
|
18357
|
-
return
|
|
19190
|
+
return bytes2;
|
|
18358
19191
|
}
|
|
18359
19192
|
__name(hexToBytes, "hexToBytes");
|
|
18360
|
-
function bytesToHex(
|
|
18361
|
-
return Array.from(
|
|
19193
|
+
function bytesToHex(bytes2) {
|
|
19194
|
+
return Array.from(bytes2).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
18362
19195
|
}
|
|
18363
19196
|
__name(bytesToHex, "bytesToHex");
|
|
18364
19197
|
async function deriveKeyFromPassword(password, salt, params = DEFAULT_KDF_PARAMS) {
|
|
@@ -18507,11 +19340,10 @@ async function getOrCreateMasterKey() {
|
|
|
18507
19340
|
(s) => s.get("master-key")
|
|
18508
19341
|
);
|
|
18509
19342
|
if (existing) return existing;
|
|
18510
|
-
const key = await crypto.subtle.generateKey(
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
);
|
|
19343
|
+
const key = await crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, false, [
|
|
19344
|
+
"encrypt",
|
|
19345
|
+
"decrypt"
|
|
19346
|
+
]);
|
|
18515
19347
|
await tx(db, KEYS_STORE, "readwrite", (s) => s.put(key, "master-key"));
|
|
18516
19348
|
return key;
|
|
18517
19349
|
} finally {
|
|
@@ -18526,21 +19358,21 @@ async function getOrCreateMasterKey() {
|
|
|
18526
19358
|
}
|
|
18527
19359
|
__name(getOrCreateMasterKey, "getOrCreateMasterKey");
|
|
18528
19360
|
function bufferToBase642(buf) {
|
|
18529
|
-
const
|
|
19361
|
+
const bytes2 = new Uint8Array(buf);
|
|
18530
19362
|
let binary = "";
|
|
18531
|
-
for (let i = 0; i <
|
|
18532
|
-
binary += String.fromCharCode(
|
|
19363
|
+
for (let i = 0; i < bytes2.byteLength; i++) {
|
|
19364
|
+
binary += String.fromCharCode(bytes2[i]);
|
|
18533
19365
|
}
|
|
18534
19366
|
return btoa(binary);
|
|
18535
19367
|
}
|
|
18536
19368
|
__name(bufferToBase642, "bufferToBase64");
|
|
18537
19369
|
function base64ToBuffer2(b64) {
|
|
18538
19370
|
const binary = atob(b64);
|
|
18539
|
-
const
|
|
19371
|
+
const bytes2 = new Uint8Array(binary.length);
|
|
18540
19372
|
for (let i = 0; i < binary.length; i++) {
|
|
18541
|
-
|
|
19373
|
+
bytes2[i] = binary.charCodeAt(i);
|
|
18542
19374
|
}
|
|
18543
|
-
return
|
|
19375
|
+
return bytes2.buffer;
|
|
18544
19376
|
}
|
|
18545
19377
|
__name(base64ToBuffer2, "base64ToBuffer");
|
|
18546
19378
|
async function encryptShare(share, id) {
|
|
@@ -18612,12 +19444,7 @@ __name(getShareVersion, "getShareVersion");
|
|
|
18612
19444
|
async function getDeviceShare(id = DEFAULT_DEVICE_SHARE_ID) {
|
|
18613
19445
|
const db = await openDB();
|
|
18614
19446
|
try {
|
|
18615
|
-
const raw = await tx(
|
|
18616
|
-
db,
|
|
18617
|
-
SHARES_STORE,
|
|
18618
|
-
"readonly",
|
|
18619
|
-
(s) => s.get(id)
|
|
18620
|
-
);
|
|
19447
|
+
const raw = await tx(db, SHARES_STORE, "readonly", (s) => s.get(id));
|
|
18621
19448
|
if (raw == null) {
|
|
18622
19449
|
return null;
|
|
18623
19450
|
}
|
|
@@ -18676,7 +19503,9 @@ async function listAllDeviceShares() {
|
|
|
18676
19503
|
try {
|
|
18677
19504
|
const share = await getDeviceShare(id);
|
|
18678
19505
|
if (!share) {
|
|
18679
|
-
console.warn(
|
|
19506
|
+
console.warn(
|
|
19507
|
+
`SSS Storage: removing orphaned entry that failed to decrypt: ${id}`
|
|
19508
|
+
);
|
|
18680
19509
|
await deleteDeviceShare(id);
|
|
18681
19510
|
continue;
|
|
18682
19511
|
}
|
|
@@ -18760,6 +19589,7 @@ function createAdaptiveStorage() {
|
|
|
18760
19589
|
getDeviceShare: /* @__PURE__ */ __name((id) => isPublicComputerMode() ? sessionGetDeviceShare(id) : getDeviceShare(id), "getDeviceShare"),
|
|
18761
19590
|
hasDeviceShare: /* @__PURE__ */ __name((id) => isPublicComputerMode() ? sessionHasDeviceShare(id) : hasDeviceShare(id), "hasDeviceShare"),
|
|
18762
19591
|
clearAllShares: /* @__PURE__ */ __name((id) => isPublicComputerMode() ? sessionClearAllShares(id) : clearAllShares(id), "clearAllShares"),
|
|
19592
|
+
deleteDeviceShare: /* @__PURE__ */ __name((id) => isPublicComputerMode() ? sessionDeleteDeviceShare(id) : deleteDeviceShare(id), "deleteDeviceShare"),
|
|
18763
19593
|
storeShareVersion: /* @__PURE__ */ __name((version, id) => isPublicComputerMode() ? sessionStoreShareVersion(version, id) : storeShareVersion(version, id), "storeShareVersion"),
|
|
18764
19594
|
getShareVersion: /* @__PURE__ */ __name((id) => isPublicComputerMode() ? sessionGetShareVersion(id) : getShareVersion(id), "getShareVersion")
|
|
18765
19595
|
};
|
|
@@ -18950,16 +19780,16 @@ async function getWordlist() {
|
|
|
18950
19780
|
return wordlistPromise;
|
|
18951
19781
|
}
|
|
18952
19782
|
__name(getWordlist, "getWordlist");
|
|
18953
|
-
function bytesToBits(
|
|
18954
|
-
return Array.from(
|
|
19783
|
+
function bytesToBits(bytes2) {
|
|
19784
|
+
return Array.from(bytes2).map((b) => b.toString(2).padStart(8, "0")).join("");
|
|
18955
19785
|
}
|
|
18956
19786
|
__name(bytesToBits, "bytesToBits");
|
|
18957
19787
|
function bitsToBytes(bits) {
|
|
18958
|
-
const
|
|
18959
|
-
for (let i = 0; i <
|
|
18960
|
-
|
|
19788
|
+
const bytes2 = new Uint8Array(Math.ceil(bits.length / 8));
|
|
19789
|
+
for (let i = 0; i < bytes2.length; i++) {
|
|
19790
|
+
bytes2[i] = parseInt(bits.slice(i * 8, (i + 1) * 8).padEnd(8, "0"), 2);
|
|
18961
19791
|
}
|
|
18962
|
-
return
|
|
19792
|
+
return bytes2;
|
|
18963
19793
|
}
|
|
18964
19794
|
__name(bitsToBytes, "bitsToBytes");
|
|
18965
19795
|
async function computeChecksum(data) {
|
|
@@ -18997,12 +19827,12 @@ async function recoveryPhraseToShare(phrase) {
|
|
|
18997
19827
|
bits += index.toString(2).padStart(11, "0");
|
|
18998
19828
|
}
|
|
18999
19829
|
let dataByteCount = 0;
|
|
19000
|
-
for (let
|
|
19001
|
-
const checksumBits2 = Math.floor(
|
|
19002
|
-
const totalBits =
|
|
19830
|
+
for (let bytes2 = 1; bytes2 <= 64; bytes2++) {
|
|
19831
|
+
const checksumBits2 = Math.floor(bytes2 / 4);
|
|
19832
|
+
const totalBits = bytes2 * 8 + checksumBits2;
|
|
19003
19833
|
const wordsNeeded = Math.ceil(totalBits / 11);
|
|
19004
19834
|
if (wordsNeeded === words.length) {
|
|
19005
|
-
dataByteCount =
|
|
19835
|
+
dataByteCount = bytes2;
|
|
19006
19836
|
} else if (wordsNeeded > words.length) {
|
|
19007
19837
|
break;
|
|
19008
19838
|
}
|
|
@@ -19040,6 +19870,33 @@ function countWords(phrase) {
|
|
|
19040
19870
|
return phrase.trim().split(/\s+/).filter((w) => w.length > 0).length;
|
|
19041
19871
|
}
|
|
19042
19872
|
__name(countWords, "countWords");
|
|
19873
|
+
function randomIndex(max) {
|
|
19874
|
+
const limit = 4294967296 - 4294967296 % max;
|
|
19875
|
+
for (; ; ) {
|
|
19876
|
+
const value = crypto.getRandomValues(new Uint32Array(1))[0];
|
|
19877
|
+
if (value === void 0) throw new Error("Failed to choose recovery phrase words");
|
|
19878
|
+
if (value < limit) return value % max;
|
|
19879
|
+
}
|
|
19880
|
+
}
|
|
19881
|
+
__name(randomIndex, "randomIndex");
|
|
19882
|
+
async function buildRecoveryPhraseChallengeOptions(phrase, challengeWordIndices, optionCount = 6) {
|
|
19883
|
+
const words = phrase.trim().split(/\s+/);
|
|
19884
|
+
const phraseWords = new Set(words);
|
|
19885
|
+
const decoyPool = (await getWordlist()).filter((word) => !phraseWords.has(word));
|
|
19886
|
+
return challengeWordIndices.map((wordIndex) => {
|
|
19887
|
+
const answer = words[wordIndex];
|
|
19888
|
+
if (!answer) throw new Error("Recovery phrase challenge index is out of range");
|
|
19889
|
+
const options = /* @__PURE__ */ new Set([answer]);
|
|
19890
|
+
while (options.size < optionCount) options.add(decoyPool[randomIndex(decoyPool.length)]);
|
|
19891
|
+
const shuffled = [...options];
|
|
19892
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
19893
|
+
const j = randomIndex(i + 1);
|
|
19894
|
+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
19895
|
+
}
|
|
19896
|
+
return shuffled;
|
|
19897
|
+
});
|
|
19898
|
+
}
|
|
19899
|
+
__name(buildRecoveryPhraseChallengeOptions, "buildRecoveryPhraseChallengeOptions");
|
|
19043
19900
|
|
|
19044
19901
|
// src/key-manager.ts
|
|
19045
19902
|
var SSSKeyManager = class {
|
|
@@ -19265,23 +20122,776 @@ function createSSSKeyManager(config) {
|
|
|
19265
20122
|
}
|
|
19266
20123
|
__name(createSSSKeyManager, "createSSSKeyManager");
|
|
19267
20124
|
|
|
19268
|
-
// src/
|
|
19269
|
-
var
|
|
19270
|
-
|
|
19271
|
-
|
|
19272
|
-
|
|
19273
|
-
|
|
19274
|
-
|
|
19275
|
-
|
|
20125
|
+
// src/email-relay-crypto.ts
|
|
20126
|
+
var EMAIL_RELAY_ENVELOPE_VERSION = 1;
|
|
20127
|
+
var EMAIL_RELAY_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
|
|
20128
|
+
var encodeUtf8 = /* @__PURE__ */ __name((value) => {
|
|
20129
|
+
const bytes2 = new TextEncoder().encode(value);
|
|
20130
|
+
const copy = new Uint8Array(new ArrayBuffer(bytes2.byteLength));
|
|
20131
|
+
copy.set(bytes2);
|
|
20132
|
+
return copy;
|
|
20133
|
+
}, "encodeUtf8");
|
|
20134
|
+
var EMAIL_RELAY_INFO = encodeUtf8("learncard-email-relay-v1");
|
|
20135
|
+
var SIX_DIGIT_CODE_RANGE = 9e5;
|
|
20136
|
+
var UINT32_RANGE = 4294967296;
|
|
20137
|
+
var MAX_UNBIASED_UINT32 = Math.floor(UINT32_RANGE / SIX_DIGIT_CODE_RANGE) * SIX_DIGIT_CODE_RANGE;
|
|
20138
|
+
var isRecord = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isRecord");
|
|
20139
|
+
var requireString = /* @__PURE__ */ __name((record, key, options) => {
|
|
20140
|
+
const value = record[key];
|
|
20141
|
+
if (typeof value !== "string" || value.length < (options.min ?? 1) || value.length > options.max || options.pattern && !options.pattern.test(value)) {
|
|
20142
|
+
throw new Error(`Invalid email relay ${key}`);
|
|
19276
20143
|
}
|
|
19277
|
-
|
|
19278
|
-
|
|
20144
|
+
return value;
|
|
20145
|
+
}, "requireString");
|
|
20146
|
+
var parseBranding = /* @__PURE__ */ __name((value) => {
|
|
20147
|
+
if (value === void 0) return void 0;
|
|
20148
|
+
if (!isRecord(value)) throw new Error("Invalid email relay branding");
|
|
20149
|
+
const branding = {};
|
|
20150
|
+
const keys = [
|
|
20151
|
+
"brandName",
|
|
20152
|
+
"logoUrl",
|
|
20153
|
+
"logoAlt",
|
|
20154
|
+
"primaryColor",
|
|
20155
|
+
"primaryTextColor",
|
|
20156
|
+
"supportEmail",
|
|
20157
|
+
"websiteUrl",
|
|
20158
|
+
"appUrl",
|
|
20159
|
+
"fromDomain",
|
|
20160
|
+
"copyrightHolder"
|
|
20161
|
+
];
|
|
20162
|
+
for (const key of keys) {
|
|
20163
|
+
const field = value[key];
|
|
20164
|
+
if (field === void 0) continue;
|
|
20165
|
+
if (typeof field !== "string" || field.length > 2048) {
|
|
20166
|
+
throw new Error(`Invalid email relay branding.${key}`);
|
|
20167
|
+
}
|
|
20168
|
+
branding[key] = field;
|
|
19279
20169
|
}
|
|
19280
|
-
|
|
19281
|
-
|
|
19282
|
-
|
|
19283
|
-
|
|
19284
|
-
|
|
20170
|
+
return branding;
|
|
20171
|
+
}, "parseBranding");
|
|
20172
|
+
var parseEmailRelayEnvelope = /* @__PURE__ */ __name((value) => {
|
|
20173
|
+
if (!isRecord(value)) throw new Error("Invalid email relay envelope");
|
|
20174
|
+
if (value.version !== EMAIL_RELAY_ENVELOPE_VERSION) {
|
|
20175
|
+
throw new Error("Unsupported email relay envelope version");
|
|
20176
|
+
}
|
|
20177
|
+
if (value.algorithm !== EMAIL_RELAY_ALGORITHM) {
|
|
20178
|
+
throw new Error("Unsupported email relay algorithm");
|
|
20179
|
+
}
|
|
20180
|
+
return {
|
|
20181
|
+
version: EMAIL_RELAY_ENVELOPE_VERSION,
|
|
20182
|
+
algorithm: EMAIL_RELAY_ALGORITHM,
|
|
20183
|
+
keyId: requireString(value, "keyId", {
|
|
20184
|
+
max: 128,
|
|
20185
|
+
pattern: /^[A-Za-z0-9._-]+$/
|
|
20186
|
+
}),
|
|
20187
|
+
ephemeralPublicKey: requireString(value, "ephemeralPublicKey", { max: 256 }),
|
|
20188
|
+
salt: requireString(value, "salt", { max: 128 }),
|
|
20189
|
+
iv: requireString(value, "iv", { max: 64 }),
|
|
20190
|
+
ciphertext: requireString(value, "ciphertext", { max: 16384 })
|
|
20191
|
+
};
|
|
20192
|
+
}, "parseEmailRelayEnvelope");
|
|
20193
|
+
var parseEmailRelayPlaintext = /* @__PURE__ */ __name((value) => {
|
|
20194
|
+
if (!isRecord(value) || value.version !== EMAIL_RELAY_ENVELOPE_VERSION) {
|
|
20195
|
+
throw new Error("Invalid email relay plaintext");
|
|
20196
|
+
}
|
|
20197
|
+
return {
|
|
20198
|
+
version: EMAIL_RELAY_ENVELOPE_VERSION,
|
|
20199
|
+
targetEmail: requireString(value, "targetEmail", {
|
|
20200
|
+
max: 320,
|
|
20201
|
+
pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
|
20202
|
+
}).trim().toLowerCase(),
|
|
20203
|
+
recoveryKey: requireString(value, "recoveryKey", {
|
|
20204
|
+
min: 5,
|
|
20205
|
+
max: 4096,
|
|
20206
|
+
pattern: /^[0-9a-f]+$/i
|
|
20207
|
+
}),
|
|
20208
|
+
confirmationCode: requireString(value, "confirmationCode", {
|
|
20209
|
+
max: 6,
|
|
20210
|
+
pattern: /^\d{6}$/
|
|
20211
|
+
}),
|
|
20212
|
+
branding: parseBranding(value.branding)
|
|
20213
|
+
};
|
|
20214
|
+
}, "parseEmailRelayPlaintext");
|
|
20215
|
+
var getAad = /* @__PURE__ */ __name((envelope) => encodeUtf8(`${envelope.version}|${envelope.algorithm}|${envelope.keyId}`), "getAad");
|
|
20216
|
+
var deriveAesKey = /* @__PURE__ */ __name(async (sharedSecret, salt, usage) => {
|
|
20217
|
+
const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
|
|
20218
|
+
"deriveKey"
|
|
20219
|
+
]);
|
|
20220
|
+
return crypto.subtle.deriveKey(
|
|
20221
|
+
{ name: "HKDF", hash: "SHA-256", salt, info: EMAIL_RELAY_INFO },
|
|
20222
|
+
keyMaterial,
|
|
20223
|
+
{ name: "AES-GCM", length: 256 },
|
|
20224
|
+
false,
|
|
20225
|
+
[usage]
|
|
20226
|
+
);
|
|
20227
|
+
}, "deriveAesKey");
|
|
20228
|
+
var generateEmailRelayConfirmationCode = /* @__PURE__ */ __name(() => {
|
|
20229
|
+
const random = new Uint32Array(1);
|
|
20230
|
+
let value;
|
|
20231
|
+
do {
|
|
20232
|
+
crypto.getRandomValues(random);
|
|
20233
|
+
value = random[0] ?? UINT32_RANGE;
|
|
20234
|
+
} while (value >= MAX_UNBIASED_UINT32);
|
|
20235
|
+
return String(1e5 + value % SIX_DIGIT_CODE_RANGE);
|
|
20236
|
+
}, "generateEmailRelayConfirmationCode");
|
|
20237
|
+
var encryptEmailRelayPayload = /* @__PURE__ */ __name(async (input, publicKeyBase64, keyId) => {
|
|
20238
|
+
const plaintext = parseEmailRelayPlaintext({
|
|
20239
|
+
...input,
|
|
20240
|
+
version: EMAIL_RELAY_ENVELOPE_VERSION
|
|
20241
|
+
});
|
|
20242
|
+
const normalizedKeyId = keyId.trim();
|
|
20243
|
+
if (!publicKeyBase64.trim()) throw new Error("Email relay public key is not configured");
|
|
20244
|
+
if (!/^[A-Za-z0-9._-]{1,128}$/.test(normalizedKeyId)) {
|
|
20245
|
+
throw new Error("Email relay key ID is not configured");
|
|
20246
|
+
}
|
|
20247
|
+
const recipientPublicKey = await crypto.subtle.importKey(
|
|
20248
|
+
"spki",
|
|
20249
|
+
base64ToBuffer(publicKeyBase64.trim()).buffer,
|
|
20250
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20251
|
+
false,
|
|
20252
|
+
[]
|
|
20253
|
+
);
|
|
20254
|
+
const ephemeralKeyPair = await crypto.subtle.generateKey(
|
|
20255
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20256
|
+
true,
|
|
20257
|
+
["deriveBits"]
|
|
20258
|
+
);
|
|
20259
|
+
const sharedSecret = await crypto.subtle.deriveBits(
|
|
20260
|
+
{ name: "ECDH", public: recipientPublicKey },
|
|
20261
|
+
ephemeralKeyPair.privateKey,
|
|
20262
|
+
256
|
|
20263
|
+
);
|
|
20264
|
+
const salt = crypto.getRandomValues(new Uint8Array(32));
|
|
20265
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
20266
|
+
const aesKey = await deriveAesKey(sharedSecret, salt, "encrypt");
|
|
20267
|
+
const envelopeMetadata = {
|
|
20268
|
+
version: EMAIL_RELAY_ENVELOPE_VERSION,
|
|
20269
|
+
algorithm: EMAIL_RELAY_ALGORITHM,
|
|
20270
|
+
keyId: normalizedKeyId
|
|
20271
|
+
};
|
|
20272
|
+
const ciphertext = await crypto.subtle.encrypt(
|
|
20273
|
+
{ name: "AES-GCM", iv, additionalData: getAad(envelopeMetadata) },
|
|
20274
|
+
aesKey,
|
|
20275
|
+
encodeUtf8(JSON.stringify(plaintext))
|
|
20276
|
+
);
|
|
20277
|
+
const ephemeralPublicKey = await crypto.subtle.exportKey("raw", ephemeralKeyPair.publicKey);
|
|
20278
|
+
return {
|
|
20279
|
+
...envelopeMetadata,
|
|
20280
|
+
ephemeralPublicKey: bufferToBase64(ephemeralPublicKey),
|
|
20281
|
+
salt: bufferToBase64(salt.buffer),
|
|
20282
|
+
iv: bufferToBase64(iv.buffer),
|
|
20283
|
+
ciphertext: bufferToBase64(ciphertext)
|
|
20284
|
+
};
|
|
20285
|
+
}, "encryptEmailRelayPayload");
|
|
20286
|
+
var decryptEmailRelayPayload = /* @__PURE__ */ __name(async (value, privateKeyBase64) => {
|
|
20287
|
+
const envelope = parseEmailRelayEnvelope(value);
|
|
20288
|
+
const privateKey = await crypto.subtle.importKey(
|
|
20289
|
+
"pkcs8",
|
|
20290
|
+
base64ToBuffer(privateKeyBase64.trim()).buffer,
|
|
20291
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20292
|
+
false,
|
|
20293
|
+
["deriveBits"]
|
|
20294
|
+
);
|
|
20295
|
+
const ephemeralPublicKey = await crypto.subtle.importKey(
|
|
20296
|
+
"raw",
|
|
20297
|
+
base64ToBuffer(envelope.ephemeralPublicKey).buffer,
|
|
20298
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20299
|
+
false,
|
|
20300
|
+
[]
|
|
20301
|
+
);
|
|
20302
|
+
const sharedSecret = await crypto.subtle.deriveBits(
|
|
20303
|
+
{ name: "ECDH", public: ephemeralPublicKey },
|
|
20304
|
+
privateKey,
|
|
20305
|
+
256
|
|
20306
|
+
);
|
|
20307
|
+
const salt = base64ToBuffer(envelope.salt);
|
|
20308
|
+
const iv = base64ToBuffer(envelope.iv);
|
|
20309
|
+
const aesKey = await deriveAesKey(sharedSecret, salt, "decrypt");
|
|
20310
|
+
const decrypted = await crypto.subtle.decrypt(
|
|
20311
|
+
{ name: "AES-GCM", iv, additionalData: getAad(envelope) },
|
|
20312
|
+
aesKey,
|
|
20313
|
+
base64ToBuffer(envelope.ciphertext)
|
|
20314
|
+
);
|
|
20315
|
+
const parsed = JSON.parse(new TextDecoder().decode(decrypted));
|
|
20316
|
+
return parseEmailRelayPlaintext(parsed);
|
|
20317
|
+
}, "decryptEmailRelayPayload");
|
|
20318
|
+
|
|
20319
|
+
// src/escrow-crypto.ts
|
|
20320
|
+
var ESCROW_ENVELOPE_VERSION = 1;
|
|
20321
|
+
var ESCROW_ALGORITHM = "P-256-HKDF-SHA256-AES-256-GCM";
|
|
20322
|
+
var ESCROW_BLOB_INFO = "learncard-escrow-blob-v1";
|
|
20323
|
+
var ESCROW_RELEASE_INFO = "learncard-escrow-release-v1";
|
|
20324
|
+
var ESCROW_CLIENT_KEY_ID = "client";
|
|
20325
|
+
var encodeUtf82 = /* @__PURE__ */ __name((value) => {
|
|
20326
|
+
const bytes2 = new TextEncoder().encode(value);
|
|
20327
|
+
const copy = new Uint8Array(new ArrayBuffer(bytes2.byteLength));
|
|
20328
|
+
copy.set(bytes2);
|
|
20329
|
+
return copy;
|
|
20330
|
+
}, "encodeUtf8");
|
|
20331
|
+
var isRecord2 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isRecord");
|
|
20332
|
+
var requireString2 = /* @__PURE__ */ __name((record, key, options) => {
|
|
20333
|
+
const value = record[key];
|
|
20334
|
+
if (typeof value !== "string" || value.length < (options.min ?? 1) || value.length > options.max || options.pattern && !options.pattern.test(value)) {
|
|
20335
|
+
throw new Error(`Invalid escrow ${key}`);
|
|
20336
|
+
}
|
|
20337
|
+
return value;
|
|
20338
|
+
}, "requireString");
|
|
20339
|
+
var parseEscrowEnvelope = /* @__PURE__ */ __name((value) => {
|
|
20340
|
+
if (!isRecord2(value)) throw new Error("Invalid escrow envelope");
|
|
20341
|
+
if (value.version !== ESCROW_ENVELOPE_VERSION) {
|
|
20342
|
+
throw new Error("Unsupported escrow envelope version");
|
|
20343
|
+
}
|
|
20344
|
+
if (value.algorithm !== ESCROW_ALGORITHM) {
|
|
20345
|
+
throw new Error("Unsupported escrow algorithm");
|
|
20346
|
+
}
|
|
20347
|
+
return {
|
|
20348
|
+
version: ESCROW_ENVELOPE_VERSION,
|
|
20349
|
+
algorithm: ESCROW_ALGORITHM,
|
|
20350
|
+
keyId: requireString2(value, "keyId", { max: 128, pattern: /^[A-Za-z0-9._-]+$/ }),
|
|
20351
|
+
ephemeralPublicKey: requireString2(value, "ephemeralPublicKey", { max: 256 }),
|
|
20352
|
+
salt: requireString2(value, "salt", { max: 128 }),
|
|
20353
|
+
iv: requireString2(value, "iv", { max: 64 }),
|
|
20354
|
+
ciphertext: requireString2(value, "ciphertext", { max: 16384 })
|
|
20355
|
+
};
|
|
20356
|
+
}, "parseEscrowEnvelope");
|
|
20357
|
+
var parseEscrowBlobPlaintext = /* @__PURE__ */ __name((value) => {
|
|
20358
|
+
if (!isRecord2(value) || value.version !== ESCROW_ENVELOPE_VERSION) {
|
|
20359
|
+
throw new Error("Invalid escrow plaintext");
|
|
20360
|
+
}
|
|
20361
|
+
if (typeof value.shareVersion !== "number" || !Number.isInteger(value.shareVersion) || value.shareVersion <= 0) {
|
|
20362
|
+
throw new Error("Invalid escrow shareVersion");
|
|
20363
|
+
}
|
|
20364
|
+
return {
|
|
20365
|
+
version: ESCROW_ENVELOPE_VERSION,
|
|
20366
|
+
recoveryShare: requireString2(value, "recoveryShare", {
|
|
20367
|
+
min: 5,
|
|
20368
|
+
max: 4096,
|
|
20369
|
+
pattern: /^[0-9a-f]+$/i
|
|
20370
|
+
}).toLowerCase(),
|
|
20371
|
+
did: requireString2(value, "did", { max: 2048, pattern: /^did:/ }),
|
|
20372
|
+
shareVersion: value.shareVersion,
|
|
20373
|
+
...value.pinVerifier !== void 0 ? {
|
|
20374
|
+
pinVerifier: requireString2(value, "pinVerifier", {
|
|
20375
|
+
min: 64,
|
|
20376
|
+
max: 64,
|
|
20377
|
+
pattern: /^[0-9a-f]{64}$/i
|
|
20378
|
+
}).toLowerCase()
|
|
20379
|
+
} : {}
|
|
20380
|
+
};
|
|
20381
|
+
}, "parseEscrowBlobPlaintext");
|
|
20382
|
+
var parseEscrowReleasePlaintext = /* @__PURE__ */ __name((value) => {
|
|
20383
|
+
const plaintext = parseEscrowBlobPlaintext(value);
|
|
20384
|
+
if (!isRecord2(value)) throw new Error("Invalid escrow plaintext");
|
|
20385
|
+
return {
|
|
20386
|
+
...plaintext,
|
|
20387
|
+
holdId: requireString2(value, "holdId", { max: 128, pattern: /^[A-Za-z0-9._-]+$/ })
|
|
20388
|
+
};
|
|
20389
|
+
}, "parseEscrowReleasePlaintext");
|
|
20390
|
+
var getAad2 = /* @__PURE__ */ __name((envelope) => encodeUtf82(`${envelope.version}|${envelope.algorithm}|${envelope.keyId}`), "getAad");
|
|
20391
|
+
var deriveAesKey2 = /* @__PURE__ */ __name(async (sharedSecret, salt, usage, info) => {
|
|
20392
|
+
const keyMaterial = await crypto.subtle.importKey("raw", sharedSecret, "HKDF", false, [
|
|
20393
|
+
"deriveKey"
|
|
20394
|
+
]);
|
|
20395
|
+
return crypto.subtle.deriveKey(
|
|
20396
|
+
{ name: "HKDF", hash: "SHA-256", salt, info: encodeUtf82(info) },
|
|
20397
|
+
keyMaterial,
|
|
20398
|
+
{ name: "AES-GCM", length: 256 },
|
|
20399
|
+
false,
|
|
20400
|
+
[usage]
|
|
20401
|
+
);
|
|
20402
|
+
}, "deriveAesKey");
|
|
20403
|
+
var generateEscrowKeyPair = /* @__PURE__ */ __name(async () => {
|
|
20404
|
+
const keyPair = await crypto.subtle.generateKey({ name: "ECDH", namedCurve: "P-256" }, true, [
|
|
20405
|
+
"deriveBits"
|
|
20406
|
+
]);
|
|
20407
|
+
const [publicKey, privateKey] = await Promise.all([
|
|
20408
|
+
crypto.subtle.exportKey("spki", keyPair.publicKey),
|
|
20409
|
+
crypto.subtle.exportKey("pkcs8", keyPair.privateKey)
|
|
20410
|
+
]);
|
|
20411
|
+
return { publicKey: bufferToBase64(publicKey), privateKey: bufferToBase64(privateKey) };
|
|
20412
|
+
}, "generateEscrowKeyPair");
|
|
20413
|
+
var encryptToRecipient = /* @__PURE__ */ __name(async (plaintextJson, spki, keyId, info) => {
|
|
20414
|
+
if (typeof spki !== "string" || !spki.trim()) {
|
|
20415
|
+
throw new Error("Escrow public key is not configured");
|
|
20416
|
+
}
|
|
20417
|
+
const recipientKeyId = requireString2({ keyId }, "keyId", {
|
|
20418
|
+
max: 128,
|
|
20419
|
+
pattern: /^[A-Za-z0-9._-]+$/
|
|
20420
|
+
});
|
|
20421
|
+
const recipientPublicKey = await crypto.subtle.importKey(
|
|
20422
|
+
"spki",
|
|
20423
|
+
base64ToBuffer(spki.trim()),
|
|
20424
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20425
|
+
false,
|
|
20426
|
+
[]
|
|
20427
|
+
);
|
|
20428
|
+
const ephemeralKeyPair = await crypto.subtle.generateKey(
|
|
20429
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20430
|
+
true,
|
|
20431
|
+
["deriveBits"]
|
|
20432
|
+
);
|
|
20433
|
+
const sharedSecret = await crypto.subtle.deriveBits(
|
|
20434
|
+
{ name: "ECDH", public: recipientPublicKey },
|
|
20435
|
+
ephemeralKeyPair.privateKey,
|
|
20436
|
+
256
|
|
20437
|
+
);
|
|
20438
|
+
const salt = crypto.getRandomValues(new Uint8Array(32));
|
|
20439
|
+
const iv = crypto.getRandomValues(new Uint8Array(12));
|
|
20440
|
+
const aesKey = await deriveAesKey2(sharedSecret, salt, "encrypt", info);
|
|
20441
|
+
const metadata = {
|
|
20442
|
+
version: ESCROW_ENVELOPE_VERSION,
|
|
20443
|
+
algorithm: ESCROW_ALGORITHM,
|
|
20444
|
+
keyId: recipientKeyId
|
|
20445
|
+
};
|
|
20446
|
+
const ciphertext = await crypto.subtle.encrypt(
|
|
20447
|
+
{ name: "AES-GCM", iv, additionalData: getAad2(metadata) },
|
|
20448
|
+
aesKey,
|
|
20449
|
+
encodeUtf82(plaintextJson)
|
|
20450
|
+
);
|
|
20451
|
+
const ephemeralPublicKey = await crypto.subtle.exportKey("raw", ephemeralKeyPair.publicKey);
|
|
20452
|
+
return {
|
|
20453
|
+
...metadata,
|
|
20454
|
+
ephemeralPublicKey: bufferToBase64(ephemeralPublicKey),
|
|
20455
|
+
salt: bufferToBase64(salt.buffer),
|
|
20456
|
+
iv: bufferToBase64(iv.buffer),
|
|
20457
|
+
ciphertext: bufferToBase64(ciphertext)
|
|
20458
|
+
};
|
|
20459
|
+
}, "encryptToRecipient");
|
|
20460
|
+
var decryptFromEnvelope = /* @__PURE__ */ __name(async (value, pkcs8, info) => {
|
|
20461
|
+
const envelope = parseEscrowEnvelope(value);
|
|
20462
|
+
const privateKey = await crypto.subtle.importKey(
|
|
20463
|
+
"pkcs8",
|
|
20464
|
+
base64ToBuffer(pkcs8.trim()),
|
|
20465
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20466
|
+
false,
|
|
20467
|
+
["deriveBits"]
|
|
20468
|
+
);
|
|
20469
|
+
const ephemeralPublicKey = await crypto.subtle.importKey(
|
|
20470
|
+
"raw",
|
|
20471
|
+
base64ToBuffer(envelope.ephemeralPublicKey),
|
|
20472
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20473
|
+
false,
|
|
20474
|
+
[]
|
|
20475
|
+
);
|
|
20476
|
+
const sharedSecret = await crypto.subtle.deriveBits(
|
|
20477
|
+
{ name: "ECDH", public: ephemeralPublicKey },
|
|
20478
|
+
privateKey,
|
|
20479
|
+
256
|
|
20480
|
+
);
|
|
20481
|
+
const salt = base64ToBuffer(envelope.salt);
|
|
20482
|
+
const iv = base64ToBuffer(envelope.iv);
|
|
20483
|
+
const aesKey = await deriveAesKey2(sharedSecret, salt, "decrypt", info);
|
|
20484
|
+
const decrypted = await crypto.subtle.decrypt(
|
|
20485
|
+
{ name: "AES-GCM", iv, additionalData: getAad2(envelope) },
|
|
20486
|
+
aesKey,
|
|
20487
|
+
base64ToBuffer(envelope.ciphertext)
|
|
20488
|
+
);
|
|
20489
|
+
const parsed = JSON.parse(new TextDecoder().decode(decrypted));
|
|
20490
|
+
return parsed;
|
|
20491
|
+
}, "decryptFromEnvelope");
|
|
20492
|
+
var encryptEscrowBlob = /* @__PURE__ */ __name(async (input, enclavePublicKeySpkiB64, keyId) => {
|
|
20493
|
+
const plaintext = parseEscrowBlobPlaintext({ ...input, version: ESCROW_ENVELOPE_VERSION });
|
|
20494
|
+
return encryptToRecipient(
|
|
20495
|
+
JSON.stringify(plaintext),
|
|
20496
|
+
enclavePublicKeySpkiB64,
|
|
20497
|
+
keyId,
|
|
20498
|
+
ESCROW_BLOB_INFO
|
|
20499
|
+
);
|
|
20500
|
+
}, "encryptEscrowBlob");
|
|
20501
|
+
var decryptEscrowBlob = /* @__PURE__ */ __name(async (envelope, enclavePrivateKeyPkcs8B64) => parseEscrowBlobPlaintext(
|
|
20502
|
+
await decryptFromEnvelope(envelope, enclavePrivateKeyPkcs8B64, ESCROW_BLOB_INFO)
|
|
20503
|
+
), "decryptEscrowBlob");
|
|
20504
|
+
var sealEscrowRelease = /* @__PURE__ */ __name(async (input, clientEphemeralPublicKeySpkiB64) => {
|
|
20505
|
+
const plaintext = parseEscrowReleasePlaintext({ ...input, version: ESCROW_ENVELOPE_VERSION });
|
|
20506
|
+
return encryptToRecipient(
|
|
20507
|
+
JSON.stringify(plaintext),
|
|
20508
|
+
clientEphemeralPublicKeySpkiB64,
|
|
20509
|
+
ESCROW_CLIENT_KEY_ID,
|
|
20510
|
+
ESCROW_RELEASE_INFO
|
|
20511
|
+
);
|
|
20512
|
+
}, "sealEscrowRelease");
|
|
20513
|
+
var openEscrowRelease = /* @__PURE__ */ __name(async (envelope, clientEphemeralPrivateKeyPkcs8B64) => parseEscrowReleasePlaintext(
|
|
20514
|
+
await decryptFromEnvelope(envelope, clientEphemeralPrivateKeyPkcs8B64, ESCROW_RELEASE_INFO)
|
|
20515
|
+
), "openEscrowRelease");
|
|
20516
|
+
|
|
20517
|
+
// src/escrow-nitro-attestation.ts
|
|
20518
|
+
import "reflect-metadata";
|
|
20519
|
+
import { decode, encode } from "cborg";
|
|
20520
|
+
import {
|
|
20521
|
+
BasicConstraintsExtension,
|
|
20522
|
+
KeyUsagesExtension,
|
|
20523
|
+
KeyUsageFlags,
|
|
20524
|
+
X509Certificate
|
|
20525
|
+
} from "@peculiar/x509";
|
|
20526
|
+
var NitroAttestationError = class extends Error {
|
|
20527
|
+
constructor(reason) {
|
|
20528
|
+
super(`Nitro attestation rejected: ${reason}`);
|
|
20529
|
+
this.reason = reason;
|
|
20530
|
+
this.name = "NitroAttestationError";
|
|
20531
|
+
}
|
|
20532
|
+
static {
|
|
20533
|
+
__name(this, "NitroAttestationError");
|
|
20534
|
+
}
|
|
20535
|
+
};
|
|
20536
|
+
var AWS_ROOT_SHA256 = "641a0321a3e244efe456463195d606317ed7cdcc3c1756e09893f3c68f79bb5b";
|
|
20537
|
+
var fail = /* @__PURE__ */ __name((reason) => {
|
|
20538
|
+
throw new NitroAttestationError(reason);
|
|
20539
|
+
}, "fail");
|
|
20540
|
+
var hex = /* @__PURE__ */ __name((bytes2) => Array.from(bytes2, (byte) => byte.toString(16).padStart(2, "0")).join(""), "hex");
|
|
20541
|
+
var bytes = /* @__PURE__ */ __name((value, reason) => value instanceof Uint8Array && value.length > 0 ? value : fail(reason), "bytes");
|
|
20542
|
+
var map = /* @__PURE__ */ __name((value, reason) => value instanceof Map ? value : fail(reason), "map");
|
|
20543
|
+
var decodeCbor = /* @__PURE__ */ __name((value) => {
|
|
20544
|
+
try {
|
|
20545
|
+
return decode(value, {
|
|
20546
|
+
useMaps: true,
|
|
20547
|
+
rejectDuplicateMapKeys: true,
|
|
20548
|
+
allowIndefinite: false,
|
|
20549
|
+
allowUndefined: false,
|
|
20550
|
+
allowNaN: false,
|
|
20551
|
+
allowInfinity: false,
|
|
20552
|
+
allowBigInt: false
|
|
20553
|
+
});
|
|
20554
|
+
} catch {
|
|
20555
|
+
return fail("cbor");
|
|
20556
|
+
}
|
|
20557
|
+
}, "decodeCbor");
|
|
20558
|
+
var decodeUserData = /* @__PURE__ */ __name((userData) => {
|
|
20559
|
+
let decoded;
|
|
20560
|
+
try {
|
|
20561
|
+
decoded = decode(userData, {
|
|
20562
|
+
useMaps: true,
|
|
20563
|
+
rejectDuplicateMapKeys: true,
|
|
20564
|
+
allowIndefinite: false,
|
|
20565
|
+
allowUndefined: false,
|
|
20566
|
+
allowNaN: false,
|
|
20567
|
+
allowInfinity: false,
|
|
20568
|
+
allowBigInt: false
|
|
20569
|
+
});
|
|
20570
|
+
} catch {
|
|
20571
|
+
return void 0;
|
|
20572
|
+
}
|
|
20573
|
+
if (!(decoded instanceof Map) || decoded.size !== 3) return void 0;
|
|
20574
|
+
const spki = decoded.get(0);
|
|
20575
|
+
const keyId = decoded.get(1);
|
|
20576
|
+
const previousKeyIds = decoded.get(2);
|
|
20577
|
+
const isKeyId = /* @__PURE__ */ __name((value) => typeof value === "string" && /^[A-Za-z0-9._-]{1,128}$/.test(value), "isKeyId");
|
|
20578
|
+
if (!(spki instanceof Uint8Array) || spki.length === 0 || !isKeyId(keyId) || !Array.isArray(previousKeyIds) || previousKeyIds.length > 3 || !previousKeyIds.every(isKeyId)) {
|
|
20579
|
+
return void 0;
|
|
20580
|
+
}
|
|
20581
|
+
return { spki, keyId, previousKeyIds };
|
|
20582
|
+
}, "decodeUserData");
|
|
20583
|
+
var verifyNitroAttestationDocument = /* @__PURE__ */ __name(async (documentB64, {
|
|
20584
|
+
expectedNonce,
|
|
20585
|
+
policy,
|
|
20586
|
+
now = Date.now()
|
|
20587
|
+
}) => {
|
|
20588
|
+
let document;
|
|
20589
|
+
try {
|
|
20590
|
+
if (!documentB64 || documentB64.length > 65536 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(documentB64))
|
|
20591
|
+
fail("cbor");
|
|
20592
|
+
document = base64ToBuffer(documentB64);
|
|
20593
|
+
} catch {
|
|
20594
|
+
return fail("cbor");
|
|
20595
|
+
}
|
|
20596
|
+
const cose = decodeCbor(document[0] === 210 ? document.subarray(1) : document);
|
|
20597
|
+
if (!Array.isArray(cose) || cose.length !== 4) fail("cose");
|
|
20598
|
+
const [protectedValue, unprotectedValue, payloadValue, signatureValue] = cose;
|
|
20599
|
+
const protectedBytes = bytes(protectedValue, "cose");
|
|
20600
|
+
const protectedHeader = map(decodeCbor(protectedBytes), "alg");
|
|
20601
|
+
if (protectedHeader.size !== 1 || protectedHeader.get(1) !== -35) fail("alg");
|
|
20602
|
+
if (map(unprotectedValue, "cose").size !== 0) fail("cose");
|
|
20603
|
+
const payloadBytes = bytes(payloadValue, "cose");
|
|
20604
|
+
const signature = bytes(signatureValue, "signature");
|
|
20605
|
+
if (signature.length !== 96) fail("signature");
|
|
20606
|
+
const payload = map(decodeCbor(payloadBytes), "cbor");
|
|
20607
|
+
const moduleId = payload.get("module_id");
|
|
20608
|
+
const timestamp = payload.get("timestamp");
|
|
20609
|
+
if (typeof moduleId !== "string" || !moduleId || payload.get("digest") !== "SHA384")
|
|
20610
|
+
fail("cbor");
|
|
20611
|
+
if (typeof timestamp !== "number" || !Number.isSafeInteger(timestamp) || timestamp < 0)
|
|
20612
|
+
fail("freshness");
|
|
20613
|
+
const leafDer = bytes(payload.get("certificate"), "chain");
|
|
20614
|
+
const bundle = payload.get("cabundle");
|
|
20615
|
+
if (!Array.isArray(bundle) || !bundle.length || bundle.length > 16) fail("chain");
|
|
20616
|
+
const ders = bundle.map((value) => bytes(value, "chain"));
|
|
20617
|
+
const rootHash = hex(
|
|
20618
|
+
new Uint8Array(await crypto.subtle.digest("SHA-256", new Uint8Array(ders[0])))
|
|
20619
|
+
);
|
|
20620
|
+
if (rootHash !== (policy.rootCertificateSha256 ?? AWS_ROOT_SHA256).toLowerCase()) fail("root");
|
|
20621
|
+
let leaf;
|
|
20622
|
+
try {
|
|
20623
|
+
const chain = [...ders, leafDer].map((der) => new X509Certificate(new Uint8Array(der)));
|
|
20624
|
+
for (let i = 0; i < chain.length; i++) {
|
|
20625
|
+
const cert = chain[i];
|
|
20626
|
+
const issuer = chain[Math.max(0, i - 1)];
|
|
20627
|
+
if (!Number.isFinite(now) || now < cert.notBefore.getTime() || now > cert.notAfter.getTime() || cert.issuer !== issuer.subject || !await cert.verify({ publicKey: issuer.publicKey, date: new Date(now) }, crypto))
|
|
20628
|
+
fail("chain");
|
|
20629
|
+
if (i < chain.length - 1) {
|
|
20630
|
+
const constraints = cert.getExtension(BasicConstraintsExtension);
|
|
20631
|
+
const usage = cert.getExtension(KeyUsagesExtension);
|
|
20632
|
+
if (!constraints?.ca || constraints.pathLength !== void 0 && chain.length - i - 2 > constraints.pathLength || usage && !(usage.usages & KeyUsageFlags.keyCertSign))
|
|
20633
|
+
fail("chain");
|
|
20634
|
+
}
|
|
20635
|
+
}
|
|
20636
|
+
leaf = chain[chain.length - 1];
|
|
20637
|
+
} catch {
|
|
20638
|
+
return fail("chain");
|
|
20639
|
+
}
|
|
20640
|
+
try {
|
|
20641
|
+
const key = await crypto.subtle.importKey(
|
|
20642
|
+
"spki",
|
|
20643
|
+
leaf.publicKey.rawData,
|
|
20644
|
+
{ name: "ECDSA", namedCurve: "P-384" },
|
|
20645
|
+
false,
|
|
20646
|
+
["verify"]
|
|
20647
|
+
);
|
|
20648
|
+
const structure = encode(["Signature1", protectedBytes, new Uint8Array(), payloadBytes]);
|
|
20649
|
+
if (!await crypto.subtle.verify(
|
|
20650
|
+
{ name: "ECDSA", hash: "SHA-384" },
|
|
20651
|
+
key,
|
|
20652
|
+
new Uint8Array(signature),
|
|
20653
|
+
new Uint8Array(structure)
|
|
20654
|
+
))
|
|
20655
|
+
fail("signature");
|
|
20656
|
+
} catch {
|
|
20657
|
+
return fail("signature");
|
|
20658
|
+
}
|
|
20659
|
+
const rawPcrs = map(payload.get("pcrs"), "pcr");
|
|
20660
|
+
const pcrs = {};
|
|
20661
|
+
for (const [index, value] of rawPcrs) {
|
|
20662
|
+
if (typeof index !== "number" || !Number.isInteger(index) || index < 0 || index > 31)
|
|
20663
|
+
fail("pcr");
|
|
20664
|
+
const pcr = bytes(value, "pcr");
|
|
20665
|
+
if (pcr.length !== 48) fail("pcr");
|
|
20666
|
+
pcrs[index] = hex(pcr);
|
|
20667
|
+
}
|
|
20668
|
+
if (pcrs[0] === "00".repeat(48)) fail("debug");
|
|
20669
|
+
if (!policy.pinnedMeasurements.some(
|
|
20670
|
+
(pin) => typeof pin.pcr0 === "string" && typeof pin.pcr1 === "string" && typeof pin.pcr2 === "string" && pin.pcr0.toLowerCase() === pcrs[0] && pin.pcr1.toLowerCase() === pcrs[1] && pin.pcr2.toLowerCase() === pcrs[2]
|
|
20671
|
+
))
|
|
20672
|
+
fail("pcr");
|
|
20673
|
+
const nonce = bytes(payload.get("nonce"), "nonce");
|
|
20674
|
+
if (!(expectedNonce instanceof Uint8Array) || expectedNonce.length !== 32 || nonce.length !== expectedNonce.length)
|
|
20675
|
+
fail("nonce");
|
|
20676
|
+
let difference = 0;
|
|
20677
|
+
for (let i = 0; i < nonce.length; i++) difference |= nonce[i] ^ expectedNonce[i];
|
|
20678
|
+
if (difference !== 0) fail("nonce");
|
|
20679
|
+
const maxAge = policy.maxAgeMs ?? 3e5;
|
|
20680
|
+
if (!Number.isFinite(maxAge) || maxAge < 0 || now - timestamp > maxAge || timestamp > now + 6e4)
|
|
20681
|
+
fail("freshness");
|
|
20682
|
+
const userData = bytes(payload.get("user_data"), "user-data");
|
|
20683
|
+
const newFormat = decodeUserData(new Uint8Array(userData));
|
|
20684
|
+
const spki = newFormat ? newFormat.spki : userData;
|
|
20685
|
+
try {
|
|
20686
|
+
await crypto.subtle.importKey(
|
|
20687
|
+
"spki",
|
|
20688
|
+
new Uint8Array(spki),
|
|
20689
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20690
|
+
false,
|
|
20691
|
+
[]
|
|
20692
|
+
);
|
|
20693
|
+
} catch {
|
|
20694
|
+
return fail("user-data");
|
|
20695
|
+
}
|
|
20696
|
+
return {
|
|
20697
|
+
escrowPublicKeySpkiB64: bufferToBase64(new Uint8Array(spki).buffer),
|
|
20698
|
+
keyId: newFormat?.keyId,
|
|
20699
|
+
previousKeyIds: newFormat?.previousKeyIds ?? [],
|
|
20700
|
+
pcrs,
|
|
20701
|
+
timestamp,
|
|
20702
|
+
moduleId
|
|
20703
|
+
};
|
|
20704
|
+
}, "verifyNitroAttestationDocument");
|
|
20705
|
+
|
|
20706
|
+
// src/escrow-attestation.ts
|
|
20707
|
+
var isRecord3 = /* @__PURE__ */ __name((value) => typeof value === "object" && value !== null && !Array.isArray(value), "isRecord");
|
|
20708
|
+
var normalizePublicKey = /* @__PURE__ */ __name((value) => {
|
|
20709
|
+
const trimmed = value.trim();
|
|
20710
|
+
if (!trimmed || trimmed.length > 512 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(trimmed)) {
|
|
20711
|
+
throw new Error("Invalid escrow attestation public key");
|
|
20712
|
+
}
|
|
20713
|
+
return bufferToBase64(base64ToBuffer(trimmed).buffer);
|
|
20714
|
+
}, "normalizePublicKey");
|
|
20715
|
+
var verifyEnclaveAttestation = /* @__PURE__ */ __name(async (attestation, policy, nonce) => {
|
|
20716
|
+
const isKeyId = /* @__PURE__ */ __name((value) => typeof value === "string" && /^[A-Za-z0-9._-]{1,128}$/.test(value), "isKeyId");
|
|
20717
|
+
const fields = [
|
|
20718
|
+
"mode",
|
|
20719
|
+
"keyId",
|
|
20720
|
+
"previousKeyIds",
|
|
20721
|
+
"publicKey",
|
|
20722
|
+
"measurements",
|
|
20723
|
+
"document",
|
|
20724
|
+
"issuedAt"
|
|
20725
|
+
];
|
|
20726
|
+
if (!isRecord3(attestation) || Object.keys(attestation).some((key) => !fields.includes(key)) || attestation.mode !== "software" && attestation.mode !== "nitro" || !isKeyId(attestation.keyId) || attestation.previousKeyIds !== void 0 && (!Array.isArray(attestation.previousKeyIds) || attestation.previousKeyIds.length > 3 || !attestation.previousKeyIds.every(isKeyId)) || typeof attestation.publicKey !== "string" || !isRecord3(attestation.measurements) || Object.entries(attestation.measurements).some(
|
|
20727
|
+
([key, value]) => !["imageSha384", "pcr0", "pcr1", "pcr2"].includes(key) || typeof value !== "string" || !value || value.length > 1024
|
|
20728
|
+
) || typeof attestation.document !== "string" || !attestation.document || attestation.document.length > 65536 || typeof attestation.issuedAt !== "string" || !Number.isFinite(Date.parse(attestation.issuedAt))) {
|
|
20729
|
+
throw new Error("Invalid escrow attestation");
|
|
20730
|
+
}
|
|
20731
|
+
const plaintextPreviousKeyIds = attestation.previousKeyIds ?? [];
|
|
20732
|
+
if (attestation.mode !== policy.mode) throw new Error("Escrow attestation mode mismatch");
|
|
20733
|
+
if (policy.mode === "nitro") {
|
|
20734
|
+
if (!nonce) throw new NitroAttestationError("nonce");
|
|
20735
|
+
const verified = await verifyNitroAttestationDocument(attestation.document, {
|
|
20736
|
+
expectedNonce: nonce,
|
|
20737
|
+
policy
|
|
20738
|
+
});
|
|
20739
|
+
try {
|
|
20740
|
+
if (normalizePublicKey(attestation.publicKey) !== verified.escrowPublicKeySpkiB64) {
|
|
20741
|
+
throw new NitroAttestationError("user-data");
|
|
20742
|
+
}
|
|
20743
|
+
} catch {
|
|
20744
|
+
throw new NitroAttestationError("user-data");
|
|
20745
|
+
}
|
|
20746
|
+
if (verified.keyId !== void 0 && verified.keyId !== attestation.keyId) {
|
|
20747
|
+
throw new NitroAttestationError("user-data");
|
|
20748
|
+
}
|
|
20749
|
+
if (plaintextPreviousKeyIds.length !== verified.previousKeyIds.length || !plaintextPreviousKeyIds.every((id, index) => id === verified.previousKeyIds[index])) {
|
|
20750
|
+
throw new NitroAttestationError("user-data");
|
|
20751
|
+
}
|
|
20752
|
+
return {
|
|
20753
|
+
publicKey: verified.escrowPublicKeySpkiB64,
|
|
20754
|
+
keyId: attestation.keyId,
|
|
20755
|
+
previousKeyIds: verified.previousKeyIds,
|
|
20756
|
+
mode: "nitro"
|
|
20757
|
+
};
|
|
20758
|
+
}
|
|
20759
|
+
const publicKey = normalizePublicKey(attestation.publicKey);
|
|
20760
|
+
await crypto.subtle.importKey(
|
|
20761
|
+
"spki",
|
|
20762
|
+
base64ToBuffer(publicKey),
|
|
20763
|
+
{ name: "ECDH", namedCurve: "P-256" },
|
|
20764
|
+
false,
|
|
20765
|
+
[]
|
|
20766
|
+
);
|
|
20767
|
+
if (!policy.pinnedPublicKeys.some((pin) => normalizePublicKey(pin) === publicKey)) {
|
|
20768
|
+
throw new Error("Escrow attestation public key is not trusted");
|
|
20769
|
+
}
|
|
20770
|
+
return {
|
|
20771
|
+
publicKey,
|
|
20772
|
+
keyId: attestation.keyId,
|
|
20773
|
+
previousKeyIds: plaintextPreviousKeyIds,
|
|
20774
|
+
mode: attestation.mode
|
|
20775
|
+
};
|
|
20776
|
+
}, "verifyEnclaveAttestation");
|
|
20777
|
+
|
|
20778
|
+
// src/types.ts
|
|
20779
|
+
var import_types = __toESM(require_dist());
|
|
20780
|
+
var EscrowPinUnavailableError = class extends Error {
|
|
20781
|
+
static {
|
|
20782
|
+
__name(this, "EscrowPinUnavailableError");
|
|
20783
|
+
}
|
|
20784
|
+
constructor() {
|
|
20785
|
+
super("PIN recovery is not available for this account.");
|
|
20786
|
+
this.name = "EscrowPinUnavailableError";
|
|
20787
|
+
}
|
|
20788
|
+
};
|
|
20789
|
+
var EscrowPinMismatchError = class extends Error {
|
|
20790
|
+
constructor(attemptsRemaining) {
|
|
20791
|
+
super("Incorrect PIN.");
|
|
20792
|
+
this.attemptsRemaining = attemptsRemaining;
|
|
20793
|
+
this.name = "EscrowPinMismatchError";
|
|
20794
|
+
}
|
|
20795
|
+
static {
|
|
20796
|
+
__name(this, "EscrowPinMismatchError");
|
|
20797
|
+
}
|
|
20798
|
+
};
|
|
20799
|
+
var EscrowPinThrottledError = class extends Error {
|
|
20800
|
+
static {
|
|
20801
|
+
__name(this, "EscrowPinThrottledError");
|
|
20802
|
+
}
|
|
20803
|
+
constructor() {
|
|
20804
|
+
super("Too many tries right now. Wait a minute and try again.");
|
|
20805
|
+
this.name = "EscrowPinThrottledError";
|
|
20806
|
+
}
|
|
20807
|
+
};
|
|
20808
|
+
var EscrowHoldRestartThrottledError = class extends Error {
|
|
20809
|
+
constructor(retryAfter) {
|
|
20810
|
+
super("A recovery request was started recently. Please wait before restarting.");
|
|
20811
|
+
this.retryAfter = retryAfter;
|
|
20812
|
+
this.name = "EscrowHoldRestartThrottledError";
|
|
20813
|
+
}
|
|
20814
|
+
static {
|
|
20815
|
+
__name(this, "EscrowHoldRestartThrottledError");
|
|
20816
|
+
}
|
|
20817
|
+
};
|
|
20818
|
+
var EscrowPinLockedError = class extends Error {
|
|
20819
|
+
static {
|
|
20820
|
+
__name(this, "EscrowPinLockedError");
|
|
20821
|
+
}
|
|
20822
|
+
constructor() {
|
|
20823
|
+
super("Too many incorrect PIN attempts. You can still recover by waiting.");
|
|
20824
|
+
this.name = "EscrowPinLockedError";
|
|
20825
|
+
}
|
|
20826
|
+
};
|
|
20827
|
+
|
|
20828
|
+
// src/escrow-pin.ts
|
|
20829
|
+
var PIN_MIN_LENGTH = 6;
|
|
20830
|
+
var PIN_MAX_LENGTH = 12;
|
|
20831
|
+
var ESCROW_PIN_MAX_ATTEMPTS = 10;
|
|
20832
|
+
var TRIVIAL_PINS = /* @__PURE__ */ new Set([
|
|
20833
|
+
"123456",
|
|
20834
|
+
"654321",
|
|
20835
|
+
"000000",
|
|
20836
|
+
"111111",
|
|
20837
|
+
"121212",
|
|
20838
|
+
"112233",
|
|
20839
|
+
"123123",
|
|
20840
|
+
"696969",
|
|
20841
|
+
"123321"
|
|
20842
|
+
]);
|
|
20843
|
+
var normalizePin = /* @__PURE__ */ __name((raw) => raw.trim().normalize("NFKD").replace(/\D/g, ""), "normalizePin");
|
|
20844
|
+
var validatePin = /* @__PURE__ */ __name((pin) => {
|
|
20845
|
+
const normalized = normalizePin(pin);
|
|
20846
|
+
if (normalized.length < PIN_MIN_LENGTH || normalized.length > PIN_MAX_LENGTH) {
|
|
20847
|
+
return { ok: false, reason: "length" };
|
|
20848
|
+
}
|
|
20849
|
+
if (/^(\d)\1+$/.test(normalized) || "0123456789".includes(normalized) || "9876543210".includes(normalized) || TRIVIAL_PINS.has(normalized)) {
|
|
20850
|
+
return { ok: false, reason: "trivial" };
|
|
20851
|
+
}
|
|
20852
|
+
return { ok: true };
|
|
20853
|
+
}, "validatePin");
|
|
20854
|
+
var generatePinSalt = /* @__PURE__ */ __name(() => bufferToBase64(crypto.getRandomValues(new Uint8Array(16)).buffer), "generatePinSalt");
|
|
20855
|
+
var derivePinProof = /* @__PURE__ */ __name(async (pin, pinSaltBase64) => {
|
|
20856
|
+
const salt = base64ToBuffer(pinSaltBase64);
|
|
20857
|
+
if (salt.length !== 16) throw new Error("Invalid escrow PIN salt length");
|
|
20858
|
+
const key = await deriveKeyFromPassword(normalizePin(pin), salt);
|
|
20859
|
+
try {
|
|
20860
|
+
return bytesToHex(key);
|
|
20861
|
+
} finally {
|
|
20862
|
+
key.fill(0);
|
|
20863
|
+
}
|
|
20864
|
+
}, "derivePinProof");
|
|
20865
|
+
var constantTimeEqualHex = /* @__PURE__ */ __name((a, b) => {
|
|
20866
|
+
if (a.length !== b.length || !/^(?:[0-9a-f]{2})+$/i.test(a) || !/^(?:[0-9a-f]{2})+$/i.test(b)) {
|
|
20867
|
+
return false;
|
|
20868
|
+
}
|
|
20869
|
+
const aBytes = hexToBytes(a);
|
|
20870
|
+
const bBytes = hexToBytes(b);
|
|
20871
|
+
let difference = 0;
|
|
20872
|
+
for (let i = 0; i < aBytes.length; i++) {
|
|
20873
|
+
difference |= aBytes[i] ^ bBytes[i];
|
|
20874
|
+
}
|
|
20875
|
+
return difference === 0;
|
|
20876
|
+
}, "constantTimeEqualHex");
|
|
20877
|
+
|
|
20878
|
+
// src/atomic-operations.ts
|
|
20879
|
+
var ShareVerificationError = class extends Error {
|
|
20880
|
+
constructor(message, combination, expected, got) {
|
|
20881
|
+
super(message);
|
|
20882
|
+
this.combination = combination;
|
|
20883
|
+
this.expected = expected;
|
|
20884
|
+
this.got = got;
|
|
20885
|
+
this.name = "ShareVerificationError";
|
|
20886
|
+
}
|
|
20887
|
+
static {
|
|
20888
|
+
__name(this, "ShareVerificationError");
|
|
20889
|
+
}
|
|
20890
|
+
};
|
|
20891
|
+
var AtomicUpdateError = class extends Error {
|
|
20892
|
+
constructor(message, phase, rolledBack, cause) {
|
|
20893
|
+
super(message);
|
|
20894
|
+
this.phase = phase;
|
|
19285
20895
|
this.rolledBack = rolledBack;
|
|
19286
20896
|
this.cause = cause;
|
|
19287
20897
|
this.name = "AtomicUpdateError";
|
|
@@ -19290,6 +20900,15 @@ var AtomicUpdateError = class extends Error {
|
|
|
19290
20900
|
__name(this, "AtomicUpdateError");
|
|
19291
20901
|
}
|
|
19292
20902
|
};
|
|
20903
|
+
var ShareWriteRejectedError = class extends Error {
|
|
20904
|
+
static {
|
|
20905
|
+
__name(this, "ShareWriteRejectedError");
|
|
20906
|
+
}
|
|
20907
|
+
constructor(message) {
|
|
20908
|
+
super(message);
|
|
20909
|
+
this.name = "ShareWriteRejectedError";
|
|
20910
|
+
}
|
|
20911
|
+
};
|
|
19293
20912
|
async function splitAndVerify(privateKey) {
|
|
19294
20913
|
const shares = await splitPrivateKey(privateKey);
|
|
19295
20914
|
const combinations = [
|
|
@@ -19346,18 +20965,37 @@ async function atomicShareUpdate(privateKey, storage, options = {}) {
|
|
|
19346
20965
|
try {
|
|
19347
20966
|
await storage.storeAuth(newShares.authShare);
|
|
19348
20967
|
} catch (e) {
|
|
19349
|
-
if (
|
|
20968
|
+
if (!(e instanceof ShareWriteRejectedError)) {
|
|
20969
|
+
throw new AtomicUpdateError(
|
|
20970
|
+
"Auth share write outcome unknown; device share preserved for reconciliation",
|
|
20971
|
+
"store_auth",
|
|
20972
|
+
false,
|
|
20973
|
+
e instanceof Error ? e : void 0
|
|
20974
|
+
);
|
|
20975
|
+
}
|
|
20976
|
+
let rolledBack = false;
|
|
20977
|
+
if (deviceStored) {
|
|
19350
20978
|
try {
|
|
19351
|
-
|
|
19352
|
-
|
|
20979
|
+
if (options.previousDeviceShare !== void 0) {
|
|
20980
|
+
await storage.storeDevice(options.previousDeviceShare);
|
|
20981
|
+
options.onRollback?.("Server storage failed, restored previous device share");
|
|
20982
|
+
rolledBack = true;
|
|
20983
|
+
} else if (storage.clearDevice) {
|
|
20984
|
+
await storage.clearDevice();
|
|
20985
|
+
options.onRollback?.("Server storage failed, removed new device share");
|
|
20986
|
+
rolledBack = true;
|
|
20987
|
+
}
|
|
19353
20988
|
} catch (rollbackError) {
|
|
19354
|
-
console.error(
|
|
20989
|
+
console.error(
|
|
20990
|
+
"CRITICAL: Rollback failed after auth share storage failure",
|
|
20991
|
+
rollbackError
|
|
20992
|
+
);
|
|
19355
20993
|
}
|
|
19356
20994
|
}
|
|
19357
20995
|
throw new AtomicUpdateError(
|
|
19358
|
-
"Failed to store auth share on server, rolled back device share",
|
|
20996
|
+
rolledBack ? "Failed to store auth share on server, rolled back device share" : "Failed to store auth share on server; rollback did not complete",
|
|
19359
20997
|
"store_auth",
|
|
19360
|
-
|
|
20998
|
+
rolledBack,
|
|
19361
20999
|
e instanceof Error ? e : void 0
|
|
19362
21000
|
);
|
|
19363
21001
|
}
|
|
@@ -19411,12 +21049,16 @@ async function atomicRecovery(recoveryShare, authShareData, storage, options = {
|
|
|
19411
21049
|
__name(atomicRecovery, "atomicRecovery");
|
|
19412
21050
|
|
|
19413
21051
|
// src/sss-strategy.ts
|
|
21052
|
+
var import_types3 = __toESM(require_dist());
|
|
19414
21053
|
var SSS_DB_NAME = "lcb-sss-keys";
|
|
21054
|
+
var DEFAULT_DEVICE_SHARE_ID2 = "sss-device-share";
|
|
21055
|
+
var MAX_RECONCILIATION_HISTORY = 5;
|
|
19415
21056
|
var defaultStorage = {
|
|
19416
21057
|
storeDeviceShare,
|
|
19417
21058
|
getDeviceShare,
|
|
19418
21059
|
hasDeviceShare,
|
|
19419
21060
|
clearAllShares,
|
|
21061
|
+
deleteDeviceShare,
|
|
19420
21062
|
storeShareVersion,
|
|
19421
21063
|
getShareVersion
|
|
19422
21064
|
};
|
|
@@ -19425,10 +21067,24 @@ var buildHeaders = /* @__PURE__ */ __name((token, didAuthVp, tenantId) => ({
|
|
|
19425
21067
|
...didAuthVp ? { Authorization: `Bearer ${didAuthVp}` } : {},
|
|
19426
21068
|
...tenantId ? { "X-Tenant-Id": tenantId } : {}
|
|
19427
21069
|
}), "buildHeaders");
|
|
21070
|
+
var SERVER_REQUEST_TIMEOUT_MS = 3e4;
|
|
21071
|
+
var requestTimeoutSignal = /* @__PURE__ */ __name((ms = SERVER_REQUEST_TIMEOUT_MS) => typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(ms) : void 0, "requestTimeoutSignal");
|
|
21072
|
+
var describeHttpStatus = /* @__PURE__ */ __name((response) => response.statusText ? `${response.status} ${response.statusText}` : `${response.status}`, "describeHttpStatus");
|
|
21073
|
+
var EscrowRequestError = class extends Error {
|
|
21074
|
+
constructor(status) {
|
|
21075
|
+
super("Escrow request failed");
|
|
21076
|
+
this.status = status;
|
|
21077
|
+
this.name = "EscrowRequestError";
|
|
21078
|
+
}
|
|
21079
|
+
static {
|
|
21080
|
+
__name(this, "EscrowRequestError");
|
|
21081
|
+
}
|
|
21082
|
+
};
|
|
19428
21083
|
var fetchAuthShareRaw = /* @__PURE__ */ __name(async (serverUrl, token, providerType, shareVersion, tenantId) => {
|
|
19429
21084
|
const response = await fetch(`${serverUrl}/keys/auth-share`, {
|
|
19430
21085
|
method: "POST",
|
|
19431
21086
|
headers: buildHeaders(token, void 0, tenantId),
|
|
21087
|
+
signal: requestTimeoutSignal(),
|
|
19432
21088
|
body: JSON.stringify({
|
|
19433
21089
|
authToken: token,
|
|
19434
21090
|
providerType,
|
|
@@ -19437,42 +21093,103 @@ var fetchAuthShareRaw = /* @__PURE__ */ __name(async (serverUrl, token, provider
|
|
|
19437
21093
|
});
|
|
19438
21094
|
if (!response.ok) {
|
|
19439
21095
|
if (response.status === 404) return null;
|
|
19440
|
-
throw new Error(`Failed to fetch key status: ${response
|
|
21096
|
+
throw new Error(`Failed to fetch key status: ${describeHttpStatus(response)}`);
|
|
19441
21097
|
}
|
|
19442
21098
|
return response.json();
|
|
19443
21099
|
}, "fetchAuthShareRaw");
|
|
19444
|
-
var putAuthShare = /* @__PURE__ */ __name(async (serverUrl, token, providerType, authShare, primaryDid, didAuthVp, tenantId) => {
|
|
21100
|
+
var putAuthShare = /* @__PURE__ */ __name(async (serverUrl, token, providerType, authShare, primaryDid, didAuthVp, tenantId, expectedShareVersion) => {
|
|
19445
21101
|
const response = await fetch(`${serverUrl}/keys/auth-share`, {
|
|
19446
21102
|
method: "PUT",
|
|
19447
21103
|
headers: buildHeaders(token, didAuthVp, tenantId),
|
|
21104
|
+
signal: requestTimeoutSignal(),
|
|
19448
21105
|
body: JSON.stringify({
|
|
19449
21106
|
authToken: token,
|
|
19450
21107
|
providerType,
|
|
19451
21108
|
authShare: { encryptedData: authShare, encryptedDek: "", iv: "" },
|
|
19452
21109
|
primaryDid,
|
|
19453
|
-
securityLevel: "basic"
|
|
21110
|
+
securityLevel: "basic",
|
|
21111
|
+
sssActivationState: "provisional",
|
|
21112
|
+
expectedShareVersion
|
|
19454
21113
|
})
|
|
19455
21114
|
});
|
|
19456
21115
|
if (!response.ok) {
|
|
19457
|
-
|
|
21116
|
+
const message = `Failed to store auth share: ${describeHttpStatus(response)}`;
|
|
21117
|
+
if (response.status >= 400 && response.status < 500 && response.status !== 408) {
|
|
21118
|
+
throw new ShareWriteRejectedError(message);
|
|
21119
|
+
}
|
|
21120
|
+
throw new Error(message);
|
|
19458
21121
|
}
|
|
19459
21122
|
const data = await response.json();
|
|
19460
|
-
return {
|
|
21123
|
+
return {
|
|
21124
|
+
shareVersion: data.shareVersion ?? 1,
|
|
21125
|
+
expectedShareVersionChecked: data.expectedShareVersionChecked === true
|
|
21126
|
+
};
|
|
19461
21127
|
}, "putAuthShare");
|
|
21128
|
+
var authShareToString = /* @__PURE__ */ __name((authShare) => {
|
|
21129
|
+
if (typeof authShare === "string") return authShare;
|
|
21130
|
+
if (typeof authShare === "object" && authShare !== null && "encryptedData" in authShare && typeof authShare.encryptedData === "string") {
|
|
21131
|
+
return authShare.encryptedData;
|
|
21132
|
+
}
|
|
21133
|
+
return null;
|
|
21134
|
+
}, "authShareToString");
|
|
21135
|
+
var requestFreshDidAuthVp = /* @__PURE__ */ __name(async (serverUrl, privateKey, did, signDidAuthVp, tenantId) => {
|
|
21136
|
+
const bootstrapVp = await signDidAuthVp(privateKey);
|
|
21137
|
+
const response = await fetch(`${serverUrl}/keys/challenge`, {
|
|
21138
|
+
method: "POST",
|
|
21139
|
+
headers: buildHeaders("", bootstrapVp, tenantId),
|
|
21140
|
+
signal: requestTimeoutSignal(),
|
|
21141
|
+
body: JSON.stringify({ did })
|
|
21142
|
+
});
|
|
21143
|
+
if (!response.ok) {
|
|
21144
|
+
throw new Error(`Failed to request DID challenge: ${describeHttpStatus(response)}`);
|
|
21145
|
+
}
|
|
21146
|
+
const data = await response.json();
|
|
21147
|
+
if (!data.challenge) throw new Error("DID challenge response was empty");
|
|
21148
|
+
return signDidAuthVp(privateKey, data.challenge);
|
|
21149
|
+
}, "requestFreshDidAuthVp");
|
|
19462
21150
|
var fetchRecoveryShare = /* @__PURE__ */ __name(async (serverUrl, token, providerType, type, credentialId, tenantId) => {
|
|
19463
|
-
const params = new URLSearchParams({ type, providerType
|
|
21151
|
+
const params = new URLSearchParams({ type, providerType });
|
|
19464
21152
|
if (credentialId) {
|
|
19465
21153
|
params.set("credentialId", credentialId);
|
|
19466
21154
|
}
|
|
19467
21155
|
const response = await fetch(`${serverUrl}/keys/recovery?${params}`, {
|
|
19468
21156
|
method: "GET",
|
|
19469
|
-
headers:
|
|
21157
|
+
headers: {
|
|
21158
|
+
"Content-Type": "application/json",
|
|
21159
|
+
"X-Auth-Token": token,
|
|
21160
|
+
...tenantId ? { "X-Tenant-Id": tenantId } : {}
|
|
21161
|
+
}
|
|
19470
21162
|
});
|
|
19471
21163
|
if (!response.ok) {
|
|
19472
21164
|
throw new Error(`No ${type} recovery share found`);
|
|
19473
21165
|
}
|
|
19474
21166
|
return response.json();
|
|
19475
21167
|
}, "fetchRecoveryShare");
|
|
21168
|
+
var IdentityRecoverySessionConsumedError = class extends Error {
|
|
21169
|
+
static {
|
|
21170
|
+
__name(this, "IdentityRecoverySessionConsumedError");
|
|
21171
|
+
}
|
|
21172
|
+
constructor(message) {
|
|
21173
|
+
super(message);
|
|
21174
|
+
this.name = "IdentityRecoverySessionConsumedError";
|
|
21175
|
+
}
|
|
21176
|
+
};
|
|
21177
|
+
var postJson = /* @__PURE__ */ __name(async (url, body, headers) => {
|
|
21178
|
+
const response = await fetch(url, {
|
|
21179
|
+
method: "POST",
|
|
21180
|
+
headers,
|
|
21181
|
+
body: JSON.stringify(body)
|
|
21182
|
+
});
|
|
21183
|
+
if (!response.ok) {
|
|
21184
|
+
const data = await response.json().catch(() => null);
|
|
21185
|
+
const message = data?.error?.message || data?.message || response.statusText;
|
|
21186
|
+
if (response.status >= 400 && response.status < 500 && response.status !== 408) {
|
|
21187
|
+
throw new ShareWriteRejectedError(message);
|
|
21188
|
+
}
|
|
21189
|
+
throw new Error(message);
|
|
21190
|
+
}
|
|
21191
|
+
return response.json();
|
|
21192
|
+
}, "postJson");
|
|
19476
21193
|
var postRecoveryMethod = /* @__PURE__ */ __name(async (serverUrl, token, providerType, body, didAuthVp, tenantId) => {
|
|
19477
21194
|
const response = await fetch(`${serverUrl}/keys/recovery`, {
|
|
19478
21195
|
method: "POST",
|
|
@@ -19480,9 +21197,40 @@ var postRecoveryMethod = /* @__PURE__ */ __name(async (serverUrl, token, provide
|
|
|
19480
21197
|
body: JSON.stringify({ authToken: token, providerType, ...body })
|
|
19481
21198
|
});
|
|
19482
21199
|
if (!response.ok) {
|
|
19483
|
-
throw new Error(`Failed to add recovery method: ${response
|
|
21200
|
+
throw new Error(`Failed to add recovery method: ${describeHttpStatus(response)}`);
|
|
19484
21201
|
}
|
|
19485
21202
|
}, "postRecoveryMethod");
|
|
21203
|
+
var postRecoveryConfirmation = /* @__PURE__ */ __name(async (serverUrl, token, providerType, body, didAuthVp, tenantId) => {
|
|
21204
|
+
const response = await fetch(`${serverUrl}/keys/recovery/confirm`, {
|
|
21205
|
+
method: "POST",
|
|
21206
|
+
headers: buildHeaders(token, didAuthVp, tenantId),
|
|
21207
|
+
body: JSON.stringify({ authToken: token, providerType, ...body })
|
|
21208
|
+
});
|
|
21209
|
+
if (!response.ok) {
|
|
21210
|
+
const data = await response.json().catch(() => null);
|
|
21211
|
+
const message = data?.error?.message || data?.message || `Failed to confirm recovery method`;
|
|
21212
|
+
throw new Error(message);
|
|
21213
|
+
}
|
|
21214
|
+
}, "postRecoveryConfirmation");
|
|
21215
|
+
var calculateShareChecksum = /* @__PURE__ */ __name(async (share) => {
|
|
21216
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(share));
|
|
21217
|
+
return bytesToHex(new Uint8Array(digest));
|
|
21218
|
+
}, "calculateShareChecksum");
|
|
21219
|
+
var RECOVERY_PHRASE_CHALLENGE_COUNT = 2;
|
|
21220
|
+
var selectRecoveryPhraseChallengeIndices = /* @__PURE__ */ __name((wordCount, challengeCount = RECOVERY_PHRASE_CHALLENGE_COUNT) => {
|
|
21221
|
+
if (wordCount < challengeCount) {
|
|
21222
|
+
throw new Error("Recovery phrase does not contain enough words for confirmation");
|
|
21223
|
+
}
|
|
21224
|
+
const indices = /* @__PURE__ */ new Set();
|
|
21225
|
+
const limit = 4294967296 - 4294967296 % wordCount;
|
|
21226
|
+
while (indices.size < challengeCount) {
|
|
21227
|
+
const randomValue = crypto.getRandomValues(new Uint32Array(1))[0];
|
|
21228
|
+
if (randomValue === void 0) throw new Error("Failed to choose recovery phrase words");
|
|
21229
|
+
if (randomValue >= limit) continue;
|
|
21230
|
+
indices.add(randomValue % wordCount);
|
|
21231
|
+
}
|
|
21232
|
+
return [...indices].sort((a, b) => a - b);
|
|
21233
|
+
}, "selectRecoveryPhraseChallengeIndices");
|
|
19486
21234
|
var VERSION_PREFIX_LEN = 4;
|
|
19487
21235
|
var formatVersionedEmailShare = /* @__PURE__ */ __name((emailShare, shareVersion) => shareVersion.toString(16).padStart(VERSION_PREFIX_LEN, "0") + emailShare, "formatVersionedEmailShare");
|
|
19488
21236
|
var parseVersionedEmailShare = /* @__PURE__ */ __name((input) => {
|
|
@@ -19495,44 +21243,532 @@ var parseVersionedEmailShare = /* @__PURE__ */ __name((input) => {
|
|
|
19495
21243
|
}
|
|
19496
21244
|
return { share: input, version: void 0 };
|
|
19497
21245
|
}, "parseVersionedEmailShare");
|
|
19498
|
-
var sendEmailBackupShare = /* @__PURE__ */ __name(async (serverUrl, token, providerType, emailShare, email, shareVersion, tenantId) => {
|
|
19499
|
-
|
|
19500
|
-
|
|
19501
|
-
|
|
19502
|
-
|
|
19503
|
-
|
|
19504
|
-
|
|
19505
|
-
|
|
19506
|
-
|
|
19507
|
-
|
|
19508
|
-
|
|
19509
|
-
|
|
19510
|
-
|
|
19511
|
-
}
|
|
19512
|
-
}, "sendEmailBackupShare");
|
|
19513
|
-
var sendEmailShareToRecoveryEmail = /* @__PURE__ */ __name(async (serverUrl, token, providerType, emailShare, shareVersion, tenantId) => {
|
|
19514
|
-
const payload = shareVersion != null ? formatVersionedEmailShare(emailShare, shareVersion) : emailShare;
|
|
21246
|
+
var sendEmailBackupShare = /* @__PURE__ */ __name(async (serverUrl, token, providerType, emailShare, email, escrowRelayPublicKey, escrowRelayKeyId, emailBranding, shareVersion, didAuthVp, tenantId) => {
|
|
21247
|
+
const recoveryKey = shareVersion != null ? formatVersionedEmailShare(emailShare, shareVersion) : emailShare;
|
|
21248
|
+
const confirmationCode = generateEmailRelayConfirmationCode();
|
|
21249
|
+
const relayPayload = await encryptEmailRelayPayload(
|
|
21250
|
+
{
|
|
21251
|
+
targetEmail: email,
|
|
21252
|
+
recoveryKey,
|
|
21253
|
+
confirmationCode,
|
|
21254
|
+
branding: emailBranding
|
|
21255
|
+
},
|
|
21256
|
+
escrowRelayPublicKey,
|
|
21257
|
+
escrowRelayKeyId
|
|
21258
|
+
);
|
|
19515
21259
|
const response = await fetch(`${serverUrl}/keys/email-backup`, {
|
|
19516
21260
|
method: "POST",
|
|
19517
|
-
headers: buildHeaders(token,
|
|
21261
|
+
headers: buildHeaders(token, didAuthVp, tenantId),
|
|
19518
21262
|
body: JSON.stringify({
|
|
19519
21263
|
authToken: token,
|
|
19520
21264
|
providerType,
|
|
19521
|
-
|
|
19522
|
-
|
|
21265
|
+
relayPayload,
|
|
21266
|
+
confirmationCode,
|
|
21267
|
+
email,
|
|
21268
|
+
shareVersion
|
|
19523
21269
|
})
|
|
19524
21270
|
});
|
|
19525
21271
|
if (!response.ok) {
|
|
19526
|
-
throw new Error(`Failed to send recovery share
|
|
21272
|
+
throw new Error(`Failed to send recovery share: ${describeHttpStatus(response)}`);
|
|
21273
|
+
}
|
|
21274
|
+
}, "sendEmailBackupShare");
|
|
21275
|
+
var rotationChain = Promise.resolve();
|
|
21276
|
+
var withRotationLock = /* @__PURE__ */ __name((operation) => {
|
|
21277
|
+
const run = rotationChain.then(operation, operation);
|
|
21278
|
+
rotationChain = run.catch(() => void 0);
|
|
21279
|
+
return run;
|
|
21280
|
+
}, "withRotationLock");
|
|
21281
|
+
var pendingShareId = /* @__PURE__ */ __name((storageId) => `sss-pending-share:${storageId ?? DEFAULT_DEVICE_SHARE_ID2}`, "pendingShareId");
|
|
21282
|
+
var PENDING_WRITE_EXPIRY_MS = 10 * 60 * 1e3;
|
|
21283
|
+
var MAX_PENDING_SHARE_CANDIDATES = 8;
|
|
21284
|
+
var readPendingShareCandidates = /* @__PURE__ */ __name(async (storage, storageId) => {
|
|
21285
|
+
const raw = await storage.getDeviceShare(pendingShareId(storageId));
|
|
21286
|
+
if (!raw) return [];
|
|
21287
|
+
if (!raw.trimStart().startsWith("{")) return [{ share: raw, createdAt: 0 }];
|
|
21288
|
+
const data = JSON.parse(raw);
|
|
21289
|
+
if (!data || typeof data !== "object" || !("v" in data) || data.v !== 1 || !("candidates" in data) || !Array.isArray(data.candidates) || !data.candidates.every(
|
|
21290
|
+
(candidate) => candidate !== null && typeof candidate === "object" && "share" in candidate && typeof candidate.share === "string" && "createdAt" in candidate && typeof candidate.createdAt === "number" && Number.isFinite(candidate.createdAt) && candidate.createdAt >= 0
|
|
21291
|
+
))
|
|
21292
|
+
throw new Error("Invalid pending share candidates");
|
|
21293
|
+
return data.candidates;
|
|
21294
|
+
}, "readPendingShareCandidates");
|
|
21295
|
+
var clearPendingShareCandidates = /* @__PURE__ */ __name(async (storage, storageId) => storage.clearAllShares(pendingShareId(storageId)), "clearPendingShareCandidates");
|
|
21296
|
+
var writePendingShareCandidates = /* @__PURE__ */ __name(async (storage, candidates, storageId) => {
|
|
21297
|
+
if (!candidates.length) return clearPendingShareCandidates(storage, storageId);
|
|
21298
|
+
await storage.storeDeviceShare(JSON.stringify({ v: 1, candidates }), pendingShareId(storageId));
|
|
21299
|
+
}, "writePendingShareCandidates");
|
|
21300
|
+
var addPendingShareCandidate = /* @__PURE__ */ __name(async (storage, candidate, storageId) => {
|
|
21301
|
+
const candidates = await readPendingShareCandidates(storage, storageId);
|
|
21302
|
+
if (candidates.length >= MAX_PENDING_SHARE_CANDIDATES) {
|
|
21303
|
+
throw new AtomicUpdateError(
|
|
21304
|
+
"Reconcile the pending share update before writing new shares",
|
|
21305
|
+
"store_device",
|
|
21306
|
+
false
|
|
21307
|
+
);
|
|
21308
|
+
}
|
|
21309
|
+
await writePendingShareCandidates(storage, [...candidates, candidate], storageId);
|
|
21310
|
+
}, "addPendingShareCandidate");
|
|
21311
|
+
var removePendingShareCandidate = /* @__PURE__ */ __name(async (storage, share, storageId) => {
|
|
21312
|
+
const candidates = await readPendingShareCandidates(storage, storageId);
|
|
21313
|
+
await writePendingShareCandidates(
|
|
21314
|
+
storage,
|
|
21315
|
+
candidates.filter((candidate) => candidate.share !== share),
|
|
21316
|
+
storageId
|
|
21317
|
+
);
|
|
21318
|
+
}, "removePendingShareCandidate");
|
|
21319
|
+
var resolvePendingShareCandidates = /* @__PURE__ */ __name(async (storage, storageId, fetchCurrent, expectedDid, didFromPrivateKey, assertActiveUser = () => {
|
|
21320
|
+
}, onPromoted, fetchHistorical) => {
|
|
21321
|
+
const candidates = await readPendingShareCandidates(storage, storageId);
|
|
21322
|
+
const snapshot = await fetchCurrent();
|
|
21323
|
+
assertActiveUser();
|
|
21324
|
+
const { authShare, currentVersion } = snapshot;
|
|
21325
|
+
if (authShare && (currentVersion === null || !Number.isInteger(currentVersion) || currentVersion < 1)) {
|
|
21326
|
+
throw new Error("Current auth share is missing a valid share version");
|
|
21327
|
+
}
|
|
21328
|
+
if (authShare && currentVersion !== null) {
|
|
21329
|
+
for (const candidate of candidates) {
|
|
21330
|
+
const health = await verifyStoredShares(
|
|
21331
|
+
{ getDevice: /* @__PURE__ */ __name(async () => candidate.share, "getDevice"), getAuth: /* @__PURE__ */ __name(async () => authShare, "getAuth") },
|
|
21332
|
+
expectedDid,
|
|
21333
|
+
didFromPrivateKey
|
|
21334
|
+
);
|
|
21335
|
+
assertActiveUser();
|
|
21336
|
+
if (!health.healthy) continue;
|
|
21337
|
+
const privateKey = await reconstructFromShares([candidate.share, authShare]);
|
|
21338
|
+
assertActiveUser();
|
|
21339
|
+
await storage.storeDeviceShare(candidate.share, storageId);
|
|
21340
|
+
await storage.storeShareVersion(currentVersion, storageId);
|
|
21341
|
+
await removePendingShareCandidate(storage, candidate.share, storageId);
|
|
21342
|
+
assertActiveUser();
|
|
21343
|
+
onPromoted?.(snapshot);
|
|
21344
|
+
return { snapshot, privateKey };
|
|
21345
|
+
}
|
|
21346
|
+
}
|
|
21347
|
+
const matched = /* @__PURE__ */ new Set();
|
|
21348
|
+
const history = /* @__PURE__ */ new Map();
|
|
21349
|
+
let historyComplete = true;
|
|
21350
|
+
if (candidates.length && currentVersion !== null) {
|
|
21351
|
+
for (let version = currentVersion - 1; version >= 1 && version >= currentVersion - MAX_RECONCILIATION_HISTORY; version--) {
|
|
21352
|
+
if (!fetchHistorical) {
|
|
21353
|
+
historyComplete = false;
|
|
21354
|
+
break;
|
|
21355
|
+
}
|
|
21356
|
+
try {
|
|
21357
|
+
const share = await fetchHistorical(version);
|
|
21358
|
+
if (share) history.set(version, share);
|
|
21359
|
+
} catch {
|
|
21360
|
+
historyComplete = false;
|
|
21361
|
+
}
|
|
21362
|
+
assertActiveUser();
|
|
21363
|
+
}
|
|
19527
21364
|
}
|
|
19528
|
-
|
|
21365
|
+
const mainShare = await storage.getDeviceShare(storageId);
|
|
21366
|
+
let mainHealthy = false;
|
|
21367
|
+
const retainedShares = [...history.values(), ...authShare ? [authShare] : []];
|
|
21368
|
+
if (mainShare) {
|
|
21369
|
+
for (const share of retainedShares) {
|
|
21370
|
+
const health = await verifyStoredShares(
|
|
21371
|
+
{ getDevice: /* @__PURE__ */ __name(async () => mainShare, "getDevice"), getAuth: /* @__PURE__ */ __name(async () => share, "getAuth") },
|
|
21372
|
+
expectedDid,
|
|
21373
|
+
didFromPrivateKey
|
|
21374
|
+
);
|
|
21375
|
+
assertActiveUser();
|
|
21376
|
+
if (health.healthy) {
|
|
21377
|
+
mainHealthy = true;
|
|
21378
|
+
break;
|
|
21379
|
+
}
|
|
21380
|
+
}
|
|
21381
|
+
}
|
|
21382
|
+
let promoted;
|
|
21383
|
+
for (const candidate of candidates) {
|
|
21384
|
+
for (const [version, share] of history) {
|
|
21385
|
+
const health = await verifyStoredShares(
|
|
21386
|
+
{ getDevice: /* @__PURE__ */ __name(async () => candidate.share, "getDevice"), getAuth: /* @__PURE__ */ __name(async () => share, "getAuth") },
|
|
21387
|
+
expectedDid,
|
|
21388
|
+
didFromPrivateKey
|
|
21389
|
+
);
|
|
21390
|
+
assertActiveUser();
|
|
21391
|
+
if (!health.healthy) continue;
|
|
21392
|
+
matched.add(candidate.share);
|
|
21393
|
+
if (!mainHealthy && !promoted) {
|
|
21394
|
+
await storage.storeDeviceShare(candidate.share, storageId);
|
|
21395
|
+
await storage.storeShareVersion(version, storageId);
|
|
21396
|
+
assertActiveUser();
|
|
21397
|
+
onPromoted?.({ currentVersion: version, authShare: share });
|
|
21398
|
+
promoted = candidate.share;
|
|
21399
|
+
}
|
|
21400
|
+
break;
|
|
21401
|
+
}
|
|
21402
|
+
}
|
|
21403
|
+
const live = candidates.filter(
|
|
21404
|
+
(candidate) => candidate.share !== promoted && (matched.has(candidate.share) || !historyComplete || candidate.createdAt !== 0 && Date.now() - candidate.createdAt <= PENDING_WRITE_EXPIRY_MS)
|
|
21405
|
+
);
|
|
21406
|
+
if (live.length !== candidates.length) {
|
|
21407
|
+
assertActiveUser();
|
|
21408
|
+
await writePendingShareCandidates(storage, live, storageId);
|
|
21409
|
+
}
|
|
21410
|
+
return { snapshot, privateKey: null };
|
|
21411
|
+
}, "resolvePendingShareCandidates");
|
|
21412
|
+
var activeShareUpdates = /* @__PURE__ */ new WeakMap();
|
|
21413
|
+
var shareUpdateStorageOwners = /* @__PURE__ */ new WeakMap();
|
|
21414
|
+
var withShareUpdateLock = /* @__PURE__ */ __name(async (storage, storageId, operation) => {
|
|
21415
|
+
const id = pendingShareId(storageId);
|
|
21416
|
+
const owner = shareUpdateStorageOwners.get(storage) ?? storage;
|
|
21417
|
+
const active = activeShareUpdates.get(owner) ?? /* @__PURE__ */ new Set();
|
|
21418
|
+
activeShareUpdates.set(owner, active);
|
|
21419
|
+
const busy = /* @__PURE__ */ __name(() => new AtomicUpdateError("A share update is already in progress", "store_device", false), "busy");
|
|
21420
|
+
if (active.has(id)) throw busy();
|
|
21421
|
+
active.add(id);
|
|
21422
|
+
try {
|
|
21423
|
+
if (typeof navigator !== "undefined" && navigator.locks) {
|
|
21424
|
+
return await navigator.locks.request(id, { ifAvailable: true }, async (lock) => {
|
|
21425
|
+
if (!lock) throw busy();
|
|
21426
|
+
return operation();
|
|
21427
|
+
});
|
|
21428
|
+
}
|
|
21429
|
+
return await operation();
|
|
21430
|
+
} finally {
|
|
21431
|
+
active.delete(id);
|
|
21432
|
+
}
|
|
21433
|
+
}, "withShareUpdateLock");
|
|
21434
|
+
var persistSharesWithoutLock = /* @__PURE__ */ __name(async (privateKey, serverUrl, token, providerType, primaryDid, storage, storageId, didFromPrivateKey, signDidAuthVp, tenantId, onPromoted, assertActiveUser = () => {
|
|
21435
|
+
}) => {
|
|
21436
|
+
if (primaryDid && didFromPrivateKey) {
|
|
21437
|
+
const derivedDid = await didFromPrivateKey(privateKey);
|
|
21438
|
+
if (derivedDid && derivedDid !== primaryDid) {
|
|
21439
|
+
throw new Error(
|
|
21440
|
+
"rotateShares: key does not match expected DID \u2014 refusing to overwrite server shares"
|
|
21441
|
+
);
|
|
21442
|
+
}
|
|
21443
|
+
}
|
|
21444
|
+
const { snapshot } = await resolvePendingShareCandidates(
|
|
21445
|
+
storage,
|
|
21446
|
+
storageId,
|
|
21447
|
+
async () => {
|
|
21448
|
+
const data = await fetchAuthShareRaw(
|
|
21449
|
+
serverUrl,
|
|
21450
|
+
token,
|
|
21451
|
+
providerType,
|
|
21452
|
+
void 0,
|
|
21453
|
+
tenantId
|
|
21454
|
+
);
|
|
21455
|
+
return {
|
|
21456
|
+
currentVersion: data?.shareVersion ?? null,
|
|
21457
|
+
authShare: authShareToString(data?.authShare)
|
|
21458
|
+
};
|
|
21459
|
+
},
|
|
21460
|
+
primaryDid,
|
|
21461
|
+
didFromPrivateKey ?? (async (key) => key === privateKey ? primaryDid : `${primaryDid}:mismatch`),
|
|
21462
|
+
assertActiveUser,
|
|
21463
|
+
onPromoted,
|
|
21464
|
+
async (version) => authShareToString(
|
|
21465
|
+
(await fetchAuthShareRaw(serverUrl, token, providerType, version, tenantId))?.authShare
|
|
21466
|
+
)
|
|
21467
|
+
);
|
|
21468
|
+
const didAuthVp = signDidAuthVp ? await requestFreshDidAuthVp(serverUrl, privateKey, primaryDid, signDidAuthVp, tenantId) : void 0;
|
|
21469
|
+
assertActiveUser();
|
|
21470
|
+
let shareVersion;
|
|
21471
|
+
let stagedShare = "";
|
|
21472
|
+
const shares = await atomicShareUpdate(privateKey, {
|
|
21473
|
+
storeDevice: /* @__PURE__ */ __name(async (share) => {
|
|
21474
|
+
assertActiveUser();
|
|
21475
|
+
stagedShare = share;
|
|
21476
|
+
await addPendingShareCandidate(storage, { share, createdAt: Date.now() }, storageId);
|
|
21477
|
+
}, "storeDevice"),
|
|
21478
|
+
clearDevice: /* @__PURE__ */ __name(() => removePendingShareCandidate(storage, stagedShare, storageId), "clearDevice"),
|
|
21479
|
+
storeAuth: /* @__PURE__ */ __name(async (share) => {
|
|
21480
|
+
assertActiveUser();
|
|
21481
|
+
const result = await putAuthShare(
|
|
21482
|
+
serverUrl,
|
|
21483
|
+
token,
|
|
21484
|
+
providerType,
|
|
21485
|
+
share,
|
|
21486
|
+
primaryDid,
|
|
21487
|
+
didAuthVp,
|
|
21488
|
+
tenantId,
|
|
21489
|
+
snapshot.currentVersion ?? 0
|
|
21490
|
+
);
|
|
21491
|
+
shareVersion = result.shareVersion;
|
|
21492
|
+
}, "storeAuth")
|
|
21493
|
+
});
|
|
21494
|
+
if (shareVersion === void 0) {
|
|
21495
|
+
throw new Error("Server did not return a share version");
|
|
21496
|
+
}
|
|
21497
|
+
await storage.storeDeviceShare(shares.deviceShare, storageId);
|
|
21498
|
+
await storage.storeShareVersion(shareVersion, storageId);
|
|
21499
|
+
await removePendingShareCandidate(storage, shares.deviceShare, storageId);
|
|
21500
|
+
assertActiveUser();
|
|
21501
|
+
return { shares, shareVersion };
|
|
21502
|
+
}, "persistSharesWithoutLock");
|
|
21503
|
+
var persistSharesAtomically = /* @__PURE__ */ __name((...args) => withShareUpdateLock(
|
|
21504
|
+
args[5],
|
|
21505
|
+
args[6],
|
|
21506
|
+
() => withRotationLock(() => persistSharesWithoutLock(...args))
|
|
21507
|
+
), "persistSharesAtomically");
|
|
19529
21508
|
function createSSSStrategy(config) {
|
|
19530
|
-
const {
|
|
21509
|
+
const {
|
|
21510
|
+
serverUrl,
|
|
21511
|
+
enableEmailBackupShare = false,
|
|
21512
|
+
escrowRelayPublicKey = "",
|
|
21513
|
+
escrowRelayKeyId = "",
|
|
21514
|
+
emailBranding,
|
|
21515
|
+
tenantId
|
|
21516
|
+
} = config;
|
|
19531
21517
|
const storage = config.storage || defaultStorage;
|
|
21518
|
+
let storageGeneration = 0;
|
|
21519
|
+
const localWrites = /* @__PURE__ */ new Set();
|
|
21520
|
+
const guardedStorage = /* @__PURE__ */ __name(() => {
|
|
21521
|
+
const generation = storageGeneration;
|
|
21522
|
+
const write = /* @__PURE__ */ __name((operation) => {
|
|
21523
|
+
if (generation !== storageGeneration) {
|
|
21524
|
+
return Promise.reject(new Error("This recovery request was cancelled."));
|
|
21525
|
+
}
|
|
21526
|
+
const pending = operation();
|
|
21527
|
+
localWrites.add(pending);
|
|
21528
|
+
return pending.finally(() => localWrites.delete(pending));
|
|
21529
|
+
}, "write");
|
|
21530
|
+
const guarded = {
|
|
21531
|
+
...storage,
|
|
21532
|
+
storeDeviceShare: /* @__PURE__ */ __name((share, id) => write(() => storage.storeDeviceShare(share, id)), "storeDeviceShare"),
|
|
21533
|
+
storeShareVersion: /* @__PURE__ */ __name((version, id) => write(() => storage.storeShareVersion(version, id)), "storeShareVersion"),
|
|
21534
|
+
clearAllShares: /* @__PURE__ */ __name((id) => write(() => storage.clearAllShares(id)), "clearAllShares"),
|
|
21535
|
+
deleteDeviceShare: /* @__PURE__ */ __name((id) => write(() => storage.deleteDeviceShare(id)), "deleteDeviceShare")
|
|
21536
|
+
};
|
|
21537
|
+
shareUpdateStorageOwners.set(guarded, storage);
|
|
21538
|
+
return guarded;
|
|
21539
|
+
}, "guardedStorage");
|
|
19532
21540
|
let activeStorageId;
|
|
19533
21541
|
let lastEmailShare;
|
|
19534
21542
|
let lastShareVersion;
|
|
19535
|
-
let
|
|
21543
|
+
let pendingPhraseConfirmation;
|
|
21544
|
+
let pendingBackupConfirmation;
|
|
21545
|
+
let pendingIdentityRecovery;
|
|
21546
|
+
let lastServerSnapshot = null;
|
|
21547
|
+
let escrowEnrollmentInFlight;
|
|
21548
|
+
let staleEscrowReenrollAttempted = false;
|
|
21549
|
+
let unenrolledRotation;
|
|
21550
|
+
const escrowRequest = /* @__PURE__ */ __name(async (path, init, pinAttempt = false) => {
|
|
21551
|
+
const response = await fetch(`${serverUrl}/keys/escrow${path}`, {
|
|
21552
|
+
signal: requestTimeoutSignal(),
|
|
21553
|
+
...init
|
|
21554
|
+
});
|
|
21555
|
+
if (!response.ok) {
|
|
21556
|
+
if (!pinAttempt && path === "/recover" && response.status === 429) {
|
|
21557
|
+
const body = await response.json().catch(() => void 0);
|
|
21558
|
+
const message = body && typeof body === "object" && "message" in body && typeof body.message === "string" ? body.message : "";
|
|
21559
|
+
const retryAfter = /Try again after (\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z)\./.exec(
|
|
21560
|
+
message
|
|
21561
|
+
)?.[1];
|
|
21562
|
+
throw new EscrowHoldRestartThrottledError(
|
|
21563
|
+
retryAfter && Number.isFinite(Date.parse(retryAfter)) ? retryAfter : void 0
|
|
21564
|
+
);
|
|
21565
|
+
}
|
|
21566
|
+
if (pinAttempt && response.status === 429) {
|
|
21567
|
+
const body = await response.json().catch(() => void 0);
|
|
21568
|
+
if (body && typeof body === "object" && "message" in body && body.message === import_types3.ESCROW_PIN_LOCKED_MESSAGE) {
|
|
21569
|
+
throw new EscrowPinLockedError();
|
|
21570
|
+
}
|
|
21571
|
+
throw new EscrowPinThrottledError();
|
|
21572
|
+
}
|
|
21573
|
+
if (pinAttempt && response.status === 403) {
|
|
21574
|
+
const body = await response.json().catch(() => void 0);
|
|
21575
|
+
if (body && typeof body === "object" && "message" in body && body.message === import_types3.ESCROW_PIN_UNAVAILABLE_MESSAGE) {
|
|
21576
|
+
throw new EscrowPinUnavailableError();
|
|
21577
|
+
}
|
|
21578
|
+
if (body && typeof body === "object" && "message" in body && typeof body.message === "string" && body.message.startsWith("Incorrect PIN.")) {
|
|
21579
|
+
const match = import_types3.ESCROW_PIN_MISMATCH_PATTERN.exec(body.message);
|
|
21580
|
+
const remaining = match ? Number(match[1]) : 0;
|
|
21581
|
+
throw new EscrowPinMismatchError(
|
|
21582
|
+
Number.isSafeInteger(remaining) && remaining >= 0 && remaining < ESCROW_PIN_MAX_ATTEMPTS ? remaining : 0
|
|
21583
|
+
);
|
|
21584
|
+
}
|
|
21585
|
+
}
|
|
21586
|
+
throw new EscrowRequestError(response.status);
|
|
21587
|
+
}
|
|
21588
|
+
try {
|
|
21589
|
+
return await response.json();
|
|
21590
|
+
} catch {
|
|
21591
|
+
throw new EscrowRequestError(response.status);
|
|
21592
|
+
}
|
|
21593
|
+
}, "escrowRequest");
|
|
21594
|
+
const fetchVerifiedEnclaveKey = /* @__PURE__ */ __name(async () => {
|
|
21595
|
+
if (!config.escrow?.enabled) throw new Error("Escrow enrollment is disabled");
|
|
21596
|
+
const nonce = crypto.getRandomValues(new Uint8Array(32));
|
|
21597
|
+
const nonceHex = Array.from(nonce, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
21598
|
+
const { attestation } = await escrowRequest(
|
|
21599
|
+
`/attestation?nonce=${nonceHex}`,
|
|
21600
|
+
{
|
|
21601
|
+
method: "GET",
|
|
21602
|
+
headers: buildHeaders("", void 0, tenantId)
|
|
21603
|
+
}
|
|
21604
|
+
);
|
|
21605
|
+
return verifyEnclaveAttestation(attestation, config.escrow.attestation, nonce);
|
|
21606
|
+
}, "fetchVerifiedEnclaveKey");
|
|
21607
|
+
const enrollEscrow = /* @__PURE__ */ __name(async (token, providerType, privateKey, primaryDid, shares, shareVersion, signDidAuthVp, verifiedKey, pinMaterial, clearPin = false) => {
|
|
21608
|
+
if (!config.escrow?.enabled) throw new Error("Escrow enrollment is disabled");
|
|
21609
|
+
if (!signDidAuthVp) throw new Error("DID proof signing is required for escrow enrollment");
|
|
21610
|
+
const { publicKey, keyId } = verifiedKey ?? await fetchVerifiedEnclaveKey();
|
|
21611
|
+
const envelope = await encryptEscrowBlob(
|
|
21612
|
+
{
|
|
21613
|
+
recoveryShare: shares.recoveryShare,
|
|
21614
|
+
did: primaryDid,
|
|
21615
|
+
shareVersion,
|
|
21616
|
+
...pinMaterial ? { pinVerifier: pinMaterial.pinVerifier } : {}
|
|
21617
|
+
},
|
|
21618
|
+
publicKey,
|
|
21619
|
+
keyId
|
|
21620
|
+
);
|
|
21621
|
+
const vp = await requestFreshDidAuthVp(
|
|
21622
|
+
serverUrl,
|
|
21623
|
+
privateKey,
|
|
21624
|
+
primaryDid,
|
|
21625
|
+
signDidAuthVp,
|
|
21626
|
+
tenantId
|
|
21627
|
+
);
|
|
21628
|
+
await escrowRequest("", {
|
|
21629
|
+
method: "POST",
|
|
21630
|
+
headers: buildHeaders(token, vp, tenantId),
|
|
21631
|
+
body: JSON.stringify({
|
|
21632
|
+
authToken: token,
|
|
21633
|
+
providerType,
|
|
21634
|
+
envelope,
|
|
21635
|
+
shareVersion,
|
|
21636
|
+
enclaveKeyId: keyId,
|
|
21637
|
+
...pinMaterial ? { pinSalt: pinMaterial.pinSalt } : {},
|
|
21638
|
+
...clearPin ? { clearPin: true } : {}
|
|
21639
|
+
})
|
|
21640
|
+
});
|
|
21641
|
+
}, "enrollEscrow");
|
|
21642
|
+
const tryEnrollEscrow = /* @__PURE__ */ __name(async (...args) => {
|
|
21643
|
+
if (!config.escrow?.enabled) return;
|
|
21644
|
+
try {
|
|
21645
|
+
await enrollEscrow(...args);
|
|
21646
|
+
} catch (err) {
|
|
21647
|
+
try {
|
|
21648
|
+
if (config.onEscrowError) config.onEscrowError(err);
|
|
21649
|
+
else console.warn("SSS: escrow enrollment failed");
|
|
21650
|
+
} catch {
|
|
21651
|
+
console.warn("SSS: escrow error reporting failed");
|
|
21652
|
+
}
|
|
21653
|
+
}
|
|
21654
|
+
}, "tryEnrollEscrow");
|
|
21655
|
+
const ensureEscrowEnrollmentUnguarded = /* @__PURE__ */ __name(async (self, params, storage2, forceRotate = false) => {
|
|
21656
|
+
if (!config.escrow?.enabled) return { enrolled: false, reason: "disabled" };
|
|
21657
|
+
const pin = params.options?.pin;
|
|
21658
|
+
if (pin !== void 0) {
|
|
21659
|
+
const validation = validatePin(pin);
|
|
21660
|
+
if (!validation.ok)
|
|
21661
|
+
throw new Error(
|
|
21662
|
+
validation.reason === "length" ? "PIN must contain 6\u201312 digits." : "Choose a PIN without trivial or sequential patterns."
|
|
21663
|
+
);
|
|
21664
|
+
}
|
|
21665
|
+
const status = await self.fetchServerKeyStatus(params.token, params.providerType);
|
|
21666
|
+
if (status.escrowOptedOut) return { enrolled: false, reason: "opted-out" };
|
|
21667
|
+
const currentlyEnrolled = status.shareVersion !== null && status.recoveryMethods.some(
|
|
21668
|
+
(method) => method.type === "escrow" && method.shareVersion === status.shareVersion && (Boolean(method.confirmedAt) || "confirmationStatus" in method && method.confirmationStatus === "confirmed")
|
|
21669
|
+
);
|
|
21670
|
+
const repairingStaleBlob = pin === void 0 && !forceRotate && currentlyEnrolled && !!status.escrowStale && !staleEscrowReenrollAttempted;
|
|
21671
|
+
if (!forceRotate && pin === void 0 && currentlyEnrolled && !repairingStaleBlob)
|
|
21672
|
+
return { enrolled: true, changed: false };
|
|
21673
|
+
if (repairingStaleBlob) staleEscrowReenrollAttempted = true;
|
|
21674
|
+
if (!status.primaryDid) throw new Error("Cannot enroll escrow without a primary DID");
|
|
21675
|
+
if (!params.signDidAuthVp) {
|
|
21676
|
+
throw new Error("DID proof signing is required for escrow enrollment");
|
|
21677
|
+
}
|
|
21678
|
+
try {
|
|
21679
|
+
if (!forceRotate && pin === void 0 && unenrolledRotation && unenrolledRotation.shareVersion === status.shareVersion && unenrolledRotation.primaryDid === status.primaryDid) {
|
|
21680
|
+
const retry = unenrolledRotation;
|
|
21681
|
+
await enrollEscrow(
|
|
21682
|
+
params.token,
|
|
21683
|
+
params.providerType,
|
|
21684
|
+
params.privateKey,
|
|
21685
|
+
retry.primaryDid,
|
|
21686
|
+
retry.shares,
|
|
21687
|
+
retry.shareVersion,
|
|
21688
|
+
params.signDidAuthVp,
|
|
21689
|
+
void 0,
|
|
21690
|
+
void 0,
|
|
21691
|
+
retry.clearPin
|
|
21692
|
+
);
|
|
21693
|
+
unenrolledRotation = void 0;
|
|
21694
|
+
return { enrolled: true, changed: true, shareVersion: retry.shareVersion };
|
|
21695
|
+
}
|
|
21696
|
+
const verifiedKey = await fetchVerifiedEnclaveKey();
|
|
21697
|
+
const pinSalt = pin !== void 0 ? generatePinSalt() : void 0;
|
|
21698
|
+
const pinMaterial = pin !== void 0 && pinSalt !== void 0 ? { pinSalt, pinVerifier: await derivePinProof(pin, pinSalt) } : void 0;
|
|
21699
|
+
const storageId = activeStorageId;
|
|
21700
|
+
const primaryDid = status.primaryDid;
|
|
21701
|
+
const { shares, shareVersion } = await withShareUpdateLock(
|
|
21702
|
+
storage2,
|
|
21703
|
+
storageId,
|
|
21704
|
+
() => persistSharesWithoutLock(
|
|
21705
|
+
params.privateKey,
|
|
21706
|
+
serverUrl,
|
|
21707
|
+
params.token,
|
|
21708
|
+
params.providerType,
|
|
21709
|
+
primaryDid,
|
|
21710
|
+
storage2,
|
|
21711
|
+
storageId,
|
|
21712
|
+
void 0,
|
|
21713
|
+
params.signDidAuthVp,
|
|
21714
|
+
tenantId
|
|
21715
|
+
)
|
|
21716
|
+
);
|
|
21717
|
+
lastEmailShare = shares.emailShare;
|
|
21718
|
+
lastShareVersion = shareVersion;
|
|
21719
|
+
lastServerSnapshot = {
|
|
21720
|
+
currentVersion: shareVersion,
|
|
21721
|
+
resolvedVersion: shareVersion,
|
|
21722
|
+
authShare: shares.authShare,
|
|
21723
|
+
primaryDid: status.primaryDid
|
|
21724
|
+
};
|
|
21725
|
+
unenrolledRotation = pinMaterial ? void 0 : { shares, shareVersion, primaryDid: status.primaryDid, clearPin: forceRotate };
|
|
21726
|
+
await enrollEscrow(
|
|
21727
|
+
params.token,
|
|
21728
|
+
params.providerType,
|
|
21729
|
+
params.privateKey,
|
|
21730
|
+
status.primaryDid,
|
|
21731
|
+
shares,
|
|
21732
|
+
shareVersion,
|
|
21733
|
+
params.signDidAuthVp,
|
|
21734
|
+
verifiedKey,
|
|
21735
|
+
pinMaterial,
|
|
21736
|
+
forceRotate
|
|
21737
|
+
);
|
|
21738
|
+
unenrolledRotation = void 0;
|
|
21739
|
+
return { enrolled: true, changed: true, shareVersion };
|
|
21740
|
+
} catch (err) {
|
|
21741
|
+
if (!repairingStaleBlob) throw err;
|
|
21742
|
+
try {
|
|
21743
|
+
if (config.onEscrowError) config.onEscrowError(err);
|
|
21744
|
+
else console.warn("SSS: escrow enrollment failed");
|
|
21745
|
+
} catch {
|
|
21746
|
+
console.warn("SSS: escrow error reporting failed");
|
|
21747
|
+
}
|
|
21748
|
+
return { enrolled: true, changed: false };
|
|
21749
|
+
}
|
|
21750
|
+
}, "ensureEscrowEnrollmentUnguarded");
|
|
21751
|
+
const recordPromotion = /* @__PURE__ */ __name((primaryDid) => (snapshot) => {
|
|
21752
|
+
lastEmailShare = void 0;
|
|
21753
|
+
lastShareVersion = snapshot.currentVersion ?? void 0;
|
|
21754
|
+
lastServerSnapshot = {
|
|
21755
|
+
...snapshot,
|
|
21756
|
+
resolvedVersion: snapshot.currentVersion,
|
|
21757
|
+
primaryDid
|
|
21758
|
+
};
|
|
21759
|
+
}, "recordPromotion");
|
|
21760
|
+
const captureActiveUserGuard = /* @__PURE__ */ __name(() => {
|
|
21761
|
+
const storageId = activeStorageId;
|
|
21762
|
+
return () => {
|
|
21763
|
+
if (activeStorageId !== storageId) {
|
|
21764
|
+
throw new AtomicUpdateError(
|
|
21765
|
+
"Active account changed during share update",
|
|
21766
|
+
"verify_stored",
|
|
21767
|
+
false
|
|
21768
|
+
);
|
|
21769
|
+
}
|
|
21770
|
+
};
|
|
21771
|
+
}, "captureActiveUserGuard");
|
|
19536
21772
|
return {
|
|
19537
21773
|
name: "sss",
|
|
19538
21774
|
capabilities: {
|
|
@@ -19543,23 +21779,31 @@ function createSSSStrategy(config) {
|
|
|
19543
21779
|
},
|
|
19544
21780
|
// --- User scoping ---
|
|
19545
21781
|
setActiveUser(userId) {
|
|
21782
|
+
if (activeStorageId !== `sss-device-share:${userId}`) storageGeneration++;
|
|
19546
21783
|
activeStorageId = `sss-device-share:${userId}`;
|
|
21784
|
+
lastServerSnapshot = null;
|
|
21785
|
+
pendingPhraseConfirmation = void 0;
|
|
21786
|
+
pendingBackupConfirmation = void 0;
|
|
19547
21787
|
},
|
|
19548
21788
|
// --- Key lifecycle ---
|
|
19549
21789
|
async hasLocalKey() {
|
|
19550
21790
|
if (await storage.hasDeviceShare(activeStorageId)) return true;
|
|
21791
|
+
if ((await readPendingShareCandidates(storage, activeStorageId)).length) return true;
|
|
19551
21792
|
if (activeStorageId) {
|
|
19552
21793
|
return storage.hasDeviceShare();
|
|
19553
21794
|
}
|
|
19554
21795
|
return false;
|
|
19555
21796
|
},
|
|
19556
21797
|
async getLocalKey() {
|
|
19557
|
-
const
|
|
21798
|
+
const storage2 = guardedStorage();
|
|
21799
|
+
const scoped = await storage2.getDeviceShare(activeStorageId);
|
|
19558
21800
|
if (scoped) return scoped;
|
|
21801
|
+
const pending = await readPendingShareCandidates(storage2, activeStorageId);
|
|
21802
|
+
if (pending.length) return pending[pending.length - 1].share;
|
|
19559
21803
|
if (activeStorageId) {
|
|
19560
|
-
const legacy = await
|
|
21804
|
+
const legacy = await storage2.getDeviceShare();
|
|
19561
21805
|
if (legacy) {
|
|
19562
|
-
await
|
|
21806
|
+
await storage2.storeDeviceShare(legacy, activeStorageId);
|
|
19563
21807
|
return legacy;
|
|
19564
21808
|
}
|
|
19565
21809
|
}
|
|
@@ -19568,8 +21812,20 @@ function createSSSStrategy(config) {
|
|
|
19568
21812
|
async storeLocalKey(key) {
|
|
19569
21813
|
return storage.storeDeviceShare(key, activeStorageId);
|
|
19570
21814
|
},
|
|
19571
|
-
async clearLocalKeys() {
|
|
19572
|
-
|
|
21815
|
+
async clearLocalKeys(options) {
|
|
21816
|
+
const storageId = activeStorageId;
|
|
21817
|
+
if (options?.preservePending) {
|
|
21818
|
+
const storage2 = guardedStorage();
|
|
21819
|
+
return withShareUpdateLock(
|
|
21820
|
+
storage2,
|
|
21821
|
+
storageId,
|
|
21822
|
+
() => storage2.deleteDeviceShare(storageId)
|
|
21823
|
+
);
|
|
21824
|
+
}
|
|
21825
|
+
storageGeneration++;
|
|
21826
|
+
await Promise.allSettled(localWrites);
|
|
21827
|
+
await clearPendingShareCandidates(storage, storageId);
|
|
21828
|
+
return storage.clearAllShares(storageId);
|
|
19573
21829
|
},
|
|
19574
21830
|
async splitKey(privateKey) {
|
|
19575
21831
|
const { shares } = await splitAndVerify(privateKey);
|
|
@@ -19593,9 +21849,175 @@ function createSSSStrategy(config) {
|
|
|
19593
21849
|
);
|
|
19594
21850
|
return result.healthy;
|
|
19595
21851
|
},
|
|
21852
|
+
async getFreshDidAuthVp(privateKey, did, signDidAuthVp) {
|
|
21853
|
+
return requestFreshDidAuthVp(serverUrl, privateKey, did, signDidAuthVp, tenantId);
|
|
21854
|
+
},
|
|
21855
|
+
async atomicUpdateShares(params) {
|
|
21856
|
+
const storage2 = guardedStorage();
|
|
21857
|
+
const result = await persistSharesAtomically(
|
|
21858
|
+
params.privateKey,
|
|
21859
|
+
serverUrl,
|
|
21860
|
+
params.token,
|
|
21861
|
+
params.providerType,
|
|
21862
|
+
params.did,
|
|
21863
|
+
storage2,
|
|
21864
|
+
activeStorageId,
|
|
21865
|
+
void 0,
|
|
21866
|
+
params.signDidAuthVp,
|
|
21867
|
+
tenantId,
|
|
21868
|
+
recordPromotion(params.did),
|
|
21869
|
+
captureActiveUserGuard()
|
|
21870
|
+
);
|
|
21871
|
+
lastEmailShare = result.shares.emailShare;
|
|
21872
|
+
lastShareVersion = result.shareVersion;
|
|
21873
|
+
lastServerSnapshot = {
|
|
21874
|
+
currentVersion: result.shareVersion,
|
|
21875
|
+
resolvedVersion: result.shareVersion,
|
|
21876
|
+
authShare: result.shares.authShare,
|
|
21877
|
+
primaryDid: params.did
|
|
21878
|
+
};
|
|
21879
|
+
},
|
|
21880
|
+
async reconcileShares(params) {
|
|
21881
|
+
const storage2 = guardedStorage();
|
|
21882
|
+
const storageId = activeStorageId;
|
|
21883
|
+
const assertActiveUser = /* @__PURE__ */ __name(() => {
|
|
21884
|
+
if (activeStorageId !== storageId) {
|
|
21885
|
+
throw new AtomicUpdateError(
|
|
21886
|
+
"Active account changed during reconciliation",
|
|
21887
|
+
"verify_stored",
|
|
21888
|
+
false
|
|
21889
|
+
);
|
|
21890
|
+
}
|
|
21891
|
+
}, "assertActiveUser");
|
|
21892
|
+
return withShareUpdateLock(storage2, storageId, async () => {
|
|
21893
|
+
let deviceShare = await storage2.getDeviceShare(storageId);
|
|
21894
|
+
const pending = await readPendingShareCandidates(storage2, storageId);
|
|
21895
|
+
if (!deviceShare && !pending.length) return null;
|
|
21896
|
+
const resolution = await resolvePendingShareCandidates(
|
|
21897
|
+
storage2,
|
|
21898
|
+
storageId,
|
|
21899
|
+
async () => {
|
|
21900
|
+
const data = await fetchAuthShareRaw(
|
|
21901
|
+
serverUrl,
|
|
21902
|
+
params.token,
|
|
21903
|
+
params.providerType,
|
|
21904
|
+
void 0,
|
|
21905
|
+
tenantId
|
|
21906
|
+
);
|
|
21907
|
+
return {
|
|
21908
|
+
currentVersion: data?.shareVersion ?? null,
|
|
21909
|
+
authShare: authShareToString(data?.authShare)
|
|
21910
|
+
};
|
|
21911
|
+
},
|
|
21912
|
+
params.expectedDid,
|
|
21913
|
+
params.didFromPrivateKey,
|
|
21914
|
+
assertActiveUser,
|
|
21915
|
+
recordPromotion(params.expectedDid),
|
|
21916
|
+
async (version) => authShareToString(
|
|
21917
|
+
(await fetchAuthShareRaw(
|
|
21918
|
+
serverUrl,
|
|
21919
|
+
params.token,
|
|
21920
|
+
params.providerType,
|
|
21921
|
+
version,
|
|
21922
|
+
tenantId
|
|
21923
|
+
))?.authShare
|
|
21924
|
+
)
|
|
21925
|
+
);
|
|
21926
|
+
assertActiveUser();
|
|
21927
|
+
if (resolution.privateKey) {
|
|
21928
|
+
return { privateKey: resolution.privateKey, did: params.expectedDid };
|
|
21929
|
+
}
|
|
21930
|
+
const { currentVersion, authShare: currentAuthShare } = resolution.snapshot;
|
|
21931
|
+
if (currentVersion === null && !currentAuthShare) return null;
|
|
21932
|
+
deviceShare = await storage2.getDeviceShare(storageId);
|
|
21933
|
+
const localVersion = await storage2.getShareVersion(storageId);
|
|
21934
|
+
if (!deviceShare) return null;
|
|
21935
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
21936
|
+
const addCandidate = /* @__PURE__ */ __name((version, authShare) => {
|
|
21937
|
+
if (version !== null && authShare && !candidates.has(version)) {
|
|
21938
|
+
candidates.set(version, authShare);
|
|
21939
|
+
}
|
|
21940
|
+
}, "addCandidate");
|
|
21941
|
+
addCandidate(
|
|
21942
|
+
lastServerSnapshot?.resolvedVersion ?? null,
|
|
21943
|
+
lastServerSnapshot?.authShare ?? null
|
|
21944
|
+
);
|
|
21945
|
+
addCandidate(currentVersion, currentAuthShare);
|
|
21946
|
+
const versionsToTry = /* @__PURE__ */ new Set();
|
|
21947
|
+
if (localVersion !== null) versionsToTry.add(localVersion);
|
|
21948
|
+
if (currentVersion !== null) {
|
|
21949
|
+
for (let version = currentVersion; version >= 1 && version >= currentVersion - MAX_RECONCILIATION_HISTORY; version--) {
|
|
21950
|
+
versionsToTry.add(version);
|
|
21951
|
+
}
|
|
21952
|
+
}
|
|
21953
|
+
for (const version of versionsToTry) {
|
|
21954
|
+
if (candidates.has(version)) continue;
|
|
21955
|
+
const data = await fetchAuthShareRaw(
|
|
21956
|
+
serverUrl,
|
|
21957
|
+
params.token,
|
|
21958
|
+
params.providerType,
|
|
21959
|
+
version,
|
|
21960
|
+
tenantId
|
|
21961
|
+
);
|
|
21962
|
+
addCandidate(version, authShareToString(data?.authShare));
|
|
21963
|
+
}
|
|
21964
|
+
for (const [candidateVersion, authShare] of candidates) {
|
|
21965
|
+
const health = await verifyStoredShares(
|
|
21966
|
+
{
|
|
21967
|
+
getDevice: /* @__PURE__ */ __name(async () => deviceShare, "getDevice"),
|
|
21968
|
+
getAuth: /* @__PURE__ */ __name(async () => authShare, "getAuth")
|
|
21969
|
+
},
|
|
21970
|
+
params.expectedDid,
|
|
21971
|
+
params.didFromPrivateKey
|
|
21972
|
+
);
|
|
21973
|
+
if (!health.healthy) continue;
|
|
21974
|
+
assertActiveUser();
|
|
21975
|
+
const privateKey = await reconstructFromShares([deviceShare, authShare]);
|
|
21976
|
+
if (candidateVersion === currentVersion) {
|
|
21977
|
+
if (localVersion !== currentVersion) {
|
|
21978
|
+
await storage2.storeShareVersion(candidateVersion, storageId);
|
|
21979
|
+
}
|
|
21980
|
+
assertActiveUser();
|
|
21981
|
+
lastServerSnapshot = {
|
|
21982
|
+
currentVersion,
|
|
21983
|
+
resolvedVersion: candidateVersion,
|
|
21984
|
+
authShare,
|
|
21985
|
+
primaryDid: params.expectedDid
|
|
21986
|
+
};
|
|
21987
|
+
return localVersion === currentVersion ? null : { privateKey, did: params.expectedDid };
|
|
21988
|
+
}
|
|
21989
|
+
const result = await persistSharesWithoutLock(
|
|
21990
|
+
privateKey,
|
|
21991
|
+
serverUrl,
|
|
21992
|
+
params.token,
|
|
21993
|
+
params.providerType,
|
|
21994
|
+
params.expectedDid,
|
|
21995
|
+
storage2,
|
|
21996
|
+
storageId,
|
|
21997
|
+
params.didFromPrivateKey,
|
|
21998
|
+
params.signDidAuthVp,
|
|
21999
|
+
tenantId,
|
|
22000
|
+
recordPromotion(params.expectedDid),
|
|
22001
|
+
assertActiveUser
|
|
22002
|
+
);
|
|
22003
|
+
assertActiveUser();
|
|
22004
|
+
lastEmailShare = result.shares.emailShare;
|
|
22005
|
+
lastShareVersion = result.shareVersion;
|
|
22006
|
+
lastServerSnapshot = {
|
|
22007
|
+
currentVersion: result.shareVersion,
|
|
22008
|
+
resolvedVersion: result.shareVersion,
|
|
22009
|
+
authShare: result.shares.authShare,
|
|
22010
|
+
primaryDid: params.expectedDid
|
|
22011
|
+
};
|
|
22012
|
+
return { privateKey, did: params.expectedDid };
|
|
22013
|
+
}
|
|
22014
|
+
return null;
|
|
22015
|
+
});
|
|
22016
|
+
},
|
|
19596
22017
|
// --- Server communication ---
|
|
19597
22018
|
async fetchServerKeyStatus(token, providerType) {
|
|
19598
|
-
const
|
|
22019
|
+
const storage2 = guardedStorage();
|
|
22020
|
+
const localVersion = await storage2.getShareVersion(activeStorageId);
|
|
19599
22021
|
const data = await fetchAuthShareRaw(
|
|
19600
22022
|
serverUrl,
|
|
19601
22023
|
token,
|
|
@@ -19604,7 +22026,7 @@ function createSSSStrategy(config) {
|
|
|
19604
22026
|
tenantId
|
|
19605
22027
|
);
|
|
19606
22028
|
if (!data) {
|
|
19607
|
-
|
|
22029
|
+
lastServerSnapshot = null;
|
|
19608
22030
|
return {
|
|
19609
22031
|
exists: false,
|
|
19610
22032
|
needsMigration: false,
|
|
@@ -19612,16 +22034,25 @@ function createSSSStrategy(config) {
|
|
|
19612
22034
|
recoveryMethods: [],
|
|
19613
22035
|
authShare: null,
|
|
19614
22036
|
shareVersion: null,
|
|
19615
|
-
maskedRecoveryEmail: null
|
|
22037
|
+
maskedRecoveryEmail: null,
|
|
22038
|
+
sssActivationState: null
|
|
19616
22039
|
};
|
|
19617
22040
|
}
|
|
19618
22041
|
const rawAuthShare = data.authShare;
|
|
19619
|
-
const authShareString =
|
|
22042
|
+
const authShareString = authShareToString(rawAuthShare);
|
|
19620
22043
|
const serverVersion = data.shareVersion ?? null;
|
|
19621
|
-
if (
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
|
|
22044
|
+
if (
|
|
22045
|
+
// Version 0 means "no auth share yet" and must never be pinned locally.
|
|
22046
|
+
serverVersion != null && serverVersion > 0 && localVersion == null && !(await readPendingShareCandidates(storage2, activeStorageId)).length
|
|
22047
|
+
) {
|
|
22048
|
+
storage2.storeShareVersion(serverVersion, activeStorageId).catch((e) => console.warn("SSS: failed to backfill local shareVersion", e));
|
|
22049
|
+
}
|
|
22050
|
+
lastServerSnapshot = {
|
|
22051
|
+
currentVersion: serverVersion,
|
|
22052
|
+
resolvedVersion: authShareString ? localVersion ?? serverVersion : null,
|
|
22053
|
+
authShare: authShareString,
|
|
22054
|
+
primaryDid: data.primaryDid || null
|
|
22055
|
+
};
|
|
19625
22056
|
return {
|
|
19626
22057
|
exists: !!rawAuthShare || !!data.keyProvider || !!data.primaryDid,
|
|
19627
22058
|
needsMigration: data.keyProvider === "web3auth",
|
|
@@ -19629,35 +22060,266 @@ function createSSSStrategy(config) {
|
|
|
19629
22060
|
recoveryMethods: data.recoveryMethods || [],
|
|
19630
22061
|
authShare: authShareString,
|
|
19631
22062
|
shareVersion: serverVersion,
|
|
19632
|
-
maskedRecoveryEmail: data.maskedRecoveryEmail ?? null
|
|
22063
|
+
maskedRecoveryEmail: data.maskedRecoveryEmail ?? null,
|
|
22064
|
+
escrowOptedOut: data.escrowOptedOut === true,
|
|
22065
|
+
escrowPin: data.escrowPin,
|
|
22066
|
+
escrowStale: data.escrowStale,
|
|
22067
|
+
sssActivationState: data.sssActivationState ?? "active"
|
|
19633
22068
|
};
|
|
19634
22069
|
},
|
|
19635
22070
|
async storeAuthShare(token, providerType, authShare, primaryDid, didAuthVp) {
|
|
19636
|
-
const
|
|
19637
|
-
|
|
19638
|
-
|
|
19639
|
-
|
|
19640
|
-
|
|
19641
|
-
|
|
19642
|
-
|
|
19643
|
-
|
|
22071
|
+
const storage2 = guardedStorage();
|
|
22072
|
+
const { shareVersion } = await withRotationLock(
|
|
22073
|
+
() => putAuthShare(
|
|
22074
|
+
serverUrl,
|
|
22075
|
+
token,
|
|
22076
|
+
providerType,
|
|
22077
|
+
authShare,
|
|
22078
|
+
primaryDid,
|
|
22079
|
+
didAuthVp,
|
|
22080
|
+
tenantId
|
|
22081
|
+
)
|
|
19644
22082
|
);
|
|
19645
|
-
await
|
|
22083
|
+
await storage2.storeShareVersion(shareVersion, activeStorageId);
|
|
19646
22084
|
lastShareVersion = shareVersion;
|
|
19647
22085
|
},
|
|
19648
|
-
async markMigrated(token, providerType, didAuthVp) {
|
|
19649
|
-
const response = await fetch(`${serverUrl}/keys/migrate`, {
|
|
22086
|
+
async markMigrated(token, providerType, didAuthVp) {
|
|
22087
|
+
const response = await fetch(`${serverUrl}/keys/migrate`, {
|
|
22088
|
+
method: "POST",
|
|
22089
|
+
headers: buildHeaders(token, didAuthVp, tenantId),
|
|
22090
|
+
body: JSON.stringify({ authToken: token, providerType })
|
|
22091
|
+
});
|
|
22092
|
+
if (!response.ok) {
|
|
22093
|
+
throw new Error(`Failed to mark migrated: ${describeHttpStatus(response)}`);
|
|
22094
|
+
}
|
|
22095
|
+
},
|
|
22096
|
+
async activate(token, providerType, didAuthVp) {
|
|
22097
|
+
const response = await fetch(`${serverUrl}/keys/activate`, {
|
|
19650
22098
|
method: "POST",
|
|
19651
22099
|
headers: buildHeaders(token, didAuthVp, tenantId),
|
|
19652
22100
|
body: JSON.stringify({ authToken: token, providerType })
|
|
19653
22101
|
});
|
|
19654
22102
|
if (!response.ok) {
|
|
19655
|
-
throw new Error(`Failed to
|
|
22103
|
+
throw new Error(`Failed to activate SSS key: ${describeHttpStatus(response)}`);
|
|
19656
22104
|
}
|
|
19657
22105
|
},
|
|
19658
22106
|
// --- Recovery execution ---
|
|
22107
|
+
async getEscrowEnrollmentState(params) {
|
|
22108
|
+
if (!config.escrow?.enabled) return { state: "disabled" };
|
|
22109
|
+
const status = await this.fetchServerKeyStatus(params.token, params.providerType);
|
|
22110
|
+
if (status.escrowOptedOut) return { state: "opted-out", escrowPin: status.escrowPin };
|
|
22111
|
+
const confirmedEscrow = status.recoveryMethods.filter(
|
|
22112
|
+
(method) => method.type === "escrow" && (Boolean(method.confirmedAt) || "confirmationStatus" in method && method.confirmationStatus === "confirmed")
|
|
22113
|
+
);
|
|
22114
|
+
const enrolled = status.shareVersion !== null && confirmedEscrow.some((method) => method.shareVersion === status.shareVersion);
|
|
22115
|
+
if (confirmedEscrow.length > 0 && (!enrolled || status.escrowStale))
|
|
22116
|
+
return {
|
|
22117
|
+
state: "stale",
|
|
22118
|
+
escrowPin: status.escrowPin,
|
|
22119
|
+
staleReason: status.escrowStale
|
|
22120
|
+
};
|
|
22121
|
+
return { state: enrolled ? "enrolled" : "not-enrolled", escrowPin: status.escrowPin };
|
|
22122
|
+
},
|
|
22123
|
+
async disableEscrowRecovery(params) {
|
|
22124
|
+
const status = await this.fetchServerKeyStatus(params.token, params.providerType);
|
|
22125
|
+
if (!status.primaryDid) throw new Error("Cannot disable escrow without a primary DID");
|
|
22126
|
+
const vp = await requestFreshDidAuthVp(
|
|
22127
|
+
serverUrl,
|
|
22128
|
+
params.privateKey,
|
|
22129
|
+
status.primaryDid,
|
|
22130
|
+
params.signDidAuthVp,
|
|
22131
|
+
tenantId
|
|
22132
|
+
);
|
|
22133
|
+
await escrowRequest("", {
|
|
22134
|
+
method: "DELETE",
|
|
22135
|
+
headers: buildHeaders(params.token, vp, tenantId),
|
|
22136
|
+
body: JSON.stringify({
|
|
22137
|
+
authToken: params.token,
|
|
22138
|
+
providerType: params.providerType,
|
|
22139
|
+
optOut: true
|
|
22140
|
+
})
|
|
22141
|
+
});
|
|
22142
|
+
},
|
|
22143
|
+
async enableEscrowRecovery(params) {
|
|
22144
|
+
const storage2 = guardedStorage();
|
|
22145
|
+
return withRotationLock(async () => {
|
|
22146
|
+
if (!config.escrow?.enabled)
|
|
22147
|
+
return { enrolled: false, reason: "disabled" };
|
|
22148
|
+
const status = await this.fetchServerKeyStatus(params.token, params.providerType);
|
|
22149
|
+
if (!status.primaryDid)
|
|
22150
|
+
throw new Error("Cannot enable escrow without a primary DID");
|
|
22151
|
+
const vp = await requestFreshDidAuthVp(
|
|
22152
|
+
serverUrl,
|
|
22153
|
+
params.privateKey,
|
|
22154
|
+
status.primaryDid,
|
|
22155
|
+
params.signDidAuthVp,
|
|
22156
|
+
tenantId
|
|
22157
|
+
);
|
|
22158
|
+
await escrowRequest("/opt-in", {
|
|
22159
|
+
method: "POST",
|
|
22160
|
+
headers: buildHeaders(params.token, vp, tenantId),
|
|
22161
|
+
body: JSON.stringify({
|
|
22162
|
+
authToken: params.token,
|
|
22163
|
+
providerType: params.providerType
|
|
22164
|
+
})
|
|
22165
|
+
});
|
|
22166
|
+
return ensureEscrowEnrollmentUnguarded(this, params, storage2);
|
|
22167
|
+
});
|
|
22168
|
+
},
|
|
22169
|
+
async setEscrowPin({ pin, ...params }) {
|
|
22170
|
+
const storage2 = guardedStorage();
|
|
22171
|
+
const result = await withRotationLock(
|
|
22172
|
+
() => ensureEscrowEnrollmentUnguarded(this, { ...params, options: { pin } }, storage2)
|
|
22173
|
+
);
|
|
22174
|
+
if (!result.enrolled || !result.changed) {
|
|
22175
|
+
throw new Error("Automatic recovery is not available for this account.");
|
|
22176
|
+
}
|
|
22177
|
+
},
|
|
22178
|
+
async clearEscrowPin(params) {
|
|
22179
|
+
const storage2 = guardedStorage();
|
|
22180
|
+
const result = await withRotationLock(
|
|
22181
|
+
() => ensureEscrowEnrollmentUnguarded(this, params, storage2, true)
|
|
22182
|
+
);
|
|
22183
|
+
if (!result.enrolled || !result.changed) {
|
|
22184
|
+
throw new Error("Automatic recovery is not available for this account.");
|
|
22185
|
+
}
|
|
22186
|
+
},
|
|
22187
|
+
/** Enroll missing/stale escrow material using the standard atomic rotation. */
|
|
22188
|
+
async ensureEscrowEnrollment(params) {
|
|
22189
|
+
const storage2 = guardedStorage();
|
|
22190
|
+
if (params.options?.pin !== void 0)
|
|
22191
|
+
return withRotationLock(
|
|
22192
|
+
() => ensureEscrowEnrollmentUnguarded(this, params, storage2)
|
|
22193
|
+
);
|
|
22194
|
+
if (escrowEnrollmentInFlight) return escrowEnrollmentInFlight;
|
|
22195
|
+
escrowEnrollmentInFlight = withRotationLock(
|
|
22196
|
+
() => ensureEscrowEnrollmentUnguarded(this, params, storage2)
|
|
22197
|
+
);
|
|
22198
|
+
try {
|
|
22199
|
+
return await escrowEnrollmentInFlight;
|
|
22200
|
+
} finally {
|
|
22201
|
+
escrowEnrollmentInFlight = void 0;
|
|
22202
|
+
}
|
|
22203
|
+
},
|
|
22204
|
+
/** Start or explicitly restart a hold with fresh client-bound resume secrets. */
|
|
22205
|
+
async startEscrowRecovery(params) {
|
|
22206
|
+
const sessionProof = params.recoverySessionToken !== void 0;
|
|
22207
|
+
if (sessionProof ? params.token !== void 0 || params.providerType !== void 0 : !params.token || !params.providerType) {
|
|
22208
|
+
throw new Error("Provide exactly one identity proof");
|
|
22209
|
+
}
|
|
22210
|
+
const pair = await generateEscrowKeyPair();
|
|
22211
|
+
const result = await escrowRequest(
|
|
22212
|
+
"/recover",
|
|
22213
|
+
{
|
|
22214
|
+
method: "POST",
|
|
22215
|
+
headers: buildHeaders("", void 0, params.tenantId ?? tenantId),
|
|
22216
|
+
body: JSON.stringify({
|
|
22217
|
+
clientEphemeralPublicKey: pair.publicKey,
|
|
22218
|
+
...params.options?.restart ? { restart: true } : {},
|
|
22219
|
+
...params.options?.releasePolicy ? { releasePolicy: params.options.releasePolicy } : {},
|
|
22220
|
+
...sessionProof ? { recoverySessionToken: params.recoverySessionToken } : { authToken: params.token, providerType: params.providerType }
|
|
22221
|
+
})
|
|
22222
|
+
},
|
|
22223
|
+
params.options?.releasePolicy === "pin"
|
|
22224
|
+
);
|
|
22225
|
+
return { ...result, clientEphemeralPrivateKey: pair.privateKey };
|
|
22226
|
+
},
|
|
22227
|
+
/** Read hold status; secrets (auth or resume token) never travel in a URL. */
|
|
22228
|
+
async getEscrowRecoveryStatus(params) {
|
|
22229
|
+
const query = new URLSearchParams(
|
|
22230
|
+
"holdId" in params ? { holdId: params.holdId } : { providerType: params.providerType }
|
|
22231
|
+
);
|
|
22232
|
+
const secret = "holdId" in params ? params.resumeToken : params.token;
|
|
22233
|
+
const result = await escrowRequest(
|
|
22234
|
+
`/status?${query}`,
|
|
22235
|
+
{
|
|
22236
|
+
method: "GET",
|
|
22237
|
+
headers: {
|
|
22238
|
+
...buildHeaders("", void 0, tenantId),
|
|
22239
|
+
"X-Auth-Token": secret
|
|
22240
|
+
}
|
|
22241
|
+
}
|
|
22242
|
+
);
|
|
22243
|
+
return result.hold;
|
|
22244
|
+
},
|
|
22245
|
+
/** Cancel a pending hold with a fresh DID-owner proof. */
|
|
22246
|
+
async cancelEscrowRecovery(params) {
|
|
22247
|
+
const status = await this.fetchServerKeyStatus(params.token, params.providerType);
|
|
22248
|
+
if (!status.primaryDid) throw new Error("Cannot cancel escrow without a primary DID");
|
|
22249
|
+
const vp = await requestFreshDidAuthVp(
|
|
22250
|
+
serverUrl,
|
|
22251
|
+
params.privateKey,
|
|
22252
|
+
status.primaryDid,
|
|
22253
|
+
params.signDidAuthVp,
|
|
22254
|
+
tenantId
|
|
22255
|
+
);
|
|
22256
|
+
const result = await escrowRequest("/cancel", {
|
|
22257
|
+
method: "POST",
|
|
22258
|
+
headers: buildHeaders(params.token, vp, tenantId),
|
|
22259
|
+
body: JSON.stringify({
|
|
22260
|
+
authToken: params.token,
|
|
22261
|
+
providerType: params.providerType
|
|
22262
|
+
})
|
|
22263
|
+
});
|
|
22264
|
+
return { cancelled: result.cancelled };
|
|
22265
|
+
},
|
|
19659
22266
|
async executeRecovery(params) {
|
|
19660
|
-
const
|
|
22267
|
+
const storage2 = guardedStorage();
|
|
22268
|
+
const { token, providerType, input, didFromPrivateKey, signDidAuthVp } = params;
|
|
22269
|
+
if (input.method === "escrow" || input.method === "escrow-pin") {
|
|
22270
|
+
if (!didFromPrivateKey)
|
|
22271
|
+
throw new Error("DID verification is required for escrow recovery");
|
|
22272
|
+
const start = input.method === "escrow-pin" ? await this.startEscrowRecovery({
|
|
22273
|
+
token,
|
|
22274
|
+
providerType,
|
|
22275
|
+
options: { releasePolicy: "pin" }
|
|
22276
|
+
}) : input;
|
|
22277
|
+
let pinProof;
|
|
22278
|
+
if (input.method === "escrow-pin") {
|
|
22279
|
+
if (!("pinSalt" in start) || !start.pinSalt || !start.resumeToken)
|
|
22280
|
+
throw new Error("PIN recovery response is missing required material");
|
|
22281
|
+
pinProof = await derivePinProof(input.pin, start.pinSalt);
|
|
22282
|
+
}
|
|
22283
|
+
const material = await escrowRequest(
|
|
22284
|
+
"/complete",
|
|
22285
|
+
{
|
|
22286
|
+
method: "POST",
|
|
22287
|
+
headers: buildHeaders("", void 0, tenantId),
|
|
22288
|
+
body: JSON.stringify({
|
|
22289
|
+
holdId: start.holdId,
|
|
22290
|
+
resumeToken: start.resumeToken,
|
|
22291
|
+
...pinProof ? { pinProof } : {}
|
|
22292
|
+
})
|
|
22293
|
+
},
|
|
22294
|
+
input.method === "escrow-pin"
|
|
22295
|
+
);
|
|
22296
|
+
const plaintext = await openEscrowRelease(
|
|
22297
|
+
material.sealedShare,
|
|
22298
|
+
start.clientEphemeralPrivateKey
|
|
22299
|
+
);
|
|
22300
|
+
if (plaintext.holdId !== start.holdId || plaintext.did !== material.primaryDid || plaintext.shareVersion !== material.shareVersion) {
|
|
22301
|
+
throw new Error("Escrow recovery material does not match the request");
|
|
22302
|
+
}
|
|
22303
|
+
const authShare = material.authShare.encryptedData;
|
|
22304
|
+
const privateKey2 = await reconstructFromShares([
|
|
22305
|
+
plaintext.recoveryShare,
|
|
22306
|
+
authShare
|
|
22307
|
+
]);
|
|
22308
|
+
if (!material.primaryDid || await didFromPrivateKey(privateKey2) !== material.primaryDid) {
|
|
22309
|
+
throw new Error(
|
|
22310
|
+
"Recovery produced an incorrect key. Try another recovery method."
|
|
22311
|
+
);
|
|
22312
|
+
}
|
|
22313
|
+
pendingIdentityRecovery = {
|
|
22314
|
+
privateKey: privateKey2,
|
|
22315
|
+
primaryDid: material.primaryDid,
|
|
22316
|
+
recoveryShare: plaintext.recoveryShare,
|
|
22317
|
+
authShare,
|
|
22318
|
+
rebindSessionToken: material.rebindSessionToken
|
|
22319
|
+
};
|
|
22320
|
+
if (!token) return { privateKey: privateKey2, did: material.primaryDid };
|
|
22321
|
+
return this.completeIdentityRecovery({ token, providerType, signDidAuthVp });
|
|
22322
|
+
}
|
|
19661
22323
|
let recoveryShare;
|
|
19662
22324
|
let recoveryShareVersion;
|
|
19663
22325
|
switch (input.method) {
|
|
@@ -19751,14 +22413,61 @@ function createSSSStrategy(config) {
|
|
|
19751
22413
|
);
|
|
19752
22414
|
}
|
|
19753
22415
|
}
|
|
19754
|
-
await
|
|
19755
|
-
|
|
19756
|
-
|
|
22416
|
+
const { shares, shareVersion } = await persistSharesAtomically(
|
|
22417
|
+
privateKey,
|
|
22418
|
+
serverUrl,
|
|
22419
|
+
token,
|
|
22420
|
+
providerType,
|
|
22421
|
+
primaryDid,
|
|
22422
|
+
storage2,
|
|
22423
|
+
activeStorageId,
|
|
22424
|
+
didFromPrivateKey,
|
|
22425
|
+
signDidAuthVp,
|
|
22426
|
+
tenantId,
|
|
22427
|
+
recordPromotion(primaryDid),
|
|
22428
|
+
captureActiveUserGuard()
|
|
22429
|
+
);
|
|
22430
|
+
lastEmailShare = shares.emailShare;
|
|
22431
|
+
lastShareVersion = shareVersion;
|
|
22432
|
+
lastServerSnapshot = {
|
|
22433
|
+
currentVersion: shareVersion,
|
|
22434
|
+
resolvedVersion: shareVersion,
|
|
22435
|
+
authShare: shares.authShare,
|
|
22436
|
+
primaryDid
|
|
22437
|
+
};
|
|
22438
|
+
await tryEnrollEscrow(
|
|
22439
|
+
token,
|
|
22440
|
+
providerType,
|
|
22441
|
+
privateKey,
|
|
22442
|
+
primaryDid,
|
|
22443
|
+
shares,
|
|
22444
|
+
shareVersion,
|
|
22445
|
+
signDidAuthVp
|
|
22446
|
+
);
|
|
19757
22447
|
return { privateKey, did: primaryDid };
|
|
19758
22448
|
},
|
|
19759
22449
|
// --- Recovery setup ---
|
|
19760
22450
|
async setupRecoveryMethod(params) {
|
|
22451
|
+
const storage2 = guardedStorage();
|
|
19761
22452
|
const { token, providerType, privateKey, input, authUser, signDidAuthVp } = params;
|
|
22453
|
+
if (input.method === "escrow" && input.pin !== void 0) {
|
|
22454
|
+
if (!signDidAuthVp)
|
|
22455
|
+
throw new Error("DID proof signing is required for escrow enrollment");
|
|
22456
|
+
const result = await this.enableEscrowRecovery({
|
|
22457
|
+
token,
|
|
22458
|
+
providerType,
|
|
22459
|
+
privateKey,
|
|
22460
|
+
signDidAuthVp,
|
|
22461
|
+
options: { pin: input.pin }
|
|
22462
|
+
});
|
|
22463
|
+
if (!result.enrolled || !result.changed)
|
|
22464
|
+
throw new Error("Escrow enrollment is disabled");
|
|
22465
|
+
return { method: "escrow", shareVersion: result.shareVersion };
|
|
22466
|
+
}
|
|
22467
|
+
if (input.method === "escrow" && !config.escrow?.enabled) {
|
|
22468
|
+
throw new Error("Escrow enrollment is disabled");
|
|
22469
|
+
}
|
|
22470
|
+
const escrowKey = input.method === "escrow" ? await fetchVerifiedEnclaveKey() : void 0;
|
|
19762
22471
|
let passkeyCredential;
|
|
19763
22472
|
if (input.method === "passkey") {
|
|
19764
22473
|
if (!isWebAuthnSupported()) {
|
|
@@ -19768,10 +22477,6 @@ function createSSSStrategy(config) {
|
|
|
19768
22477
|
const userName = authUser?.email || authUser?.phone || authUser?.id || "";
|
|
19769
22478
|
passkeyCredential = await createPasskeyCredential(userId, userName);
|
|
19770
22479
|
}
|
|
19771
|
-
const vpJwt = signDidAuthVp ? await signDidAuthVp(privateKey) : void 0;
|
|
19772
|
-
const { shares } = await splitAndVerify(privateKey);
|
|
19773
|
-
lastEmailShare = shares.emailShare;
|
|
19774
|
-
await storage.storeDeviceShare(shares.deviceShare, activeStorageId);
|
|
19775
22480
|
const serverData = await fetchAuthShareRaw(
|
|
19776
22481
|
serverUrl,
|
|
19777
22482
|
token,
|
|
@@ -19780,39 +22485,42 @@ function createSSSStrategy(config) {
|
|
|
19780
22485
|
tenantId
|
|
19781
22486
|
);
|
|
19782
22487
|
const primaryDid = serverData?.primaryDid || "";
|
|
19783
|
-
|
|
22488
|
+
if (!primaryDid) throw new Error("Cannot set up recovery without a primary DID");
|
|
22489
|
+
const { shares, shareVersion } = await persistSharesAtomically(
|
|
22490
|
+
privateKey,
|
|
19784
22491
|
serverUrl,
|
|
19785
22492
|
token,
|
|
19786
22493
|
providerType,
|
|
19787
|
-
shares.authShare,
|
|
19788
22494
|
primaryDid,
|
|
19789
|
-
|
|
19790
|
-
|
|
22495
|
+
storage2,
|
|
22496
|
+
activeStorageId,
|
|
22497
|
+
void 0,
|
|
22498
|
+
signDidAuthVp,
|
|
22499
|
+
tenantId,
|
|
22500
|
+
recordPromotion(primaryDid),
|
|
22501
|
+
captureActiveUserGuard()
|
|
19791
22502
|
);
|
|
19792
|
-
|
|
19793
|
-
|
|
19794
|
-
|
|
19795
|
-
|
|
19796
|
-
|
|
19797
|
-
|
|
19798
|
-
|
|
19799
|
-
|
|
19800
|
-
tenantId
|
|
19801
|
-
) : authUser?.email ? sendEmailBackupShare(
|
|
19802
|
-
serverUrl,
|
|
19803
|
-
token,
|
|
19804
|
-
providerType,
|
|
19805
|
-
lastEmailShare,
|
|
19806
|
-
authUser.email,
|
|
19807
|
-
shareVersion,
|
|
19808
|
-
tenantId
|
|
19809
|
-
) : Promise.resolve();
|
|
19810
|
-
resend.catch(
|
|
19811
|
-
(e) => console.warn("Email backup share re-send failed (non-fatal):", e)
|
|
19812
|
-
);
|
|
19813
|
-
lastEmailShare = void 0;
|
|
19814
|
-
}
|
|
22503
|
+
lastEmailShare = shares.emailShare;
|
|
22504
|
+
lastShareVersion = shareVersion;
|
|
22505
|
+
lastServerSnapshot = {
|
|
22506
|
+
currentVersion: shareVersion,
|
|
22507
|
+
resolvedVersion: shareVersion,
|
|
22508
|
+
authShare: shares.authShare,
|
|
22509
|
+
primaryDid
|
|
22510
|
+
};
|
|
19815
22511
|
switch (input.method) {
|
|
22512
|
+
case "escrow":
|
|
22513
|
+
await enrollEscrow(
|
|
22514
|
+
token,
|
|
22515
|
+
providerType,
|
|
22516
|
+
privateKey,
|
|
22517
|
+
primaryDid,
|
|
22518
|
+
shares,
|
|
22519
|
+
shareVersion,
|
|
22520
|
+
signDidAuthVp,
|
|
22521
|
+
escrowKey
|
|
22522
|
+
);
|
|
22523
|
+
return { method: "escrow", shareVersion };
|
|
19816
22524
|
case "passkey": {
|
|
19817
22525
|
const credential = passkeyCredential;
|
|
19818
22526
|
const encryptedShare = await encryptShareWithPasskey(
|
|
@@ -19832,9 +22540,38 @@ function createSSSStrategy(config) {
|
|
|
19832
22540
|
credentialId: credential.credentialId,
|
|
19833
22541
|
shareVersion
|
|
19834
22542
|
},
|
|
19835
|
-
|
|
22543
|
+
signDidAuthVp ? await requestFreshDidAuthVp(
|
|
22544
|
+
serverUrl,
|
|
22545
|
+
privateKey,
|
|
22546
|
+
primaryDid,
|
|
22547
|
+
signDidAuthVp,
|
|
22548
|
+
tenantId
|
|
22549
|
+
) : void 0,
|
|
19836
22550
|
tenantId
|
|
19837
22551
|
);
|
|
22552
|
+
await postRecoveryConfirmation(
|
|
22553
|
+
serverUrl,
|
|
22554
|
+
token,
|
|
22555
|
+
providerType,
|
|
22556
|
+
{ type: "passkey", credentialId: credential.credentialId },
|
|
22557
|
+
signDidAuthVp ? await requestFreshDidAuthVp(
|
|
22558
|
+
serverUrl,
|
|
22559
|
+
privateKey,
|
|
22560
|
+
primaryDid,
|
|
22561
|
+
signDidAuthVp,
|
|
22562
|
+
tenantId
|
|
22563
|
+
) : void 0,
|
|
22564
|
+
tenantId
|
|
22565
|
+
);
|
|
22566
|
+
await tryEnrollEscrow(
|
|
22567
|
+
token,
|
|
22568
|
+
providerType,
|
|
22569
|
+
privateKey,
|
|
22570
|
+
primaryDid,
|
|
22571
|
+
shares,
|
|
22572
|
+
shareVersion,
|
|
22573
|
+
signDidAuthVp
|
|
22574
|
+
);
|
|
19838
22575
|
return { method: "passkey", credentialId: credential.credentialId };
|
|
19839
22576
|
}
|
|
19840
22577
|
case "phrase": {
|
|
@@ -19847,10 +22584,38 @@ function createSSSStrategy(config) {
|
|
|
19847
22584
|
type: "phrase",
|
|
19848
22585
|
shareVersion
|
|
19849
22586
|
},
|
|
19850
|
-
|
|
22587
|
+
signDidAuthVp ? await requestFreshDidAuthVp(
|
|
22588
|
+
serverUrl,
|
|
22589
|
+
privateKey,
|
|
22590
|
+
primaryDid,
|
|
22591
|
+
signDidAuthVp,
|
|
22592
|
+
tenantId
|
|
22593
|
+
) : void 0,
|
|
19851
22594
|
tenantId
|
|
19852
22595
|
);
|
|
19853
|
-
|
|
22596
|
+
const challengeWordIndices = selectRecoveryPhraseChallengeIndices(
|
|
22597
|
+
phrase.split(/\s+/).length
|
|
22598
|
+
);
|
|
22599
|
+
const challengeWordOptions = await buildRecoveryPhraseChallengeOptions(
|
|
22600
|
+
phrase,
|
|
22601
|
+
challengeWordIndices
|
|
22602
|
+
);
|
|
22603
|
+
pendingPhraseConfirmation = { phrase, challengeWordIndices };
|
|
22604
|
+
await tryEnrollEscrow(
|
|
22605
|
+
token,
|
|
22606
|
+
providerType,
|
|
22607
|
+
privateKey,
|
|
22608
|
+
primaryDid,
|
|
22609
|
+
shares,
|
|
22610
|
+
shareVersion,
|
|
22611
|
+
signDidAuthVp
|
|
22612
|
+
);
|
|
22613
|
+
return {
|
|
22614
|
+
method: "phrase",
|
|
22615
|
+
phrase,
|
|
22616
|
+
challengeWordIndices,
|
|
22617
|
+
challengeWordOptions
|
|
22618
|
+
};
|
|
19854
22619
|
}
|
|
19855
22620
|
case "backup": {
|
|
19856
22621
|
const encrypted = await encryptWithPassword(
|
|
@@ -19862,6 +22627,7 @@ function createSSSStrategy(config) {
|
|
|
19862
22627
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19863
22628
|
primaryDid: input.did,
|
|
19864
22629
|
shareVersion,
|
|
22630
|
+
shareChecksum: await calculateShareChecksum(shares.recoveryShare),
|
|
19865
22631
|
encryptedShare: {
|
|
19866
22632
|
ciphertext: encrypted.ciphertext,
|
|
19867
22633
|
iv: encrypted.iv,
|
|
@@ -19877,36 +22643,121 @@ function createSSSStrategy(config) {
|
|
|
19877
22643
|
type: "backup",
|
|
19878
22644
|
shareVersion
|
|
19879
22645
|
},
|
|
19880
|
-
|
|
22646
|
+
signDidAuthVp ? await requestFreshDidAuthVp(
|
|
22647
|
+
serverUrl,
|
|
22648
|
+
privateKey,
|
|
22649
|
+
primaryDid,
|
|
22650
|
+
signDidAuthVp,
|
|
22651
|
+
tenantId
|
|
22652
|
+
) : void 0,
|
|
19881
22653
|
tenantId
|
|
19882
22654
|
);
|
|
22655
|
+
pendingBackupConfirmation = {
|
|
22656
|
+
backupFile,
|
|
22657
|
+
recoveryShare: shares.recoveryShare
|
|
22658
|
+
};
|
|
22659
|
+
await tryEnrollEscrow(
|
|
22660
|
+
token,
|
|
22661
|
+
providerType,
|
|
22662
|
+
privateKey,
|
|
22663
|
+
primaryDid,
|
|
22664
|
+
shares,
|
|
22665
|
+
shareVersion,
|
|
22666
|
+
signDidAuthVp
|
|
22667
|
+
);
|
|
19883
22668
|
return { method: "backup", backupFile };
|
|
19884
22669
|
}
|
|
19885
22670
|
case "email": {
|
|
19886
|
-
await
|
|
22671
|
+
const didAuthVp = signDidAuthVp ? await requestFreshDidAuthVp(
|
|
22672
|
+
serverUrl,
|
|
22673
|
+
privateKey,
|
|
22674
|
+
primaryDid,
|
|
22675
|
+
signDidAuthVp,
|
|
22676
|
+
tenantId
|
|
22677
|
+
) : void 0;
|
|
22678
|
+
await sendEmailBackupShare(
|
|
19887
22679
|
serverUrl,
|
|
19888
22680
|
token,
|
|
19889
22681
|
providerType,
|
|
19890
22682
|
shares.emailShare,
|
|
22683
|
+
input.email,
|
|
22684
|
+
escrowRelayPublicKey,
|
|
22685
|
+
escrowRelayKeyId,
|
|
22686
|
+
emailBranding,
|
|
19891
22687
|
shareVersion,
|
|
22688
|
+
didAuthVp,
|
|
19892
22689
|
tenantId
|
|
19893
22690
|
);
|
|
19894
|
-
await
|
|
19895
|
-
serverUrl,
|
|
22691
|
+
await tryEnrollEscrow(
|
|
19896
22692
|
token,
|
|
19897
22693
|
providerType,
|
|
19898
|
-
|
|
19899
|
-
|
|
19900
|
-
|
|
19901
|
-
|
|
19902
|
-
|
|
19903
|
-
tenantId
|
|
22694
|
+
privateKey,
|
|
22695
|
+
primaryDid,
|
|
22696
|
+
shares,
|
|
22697
|
+
shareVersion,
|
|
22698
|
+
signDidAuthVp
|
|
19904
22699
|
);
|
|
19905
|
-
hasRecoveryEmail = true;
|
|
19906
22700
|
return { method: "email" };
|
|
19907
22701
|
}
|
|
19908
22702
|
}
|
|
19909
22703
|
},
|
|
22704
|
+
async confirmRecoveryMethod(params) {
|
|
22705
|
+
const { token, providerType, privateKey, input, signDidAuthVp } = params;
|
|
22706
|
+
const primaryDid = lastServerSnapshot?.primaryDid;
|
|
22707
|
+
if (!primaryDid) throw new Error("Cannot confirm recovery without a primary DID");
|
|
22708
|
+
const confirmationBody = { type: input.method };
|
|
22709
|
+
if (input.method === "phrase") {
|
|
22710
|
+
const pending = pendingPhraseConfirmation;
|
|
22711
|
+
if (!pending) throw new Error("Generate a new recovery phrase to continue");
|
|
22712
|
+
const phraseWords = pending.phrase.trim().toLowerCase().split(/\s+/);
|
|
22713
|
+
const matches = input.challengeWords.length === pending.challengeWordIndices.length && pending.challengeWordIndices.every(
|
|
22714
|
+
(wordIndex, answerIndex) => input.challengeWords[answerIndex]?.trim().toLowerCase() === phraseWords[wordIndex]
|
|
22715
|
+
);
|
|
22716
|
+
if (!matches) {
|
|
22717
|
+
throw new Error("Those words do not match. Check your phrase and try again.");
|
|
22718
|
+
}
|
|
22719
|
+
} else if (input.method === "backup") {
|
|
22720
|
+
const pending = pendingBackupConfirmation;
|
|
22721
|
+
if (!pending) throw new Error("Generate a new backup file to continue");
|
|
22722
|
+
let suppliedBackup;
|
|
22723
|
+
let decryptedShare;
|
|
22724
|
+
try {
|
|
22725
|
+
suppliedBackup = JSON.parse(input.fileContents);
|
|
22726
|
+
decryptedShare = await decryptWithPassword(
|
|
22727
|
+
suppliedBackup.encryptedShare.ciphertext,
|
|
22728
|
+
suppliedBackup.encryptedShare.iv,
|
|
22729
|
+
suppliedBackup.encryptedShare.salt,
|
|
22730
|
+
input.password,
|
|
22731
|
+
suppliedBackup.encryptedShare.kdfParams
|
|
22732
|
+
);
|
|
22733
|
+
} catch {
|
|
22734
|
+
throw new Error("Incorrect password or corrupted data. Please try again.");
|
|
22735
|
+
}
|
|
22736
|
+
const checksum = await calculateShareChecksum(decryptedShare);
|
|
22737
|
+
if (suppliedBackup.shareChecksum !== checksum || pending.backupFile.shareChecksum !== checksum || decryptedShare !== pending.recoveryShare) {
|
|
22738
|
+
throw new Error("This backup file could not be verified. Please try again.");
|
|
22739
|
+
}
|
|
22740
|
+
} else {
|
|
22741
|
+
confirmationBody.code = input.code;
|
|
22742
|
+
}
|
|
22743
|
+
const didAuthVp = signDidAuthVp ? await requestFreshDidAuthVp(
|
|
22744
|
+
serverUrl,
|
|
22745
|
+
privateKey,
|
|
22746
|
+
primaryDid,
|
|
22747
|
+
signDidAuthVp,
|
|
22748
|
+
tenantId
|
|
22749
|
+
) : void 0;
|
|
22750
|
+
await postRecoveryConfirmation(
|
|
22751
|
+
serverUrl,
|
|
22752
|
+
token,
|
|
22753
|
+
providerType,
|
|
22754
|
+
confirmationBody,
|
|
22755
|
+
didAuthVp,
|
|
22756
|
+
tenantId
|
|
22757
|
+
);
|
|
22758
|
+
if (input.method === "phrase") pendingPhraseConfirmation = void 0;
|
|
22759
|
+
if (input.method === "backup") pendingBackupConfirmation = void 0;
|
|
22760
|
+
},
|
|
19910
22761
|
async getAvailableRecoveryMethods(token, providerType) {
|
|
19911
22762
|
try {
|
|
19912
22763
|
const serverData = await fetchAuthShareRaw(
|
|
@@ -19917,15 +22768,274 @@ function createSSSStrategy(config) {
|
|
|
19917
22768
|
tenantId
|
|
19918
22769
|
);
|
|
19919
22770
|
const methods = serverData?.recoveryMethods || [];
|
|
19920
|
-
|
|
19921
|
-
|
|
19922
|
-
|
|
19923
|
-
|
|
22771
|
+
const activationState = serverData?.sssActivationState ?? "active";
|
|
22772
|
+
return methods.filter((method) => {
|
|
22773
|
+
if (method.confirmedAt) return true;
|
|
22774
|
+
if (method.confirmationStatus) return false;
|
|
22775
|
+
return activationState === "active";
|
|
22776
|
+
});
|
|
19924
22777
|
} catch (e) {
|
|
19925
22778
|
console.error("Error getting recovery methods:", e);
|
|
19926
22779
|
return [];
|
|
19927
22780
|
}
|
|
19928
22781
|
},
|
|
22782
|
+
async startIdentityRecovery(email) {
|
|
22783
|
+
await postJson(
|
|
22784
|
+
`${serverUrl}/keys/recovery-session/start`,
|
|
22785
|
+
{ email },
|
|
22786
|
+
buildHeaders("", void 0, tenantId)
|
|
22787
|
+
);
|
|
22788
|
+
},
|
|
22789
|
+
async verifyIdentityRecovery(email, code) {
|
|
22790
|
+
const result = await postJson(
|
|
22791
|
+
`${serverUrl}/keys/recovery-session/verify`,
|
|
22792
|
+
{ email, code },
|
|
22793
|
+
buildHeaders("", void 0, tenantId)
|
|
22794
|
+
);
|
|
22795
|
+
return {
|
|
22796
|
+
...result,
|
|
22797
|
+
recoveryMethods: result.recoveryMethods.map((method) => ({
|
|
22798
|
+
...method,
|
|
22799
|
+
createdAt: new Date(method.createdAt)
|
|
22800
|
+
}))
|
|
22801
|
+
};
|
|
22802
|
+
},
|
|
22803
|
+
async prepareIdentityRecovery(params) {
|
|
22804
|
+
const { input } = params;
|
|
22805
|
+
if (input.method === "escrow") {
|
|
22806
|
+
throw new Error("Use executeRecovery to complete an escrow hold");
|
|
22807
|
+
}
|
|
22808
|
+
let recoveryShare;
|
|
22809
|
+
switch (input.method) {
|
|
22810
|
+
case "passkey":
|
|
22811
|
+
break;
|
|
22812
|
+
case "phrase":
|
|
22813
|
+
if (!await validateRecoveryPhrase(input.phrase)) {
|
|
22814
|
+
throw new Error("Invalid recovery phrase");
|
|
22815
|
+
}
|
|
22816
|
+
recoveryShare = await recoveryPhraseToShare(input.phrase);
|
|
22817
|
+
break;
|
|
22818
|
+
case "backup": {
|
|
22819
|
+
const backup = JSON.parse(input.fileContents);
|
|
22820
|
+
if (backup.version !== 1) throw new Error("Unsupported backup file version");
|
|
22821
|
+
recoveryShare = await decryptWithPassword(
|
|
22822
|
+
backup.encryptedShare.ciphertext,
|
|
22823
|
+
backup.encryptedShare.iv,
|
|
22824
|
+
backup.encryptedShare.salt,
|
|
22825
|
+
input.password,
|
|
22826
|
+
backup.encryptedShare.kdfParams
|
|
22827
|
+
);
|
|
22828
|
+
break;
|
|
22829
|
+
}
|
|
22830
|
+
case "email":
|
|
22831
|
+
recoveryShare = parseVersionedEmailShare(input.emailShare.trim()).share;
|
|
22832
|
+
break;
|
|
22833
|
+
}
|
|
22834
|
+
try {
|
|
22835
|
+
const material = await postJson(
|
|
22836
|
+
`${serverUrl}/keys/recovery-session/recover`,
|
|
22837
|
+
{
|
|
22838
|
+
recoverySessionToken: params.recoverySessionToken,
|
|
22839
|
+
type: input.method,
|
|
22840
|
+
...input.method === "passkey" ? { credentialId: input.credentialId } : {}
|
|
22841
|
+
},
|
|
22842
|
+
buildHeaders("", void 0, tenantId)
|
|
22843
|
+
);
|
|
22844
|
+
if (input.method === "passkey") {
|
|
22845
|
+
if (!material.encryptedShare) {
|
|
22846
|
+
throw new Error("No passkey recovery data found");
|
|
22847
|
+
}
|
|
22848
|
+
recoveryShare = await decryptShareWithPasskey({
|
|
22849
|
+
encryptedData: material.encryptedShare.encryptedData,
|
|
22850
|
+
iv: material.encryptedShare.iv,
|
|
22851
|
+
credentialId: input.credentialId
|
|
22852
|
+
});
|
|
22853
|
+
}
|
|
22854
|
+
if (!recoveryShare) throw new Error("Recovery data was empty");
|
|
22855
|
+
const authShare = material.authShare.encryptedData;
|
|
22856
|
+
let privateKey;
|
|
22857
|
+
try {
|
|
22858
|
+
privateKey = await reconstructFromShares([recoveryShare, authShare]);
|
|
22859
|
+
} catch {
|
|
22860
|
+
throw new Error(
|
|
22861
|
+
"Recovery produced an incorrect key. Try another recovery method."
|
|
22862
|
+
);
|
|
22863
|
+
}
|
|
22864
|
+
const derivedDid = await params.didFromPrivateKey(privateKey);
|
|
22865
|
+
if (!derivedDid || derivedDid !== material.primaryDid) {
|
|
22866
|
+
throw new Error(
|
|
22867
|
+
"Recovery produced an incorrect key. Try another recovery method."
|
|
22868
|
+
);
|
|
22869
|
+
}
|
|
22870
|
+
pendingIdentityRecovery = {
|
|
22871
|
+
privateKey,
|
|
22872
|
+
primaryDid: material.primaryDid,
|
|
22873
|
+
recoveryShare,
|
|
22874
|
+
authShare,
|
|
22875
|
+
rebindSessionToken: material.rebindSessionToken
|
|
22876
|
+
};
|
|
22877
|
+
return { privateKey, did: material.primaryDid };
|
|
22878
|
+
} catch (error) {
|
|
22879
|
+
const message = error instanceof Error ? error.message : "Identity recovery failed";
|
|
22880
|
+
throw new IdentityRecoverySessionConsumedError(message);
|
|
22881
|
+
}
|
|
22882
|
+
},
|
|
22883
|
+
hasPendingIdentityRecovery() {
|
|
22884
|
+
return Boolean(pendingIdentityRecovery);
|
|
22885
|
+
},
|
|
22886
|
+
cancelIdentityRecovery() {
|
|
22887
|
+
pendingIdentityRecovery = void 0;
|
|
22888
|
+
},
|
|
22889
|
+
async completeIdentityRecovery(params) {
|
|
22890
|
+
const storage2 = guardedStorage();
|
|
22891
|
+
const generation = storageGeneration;
|
|
22892
|
+
const pending = pendingIdentityRecovery;
|
|
22893
|
+
const signDidAuthVp = params.signDidAuthVp;
|
|
22894
|
+
if (!pending) throw new Error("No identity recovery is waiting for a new sign-in");
|
|
22895
|
+
if (!signDidAuthVp) {
|
|
22896
|
+
throw new Error("DID proof signing is required to bind a new sign-in");
|
|
22897
|
+
}
|
|
22898
|
+
const storageId = activeStorageId;
|
|
22899
|
+
const { shares, shareVersion } = await withShareUpdateLock(
|
|
22900
|
+
storage2,
|
|
22901
|
+
storageId,
|
|
22902
|
+
() => withRotationLock(async () => {
|
|
22903
|
+
const assertActive = /* @__PURE__ */ __name(() => {
|
|
22904
|
+
if (activeStorageId !== storageId || pendingIdentityRecovery !== pending || storageGeneration !== generation) {
|
|
22905
|
+
throw new Error("This recovery request was cancelled.");
|
|
22906
|
+
}
|
|
22907
|
+
}, "assertActive");
|
|
22908
|
+
assertActive();
|
|
22909
|
+
const candidates = await readPendingShareCandidates(storage2, storageId);
|
|
22910
|
+
if (pending.rebind && pending.rebind.storageId !== storageId) {
|
|
22911
|
+
throw new Error("Active account changed during identity recovery");
|
|
22912
|
+
}
|
|
22913
|
+
if (candidates.some(
|
|
22914
|
+
(candidate) => candidate.share !== pending.rebind?.shares.deviceShare
|
|
22915
|
+
)) {
|
|
22916
|
+
throw new Error(
|
|
22917
|
+
"Reconcile the pending share update before binding a sign-in"
|
|
22918
|
+
);
|
|
22919
|
+
}
|
|
22920
|
+
let shareVersion2;
|
|
22921
|
+
const retry = pending.rebind?.attempted ?? false;
|
|
22922
|
+
if (retry && pending.rebind) {
|
|
22923
|
+
const current = await fetchAuthShareRaw(
|
|
22924
|
+
serverUrl,
|
|
22925
|
+
params.token,
|
|
22926
|
+
params.providerType,
|
|
22927
|
+
void 0,
|
|
22928
|
+
tenantId
|
|
22929
|
+
);
|
|
22930
|
+
const authShare = authShareToString(current?.authShare);
|
|
22931
|
+
if (authShare && current?.shareVersion != null) {
|
|
22932
|
+
const health = await verifyStoredShares(
|
|
22933
|
+
{
|
|
22934
|
+
getDevice: /* @__PURE__ */ __name(async () => pending.rebind.shares.deviceShare, "getDevice"),
|
|
22935
|
+
getAuth: /* @__PURE__ */ __name(async () => authShare, "getAuth")
|
|
22936
|
+
},
|
|
22937
|
+
pending.primaryDid,
|
|
22938
|
+
async (key) => key === pending.privateKey ? pending.primaryDid : ""
|
|
22939
|
+
);
|
|
22940
|
+
if (health.healthy) shareVersion2 = current.shareVersion;
|
|
22941
|
+
}
|
|
22942
|
+
}
|
|
22943
|
+
assertActive();
|
|
22944
|
+
if (shareVersion2 === void 0) {
|
|
22945
|
+
const didAuthVp = await requestFreshDidAuthVp(
|
|
22946
|
+
serverUrl,
|
|
22947
|
+
pending.privateKey,
|
|
22948
|
+
pending.primaryDid,
|
|
22949
|
+
signDidAuthVp,
|
|
22950
|
+
tenantId
|
|
22951
|
+
);
|
|
22952
|
+
assertActive();
|
|
22953
|
+
pending.rebind ??= {
|
|
22954
|
+
shares: (await splitAndVerify(pending.privateKey)).shares,
|
|
22955
|
+
storageId,
|
|
22956
|
+
attempted: false
|
|
22957
|
+
};
|
|
22958
|
+
const rebind = pending.rebind;
|
|
22959
|
+
if (!candidates.some(
|
|
22960
|
+
(candidate) => candidate.share === rebind.shares.deviceShare
|
|
22961
|
+
)) {
|
|
22962
|
+
await addPendingShareCandidate(
|
|
22963
|
+
storage2,
|
|
22964
|
+
{ share: rebind.shares.deviceShare, createdAt: Date.now() },
|
|
22965
|
+
storageId
|
|
22966
|
+
);
|
|
22967
|
+
}
|
|
22968
|
+
assertActive();
|
|
22969
|
+
rebind.attempted = true;
|
|
22970
|
+
try {
|
|
22971
|
+
const response = await postJson(
|
|
22972
|
+
`${serverUrl}/keys/recovery-session/rebind`,
|
|
22973
|
+
{
|
|
22974
|
+
recoverySessionToken: pending.rebindSessionToken,
|
|
22975
|
+
providerType: params.providerType,
|
|
22976
|
+
primaryDid: pending.primaryDid,
|
|
22977
|
+
authShare: {
|
|
22978
|
+
encryptedData: rebind.shares.authShare,
|
|
22979
|
+
encryptedDek: "",
|
|
22980
|
+
iv: ""
|
|
22981
|
+
}
|
|
22982
|
+
},
|
|
22983
|
+
{
|
|
22984
|
+
...buildHeaders("", didAuthVp, tenantId),
|
|
22985
|
+
"X-Auth-Token": params.token
|
|
22986
|
+
}
|
|
22987
|
+
);
|
|
22988
|
+
shareVersion2 = response.shareVersion;
|
|
22989
|
+
} catch (error) {
|
|
22990
|
+
if (error instanceof ShareWriteRejectedError && !retry) {
|
|
22991
|
+
await removePendingShareCandidate(
|
|
22992
|
+
storage2,
|
|
22993
|
+
rebind.shares.deviceShare,
|
|
22994
|
+
storageId
|
|
22995
|
+
);
|
|
22996
|
+
pending.rebind = void 0;
|
|
22997
|
+
}
|
|
22998
|
+
throw error;
|
|
22999
|
+
}
|
|
23000
|
+
}
|
|
23001
|
+
if (shareVersion2 === void 0 || !pending.rebind) {
|
|
23002
|
+
throw new Error("Server did not confirm the new share");
|
|
23003
|
+
}
|
|
23004
|
+
assertActive();
|
|
23005
|
+
const shares2 = pending.rebind.shares;
|
|
23006
|
+
await storage2.storeDeviceShare(shares2.deviceShare, storageId);
|
|
23007
|
+
await storage2.storeShareVersion(shareVersion2, storageId);
|
|
23008
|
+
await clearPendingShareCandidates(storage2, storageId);
|
|
23009
|
+
assertActive();
|
|
23010
|
+
lastEmailShare = shares2.emailShare;
|
|
23011
|
+
lastShareVersion = shareVersion2;
|
|
23012
|
+
lastServerSnapshot = {
|
|
23013
|
+
currentVersion: shareVersion2,
|
|
23014
|
+
resolvedVersion: shareVersion2,
|
|
23015
|
+
authShare: shares2.authShare,
|
|
23016
|
+
primaryDid: pending.primaryDid
|
|
23017
|
+
};
|
|
23018
|
+
pendingIdentityRecovery = void 0;
|
|
23019
|
+
return { shares: shares2, shareVersion: shareVersion2 };
|
|
23020
|
+
})
|
|
23021
|
+
);
|
|
23022
|
+
await tryEnrollEscrow(
|
|
23023
|
+
params.token,
|
|
23024
|
+
params.providerType,
|
|
23025
|
+
pending.privateKey,
|
|
23026
|
+
pending.primaryDid,
|
|
23027
|
+
shares,
|
|
23028
|
+
shareVersion,
|
|
23029
|
+
signDidAuthVp,
|
|
23030
|
+
void 0,
|
|
23031
|
+
void 0,
|
|
23032
|
+
true
|
|
23033
|
+
);
|
|
23034
|
+
if (activeStorageId !== storageId || storageGeneration !== generation) {
|
|
23035
|
+
throw new Error("This recovery request was cancelled.");
|
|
23036
|
+
}
|
|
23037
|
+
return { privateKey: pending.privateKey, did: pending.primaryDid };
|
|
23038
|
+
},
|
|
19929
23039
|
// --- Contact method management ---
|
|
19930
23040
|
async upgradeContactMethod(token, providerType, previousPhone, email, code) {
|
|
19931
23041
|
const res = await fetch(`${serverUrl}/keys/upgrade-contact-method`, {
|
|
@@ -19948,7 +23058,7 @@ function createSSSStrategy(config) {
|
|
|
19948
23058
|
return { customToken: data?.customToken };
|
|
19949
23059
|
},
|
|
19950
23060
|
// --- Email backup ---
|
|
19951
|
-
async sendEmailBackupShare(token, providerType, _privateKey, email) {
|
|
23061
|
+
async sendEmailBackupShare(token, providerType, _privateKey, email, didAuthVp) {
|
|
19952
23062
|
if (!enableEmailBackupShare) return;
|
|
19953
23063
|
if (!lastEmailShare) {
|
|
19954
23064
|
console.warn(
|
|
@@ -19956,29 +23066,22 @@ function createSSSStrategy(config) {
|
|
|
19956
23066
|
);
|
|
19957
23067
|
return;
|
|
19958
23068
|
}
|
|
19959
|
-
if (
|
|
19960
|
-
await sendEmailShareToRecoveryEmail(
|
|
19961
|
-
serverUrl,
|
|
19962
|
-
token,
|
|
19963
|
-
providerType,
|
|
19964
|
-
lastEmailShare,
|
|
19965
|
-
lastShareVersion,
|
|
19966
|
-
tenantId
|
|
19967
|
-
);
|
|
19968
|
-
} else {
|
|
19969
|
-
if (!email) {
|
|
19970
|
-
console.warn("Cannot send email backup share: no email address");
|
|
19971
|
-
return;
|
|
19972
|
-
}
|
|
23069
|
+
if (email) {
|
|
19973
23070
|
await sendEmailBackupShare(
|
|
19974
23071
|
serverUrl,
|
|
19975
23072
|
token,
|
|
19976
23073
|
providerType,
|
|
19977
23074
|
lastEmailShare,
|
|
19978
23075
|
email,
|
|
23076
|
+
escrowRelayPublicKey,
|
|
23077
|
+
escrowRelayKeyId,
|
|
23078
|
+
emailBranding,
|
|
19979
23079
|
lastShareVersion,
|
|
23080
|
+
didAuthVp,
|
|
19980
23081
|
tenantId
|
|
19981
23082
|
);
|
|
23083
|
+
} else {
|
|
23084
|
+
throw new Error("Enter a recovery email before sending a recovery key");
|
|
19982
23085
|
}
|
|
19983
23086
|
lastEmailShare = void 0;
|
|
19984
23087
|
lastShareVersion = void 0;
|
|
@@ -19995,6 +23098,8 @@ function createSSSStrategy(config) {
|
|
|
19995
23098
|
return [SSS_DB_NAME];
|
|
19996
23099
|
},
|
|
19997
23100
|
async cleanup() {
|
|
23101
|
+
storageGeneration++;
|
|
23102
|
+
await Promise.allSettled(localWrites);
|
|
19998
23103
|
}
|
|
19999
23104
|
};
|
|
20000
23105
|
}
|
|
@@ -20087,13 +23192,7 @@ var decryptShareFromTransfer = /* @__PURE__ */ __name(async (payload, recipientP
|
|
|
20087
23192
|
}, "decryptShareFromTransfer");
|
|
20088
23193
|
|
|
20089
23194
|
// src/qr-login.ts
|
|
20090
|
-
var buildHeaders2 = /* @__PURE__ */ __name((
|
|
20091
|
-
const headers = { "Content-Type": "application/json" };
|
|
20092
|
-
if (token) {
|
|
20093
|
-
headers.Authorization = `Bearer ${token}`;
|
|
20094
|
-
}
|
|
20095
|
-
return headers;
|
|
20096
|
-
}, "buildHeaders");
|
|
23195
|
+
var buildHeaders2 = /* @__PURE__ */ __name(() => ({ "Content-Type": "application/json" }), "buildHeaders");
|
|
20097
23196
|
var createQrLoginSession = /* @__PURE__ */ __name(async (config) => {
|
|
20098
23197
|
const ephemeralKeypair = await generateEphemeralKeypair();
|
|
20099
23198
|
const response = await fetch(`${config.serverUrl}/qr-login/session`, {
|
|
@@ -20161,10 +23260,14 @@ var pollUntilApproved = /* @__PURE__ */ __name(async (config, sessionId, ephemer
|
|
|
20161
23260
|
await new Promise((resolve, reject) => {
|
|
20162
23261
|
const timer = setTimeout(resolve, intervalMs);
|
|
20163
23262
|
if (options?.signal) {
|
|
20164
|
-
options.signal.addEventListener(
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
23263
|
+
options.signal.addEventListener(
|
|
23264
|
+
"abort",
|
|
23265
|
+
() => {
|
|
23266
|
+
clearTimeout(timer);
|
|
23267
|
+
reject(new Error("QR login polling aborted"));
|
|
23268
|
+
},
|
|
23269
|
+
{ once: true }
|
|
23270
|
+
);
|
|
20168
23271
|
}
|
|
20169
23272
|
});
|
|
20170
23273
|
}
|
|
@@ -20216,43 +23319,69 @@ var notifyDevicesForQrSession = /* @__PURE__ */ __name(async (config, sessionId,
|
|
|
20216
23319
|
return { sent: false, deviceCount: 0 };
|
|
20217
23320
|
}
|
|
20218
23321
|
}, "notifyDevicesForQrSession");
|
|
20219
|
-
|
|
20220
|
-
// src/types.ts
|
|
20221
|
-
var import_types = __toESM(require_dist());
|
|
20222
23322
|
var export_AuthSessionError = import_types.AuthSessionError;
|
|
20223
23323
|
export {
|
|
20224
23324
|
AtomicUpdateError,
|
|
20225
23325
|
export_AuthSessionError as AuthSessionError,
|
|
20226
23326
|
DEFAULT_KDF_PARAMS,
|
|
23327
|
+
EMAIL_RELAY_ALGORITHM,
|
|
23328
|
+
EMAIL_RELAY_ENVELOPE_VERSION,
|
|
23329
|
+
ESCROW_ALGORITHM,
|
|
23330
|
+
ESCROW_BLOB_INFO,
|
|
23331
|
+
ESCROW_CLIENT_KEY_ID,
|
|
23332
|
+
ESCROW_ENVELOPE_VERSION,
|
|
23333
|
+
ESCROW_PIN_MAX_ATTEMPTS,
|
|
23334
|
+
ESCROW_RELEASE_INFO,
|
|
23335
|
+
EscrowHoldRestartThrottledError,
|
|
23336
|
+
EscrowPinLockedError,
|
|
23337
|
+
EscrowPinMismatchError,
|
|
23338
|
+
EscrowPinThrottledError,
|
|
23339
|
+
EscrowPinUnavailableError,
|
|
23340
|
+
EscrowRequestError,
|
|
23341
|
+
IdentityRecoverySessionConsumedError,
|
|
23342
|
+
NitroAttestationError,
|
|
23343
|
+
PIN_MAX_LENGTH,
|
|
23344
|
+
PIN_MIN_LENGTH,
|
|
20227
23345
|
SSSApiClient,
|
|
20228
23346
|
SSSKeyManager,
|
|
20229
23347
|
SSS_THRESHOLD,
|
|
20230
23348
|
SSS_TOTAL_SHARES,
|
|
20231
23349
|
ShareVerificationError,
|
|
23350
|
+
ShareWriteRejectedError,
|
|
20232
23351
|
approveQrLoginSession,
|
|
20233
23352
|
atomicRecovery,
|
|
20234
23353
|
atomicShareUpdate,
|
|
20235
23354
|
base64ToBuffer,
|
|
20236
23355
|
bufferToBase64,
|
|
23356
|
+
buildRecoveryPhraseChallengeOptions,
|
|
20237
23357
|
bytesToHex,
|
|
20238
23358
|
clearAllShares,
|
|
23359
|
+
constantTimeEqualHex,
|
|
20239
23360
|
countWords,
|
|
20240
23361
|
createAdaptiveStorage,
|
|
20241
23362
|
createPasskeyCredential,
|
|
20242
23363
|
createQrLoginSession,
|
|
20243
23364
|
createSSSKeyManager,
|
|
20244
23365
|
createSSSStrategy,
|
|
23366
|
+
decryptEmailRelayPayload,
|
|
23367
|
+
decryptEscrowBlob,
|
|
20245
23368
|
decryptShareFromTransfer,
|
|
20246
23369
|
decryptShareWithPasskey,
|
|
20247
23370
|
decryptWithPassword,
|
|
20248
23371
|
deleteDeviceShare,
|
|
20249
23372
|
deriveKeyFromPasskey,
|
|
20250
23373
|
deriveKeyFromPassword,
|
|
23374
|
+
derivePinProof,
|
|
23375
|
+
encryptEmailRelayPayload,
|
|
23376
|
+
encryptEscrowBlob,
|
|
20251
23377
|
encryptShareForTransfer,
|
|
20252
23378
|
encryptShareWithPasskey,
|
|
20253
23379
|
encryptWithPassword,
|
|
20254
23380
|
generateEd25519PrivateKey,
|
|
23381
|
+
generateEmailRelayConfirmationCode,
|
|
20255
23382
|
generateEphemeralKeypair,
|
|
23383
|
+
generateEscrowKeyPair,
|
|
23384
|
+
generatePinSalt,
|
|
20256
23385
|
generateRecoveryPhrase,
|
|
20257
23386
|
getDeviceShare,
|
|
20258
23387
|
getQrLoginSessionInfo,
|
|
@@ -20263,18 +23392,29 @@ export {
|
|
|
20263
23392
|
isPublicComputerMode,
|
|
20264
23393
|
isWebAuthnSupported,
|
|
20265
23394
|
listAllDeviceShares,
|
|
23395
|
+
normalizePin,
|
|
20266
23396
|
notifyDevicesForQrSession,
|
|
23397
|
+
openEscrowRelease,
|
|
23398
|
+
parseEmailRelayEnvelope,
|
|
23399
|
+
parseEmailRelayPlaintext,
|
|
23400
|
+
parseEscrowBlobPlaintext,
|
|
23401
|
+
parseEscrowEnvelope,
|
|
23402
|
+
parseEscrowReleasePlaintext,
|
|
20267
23403
|
pollQrLoginSession,
|
|
20268
23404
|
pollUntilApproved,
|
|
20269
23405
|
reconstructFromShares,
|
|
20270
23406
|
reconstructPrivateKey,
|
|
20271
23407
|
recoveryPhraseToShare,
|
|
23408
|
+
sealEscrowRelease,
|
|
20272
23409
|
setPublicComputerMode,
|
|
20273
23410
|
shareToRecoveryPhrase,
|
|
20274
23411
|
splitAndVerify,
|
|
20275
23412
|
splitPrivateKey,
|
|
20276
23413
|
storeDeviceShare,
|
|
20277
23414
|
storeShareVersion,
|
|
23415
|
+
validatePin,
|
|
20278
23416
|
validateRecoveryPhrase,
|
|
23417
|
+
verifyEnclaveAttestation,
|
|
23418
|
+
verifyNitroAttestationDocument,
|
|
20279
23419
|
verifyStoredShares
|
|
20280
23420
|
};
|