@frontmcp/auth 1.3.0 → 1.4.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/authorities/authorities.profiles.d.ts +14 -1
- package/authorities/authorities.profiles.d.ts.map +1 -1
- package/authorization/dcr-client.registry.d.ts +83 -0
- package/authorization/dcr-client.registry.d.ts.map +1 -0
- package/authorization/index.d.ts +2 -0
- package/authorization/index.d.ts.map +1 -1
- package/cimd/cimd.service.d.ts +2 -9
- package/cimd/cimd.service.d.ts.map +1 -1
- package/common/session.types.d.ts +4 -4
- package/esm/index.mjs +1821 -214
- package/esm/package.json +8 -8
- package/index.d.ts +5 -5
- package/index.d.ts.map +1 -1
- package/index.js +2030 -383
- package/jwks/jwks.service.d.ts +2 -4
- package/jwks/jwks.service.d.ts.map +1 -1
- package/options/app-auth.schema.d.ts +226 -0
- package/options/app-auth.schema.d.ts.map +1 -1
- package/options/index.d.ts +4 -4
- package/options/index.d.ts.map +1 -1
- package/options/interfaces.d.ts +580 -4
- package/options/interfaces.d.ts.map +1 -1
- package/options/orchestrated.schema.d.ts +492 -1
- package/options/orchestrated.schema.d.ts.map +1 -1
- package/options/schema.d.ts +226 -0
- package/options/schema.d.ts.map +1 -1
- package/options/shared.schemas.d.ts +237 -2
- package/options/shared.schemas.d.ts.map +1 -1
- package/package.json +8 -8
- package/session/authorization.store.d.ts +117 -47
- package/session/authorization.store.d.ts.map +1 -1
- package/session/consent.store.d.ts +86 -0
- package/session/consent.store.d.ts.map +1 -0
- package/session/credential-resume-link.d.ts +64 -0
- package/session/credential-resume-link.d.ts.map +1 -0
- package/session/credentials-accessor.d.ts +102 -0
- package/session/credentials-accessor.d.ts.map +1 -0
- package/session/credentials-accessor.impl.d.ts +46 -0
- package/session/credentials-accessor.impl.d.ts.map +1 -0
- package/session/index.d.ts +32 -2
- package/session/index.d.ts.map +1 -1
- package/session/orchestrated-token.crypto.d.ts +33 -0
- package/session/orchestrated-token.crypto.d.ts.map +1 -0
- package/session/secure-store-accessor.d.ts +77 -0
- package/session/secure-store-accessor.d.ts.map +1 -0
- package/session/secure-store-accessor.impl.d.ts +61 -0
- package/session/secure-store-accessor.impl.d.ts.map +1 -0
- package/session/secure-store-backends.d.ts +75 -0
- package/session/secure-store-backends.d.ts.map +1 -0
- package/session/secure-store.d.ts +89 -0
- package/session/secure-store.d.ts.map +1 -0
- package/session/secure-store.factory.d.ts +62 -0
- package/session/secure-store.factory.d.ts.map +1 -0
- package/session/session-credential-vault.d.ts +153 -0
- package/session/session-credential-vault.d.ts.map +1 -0
- package/session/session-credential-vault.factory.d.ts +50 -0
- package/session/session-credential-vault.factory.d.ts.map +1 -0
- package/session/storage-authorization.store.d.ts +51 -0
- package/session/storage-authorization.store.d.ts.map +1 -0
- package/session/storage-consent.store.d.ts +33 -0
- package/session/storage-consent.store.d.ts.map +1 -0
- package/session/storage-federated-auth.session.d.ts +36 -0
- package/session/storage-federated-auth.session.d.ts.map +1 -0
- package/session/storage-orchestrated-token.store.d.ts +72 -0
- package/session/storage-orchestrated-token.store.d.ts.map +1 -0
- package/session/token-storage.factory.d.ts +46 -0
- package/session/token-storage.factory.d.ts.map +1 -0
- package/ui/index.d.ts +3 -2
- package/ui/index.d.ts.map +1 -1
- package/ui/local-login.helper.d.ts +31 -0
- package/ui/local-login.helper.d.ts.map +1 -0
- package/ui/templates.d.ts +118 -2
- package/ui/templates.d.ts.map +1 -1
- package/vault/auth-providers.types.d.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frontmcp/auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "FrontMCP Auth - Authentication, session management, and credential vault",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -47,25 +47,25 @@
|
|
|
47
47
|
"node": ">=24.0.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"
|
|
50
|
+
"@frontmcp/lazy-zod": "1.4.1",
|
|
51
|
+
"@frontmcp/storage-sqlite": "1.4.1",
|
|
51
52
|
"@vercel/kv": "^3.0.0",
|
|
52
|
-
"
|
|
53
|
-
"@frontmcp/lazy-zod": "1.3.0"
|
|
53
|
+
"ioredis": "^5.0.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependenciesMeta": {
|
|
56
|
-
"
|
|
56
|
+
"@frontmcp/storage-sqlite": {
|
|
57
57
|
"optional": true
|
|
58
58
|
},
|
|
59
59
|
"@vercel/kv": {
|
|
60
60
|
"optional": true
|
|
61
61
|
},
|
|
62
|
-
"
|
|
62
|
+
"ioredis": {
|
|
63
63
|
"optional": true
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@frontmcp/
|
|
68
|
-
"@frontmcp/
|
|
67
|
+
"@frontmcp/di": "1.4.1",
|
|
68
|
+
"@frontmcp/utils": "1.4.1",
|
|
69
69
|
"jose": "^6.0.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
@@ -55,6 +55,19 @@ export interface AuthorizationCodeRecord {
|
|
|
55
55
|
federatedLoginUsed?: boolean;
|
|
56
56
|
/** Pending auth ID for token migration (federated login) */
|
|
57
57
|
pendingAuthId?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Progressive/Incremental authorization: the app IDs this code grants access
|
|
60
|
+
* to. Embedded as the `authorized_apps` claim in the minted token (which
|
|
61
|
+
* turns on app-level gating). Only set when `incrementalAuth` is enabled for
|
|
62
|
+
* the scope; absent for non-incremental setups (preserving allow-all).
|
|
63
|
+
*/
|
|
64
|
+
authorizedAppIds?: string[];
|
|
65
|
+
/**
|
|
66
|
+
* Custom claims returned by a local `authenticate` verifier (Checkpoint 3a).
|
|
67
|
+
* Embedded (namespaced) in the minted access token. Reserved claims
|
|
68
|
+
* (sub/iss/exp/…) are stripped when signed.
|
|
69
|
+
*/
|
|
70
|
+
customClaims?: Record<string, unknown>;
|
|
58
71
|
}
|
|
59
72
|
/**
|
|
60
73
|
* Consent state for tool selection
|
|
@@ -120,10 +133,22 @@ export interface PendingAuthorizationRecord {
|
|
|
120
133
|
existingSessionId?: string;
|
|
121
134
|
/** Existing authorization ID to expand */
|
|
122
135
|
existingAuthorizationId?: string;
|
|
136
|
+
/**
|
|
137
|
+
* App IDs the client already holds a grant for (its prior `authorized_apps`
|
|
138
|
+
* claim), carried forward on an incremental authorize so the minted token's
|
|
139
|
+
* grant is the UNION of these plus `targetAppId`.
|
|
140
|
+
*/
|
|
141
|
+
priorAuthorizedAppIds?: string[];
|
|
123
142
|
/** Federated login state for multi-provider auth */
|
|
124
143
|
federatedLogin?: FederatedLoginStateRecord;
|
|
125
144
|
/** Consent state for tool selection */
|
|
126
145
|
consent?: ConsentStateRecord;
|
|
146
|
+
/**
|
|
147
|
+
* Anti-CSRF token minted at SSR time for a custom `@AuthUi` page (#469).
|
|
148
|
+
* Echoed back by the client in the `csrf` field and verified on the callback /
|
|
149
|
+
* extra submit. Absent for the built-in pages (no CSRF requirement there).
|
|
150
|
+
*/
|
|
151
|
+
authUiCsrf?: string;
|
|
127
152
|
}
|
|
128
153
|
/**
|
|
129
154
|
* Refresh token record
|
|
@@ -178,7 +203,87 @@ export declare const authorizationCodeRecordSchema: import("@frontmcp/lazy-zod")
|
|
|
178
203
|
consentEnabled: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
179
204
|
federatedLoginUsed: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodBoolean>;
|
|
180
205
|
pendingAuthId: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodString>;
|
|
206
|
+
authorizedAppIds: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodArray<import("@frontmcp/lazy-zod").ZodString>>;
|
|
207
|
+
customClaims: import("@frontmcp/lazy-zod").ZodOptional<import("@frontmcp/lazy-zod").ZodRecord<import("@frontmcp/lazy-zod").ZodString, import("@frontmcp/lazy-zod").ZodUnknown>>;
|
|
181
208
|
}, import("zod/v4/core").$strip>;
|
|
209
|
+
/**
|
|
210
|
+
* Parameters for building an authorization code record.
|
|
211
|
+
*/
|
|
212
|
+
export interface CreateCodeRecordParams {
|
|
213
|
+
clientId: string;
|
|
214
|
+
redirectUri: string;
|
|
215
|
+
scopes: string[];
|
|
216
|
+
pkce: PkceChallenge;
|
|
217
|
+
userSub: string;
|
|
218
|
+
userEmail?: string;
|
|
219
|
+
userName?: string;
|
|
220
|
+
state?: string;
|
|
221
|
+
resource?: string;
|
|
222
|
+
selectedToolIds?: string[];
|
|
223
|
+
selectedProviderIds?: string[];
|
|
224
|
+
skippedProviderIds?: string[];
|
|
225
|
+
consentEnabled?: boolean;
|
|
226
|
+
federatedLoginUsed?: boolean;
|
|
227
|
+
pendingAuthId?: string;
|
|
228
|
+
authorizedAppIds?: string[];
|
|
229
|
+
customClaims?: Record<string, unknown>;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Parameters for building a pending authorization record.
|
|
233
|
+
*/
|
|
234
|
+
export interface CreatePendingRecordParams {
|
|
235
|
+
clientId: string;
|
|
236
|
+
redirectUri: string;
|
|
237
|
+
scopes: string[];
|
|
238
|
+
pkce: PkceChallenge;
|
|
239
|
+
state?: string;
|
|
240
|
+
resource?: string;
|
|
241
|
+
isIncremental?: boolean;
|
|
242
|
+
targetAppId?: string;
|
|
243
|
+
targetToolId?: string;
|
|
244
|
+
existingSessionId?: string;
|
|
245
|
+
existingAuthorizationId?: string;
|
|
246
|
+
priorAuthorizedAppIds?: string[];
|
|
247
|
+
federatedLogin?: FederatedLoginStateRecord;
|
|
248
|
+
consent?: ConsentStateRecord;
|
|
249
|
+
authUiCsrf?: string;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Parameters for building a refresh token record.
|
|
253
|
+
*/
|
|
254
|
+
export interface CreateRefreshTokenRecordParams {
|
|
255
|
+
clientId: string;
|
|
256
|
+
userSub: string;
|
|
257
|
+
scopes: string[];
|
|
258
|
+
resource?: string;
|
|
259
|
+
}
|
|
260
|
+
/** Default TTL for authorization codes (60 seconds). */
|
|
261
|
+
export declare const AUTH_CODE_TTL_MS: number;
|
|
262
|
+
/** Default TTL for pending authorizations (10 minutes). */
|
|
263
|
+
export declare const PENDING_AUTH_TTL_MS: number;
|
|
264
|
+
/** Default TTL for refresh tokens (30 days). */
|
|
265
|
+
export declare const REFRESH_TOKEN_TTL_MS: number;
|
|
266
|
+
/**
|
|
267
|
+
* Generate a cryptographically secure authorization code.
|
|
268
|
+
*/
|
|
269
|
+
export declare function generateAuthorizationCode(): string;
|
|
270
|
+
/**
|
|
271
|
+
* Generate a refresh token string.
|
|
272
|
+
*/
|
|
273
|
+
export declare function generateRefreshTokenValue(): string;
|
|
274
|
+
/**
|
|
275
|
+
* Build an authorization code record with defaults. Pure (no storage I/O), so
|
|
276
|
+
* it is shared by every {@link AuthorizationStore} implementation.
|
|
277
|
+
*/
|
|
278
|
+
export declare function buildCodeRecord(params: CreateCodeRecordParams): AuthorizationCodeRecord;
|
|
279
|
+
/**
|
|
280
|
+
* Build a pending authorization record with defaults.
|
|
281
|
+
*/
|
|
282
|
+
export declare function buildPendingRecord(params: CreatePendingRecordParams): PendingAuthorizationRecord;
|
|
283
|
+
/**
|
|
284
|
+
* Build a refresh token record with defaults.
|
|
285
|
+
*/
|
|
286
|
+
export declare function buildRefreshTokenRecord(params: CreateRefreshTokenRecordParams): RefreshTokenRecord;
|
|
182
287
|
/**
|
|
183
288
|
* Authorization Store Interface
|
|
184
289
|
*/
|
|
@@ -196,6 +301,9 @@ export interface AuthorizationStore {
|
|
|
196
301
|
rotateRefreshToken(oldToken: string, newRecord: RefreshTokenRecord): Promise<void>;
|
|
197
302
|
generateCode(): string;
|
|
198
303
|
generateRefreshToken(): string;
|
|
304
|
+
createCodeRecord(params: CreateCodeRecordParams): AuthorizationCodeRecord;
|
|
305
|
+
createPendingRecord(params: CreatePendingRecordParams): PendingAuthorizationRecord;
|
|
306
|
+
createRefreshTokenRecord(params: CreateRefreshTokenRecordParams): RefreshTokenRecord;
|
|
199
307
|
cleanup(): Promise<void>;
|
|
200
308
|
}
|
|
201
309
|
/**
|
|
@@ -213,12 +321,6 @@ export declare class InMemoryAuthorizationStore implements AuthorizationStore {
|
|
|
213
321
|
private codes;
|
|
214
322
|
private pending;
|
|
215
323
|
private refreshTokens;
|
|
216
|
-
/** Default TTL for authorization codes (60 seconds) */
|
|
217
|
-
private readonly codeTtlMs;
|
|
218
|
-
/** Default TTL for pending authorizations (10 minutes) */
|
|
219
|
-
private readonly pendingTtlMs;
|
|
220
|
-
/** Default TTL for refresh tokens (30 days) */
|
|
221
|
-
private readonly refreshTtlMs;
|
|
222
324
|
generateCode(): string;
|
|
223
325
|
generateRefreshToken(): string;
|
|
224
326
|
storeAuthorizationCode(record: AuthorizationCodeRecord): Promise<void>;
|
|
@@ -234,52 +336,17 @@ export declare class InMemoryAuthorizationStore implements AuthorizationStore {
|
|
|
234
336
|
rotateRefreshToken(oldToken: string, newRecord: RefreshTokenRecord): Promise<void>;
|
|
235
337
|
cleanup(): Promise<void>;
|
|
236
338
|
/**
|
|
237
|
-
* Create an authorization code record with defaults
|
|
339
|
+
* Create an authorization code record with defaults.
|
|
238
340
|
*/
|
|
239
|
-
createCodeRecord(params:
|
|
240
|
-
clientId: string;
|
|
241
|
-
redirectUri: string;
|
|
242
|
-
scopes: string[];
|
|
243
|
-
pkce: PkceChallenge;
|
|
244
|
-
userSub: string;
|
|
245
|
-
userEmail?: string;
|
|
246
|
-
userName?: string;
|
|
247
|
-
state?: string;
|
|
248
|
-
resource?: string;
|
|
249
|
-
selectedToolIds?: string[];
|
|
250
|
-
selectedProviderIds?: string[];
|
|
251
|
-
skippedProviderIds?: string[];
|
|
252
|
-
consentEnabled?: boolean;
|
|
253
|
-
federatedLoginUsed?: boolean;
|
|
254
|
-
pendingAuthId?: string;
|
|
255
|
-
}): AuthorizationCodeRecord;
|
|
341
|
+
createCodeRecord(params: CreateCodeRecordParams): AuthorizationCodeRecord;
|
|
256
342
|
/**
|
|
257
|
-
* Create a pending authorization record with defaults
|
|
343
|
+
* Create a pending authorization record with defaults.
|
|
258
344
|
*/
|
|
259
|
-
createPendingRecord(params:
|
|
260
|
-
clientId: string;
|
|
261
|
-
redirectUri: string;
|
|
262
|
-
scopes: string[];
|
|
263
|
-
pkce: PkceChallenge;
|
|
264
|
-
state?: string;
|
|
265
|
-
resource?: string;
|
|
266
|
-
isIncremental?: boolean;
|
|
267
|
-
targetAppId?: string;
|
|
268
|
-
targetToolId?: string;
|
|
269
|
-
existingSessionId?: string;
|
|
270
|
-
existingAuthorizationId?: string;
|
|
271
|
-
federatedLogin?: FederatedLoginStateRecord;
|
|
272
|
-
consent?: ConsentStateRecord;
|
|
273
|
-
}): PendingAuthorizationRecord;
|
|
345
|
+
createPendingRecord(params: CreatePendingRecordParams): PendingAuthorizationRecord;
|
|
274
346
|
/**
|
|
275
|
-
* Create a refresh token record with defaults
|
|
347
|
+
* Create a refresh token record with defaults.
|
|
276
348
|
*/
|
|
277
|
-
createRefreshTokenRecord(params:
|
|
278
|
-
clientId: string;
|
|
279
|
-
userSub: string;
|
|
280
|
-
scopes: string[];
|
|
281
|
-
resource?: string;
|
|
282
|
-
}): RefreshTokenRecord;
|
|
349
|
+
createRefreshTokenRecord(params: CreateRefreshTokenRecordParams): RefreshTokenRecord;
|
|
283
350
|
}
|
|
284
351
|
/**
|
|
285
352
|
* Redis Authorization Store (placeholder)
|
|
@@ -294,6 +361,9 @@ export declare class RedisAuthorizationStore implements AuthorizationStore {
|
|
|
294
361
|
private key;
|
|
295
362
|
generateCode(): string;
|
|
296
363
|
generateRefreshToken(): string;
|
|
364
|
+
createCodeRecord(params: CreateCodeRecordParams): AuthorizationCodeRecord;
|
|
365
|
+
createPendingRecord(params: CreatePendingRecordParams): PendingAuthorizationRecord;
|
|
366
|
+
createRefreshTokenRecord(params: CreateRefreshTokenRecordParams): RefreshTokenRecord;
|
|
297
367
|
storeAuthorizationCode(record: AuthorizationCodeRecord): Promise<void>;
|
|
298
368
|
getAuthorizationCode(code: string): Promise<AuthorizationCodeRecord | null>;
|
|
299
369
|
markCodeUsed(code: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization.store.d.ts","sourceRoot":"","sources":["../../src/session/authorization.store.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAKH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,sCAAsC;IACtC,IAAI,EAAE,aAAa,CAAC;IACpB,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,IAAI,EAAE,OAAO,CAAC;IACd,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,0CAA0C;IAC1C,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"authorization.store.d.ts","sourceRoot":"","sources":["../../src/session/authorization.store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Remembered Consent Store
|
|
3
|
+
*
|
|
4
|
+
* Persists a user's per-client tool-consent selection so that consent mode
|
|
5
|
+
* (`auth.consent.rememberConsent`) can reuse it on a subsequent login instead
|
|
6
|
+
* of re-prompting every time.
|
|
7
|
+
*
|
|
8
|
+
* Semantics (see {@link RememberedConsentRecord}):
|
|
9
|
+
* - Keyed by `consent:{userSub}:{clientId}` — one record per (user, client).
|
|
10
|
+
* - `selectedToolIds` is what the user last consented to (NOT including
|
|
11
|
+
* `excludedTools`, which are always available regardless of consent).
|
|
12
|
+
* - `seenToolIds` is the full set of tool ids that were OFFERED the last time
|
|
13
|
+
* consent was collected. On a later login the consent screen is SKIPPED only
|
|
14
|
+
* when every currently-available tool id is already in `seenToolIds` (i.e. no
|
|
15
|
+
* NEW tool appeared). If a new tool appeared, the screen is re-rendered
|
|
16
|
+
* pre-filled with `selectedToolIds` so the user decides about the new one —
|
|
17
|
+
* a newly-added tool is NEVER silently granted.
|
|
18
|
+
*
|
|
19
|
+
* No PII is stored: only the opaque subject identifier, the client id, and tool
|
|
20
|
+
* ids. The minted token's `consent.selectedTools` claim still drives call-time
|
|
21
|
+
* enforcement; this store only changes which selection is collected/reused at
|
|
22
|
+
* authorize time.
|
|
23
|
+
*
|
|
24
|
+
* Parallels {@link FederatedAuthSessionStore}: an {@link InMemoryConsentStore}
|
|
25
|
+
* for the default (memory) path and a `StorageConsentStore` (adapter-backed) for
|
|
26
|
+
* Redis/SQLite, swapped in when a persistent token-storage backend is
|
|
27
|
+
* configured.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* A remembered per-(user, client) consent selection.
|
|
31
|
+
*/
|
|
32
|
+
export interface RememberedConsentRecord {
|
|
33
|
+
/** Opaque subject identifier of the consenting user. */
|
|
34
|
+
userSub: string;
|
|
35
|
+
/** OAuth client id the consent was granted to. */
|
|
36
|
+
clientId: string;
|
|
37
|
+
/**
|
|
38
|
+
* Tool ids the user last consented to. Does NOT include `excludedTools`
|
|
39
|
+
* (those are always available and are merged in at mint time).
|
|
40
|
+
*/
|
|
41
|
+
selectedToolIds: string[];
|
|
42
|
+
/**
|
|
43
|
+
* Full set of tool ids that were OFFERED when consent was last collected.
|
|
44
|
+
* Used to detect newly-added tools (available ids not in this set) so the
|
|
45
|
+
* screen is re-shown rather than silently granting a new tool.
|
|
46
|
+
*/
|
|
47
|
+
seenToolIds: string[];
|
|
48
|
+
/** Last-updated timestamp (epoch ms). */
|
|
49
|
+
updatedAt: number;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Store interface for remembered consent selections.
|
|
53
|
+
*/
|
|
54
|
+
export interface ConsentStore {
|
|
55
|
+
/** Get the remembered consent record for a (user, client), or null. */
|
|
56
|
+
get(userSub: string, clientId: string): Promise<RememberedConsentRecord | null>;
|
|
57
|
+
/** Persist (insert or overwrite) a remembered consent record. */
|
|
58
|
+
set(record: RememberedConsentRecord): Promise<void>;
|
|
59
|
+
/** Delete the remembered consent record for a (user, client). */
|
|
60
|
+
delete(userSub: string, clientId: string): Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build the storage key for a remembered consent record.
|
|
64
|
+
*
|
|
65
|
+
* Shared by both store implementations so the in-memory and adapter-backed
|
|
66
|
+
* variants can never drift on key shape.
|
|
67
|
+
*/
|
|
68
|
+
export declare function consentRecordKey(userSub: string, clientId: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* In-Memory Remembered Consent Store.
|
|
71
|
+
*
|
|
72
|
+
* Default (memory) implementation; the remembered selection is lost on restart,
|
|
73
|
+
* matching the rest of the in-memory auth stores. Use a persistent backend
|
|
74
|
+
* (Redis/SQLite via `tokenStorage`) to survive restarts.
|
|
75
|
+
*/
|
|
76
|
+
export declare class InMemoryConsentStore implements ConsentStore {
|
|
77
|
+
private readonly records;
|
|
78
|
+
get(userSub: string, clientId: string): Promise<RememberedConsentRecord | null>;
|
|
79
|
+
set(record: RememberedConsentRecord): Promise<void>;
|
|
80
|
+
delete(userSub: string, clientId: string): Promise<void>;
|
|
81
|
+
/** Number of remembered records (for testing/monitoring). */
|
|
82
|
+
get size(): number;
|
|
83
|
+
/** Clear all remembered records (for testing). */
|
|
84
|
+
clear(): void;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=consent.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consent.store.d.ts","sourceRoot":"","sources":["../../src/session/consent.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;OAIG;IACH,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,yCAAyC;IACzC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,uEAAuE;IACvE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;IAEhF,iEAAiE;IACjE,GAAG,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEpD,iEAAiE;IACjE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1E;AAED;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8C;IAEhE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAO/E,GAAG,CAAC,MAAM,EAAE,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUnD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D,6DAA6D;IAC7D,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,kDAAkD;IAClD,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential resume-link signing (Checkpoint 3b).
|
|
3
|
+
*
|
|
4
|
+
* When a tool asks for a credential that is not connected
|
|
5
|
+
* (`this.credentials.requireConnect({ key })`), the framework returns a
|
|
6
|
+
* structured "credential not connected" result carrying a FRAMEWORK-SIGNED
|
|
7
|
+
* resume URL. The URL embeds an HMAC-SHA256 token over `{ sub, key, context?,
|
|
8
|
+
* exp }`, signed with the server secret. The mid-session add-credential handler
|
|
9
|
+
* verifies the token (constant-time, via {@link verifyData}) and refuses expired
|
|
10
|
+
* or tampered tokens, so a browser cannot be redirected into adding a credential
|
|
11
|
+
* for an arbitrary subject/key.
|
|
12
|
+
*
|
|
13
|
+
* Reuses `@frontmcp/utils` HMAC signing (`signData`/`verifyData`) — no new
|
|
14
|
+
* crypto. The signed payload contains NO secret material; it only authorizes
|
|
15
|
+
* *which* `(sub, key)` slot the resume page may write to.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* The payload signed into a credential resume token.
|
|
19
|
+
*/
|
|
20
|
+
export interface CredentialResumePayload {
|
|
21
|
+
/** Subject the credential will be stored under (the request's authenticated sub). */
|
|
22
|
+
sub: string;
|
|
23
|
+
/** Credential key being connected (e.g. provider id). */
|
|
24
|
+
key: string;
|
|
25
|
+
/** Optional opaque context forwarded back to `authenticate()` as `resume.context`. */
|
|
26
|
+
context?: string;
|
|
27
|
+
/** Absolute expiry, epoch milliseconds. */
|
|
28
|
+
exp: number;
|
|
29
|
+
}
|
|
30
|
+
/** Default resume-token TTL: 10 minutes (short-lived). */
|
|
31
|
+
export declare const DEFAULT_RESUME_TTL_MS = 600000;
|
|
32
|
+
/**
|
|
33
|
+
* Sign a credential resume token (HMAC-SHA256 over the payload).
|
|
34
|
+
*
|
|
35
|
+
* @param input - subject, key, optional context, and TTL.
|
|
36
|
+
* @param secret - the server signing secret (HMAC key).
|
|
37
|
+
* @returns a compact base64url token string suitable for a URL query param.
|
|
38
|
+
*/
|
|
39
|
+
export declare function signCredentialResumeToken(input: {
|
|
40
|
+
sub: string;
|
|
41
|
+
key: string;
|
|
42
|
+
context?: string;
|
|
43
|
+
ttlMs?: number;
|
|
44
|
+
}, secret: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* Verify a credential resume token: constant-time signature check (via
|
|
47
|
+
* {@link verifyData}) AND expiry enforcement.
|
|
48
|
+
*
|
|
49
|
+
* @param token - the base64url token from {@link signCredentialResumeToken}.
|
|
50
|
+
* @param secret - the server signing secret (must match the signing secret).
|
|
51
|
+
* @param now - current time (epoch ms), injectable for tests. @default Date.now()
|
|
52
|
+
* @returns the verified payload, or null when the signature is invalid,
|
|
53
|
+
* the token is malformed, or it has expired.
|
|
54
|
+
*/
|
|
55
|
+
export declare function verifyCredentialResumeToken(token: string, secret: string, now?: number): CredentialResumePayload | null;
|
|
56
|
+
/**
|
|
57
|
+
* Build the absolute resume URL a "credential not connected" result hands back.
|
|
58
|
+
*
|
|
59
|
+
* @param basePath - the auth scope's full base path (e.g. `https://host/mcp`).
|
|
60
|
+
* @param token - a token from {@link signCredentialResumeToken}.
|
|
61
|
+
* @returns `${basePath}/oauth/connect?token=...`
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildCredentialResumeUrl(basePath: string, token: string): string;
|
|
64
|
+
//# sourceMappingURL=credential-resume-link.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credential-resume-link.d.ts","sourceRoot":"","sources":["../../src/session/credential-resume-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,qFAAqF;IACrF,GAAG,EAAE,MAAM,CAAC;IACZ,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,0DAA0D;AAC1D,eAAO,MAAM,qBAAqB,SAAU,CAAC;AAE7C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACrE,MAAM,EAAE,MAAM,GACb,MAAM,CAWR;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,MAAmB,GACvB,uBAAuB,GAAG,IAAI,CAuBhC;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGhF"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredentialsAccessor — the `this.credentials` ToolContext API (Checkpoint 3b).
|
|
3
|
+
*
|
|
4
|
+
* Runtime accessor tools use to read per-session credentials persisted by a
|
|
5
|
+
* local `authenticate()` verifier, and to ask the agent to connect a missing
|
|
6
|
+
* credential mid-session via a framework-signed resume URL.
|
|
7
|
+
*
|
|
8
|
+
* Resolution of the request's authenticated `sub` and the server signing secret
|
|
9
|
+
* is handled by the implementation ({@link CredentialsAccessorImpl}); tools only
|
|
10
|
+
* see the small API below.
|
|
11
|
+
*/
|
|
12
|
+
import { type Token } from '@frontmcp/di';
|
|
13
|
+
import { type StoredCredential } from './session-credential-vault';
|
|
14
|
+
/**
|
|
15
|
+
* A credential as returned to a tool: the secret plus optional non-secret
|
|
16
|
+
* metadata. Identical in shape to {@link StoredCredential}.
|
|
17
|
+
*/
|
|
18
|
+
export type CredentialValue = StoredCredential;
|
|
19
|
+
/**
|
|
20
|
+
* Structured "credential not connected" result returned by
|
|
21
|
+
* {@link CredentialsAccessor.requireConnect} when the requested credential is
|
|
22
|
+
* absent. Carries a framework-signed resume URL the agent/client can open to
|
|
23
|
+
* have the user connect the credential mid-session.
|
|
24
|
+
*/
|
|
25
|
+
export interface CredentialNotConnected {
|
|
26
|
+
/** Discriminator. Always `false` — the credential is not available. */
|
|
27
|
+
connected: false;
|
|
28
|
+
/** The credential key that is missing. */
|
|
29
|
+
key: string;
|
|
30
|
+
/** Framework-signed, short-lived URL that opens the add-credential page. */
|
|
31
|
+
resumeUrl: string;
|
|
32
|
+
/** Human-readable hint for the agent/user. */
|
|
33
|
+
message: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Successful resolution returned by {@link CredentialsAccessor.requireConnect}
|
|
37
|
+
* when the credential IS present.
|
|
38
|
+
*/
|
|
39
|
+
export interface CredentialConnected {
|
|
40
|
+
/** Discriminator. Always `true` — the credential is available. */
|
|
41
|
+
connected: true;
|
|
42
|
+
/** The credential key. */
|
|
43
|
+
key: string;
|
|
44
|
+
/** The resolved credential value. */
|
|
45
|
+
credential: CredentialValue;
|
|
46
|
+
}
|
|
47
|
+
/** Discriminated union returned by {@link CredentialsAccessor.requireConnect}. */
|
|
48
|
+
export type RequireConnectResult = CredentialConnected | CredentialNotConnected;
|
|
49
|
+
/**
|
|
50
|
+
* Options for {@link CredentialsAccessor.requireConnect}.
|
|
51
|
+
*/
|
|
52
|
+
export interface RequireConnectOptions {
|
|
53
|
+
/** Credential key to require (e.g. provider id). */
|
|
54
|
+
key: string;
|
|
55
|
+
/**
|
|
56
|
+
* Optional opaque context forwarded to `authenticate()` as `resume.context`
|
|
57
|
+
* when the user connects the credential (e.g. which resource triggered it).
|
|
58
|
+
*/
|
|
59
|
+
context?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Runtime accessor for per-session credentials, available on tool contexts as
|
|
63
|
+
* `this.credentials`:
|
|
64
|
+
*
|
|
65
|
+
* ```typescript
|
|
66
|
+
* @Tool({ name: 'call_api' })
|
|
67
|
+
* class CallApiTool extends ToolContext {
|
|
68
|
+
* async execute(input: Input): Promise<Output> {
|
|
69
|
+
* const cred = await this.credentials.get('acme');
|
|
70
|
+
* if (!cred) {
|
|
71
|
+
* const res = await this.credentials.requireConnect({ key: 'acme' });
|
|
72
|
+
* if (!res.connected) return { connectUrl: res.resumeUrl };
|
|
73
|
+
* }
|
|
74
|
+
* // use cred.secret …
|
|
75
|
+
* }
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export interface CredentialsAccessor {
|
|
80
|
+
/**
|
|
81
|
+
* Get a credential by key for the current request's subject. Returns
|
|
82
|
+
* undefined when the subject is anonymous, has no live vault, or has no such
|
|
83
|
+
* credential (or when decryption fails after a vault rotation).
|
|
84
|
+
*/
|
|
85
|
+
get(key: string): Promise<CredentialValue | undefined>;
|
|
86
|
+
/**
|
|
87
|
+
* List the credential keys available to the current request's subject.
|
|
88
|
+
* Empty when anonymous or when there is no live vault.
|
|
89
|
+
*/
|
|
90
|
+
list(): Promise<string[]>;
|
|
91
|
+
/**
|
|
92
|
+
* Resolve a credential, returning a framework-signed resume URL when it is not
|
|
93
|
+
* connected so the caller can prompt the user to connect it mid-session.
|
|
94
|
+
*/
|
|
95
|
+
requireConnect(options: RequireConnectOptions): Promise<RequireConnectResult>;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* DI token for {@link CredentialsAccessor}. Resolved by the `this.credentials`
|
|
99
|
+
* context extension.
|
|
100
|
+
*/
|
|
101
|
+
export declare const CREDENTIALS_ACCESSOR: Token<CredentialsAccessor>;
|
|
102
|
+
//# sourceMappingURL=credentials-accessor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-accessor.d.ts","sourceRoot":"","sources":["../../src/session/credentials-accessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,gBAAgB,CAAC;AAE/C;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,uEAAuE;IACvE,SAAS,EAAE,KAAK,CAAC;IACjB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,kEAAkE;IAClE,SAAS,EAAE,IAAI,CAAC;IAChB,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,UAAU,EAAE,eAAe,CAAC;CAC7B;AAED,kFAAkF;AAClF,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,sBAAsB,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IAEvD;;;OAGG;IACH,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1B;;;OAGG;IACH,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CAC/E;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAkD,KAAK,CAAC,mBAAmB,CAAC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CredentialsAccessorImpl — request-scoped implementation of the
|
|
3
|
+
* `this.credentials` accessor (Checkpoint 3b).
|
|
4
|
+
*
|
|
5
|
+
* Binds a {@link SessionCredentialVault} to the current request's authenticated
|
|
6
|
+
* subject and signing secret. The subject is resolved lazily via the injected
|
|
7
|
+
* `resolveSub` callback (so an anonymous/unauthenticated request yields no
|
|
8
|
+
* credentials), and `requireConnect` mints a framework-signed resume URL using
|
|
9
|
+
* {@link signCredentialResumeToken}.
|
|
10
|
+
*/
|
|
11
|
+
import { type AuthLogger } from '../common/auth-logger.interface';
|
|
12
|
+
import { type CredentialsAccessor, type CredentialValue, type RequireConnectOptions, type RequireConnectResult } from './credentials-accessor';
|
|
13
|
+
import { type SessionCredentialVault } from './session-credential-vault';
|
|
14
|
+
/**
|
|
15
|
+
* Dependencies for {@link CredentialsAccessorImpl}.
|
|
16
|
+
*/
|
|
17
|
+
export interface CredentialsAccessorDeps {
|
|
18
|
+
/** The per-session credential vault. */
|
|
19
|
+
vault: SessionCredentialVault;
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the current request's authenticated subject. Returns undefined for
|
|
22
|
+
* anonymous/unauthenticated requests (no credentials are exposed then).
|
|
23
|
+
*/
|
|
24
|
+
resolveSub: () => string | undefined;
|
|
25
|
+
/** Server HMAC signing secret used for resume tokens. */
|
|
26
|
+
signingSecret: string;
|
|
27
|
+
/** Auth scope base path used to build the resume URL (e.g. `https://host/mcp`). */
|
|
28
|
+
basePath: string;
|
|
29
|
+
/** Resume-token TTL in ms (short-lived). */
|
|
30
|
+
resumeTtlMs?: number;
|
|
31
|
+
/** Scoped logger. */
|
|
32
|
+
logger?: AuthLogger;
|
|
33
|
+
}
|
|
34
|
+
export declare class CredentialsAccessorImpl implements CredentialsAccessor {
|
|
35
|
+
private readonly vault;
|
|
36
|
+
private readonly resolveSub;
|
|
37
|
+
private readonly signingSecret;
|
|
38
|
+
private readonly basePath;
|
|
39
|
+
private readonly resumeTtlMs?;
|
|
40
|
+
private readonly logger;
|
|
41
|
+
constructor(deps: CredentialsAccessorDeps);
|
|
42
|
+
get(key: string): Promise<CredentialValue | undefined>;
|
|
43
|
+
list(): Promise<string[]>;
|
|
44
|
+
requireConnect(options: RequireConnectOptions): Promise<RequireConnectResult>;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=credentials-accessor.impl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-accessor.impl.d.ts","sourceRoot":"","sources":["../../src/session/credentials-accessor.impl.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAElF,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,KAAK,EAAE,sBAAsB,CAAC;IAC9B;;;OAGG;IACH,UAAU,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACrC,yDAAyD;IACzD,aAAa,EAAE,MAAM,CAAC;IACtB,mFAAmF;IACnF,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB;IACrB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,qBAAa,uBAAwB,YAAW,mBAAmB;IACjE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2B;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAExB,IAAI,EAAE,uBAAuB;IASnC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAMtD,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAMzB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CA2BpF"}
|