@learncard/types 5.17.4 → 5.17.5
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 +5 -5
- package/dist/bitstring-status-list.d.ts +1 -1
- package/dist/bitstring-status-list.d.ts.map +1 -1
- package/dist/clr.d.ts +1 -1
- package/dist/clr.d.ts.map +1 -1
- package/dist/credential-format.d.ts +1 -1
- package/dist/credential-format.d.ts.map +1 -1
- package/dist/crypto.d.ts +1 -1
- package/dist/crypto.d.ts.map +1 -1
- package/dist/did.d.ts +1 -1
- package/dist/did.d.ts.map +1 -1
- package/dist/lcn.d.ts +5 -2
- package/dist/lcn.d.ts.map +1 -1
- package/dist/learncard.d.ts +1 -1
- package/dist/learncard.d.ts.map +1 -1
- package/dist/learncloud.d.ts +1 -1
- package/dist/learncloud.d.ts.map +1 -1
- package/dist/mongo.d.ts +1 -1
- package/dist/mongo.d.ts.map +1 -1
- package/dist/obv3.d.ts +1 -1
- package/dist/obv3.d.ts.map +1 -1
- package/dist/queries.d.ts +1 -1
- package/dist/queries.d.ts.map +1 -1
- package/dist/types.cjs.development.cjs +82 -81
- package/dist/types.cjs.development.cjs.map +3 -3
- package/dist/types.cjs.production.min.cjs +1 -1
- package/dist/types.cjs.production.min.cjs.map +3 -3
- package/dist/types.esm.js +14 -13
- package/dist/types.esm.js.map +2 -2
- package/dist/vc.d.ts +1 -1
- package/dist/vc.d.ts.map +1 -1
- package/package.json +64 -62
- package/src/auth.ts +460 -0
- package/src/bitstring-status-list.ts +44 -0
- package/src/clr.ts +68 -0
- package/src/credential-format.ts +154 -0
- package/src/crypto.ts +41 -0
- package/src/did.ts +47 -0
- package/src/helpers.ts +10 -0
- package/src/index.ts +17 -0
- package/src/lcn.ts +2181 -0
- package/src/learncard.ts +123 -0
- package/src/learncloud.ts +26 -0
- package/src/mongo.ts +14 -0
- package/src/obv3.ts +252 -0
- package/src/queries.ts +56 -0
- package/src/registries.ts +9 -0
- package/src/vc.ts +221 -0
- package/src/wasm.ts +1 -0
package/dist/vc.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
2
|
export declare const ContextValidator: z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
|
|
3
3
|
export type Context = z.infer<typeof ContextValidator>;
|
|
4
4
|
export declare const AchievementCriteriaValidator: z.ZodObject<{
|
package/dist/vc.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vc.d.ts","sourceRoot":"","sources":["../src/vc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"vc.d.ts","sourceRoot":"","sources":["../src/vc.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,64 +1,66 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"files": [
|
|
21
|
-
"dist"
|
|
22
|
-
],
|
|
23
|
-
"author": "Learning Economy Foundation (www.learningeconomy.io)",
|
|
24
|
-
"license": "MIT",
|
|
25
|
-
"homepage": "https://github.com/learningeconomy/LearnCard/tree/main/packages/learn-card-types/README.md",
|
|
26
|
-
"repository": {
|
|
27
|
-
"type": "git",
|
|
28
|
-
"url": "https://github.com/learningeconomy/LearnCard"
|
|
29
|
-
},
|
|
30
|
-
"bugs": {
|
|
31
|
-
"url": "https://github.com/learningeconomy/LearnCard/issues"
|
|
32
|
-
},
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"zod": "^4.1.13"
|
|
35
|
-
},
|
|
36
|
-
"devDependencies": {
|
|
37
|
-
"@esbuild-plugins/node-resolve": "^0.2.2",
|
|
38
|
-
"@size-limit/preset-small-lib": "^7.0.8",
|
|
39
|
-
"@types/node": "^17.0.38",
|
|
40
|
-
"aqu": "0.4.3",
|
|
41
|
-
"esbuild": "^0.27.1",
|
|
42
|
-
"husky": "^8.0.1",
|
|
43
|
-
"lint-staged": "^13.0.0",
|
|
44
|
-
"np": "^7.6.1",
|
|
45
|
-
"size-limit": "^7.0.8",
|
|
46
|
-
"typescript": "5.6.2"
|
|
47
|
-
},
|
|
48
|
-
"types": "./dist/index.d.ts",
|
|
49
|
-
"sideEffects": false,
|
|
50
|
-
"size-limit": [
|
|
51
|
-
{
|
|
52
|
-
"path": "dist/types.cjs.production.min.js",
|
|
53
|
-
"limit": "10 KB"
|
|
2
|
+
"name": "@learncard/types",
|
|
3
|
+
"version": "5.17.5",
|
|
4
|
+
"description": "Shared types for learn card",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/types.esm.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"development": "./src/index.ts",
|
|
11
|
+
"import": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/types.esm.js"
|
|
14
|
+
},
|
|
15
|
+
"require": {
|
|
16
|
+
"types": "./dist/index.d.cts",
|
|
17
|
+
"default": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
54
20
|
},
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"src"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "node ./scripts/build.mjs && shx cp ./scripts/mixedEntypoint.js ./dist/index.cjs && tsc --p tsconfig.json && shx cp ./dist/index.d.ts ./dist/index.d.cts",
|
|
27
|
+
"start": "aqu watch"
|
|
28
|
+
},
|
|
29
|
+
"author": "Learning Economy Foundation (www.learningeconomy.io)",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"homepage": "https://github.com/learningeconomy/LearnCard/tree/main/packages/learn-card-types/README.md",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/learningeconomy/LearnCard"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/learningeconomy/LearnCard/issues"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"zod": "^4.1.13"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@esbuild-plugins/node-resolve": "^0.2.2",
|
|
44
|
+
"@size-limit/preset-small-lib": "^7.0.8",
|
|
45
|
+
"@types/node": "^17.0.38",
|
|
46
|
+
"aqu": "0.4.3",
|
|
47
|
+
"esbuild": "^0.27.1",
|
|
48
|
+
"husky": "^8.0.1",
|
|
49
|
+
"lint-staged": "^13.0.0",
|
|
50
|
+
"np": "^7.6.1",
|
|
51
|
+
"size-limit": "^7.0.8",
|
|
52
|
+
"typescript": "5.6.2"
|
|
53
|
+
},
|
|
54
|
+
"types": "./dist/index.d.ts",
|
|
55
|
+
"sideEffects": false,
|
|
56
|
+
"size-limit": [
|
|
57
|
+
{
|
|
58
|
+
"path": "dist/types.cjs.production.min.js",
|
|
59
|
+
"limit": "10 KB"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"path": "dist/types.esm.js",
|
|
63
|
+
"limit": "10 KB"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-agnostic interfaces for authentication and key derivation.
|
|
3
|
+
*
|
|
4
|
+
* Both @learncard/sss-key-manager and learn-card-base import from here,
|
|
5
|
+
* ensuring a single canonical source for abstract interfaces without
|
|
6
|
+
* coupling consumers to any specific implementation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Auth Session Error
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Typed error for auth session issues.
|
|
15
|
+
* Auth providers should throw this (instead of generic Error) when the
|
|
16
|
+
* session is expired, revoked, or missing so the coordinator can
|
|
17
|
+
* distinguish "not logged in" from "unexpected failure".
|
|
18
|
+
*/
|
|
19
|
+
export class AuthSessionError extends Error {
|
|
20
|
+
constructor(
|
|
21
|
+
message: string,
|
|
22
|
+
public readonly reason: 'expired' | 'no_session' | 'revoked' | 'network'
|
|
23
|
+
) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = 'AuthSessionError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// Auth Provider
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Auth provider identifier. Known values: 'firebase', 'supertokens', 'keycloak', 'oidc'.
|
|
35
|
+
* Use any string to support custom auth providers without modifying this type.
|
|
36
|
+
*/
|
|
37
|
+
export type AuthProviderType = string;
|
|
38
|
+
|
|
39
|
+
export interface AuthUser {
|
|
40
|
+
id: string;
|
|
41
|
+
email?: string;
|
|
42
|
+
phone?: string;
|
|
43
|
+
displayName?: string;
|
|
44
|
+
photoUrl?: string;
|
|
45
|
+
providerType: AuthProviderType;
|
|
46
|
+
|
|
47
|
+
/** Account creation timestamp (when available from the auth provider) */
|
|
48
|
+
createdAt?: Date;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Abstract auth provider interface.
|
|
53
|
+
* Implementations wrap a specific auth SDK (Firebase, Supertokens, etc.)
|
|
54
|
+
* and expose a uniform API to the coordinator.
|
|
55
|
+
*/
|
|
56
|
+
export interface AuthProvider {
|
|
57
|
+
getIdToken(forceRefresh?: boolean): Promise<string>;
|
|
58
|
+
getCurrentUser(): Promise<AuthUser | null>;
|
|
59
|
+
getProviderType(): AuthProviderType;
|
|
60
|
+
signOut(): Promise<void>;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Attempt to silently refresh the auth session (e.g., force-refresh
|
|
64
|
+
* the JWT using the underlying refresh token).
|
|
65
|
+
*
|
|
66
|
+
* Returns `true` if the session was successfully refreshed.
|
|
67
|
+
* Returns `false` if a full re-authentication is required.
|
|
68
|
+
*
|
|
69
|
+
* Optional — providers that don't implement this will require full
|
|
70
|
+
* re-auth whenever the session expires.
|
|
71
|
+
*/
|
|
72
|
+
refreshSession?(): Promise<boolean>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Re-authenticate with a server-issued token (e.g., a Firebase custom
|
|
76
|
+
* token returned after a server-side account change that invalidates
|
|
77
|
+
* the current session).
|
|
78
|
+
*
|
|
79
|
+
* Returns the refreshed AuthUser read directly from the auth SDK
|
|
80
|
+
* (not from the app store, which may be stale).
|
|
81
|
+
*
|
|
82
|
+
* Optional — only needed by providers whose server-side account
|
|
83
|
+
* mutations invalidate the client session.
|
|
84
|
+
*/
|
|
85
|
+
reauthenticateWithToken?(token: string): Promise<AuthUser | null>;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Sign-In Adapter (Phase 2)
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Opaque handle returned by `sendPhoneOtp()`.
|
|
94
|
+
* On web this wraps a ConfirmationResult; on native it carries a verificationId.
|
|
95
|
+
* Consumers pass this back to `confirmPhoneOtp()` — never inspect internals.
|
|
96
|
+
*/
|
|
97
|
+
export interface PhoneVerificationHandle {
|
|
98
|
+
verificationId: string;
|
|
99
|
+
|
|
100
|
+
/** Platform-specific confirmation object (e.g. Firebase ConfirmationResult) */
|
|
101
|
+
_internal?: unknown;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Abstract sign-in adapter interface.
|
|
106
|
+
*
|
|
107
|
+
* Encapsulates **all** provider-specific sign-in logic (Firebase, Supertokens,
|
|
108
|
+
* Keycloak, …). Apps register a concrete adapter at startup via
|
|
109
|
+
* `registerSignInAdapterFactory()` and resolve it through the provider registry.
|
|
110
|
+
*
|
|
111
|
+
* The `subscribe()` method is the **single source of truth** for auth state:
|
|
112
|
+
* `SignInAdapterProvider` calls it once and writes every state change to
|
|
113
|
+
* `authUserStore`, replacing the Phase 1 bridge.
|
|
114
|
+
*
|
|
115
|
+
* Individual sign-in methods return `Promise<AuthUser>` on success and throw
|
|
116
|
+
* on failure — the app-level hook (`useFirebase` / `useAuth`) handles UI
|
|
117
|
+
* feedback (toasts, modals, analytics).
|
|
118
|
+
*/
|
|
119
|
+
export interface SignInAdapter {
|
|
120
|
+
readonly providerType: AuthProviderType;
|
|
121
|
+
|
|
122
|
+
// --- Auth state ---
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Subscribe to auth-state changes. The callback fires immediately with
|
|
126
|
+
* the current state and again on every sign-in / sign-out.
|
|
127
|
+
*
|
|
128
|
+
* Returns an unsubscribe function.
|
|
129
|
+
*/
|
|
130
|
+
subscribe(onUser: (user: AuthUser | null) => void): () => void;
|
|
131
|
+
|
|
132
|
+
/** Synchronous snapshot of the last user emitted by `subscribe()`. */
|
|
133
|
+
getCurrentUser(): AuthUser | null;
|
|
134
|
+
|
|
135
|
+
// --- Email link (passwordless) ---
|
|
136
|
+
|
|
137
|
+
sendEmailLink(email: string, redirectUrl?: string): Promise<void>;
|
|
138
|
+
|
|
139
|
+
verifyEmailLink(email: string, link: string): Promise<AuthUser>;
|
|
140
|
+
|
|
141
|
+
isEmailLink(link: string): boolean;
|
|
142
|
+
|
|
143
|
+
// --- Phone OTP ---
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Send an SMS OTP to the given number.
|
|
147
|
+
* On web this sets up a RecaptchaVerifier transparently.
|
|
148
|
+
*/
|
|
149
|
+
sendPhoneOtp(phoneNumber: string): Promise<PhoneVerificationHandle>;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Confirm a phone OTP using the handle returned by `sendPhoneOtp()`.
|
|
153
|
+
*/
|
|
154
|
+
confirmPhoneOtp(handle: PhoneVerificationHandle, code: string | number): Promise<AuthUser>;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Confirm a phone OTP using a native verificationId (Capacitor auto-verify
|
|
158
|
+
* path). Falls back to `confirmPhoneOtp` when not implemented.
|
|
159
|
+
*/
|
|
160
|
+
confirmNativePhoneOtp?(verificationId: string, code: string | number): Promise<AuthUser>;
|
|
161
|
+
|
|
162
|
+
// --- OAuth ---
|
|
163
|
+
|
|
164
|
+
signInWithGoogle(): Promise<AuthUser>;
|
|
165
|
+
|
|
166
|
+
signInWithApple(): Promise<AuthUser>;
|
|
167
|
+
|
|
168
|
+
/** Check for a pending OAuth redirect result (e.g. Apple on web). */
|
|
169
|
+
checkRedirectResult?(): Promise<AuthUser | null>;
|
|
170
|
+
|
|
171
|
+
// --- Custom / SSO ---
|
|
172
|
+
|
|
173
|
+
signInWithCustomToken(token: string): Promise<AuthUser>;
|
|
174
|
+
|
|
175
|
+
/** Sign in with an OIDC credential (e.g. Keycloak World Scouts SSO). */
|
|
176
|
+
signInWithOidcCredential?(providerId: string, idToken: string): Promise<AuthUser>;
|
|
177
|
+
|
|
178
|
+
// --- Account management ---
|
|
179
|
+
|
|
180
|
+
deleteAccount(): Promise<void>;
|
|
181
|
+
|
|
182
|
+
signOut(): Promise<void>;
|
|
183
|
+
|
|
184
|
+
// --- Cleanup ---
|
|
185
|
+
|
|
186
|
+
/** Tear down any DOM elements created by the adapter (e.g. RecaptchaVerifier). */
|
|
187
|
+
cleanup?(): void;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
// Recovery (generic)
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Recovery method metadata returned by the server.
|
|
196
|
+
* The `type` is a string so strategies can define their own method types
|
|
197
|
+
* without modifying this interface.
|
|
198
|
+
*/
|
|
199
|
+
export interface RecoveryMethodInfo {
|
|
200
|
+
type: string;
|
|
201
|
+
createdAt: Date;
|
|
202
|
+
credentialId?: string;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Generic result of a successful recovery execution.
|
|
207
|
+
* All strategies must produce a private key + DID.
|
|
208
|
+
*/
|
|
209
|
+
export interface RecoveryResult {
|
|
210
|
+
privateKey: string;
|
|
211
|
+
did: string;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
// Server Key Status
|
|
216
|
+
// ---------------------------------------------------------------------------
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Server key status returned by the strategy's fetchServerKeyStatus.
|
|
220
|
+
* The strategy owns the server shape — different strategies may
|
|
221
|
+
* have fundamentally different server payloads.
|
|
222
|
+
*/
|
|
223
|
+
export interface ServerKeyStatus {
|
|
224
|
+
exists: boolean;
|
|
225
|
+
needsMigration: boolean;
|
|
226
|
+
primaryDid: string | null;
|
|
227
|
+
recoveryMethods: RecoveryMethodInfo[];
|
|
228
|
+
authShare: string | null;
|
|
229
|
+
shareVersion: number | null;
|
|
230
|
+
maskedRecoveryEmail?: string | null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// ---------------------------------------------------------------------------
|
|
234
|
+
// Key Derivation Capabilities
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Declarative capability flags for a key derivation strategy.
|
|
239
|
+
*
|
|
240
|
+
* UI components read these to decide which features to show.
|
|
241
|
+
* Each strategy declares its own capabilities — no strategy-specific
|
|
242
|
+
* checks needed in the UI layer.
|
|
243
|
+
*
|
|
244
|
+
* All flags default to `false` when absent.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* // SSS declares full capabilities:
|
|
249
|
+
* capabilities: { recovery: true, deviceLinking: true, localKeyPersistence: true }
|
|
250
|
+
*
|
|
251
|
+
* // Web3Auth derives keys on-demand, nothing local to manage:
|
|
252
|
+
* capabilities: { recovery: false, deviceLinking: false, localKeyPersistence: false }
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
export interface KeyDerivationCapabilities {
|
|
256
|
+
/** Strategy supports user-facing recovery methods (setup + execution) */
|
|
257
|
+
recovery: boolean;
|
|
258
|
+
|
|
259
|
+
/** Strategy supports cross-device key transfer (e.g., QR-based device linking) */
|
|
260
|
+
deviceLinking: boolean;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Strategy persists key material locally (e.g., device share in IndexedDB).
|
|
264
|
+
* When true, "public computer" / "forget device" features are relevant.
|
|
265
|
+
*/
|
|
266
|
+
localKeyPersistence: boolean;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Strategy supports upgrading the user's contact method (e.g., phone → email).
|
|
270
|
+
* When true, the `upgradeContactMethod` method is available and the
|
|
271
|
+
* email-linking gate can be shown for phone-only users.
|
|
272
|
+
*/
|
|
273
|
+
contactMethodUpgrade: boolean;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Key Derivation Strategy (generic)
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Key Derivation Strategy
|
|
282
|
+
*
|
|
283
|
+
* Abstract interface for different key derivation implementations.
|
|
284
|
+
* Used by AuthCoordinator to delegate key operations.
|
|
285
|
+
*
|
|
286
|
+
* The strategy owns:
|
|
287
|
+
* - Local key storage
|
|
288
|
+
* - Key splitting and reconstruction
|
|
289
|
+
* - Server communication for remote key components
|
|
290
|
+
* - Recovery method execution and setup
|
|
291
|
+
* - Storage cleanup knowledge
|
|
292
|
+
*
|
|
293
|
+
* Type parameters allow each strategy to define its own recovery shapes:
|
|
294
|
+
* - TRecoveryInput: what the user provides to recover (e.g., password, passkey)
|
|
295
|
+
* - TRecoverySetupInput: what the user provides to set up a recovery method
|
|
296
|
+
* - TRecoverySetupResult: what setup returns (e.g., generated phrase, credential ID)
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* // SSS strategy with specific recovery types:
|
|
300
|
+
* type SSSStrategy = KeyDerivationStrategy<SSSRecoveryInput, SSSRecoverySetupInput, SSSRecoverySetupResult>;
|
|
301
|
+
*
|
|
302
|
+
* // Simple strategy with no recovery:
|
|
303
|
+
* type SimpleStrategy = KeyDerivationStrategy<never, never, never>;
|
|
304
|
+
*/
|
|
305
|
+
export interface KeyDerivationStrategy<
|
|
306
|
+
TRecoveryInput = unknown,
|
|
307
|
+
TRecoverySetupInput = unknown,
|
|
308
|
+
TRecoverySetupResult = unknown,
|
|
309
|
+
> {
|
|
310
|
+
readonly name: string;
|
|
311
|
+
|
|
312
|
+
/** Declarative feature flags — UI reads these to gate features */
|
|
313
|
+
readonly capabilities: KeyDerivationCapabilities;
|
|
314
|
+
|
|
315
|
+
// --- Key lifecycle ---
|
|
316
|
+
|
|
317
|
+
/** Check if there's a local key component (e.g., device share) */
|
|
318
|
+
hasLocalKey(): Promise<boolean>;
|
|
319
|
+
|
|
320
|
+
/** Get the local key component */
|
|
321
|
+
getLocalKey(): Promise<string | null>;
|
|
322
|
+
|
|
323
|
+
/** Store a local key component */
|
|
324
|
+
storeLocalKey(key: string): Promise<void>;
|
|
325
|
+
|
|
326
|
+
/** Clear all local key data */
|
|
327
|
+
clearLocalKeys(): Promise<void>;
|
|
328
|
+
|
|
329
|
+
/** Split a private key into shares/components */
|
|
330
|
+
splitKey(privateKey: string): Promise<{ localKey: string; remoteKey: string }>;
|
|
331
|
+
|
|
332
|
+
/** Reconstruct private key from components */
|
|
333
|
+
reconstructKey(localKey: string, remoteKey: string): Promise<string>;
|
|
334
|
+
|
|
335
|
+
/** Verify that stored keys can reconstruct the expected DID */
|
|
336
|
+
verifyKeys?(
|
|
337
|
+
localKey: string,
|
|
338
|
+
remoteKey: string,
|
|
339
|
+
expectedDid: string,
|
|
340
|
+
didFromPrivateKey: (pk: string) => Promise<string>
|
|
341
|
+
): Promise<boolean>;
|
|
342
|
+
|
|
343
|
+
// --- Server communication ---
|
|
344
|
+
|
|
345
|
+
/** Fetch the server-side key status for the authenticated user */
|
|
346
|
+
fetchServerKeyStatus(token: string, providerType: AuthProviderType): Promise<ServerKeyStatus>;
|
|
347
|
+
|
|
348
|
+
/** Store the remote key component on the server */
|
|
349
|
+
storeAuthShare(token: string, providerType: AuthProviderType, remoteKey: string, did: string, didAuthVp?: string): Promise<void>;
|
|
350
|
+
|
|
351
|
+
/** Mark migration complete on the server (optional — only needed for migration-capable strategies) */
|
|
352
|
+
markMigrated?(token: string, providerType: AuthProviderType, didAuthVp?: string): Promise<void>;
|
|
353
|
+
|
|
354
|
+
// --- Recovery ---
|
|
355
|
+
|
|
356
|
+
/** Execute a recovery flow and return the recovered private key + DID */
|
|
357
|
+
executeRecovery(params: {
|
|
358
|
+
token: string;
|
|
359
|
+
providerType: AuthProviderType;
|
|
360
|
+
input: TRecoveryInput;
|
|
361
|
+
/** Optional: validate the reconstructed key's DID before rotating shares */
|
|
362
|
+
didFromPrivateKey?: (privateKey: string) => Promise<string>;
|
|
363
|
+
}): Promise<RecoveryResult>;
|
|
364
|
+
|
|
365
|
+
/** Set up a new recovery method */
|
|
366
|
+
setupRecoveryMethod?(params: {
|
|
367
|
+
token: string;
|
|
368
|
+
providerType: AuthProviderType;
|
|
369
|
+
privateKey: string;
|
|
370
|
+
input: TRecoverySetupInput;
|
|
371
|
+
authUser?: AuthUser;
|
|
372
|
+
/** Optional: sign a DID-Auth VP JWT for server write operations */
|
|
373
|
+
signDidAuthVp?: (privateKey: string) => Promise<string>;
|
|
374
|
+
}): Promise<TRecoverySetupResult>;
|
|
375
|
+
|
|
376
|
+
/** Get configured recovery methods for the authenticated user */
|
|
377
|
+
getAvailableRecoveryMethods?(token: string, providerType: AuthProviderType): Promise<RecoveryMethodInfo[]>;
|
|
378
|
+
|
|
379
|
+
// --- Contact method management ---
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Verify email ownership and upgrade the user's contact method on the
|
|
383
|
+
* server (e.g., phone → email). The server verifies the OTP code, links
|
|
384
|
+
* the email to the auth account (passwordless), and atomically updates
|
|
385
|
+
* the UserKey contact method.
|
|
386
|
+
*
|
|
387
|
+
* Strategies that don't manage server-side contact methods can omit this.
|
|
388
|
+
*
|
|
389
|
+
* @param token - Auth token for the current session
|
|
390
|
+
* @param providerType - Auth provider type
|
|
391
|
+
* @param previousPhone - The phone number being replaced
|
|
392
|
+
* @param email - The new email address (already OTP-verified client-side)
|
|
393
|
+
* @param code - The 6-digit verification code
|
|
394
|
+
*/
|
|
395
|
+
upgradeContactMethod?(
|
|
396
|
+
token: string,
|
|
397
|
+
providerType: AuthProviderType,
|
|
398
|
+
previousPhone: string,
|
|
399
|
+
email: string,
|
|
400
|
+
code: string
|
|
401
|
+
): Promise<{ customToken?: string } | void>;
|
|
402
|
+
|
|
403
|
+
// --- Email backup ---
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Send a backup share to the user's email for fail-safe recovery.
|
|
407
|
+
* Called by the coordinator after key setup or migration.
|
|
408
|
+
* Implementation should be fire-and-forget (non-fatal on failure).
|
|
409
|
+
*
|
|
410
|
+
* @param token - Auth token for server communication
|
|
411
|
+
* @param providerType - Auth provider type
|
|
412
|
+
* @param privateKey - The private key to derive the email share from
|
|
413
|
+
* @param email - Destination email address
|
|
414
|
+
*/
|
|
415
|
+
sendEmailBackupShare?(
|
|
416
|
+
token: string,
|
|
417
|
+
providerType: AuthProviderType,
|
|
418
|
+
privateKey: string,
|
|
419
|
+
email: string
|
|
420
|
+
): Promise<void>;
|
|
421
|
+
|
|
422
|
+
// --- Share versioning ---
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Get the share version associated with the local device share.
|
|
426
|
+
* Used to request the matching auth share from the server and to
|
|
427
|
+
* include in QR cross-device transfers.
|
|
428
|
+
*
|
|
429
|
+
* Returns null for legacy shares with no stored version.
|
|
430
|
+
*/
|
|
431
|
+
getLocalShareVersion?(): Promise<number | null>;
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Store the share version for the local device share.
|
|
435
|
+
* Called after receiving a device share + version via QR transfer.
|
|
436
|
+
*/
|
|
437
|
+
storeLocalShareVersion?(version: number): Promise<void>;
|
|
438
|
+
|
|
439
|
+
// --- User scoping ---
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Inform the strategy which user is active so it can scope local storage
|
|
443
|
+
* (e.g., device shares) per-user. Called by the coordinator after
|
|
444
|
+
* authentication, before any local-key operations.
|
|
445
|
+
*
|
|
446
|
+
* Strategies that don't need per-user scoping can omit this method.
|
|
447
|
+
*
|
|
448
|
+
* @param userId - Stable, unique identifier for the authenticated user
|
|
449
|
+
* (e.g., Firebase UID). Must NOT change across sessions.
|
|
450
|
+
*/
|
|
451
|
+
setActiveUser?(userId: string): void;
|
|
452
|
+
|
|
453
|
+
// --- Cleanup ---
|
|
454
|
+
|
|
455
|
+
/** Return storage keys (e.g., IndexedDB database names) that should be preserved during logout */
|
|
456
|
+
getPreservedStorageKeys(): string[];
|
|
457
|
+
|
|
458
|
+
/** Strategy-specific cleanup beyond clearLocalKeys (optional) */
|
|
459
|
+
cleanup?(): Promise<void>;
|
|
460
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
|
|
3
|
+
export const BITSTRING_STATUS_PURPOSES = ['revocation', 'suspension'] as const;
|
|
4
|
+
export const DEFAULT_BITSTRING_STATUS_LIST_SIZE = 131_072;
|
|
5
|
+
|
|
6
|
+
export const BitstringStatusPurposeValidator = z.enum(BITSTRING_STATUS_PURPOSES);
|
|
7
|
+
export type BitstringStatusPurpose = z.infer<typeof BitstringStatusPurposeValidator>;
|
|
8
|
+
|
|
9
|
+
export const BitstringStatusListEntryValidator = z.object({
|
|
10
|
+
id: z.string().optional(),
|
|
11
|
+
type: z.literal('BitstringStatusListEntry'),
|
|
12
|
+
statusPurpose: BitstringStatusPurposeValidator,
|
|
13
|
+
statusListIndex: z.string(),
|
|
14
|
+
statusListCredential: z.string(),
|
|
15
|
+
});
|
|
16
|
+
export type BitstringStatusListEntry = z.infer<typeof BitstringStatusListEntryValidator>;
|
|
17
|
+
|
|
18
|
+
export const AllocatedBitstringStatusListEntryValidator = BitstringStatusListEntryValidator.extend({
|
|
19
|
+
id: z.string(),
|
|
20
|
+
});
|
|
21
|
+
export type AllocatedBitstringStatusListEntry = z.infer<
|
|
22
|
+
typeof AllocatedBitstringStatusListEntryValidator
|
|
23
|
+
>;
|
|
24
|
+
|
|
25
|
+
export const BitstringStatusListCredentialSubjectValidator = z.object({
|
|
26
|
+
id: z.string().optional(),
|
|
27
|
+
type: z.literal('BitstringStatusList'),
|
|
28
|
+
statusPurpose: BitstringStatusPurposeValidator,
|
|
29
|
+
encodedList: z.string(),
|
|
30
|
+
});
|
|
31
|
+
export type BitstringStatusListCredentialSubject = z.infer<
|
|
32
|
+
typeof BitstringStatusListCredentialSubjectValidator
|
|
33
|
+
>;
|
|
34
|
+
|
|
35
|
+
export const AllocateCredentialStatusInputValidator = z
|
|
36
|
+
.object({
|
|
37
|
+
statusPurposes: z.array(BitstringStatusPurposeValidator).optional(),
|
|
38
|
+
listSize: z.number().int().positive().optional(),
|
|
39
|
+
})
|
|
40
|
+
.default({});
|
|
41
|
+
export type AllocateCredentialStatusInput = z.infer<typeof AllocateCredentialStatusInputValidator>;
|
|
42
|
+
|
|
43
|
+
export type BitstringCredentialStatusPurpose = BitstringStatusPurpose;
|
|
44
|
+
export type BitstringCredentialStatusEntry = AllocatedBitstringStatusListEntry;
|