@atlasauth/backend 0.23.0 → 0.25.0
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/CHANGELOG.md +14 -0
- package/dist/auth0-session.d.ts +23 -0
- package/dist/auth0-session.js +80 -0
- package/dist/auth0-session.js.map +1 -0
- package/dist/better-auth.d.ts +4 -8
- package/dist/better-auth.js +42 -150
- package/dist/better-auth.js.map +1 -1
- package/dist/client/abac.d.ts +132 -0
- package/dist/client/abac.js +48 -0
- package/dist/client/abac.js.map +1 -0
- package/dist/client/access-policies.d.ts +100 -0
- package/dist/client/access-policies.js +29 -0
- package/dist/client/access-policies.js.map +1 -0
- package/dist/client/action-gallery.d.ts +1 -1
- package/dist/client/action-gallery.js.map +1 -1
- package/dist/client/actions.d.ts +129 -6
- package/dist/client/actions.js +4 -0
- package/dist/client/actions.js.map +1 -1
- package/dist/client/analytics-reports.d.ts +215 -0
- package/dist/client/analytics-reports.js +56 -0
- package/dist/client/analytics-reports.js.map +1 -0
- package/dist/client/app-catalog.d.ts +74 -0
- package/dist/client/app-catalog.js +30 -0
- package/dist/client/app-catalog.js.map +1 -0
- package/dist/client/attack-protection.d.ts +10 -0
- package/dist/client/attack-protection.js +8 -0
- package/dist/client/attack-protection.js.map +1 -1
- package/dist/client/audit-events.d.ts +71 -0
- package/dist/client/audit-events.js +28 -0
- package/dist/client/audit-events.js.map +1 -1
- package/dist/client/credentials.d.ts +8 -0
- package/dist/client/credentials.js.map +1 -1
- package/dist/client/delegated-ui-proxy.d.ts +25 -0
- package/dist/client/delegated-ui-proxy.js +46 -0
- package/dist/client/delegated-ui-proxy.js.map +1 -0
- package/dist/client/devices.d.ts +44 -0
- package/dist/client/devices.js +26 -0
- package/dist/client/devices.js.map +1 -0
- package/dist/client/email-templates.d.ts +1 -1
- package/dist/client/email-templates.js.map +1 -1
- package/dist/client/flags.d.ts +101 -0
- package/dist/client/flags.js +104 -0
- package/dist/client/flags.js.map +1 -0
- package/dist/client/groups.d.ts +146 -0
- package/dist/client/groups.js +67 -0
- package/dist/client/groups.js.map +1 -0
- package/dist/client/identity-verification.d.ts +62 -0
- package/dist/client/identity-verification.js +39 -0
- package/dist/client/identity-verification.js.map +1 -0
- package/dist/client/index.d.ts +997 -2
- package/dist/client/index.js +77 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/journeys.d.ts +108 -0
- package/dist/client/journeys.js +35 -0
- package/dist/client/journeys.js.map +1 -0
- package/dist/client/log-streams.d.ts +1 -1
- package/dist/client/marketing.d.ts +67 -0
- package/dist/client/marketing.js +26 -0
- package/dist/client/marketing.js.map +1 -0
- package/dist/client/mcp-gateways.d.ts +54 -0
- package/dist/client/mcp-gateways.js +25 -0
- package/dist/client/mcp-gateways.js.map +1 -0
- package/dist/client/messaging.d.ts +14 -3
- package/dist/client/messaging.js.map +1 -1
- package/dist/client/mfa-factors.d.ts +120 -0
- package/dist/client/mfa-factors.js +73 -0
- package/dist/client/mfa-factors.js.map +1 -0
- package/dist/client/migrations.d.ts +286 -0
- package/dist/client/migrations.js +103 -0
- package/dist/client/migrations.js.map +1 -0
- package/dist/client/network-acls.d.ts +6 -1
- package/dist/client/network-acls.js.map +1 -1
- package/dist/client/network-zones.d.ts +56 -0
- package/dist/client/network-zones.js +29 -0
- package/dist/client/network-zones.js.map +1 -0
- package/dist/client/notifications.d.ts +1 -1
- package/dist/client/notifications.js.map +1 -1
- package/dist/client/oauth-clients.d.ts +183 -3
- package/dist/client/oauth-clients.js +64 -0
- package/dist/client/oauth-clients.js.map +1 -1
- package/dist/client/org-role-grants.d.ts +57 -0
- package/dist/client/org-role-grants.js +40 -0
- package/dist/client/org-role-grants.js.map +1 -0
- package/dist/client/organizations.d.ts +52 -0
- package/dist/client/organizations.js +44 -0
- package/dist/client/organizations.js.map +1 -1
- package/dist/client/page-templates.d.ts +78 -0
- package/dist/client/page-templates.js +31 -0
- package/dist/client/page-templates.js.map +1 -0
- package/dist/client/passkey-api.d.ts +73 -0
- package/dist/client/passkey-api.js +34 -0
- package/dist/client/passkey-api.js.map +1 -0
- package/dist/client/resources.d.ts +149 -0
- package/dist/client/resources.js +73 -0
- package/dist/client/resources.js.map +1 -0
- package/dist/client/risk-based-mfa.d.ts +147 -0
- package/dist/client/risk-based-mfa.js +30 -0
- package/dist/client/risk-based-mfa.js.map +1 -1
- package/dist/client/roles.d.ts +4 -0
- package/dist/client/roles.js.map +1 -1
- package/dist/client/service-connectors.d.ts +83 -0
- package/dist/client/service-connectors.js +33 -0
- package/dist/client/service-connectors.js.map +1 -0
- package/dist/client/ssf.d.ts +111 -0
- package/dist/client/ssf.js +49 -0
- package/dist/client/ssf.js.map +1 -0
- package/dist/client/sso-onboarding.d.ts +6 -0
- package/dist/client/sso-onboarding.js.map +1 -1
- package/dist/client/users.d.ts +302 -0
- package/dist/client/users.js +125 -0
- package/dist/client/users.js.map +1 -1
- package/dist/client/vault.d.ts +85 -0
- package/dist/client/vault.js +50 -0
- package/dist/client/vault.js.map +1 -0
- package/dist/client/vc.d.ts +128 -0
- package/dist/client/vc.js +43 -0
- package/dist/client/vc.js.map +1 -0
- package/dist/client/webhooks.d.ts +31 -2
- package/dist/client/webhooks.js.map +1 -1
- package/dist/client/workflows.d.ts +131 -0
- package/dist/client/workflows.js +36 -0
- package/dist/client/workflows.js.map +1 -0
- package/dist/framework-bridge.d.ts +98 -0
- package/dist/framework-bridge.js +264 -0
- package/dist/framework-bridge.js.map +1 -0
- package/dist/framework-sessions.d.ts +147 -0
- package/dist/framework-sessions.js +544 -0
- package/dist/framework-sessions.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/legacy-issuer-presets.d.ts +85 -0
- package/dist/legacy-issuer-presets.js +165 -0
- package/dist/legacy-issuer-presets.js.map +1 -0
- package/dist/legacy-issuers.d.ts +16 -2
- package/dist/legacy-issuers.js +16 -1
- package/dist/legacy-issuers.js.map +1 -1
- package/dist/legacy-verify.d.ts +103 -0
- package/dist/legacy-verify.js +244 -0
- package/dist/legacy-verify.js.map +1 -0
- package/dist/magic-did.d.ts +5 -0
- package/dist/magic-did.js +49 -0
- package/dist/magic-did.js.map +1 -0
- package/dist/migration-bridge.d.ts +162 -0
- package/dist/migration-bridge.js +354 -0
- package/dist/migration-bridge.js.map +1 -0
- package/dist/migration-presets-g3.d.ts +2 -0
- package/dist/migration-presets-g3.js +254 -0
- package/dist/migration-presets-g3.js.map +1 -0
- package/dist/migration-presets-g4/authentik.d.ts +14 -0
- package/dist/migration-presets-g4/authentik.js +37 -0
- package/dist/migration-presets-g4/authentik.js.map +1 -0
- package/dist/migration-presets-g4/fusionauth.d.ts +2 -0
- package/dist/migration-presets-g4/fusionauth.js +52 -0
- package/dist/migration-presets-g4/fusionauth.js.map +1 -0
- package/dist/migration-presets-g4/hanko.d.ts +12 -0
- package/dist/migration-presets-g4/hanko.js +46 -0
- package/dist/migration-presets-g4/hanko.js.map +1 -0
- package/dist/migration-presets-g4/keycloak.d.ts +16 -0
- package/dist/migration-presets-g4/keycloak.js +37 -0
- package/dist/migration-presets-g4/keycloak.js.map +1 -0
- package/dist/migration-presets-g4/logto.d.ts +12 -0
- package/dist/migration-presets-g4/logto.js +35 -0
- package/dist/migration-presets-g4/logto.js.map +1 -0
- package/dist/migration-presets-g4/ory.d.ts +2 -0
- package/dist/migration-presets-g4/ory.js +67 -0
- package/dist/migration-presets-g4/ory.js.map +1 -0
- package/dist/migration-presets-g4/supertokens.d.ts +13 -0
- package/dist/migration-presets-g4/supertokens.js +35 -0
- package/dist/migration-presets-g4/supertokens.js.map +1 -0
- package/dist/migration-presets-g4/zitadel.d.ts +2 -0
- package/dist/migration-presets-g4/zitadel.js +36 -0
- package/dist/migration-presets-g4/zitadel.js.map +1 -0
- package/dist/migration-presets-g4.d.ts +10 -0
- package/dist/migration-presets-g4.js +30 -0
- package/dist/migration-presets-g4.js.map +1 -0
- package/dist/migration-presets.d.ts +156 -0
- package/dist/migration-presets.js +536 -0
- package/dist/migration-presets.js.map +1 -0
- package/dist/request-auth.d.ts +32 -0
- package/dist/request-auth.js +72 -0
- package/dist/request-auth.js.map +1 -0
- package/dist/verify.d.ts +2 -0
- package/dist/verify.js.map +1 -1
- package/dist/workos-session.d.ts +30 -0
- package/dist/workos-session.js +123 -0
- package/dist/workos-session.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.25.0 — 2026-10-26
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `mfaFactors` client resource for the additional authentication factors: `setYubicoSecret` / `removeYubicoSecret`, `setDuoSecret` / `removeDuoSecret` / `duoHealthCheck`, `setSmartCardSecret` / `removeSmartCardSecret` (all write-only), `yubikeys` (`list`, `register`, `remove`), `smartCardMappings` (`list`, `add`, `remove`) and `resetSecurityQuestions`.
|
|
10
|
+
- `users.create({ mfa })` is typed (`ImportedMfa`): an authenticator (`totp`: SHA-1/256/512, 6 or 8 digits, 30 or 60 seconds) or a counter-based token (`hotp`), plus recovery codes.
|
|
11
|
+
|
|
12
|
+
## 0.24.0 — 2026-10-25
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Moving from any auth vendor without signing anyone out: `createMigrationBridge` / `exchangeMigrationSession` (the vendor-neutral session bridge, `POST /v1/migrations/{source}/exchange`), per-vendor bridge presets (`listMigrationBridgePresets`, `resolveMigrationBridgePreset`, `registerMigrationBridgePreset`) for Auth0, Clerk, Cognito, Firebase, Supabase, WorkOS, Okta, Stytch, Keycloak, FusionAuth, Kinde, Descope, Frontegg and session-table sources, and an `extractToken` hook for vendor cookies encrypted with your app's secret. `createBetterAuthBridge` / `exchangeBetterAuthSession` now run on it, unchanged.
|
|
17
|
+
- `migrations` client resource: `imports(source)` (`getPublicKey`, `rotatePublicKey`, `create`, `list`, `get`, `uploadPart`, `finalize`, `dryRun`, `apply`, `delete`, `upload`, `waitFor`), `bridge(source)` (`get`, `update`, `delete`) and `sources()`.
|
|
18
|
+
|
|
5
19
|
## 0.23.0 — 2026-10-25
|
|
6
20
|
|
|
7
21
|
### Added
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MigrationTokenExtractor } from './migration-bridge';
|
|
2
|
+
/**
|
|
3
|
+
* Open an Auth0 SDK session cookie on YOUR server, for the zero-logout bridge.
|
|
4
|
+
*
|
|
5
|
+
* nextjs-auth0 (v4 `__session`, v3 `appSession`) and express-openid-connect
|
|
6
|
+
* (`appSession`) keep the session in a JWE (`alg: dir`, `enc: A256GCM`) whose
|
|
7
|
+
* key is HKDF-SHA256(AUTH0_SECRET, salt "", info "JWE CEK", 32 bytes). Large
|
|
8
|
+
* sessions are split across `__session__0, __session__1…` (v4) or
|
|
9
|
+
* `appSession.0, appSession.1…` (v3, express-openid-connect). Inside is the
|
|
10
|
+
* ID token Auth0 issued at sign-in; the bridge exchanges that (preset `auth0`).
|
|
11
|
+
*
|
|
12
|
+
* migrationBridge({ source: 'auth0', presetVars: { domain, client_id },
|
|
13
|
+
* extractToken: auth0SessionTokenExtractor({ secret: process.env.AUTH0_SECRET! }) })
|
|
14
|
+
*
|
|
15
|
+
* The secret never leaves your server. Pass several secrets while one rotates.
|
|
16
|
+
*/
|
|
17
|
+
export declare function auth0SessionTokenExtractor(options: {
|
|
18
|
+
secret: string | readonly string[];
|
|
19
|
+
/** Cookie names to try, in order (default `__session`, then `appSession`). */
|
|
20
|
+
cookieNames?: readonly string[];
|
|
21
|
+
}): MigrationTokenExtractor;
|
|
22
|
+
/** HKDF-SHA256(secret, salt "", info "JWE CEK", 32): the Auth0 SDKs' cookie key. */
|
|
23
|
+
export declare function auth0CookieKey(secret: string): Uint8Array;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.auth0SessionTokenExtractor = auth0SessionTokenExtractor;
|
|
4
|
+
exports.auth0CookieKey = auth0CookieKey;
|
|
5
|
+
const hkdf_1 = require("@noble/hashes/hkdf");
|
|
6
|
+
const sha256_1 = require("@noble/hashes/sha256");
|
|
7
|
+
const jose_1 = require("jose");
|
|
8
|
+
/**
|
|
9
|
+
* Open an Auth0 SDK session cookie on YOUR server, for the zero-logout bridge.
|
|
10
|
+
*
|
|
11
|
+
* nextjs-auth0 (v4 `__session`, v3 `appSession`) and express-openid-connect
|
|
12
|
+
* (`appSession`) keep the session in a JWE (`alg: dir`, `enc: A256GCM`) whose
|
|
13
|
+
* key is HKDF-SHA256(AUTH0_SECRET, salt "", info "JWE CEK", 32 bytes). Large
|
|
14
|
+
* sessions are split across `__session__0, __session__1…` (v4) or
|
|
15
|
+
* `appSession.0, appSession.1…` (v3, express-openid-connect). Inside is the
|
|
16
|
+
* ID token Auth0 issued at sign-in; the bridge exchanges that (preset `auth0`).
|
|
17
|
+
*
|
|
18
|
+
* migrationBridge({ source: 'auth0', presetVars: { domain, client_id },
|
|
19
|
+
* extractToken: auth0SessionTokenExtractor({ secret: process.env.AUTH0_SECRET! }) })
|
|
20
|
+
*
|
|
21
|
+
* The secret never leaves your server. Pass several secrets while one rotates.
|
|
22
|
+
*/
|
|
23
|
+
function auth0SessionTokenExtractor(options) {
|
|
24
|
+
const secrets = (typeof options.secret === 'string' ? [options.secret] : [...options.secret]).filter(Boolean);
|
|
25
|
+
if (secrets.length === 0)
|
|
26
|
+
throw new Error('auth0SessionTokenExtractor: pass your AUTH0_SECRET.');
|
|
27
|
+
const keys = secrets.map(auth0CookieKey);
|
|
28
|
+
const names = options.cookieNames ?? ['__session', 'appSession'];
|
|
29
|
+
return async ({ cookies }) => {
|
|
30
|
+
for (const name of names) {
|
|
31
|
+
const value = readChunked(cookies, name);
|
|
32
|
+
// A JWE has five segments; Atlas's own `__session` is a JWT (three) and is skipped.
|
|
33
|
+
if (!value || value.split('.').length !== 5)
|
|
34
|
+
continue;
|
|
35
|
+
for (const key of keys) {
|
|
36
|
+
const token = await openSession(value, key);
|
|
37
|
+
if (token)
|
|
38
|
+
return token;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return undefined;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** HKDF-SHA256(secret, salt "", info "JWE CEK", 32): the Auth0 SDKs' cookie key. */
|
|
45
|
+
function auth0CookieKey(secret) {
|
|
46
|
+
return (0, hkdf_1.hkdf)(sha256_1.sha256, new TextEncoder().encode(secret), new Uint8Array(0), new TextEncoder().encode('JWE CEK'), 32);
|
|
47
|
+
}
|
|
48
|
+
/** The cookie value, joined from `name__0…` / `name.0…` chunks when it was split. */
|
|
49
|
+
function readChunked(cookies, name) {
|
|
50
|
+
if (cookies[name])
|
|
51
|
+
return cookies[name];
|
|
52
|
+
for (const sep of ['__', '.']) {
|
|
53
|
+
const parts = [];
|
|
54
|
+
for (let i = 0; cookies[`${name}${sep}${i}`] !== undefined; i++)
|
|
55
|
+
parts.push(cookies[`${name}${sep}${i}`]);
|
|
56
|
+
if (parts.length)
|
|
57
|
+
return parts.join('');
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
async function openSession(jwe, key) {
|
|
62
|
+
let payload;
|
|
63
|
+
try {
|
|
64
|
+
const { plaintext, protectedHeader } = await (0, jose_1.compactDecrypt)(jwe, key, { keyManagementAlgorithms: ['dir'], contentEncryptionAlgorithms: ['A256GCM'] });
|
|
65
|
+
// express-openid-connect / nextjs-auth0 put the session expiry in the header.
|
|
66
|
+
if (typeof protectedHeader.exp === 'number' && protectedHeader.exp * 1000 < Date.now())
|
|
67
|
+
return undefined;
|
|
68
|
+
payload = JSON.parse(new TextDecoder().decode(plaintext));
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
if (!payload || typeof payload !== 'object')
|
|
74
|
+
return undefined;
|
|
75
|
+
const p = payload;
|
|
76
|
+
// v4: tokenSet.idToken; v3: idToken; express-openid-connect: id_token.
|
|
77
|
+
const token = p.tokenSet?.idToken ?? p.idToken ?? p.id_token;
|
|
78
|
+
return typeof token === 'string' && token.split('.').length === 3 ? token : undefined;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=auth0-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth0-session.js","sourceRoot":"","sources":["../src/auth0-session.ts"],"names":[],"mappings":"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"}
|
package/dist/better-auth.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type MigrationBridgeRequest } from './migration-bridge';
|
|
1
2
|
/**
|
|
2
3
|
* Moving from Better Auth to Atlas without signing anyone out.
|
|
3
4
|
*
|
|
@@ -144,14 +145,9 @@ export type BetterAuthBridgeDecision =
|
|
|
144
145
|
* The bridge as a function of a request's headers. Call it from middleware
|
|
145
146
|
* before your normal auth check; it does nothing (no network) for a request
|
|
146
147
|
* without a Better Auth cookie or with an Atlas session (`__session` /
|
|
147
|
-
* `__atlas_rt`) already present.
|
|
148
|
+
* `__atlas_rt`) already present. The generic {@link createMigrationBridge} with
|
|
149
|
+
* the Better Auth cookie names.
|
|
148
150
|
*/
|
|
149
|
-
export declare function createBetterAuthBridge(options: BetterAuthBridgeOptions): (request:
|
|
150
|
-
headers: {
|
|
151
|
-
get(name: string): string | null;
|
|
152
|
-
} | Record<string, string | string[] | undefined>;
|
|
153
|
-
/** The end user's IP as your framework resolved it (forwarded on the secret-key path). */
|
|
154
|
-
ip?: string;
|
|
155
|
-
}) => Promise<BetterAuthBridgeDecision>;
|
|
151
|
+
export declare function createBetterAuthBridge(options: BetterAuthBridgeOptions): (request: MigrationBridgeRequest) => Promise<BetterAuthBridgeDecision>;
|
|
156
152
|
/** Serialize a {@link BridgeCookie} as a `Set-Cookie` header value. */
|
|
157
153
|
export declare function serializeBridgeCookie(cookie: BridgeCookie): string;
|
package/dist/better-auth.js
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BETTER_AUTH_BAPI_EXCHANGE_PATH = exports.BETTER_AUTH_EXCHANGE_PATH = exports.BETTER_AUTH_COOKIE_PREFIX = void 0;
|
|
4
|
+
exports.betterAuthCookieNames = betterAuthCookieNames;
|
|
5
|
+
exports.readBetterAuthSessionCookie = readBetterAuthSessionCookie;
|
|
6
|
+
exports.exchangeBetterAuthSession = exchangeBetterAuthSession;
|
|
7
|
+
exports.createBetterAuthBridge = createBetterAuthBridge;
|
|
8
|
+
exports.serializeBridgeCookie = serializeBridgeCookie;
|
|
9
|
+
const migration_bridge_1 = require("./migration-bridge");
|
|
2
10
|
/**
|
|
3
11
|
* Moving from Better Auth to Atlas without signing anyone out.
|
|
4
12
|
*
|
|
@@ -15,21 +23,12 @@
|
|
|
15
23
|
* cookies to set and clear; the Next.js middleware and the Express / Fastify /
|
|
16
24
|
* Hono adapters render it.
|
|
17
25
|
*/
|
|
18
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
-
exports.BETTER_AUTH_BAPI_EXCHANGE_PATH = exports.BETTER_AUTH_EXCHANGE_PATH = exports.BETTER_AUTH_COOKIE_PREFIX = void 0;
|
|
20
|
-
exports.betterAuthCookieNames = betterAuthCookieNames;
|
|
21
|
-
exports.readBetterAuthSessionCookie = readBetterAuthSessionCookie;
|
|
22
|
-
exports.exchangeBetterAuthSession = exchangeBetterAuthSession;
|
|
23
|
-
exports.createBetterAuthBridge = createBetterAuthBridge;
|
|
24
|
-
exports.serializeBridgeCookie = serializeBridgeCookie;
|
|
25
26
|
/** Better Auth's default cookie prefix (`advanced.cookiePrefix`). */
|
|
26
27
|
exports.BETTER_AUTH_COOKIE_PREFIX = 'better-auth';
|
|
27
28
|
/** The FAPI path of the exchange (publishable key; per-IP limited — the browser / fallback path). */
|
|
28
29
|
exports.BETTER_AUTH_EXCHANGE_PATH = '/v1/client/migrations/better_auth/exchange';
|
|
29
30
|
/** The Backend API path (secret key; limited per instance for a bulk cutover — the server path). */
|
|
30
31
|
exports.BETTER_AUTH_BAPI_EXCHANGE_PATH = '/v1/migrations/better_auth/exchange';
|
|
31
|
-
/** Default Backend API origin. */
|
|
32
|
-
const DEFAULT_BAPI_URL = 'https://api.atlasauth.net';
|
|
33
32
|
/** The Better Auth cookies the bridge reads (session_token) and clears (all of them). */
|
|
34
33
|
function betterAuthCookieNames(prefix = exports.BETTER_AUTH_COOKIE_PREFIX) {
|
|
35
34
|
const base = ['session_token', 'session_data', 'account_data', 'dont_remember'].map((n) => `${prefix}.${n}`);
|
|
@@ -72,150 +71,49 @@ function readBetterAuthSessionCookie(cookieHeader, options = {}) {
|
|
|
72
71
|
* Auth cookie and tries again on a later request.
|
|
73
72
|
*/
|
|
74
73
|
async function exchangeBetterAuthSession(options) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
headers['x-atlas-client-user-agent'] = options.userAgent;
|
|
87
|
-
}
|
|
88
|
-
else {
|
|
89
|
-
headers['x-publishable-key'] = options.publishableKey;
|
|
90
|
-
if (options.userAgent)
|
|
91
|
-
headers['user-agent'] = options.userAgent;
|
|
92
|
-
}
|
|
93
|
-
let res;
|
|
94
|
-
try {
|
|
95
|
-
res = await doFetch(url, {
|
|
96
|
-
method: 'POST',
|
|
97
|
-
headers,
|
|
98
|
-
body: JSON.stringify({
|
|
99
|
-
token: options.token,
|
|
100
|
-
...(viaSecretKey ? {} : { delivery: 'body' }),
|
|
101
|
-
...(options.remember === false ? { remember: false } : {}),
|
|
102
|
-
}),
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
return { kind: 'refused', outcome: 'unavailable', status: 0 };
|
|
107
|
-
}
|
|
108
|
-
const data = (await res.json().catch(() => null));
|
|
109
|
-
if (res.ok && data?.object === 'session_tokens' && data.jwt && data.refresh_token) {
|
|
110
|
-
return {
|
|
111
|
-
kind: 'session',
|
|
112
|
-
jwt: data.jwt,
|
|
113
|
-
refreshToken: data.refresh_token,
|
|
114
|
-
sessionId: data.session_id ?? '',
|
|
115
|
-
userId: data.user_id ?? '',
|
|
116
|
-
expiresIn: data.expires_in ?? 0,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
if (res.ok &&
|
|
120
|
-
data?.object === 'sign_in_attempt' &&
|
|
121
|
-
data.id &&
|
|
122
|
-
(data.status === 'needs_second_factor' || data.status === 'needs_mfa_enrollment')) {
|
|
123
|
-
return { kind: 'needs_mfa', attemptId: data.id, status: data.status };
|
|
124
|
-
}
|
|
125
|
-
if (res.status === 429)
|
|
126
|
-
return { kind: 'refused', outcome: 'rate_limited', status: 429 };
|
|
127
|
-
const outcome = data?.errors?.[0]?.meta?.bridge_outcome;
|
|
128
|
-
const known = ['closed', 'invalid', 'signature_invalid', 'expired', 'reused', 'user_unavailable', 'rate_limited'];
|
|
129
|
-
if (outcome && known.includes(outcome)) {
|
|
130
|
-
return { kind: 'refused', outcome: outcome, status: res.status };
|
|
131
|
-
}
|
|
132
|
-
// Anything else (a 5xx, a guard refusal, an unparsable body) is not a verdict
|
|
133
|
-
// on the Better Auth session: keep it and retry later.
|
|
134
|
-
return { kind: 'refused', outcome: 'unavailable', status: res.status };
|
|
74
|
+
return toBetterAuthResult(await (0, migration_bridge_1.exchangeMigrationSession)({ ...options, source: 'better_auth' }));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The generic exchange's answer in Better Auth's terms. `user_unknown` is not a
|
|
78
|
+
* Better Auth outcome (the Better Auth exchange never sends it), so it reads as
|
|
79
|
+
* any other unknown verdict did before: not a judgement on the session.
|
|
80
|
+
*/
|
|
81
|
+
function toBetterAuthResult(result) {
|
|
82
|
+
if (result.kind === 'refused' && result.outcome === 'user_unknown')
|
|
83
|
+
return { kind: 'refused', outcome: 'unavailable', status: result.status };
|
|
84
|
+
return result;
|
|
135
85
|
}
|
|
136
|
-
/** Refusals that say the Better Auth session will never exchange: its cookies are cleared. */
|
|
137
|
-
const FINAL = ['invalid', 'signature_invalid', 'expired', 'reused', 'user_unavailable'];
|
|
138
86
|
/**
|
|
139
87
|
* The bridge as a function of a request's headers. Call it from middleware
|
|
140
88
|
* before your normal auth check; it does nothing (no network) for a request
|
|
141
89
|
* without a Better Auth cookie or with an Atlas session (`__session` /
|
|
142
|
-
* `__atlas_rt`) already present.
|
|
90
|
+
* `__atlas_rt`) already present. The generic {@link createMigrationBridge} with
|
|
91
|
+
* the Better Auth cookie names.
|
|
143
92
|
*/
|
|
144
93
|
function createBetterAuthBridge(options) {
|
|
145
|
-
const
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
if (
|
|
164
|
-
return { action: '
|
|
165
|
-
|
|
166
|
-
fapiOrigin: options.fapiOrigin,
|
|
167
|
-
publishableKey: options.publishableKey,
|
|
168
|
-
token,
|
|
169
|
-
fetchImpl: options.fetchImpl,
|
|
170
|
-
userAgent: header(request.headers, 'user-agent'),
|
|
171
|
-
secretKey: options.secretKey,
|
|
172
|
-
bapiBaseUrl: options.bapiBaseUrl,
|
|
173
|
-
clientIp: request.ip ?? clientIpFrom(request.headers),
|
|
174
|
-
});
|
|
175
|
-
if (result.kind === 'session') {
|
|
176
|
-
return {
|
|
177
|
-
action: 'signed_in',
|
|
178
|
-
session: result,
|
|
179
|
-
cookies: [
|
|
180
|
-
{ name: '__session', value: result.jwt, options: { path: '/', sameSite: 'lax', secure } },
|
|
181
|
-
{
|
|
182
|
-
name: '__atlas_rt',
|
|
183
|
-
value: result.refreshToken,
|
|
184
|
-
options: { path: '/', httpOnly: true, sameSite: 'lax', secure },
|
|
185
|
-
},
|
|
186
|
-
...clearBetterAuth(),
|
|
187
|
-
],
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
if (result.kind === 'needs_mfa') {
|
|
191
|
-
return {
|
|
192
|
-
action: 'needs_mfa',
|
|
193
|
-
attemptId: result.attemptId,
|
|
194
|
-
status: result.status,
|
|
195
|
-
cookies: clearBetterAuth(),
|
|
196
|
-
continuationUrl: (url) => {
|
|
197
|
-
const next = new URL(url);
|
|
198
|
-
next.searchParams.set('__atlas_attempt', result.attemptId);
|
|
199
|
-
next.searchParams.set('__atlas_status', result.status);
|
|
200
|
-
return next.toString();
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
return {
|
|
205
|
-
action: 'refused',
|
|
206
|
-
outcome: result.outcome,
|
|
207
|
-
cookies: FINAL.includes(result.outcome) ? clearBetterAuth() : [],
|
|
208
|
-
};
|
|
94
|
+
const names = betterAuthCookieNames(options.cookiePrefix);
|
|
95
|
+
const bridge = (0, migration_bridge_1.createMigrationBridge)({
|
|
96
|
+
source: 'better_auth',
|
|
97
|
+
preset: 'better_auth',
|
|
98
|
+
fapiOrigin: options.fapiOrigin,
|
|
99
|
+
publishableKey: options.publishableKey,
|
|
100
|
+
secretKey: options.secretKey,
|
|
101
|
+
bapiBaseUrl: options.bapiBaseUrl,
|
|
102
|
+
cookieNames: options.cookieName ? [`__Secure-${options.cookieName}`, options.cookieName] : names.sessionToken,
|
|
103
|
+
clearCookieNames: names.all.concat(options.cookieName ? [options.cookieName, `__Secure-${options.cookieName}`] : []),
|
|
104
|
+
tokenFormat: 'raw',
|
|
105
|
+
bearer: false,
|
|
106
|
+
oldCookieDomain: options.betterAuthCookieDomain,
|
|
107
|
+
secure: options.secure,
|
|
108
|
+
fetchImpl: options.fetchImpl,
|
|
109
|
+
});
|
|
110
|
+
return async function betterAuthBridge(request) {
|
|
111
|
+
const decision = await bridge(request);
|
|
112
|
+
if (decision.action === 'refused' && decision.outcome === 'user_unknown')
|
|
113
|
+
return { action: 'refused', outcome: 'unavailable', cookies: [] };
|
|
114
|
+
return decision;
|
|
209
115
|
};
|
|
210
116
|
}
|
|
211
|
-
function header(headers, name) {
|
|
212
|
-
if (typeof headers.get === 'function') {
|
|
213
|
-
return headers.get(name) ?? undefined;
|
|
214
|
-
}
|
|
215
|
-
const record = headers;
|
|
216
|
-
const value = record[name] ?? record[name.toLowerCase()];
|
|
217
|
-
return Array.isArray(value) ? value.join('; ') : value;
|
|
218
|
-
}
|
|
219
117
|
/** Serialize a {@link BridgeCookie} as a `Set-Cookie` header value. */
|
|
220
118
|
function serializeBridgeCookie(cookie) {
|
|
221
119
|
const o = cookie.options;
|
|
@@ -236,10 +134,4 @@ function serializeBridgeCookie(cookie) {
|
|
|
236
134
|
parts.push(`SameSite=${o.sameSite[0].toUpperCase()}${o.sameSite.slice(1)}`);
|
|
237
135
|
return parts.join('; ');
|
|
238
136
|
}
|
|
239
|
-
/** The client IP a proxy in front of your server recorded (first X-Forwarded-For hop, or X-Real-IP). */
|
|
240
|
-
function clientIpFrom(headers) {
|
|
241
|
-
const xff = header(headers, 'x-forwarded-for');
|
|
242
|
-
const first = xff?.split(',')[0]?.trim();
|
|
243
|
-
return first || header(headers, 'x-real-ip')?.trim() || undefined;
|
|
244
|
-
}
|
|
245
137
|
//# sourceMappingURL=better-auth.js.map
|
package/dist/better-auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"better-auth.js","sourceRoot":"","sources":["../src/better-auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"better-auth.js","sourceRoot":"","sources":["../src/better-auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type RequestFn } from './request';
|
|
2
|
+
import type { ListPage } from './types';
|
|
3
|
+
export interface AbacPolicyTestCase {
|
|
4
|
+
name: string;
|
|
5
|
+
/** principal, action, resource, context and optional entities. */
|
|
6
|
+
request: Record<string, unknown>;
|
|
7
|
+
expect: 'allow' | 'deny';
|
|
8
|
+
}
|
|
9
|
+
/** An ABAC policy: named, versioned source in the Cedar-subset policy language. */
|
|
10
|
+
export interface AbacPolicy {
|
|
11
|
+
object: 'abac_policy';
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
description: string | null;
|
|
15
|
+
enabled: boolean;
|
|
16
|
+
current_version: number;
|
|
17
|
+
/** The FGA store `fga.check(...)` in the source consults. */
|
|
18
|
+
fga_store_id: string | null;
|
|
19
|
+
source: string;
|
|
20
|
+
tests: AbacPolicyTestCase[];
|
|
21
|
+
created_at: number;
|
|
22
|
+
updated_at: number;
|
|
23
|
+
}
|
|
24
|
+
export interface AbacPolicyVersion {
|
|
25
|
+
object: 'abac_policy_version';
|
|
26
|
+
policy_id: string;
|
|
27
|
+
version: number;
|
|
28
|
+
source: string;
|
|
29
|
+
tests: AbacPolicyTestCase[];
|
|
30
|
+
current: boolean;
|
|
31
|
+
created_at: number;
|
|
32
|
+
}
|
|
33
|
+
export interface CreateAbacPolicyBody {
|
|
34
|
+
name: string;
|
|
35
|
+
description?: string | null;
|
|
36
|
+
enabled?: boolean;
|
|
37
|
+
fga_store_id?: string | null;
|
|
38
|
+
source: string;
|
|
39
|
+
tests?: AbacPolicyTestCase[];
|
|
40
|
+
}
|
|
41
|
+
/** Sending `source` appends a new version; `current_version` (without source) rolls back. */
|
|
42
|
+
export type UpdateAbacPolicyBody = Partial<CreateAbacPolicyBody> & {
|
|
43
|
+
current_version?: number;
|
|
44
|
+
};
|
|
45
|
+
export interface AbacEntity {
|
|
46
|
+
type: string;
|
|
47
|
+
id: string;
|
|
48
|
+
attributes?: Record<string, unknown>;
|
|
49
|
+
/** `Type::id` uids this entity is a member of (for `in`). */
|
|
50
|
+
parents?: string[];
|
|
51
|
+
}
|
|
52
|
+
export interface AbacEvaluateBody {
|
|
53
|
+
principal: AbacEntity;
|
|
54
|
+
action: string;
|
|
55
|
+
resource: AbacEntity;
|
|
56
|
+
context?: Record<string, unknown>;
|
|
57
|
+
entities?: AbacEntity[];
|
|
58
|
+
/** Evaluate only these policies (default: every enabled one). */
|
|
59
|
+
policy_ids?: string[];
|
|
60
|
+
}
|
|
61
|
+
export interface AbacDecision {
|
|
62
|
+
object: 'abac_decision';
|
|
63
|
+
decision: 'allow' | 'deny';
|
|
64
|
+
reasons: string[];
|
|
65
|
+
errors: string[];
|
|
66
|
+
}
|
|
67
|
+
export interface AbacTestRun {
|
|
68
|
+
object: 'abac_policy_test_run';
|
|
69
|
+
passed: boolean;
|
|
70
|
+
results: Array<{
|
|
71
|
+
name: string;
|
|
72
|
+
expect: 'allow' | 'deny';
|
|
73
|
+
actual: 'allow' | 'deny';
|
|
74
|
+
passed: boolean;
|
|
75
|
+
}>;
|
|
76
|
+
}
|
|
77
|
+
export interface AuthzenEvaluation {
|
|
78
|
+
subject?: {
|
|
79
|
+
type: string;
|
|
80
|
+
id: string;
|
|
81
|
+
properties?: Record<string, unknown>;
|
|
82
|
+
};
|
|
83
|
+
resource?: {
|
|
84
|
+
type: string;
|
|
85
|
+
id: string;
|
|
86
|
+
properties?: Record<string, unknown>;
|
|
87
|
+
};
|
|
88
|
+
action?: {
|
|
89
|
+
name: string;
|
|
90
|
+
properties?: Record<string, unknown>;
|
|
91
|
+
};
|
|
92
|
+
context?: Record<string, unknown>;
|
|
93
|
+
}
|
|
94
|
+
/** ABAC policies and the policy decision point (including the AuthZEN endpoints). */
|
|
95
|
+
export declare function abacResource(request: RequestFn): {
|
|
96
|
+
list(): Promise<ListPage<AbacPolicy>>;
|
|
97
|
+
get(id: string): Promise<AbacPolicy>;
|
|
98
|
+
create(body: CreateAbacPolicyBody, idempotencyKey?: string): Promise<AbacPolicy>;
|
|
99
|
+
update(id: string, body: UpdateAbacPolicyBody): Promise<AbacPolicy>;
|
|
100
|
+
delete(id: string): Promise<{
|
|
101
|
+
object: "abac_policy";
|
|
102
|
+
id: string;
|
|
103
|
+
deleted: true;
|
|
104
|
+
}>;
|
|
105
|
+
versions(id: string): Promise<ListPage<AbacPolicyVersion>>;
|
|
106
|
+
/** Run a version's tests (default: current), or a draft `source` and `tests`, without saving. */
|
|
107
|
+
test(id: string, body?: {
|
|
108
|
+
version?: number;
|
|
109
|
+
source?: string;
|
|
110
|
+
tests?: AbacPolicyTestCase[];
|
|
111
|
+
}): Promise<AbacTestRun>;
|
|
112
|
+
/** May `principal` perform `action` on `resource`? */
|
|
113
|
+
evaluate(body: AbacEvaluateBody): Promise<AbacDecision>;
|
|
114
|
+
/** Convenience: the boolean answer to {@link evaluate}. */
|
|
115
|
+
isAllowed(body: AbacEvaluateBody): Promise<boolean>;
|
|
116
|
+
/** AuthZEN 1.0 Access Evaluation. */
|
|
117
|
+
authzenEvaluation(body: AuthzenEvaluation): Promise<{
|
|
118
|
+
decision: boolean;
|
|
119
|
+
context?: Record<string, unknown>;
|
|
120
|
+
}>;
|
|
121
|
+
/** AuthZEN 1.0 Access Evaluations (batch). */
|
|
122
|
+
authzenEvaluations(body: AuthzenEvaluation & {
|
|
123
|
+
evaluations?: AuthzenEvaluation[];
|
|
124
|
+
options?: {
|
|
125
|
+
evaluations_semantic?: "execute_all" | "deny_on_first_deny" | "permit_on_first_permit";
|
|
126
|
+
};
|
|
127
|
+
}): Promise<{
|
|
128
|
+
evaluations: Array<{
|
|
129
|
+
decision: boolean;
|
|
130
|
+
}>;
|
|
131
|
+
}>;
|
|
132
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.abacResource = abacResource;
|
|
4
|
+
const request_1 = require("./request");
|
|
5
|
+
/** ABAC policies and the policy decision point (including the AuthZEN endpoints). */
|
|
6
|
+
function abacResource(request) {
|
|
7
|
+
return {
|
|
8
|
+
list() {
|
|
9
|
+
return request({ method: 'GET', path: '/v1/abac_policies' });
|
|
10
|
+
},
|
|
11
|
+
get(id) {
|
|
12
|
+
return request({ method: 'GET', path: `/v1/abac_policies/${(0, request_1.enc)(id)}` });
|
|
13
|
+
},
|
|
14
|
+
create(body, idempotencyKey) {
|
|
15
|
+
return request({ method: 'POST', path: '/v1/abac_policies', body, idempotencyKey });
|
|
16
|
+
},
|
|
17
|
+
update(id, body) {
|
|
18
|
+
return request({ method: 'PATCH', path: `/v1/abac_policies/${(0, request_1.enc)(id)}`, body });
|
|
19
|
+
},
|
|
20
|
+
delete(id) {
|
|
21
|
+
return request({ method: 'DELETE', path: `/v1/abac_policies/${(0, request_1.enc)(id)}` });
|
|
22
|
+
},
|
|
23
|
+
versions(id) {
|
|
24
|
+
return request({ method: 'GET', path: `/v1/abac_policies/${(0, request_1.enc)(id)}/versions` });
|
|
25
|
+
},
|
|
26
|
+
/** Run a version's tests (default: current), or a draft `source` and `tests`, without saving. */
|
|
27
|
+
test(id, body = {}) {
|
|
28
|
+
return request({ method: 'POST', path: `/v1/abac_policies/${(0, request_1.enc)(id)}/test`, body });
|
|
29
|
+
},
|
|
30
|
+
/** May `principal` perform `action` on `resource`? */
|
|
31
|
+
evaluate(body) {
|
|
32
|
+
return request({ method: 'POST', path: '/v1/abac/evaluate', body });
|
|
33
|
+
},
|
|
34
|
+
/** Convenience: the boolean answer to {@link evaluate}. */
|
|
35
|
+
async isAllowed(body) {
|
|
36
|
+
return (await request({ method: 'POST', path: '/v1/abac/evaluate', body })).decision === 'allow';
|
|
37
|
+
},
|
|
38
|
+
/** AuthZEN 1.0 Access Evaluation. */
|
|
39
|
+
authzenEvaluation(body) {
|
|
40
|
+
return request({ method: 'POST', path: '/v1/authzen/access/v1/evaluation', body });
|
|
41
|
+
},
|
|
42
|
+
/** AuthZEN 1.0 Access Evaluations (batch). */
|
|
43
|
+
authzenEvaluations(body) {
|
|
44
|
+
return request({ method: 'POST', path: '/v1/authzen/access/v1/evaluations', body });
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=abac.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"abac.js","sourceRoot":"","sources":["../../src/client/abac.ts"],"names":[],"mappings":";;AAuFA,oCA2CC;AAlID,uCAAgD;AAsFhD,qFAAqF;AACrF,SAAgB,YAAY,CAAC,OAAkB;IAC7C,OAAO;QACL,IAAI;YACF,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,GAAG,CAAC,EAAU;YACZ,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,MAAM,CAAC,IAA0B,EAAE,cAAuB;YACxD,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,CAAC,EAAU,EAAE,IAA0B;YAC3C,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,qBAAqB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,CAAC,EAAU;YACf,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,IAAA,aAAG,EAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,QAAQ,CAAC,EAAU;YACjB,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,qBAAqB,IAAA,aAAG,EAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QACnF,CAAC;QACD,iGAAiG;QACjG,IAAI,CAAC,EAAU,EAAE,OAA4E,EAAE;YAC7F,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,qBAAqB,IAAA,aAAG,EAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,sDAAsD;QACtD,QAAQ,CAAC,IAAsB;YAC7B,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC;QACD,2DAA2D;QAC3D,KAAK,CAAC,SAAS,CAAC,IAAsB;YACpC,OAAO,CAAC,MAAM,OAAO,CAAe,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC;QACjH,CAAC;QACD,qCAAqC;QACrC,iBAAiB,CAAC,IAAuB;YACvC,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,kCAAkC,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,CAAC;QACD,8CAA8C;QAC9C,kBAAkB,CAChB,IAAqK;YAErK,OAAO,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,mCAAmC,EAAE,IAAI,EAAE,CAAC,CAAC;QACtF,CAAC;KACF,CAAC;AACJ,CAAC"}
|