@learncard/sss-key-manager 0.1.21 → 0.1.22
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 +157 -16
- package/dist/sss-key-manager.cjs.development.js +227 -4
- package/dist/sss-key-manager.cjs.development.js.map +2 -2
- package/dist/sss-key-manager.cjs.production.min.js +6 -6
- package/dist/sss-key-manager.cjs.production.min.js.map +3 -3
- package/dist/sss-key-manager.esm.js +227 -4
- package/dist/sss-key-manager.esm.js.map +2 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,14 +8,14 @@ This package provides a secure, self-hosted alternative to Web3Auth Single Facto
|
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
11
|
+
- **Key Splitting**: Split ed25519 private keys into 3 shares with 2-of-3 threshold
|
|
12
|
+
- **Device Storage**: Encrypted local storage using AES-GCM with IndexedDB
|
|
13
|
+
- **Server Storage**: Encrypted auth share stored on server with envelope encryption
|
|
14
|
+
- **Recovery Methods**:
|
|
15
|
+
- Password-based (Argon2id KDF)
|
|
16
|
+
- Passkey/WebAuthn PRF (coming soon)
|
|
17
|
+
- Backup file export/import
|
|
18
|
+
- **Migration**: Seamless migration from Web3Auth SFA
|
|
19
19
|
|
|
20
20
|
## Installation
|
|
21
21
|
|
|
@@ -115,19 +115,19 @@ const privateKey = await keyManager.recover({
|
|
|
115
115
|
|
|
116
116
|
## Security Model
|
|
117
117
|
|
|
118
|
-
-
|
|
119
|
-
-
|
|
120
|
-
-
|
|
121
|
-
-
|
|
118
|
+
- **Device Share**: Encrypted with non-extractable AES-GCM key stored in IndexedDB
|
|
119
|
+
- **Auth Share**: Server-side envelope encryption (DEK + KMS-encrypted DEK)
|
|
120
|
+
- **Recovery Share**: Password-based uses Argon2id KDF with secure parameters
|
|
121
|
+
- **Threshold**: Any 2 of 3 shares can reconstruct the key
|
|
122
122
|
|
|
123
123
|
## Auth Provider Support
|
|
124
124
|
|
|
125
125
|
The package is designed to work with any authentication provider:
|
|
126
126
|
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
-
|
|
127
|
+
- Firebase Authentication (default for production)
|
|
128
|
+
- SuperTokens (recommended for self-hosting/local dev)
|
|
129
|
+
- Keycloak (enterprise SSO)
|
|
130
|
+
- Any OIDC-compliant provider
|
|
131
131
|
|
|
132
132
|
## API Reference
|
|
133
133
|
|
|
@@ -167,6 +167,147 @@ Exports an encrypted backup file.
|
|
|
167
167
|
|
|
168
168
|
Returns the current security level based on configured recovery methods.
|
|
169
169
|
|
|
170
|
+
## Four shares
|
|
171
|
+
|
|
172
|
+
`SSS_TOTAL_SHARES = 4` and `SSS_THRESHOLD = 2`: any two shares reconstruct the private key, while one share alone reveals nothing about it.
|
|
173
|
+
|
|
174
|
+
| Share | Where it lives | Purpose |
|
|
175
|
+
| -------------- | ---------------------------------------------------------------------------------- | ---------------------------------- |
|
|
176
|
+
| Device share | Local IndexedDB | Same-device sign-in |
|
|
177
|
+
| Auth share | LearnCard API server, encrypted at rest | Authenticated sign-in and recovery |
|
|
178
|
+
| Recovery share | Passkey-protected server record, offline phrase, or password-encrypted backup file | User-controlled recovery |
|
|
179
|
+
| Email share | Recovery email backup, encrypted before delivery | Optional additional recovery path |
|
|
180
|
+
|
|
181
|
+
Passkeys protect the recovery share using a key derived from WebAuthn PRF output. A recovery phrase encodes the share as a mnemonic; a backup file encrypts it using Argon2id password derivation and AES-GCM, with its salt and KDF parameters stored in the file.
|
|
182
|
+
|
|
183
|
+
### Server-side encryption
|
|
184
|
+
|
|
185
|
+
The `lca-api` service derives an AES-256-GCM key from its server `SEED` using HKDF-SHA256, with salt `lca-auth-share-encryption` and info `v1`. Each auth-share encryption uses a fresh 12-byte IV; the stored ciphertext includes the 16-byte authentication tag.
|
|
186
|
+
|
|
187
|
+
This implementation encrypts the share directly with the derived key. It does **not** generate a per-share Data Encryption Key (DEK) wrapped by a separate Key Encryption Key (KEK): the `encryptedDek` field holds the format marker `server-v1`, not a wrapped DEK. Password backup encryption and server auth-share encryption are separate mechanisms.
|
|
188
|
+
|
|
189
|
+
## Key Types
|
|
190
|
+
|
|
191
|
+
### ContactMethod
|
|
192
|
+
|
|
193
|
+
Identifies a user by their primary contact method:
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
type ContactMethodType = 'email' | 'phone';
|
|
197
|
+
|
|
198
|
+
interface ContactMethod {
|
|
199
|
+
type: ContactMethodType;
|
|
200
|
+
value: string;
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### SecurityLevel
|
|
205
|
+
|
|
206
|
+
Describes how well-protected a user's key is:
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
type SecurityLevel = 'basic' | 'enhanced' | 'advanced';
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
- **basic** — device + server share only (no recovery method)
|
|
213
|
+
- **enhanced** — at least one recovery method configured
|
|
214
|
+
- **advanced** — multiple recovery methods configured
|
|
215
|
+
|
|
216
|
+
### RecoveryInput
|
|
217
|
+
|
|
218
|
+
What the user provides to recover their key:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
type RecoveryInput =
|
|
222
|
+
| { method: 'passkey'; credentialId: string }
|
|
223
|
+
| { method: 'phrase'; phrase: string }
|
|
224
|
+
| { method: 'backup'; fileContents: string; password: string }
|
|
225
|
+
| { method: 'email'; emailShare: string };
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### RecoverySetupInput
|
|
229
|
+
|
|
230
|
+
What the user provides to set up a new recovery method:
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
type RecoverySetupInput =
|
|
234
|
+
| { method: 'passkey' }
|
|
235
|
+
| { method: 'phrase' }
|
|
236
|
+
| { method: 'backup'; password: string; did: string }
|
|
237
|
+
| { method: 'email' };
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### BackupFile
|
|
241
|
+
|
|
242
|
+
The JSON structure of a downloadable backup file:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
interface BackupFile {
|
|
246
|
+
version: 1;
|
|
247
|
+
createdAt: string;
|
|
248
|
+
primaryDid: string;
|
|
249
|
+
shareVersion?: number;
|
|
250
|
+
encryptedShare: {
|
|
251
|
+
ciphertext: string;
|
|
252
|
+
iv: string;
|
|
253
|
+
salt: string;
|
|
254
|
+
kdfParams: {
|
|
255
|
+
algorithm: 'argon2id';
|
|
256
|
+
timeCost: number;
|
|
257
|
+
memoryCost: number;
|
|
258
|
+
parallelism: number;
|
|
259
|
+
};
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## SSSStrategy
|
|
265
|
+
|
|
266
|
+
The main class that implements `KeyDerivationStrategy`. It is typically instantiated by the AuthCoordinator, not directly by application code.
|
|
267
|
+
|
|
268
|
+
### Configuration
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
interface SSSStrategyConfig {
|
|
272
|
+
serverUrl: string;
|
|
273
|
+
enableEmailBackupShare?: boolean;
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
| Option | Default | Description |
|
|
278
|
+
| ------------------------ | ------- | ---------------------------------------------------------------------- |
|
|
279
|
+
| `serverUrl` | — | Base URL of the lca-api server (e.g., `https://api.example.com/api`) |
|
|
280
|
+
| `enableEmailBackupShare` | `false` | Automatically send a backup share to the user's email during key setup |
|
|
281
|
+
|
|
282
|
+
### Key Methods
|
|
283
|
+
|
|
284
|
+
| Method | Purpose |
|
|
285
|
+
| -------------------------------------------------- | --------------------------------------------------------------------- |
|
|
286
|
+
| `fetchServerKeyStatus(token, providerType)` | Check if a key record exists on the server for the authenticated user |
|
|
287
|
+
| `setupNewKey(token, providerType, signVp)` | Generate a new key, split it, store shares on device and server |
|
|
288
|
+
| `reconstructKey(token, providerType)` | Reconstruct the key from device share + auth share |
|
|
289
|
+
| `recoverKey(token, providerType, input)` | Recover the key using a recovery method + auth share |
|
|
290
|
+
| `hasLocalKey()` | Check if a device share exists in IndexedDB |
|
|
291
|
+
| `clearLocalKey()` | Remove the device share from IndexedDB |
|
|
292
|
+
| `setupRecoveryMethod(params)` | Set up a new recovery method (passkey, phrase, backup, email) |
|
|
293
|
+
| `getAvailableRecoveryMethods(token, providerType)` | List the user's configured recovery methods |
|
|
294
|
+
|
|
295
|
+
## API Client
|
|
296
|
+
|
|
297
|
+
The `api-client.ts` module provides a typed fetch wrapper for all lca-api `/keys/*` and `/qr-login/*` routes. It is used internally by the SSS strategy but can also be used directly:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
import { createApiClient } from '@learncard/sss-key-manager';
|
|
301
|
+
|
|
302
|
+
const client = createApiClient({ serverUrl: 'https://api.example.com/api' });
|
|
303
|
+
|
|
304
|
+
const status = await client.getAuthShare({
|
|
305
|
+
authToken: token,
|
|
306
|
+
providerType: 'firebase',
|
|
307
|
+
contactMethod: { type: 'email', value: 'user@example.com' },
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
170
311
|
## License
|
|
171
312
|
|
|
172
313
|
MIT
|
|
@@ -66,6 +66,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
66
66
|
AgeRatingValidator: /* @__PURE__ */ __name(() => AgeRatingValidator, "AgeRatingValidator"),
|
|
67
67
|
AlignmentTargetTypeValidator: /* @__PURE__ */ __name(() => AlignmentTargetTypeValidator, "AlignmentTargetTypeValidator"),
|
|
68
68
|
AlignmentValidator: /* @__PURE__ */ __name(() => AlignmentValidator, "AlignmentValidator"),
|
|
69
|
+
AllocateCredentialRefreshInputValidator: /* @__PURE__ */ __name(() => AllocateCredentialRefreshInputValidator, "AllocateCredentialRefreshInputValidator"),
|
|
70
|
+
AllocateCredentialRefreshResultValidator: /* @__PURE__ */ __name(() => AllocateCredentialRefreshResultValidator, "AllocateCredentialRefreshResultValidator"),
|
|
69
71
|
AllocateCredentialStatusInputValidator: /* @__PURE__ */ __name(() => AllocateCredentialStatusInputValidator, "AllocateCredentialStatusInputValidator"),
|
|
70
72
|
AllocatedBitstringStatusListEntryValidator: /* @__PURE__ */ __name(() => AllocatedBitstringStatusListEntryValidator, "AllocatedBitstringStatusListEntryValidator"),
|
|
71
73
|
AllowConnectionRequestsEnum: /* @__PURE__ */ __name(() => AllowConnectionRequestsEnum, "AllowConnectionRequestsEnum"),
|
|
@@ -147,6 +149,16 @@ var require_types_cjs_development = __commonJS({
|
|
|
147
149
|
CredentialInfoValidator: /* @__PURE__ */ __name(() => CredentialInfoValidator, "CredentialInfoValidator"),
|
|
148
150
|
CredentialNameRefValidator: /* @__PURE__ */ __name(() => CredentialNameRefValidator, "CredentialNameRefValidator"),
|
|
149
151
|
CredentialRecordValidator: /* @__PURE__ */ __name(() => CredentialRecordValidator, "CredentialRecordValidator"),
|
|
152
|
+
CredentialRefreshChallengeValidator: /* @__PURE__ */ __name(() => CredentialRefreshChallengeValidator, "CredentialRefreshChallengeValidator"),
|
|
153
|
+
CredentialRefreshFailedResultValidator: /* @__PURE__ */ __name(() => CredentialRefreshFailedResultValidator, "CredentialRefreshFailedResultValidator"),
|
|
154
|
+
CredentialRefreshFailureCodeValidator: /* @__PURE__ */ __name(() => CredentialRefreshFailureCodeValidator, "CredentialRefreshFailureCodeValidator"),
|
|
155
|
+
CredentialRefreshResponseEnvelopeValidator: /* @__PURE__ */ __name(() => CredentialRefreshResponseEnvelopeValidator, "CredentialRefreshResponseEnvelopeValidator"),
|
|
156
|
+
CredentialRefreshResultValidator: /* @__PURE__ */ __name(() => CredentialRefreshResultValidator, "CredentialRefreshResultValidator"),
|
|
157
|
+
CredentialRefreshSigningModeValidator: /* @__PURE__ */ __name(() => CredentialRefreshSigningModeValidator, "CredentialRefreshSigningModeValidator"),
|
|
158
|
+
CredentialRefreshUnchangedResultValidator: /* @__PURE__ */ __name(() => CredentialRefreshUnchangedResultValidator, "CredentialRefreshUnchangedResultValidator"),
|
|
159
|
+
CredentialRefreshUnsupportedResultValidator: /* @__PURE__ */ __name(() => CredentialRefreshUnsupportedResultValidator, "CredentialRefreshUnsupportedResultValidator"),
|
|
160
|
+
CredentialRefreshUpdatedResultValidator: /* @__PURE__ */ __name(() => CredentialRefreshUpdatedResultValidator, "CredentialRefreshUpdatedResultValidator"),
|
|
161
|
+
CredentialRefreshVersionMetadataValidator: /* @__PURE__ */ __name(() => CredentialRefreshVersionMetadataValidator, "CredentialRefreshVersionMetadataValidator"),
|
|
150
162
|
CredentialSchemaValidator: /* @__PURE__ */ __name(() => CredentialSchemaValidator, "CredentialSchemaValidator"),
|
|
151
163
|
CredentialStatusValidator: /* @__PURE__ */ __name(() => CredentialStatusValidator, "CredentialStatusValidator"),
|
|
152
164
|
CredentialSubjectValidator: /* @__PURE__ */ __name(() => CredentialSubjectValidator, "CredentialSubjectValidator"),
|
|
@@ -167,6 +179,8 @@ var require_types_cjs_development = __commonJS({
|
|
|
167
179
|
GeoCoordinatesValidator: /* @__PURE__ */ __name(() => GeoCoordinatesValidator, "GeoCoordinatesValidator"),
|
|
168
180
|
GetCounterEventValidator: /* @__PURE__ */ __name(() => GetCounterEventValidator, "GetCounterEventValidator"),
|
|
169
181
|
GetCountersEventValidator: /* @__PURE__ */ __name(() => GetCountersEventValidator, "GetCountersEventValidator"),
|
|
182
|
+
GetCredentialRefreshHistoryInputValidator: /* @__PURE__ */ __name(() => GetCredentialRefreshHistoryInputValidator, "GetCredentialRefreshHistoryInputValidator"),
|
|
183
|
+
GetCredentialRefreshHistoryResultValidator: /* @__PURE__ */ __name(() => GetCredentialRefreshHistoryResultValidator, "GetCredentialRefreshHistoryResultValidator"),
|
|
170
184
|
GetFullSkillTreeInputValidator: /* @__PURE__ */ __name(() => GetFullSkillTreeInputValidator, "GetFullSkillTreeInputValidator"),
|
|
171
185
|
GetFullSkillTreeResultValidator: /* @__PURE__ */ __name(() => GetFullSkillTreeResultValidator, "GetFullSkillTreeResultValidator"),
|
|
172
186
|
GetSkillPathInputValidator: /* @__PURE__ */ __name(() => GetSkillPathInputValidator, "GetSkillPathInputValidator"),
|
|
@@ -191,6 +205,7 @@ var require_types_cjs_development = __commonJS({
|
|
|
191
205
|
JWEValidator: /* @__PURE__ */ __name(() => JWEValidator, "JWEValidator"),
|
|
192
206
|
JWKValidator: /* @__PURE__ */ __name(() => JWKValidator, "JWKValidator"),
|
|
193
207
|
JWKWithPrivateKeyValidator: /* @__PURE__ */ __name(() => JWKWithPrivateKeyValidator, "JWKWithPrivateKeyValidator"),
|
|
208
|
+
JweCredentialRefreshEnvelopeValidator: /* @__PURE__ */ __name(() => JweCredentialRefreshEnvelopeValidator, "JweCredentialRefreshEnvelopeValidator"),
|
|
194
209
|
KnownAchievementTypeValidator: /* @__PURE__ */ __name(() => KnownAchievementTypeValidator, "KnownAchievementTypeValidator"),
|
|
195
210
|
LCNAuthedProfileValidator: /* @__PURE__ */ __name(() => LCNAuthedProfileValidator, "LCNAuthedProfileValidator"),
|
|
196
211
|
LCNBoostClaimLinkOptionsValidator: /* @__PURE__ */ __name(() => LCNBoostClaimLinkOptionsValidator, "LCNBoostClaimLinkOptionsValidator"),
|
|
@@ -228,7 +243,9 @@ var require_types_cjs_development = __commonJS({
|
|
|
228
243
|
LCNSigningAuthorityValidator: /* @__PURE__ */ __name(() => LCNSigningAuthorityValidator, "LCNSigningAuthorityValidator"),
|
|
229
244
|
LCNVisibleProfileValidator: /* @__PURE__ */ __name(() => LCNVisibleProfileValidator, "LCNVisibleProfileValidator"),
|
|
230
245
|
LaunchTypeValidator: /* @__PURE__ */ __name(() => LaunchTypeValidator, "LaunchTypeValidator"),
|
|
246
|
+
LearnCardRefreshAuthorizationValidator: /* @__PURE__ */ __name(() => LearnCardRefreshAuthorizationValidator, "LearnCardRefreshAuthorizationValidator"),
|
|
231
247
|
LinkProviderFrameworkInputValidator: /* @__PURE__ */ __name(() => LinkProviderFrameworkInputValidator, "LinkProviderFrameworkInputValidator"),
|
|
248
|
+
ManagedCredentialRefreshServiceValidator: /* @__PURE__ */ __name(() => ManagedCredentialRefreshServiceValidator, "ManagedCredentialRefreshServiceValidator"),
|
|
232
249
|
PaginatedAppStoreListingsValidator: /* @__PURE__ */ __name(() => PaginatedAppStoreListingsValidator, "PaginatedAppStoreListingsValidator"),
|
|
233
250
|
PaginatedBoostRecipientsValidator: /* @__PURE__ */ __name(() => PaginatedBoostRecipientsValidator, "PaginatedBoostRecipientsValidator"),
|
|
234
251
|
PaginatedBoostRecipientsWithChildrenValidator: /* @__PURE__ */ __name(() => PaginatedBoostRecipientsWithChildrenValidator, "PaginatedBoostRecipientsWithChildrenValidator"),
|
|
@@ -258,6 +275,12 @@ var require_types_cjs_development = __commonJS({
|
|
|
258
275
|
ProfileVisibilityEnum: /* @__PURE__ */ __name(() => ProfileVisibilityEnum, "ProfileVisibilityEnum"),
|
|
259
276
|
PromotionLevelValidator: /* @__PURE__ */ __name(() => PromotionLevelValidator, "PromotionLevelValidator"),
|
|
260
277
|
ProofValidator: /* @__PURE__ */ __name(() => ProofValidator, "ProofValidator"),
|
|
278
|
+
PublicCredentialRefreshEnvelopeValidator: /* @__PURE__ */ __name(() => PublicCredentialRefreshEnvelopeValidator, "PublicCredentialRefreshEnvelopeValidator"),
|
|
279
|
+
PublishCredentialRefreshInputValidator: /* @__PURE__ */ __name(() => PublishCredentialRefreshInputValidator, "PublishCredentialRefreshInputValidator"),
|
|
280
|
+
PublishCredentialRefreshNotificationValidator: /* @__PURE__ */ __name(() => PublishCredentialRefreshNotificationValidator, "PublishCredentialRefreshNotificationValidator"),
|
|
281
|
+
PublishCredentialRefreshResultValidator: /* @__PURE__ */ __name(() => PublishCredentialRefreshResultValidator, "PublishCredentialRefreshResultValidator"),
|
|
282
|
+
PublishIssuerSignedRefreshValidator: /* @__PURE__ */ __name(() => PublishIssuerSignedRefreshValidator, "PublishIssuerSignedRefreshValidator"),
|
|
283
|
+
PublishSigningAuthorityRefreshValidator: /* @__PURE__ */ __name(() => PublishSigningAuthorityRefreshValidator, "PublishSigningAuthorityRefreshValidator"),
|
|
261
284
|
RefreshServiceValidator: /* @__PURE__ */ __name(() => RefreshServiceValidator, "RefreshServiceValidator"),
|
|
262
285
|
RegExpValidator: /* @__PURE__ */ __name(() => RegExpValidator, "RegExpValidator"),
|
|
263
286
|
RelatedValidator: /* @__PURE__ */ __name(() => RelatedValidator, "RelatedValidator"),
|
|
@@ -298,11 +321,13 @@ var require_types_cjs_development = __commonJS({
|
|
|
298
321
|
SkillTreeNodeInputValidator: /* @__PURE__ */ __name(() => SkillTreeNodeInputValidator, "SkillTreeNodeInputValidator"),
|
|
299
322
|
SkillTreeNodeValidator: /* @__PURE__ */ __name(() => SkillTreeNodeValidator, "SkillTreeNodeValidator"),
|
|
300
323
|
SkillValidator: /* @__PURE__ */ __name(() => SkillValidator, "SkillValidator"),
|
|
324
|
+
StandardCredentialRefreshServiceValidator: /* @__PURE__ */ __name(() => StandardCredentialRefreshServiceValidator, "StandardCredentialRefreshServiceValidator"),
|
|
301
325
|
StatusCheckEntryValidator: /* @__PURE__ */ __name(() => StatusCheckEntryValidator, "StatusCheckEntryValidator"),
|
|
302
326
|
StoredCredentialEnvelopeValidator: /* @__PURE__ */ __name(() => StoredCredentialEnvelopeValidator, "StoredCredentialEnvelopeValidator"),
|
|
303
327
|
StringQuery: /* @__PURE__ */ __name(() => StringQuery, "StringQuery"),
|
|
304
328
|
SummaryCredentialDataValidator: /* @__PURE__ */ __name(() => SummaryCredentialDataValidator, "SummaryCredentialDataValidator"),
|
|
305
329
|
SummaryCredentialKeywordValidator: /* @__PURE__ */ __name(() => SummaryCredentialKeywordValidator, "SummaryCredentialKeywordValidator"),
|
|
330
|
+
SupportedCredentialRefreshServiceValidator: /* @__PURE__ */ __name(() => SupportedCredentialRefreshServiceValidator, "SupportedCredentialRefreshServiceValidator"),
|
|
306
331
|
SyncFrameworkInputValidator: /* @__PURE__ */ __name(() => SyncFrameworkInputValidator, "SyncFrameworkInputValidator"),
|
|
307
332
|
TagValidator: /* @__PURE__ */ __name(() => TagValidator, "TagValidator"),
|
|
308
333
|
TemplateRenderMethodValidator: /* @__PURE__ */ __name(() => TemplateRenderMethodValidator, "TemplateRenderMethodValidator"),
|
|
@@ -16506,7 +16531,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16506
16531
|
webhookUrl: external_exports.string().url().optional().describe("Webhook URL to receive claim notifications"),
|
|
16507
16532
|
suppressDelivery: external_exports.boolean().optional().describe("If true, returns claimUrl without sending email/SMS"),
|
|
16508
16533
|
branding: SendBrandingOptionsValidator.optional().describe("Branding for email/SMS delivery"),
|
|
16509
|
-
guardianEmail: external_exports.string().email().optional().describe("Guardian email that must approve before student can claim")
|
|
16534
|
+
guardianEmail: external_exports.string().email().optional().describe("Guardian email that must approve before student can claim"),
|
|
16535
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
16536
|
+
"How many days the credential stays claimable in the Universal Inbox (default 30). Does not change the credential validity period."
|
|
16537
|
+
)
|
|
16510
16538
|
});
|
|
16511
16539
|
var SendBoostInputValidator = external_exports.object({
|
|
16512
16540
|
type: external_exports.literal("boost"),
|
|
@@ -16801,7 +16829,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16801
16829
|
"APP_NOTIFICATION",
|
|
16802
16830
|
"CREDENTIAL_REVOKED",
|
|
16803
16831
|
"CREDENTIAL_SUSPENDED",
|
|
16804
|
-
"CREDENTIAL_UNSUSPENDED"
|
|
16832
|
+
"CREDENTIAL_UNSUSPENDED",
|
|
16833
|
+
"CREDENTIAL_REFRESHED"
|
|
16805
16834
|
]);
|
|
16806
16835
|
var LCNNotificationMessageValidator = external_exports.object({
|
|
16807
16836
|
title: external_exports.string().optional(),
|
|
@@ -16933,12 +16962,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16933
16962
|
});
|
|
16934
16963
|
var InboxCredentialValidator = external_exports.object({
|
|
16935
16964
|
id: external_exports.string(),
|
|
16936
|
-
credential: external_exports.string(),
|
|
16965
|
+
credential: external_exports.string().optional(),
|
|
16937
16966
|
isSigned: external_exports.boolean(),
|
|
16938
16967
|
currentStatus: LCNInboxStatusEnumValidator,
|
|
16939
16968
|
isAccepted: external_exports.boolean().optional(),
|
|
16940
16969
|
expiresAt: external_exports.string(),
|
|
16941
16970
|
createdAt: external_exports.string(),
|
|
16971
|
+
finalizedAt: external_exports.string().optional(),
|
|
16972
|
+
expiredAt: external_exports.string().optional(),
|
|
16973
|
+
credentialName: external_exports.string().optional(),
|
|
16974
|
+
achievementType: external_exports.string().optional(),
|
|
16942
16975
|
issuerDid: external_exports.string(),
|
|
16943
16976
|
webhookUrl: external_exports.string().optional(),
|
|
16944
16977
|
boostUri: external_exports.string().optional(),
|
|
@@ -16992,7 +17025,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16992
17025
|
"The signing authority to use for the credential. If not provided, the users default signing authority will be used if the credential is not signed."
|
|
16993
17026
|
),
|
|
16994
17027
|
webhookUrl: external_exports.string().url().optional().describe("The webhook URL to receive credential issuance events."),
|
|
16995
|
-
expiresInDays: external_exports.number().min(1).max(
|
|
17028
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
17029
|
+
"How many days the encrypted inbox payload remains claimable. This does not change the credential validity period."
|
|
17030
|
+
),
|
|
16996
17031
|
templateData: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe(
|
|
16997
17032
|
"Template data to render into the boost credential template using Mustache syntax. Only used when boostUri is provided."
|
|
16998
17033
|
),
|
|
@@ -17055,6 +17090,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17055
17090
|
credential: VCValidator.or(VPValidator).or(UnsignedVCValidator).or(CredentialNameRefValidator).describe("The credential to issue, or a { name } reference to resolve a boost template."),
|
|
17056
17091
|
configuration: external_exports.object({
|
|
17057
17092
|
publishableKey: external_exports.string(),
|
|
17093
|
+
expiresInDays: external_exports.number().int().min(1).max(720).optional().describe(
|
|
17094
|
+
"Inbox claim window in days. Defaults to 720; use a shorter window for sensitive records."
|
|
17095
|
+
),
|
|
17058
17096
|
signingAuthorityName: external_exports.string().optional(),
|
|
17059
17097
|
listingId: external_exports.string().optional(),
|
|
17060
17098
|
listingSlug: external_exports.string().optional()
|
|
@@ -17692,6 +17730,191 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17692
17730
|
const result = inAppMessagesFlagValidator.safeParse(raw);
|
|
17693
17731
|
return result.success ? result.data : EMPTY_IN_APP_MESSAGES_FLAG;
|
|
17694
17732
|
}, "parseInAppMessagesFlag");
|
|
17733
|
+
var LearnCardRefreshAuthorizationValidator = external_exports.object({ type: external_exports.literal("LearnCardDIDAuth") }).catchall(external_exports.any());
|
|
17734
|
+
var ManagedCredentialRefreshServiceValidator = external_exports.object({
|
|
17735
|
+
id: external_exports.string().min(1),
|
|
17736
|
+
type: external_exports.literal("LearnCardCredentialRefresh2026"),
|
|
17737
|
+
authorization: LearnCardRefreshAuthorizationValidator.optional()
|
|
17738
|
+
}).catchall(external_exports.any());
|
|
17739
|
+
var StandardCredentialRefreshServiceValidator = external_exports.object({
|
|
17740
|
+
id: external_exports.string().min(1),
|
|
17741
|
+
type: external_exports.literal("1EdTechCredentialRefresh")
|
|
17742
|
+
}).catchall(external_exports.any());
|
|
17743
|
+
var SupportedCredentialRefreshServiceValidator = external_exports.union([
|
|
17744
|
+
ManagedCredentialRefreshServiceValidator,
|
|
17745
|
+
StandardCredentialRefreshServiceValidator
|
|
17746
|
+
]);
|
|
17747
|
+
var AllocateCredentialRefreshInputValidator = external_exports.object({
|
|
17748
|
+
holder: external_exports.object({
|
|
17749
|
+
profileId: external_exports.string().optional(),
|
|
17750
|
+
did: external_exports.string().min(1)
|
|
17751
|
+
}),
|
|
17752
|
+
credentialId: external_exports.string().min(1)
|
|
17753
|
+
});
|
|
17754
|
+
var AllocateCredentialRefreshResultValidator = external_exports.object({
|
|
17755
|
+
refreshId: external_exports.string().min(1),
|
|
17756
|
+
refreshService: ManagedCredentialRefreshServiceValidator.extend({
|
|
17757
|
+
authorization: LearnCardRefreshAuthorizationValidator
|
|
17758
|
+
})
|
|
17759
|
+
});
|
|
17760
|
+
var CredentialRefreshSigningModeValidator = external_exports.enum(["issuer-signed", "signing-authority"]);
|
|
17761
|
+
var PublishCredentialRefreshBaseFields = {
|
|
17762
|
+
refreshId: external_exports.string().min(1),
|
|
17763
|
+
notifyHolder: external_exports.boolean().optional(),
|
|
17764
|
+
updateSummary: external_exports.string().optional(),
|
|
17765
|
+
idempotencyKey: external_exports.string().optional()
|
|
17766
|
+
};
|
|
17767
|
+
var PublishIssuerSignedRefreshValidator = external_exports.object({
|
|
17768
|
+
...PublishCredentialRefreshBaseFields,
|
|
17769
|
+
mode: external_exports.literal("issuer-signed"),
|
|
17770
|
+
signedCredential: VCValidator
|
|
17771
|
+
});
|
|
17772
|
+
var PublishSigningAuthorityRefreshValidator = external_exports.object({
|
|
17773
|
+
...PublishCredentialRefreshBaseFields,
|
|
17774
|
+
mode: external_exports.literal("signing-authority"),
|
|
17775
|
+
credential: UnsignedVCValidator,
|
|
17776
|
+
signingAuthority: external_exports.object({
|
|
17777
|
+
type: external_exports.string().min(1)
|
|
17778
|
+
}).catchall(external_exports.any())
|
|
17779
|
+
});
|
|
17780
|
+
var PublishCredentialRefreshInputValidator = external_exports.object({
|
|
17781
|
+
...PublishCredentialRefreshBaseFields,
|
|
17782
|
+
mode: CredentialRefreshSigningModeValidator,
|
|
17783
|
+
signedCredential: VCValidator.optional(),
|
|
17784
|
+
credential: UnsignedVCValidator.optional(),
|
|
17785
|
+
signingAuthority: external_exports.object({
|
|
17786
|
+
type: external_exports.string().min(1)
|
|
17787
|
+
}).catchall(external_exports.any()).optional()
|
|
17788
|
+
}).superRefine((input, ctx) => {
|
|
17789
|
+
if (input.mode === "issuer-signed" && !input.signedCredential) {
|
|
17790
|
+
ctx.addIssue({
|
|
17791
|
+
code: "custom",
|
|
17792
|
+
path: ["signedCredential"],
|
|
17793
|
+
message: "signedCredential is required for issuer-signed publication"
|
|
17794
|
+
});
|
|
17795
|
+
}
|
|
17796
|
+
if (input.mode === "issuer-signed" && (input.credential !== void 0 || input.signingAuthority !== void 0)) {
|
|
17797
|
+
ctx.addIssue({
|
|
17798
|
+
code: "custom",
|
|
17799
|
+
path: ["mode"],
|
|
17800
|
+
message: "issuer-signed publication cannot include signing-authority fields"
|
|
17801
|
+
});
|
|
17802
|
+
}
|
|
17803
|
+
if (input.mode === "signing-authority") {
|
|
17804
|
+
if (input.signedCredential !== void 0) {
|
|
17805
|
+
ctx.addIssue({
|
|
17806
|
+
code: "custom",
|
|
17807
|
+
path: ["signedCredential"],
|
|
17808
|
+
message: "signing-authority publication cannot include signedCredential"
|
|
17809
|
+
});
|
|
17810
|
+
}
|
|
17811
|
+
if (!input.credential) {
|
|
17812
|
+
ctx.addIssue({
|
|
17813
|
+
code: "custom",
|
|
17814
|
+
path: ["credential"],
|
|
17815
|
+
message: "credential is required for signing-authority publication"
|
|
17816
|
+
});
|
|
17817
|
+
}
|
|
17818
|
+
if (!input.signingAuthority) {
|
|
17819
|
+
ctx.addIssue({
|
|
17820
|
+
code: "custom",
|
|
17821
|
+
path: ["signingAuthority"],
|
|
17822
|
+
message: "signingAuthority is required for signing-authority publication"
|
|
17823
|
+
});
|
|
17824
|
+
}
|
|
17825
|
+
}
|
|
17826
|
+
});
|
|
17827
|
+
var PublishCredentialRefreshNotificationValidator = external_exports.enum([
|
|
17828
|
+
"queued",
|
|
17829
|
+
"suppressed",
|
|
17830
|
+
"not-applicable",
|
|
17831
|
+
/** Publication succeeded, but the post-commit notification enqueue must be retried. */
|
|
17832
|
+
"delivery-failed"
|
|
17833
|
+
]);
|
|
17834
|
+
var PublishCredentialRefreshResultValidator = external_exports.object({
|
|
17835
|
+
refreshId: external_exports.string().min(1),
|
|
17836
|
+
version: external_exports.number().int().positive(),
|
|
17837
|
+
publishedAt: external_exports.string().min(1),
|
|
17838
|
+
notification: PublishCredentialRefreshNotificationValidator
|
|
17839
|
+
});
|
|
17840
|
+
var CredentialRefreshVersionMetadataValidator = external_exports.object({
|
|
17841
|
+
version: external_exports.number().int().positive(),
|
|
17842
|
+
publishedAt: external_exports.string().min(1),
|
|
17843
|
+
effectiveAt: external_exports.string().optional(),
|
|
17844
|
+
etag: external_exports.string().optional(),
|
|
17845
|
+
signingMode: CredentialRefreshSigningModeValidator.optional(),
|
|
17846
|
+
updateSummary: external_exports.string().optional()
|
|
17847
|
+
});
|
|
17848
|
+
var GetCredentialRefreshHistoryInputValidator = external_exports.object({
|
|
17849
|
+
refreshId: external_exports.string().min(1),
|
|
17850
|
+
cursor: external_exports.string().optional(),
|
|
17851
|
+
limit: external_exports.number().int().positive().optional()
|
|
17852
|
+
});
|
|
17853
|
+
var GetCredentialRefreshHistoryResultValidator = external_exports.object({
|
|
17854
|
+
records: CredentialRefreshVersionMetadataValidator.array(),
|
|
17855
|
+
hasMore: external_exports.boolean(),
|
|
17856
|
+
cursor: external_exports.string().optional()
|
|
17857
|
+
});
|
|
17858
|
+
var CredentialRefreshChallengeValidator = external_exports.object({
|
|
17859
|
+
challenge: external_exports.string().min(1),
|
|
17860
|
+
expiresAt: external_exports.string().min(1),
|
|
17861
|
+
domain: external_exports.string().optional(),
|
|
17862
|
+
scheme: external_exports.literal("LearnCardDIDAuth").optional()
|
|
17863
|
+
});
|
|
17864
|
+
var PublicCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17865
|
+
format: external_exports.literal("vc"),
|
|
17866
|
+
credential: VCValidator,
|
|
17867
|
+
etag: external_exports.string().optional()
|
|
17868
|
+
});
|
|
17869
|
+
var JweCredentialRefreshEnvelopeValidator = external_exports.object({
|
|
17870
|
+
format: external_exports.literal("jwe"),
|
|
17871
|
+
jwe: JWEValidator,
|
|
17872
|
+
etag: external_exports.string().optional(),
|
|
17873
|
+
/** Present on LearnCard-managed endpoints; optional for interoperable JWE services. */
|
|
17874
|
+
version: external_exports.number().int().positive().optional()
|
|
17875
|
+
});
|
|
17876
|
+
var CredentialRefreshResponseEnvelopeValidator = external_exports.discriminatedUnion("format", [
|
|
17877
|
+
PublicCredentialRefreshEnvelopeValidator,
|
|
17878
|
+
JweCredentialRefreshEnvelopeValidator
|
|
17879
|
+
]);
|
|
17880
|
+
var CredentialRefreshFailureCodeValidator = external_exports.enum([
|
|
17881
|
+
"UNAVAILABLE",
|
|
17882
|
+
"TIMEOUT",
|
|
17883
|
+
"UNSUPPORTED_SERVICE",
|
|
17884
|
+
"UNAUTHORIZED",
|
|
17885
|
+
"MALFORMED_RESPONSE",
|
|
17886
|
+
"INVALID_PROOF",
|
|
17887
|
+
"ISSUER_MISMATCH",
|
|
17888
|
+
"ID_MISMATCH",
|
|
17889
|
+
"ROLLBACK",
|
|
17890
|
+
"REVOKED",
|
|
17891
|
+
"UNSAFE_ENDPOINT"
|
|
17892
|
+
]);
|
|
17893
|
+
var CredentialRefreshUpdatedResultValidator = external_exports.object({
|
|
17894
|
+
status: external_exports.literal("updated"),
|
|
17895
|
+
credential: VCValidator,
|
|
17896
|
+
etag: external_exports.string().optional(),
|
|
17897
|
+
managedVersion: external_exports.number().int().positive().optional()
|
|
17898
|
+
});
|
|
17899
|
+
var CredentialRefreshUnchangedResultValidator = external_exports.object({
|
|
17900
|
+
status: external_exports.literal("unchanged"),
|
|
17901
|
+
checkedAt: external_exports.string().min(1),
|
|
17902
|
+
etag: external_exports.string().optional()
|
|
17903
|
+
});
|
|
17904
|
+
var CredentialRefreshUnsupportedResultValidator = external_exports.object({
|
|
17905
|
+
status: external_exports.literal("unsupported")
|
|
17906
|
+
});
|
|
17907
|
+
var CredentialRefreshFailedResultValidator = external_exports.object({
|
|
17908
|
+
status: external_exports.literal("failed"),
|
|
17909
|
+
code: CredentialRefreshFailureCodeValidator,
|
|
17910
|
+
retryable: external_exports.boolean()
|
|
17911
|
+
});
|
|
17912
|
+
var CredentialRefreshResultValidator = external_exports.discriminatedUnion("status", [
|
|
17913
|
+
CredentialRefreshUpdatedResultValidator,
|
|
17914
|
+
CredentialRefreshUnchangedResultValidator,
|
|
17915
|
+
CredentialRefreshUnsupportedResultValidator,
|
|
17916
|
+
CredentialRefreshFailedResultValidator
|
|
17917
|
+
]);
|
|
17695
17918
|
}
|
|
17696
17919
|
});
|
|
17697
17920
|
|