@cboxdk/id-js 0.2.0 → 0.3.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/README.md CHANGED
@@ -126,6 +126,47 @@ const lease = await agent.lease(secret.id, 'call openai');
126
126
 
127
127
  A lease with no live grant is refused — the vault is deny-by-default.
128
128
 
129
+ ## Roles & permissions (federated RBAC)
130
+
131
+ Declare your app's authorization **roles** and **permissions** in code, then push them
132
+ to Cbox ID on deploy. Your app owns what a role *means*; Cbox ID owns identity and who
133
+ *holds* each role — assignments arrive back in the token's `roles` / `permissions`
134
+ claims for you to enforce. Requires the app's client to hold the `apps.manifest` scope.
135
+
136
+ ```ts
137
+ import { defineAuthz, publishManifest } from '@cboxdk/id-js';
138
+
139
+ // Declare the catalog (validated: keys are `feature:action`, roles must reference
140
+ // declared permissions). Keep this next to the code that enforces it.
141
+ export const authz = defineAuthz({
142
+ permissions: [
143
+ { key: 'invoices:create', description: 'Create invoices' },
144
+ { key: 'invoices:read', description: 'View invoices' },
145
+ ],
146
+ roles: [
147
+ { key: 'billing-admin', name: 'Billing Admin', description: 'Full billing access',
148
+ permissions: ['invoices:create', 'invoices:read'] },
149
+ ],
150
+ });
151
+
152
+ // Push it — run from a deploy step or a `package.json` script. Idempotent: an
153
+ // unchanged catalog is a server-side no-op (the manifest carries a content hash).
154
+ const summary = await publishManifest(
155
+ {
156
+ issuer: process.env.CBOX_ID_ISSUER!,
157
+ clientId: process.env.CBOX_ID_CLIENT_ID!,
158
+ clientSecret: process.env.CBOX_ID_CLIENT_SECRET!,
159
+ },
160
+ authz,
161
+ );
162
+ // → { unchanged, roles_declared, permissions_declared, ... }
163
+ ```
164
+
165
+ `publishManifest` mints a client-credentials token (`scope=apps.manifest`) and POSTs
166
+ the manifest to `{issuer}/api/v1/apps/manifest`. It is a server-side operation — keep
167
+ your `clientSecret` off the browser. The wire format matches the PHP SDK
168
+ (`cboxdk/laravel-id-client`), so any SDK can publish the same catalog.
169
+
129
170
  ## Security & scope
130
171
 
131
172
  Login is hardened by default — PKCE, `state`, nonce, and full `id_token` verification
@@ -488,6 +488,6 @@ function timingSafeEqualString(a, b) {
488
488
  return mismatch === 0;
489
489
  }
490
490
 
491
- export { AuthenticationError, CboxIdClient, CboxIdError, ConfigurationError, InvalidStateError, VaultClient, challenge, createVerifier, randomToken, verifyWebhook };
492
- //# sourceMappingURL=chunk-X5XNYQAD.js.map
493
- //# sourceMappingURL=chunk-X5XNYQAD.js.map
491
+ export { AuthenticationError, CboxIdClient, CboxIdError, ConfigurationError, Discovery, InvalidStateError, VaultClient, challenge, createVerifier, randomToken, verifyWebhook };
492
+ //# sourceMappingURL=chunk-U6KYO2XA.js.map
493
+ //# sourceMappingURL=chunk-U6KYO2XA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/pkce.ts","../src/vault.ts","../src/webhook.ts","../src/discovery.ts","../src/client.ts"],"names":["key"],"mappings":"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","file":"chunk-U6KYO2XA.js","sourcesContent":["/**\n * Base class for every error this SDK throws, so callers can `catch (e) { if (e\n * instanceof CboxIdError) ... }` in one branch.\n */\nexport class CboxIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The client is misconfigured (a required option is missing or empty). */\nexport class ConfigurationError extends CboxIdError {}\n\n/**\n * The login `state` did not match what was stored — the callback is forged or\n * stale. Treat as a fresh start, not an error to surface to the user.\n */\nexport class InvalidStateError extends CboxIdError {}\n\n/**\n * Login could not be completed: the provider returned an error, the callback was\n * missing a code, or a token / id_token failed verification.\n */\nexport class AuthenticationError extends CboxIdError {}\n","/**\n * PKCE (RFC 7636) and the random values the login flow needs, built on Web Crypto\n * (`globalThis.crypto`) so the same code runs on Node, edge runtimes and browsers.\n */\n\nfunction base64url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** A URL-safe random token of `bytes` bytes (default 32), for state and nonce. */\nexport function randomToken(bytes = 32): string {\n return base64url(crypto.getRandomValues(new Uint8Array(bytes)));\n}\n\n/** A high-entropy PKCE code verifier. */\nexport function createVerifier(): string {\n return randomToken(32);\n}\n\n/** The S256 code challenge for a verifier. */\nexport async function challenge(verifier: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n return base64url(new Uint8Array(digest));\n}\n","import { AuthenticationError } from './errors.js';\n\n/** A stored vault secret's metadata (never its plaintext). */\nexport interface VaultSecretRef {\n id: string;\n name: string;\n provider: string;\n ownerType: string | null;\n ownerId: string | null;\n expiresAt: string | null;\n revoked: boolean;\n}\n\n/** A brokered credential — the plaintext, for immediate use. */\nexport interface VaultLease {\n secretId: string;\n provider: string;\n secret: string;\n expiresAt: string;\n}\n\nexport interface StoreSecretInput {\n name: string;\n provider: string;\n secret: string;\n ownerType?: 'organization' | 'user';\n ownerId?: string;\n expiresAt?: string;\n}\n\n/**\n * Client for a Cbox ID instance's Token Vault API. Bind it to an access token\n * (obtain one with {@link CboxIdClient.machineToken}, scoped `vault.manage` for\n * provisioning or `vault.lease` for redeeming). All calls are server-to-server.\n */\nexport class VaultClient {\n private readonly base: string;\n\n constructor(\n issuer: string,\n private readonly token: string,\n private readonly timeoutMs = 10_000,\n ) {\n this.base = `${issuer.replace(/\\/$/, '')}/api/v1/vault`;\n }\n\n /** Ingest a downstream credential, sealed at rest (scope `vault.manage`). */\n store(input: StoreSecretInput): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', '/secrets', {\n name: input.name,\n provider: input.provider,\n secret: input.secret,\n owner_type: input.ownerType,\n owner_id: input.ownerId,\n expires_at: input.expiresAt,\n });\n }\n\n /** Rotate a secret's value, keeping its id and grants (scope `vault.manage`). */\n rotate(secretId: string, secret: string): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', `/secrets/${encodeURIComponent(secretId)}/rotate`, { secret });\n }\n\n /** Revoke a secret permanently (scope `vault.manage`). */\n async revoke(secretId: string): Promise<void> {\n await this.request('DELETE', `/secrets/${encodeURIComponent(secretId)}`);\n }\n\n /** Authorize an agent client to lease a secret (scope `vault.manage`). */\n grant(\n secretId: string,\n clientId: string,\n maxTtlSeconds?: number,\n ): Promise<{ secretId: string; clientId: string; maxTtlSeconds: number | null }> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/grants`, {\n client_id: clientId,\n max_ttl_seconds: maxTtlSeconds,\n }).then((raw) => {\n const r = raw as { secret_id: string; client_id: string; max_ttl_seconds: number | null };\n return { secretId: r.secret_id, clientId: r.client_id, maxTtlSeconds: r.max_ttl_seconds };\n });\n }\n\n /** Revoke an agent's authorization (scope `vault.manage`). */\n async revokeGrant(secretId: string, clientId: string): Promise<void> {\n await this.request(\n 'DELETE',\n `/secrets/${encodeURIComponent(secretId)}/grants/${encodeURIComponent(clientId)}`,\n );\n }\n\n /**\n * Redeem a leased credential for immediate use (scope `vault.lease`). The caller\n * is identified by the token's client; a lease with no live grant is refused.\n */\n lease(secretId: string, purpose: string): Promise<VaultLease> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/lease`, { purpose }).then((raw) => {\n const r = raw as { secret_id: string; provider: string; secret: string; expires_at: string };\n return { secretId: r.secret_id, provider: r.provider, secret: r.secret, expiresAt: r.expires_at };\n });\n }\n\n private async json<T>(method: string, path: string, body: Record<string, unknown>): Promise<T> {\n const response = await this.request(method, path, body);\n return (await response.json()) as T;\n }\n\n private async request(method: string, path: string, body?: Record<string, unknown>): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const init: RequestInit = {\n method,\n headers: {\n authorization: `Bearer ${this.token}`,\n ...(body ? { 'content-type': 'application/json' } : {}),\n },\n signal: controller.signal,\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n const response = await fetch(`${this.base}${path}`, init);\n if (!response.ok) {\n throw new AuthenticationError(`Vault ${method} ${path} failed with status ${response.status}.`);\n }\n return response;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","/**\n * Verify a Cbox ID webhook / inline-action signature. The header is\n * `X-Cbox-Signature: t={unix},v1={hex hmac}` — an HMAC-SHA256 over\n * `\"{timestamp}.{raw body}\"`, valid within a freshness window. Built on Web Crypto\n * so it runs on Node, edge and the browser.\n */\n\n/** Constant-time compare of two hex strings. */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n\nfunction toHex(bytes: ArrayBuffer): string {\n return Array.from(new Uint8Array(bytes))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport interface VerifyWebhookOptions {\n /** The RAW request body — the exact bytes received, not a re-encoded copy. */\n payload: string;\n /** The value of the `X-Cbox-Signature` header. */\n signatureHeader: string | null | undefined;\n /** The signing secret issued when the webhook/action endpoint was registered. */\n secret: string;\n /** Freshness window in seconds. Defaults to 300 (5 minutes). */\n toleranceSeconds?: number;\n /** Injectable clock (unix seconds), for tests. Defaults to `Date.now()`. */\n now?: number;\n}\n\n/** Returns `true` only when the signature is present, fresh and valid. Never throws. */\nexport async function verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n const { payload, signatureHeader, secret } = options;\n const toleranceSeconds = options.toleranceSeconds ?? 300;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n if (!signatureHeader) {\n return false;\n }\n\n const parts: Record<string, string> = {};\n for (const segment of signatureHeader.split(',')) {\n const [key, value] = segment.trim().split('=', 2);\n if (key) {\n parts[key] = value ?? '';\n }\n }\n\n const timestamp = parts['t'] ?? '';\n const signature = parts['v1'] ?? '';\n\n if (timestamp === '' || signature === '' || !/^\\d+$/.test(timestamp)) {\n return false;\n }\n\n if (Math.abs(now - Number(timestamp)) > toleranceSeconds) {\n return false;\n }\n\n const key = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const expected = toHex(\n await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`${timestamp}.${payload}`)),\n );\n\n return timingSafeEqual(expected, signature);\n}\n","import { AuthenticationError, ConfigurationError } from './errors.js';\nimport type { DiscoveryDocument } from './types.js';\n\n/**\n * Fetches and caches an instance's OIDC discovery document. One instance of this\n * lives per {@link CboxIdClient}; the document is refetched only after the TTL.\n */\nexport class Discovery {\n private cached: { doc: DiscoveryDocument; expiresAt: number } | null = null;\n\n constructor(\n private readonly issuer: string,\n private readonly timeoutMs: number,\n private readonly cacheTtlMs: number,\n private readonly now: () => number = Date.now,\n ) {}\n\n async document(): Promise<DiscoveryDocument> {\n if (this.cached && this.cached.expiresAt > this.now()) {\n return this.cached.doc;\n }\n\n const url = `${this.issuer.replace(/\\/$/, '')}/.well-known/openid-configuration`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n let doc: DiscoveryDocument;\n try {\n const response = await fetch(url, { signal: controller.signal });\n if (!response.ok) {\n throw new AuthenticationError(`Discovery request failed with status ${response.status}.`);\n }\n doc = (await response.json()) as DiscoveryDocument;\n } catch (error) {\n if (error instanceof AuthenticationError) {\n throw error;\n }\n throw new AuthenticationError(`Discovery request failed: ${String(error)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (typeof doc.issuer !== 'string' || doc.issuer === '') {\n throw new AuthenticationError('The discovery document was missing an issuer.');\n }\n\n this.cached = { doc, expiresAt: this.now() + this.cacheTtlMs };\n return doc;\n }\n\n /** A required endpoint from the discovery document. */\n async endpoint(name: keyof DiscoveryDocument): Promise<string> {\n const value = (await this.document())[name];\n if (typeof value !== 'string' || value === '') {\n throw new ConfigurationError(`The instance does not advertise a ${name}.`);\n }\n return value;\n }\n\n /** An optional endpoint, or null when the instance advertises none. */\n async optionalEndpoint(name: keyof DiscoveryDocument): Promise<string | null> {\n const value = (await this.document())[name];\n return typeof value === 'string' && value !== '' ? value : null;\n }\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport { Discovery } from './discovery.js';\nimport { AuthenticationError, ConfigurationError, InvalidStateError } from './errors.js';\nimport { challenge, createVerifier, randomToken } from './pkce.js';\nimport type {\n AuthorizationRequest,\n CboxIdConfig,\n CboxUser,\n TokenResponse,\n} from './types.js';\nimport { VaultClient } from './vault.js';\nimport { verifyWebhook, type VerifyWebhookOptions } from './webhook.js';\n\ntype JwksResolver = ReturnType<typeof createRemoteJWKSet>;\n\n/** Query parameters as they arrive on your callback route. */\nexport interface CallbackParams {\n code?: string | null;\n state?: string | null;\n error?: string | null;\n error_description?: string | null;\n}\n\n/** The values you persisted from {@link CboxIdClient.createAuthorizationRequest}. */\nexport interface StoredAuthState {\n state: string;\n codeVerifier: string;\n nonce: string;\n}\n\n/**\n * Turnkey Cbox ID client for JavaScript/TypeScript. It speaks standard OpenID\n * Connect against a Cbox ID instance — so integrating is a redirect and a callback,\n * not a rewrite — and adds the conveniences a hosted-identity product needs: a\n * redirect to the instance's hosted profile page, and back-channel helpers (machine\n * tokens, userinfo, introspection, webhook verification).\n *\n * Login is hardened by default: PKCE (S256), a CSRF state check, a nonce, and full\n * id_token signature + issuer + audience verification against the instance's JWKS\n * (via `jose`).\n *\n * The class is framework-agnostic: {@link createAuthorizationRequest} hands you the\n * `state`, `codeVerifier` and `nonce` to persist however you like, and\n * {@link authenticate} takes them back. For Next.js, the `@cboxdk/id-js/nextjs`\n * entry wires this to cookies for you.\n */\nexport class CboxIdClient {\n private readonly discovery: Discovery;\n private readonly jwksByUri = new Map<string, JwksResolver>();\n\n constructor(private readonly config: CboxIdConfig) {\n if (!config.issuer) {\n throw new ConfigurationError('Cbox ID config `issuer` is required.');\n }\n if (!config.clientId) {\n throw new ConfigurationError('Cbox ID config `clientId` is required.');\n }\n if (!config.redirectUri) {\n throw new ConfigurationError('Cbox ID config `redirectUri` is required.');\n }\n this.discovery = new Discovery(\n config.issuer,\n config.timeoutMs ?? 10_000,\n config.cacheTtlMs ?? 3_600_000,\n );\n }\n\n /**\n * Begin login. Returns the authorize URL plus the `state`, `codeVerifier` and\n * `nonce` — persist those (signed, httpOnly cookies are ideal) and hand them back\n * to {@link authenticate} on the callback.\n */\n async createAuthorizationRequest(options: {\n scopes?: string[];\n redirectUri?: string;\n state?: string;\n prompt?: string;\n loginHint?: string;\n maxAge?: number;\n } = {}): Promise<AuthorizationRequest> {\n const codeVerifier = createVerifier();\n const state = options.state ?? randomToken(16);\n const nonce = randomToken(16);\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: this.config.clientId,\n redirect_uri: options.redirectUri ?? this.config.redirectUri,\n scope: (options.scopes ?? this.scopes()).join(' '),\n state,\n nonce,\n code_challenge: await challenge(codeVerifier),\n code_challenge_method: 'S256',\n });\n if (options.prompt) {\n params.set('prompt', options.prompt);\n }\n if (options.loginHint) {\n params.set('login_hint', options.loginHint);\n }\n if (typeof options.maxAge === 'number') {\n params.set('max_age', String(options.maxAge));\n }\n\n const endpoint = await this.discovery.endpoint('authorization_endpoint');\n return { url: `${endpoint}?${params.toString()}`, state, codeVerifier, nonce };\n }\n\n /**\n * Complete login on your callback route: verify state, exchange the code with the\n * PKCE verifier, verify the id_token, and return the authenticated user.\n *\n * @throws InvalidStateError when state does not match (forged/stale request)\n * @throws AuthenticationError on any other failure\n */\n async authenticate(input: {\n params: CallbackParams;\n stored: StoredAuthState;\n redirectUri?: string;\n }): Promise<CboxUser> {\n const { params, stored } = input;\n\n if (!params.state || !stored.state || !timingSafeEqualString(params.state, stored.state)) {\n throw new InvalidStateError('The login state did not match — the request may be forged or stale.');\n }\n\n if (params.error) {\n throw new AuthenticationError(\n `Cbox ID returned an error: ${params.error}${params.error_description ? ` (${params.error_description})` : ''}`,\n );\n }\n\n if (!params.code) {\n throw new AuthenticationError('The callback was missing an authorization code.');\n }\n\n const tokens = await this.exchange(params.code, stored.codeVerifier, input.redirectUri);\n\n if (!tokens.access_token) {\n throw new AuthenticationError('No access token was returned.');\n }\n\n let claims: Record<string, unknown> = {};\n if (tokens.id_token) {\n claims = await this.verifyIdToken(tokens.id_token, stored.nonce);\n }\n // Enrich with userinfo (email/name/org a minimal id_token may omit).\n claims = { ...claims, ...(await this.userinfo(tokens.access_token)) };\n\n const sub = claims['sub'];\n if (typeof sub !== 'string' || sub === '') {\n throw new AuthenticationError('The verified token carried no subject.');\n }\n\n return {\n id: sub,\n email: typeof claims['email'] === 'string' ? claims['email'] : null,\n name: typeof claims['name'] === 'string' ? claims['name'] : null,\n organizationId: typeof claims['org'] === 'string' ? claims['org'] : null,\n claims,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? null,\n idToken: tokens.id_token ?? null,\n expiresIn: typeof tokens.expires_in === 'number' ? tokens.expires_in : 0,\n };\n }\n\n /**\n * The URL of the instance's hosted account/profile page (self-service password,\n * MFA, passkeys, sessions). A signed-in user is authenticated there by their Cbox\n * ID session; `returnTo` is passed so the page can link back to your app.\n */\n profileUrl(returnTo?: string): string {\n const base = `${this.config.issuer.replace(/\\/$/, '')}${this.accountPath()}`;\n return returnTo ? `${base}?${new URLSearchParams({ return_to: returnTo }).toString()}` : base;\n }\n\n /** The RP-initiated logout URL, or null when the instance advertises none. */\n async logoutUrl(returnTo?: string): Promise<string | null> {\n const endpoint = await this.discovery.optionalEndpoint('end_session_endpoint');\n if (!endpoint) {\n return null;\n }\n return returnTo\n ? `${endpoint}?${new URLSearchParams({ post_logout_redirect_uri: returnTo }).toString()}`\n : endpoint;\n }\n\n /**\n * A machine (client-credentials) access token for calling Cbox ID APIs as your\n * app, not on a user's behalf. Requires a client secret.\n */\n async machineToken(options: { scopes?: string[]; resource?: string } = {}): Promise<string> {\n const body = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.config.clientId,\n client_secret: this.requireSecret(),\n });\n if (options.scopes && options.scopes.length > 0) {\n body.set('scope', options.scopes.join(' '));\n }\n if (options.resource) {\n body.set('resource', options.resource);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Machine token request failed: ${await response.text()}`);\n }\n const json = (await response.json()) as { access_token?: unknown };\n if (typeof json.access_token !== 'string') {\n throw new AuthenticationError('The token response had no access_token.');\n }\n return json.access_token;\n }\n\n /** The OIDC userinfo claims for an access token. */\n async userinfo(accessToken: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.optionalEndpoint('userinfo_endpoint');\n if (!endpoint) {\n return {};\n }\n const response = await this.fetchWithTimeout(endpoint, {\n headers: { authorization: `Bearer ${accessToken}` },\n });\n if (!response.ok) {\n throw new AuthenticationError('Userinfo request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /**\n * RFC 7662 token introspection (confidential-client auth). Returns the raw\n * response; `active` tells you if the token is currently valid. Requires a secret.\n */\n async introspect(token: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.endpoint('introspection_endpoint');\n const basic = btoa(`${this.config.clientId}:${this.requireSecret()}`);\n const response = await this.post(\n endpoint,\n new URLSearchParams({ token }),\n { authorization: `Basic ${basic}` },\n );\n if (!response.ok) {\n throw new AuthenticationError('Introspection request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /** Verify a Cbox ID webhook / inline-action signature. See {@link verifyWebhook}. */\n verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n return verifyWebhook(options);\n }\n\n /**\n * A Token Vault client bound to an access token. Obtain the token with\n * {@link machineToken} (scope `vault.manage` to provision/grant, `vault.lease` to\n * redeem), then call `store` / `grant` / `lease` etc.\n */\n vault(accessToken: string): VaultClient {\n return new VaultClient(this.config.issuer, accessToken, this.config.timeoutMs ?? 10_000);\n }\n\n private async exchange(code: string, verifier: string, redirectUri?: string): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri ?? this.config.redirectUri,\n client_id: this.config.clientId,\n code_verifier: verifier,\n });\n if (this.config.clientSecret) {\n body.set('client_secret', this.config.clientSecret);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Token exchange failed: ${await response.text()}`);\n }\n return (await response.json()) as TokenResponse;\n }\n\n private async verifyIdToken(idToken: string, nonce: string): Promise<Record<string, unknown>> {\n const jwksUri = await this.discovery.endpoint('jwks_uri');\n let resolver = this.jwksByUri.get(jwksUri);\n if (!resolver) {\n resolver = createRemoteJWKSet(new URL(jwksUri));\n this.jwksByUri.set(jwksUri, resolver);\n }\n\n let payload: JWTPayload;\n try {\n ({ payload } = await jwtVerify(idToken, resolver, {\n issuer: this.config.issuer,\n audience: this.config.clientId,\n }));\n } catch (error) {\n throw new AuthenticationError(`The id_token could not be verified: ${String(error)}`);\n }\n\n if (nonce && payload['nonce'] !== nonce) {\n throw new AuthenticationError('The id_token nonce did not match — possible replay.');\n }\n\n return payload as Record<string, unknown>;\n }\n\n private scopes(): string[] {\n const scopes = this.config.scopes;\n return scopes && scopes.length > 0 ? scopes : ['openid', 'profile', 'email'];\n }\n\n private accountPath(): string {\n const path = this.config.accountPath;\n return path && path !== '' ? `/${path.replace(/^\\//, '')}` : '/settings';\n }\n\n private requireSecret(): string {\n if (!this.config.clientSecret) {\n throw new ConfigurationError('This call requires a `clientSecret`, but none is configured.');\n }\n return this.config.clientSecret;\n }\n\n private post(url: string, body: URLSearchParams, headers: Record<string, string> = {}): Promise<Response> {\n return this.fetchWithTimeout(url, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', ...headers },\n body,\n });\n }\n\n private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs ?? 10_000);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/** Constant-time string compare, so state validation doesn't leak via timing. */\nfunction timingSafeEqualString(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n"]}
package/dist/index.cjs CHANGED
@@ -492,14 +492,136 @@ function timingSafeEqualString(a, b) {
492
492
  return mismatch === 0;
493
493
  }
494
494
 
495
+ // src/authz.ts
496
+ function defineAuthz(declaration) {
497
+ const permissions = declaration.permissions ?? [];
498
+ const roles = declaration.roles ?? [];
499
+ assertDeclaration(permissions, roles);
500
+ return { permissions, roles };
501
+ }
502
+ async function buildManifest(declaration) {
503
+ const permissions = (declaration.permissions ?? []).map(canonicalPermission);
504
+ const roles = (declaration.roles ?? []).map(canonicalRole);
505
+ assertDeclaration(permissions, roles);
506
+ permissions.sort((a, b) => a.key.localeCompare(b.key));
507
+ roles.sort((a, b) => a.key.localeCompare(b.key));
508
+ const version = (await sha256Hex(JSON.stringify({ permissions, roles }))).slice(0, 16);
509
+ return { version, permissions, roles };
510
+ }
511
+ async function publishManifest(config, declaration) {
512
+ if (!config.issuer || !config.clientId || !config.clientSecret) {
513
+ throw new ConfigurationError("Publishing a manifest needs issuer, clientId and clientSecret.");
514
+ }
515
+ const timeoutMs = config.timeoutMs ?? 1e4;
516
+ const manifest = await buildManifest(declaration);
517
+ const discovery = new Discovery(config.issuer, timeoutMs, 36e5);
518
+ const token = await mintToken(config, discovery, timeoutMs);
519
+ const response = await fetchWithTimeout(
520
+ `${config.issuer.replace(/\/$/, "")}/api/v1/apps/manifest`,
521
+ {
522
+ method: "POST",
523
+ headers: {
524
+ authorization: `Bearer ${token}`,
525
+ accept: "application/json",
526
+ "content-type": "application/json"
527
+ },
528
+ body: JSON.stringify(manifest)
529
+ },
530
+ timeoutMs
531
+ );
532
+ if (!response.ok) {
533
+ throw new AuthenticationError(`Manifest push failed: HTTP ${response.status} ${await response.text()}`);
534
+ }
535
+ const json = await response.json();
536
+ return json !== null && typeof json === "object" ? json : {};
537
+ }
538
+ async function mintToken(config, discovery, timeoutMs) {
539
+ const response = await fetchWithTimeout(
540
+ await discovery.endpoint("token_endpoint"),
541
+ {
542
+ method: "POST",
543
+ headers: { "content-type": "application/x-www-form-urlencoded" },
544
+ body: new URLSearchParams({
545
+ grant_type: "client_credentials",
546
+ client_id: config.clientId,
547
+ client_secret: config.clientSecret,
548
+ scope: "apps.manifest"
549
+ })
550
+ },
551
+ timeoutMs
552
+ );
553
+ const json = await response.json().catch(() => ({}));
554
+ if (typeof json.access_token !== "string" || json.access_token === "") {
555
+ throw new AuthenticationError(
556
+ "Could not obtain an apps.manifest access token \u2014 check the client credentials and that the client holds the apps.manifest scope."
557
+ );
558
+ }
559
+ return json.access_token;
560
+ }
561
+ function assertDeclaration(permissions, roles) {
562
+ const permissionKeys = /* @__PURE__ */ new Set();
563
+ for (const permission of permissions) {
564
+ if (!permission.key) {
565
+ throw new ConfigurationError("Every permission needs a non-empty `key`.");
566
+ }
567
+ if (permissionKeys.has(permission.key)) {
568
+ throw new ConfigurationError(`Permission "${permission.key}" is declared more than once.`);
569
+ }
570
+ permissionKeys.add(permission.key);
571
+ }
572
+ const roleKeys = /* @__PURE__ */ new Set();
573
+ for (const role of roles) {
574
+ if (!role.key) {
575
+ throw new ConfigurationError("Every role needs a non-empty `key`.");
576
+ }
577
+ if (!role.name) {
578
+ throw new ConfigurationError(`Role "${role.key}" needs a non-empty \`name\`.`);
579
+ }
580
+ if (roleKeys.has(role.key)) {
581
+ throw new ConfigurationError(`Role "${role.key}" is declared more than once.`);
582
+ }
583
+ roleKeys.add(role.key);
584
+ for (const reference of role.permissions) {
585
+ if (!permissionKeys.has(reference)) {
586
+ throw new ConfigurationError(
587
+ `Role "${role.key}" references permission "${reference}", which is not declared.`
588
+ );
589
+ }
590
+ }
591
+ }
592
+ }
593
+ function canonicalPermission(permission) {
594
+ return permission.description === void 0 ? { key: permission.key } : { key: permission.key, description: permission.description };
595
+ }
596
+ function canonicalRole(role) {
597
+ const permissions = [...role.permissions].sort((a, b) => a.localeCompare(b));
598
+ return role.description === void 0 ? { key: role.key, name: role.name, permissions } : { key: role.key, name: role.name, description: role.description, permissions };
599
+ }
600
+ async function sha256Hex(input) {
601
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
602
+ return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
603
+ }
604
+ async function fetchWithTimeout(url, init, timeoutMs) {
605
+ const controller = new AbortController();
606
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
607
+ try {
608
+ return await fetch(url, { ...init, signal: controller.signal });
609
+ } finally {
610
+ clearTimeout(timer);
611
+ }
612
+ }
613
+
495
614
  exports.AuthenticationError = AuthenticationError;
496
615
  exports.CboxIdClient = CboxIdClient;
497
616
  exports.CboxIdError = CboxIdError;
498
617
  exports.ConfigurationError = ConfigurationError;
499
618
  exports.InvalidStateError = InvalidStateError;
500
619
  exports.VaultClient = VaultClient;
620
+ exports.buildManifest = buildManifest;
501
621
  exports.challenge = challenge;
502
622
  exports.createVerifier = createVerifier;
623
+ exports.defineAuthz = defineAuthz;
624
+ exports.publishManifest = publishManifest;
503
625
  exports.randomToken = randomToken;
504
626
  exports.verifyWebhook = verifyWebhook;
505
627
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/discovery.ts","../src/pkce.ts","../src/vault.ts","../src/webhook.ts","../src/client.ts"],"names":["key","createRemoteJWKSet","jwtVerify"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Base class for every error this SDK throws, so callers can `catch (e) { if (e\n * instanceof CboxIdError) ... }` in one branch.\n */\nexport class CboxIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The client is misconfigured (a required option is missing or empty). */\nexport class ConfigurationError extends CboxIdError {}\n\n/**\n * The login `state` did not match what was stored — the callback is forged or\n * stale. Treat as a fresh start, not an error to surface to the user.\n */\nexport class InvalidStateError extends CboxIdError {}\n\n/**\n * Login could not be completed: the provider returned an error, the callback was\n * missing a code, or a token / id_token failed verification.\n */\nexport class AuthenticationError extends CboxIdError {}\n","import { AuthenticationError, ConfigurationError } from './errors.js';\nimport type { DiscoveryDocument } from './types.js';\n\n/**\n * Fetches and caches an instance's OIDC discovery document. One instance of this\n * lives per {@link CboxIdClient}; the document is refetched only after the TTL.\n */\nexport class Discovery {\n private cached: { doc: DiscoveryDocument; expiresAt: number } | null = null;\n\n constructor(\n private readonly issuer: string,\n private readonly timeoutMs: number,\n private readonly cacheTtlMs: number,\n private readonly now: () => number = Date.now,\n ) {}\n\n async document(): Promise<DiscoveryDocument> {\n if (this.cached && this.cached.expiresAt > this.now()) {\n return this.cached.doc;\n }\n\n const url = `${this.issuer.replace(/\\/$/, '')}/.well-known/openid-configuration`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n let doc: DiscoveryDocument;\n try {\n const response = await fetch(url, { signal: controller.signal });\n if (!response.ok) {\n throw new AuthenticationError(`Discovery request failed with status ${response.status}.`);\n }\n doc = (await response.json()) as DiscoveryDocument;\n } catch (error) {\n if (error instanceof AuthenticationError) {\n throw error;\n }\n throw new AuthenticationError(`Discovery request failed: ${String(error)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (typeof doc.issuer !== 'string' || doc.issuer === '') {\n throw new AuthenticationError('The discovery document was missing an issuer.');\n }\n\n this.cached = { doc, expiresAt: this.now() + this.cacheTtlMs };\n return doc;\n }\n\n /** A required endpoint from the discovery document. */\n async endpoint(name: keyof DiscoveryDocument): Promise<string> {\n const value = (await this.document())[name];\n if (typeof value !== 'string' || value === '') {\n throw new ConfigurationError(`The instance does not advertise a ${name}.`);\n }\n return value;\n }\n\n /** An optional endpoint, or null when the instance advertises none. */\n async optionalEndpoint(name: keyof DiscoveryDocument): Promise<string | null> {\n const value = (await this.document())[name];\n return typeof value === 'string' && value !== '' ? value : null;\n }\n}\n","/**\n * PKCE (RFC 7636) and the random values the login flow needs, built on Web Crypto\n * (`globalThis.crypto`) so the same code runs on Node, edge runtimes and browsers.\n */\n\nfunction base64url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** A URL-safe random token of `bytes` bytes (default 32), for state and nonce. */\nexport function randomToken(bytes = 32): string {\n return base64url(crypto.getRandomValues(new Uint8Array(bytes)));\n}\n\n/** A high-entropy PKCE code verifier. */\nexport function createVerifier(): string {\n return randomToken(32);\n}\n\n/** The S256 code challenge for a verifier. */\nexport async function challenge(verifier: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n return base64url(new Uint8Array(digest));\n}\n","import { AuthenticationError } from './errors.js';\n\n/** A stored vault secret's metadata (never its plaintext). */\nexport interface VaultSecretRef {\n id: string;\n name: string;\n provider: string;\n ownerType: string | null;\n ownerId: string | null;\n expiresAt: string | null;\n revoked: boolean;\n}\n\n/** A brokered credential — the plaintext, for immediate use. */\nexport interface VaultLease {\n secretId: string;\n provider: string;\n secret: string;\n expiresAt: string;\n}\n\nexport interface StoreSecretInput {\n name: string;\n provider: string;\n secret: string;\n ownerType?: 'organization' | 'user';\n ownerId?: string;\n expiresAt?: string;\n}\n\n/**\n * Client for a Cbox ID instance's Token Vault API. Bind it to an access token\n * (obtain one with {@link CboxIdClient.machineToken}, scoped `vault.manage` for\n * provisioning or `vault.lease` for redeeming). All calls are server-to-server.\n */\nexport class VaultClient {\n private readonly base: string;\n\n constructor(\n issuer: string,\n private readonly token: string,\n private readonly timeoutMs = 10_000,\n ) {\n this.base = `${issuer.replace(/\\/$/, '')}/api/v1/vault`;\n }\n\n /** Ingest a downstream credential, sealed at rest (scope `vault.manage`). */\n store(input: StoreSecretInput): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', '/secrets', {\n name: input.name,\n provider: input.provider,\n secret: input.secret,\n owner_type: input.ownerType,\n owner_id: input.ownerId,\n expires_at: input.expiresAt,\n });\n }\n\n /** Rotate a secret's value, keeping its id and grants (scope `vault.manage`). */\n rotate(secretId: string, secret: string): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', `/secrets/${encodeURIComponent(secretId)}/rotate`, { secret });\n }\n\n /** Revoke a secret permanently (scope `vault.manage`). */\n async revoke(secretId: string): Promise<void> {\n await this.request('DELETE', `/secrets/${encodeURIComponent(secretId)}`);\n }\n\n /** Authorize an agent client to lease a secret (scope `vault.manage`). */\n grant(\n secretId: string,\n clientId: string,\n maxTtlSeconds?: number,\n ): Promise<{ secretId: string; clientId: string; maxTtlSeconds: number | null }> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/grants`, {\n client_id: clientId,\n max_ttl_seconds: maxTtlSeconds,\n }).then((raw) => {\n const r = raw as { secret_id: string; client_id: string; max_ttl_seconds: number | null };\n return { secretId: r.secret_id, clientId: r.client_id, maxTtlSeconds: r.max_ttl_seconds };\n });\n }\n\n /** Revoke an agent's authorization (scope `vault.manage`). */\n async revokeGrant(secretId: string, clientId: string): Promise<void> {\n await this.request(\n 'DELETE',\n `/secrets/${encodeURIComponent(secretId)}/grants/${encodeURIComponent(clientId)}`,\n );\n }\n\n /**\n * Redeem a leased credential for immediate use (scope `vault.lease`). The caller\n * is identified by the token's client; a lease with no live grant is refused.\n */\n lease(secretId: string, purpose: string): Promise<VaultLease> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/lease`, { purpose }).then((raw) => {\n const r = raw as { secret_id: string; provider: string; secret: string; expires_at: string };\n return { secretId: r.secret_id, provider: r.provider, secret: r.secret, expiresAt: r.expires_at };\n });\n }\n\n private async json<T>(method: string, path: string, body: Record<string, unknown>): Promise<T> {\n const response = await this.request(method, path, body);\n return (await response.json()) as T;\n }\n\n private async request(method: string, path: string, body?: Record<string, unknown>): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const init: RequestInit = {\n method,\n headers: {\n authorization: `Bearer ${this.token}`,\n ...(body ? { 'content-type': 'application/json' } : {}),\n },\n signal: controller.signal,\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n const response = await fetch(`${this.base}${path}`, init);\n if (!response.ok) {\n throw new AuthenticationError(`Vault ${method} ${path} failed with status ${response.status}.`);\n }\n return response;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","/**\n * Verify a Cbox ID webhook / inline-action signature. The header is\n * `X-Cbox-Signature: t={unix},v1={hex hmac}` — an HMAC-SHA256 over\n * `\"{timestamp}.{raw body}\"`, valid within a freshness window. Built on Web Crypto\n * so it runs on Node, edge and the browser.\n */\n\n/** Constant-time compare of two hex strings. */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n\nfunction toHex(bytes: ArrayBuffer): string {\n return Array.from(new Uint8Array(bytes))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport interface VerifyWebhookOptions {\n /** The RAW request body — the exact bytes received, not a re-encoded copy. */\n payload: string;\n /** The value of the `X-Cbox-Signature` header. */\n signatureHeader: string | null | undefined;\n /** The signing secret issued when the webhook/action endpoint was registered. */\n secret: string;\n /** Freshness window in seconds. Defaults to 300 (5 minutes). */\n toleranceSeconds?: number;\n /** Injectable clock (unix seconds), for tests. Defaults to `Date.now()`. */\n now?: number;\n}\n\n/** Returns `true` only when the signature is present, fresh and valid. Never throws. */\nexport async function verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n const { payload, signatureHeader, secret } = options;\n const toleranceSeconds = options.toleranceSeconds ?? 300;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n if (!signatureHeader) {\n return false;\n }\n\n const parts: Record<string, string> = {};\n for (const segment of signatureHeader.split(',')) {\n const [key, value] = segment.trim().split('=', 2);\n if (key) {\n parts[key] = value ?? '';\n }\n }\n\n const timestamp = parts['t'] ?? '';\n const signature = parts['v1'] ?? '';\n\n if (timestamp === '' || signature === '' || !/^\\d+$/.test(timestamp)) {\n return false;\n }\n\n if (Math.abs(now - Number(timestamp)) > toleranceSeconds) {\n return false;\n }\n\n const key = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const expected = toHex(\n await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`${timestamp}.${payload}`)),\n );\n\n return timingSafeEqual(expected, signature);\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport { Discovery } from './discovery.js';\nimport { AuthenticationError, ConfigurationError, InvalidStateError } from './errors.js';\nimport { challenge, createVerifier, randomToken } from './pkce.js';\nimport type {\n AuthorizationRequest,\n CboxIdConfig,\n CboxUser,\n TokenResponse,\n} from './types.js';\nimport { VaultClient } from './vault.js';\nimport { verifyWebhook, type VerifyWebhookOptions } from './webhook.js';\n\ntype JwksResolver = ReturnType<typeof createRemoteJWKSet>;\n\n/** Query parameters as they arrive on your callback route. */\nexport interface CallbackParams {\n code?: string | null;\n state?: string | null;\n error?: string | null;\n error_description?: string | null;\n}\n\n/** The values you persisted from {@link CboxIdClient.createAuthorizationRequest}. */\nexport interface StoredAuthState {\n state: string;\n codeVerifier: string;\n nonce: string;\n}\n\n/**\n * Turnkey Cbox ID client for JavaScript/TypeScript. It speaks standard OpenID\n * Connect against a Cbox ID instance — so integrating is a redirect and a callback,\n * not a rewrite — and adds the conveniences a hosted-identity product needs: a\n * redirect to the instance's hosted profile page, and back-channel helpers (machine\n * tokens, userinfo, introspection, webhook verification).\n *\n * Login is hardened by default: PKCE (S256), a CSRF state check, a nonce, and full\n * id_token signature + issuer + audience verification against the instance's JWKS\n * (via `jose`).\n *\n * The class is framework-agnostic: {@link createAuthorizationRequest} hands you the\n * `state`, `codeVerifier` and `nonce` to persist however you like, and\n * {@link authenticate} takes them back. For Next.js, the `@cboxdk/id-js/nextjs`\n * entry wires this to cookies for you.\n */\nexport class CboxIdClient {\n private readonly discovery: Discovery;\n private readonly jwksByUri = new Map<string, JwksResolver>();\n\n constructor(private readonly config: CboxIdConfig) {\n if (!config.issuer) {\n throw new ConfigurationError('Cbox ID config `issuer` is required.');\n }\n if (!config.clientId) {\n throw new ConfigurationError('Cbox ID config `clientId` is required.');\n }\n if (!config.redirectUri) {\n throw new ConfigurationError('Cbox ID config `redirectUri` is required.');\n }\n this.discovery = new Discovery(\n config.issuer,\n config.timeoutMs ?? 10_000,\n config.cacheTtlMs ?? 3_600_000,\n );\n }\n\n /**\n * Begin login. Returns the authorize URL plus the `state`, `codeVerifier` and\n * `nonce` — persist those (signed, httpOnly cookies are ideal) and hand them back\n * to {@link authenticate} on the callback.\n */\n async createAuthorizationRequest(options: {\n scopes?: string[];\n redirectUri?: string;\n state?: string;\n prompt?: string;\n loginHint?: string;\n maxAge?: number;\n } = {}): Promise<AuthorizationRequest> {\n const codeVerifier = createVerifier();\n const state = options.state ?? randomToken(16);\n const nonce = randomToken(16);\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: this.config.clientId,\n redirect_uri: options.redirectUri ?? this.config.redirectUri,\n scope: (options.scopes ?? this.scopes()).join(' '),\n state,\n nonce,\n code_challenge: await challenge(codeVerifier),\n code_challenge_method: 'S256',\n });\n if (options.prompt) {\n params.set('prompt', options.prompt);\n }\n if (options.loginHint) {\n params.set('login_hint', options.loginHint);\n }\n if (typeof options.maxAge === 'number') {\n params.set('max_age', String(options.maxAge));\n }\n\n const endpoint = await this.discovery.endpoint('authorization_endpoint');\n return { url: `${endpoint}?${params.toString()}`, state, codeVerifier, nonce };\n }\n\n /**\n * Complete login on your callback route: verify state, exchange the code with the\n * PKCE verifier, verify the id_token, and return the authenticated user.\n *\n * @throws InvalidStateError when state does not match (forged/stale request)\n * @throws AuthenticationError on any other failure\n */\n async authenticate(input: {\n params: CallbackParams;\n stored: StoredAuthState;\n redirectUri?: string;\n }): Promise<CboxUser> {\n const { params, stored } = input;\n\n if (!params.state || !stored.state || !timingSafeEqualString(params.state, stored.state)) {\n throw new InvalidStateError('The login state did not match — the request may be forged or stale.');\n }\n\n if (params.error) {\n throw new AuthenticationError(\n `Cbox ID returned an error: ${params.error}${params.error_description ? ` (${params.error_description})` : ''}`,\n );\n }\n\n if (!params.code) {\n throw new AuthenticationError('The callback was missing an authorization code.');\n }\n\n const tokens = await this.exchange(params.code, stored.codeVerifier, input.redirectUri);\n\n if (!tokens.access_token) {\n throw new AuthenticationError('No access token was returned.');\n }\n\n let claims: Record<string, unknown> = {};\n if (tokens.id_token) {\n claims = await this.verifyIdToken(tokens.id_token, stored.nonce);\n }\n // Enrich with userinfo (email/name/org a minimal id_token may omit).\n claims = { ...claims, ...(await this.userinfo(tokens.access_token)) };\n\n const sub = claims['sub'];\n if (typeof sub !== 'string' || sub === '') {\n throw new AuthenticationError('The verified token carried no subject.');\n }\n\n return {\n id: sub,\n email: typeof claims['email'] === 'string' ? claims['email'] : null,\n name: typeof claims['name'] === 'string' ? claims['name'] : null,\n organizationId: typeof claims['org'] === 'string' ? claims['org'] : null,\n claims,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? null,\n idToken: tokens.id_token ?? null,\n expiresIn: typeof tokens.expires_in === 'number' ? tokens.expires_in : 0,\n };\n }\n\n /**\n * The URL of the instance's hosted account/profile page (self-service password,\n * MFA, passkeys, sessions). A signed-in user is authenticated there by their Cbox\n * ID session; `returnTo` is passed so the page can link back to your app.\n */\n profileUrl(returnTo?: string): string {\n const base = `${this.config.issuer.replace(/\\/$/, '')}${this.accountPath()}`;\n return returnTo ? `${base}?${new URLSearchParams({ return_to: returnTo }).toString()}` : base;\n }\n\n /** The RP-initiated logout URL, or null when the instance advertises none. */\n async logoutUrl(returnTo?: string): Promise<string | null> {\n const endpoint = await this.discovery.optionalEndpoint('end_session_endpoint');\n if (!endpoint) {\n return null;\n }\n return returnTo\n ? `${endpoint}?${new URLSearchParams({ post_logout_redirect_uri: returnTo }).toString()}`\n : endpoint;\n }\n\n /**\n * A machine (client-credentials) access token for calling Cbox ID APIs as your\n * app, not on a user's behalf. Requires a client secret.\n */\n async machineToken(options: { scopes?: string[]; resource?: string } = {}): Promise<string> {\n const body = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.config.clientId,\n client_secret: this.requireSecret(),\n });\n if (options.scopes && options.scopes.length > 0) {\n body.set('scope', options.scopes.join(' '));\n }\n if (options.resource) {\n body.set('resource', options.resource);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Machine token request failed: ${await response.text()}`);\n }\n const json = (await response.json()) as { access_token?: unknown };\n if (typeof json.access_token !== 'string') {\n throw new AuthenticationError('The token response had no access_token.');\n }\n return json.access_token;\n }\n\n /** The OIDC userinfo claims for an access token. */\n async userinfo(accessToken: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.optionalEndpoint('userinfo_endpoint');\n if (!endpoint) {\n return {};\n }\n const response = await this.fetchWithTimeout(endpoint, {\n headers: { authorization: `Bearer ${accessToken}` },\n });\n if (!response.ok) {\n throw new AuthenticationError('Userinfo request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /**\n * RFC 7662 token introspection (confidential-client auth). Returns the raw\n * response; `active` tells you if the token is currently valid. Requires a secret.\n */\n async introspect(token: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.endpoint('introspection_endpoint');\n const basic = btoa(`${this.config.clientId}:${this.requireSecret()}`);\n const response = await this.post(\n endpoint,\n new URLSearchParams({ token }),\n { authorization: `Basic ${basic}` },\n );\n if (!response.ok) {\n throw new AuthenticationError('Introspection request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /** Verify a Cbox ID webhook / inline-action signature. See {@link verifyWebhook}. */\n verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n return verifyWebhook(options);\n }\n\n /**\n * A Token Vault client bound to an access token. Obtain the token with\n * {@link machineToken} (scope `vault.manage` to provision/grant, `vault.lease` to\n * redeem), then call `store` / `grant` / `lease` etc.\n */\n vault(accessToken: string): VaultClient {\n return new VaultClient(this.config.issuer, accessToken, this.config.timeoutMs ?? 10_000);\n }\n\n private async exchange(code: string, verifier: string, redirectUri?: string): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri ?? this.config.redirectUri,\n client_id: this.config.clientId,\n code_verifier: verifier,\n });\n if (this.config.clientSecret) {\n body.set('client_secret', this.config.clientSecret);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Token exchange failed: ${await response.text()}`);\n }\n return (await response.json()) as TokenResponse;\n }\n\n private async verifyIdToken(idToken: string, nonce: string): Promise<Record<string, unknown>> {\n const jwksUri = await this.discovery.endpoint('jwks_uri');\n let resolver = this.jwksByUri.get(jwksUri);\n if (!resolver) {\n resolver = createRemoteJWKSet(new URL(jwksUri));\n this.jwksByUri.set(jwksUri, resolver);\n }\n\n let payload: JWTPayload;\n try {\n ({ payload } = await jwtVerify(idToken, resolver, {\n issuer: this.config.issuer,\n audience: this.config.clientId,\n }));\n } catch (error) {\n throw new AuthenticationError(`The id_token could not be verified: ${String(error)}`);\n }\n\n if (nonce && payload['nonce'] !== nonce) {\n throw new AuthenticationError('The id_token nonce did not match — possible replay.');\n }\n\n return payload as Record<string, unknown>;\n }\n\n private scopes(): string[] {\n const scopes = this.config.scopes;\n return scopes && scopes.length > 0 ? scopes : ['openid', 'profile', 'email'];\n }\n\n private accountPath(): string {\n const path = this.config.accountPath;\n return path && path !== '' ? `/${path.replace(/^\\//, '')}` : '/settings';\n }\n\n private requireSecret(): string {\n if (!this.config.clientSecret) {\n throw new ConfigurationError('This call requires a `clientSecret`, but none is configured.');\n }\n return this.config.clientSecret;\n }\n\n private post(url: string, body: URLSearchParams, headers: Record<string, string> = {}): Promise<Response> {\n return this.fetchWithTimeout(url, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', ...headers },\n body,\n });\n }\n\n private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs ?? 10_000);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/** Constant-time string compare, so state validation doesn't leak via timing. */\nfunction timingSafeEqualString(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/discovery.ts","../src/pkce.ts","../src/vault.ts","../src/webhook.ts","../src/client.ts","../src/authz.ts"],"names":["key","createRemoteJWKSet","jwtVerify"],"mappings":";;;;;;;AAIO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA,EACrC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,OAAO,GAAA,CAAA,MAAA,CAAW,IAAA;AAAA,EACzB;AACF;AAGO,IAAM,kBAAA,GAAN,cAAiC,WAAA,CAAY;AAAC;AAM9C,IAAM,iBAAA,GAAN,cAAgC,WAAA,CAAY;AAAC;AAM7C,IAAM,mBAAA,GAAN,cAAkC,WAAA,CAAY;AAAC;;;ACjB/C,IAAM,YAAN,MAAgB;AAAA,EAGrB,YACmB,MAAA,EACA,SAAA,EACA,UAAA,EACA,GAAA,GAAoB,KAAK,GAAA,EAC1C;AAJiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AAAA,EAChB;AAAA,EAJgB,MAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,GAAA;AAAA,EANX,MAAA,GAA+D,IAAA;AAAA,EASvE,MAAM,QAAA,GAAuC;AAC3C,IAAA,IAAI,KAAK,MAAA,IAAU,IAAA,CAAK,OAAO,SAAA,GAAY,IAAA,CAAK,KAAI,EAAG;AACrD,MAAA,OAAO,KAAK,MAAA,CAAO,GAAA;AAAA,IACrB;AAEA,IAAA,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,OAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,iCAAA,CAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AAEjE,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,MAAA,EAAQ,UAAA,CAAW,QAAQ,CAAA;AAC/D,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,qCAAA,EAAwC,QAAA,CAAS,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,MAC1F;AACA,MAAA,GAAA,GAAO,MAAM,SAAS,IAAA,EAAK;AAAA,IAC7B,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,iBAAiB,mBAAA,EAAqB;AACxC,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,0BAAA,EAA6B,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IAC5E,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAEA,IAAA,IAAI,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,IAAY,GAAA,CAAI,WAAW,EAAA,EAAI;AACvD,MAAA,MAAM,IAAI,oBAAoB,+CAA+C,CAAA;AAAA,IAC/E;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,EAAE,GAAA,EAAK,SAAA,EAAW,KAAK,GAAA,EAAI,GAAI,KAAK,UAAA,EAAW;AAC7D,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,SAAS,IAAA,EAAgD;AAC7D,IAAA,MAAM,KAAA,GAAA,CAAS,MAAM,IAAA,CAAK,QAAA,IAAY,IAAI,CAAA;AAC1C,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,EAAA,EAAI;AAC7C,MAAA,MAAM,IAAI,kBAAA,CAAmB,CAAA,kCAAA,EAAqC,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,IAC3E;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,iBAAiB,IAAA,EAAuD;AAC5E,IAAA,MAAM,KAAA,GAAA,CAAS,MAAM,IAAA,CAAK,QAAA,IAAY,IAAI,CAAA;AAC1C,IAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,KAAK,KAAA,GAAQ,IAAA;AAAA,EAC7D;AACF,CAAA;;;AC3DA,SAAS,UAAU,KAAA,EAA2B;AAC5C,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAA,IAAU,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC/E;AAGO,SAAS,WAAA,CAAY,QAAQ,EAAA,EAAY;AAC9C,EAAA,OAAO,UAAU,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA;AAChE;AAGO,SAAS,cAAA,GAAyB;AACvC,EAAA,OAAO,YAAY,EAAE,CAAA;AACvB;AAGA,eAAsB,UAAU,QAAA,EAAmC;AACjE,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,QAAQ,CAAC,CAAA;AACvF,EAAA,OAAO,SAAA,CAAU,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA;AACzC;;;ACQO,IAAM,cAAN,MAAkB;AAAA,EAGvB,WAAA,CACE,MAAA,EACiB,KAAA,EACA,SAAA,GAAY,GAAA,EAC7B;AAFiB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAEjB,IAAA,IAAA,CAAK,OAAO,CAAA,EAAG,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,aAAA,CAAA;AAAA,EAC1C;AAAA,EAJmB,KAAA;AAAA,EACA,SAAA;AAAA,EALF,IAAA;AAAA;AAAA,EAWjB,MAAM,KAAA,EAAkD;AACtD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAqB,MAAA,EAAQ,UAAA,EAAY;AAAA,MACnD,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,YAAY,KAAA,CAAM,SAAA;AAAA,MAClB,UAAU,KAAA,CAAM,OAAA;AAAA,MAChB,YAAY,KAAA,CAAM;AAAA,KACnB,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,UAAkB,MAAA,EAAyC;AAChE,IAAA,OAAO,IAAA,CAAK,IAAA,CAAqB,MAAA,EAAQ,CAAA,SAAA,EAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,OAAA,CAAA,EAAW,EAAE,MAAA,EAAQ,CAAA;AAAA,EACxG;AAAA;AAAA,EAGA,MAAM,OAAO,QAAA,EAAiC;AAC5C,IAAA,MAAM,KAAK,OAAA,CAAQ,QAAA,EAAU,YAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,EACzE;AAAA;AAAA,EAGA,KAAA,CACE,QAAA,EACA,QAAA,EACA,aAAA,EAC+E;AAC/E,IAAA,OAAO,KAAK,IAAA,CAAK,MAAA,EAAQ,YAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,OAAA,CAAA,EAAW;AAAA,MAC1E,SAAA,EAAW,QAAA;AAAA,MACX,eAAA,EAAiB;AAAA,KAClB,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACf,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,OAAO,EAAE,UAAU,CAAA,CAAE,SAAA,EAAW,UAAU,CAAA,CAAE,SAAA,EAAW,aAAA,EAAe,CAAA,CAAE,eAAA,EAAgB;AAAA,IAC1F,CAAC,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,QAAA,EAAkB,QAAA,EAAiC;AACnE,IAAA,MAAM,IAAA,CAAK,OAAA;AAAA,MACT,QAAA;AAAA,MACA,YAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,QAAA,EAAW,kBAAA,CAAmB,QAAQ,CAAC,CAAA;AAAA,KACjF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAA,CAAM,UAAkB,OAAA,EAAsC;AAC5D,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAA,SAAA,EAAY,mBAAmB,QAAQ,CAAC,CAAA,MAAA,CAAA,EAAU,EAAE,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACpG,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,OAAO,EAAE,QAAA,EAAU,CAAA,CAAE,SAAA,EAAW,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,SAAA,EAAW,CAAA,CAAE,UAAA,EAAW;AAAA,IAClG,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,IAAA,CAAQ,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA2C;AAC7F,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,MAAM,IAAI,CAAA;AACtD,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA,EAEA,MAAc,OAAA,CAAQ,MAAA,EAAgB,IAAA,EAAc,IAAA,EAAmD;AACrG,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AACjE,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAoB;AAAA,QACxB,MAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AAAA,UACnC,GAAI,IAAA,GAAO,EAAE,cAAA,EAAgB,kBAAA,KAAuB;AAAC,SACvD;AAAA,QACA,QAAQ,UAAA,CAAW;AAAA,OACrB;AACA,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,MACjC;AACA,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,IAAI,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA;AACxD,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,IAAI,oBAAoB,CAAA,MAAA,EAAS,MAAM,IAAI,IAAI,CAAA,oBAAA,EAAuB,QAAA,CAAS,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,MAChG;AACA,MAAA,OAAO,QAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AACF;;;AC3HA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAoB;AACtD,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,QAAA,IAAY,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC9C;AACA,EAAA,OAAO,QAAA,KAAa,CAAA;AACtB;AAEA,SAAS,MAAM,KAAA,EAA4B;AACzC,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,KAAK,CAAC,CAAA,CACpC,IAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AACZ;AAgBA,eAAsB,cAAc,OAAA,EAAiD;AACnF,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,EAAiB,MAAA,EAAO,GAAI,OAAA;AAC7C,EAAA,MAAM,gBAAA,GAAmB,QAAQ,gBAAA,IAAoB,GAAA;AACrD,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,IAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAEvD,EAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAgC,EAAC;AACvC,EAAA,KAAA,MAAW,OAAA,IAAW,eAAA,CAAgB,KAAA,CAAM,GAAG,CAAA,EAAG;AAChD,IAAA,MAAM,CAACA,MAAK,KAAK,CAAA,GAAI,QAAQ,IAAA,EAAK,CAAE,KAAA,CAAM,GAAA,EAAK,CAAC,CAAA;AAChD,IAAA,IAAIA,IAAAA,EAAK;AACP,MAAA,KAAA,CAAMA,IAAG,IAAI,KAAA,IAAS,EAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,GAAG,CAAA,IAAK,EAAA;AAChC,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAI,CAAA,IAAK,EAAA;AAEjC,EAAA,IAAI,SAAA,KAAc,MAAM,SAAA,KAAc,EAAA,IAAM,CAAC,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA,EAAG;AACpE,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAK,GAAA,CAAI,GAAA,GAAM,OAAO,SAAS,CAAC,IAAI,gBAAA,EAAkB;AACxD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA;AAAA,IAC9B,KAAA;AAAA,IACA,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,MAAM,CAAA;AAAA,IAC/B,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,KAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AACA,EAAA,MAAM,QAAA,GAAW,KAAA;AAAA,IACf,MAAM,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,QAAQ,GAAA,EAAK,IAAI,WAAA,EAAY,CAAE,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,OAAO,EAAE,CAAC;AAAA,GAC3F;AAEA,EAAA,OAAO,eAAA,CAAgB,UAAU,SAAS,CAAA;AAC5C;;;ACjCO,IAAM,eAAN,MAAmB;AAAA,EAIxB,YAA6B,MAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAC3B,IAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,MAAA,MAAM,IAAI,mBAAmB,sCAAsC,CAAA;AAAA,IACrE;AACA,IAAA,IAAI,CAAC,OAAO,QAAA,EAAU;AACpB,MAAA,MAAM,IAAI,mBAAmB,wCAAwC,CAAA;AAAA,IACvE;AACA,IAAA,IAAI,CAAC,OAAO,WAAA,EAAa;AACvB,MAAA,MAAM,IAAI,mBAAmB,2CAA2C,CAAA;AAAA,IAC1E;AACA,IAAA,IAAA,CAAK,YAAY,IAAI,SAAA;AAAA,MACnB,MAAA,CAAO,MAAA;AAAA,MACP,OAAO,SAAA,IAAa,GAAA;AAAA,MACpB,OAAO,UAAA,IAAc;AAAA,KACvB;AAAA,EACF;AAAA,EAf6B,MAAA;AAAA,EAHZ,SAAA;AAAA,EACA,SAAA,uBAAgB,GAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwB3D,MAAM,0BAAA,CAA2B,OAAA,GAO7B,EAAC,EAAkC;AACrC,IAAA,MAAM,eAAe,cAAA,EAAe;AACpC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,WAAA,CAAY,EAAE,CAAA;AAC7C,IAAA,MAAM,KAAA,GAAQ,YAAY,EAAE,CAAA;AAE5B,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,MACjC,aAAA,EAAe,MAAA;AAAA,MACf,SAAA,EAAW,KAAK,MAAA,CAAO,QAAA;AAAA,MACvB,YAAA,EAAc,OAAA,CAAQ,WAAA,IAAe,IAAA,CAAK,MAAA,CAAO,WAAA;AAAA,MACjD,QAAQ,OAAA,CAAQ,MAAA,IAAU,KAAK,MAAA,EAAO,EAAG,KAAK,GAAG,CAAA;AAAA,MACjD,KAAA;AAAA,MACA,KAAA;AAAA,MACA,cAAA,EAAgB,MAAM,SAAA,CAAU,YAAY,CAAA;AAAA,MAC5C,qBAAA,EAAuB;AAAA,KACxB,CAAA;AACD,IAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,MAAA,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAAA,IACrC;AACA,IAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,MAAA,MAAA,CAAO,GAAA,CAAI,YAAA,EAAc,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC5C;AACA,IAAA,IAAI,OAAO,OAAA,CAAQ,MAAA,KAAW,QAAA,EAAU;AACtC,MAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,wBAAwB,CAAA;AACvE,IAAA,OAAO,EAAE,GAAA,EAAK,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,EAAI,KAAA,EAAO,YAAA,EAAc,KAAA,EAAM;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,KAAA,EAIG;AACpB,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,KAAA;AAE3B,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,qBAAA,CAAsB,MAAA,CAAO,KAAA,EAAO,MAAA,CAAO,KAAK,CAAA,EAAG;AACxF,MAAA,MAAM,IAAI,kBAAkB,0EAAqE,CAAA;AAAA,IACnG;AAEA,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,CAAA,2BAAA,EAA8B,MAAA,CAAO,KAAK,CAAA,EAAG,MAAA,CAAO,oBAAoB,CAAA,EAAA,EAAK,MAAA,CAAO,iBAAiB,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA;AAAA,OAC/G;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,MAAA,MAAM,IAAI,oBAAoB,iDAAiD,CAAA;AAAA,IACjF;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,QAAA,CAAS,OAAO,IAAA,EAAM,MAAA,CAAO,YAAA,EAAc,KAAA,CAAM,WAAW,CAAA;AAEtF,IAAA,IAAI,CAAC,OAAO,YAAA,EAAc;AACxB,MAAA,MAAM,IAAI,oBAAoB,+BAA+B,CAAA;AAAA,IAC/D;AAEA,IAAA,IAAI,SAAkC,EAAC;AACvC,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAA,GAAS,MAAM,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,QAAA,EAAU,OAAO,KAAK,CAAA;AAAA,IACjE;AAEA,IAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,GAAI,MAAM,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,YAAY,CAAA,EAAG;AAEpE,IAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,EAAA,EAAI;AACzC,MAAA,MAAM,IAAI,oBAAoB,wCAAwC,CAAA;AAAA,IACxE;AAEA,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,GAAA;AAAA,MACJ,KAAA,EAAO,OAAO,MAAA,CAAO,OAAO,MAAM,QAAA,GAAW,MAAA,CAAO,OAAO,CAAA,GAAI,IAAA;AAAA,MAC/D,IAAA,EAAM,OAAO,MAAA,CAAO,MAAM,MAAM,QAAA,GAAW,MAAA,CAAO,MAAM,CAAA,GAAI,IAAA;AAAA,MAC5D,cAAA,EAAgB,OAAO,MAAA,CAAO,KAAK,MAAM,QAAA,GAAW,MAAA,CAAO,KAAK,CAAA,GAAI,IAAA;AAAA,MACpE,MAAA;AAAA,MACA,aAAa,MAAA,CAAO,YAAA;AAAA,MACpB,YAAA,EAAc,OAAO,aAAA,IAAiB,IAAA;AAAA,MACtC,OAAA,EAAS,OAAO,QAAA,IAAY,IAAA;AAAA,MAC5B,WAAW,OAAO,MAAA,CAAO,UAAA,KAAe,QAAA,GAAW,OAAO,UAAA,GAAa;AAAA,KACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,QAAA,EAA2B;AACpC,IAAA,MAAM,IAAA,GAAO,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,EAAG,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA;AAC1E,IAAA,OAAO,QAAA,GAAW,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAI,eAAA,CAAgB,EAAE,SAAA,EAAW,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,CAAA,CAAA,GAAK,IAAA;AAAA,EAC3F;AAAA;AAAA,EAGA,MAAM,UAAU,QAAA,EAA2C;AACzD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,iBAAiB,sBAAsB,CAAA;AAC7E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,QAAA,GACH,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,IAAI,eAAA,CAAgB,EAAE,wBAAA,EAA0B,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,CAAA,CAAA,GACrF,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAA,CAAa,OAAA,GAAoD,EAAC,EAAoB;AAC1F,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,CAAgB;AAAA,MAC/B,UAAA,EAAY,oBAAA;AAAA,MACZ,SAAA,EAAW,KAAK,MAAA,CAAO,QAAA;AAAA,MACvB,aAAA,EAAe,KAAK,aAAA;AAAc,KACnC,CAAA;AACD,IAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,EAAG;AAC/C,MAAA,IAAA,CAAK,IAAI,OAAA,EAAS,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IAC5C;AACA,IAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,OAAA,CAAQ,QAAQ,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,KAAK,SAAA,CAAU,QAAA,CAAS,gBAAgB,CAAA,EAAG,IAAI,CAAA;AACtF,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,8BAAA,EAAiC,MAAM,QAAA,CAAS,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IACxF;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,IAAI,OAAO,IAAA,CAAK,YAAA,KAAiB,QAAA,EAAU;AACzC,MAAA,MAAM,IAAI,oBAAoB,yCAAyC,CAAA;AAAA,IACzE;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,SAAS,WAAA,EAAuD;AACpE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,iBAAiB,mBAAmB,CAAA;AAC1E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,gBAAA,CAAiB,QAAA,EAAU;AAAA,MACrD,OAAA,EAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA;AAAG,KACnD,CAAA;AACD,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,oBAAoB,0BAA0B,CAAA;AAAA,IAC1D;AACA,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,KAAA,EAAiD;AAChE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,wBAAwB,CAAA;AACvE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,IAAA,CAAK,aAAA,EAAe,CAAA,CAAE,CAAA;AACpE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA;AAAA,MAC1B,QAAA;AAAA,MACA,IAAI,eAAA,CAAgB,EAAE,KAAA,EAAO,CAAA;AAAA,MAC7B,EAAE,aAAA,EAAe,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA;AAAG,KACpC;AACA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,oBAAoB,+BAA+B,CAAA;AAAA,IAC/D;AACA,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA;AAAA,EAGA,cAAc,OAAA,EAAiD;AAC7D,IAAA,OAAO,cAAc,OAAO,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAA,EAAkC;AACtC,IAAA,OAAO,IAAI,YAAY,IAAA,CAAK,MAAA,CAAO,QAAQ,WAAA,EAAa,IAAA,CAAK,MAAA,CAAO,SAAA,IAAa,GAAM,CAAA;AAAA,EACzF;AAAA,EAEA,MAAc,QAAA,CAAS,IAAA,EAAc,QAAA,EAAkB,WAAA,EAA8C;AACnG,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,CAAgB;AAAA,MAC/B,UAAA,EAAY,oBAAA;AAAA,MACZ,IAAA;AAAA,MACA,YAAA,EAAc,WAAA,IAAe,IAAA,CAAK,MAAA,CAAO,WAAA;AAAA,MACzC,SAAA,EAAW,KAAK,MAAA,CAAO,QAAA;AAAA,MACvB,aAAA,EAAe;AAAA,KAChB,CAAA;AACD,IAAA,IAAI,IAAA,CAAK,OAAO,YAAA,EAAc;AAC5B,MAAA,IAAA,CAAK,GAAA,CAAI,eAAA,EAAiB,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAAA,IACpD;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,KAAK,SAAA,CAAU,QAAA,CAAS,gBAAgB,CAAA,EAAG,IAAI,CAAA;AACtF,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,uBAAA,EAA0B,MAAM,QAAA,CAAS,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IACjF;AACA,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA,EAEA,MAAc,aAAA,CAAc,OAAA,EAAiB,KAAA,EAAiD;AAC5F,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,UAAU,CAAA;AACxD,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AACzC,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,GAAWC,uBAAA,CAAmB,IAAI,GAAA,CAAI,OAAO,CAAC,CAAA;AAC9C,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAA,EAAS,QAAQ,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,CAAC,EAAE,OAAA,EAAQ,GAAI,MAAMC,cAAA,CAAU,SAAS,QAAA,EAAU;AAAA,QAChD,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,QACpB,QAAA,EAAU,KAAK,MAAA,CAAO;AAAA,OACvB,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,oCAAA,EAAuC,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IACtF;AAEA,IAAA,IAAI,KAAA,IAAS,OAAA,CAAQ,OAAO,CAAA,KAAM,KAAA,EAAO;AACvC,MAAA,MAAM,IAAI,oBAAoB,0DAAqD,CAAA;AAAA,IACrF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEQ,MAAA,GAAmB;AACzB,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,OAAO,MAAA,IAAU,OAAO,MAAA,GAAS,CAAA,GAAI,SAAS,CAAC,QAAA,EAAU,WAAW,OAAO,CAAA;AAAA,EAC7E;AAAA,EAEQ,WAAA,GAAsB;AAC5B,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,WAAA;AACzB,IAAA,OAAO,IAAA,IAAQ,SAAS,EAAA,GAAK,CAAA,CAAA,EAAI,KAAK,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,CAAA,GAAK,WAAA;AAAA,EAC/D;AAAA,EAEQ,aAAA,GAAwB;AAC9B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,MAAA,MAAM,IAAI,mBAAmB,8DAA8D,CAAA;AAAA,IAC7F;AACA,IAAA,OAAO,KAAK,MAAA,CAAO,YAAA;AAAA,EACrB;AAAA,EAEQ,IAAA,CAAK,GAAA,EAAa,IAAA,EAAuB,OAAA,GAAkC,EAAC,EAAsB;AACxG,IAAA,OAAO,IAAA,CAAK,iBAAiB,GAAA,EAAK;AAAA,MAChC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,mCAAA,EAAqC,GAAG,OAAA,EAAQ;AAAA,MAC3E;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,gBAAA,CAAiB,GAAA,EAAa,IAAA,EAAsC;AAChF,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,CAAK,MAAA,CAAO,SAAA,IAAa,GAAM,CAAA;AAClF,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,MAAM,GAAA,EAAK,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,IAChE,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AACF;AAGA,SAAS,qBAAA,CAAsB,GAAW,CAAA,EAAoB;AAC5D,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,QAAA,IAAY,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC9C;AACA,EAAA,OAAO,QAAA,KAAa,CAAA;AACtB;;;ACrRO,SAAS,YAAY,WAAA,EAA2D;AACrF,EAAA,MAAM,WAAA,GAAc,WAAA,CAAY,WAAA,IAAe,EAAC;AAChD,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,KAAA,IAAS,EAAC;AACpC,EAAA,iBAAA,CAAkB,aAAa,KAAK,CAAA;AACpC,EAAA,OAAO,EAAE,aAAa,KAAA,EAAM;AAC9B;AAOA,eAAsB,cAAc,WAAA,EAAuD;AACzF,EAAA,MAAM,eAAe,WAAA,CAAY,WAAA,IAAe,EAAC,EAAG,IAAI,mBAAmB,CAAA;AAC3E,EAAA,MAAM,SAAS,WAAA,CAAY,KAAA,IAAS,EAAC,EAAG,IAAI,aAAa,CAAA;AACzD,EAAA,iBAAA,CAAkB,aAAa,KAAK,CAAA;AAEpC,EAAA,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,GAAA,CAAI,aAAA,CAAc,CAAA,CAAE,GAAG,CAAC,CAAA;AACrD,EAAA,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,EAAE,GAAA,CAAI,aAAA,CAAc,CAAA,CAAE,GAAG,CAAC,CAAA;AAE/C,EAAA,MAAM,OAAA,GAAA,CAAW,MAAM,SAAA,CAAU,IAAA,CAAK,SAAA,CAAU,EAAE,WAAA,EAAa,KAAA,EAAO,CAAC,CAAA,EAAG,KAAA,CAAM,GAAG,EAAE,CAAA;AACrF,EAAA,OAAO,EAAE,OAAA,EAAS,WAAA,EAAa,KAAA,EAAM;AACvC;AAeA,eAAsB,eAAA,CACpB,QACA,WAAA,EAC8B;AAC9B,EAAA,IAAI,CAAC,OAAO,MAAA,IAAU,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,YAAA,EAAc;AAC9D,IAAA,MAAM,IAAI,mBAAmB,gEAAgE,CAAA;AAAA,EAC/F;AAEA,EAAA,MAAM,SAAA,GAAY,OAAO,SAAA,IAAa,GAAA;AACtC,EAAA,MAAM,QAAA,GAAW,MAAM,aAAA,CAAc,WAAW,CAAA;AAChD,EAAA,MAAM,YAAY,IAAI,SAAA,CAAU,MAAA,CAAO,MAAA,EAAQ,WAAW,IAAS,CAAA;AAEnE,EAAA,MAAM,KAAA,GAAQ,MAAM,SAAA,CAAU,MAAA,EAAQ,WAAW,SAAS,CAAA;AAE1D,EAAA,MAAM,WAAW,MAAM,gBAAA;AAAA,IACrB,GAAG,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,qBAAA,CAAA;AAAA,IACnC;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA;AAAA,QAC9B,MAAA,EAAQ,kBAAA;AAAA,QACR,cAAA,EAAgB;AAAA,OAClB;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,QAAQ;AAAA,KAC/B;AAAA,IACA;AAAA,GACF;AAEA,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,IAAI,MAAM,QAAA,CAAS,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,EACxG;AAEA,EAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,EAAA,OAAO,SAAS,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,GAAY,OAA+B,EAAC;AACtF;AAEA,eAAe,SAAA,CACb,MAAA,EACA,SAAA,EACA,SAAA,EACiB;AACjB,EAAA,MAAM,WAAW,MAAM,gBAAA;AAAA,IACrB,MAAM,SAAA,CAAU,QAAA,CAAS,gBAAgB,CAAA;AAAA,IACzC;AAAA,MACE,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,mCAAA,EAAoC;AAAA,MAC/D,IAAA,EAAM,IAAI,eAAA,CAAgB;AAAA,QACxB,UAAA,EAAY,oBAAA;AAAA,QACZ,WAAW,MAAA,CAAO,QAAA;AAAA,QAClB,eAAe,MAAA,CAAO,YAAA;AAAA,QACtB,KAAA,EAAO;AAAA,OACR;AAAA,KACH;AAAA,IACA;AAAA,GACF;AAEA,EAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACpD,EAAA,IAAI,OAAO,IAAA,CAAK,YAAA,KAAiB,QAAA,IAAY,IAAA,CAAK,iBAAiB,EAAA,EAAI;AACrE,IAAA,MAAM,IAAI,mBAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,OAAO,IAAA,CAAK,YAAA;AACd;AAEA,SAAS,iBAAA,CAAkB,aAAqC,KAAA,EAA+B;AAC7F,EAAA,MAAM,cAAA,uBAAqB,GAAA,EAAY;AACvC,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AACpC,IAAA,IAAI,CAAC,WAAW,GAAA,EAAK;AACnB,MAAA,MAAM,IAAI,mBAAmB,2CAA2C,CAAA;AAAA,IAC1E;AACA,IAAA,IAAI,cAAA,CAAe,GAAA,CAAI,UAAA,CAAW,GAAG,CAAA,EAAG;AACtC,MAAA,MAAM,IAAI,kBAAA,CAAmB,CAAA,YAAA,EAAe,UAAA,CAAW,GAAG,CAAA,6BAAA,CAA+B,CAAA;AAAA,IAC3F;AACA,IAAA,cAAA,CAAe,GAAA,CAAI,WAAW,GAAG,CAAA;AAAA,EACnC;AAEA,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAY;AACjC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AACb,MAAA,MAAM,IAAI,mBAAmB,qCAAqC,CAAA;AAAA,IACpE;AACA,IAAA,IAAI,CAAC,KAAK,IAAA,EAAM;AACd,MAAA,MAAM,IAAI,kBAAA,CAAmB,CAAA,MAAA,EAAS,IAAA,CAAK,GAAG,CAAA,6BAAA,CAA+B,CAAA;AAAA,IAC/E;AACA,IAAA,IAAI,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,EAAG;AAC1B,MAAA,MAAM,IAAI,kBAAA,CAAmB,CAAA,MAAA,EAAS,IAAA,CAAK,GAAG,CAAA,6BAAA,CAA+B,CAAA;AAAA,IAC/E;AACA,IAAA,QAAA,CAAS,GAAA,CAAI,KAAK,GAAG,CAAA;AACrB,IAAA,KAAA,MAAW,SAAA,IAAa,KAAK,WAAA,EAAa;AACxC,MAAA,IAAI,CAAC,cAAA,CAAe,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,QAAA,MAAM,IAAI,kBAAA;AAAA,UACR,CAAA,MAAA,EAAS,IAAA,CAAK,GAAG,CAAA,yBAAA,EAA4B,SAAS,CAAA,yBAAA;AAAA,SACxD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,oBAAoB,UAAA,EAAwD;AACnF,EAAA,OAAO,UAAA,CAAW,WAAA,KAAgB,MAAA,GAC9B,EAAE,KAAK,UAAA,CAAW,GAAA,EAAI,GACtB,EAAE,GAAA,EAAK,UAAA,CAAW,GAAA,EAAK,WAAA,EAAa,WAAW,WAAA,EAAY;AACjE;AAGA,SAAS,cAAc,IAAA,EAAsC;AAC3D,EAAA,MAAM,WAAA,GAAc,CAAC,GAAG,IAAA,CAAK,WAAW,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,CAAA;AAC3E,EAAA,OAAO,IAAA,CAAK,gBAAgB,MAAA,GACxB,EAAE,KAAK,IAAA,CAAK,GAAA,EAAK,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,WAAA,KAClC,EAAE,GAAA,EAAK,KAAK,GAAA,EAAK,IAAA,EAAM,KAAK,IAAA,EAAM,WAAA,EAAa,IAAA,CAAK,WAAA,EAAa,WAAA,EAAY;AACnF;AAEA,eAAe,UAAU,KAAA,EAAgC;AACvD,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,KAAK,CAAC,CAAA;AACpF,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA,CACrC,IAAI,CAAC,IAAA,KAAS,KAAK,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAChD,KAAK,EAAE,CAAA;AACZ;AAEA,eAAe,gBAAA,CAAiB,GAAA,EAAa,IAAA,EAAmB,SAAA,EAAsC;AACpG,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,UAAA,CAAW,KAAA,IAAS,SAAS,CAAA;AAC5D,EAAA,IAAI;AACF,IAAA,OAAO,MAAM,MAAM,GAAA,EAAK,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,EAChE,CAAA,SAAE;AACA,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF","file":"index.cjs","sourcesContent":["/**\n * Base class for every error this SDK throws, so callers can `catch (e) { if (e\n * instanceof CboxIdError) ... }` in one branch.\n */\nexport class CboxIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The client is misconfigured (a required option is missing or empty). */\nexport class ConfigurationError extends CboxIdError {}\n\n/**\n * The login `state` did not match what was stored — the callback is forged or\n * stale. Treat as a fresh start, not an error to surface to the user.\n */\nexport class InvalidStateError extends CboxIdError {}\n\n/**\n * Login could not be completed: the provider returned an error, the callback was\n * missing a code, or a token / id_token failed verification.\n */\nexport class AuthenticationError extends CboxIdError {}\n","import { AuthenticationError, ConfigurationError } from './errors.js';\nimport type { DiscoveryDocument } from './types.js';\n\n/**\n * Fetches and caches an instance's OIDC discovery document. One instance of this\n * lives per {@link CboxIdClient}; the document is refetched only after the TTL.\n */\nexport class Discovery {\n private cached: { doc: DiscoveryDocument; expiresAt: number } | null = null;\n\n constructor(\n private readonly issuer: string,\n private readonly timeoutMs: number,\n private readonly cacheTtlMs: number,\n private readonly now: () => number = Date.now,\n ) {}\n\n async document(): Promise<DiscoveryDocument> {\n if (this.cached && this.cached.expiresAt > this.now()) {\n return this.cached.doc;\n }\n\n const url = `${this.issuer.replace(/\\/$/, '')}/.well-known/openid-configuration`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n let doc: DiscoveryDocument;\n try {\n const response = await fetch(url, { signal: controller.signal });\n if (!response.ok) {\n throw new AuthenticationError(`Discovery request failed with status ${response.status}.`);\n }\n doc = (await response.json()) as DiscoveryDocument;\n } catch (error) {\n if (error instanceof AuthenticationError) {\n throw error;\n }\n throw new AuthenticationError(`Discovery request failed: ${String(error)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (typeof doc.issuer !== 'string' || doc.issuer === '') {\n throw new AuthenticationError('The discovery document was missing an issuer.');\n }\n\n this.cached = { doc, expiresAt: this.now() + this.cacheTtlMs };\n return doc;\n }\n\n /** A required endpoint from the discovery document. */\n async endpoint(name: keyof DiscoveryDocument): Promise<string> {\n const value = (await this.document())[name];\n if (typeof value !== 'string' || value === '') {\n throw new ConfigurationError(`The instance does not advertise a ${name}.`);\n }\n return value;\n }\n\n /** An optional endpoint, or null when the instance advertises none. */\n async optionalEndpoint(name: keyof DiscoveryDocument): Promise<string | null> {\n const value = (await this.document())[name];\n return typeof value === 'string' && value !== '' ? value : null;\n }\n}\n","/**\n * PKCE (RFC 7636) and the random values the login flow needs, built on Web Crypto\n * (`globalThis.crypto`) so the same code runs on Node, edge runtimes and browsers.\n */\n\nfunction base64url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** A URL-safe random token of `bytes` bytes (default 32), for state and nonce. */\nexport function randomToken(bytes = 32): string {\n return base64url(crypto.getRandomValues(new Uint8Array(bytes)));\n}\n\n/** A high-entropy PKCE code verifier. */\nexport function createVerifier(): string {\n return randomToken(32);\n}\n\n/** The S256 code challenge for a verifier. */\nexport async function challenge(verifier: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n return base64url(new Uint8Array(digest));\n}\n","import { AuthenticationError } from './errors.js';\n\n/** A stored vault secret's metadata (never its plaintext). */\nexport interface VaultSecretRef {\n id: string;\n name: string;\n provider: string;\n ownerType: string | null;\n ownerId: string | null;\n expiresAt: string | null;\n revoked: boolean;\n}\n\n/** A brokered credential — the plaintext, for immediate use. */\nexport interface VaultLease {\n secretId: string;\n provider: string;\n secret: string;\n expiresAt: string;\n}\n\nexport interface StoreSecretInput {\n name: string;\n provider: string;\n secret: string;\n ownerType?: 'organization' | 'user';\n ownerId?: string;\n expiresAt?: string;\n}\n\n/**\n * Client for a Cbox ID instance's Token Vault API. Bind it to an access token\n * (obtain one with {@link CboxIdClient.machineToken}, scoped `vault.manage` for\n * provisioning or `vault.lease` for redeeming). All calls are server-to-server.\n */\nexport class VaultClient {\n private readonly base: string;\n\n constructor(\n issuer: string,\n private readonly token: string,\n private readonly timeoutMs = 10_000,\n ) {\n this.base = `${issuer.replace(/\\/$/, '')}/api/v1/vault`;\n }\n\n /** Ingest a downstream credential, sealed at rest (scope `vault.manage`). */\n store(input: StoreSecretInput): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', '/secrets', {\n name: input.name,\n provider: input.provider,\n secret: input.secret,\n owner_type: input.ownerType,\n owner_id: input.ownerId,\n expires_at: input.expiresAt,\n });\n }\n\n /** Rotate a secret's value, keeping its id and grants (scope `vault.manage`). */\n rotate(secretId: string, secret: string): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', `/secrets/${encodeURIComponent(secretId)}/rotate`, { secret });\n }\n\n /** Revoke a secret permanently (scope `vault.manage`). */\n async revoke(secretId: string): Promise<void> {\n await this.request('DELETE', `/secrets/${encodeURIComponent(secretId)}`);\n }\n\n /** Authorize an agent client to lease a secret (scope `vault.manage`). */\n grant(\n secretId: string,\n clientId: string,\n maxTtlSeconds?: number,\n ): Promise<{ secretId: string; clientId: string; maxTtlSeconds: number | null }> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/grants`, {\n client_id: clientId,\n max_ttl_seconds: maxTtlSeconds,\n }).then((raw) => {\n const r = raw as { secret_id: string; client_id: string; max_ttl_seconds: number | null };\n return { secretId: r.secret_id, clientId: r.client_id, maxTtlSeconds: r.max_ttl_seconds };\n });\n }\n\n /** Revoke an agent's authorization (scope `vault.manage`). */\n async revokeGrant(secretId: string, clientId: string): Promise<void> {\n await this.request(\n 'DELETE',\n `/secrets/${encodeURIComponent(secretId)}/grants/${encodeURIComponent(clientId)}`,\n );\n }\n\n /**\n * Redeem a leased credential for immediate use (scope `vault.lease`). The caller\n * is identified by the token's client; a lease with no live grant is refused.\n */\n lease(secretId: string, purpose: string): Promise<VaultLease> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/lease`, { purpose }).then((raw) => {\n const r = raw as { secret_id: string; provider: string; secret: string; expires_at: string };\n return { secretId: r.secret_id, provider: r.provider, secret: r.secret, expiresAt: r.expires_at };\n });\n }\n\n private async json<T>(method: string, path: string, body: Record<string, unknown>): Promise<T> {\n const response = await this.request(method, path, body);\n return (await response.json()) as T;\n }\n\n private async request(method: string, path: string, body?: Record<string, unknown>): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const init: RequestInit = {\n method,\n headers: {\n authorization: `Bearer ${this.token}`,\n ...(body ? { 'content-type': 'application/json' } : {}),\n },\n signal: controller.signal,\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n const response = await fetch(`${this.base}${path}`, init);\n if (!response.ok) {\n throw new AuthenticationError(`Vault ${method} ${path} failed with status ${response.status}.`);\n }\n return response;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","/**\n * Verify a Cbox ID webhook / inline-action signature. The header is\n * `X-Cbox-Signature: t={unix},v1={hex hmac}` — an HMAC-SHA256 over\n * `\"{timestamp}.{raw body}\"`, valid within a freshness window. Built on Web Crypto\n * so it runs on Node, edge and the browser.\n */\n\n/** Constant-time compare of two hex strings. */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n\nfunction toHex(bytes: ArrayBuffer): string {\n return Array.from(new Uint8Array(bytes))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport interface VerifyWebhookOptions {\n /** The RAW request body — the exact bytes received, not a re-encoded copy. */\n payload: string;\n /** The value of the `X-Cbox-Signature` header. */\n signatureHeader: string | null | undefined;\n /** The signing secret issued when the webhook/action endpoint was registered. */\n secret: string;\n /** Freshness window in seconds. Defaults to 300 (5 minutes). */\n toleranceSeconds?: number;\n /** Injectable clock (unix seconds), for tests. Defaults to `Date.now()`. */\n now?: number;\n}\n\n/** Returns `true` only when the signature is present, fresh and valid. Never throws. */\nexport async function verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n const { payload, signatureHeader, secret } = options;\n const toleranceSeconds = options.toleranceSeconds ?? 300;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n if (!signatureHeader) {\n return false;\n }\n\n const parts: Record<string, string> = {};\n for (const segment of signatureHeader.split(',')) {\n const [key, value] = segment.trim().split('=', 2);\n if (key) {\n parts[key] = value ?? '';\n }\n }\n\n const timestamp = parts['t'] ?? '';\n const signature = parts['v1'] ?? '';\n\n if (timestamp === '' || signature === '' || !/^\\d+$/.test(timestamp)) {\n return false;\n }\n\n if (Math.abs(now - Number(timestamp)) > toleranceSeconds) {\n return false;\n }\n\n const key = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const expected = toHex(\n await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`${timestamp}.${payload}`)),\n );\n\n return timingSafeEqual(expected, signature);\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport { Discovery } from './discovery.js';\nimport { AuthenticationError, ConfigurationError, InvalidStateError } from './errors.js';\nimport { challenge, createVerifier, randomToken } from './pkce.js';\nimport type {\n AuthorizationRequest,\n CboxIdConfig,\n CboxUser,\n TokenResponse,\n} from './types.js';\nimport { VaultClient } from './vault.js';\nimport { verifyWebhook, type VerifyWebhookOptions } from './webhook.js';\n\ntype JwksResolver = ReturnType<typeof createRemoteJWKSet>;\n\n/** Query parameters as they arrive on your callback route. */\nexport interface CallbackParams {\n code?: string | null;\n state?: string | null;\n error?: string | null;\n error_description?: string | null;\n}\n\n/** The values you persisted from {@link CboxIdClient.createAuthorizationRequest}. */\nexport interface StoredAuthState {\n state: string;\n codeVerifier: string;\n nonce: string;\n}\n\n/**\n * Turnkey Cbox ID client for JavaScript/TypeScript. It speaks standard OpenID\n * Connect against a Cbox ID instance — so integrating is a redirect and a callback,\n * not a rewrite — and adds the conveniences a hosted-identity product needs: a\n * redirect to the instance's hosted profile page, and back-channel helpers (machine\n * tokens, userinfo, introspection, webhook verification).\n *\n * Login is hardened by default: PKCE (S256), a CSRF state check, a nonce, and full\n * id_token signature + issuer + audience verification against the instance's JWKS\n * (via `jose`).\n *\n * The class is framework-agnostic: {@link createAuthorizationRequest} hands you the\n * `state`, `codeVerifier` and `nonce` to persist however you like, and\n * {@link authenticate} takes them back. For Next.js, the `@cboxdk/id-js/nextjs`\n * entry wires this to cookies for you.\n */\nexport class CboxIdClient {\n private readonly discovery: Discovery;\n private readonly jwksByUri = new Map<string, JwksResolver>();\n\n constructor(private readonly config: CboxIdConfig) {\n if (!config.issuer) {\n throw new ConfigurationError('Cbox ID config `issuer` is required.');\n }\n if (!config.clientId) {\n throw new ConfigurationError('Cbox ID config `clientId` is required.');\n }\n if (!config.redirectUri) {\n throw new ConfigurationError('Cbox ID config `redirectUri` is required.');\n }\n this.discovery = new Discovery(\n config.issuer,\n config.timeoutMs ?? 10_000,\n config.cacheTtlMs ?? 3_600_000,\n );\n }\n\n /**\n * Begin login. Returns the authorize URL plus the `state`, `codeVerifier` and\n * `nonce` — persist those (signed, httpOnly cookies are ideal) and hand them back\n * to {@link authenticate} on the callback.\n */\n async createAuthorizationRequest(options: {\n scopes?: string[];\n redirectUri?: string;\n state?: string;\n prompt?: string;\n loginHint?: string;\n maxAge?: number;\n } = {}): Promise<AuthorizationRequest> {\n const codeVerifier = createVerifier();\n const state = options.state ?? randomToken(16);\n const nonce = randomToken(16);\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: this.config.clientId,\n redirect_uri: options.redirectUri ?? this.config.redirectUri,\n scope: (options.scopes ?? this.scopes()).join(' '),\n state,\n nonce,\n code_challenge: await challenge(codeVerifier),\n code_challenge_method: 'S256',\n });\n if (options.prompt) {\n params.set('prompt', options.prompt);\n }\n if (options.loginHint) {\n params.set('login_hint', options.loginHint);\n }\n if (typeof options.maxAge === 'number') {\n params.set('max_age', String(options.maxAge));\n }\n\n const endpoint = await this.discovery.endpoint('authorization_endpoint');\n return { url: `${endpoint}?${params.toString()}`, state, codeVerifier, nonce };\n }\n\n /**\n * Complete login on your callback route: verify state, exchange the code with the\n * PKCE verifier, verify the id_token, and return the authenticated user.\n *\n * @throws InvalidStateError when state does not match (forged/stale request)\n * @throws AuthenticationError on any other failure\n */\n async authenticate(input: {\n params: CallbackParams;\n stored: StoredAuthState;\n redirectUri?: string;\n }): Promise<CboxUser> {\n const { params, stored } = input;\n\n if (!params.state || !stored.state || !timingSafeEqualString(params.state, stored.state)) {\n throw new InvalidStateError('The login state did not match — the request may be forged or stale.');\n }\n\n if (params.error) {\n throw new AuthenticationError(\n `Cbox ID returned an error: ${params.error}${params.error_description ? ` (${params.error_description})` : ''}`,\n );\n }\n\n if (!params.code) {\n throw new AuthenticationError('The callback was missing an authorization code.');\n }\n\n const tokens = await this.exchange(params.code, stored.codeVerifier, input.redirectUri);\n\n if (!tokens.access_token) {\n throw new AuthenticationError('No access token was returned.');\n }\n\n let claims: Record<string, unknown> = {};\n if (tokens.id_token) {\n claims = await this.verifyIdToken(tokens.id_token, stored.nonce);\n }\n // Enrich with userinfo (email/name/org a minimal id_token may omit).\n claims = { ...claims, ...(await this.userinfo(tokens.access_token)) };\n\n const sub = claims['sub'];\n if (typeof sub !== 'string' || sub === '') {\n throw new AuthenticationError('The verified token carried no subject.');\n }\n\n return {\n id: sub,\n email: typeof claims['email'] === 'string' ? claims['email'] : null,\n name: typeof claims['name'] === 'string' ? claims['name'] : null,\n organizationId: typeof claims['org'] === 'string' ? claims['org'] : null,\n claims,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? null,\n idToken: tokens.id_token ?? null,\n expiresIn: typeof tokens.expires_in === 'number' ? tokens.expires_in : 0,\n };\n }\n\n /**\n * The URL of the instance's hosted account/profile page (self-service password,\n * MFA, passkeys, sessions). A signed-in user is authenticated there by their Cbox\n * ID session; `returnTo` is passed so the page can link back to your app.\n */\n profileUrl(returnTo?: string): string {\n const base = `${this.config.issuer.replace(/\\/$/, '')}${this.accountPath()}`;\n return returnTo ? `${base}?${new URLSearchParams({ return_to: returnTo }).toString()}` : base;\n }\n\n /** The RP-initiated logout URL, or null when the instance advertises none. */\n async logoutUrl(returnTo?: string): Promise<string | null> {\n const endpoint = await this.discovery.optionalEndpoint('end_session_endpoint');\n if (!endpoint) {\n return null;\n }\n return returnTo\n ? `${endpoint}?${new URLSearchParams({ post_logout_redirect_uri: returnTo }).toString()}`\n : endpoint;\n }\n\n /**\n * A machine (client-credentials) access token for calling Cbox ID APIs as your\n * app, not on a user's behalf. Requires a client secret.\n */\n async machineToken(options: { scopes?: string[]; resource?: string } = {}): Promise<string> {\n const body = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.config.clientId,\n client_secret: this.requireSecret(),\n });\n if (options.scopes && options.scopes.length > 0) {\n body.set('scope', options.scopes.join(' '));\n }\n if (options.resource) {\n body.set('resource', options.resource);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Machine token request failed: ${await response.text()}`);\n }\n const json = (await response.json()) as { access_token?: unknown };\n if (typeof json.access_token !== 'string') {\n throw new AuthenticationError('The token response had no access_token.');\n }\n return json.access_token;\n }\n\n /** The OIDC userinfo claims for an access token. */\n async userinfo(accessToken: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.optionalEndpoint('userinfo_endpoint');\n if (!endpoint) {\n return {};\n }\n const response = await this.fetchWithTimeout(endpoint, {\n headers: { authorization: `Bearer ${accessToken}` },\n });\n if (!response.ok) {\n throw new AuthenticationError('Userinfo request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /**\n * RFC 7662 token introspection (confidential-client auth). Returns the raw\n * response; `active` tells you if the token is currently valid. Requires a secret.\n */\n async introspect(token: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.endpoint('introspection_endpoint');\n const basic = btoa(`${this.config.clientId}:${this.requireSecret()}`);\n const response = await this.post(\n endpoint,\n new URLSearchParams({ token }),\n { authorization: `Basic ${basic}` },\n );\n if (!response.ok) {\n throw new AuthenticationError('Introspection request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /** Verify a Cbox ID webhook / inline-action signature. See {@link verifyWebhook}. */\n verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n return verifyWebhook(options);\n }\n\n /**\n * A Token Vault client bound to an access token. Obtain the token with\n * {@link machineToken} (scope `vault.manage` to provision/grant, `vault.lease` to\n * redeem), then call `store` / `grant` / `lease` etc.\n */\n vault(accessToken: string): VaultClient {\n return new VaultClient(this.config.issuer, accessToken, this.config.timeoutMs ?? 10_000);\n }\n\n private async exchange(code: string, verifier: string, redirectUri?: string): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri ?? this.config.redirectUri,\n client_id: this.config.clientId,\n code_verifier: verifier,\n });\n if (this.config.clientSecret) {\n body.set('client_secret', this.config.clientSecret);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Token exchange failed: ${await response.text()}`);\n }\n return (await response.json()) as TokenResponse;\n }\n\n private async verifyIdToken(idToken: string, nonce: string): Promise<Record<string, unknown>> {\n const jwksUri = await this.discovery.endpoint('jwks_uri');\n let resolver = this.jwksByUri.get(jwksUri);\n if (!resolver) {\n resolver = createRemoteJWKSet(new URL(jwksUri));\n this.jwksByUri.set(jwksUri, resolver);\n }\n\n let payload: JWTPayload;\n try {\n ({ payload } = await jwtVerify(idToken, resolver, {\n issuer: this.config.issuer,\n audience: this.config.clientId,\n }));\n } catch (error) {\n throw new AuthenticationError(`The id_token could not be verified: ${String(error)}`);\n }\n\n if (nonce && payload['nonce'] !== nonce) {\n throw new AuthenticationError('The id_token nonce did not match — possible replay.');\n }\n\n return payload as Record<string, unknown>;\n }\n\n private scopes(): string[] {\n const scopes = this.config.scopes;\n return scopes && scopes.length > 0 ? scopes : ['openid', 'profile', 'email'];\n }\n\n private accountPath(): string {\n const path = this.config.accountPath;\n return path && path !== '' ? `/${path.replace(/^\\//, '')}` : '/settings';\n }\n\n private requireSecret(): string {\n if (!this.config.clientSecret) {\n throw new ConfigurationError('This call requires a `clientSecret`, but none is configured.');\n }\n return this.config.clientSecret;\n }\n\n private post(url: string, body: URLSearchParams, headers: Record<string, string> = {}): Promise<Response> {\n return this.fetchWithTimeout(url, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', ...headers },\n body,\n });\n }\n\n private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs ?? 10_000);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/** Constant-time string compare, so state validation doesn't leak via timing. */\nfunction timingSafeEqualString(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n","import { Discovery } from './discovery.js';\nimport { AuthenticationError, ConfigurationError } from './errors.js';\n\n/**\n * A permission your app declares. `key` is a `feature:action` slug (e.g.\n * `invoices:create`); `description` is human-facing copy for the Cbox ID console.\n */\nexport interface PermissionDefinition {\n key: string;\n description?: string;\n}\n\n/**\n * A role your app declares. `permissions` lists the permission keys the role\n * grants — each must reference a declared {@link PermissionDefinition}.\n */\nexport interface RoleDefinition {\n key: string;\n name: string;\n description?: string;\n permissions: string[];\n}\n\n/**\n * The roles + permissions an app declares in code. Either list may be omitted.\n * Pass this to {@link defineAuthz} (to validate up front) or straight to\n * {@link buildManifest} / {@link publishManifest}.\n */\nexport interface AuthzDeclaration {\n permissions?: PermissionDefinition[];\n roles?: RoleDefinition[];\n}\n\n/**\n * The manifest as it is sent to Cbox ID: the declared permissions + roles plus a\n * content-derived `version`, so republishing an unchanged catalog is a no-op.\n */\nexport interface AuthzManifest {\n version: string;\n permissions: PermissionDefinition[];\n roles: RoleDefinition[];\n}\n\n/** What {@link publishManifest} needs to authenticate the push. */\nexport interface ManifestPublisherConfig {\n /** Base URL (issuer) of the Cbox ID instance — the `token_endpoint` is discovered from it. */\n issuer: string;\n /** Your OAuth client id. The client must hold the `apps.manifest` scope. */\n clientId: string;\n /** Your OAuth client secret. The push uses the client-credentials grant. */\n clientSecret: string;\n /** Timeout (ms) for back-channel HTTP calls. Defaults to `10000`. */\n timeoutMs?: number;\n}\n\n/**\n * The server's sync summary. The named fields are the ones the SDK/CLI reads;\n * the index signature keeps any extra fields the server returns.\n */\nexport interface ManifestSyncSummary {\n unchanged?: boolean;\n roles_declared?: number;\n permissions_declared?: number;\n version?: string;\n [key: string]: unknown;\n}\n\n/**\n * Validate a roles/permissions declaration and return it normalized (both lists\n * always present). Call this where you declare your catalog so mistakes — a role\n * that grants an undeclared permission, a duplicate key — surface immediately\n * rather than on deploy.\n *\n * @throws ConfigurationError on a missing key/name, a duplicate, or a role that\n * references a permission that was never declared.\n */\nexport function defineAuthz(declaration: AuthzDeclaration): Required<AuthzDeclaration> {\n const permissions = declaration.permissions ?? [];\n const roles = declaration.roles ?? [];\n assertDeclaration(permissions, roles);\n return { permissions, roles };\n}\n\n/**\n * Build the manifest — the declared catalog plus a stable content hash `version`\n * (first 16 hex chars of the sha256 of the canonicalized catalog). The catalog is\n * sorted by key first, so declaration order never changes the version.\n */\nexport async function buildManifest(declaration: AuthzDeclaration): Promise<AuthzManifest> {\n const permissions = (declaration.permissions ?? []).map(canonicalPermission);\n const roles = (declaration.roles ?? []).map(canonicalRole);\n assertDeclaration(permissions, roles);\n\n permissions.sort((a, b) => a.key.localeCompare(b.key));\n roles.sort((a, b) => a.key.localeCompare(b.key));\n\n const version = (await sha256Hex(JSON.stringify({ permissions, roles }))).slice(0, 16);\n return { version, permissions, roles };\n}\n\n/**\n * Publish this app's authorization manifest (its declared roles + permissions) to\n * Cbox ID. The app owns what a role means; Cbox ID owns identity and who holds it.\n *\n * It mints a client-credentials token with the `apps.manifest` scope (token\n * endpoint discovered from the issuer's OIDC configuration), then POSTs the\n * manifest to `{issuer}/api/v1/apps/manifest`. Run it on deploy or from a script;\n * an unchanged catalog is a server-side no-op.\n *\n * @returns the server's sync summary (`unchanged`, `roles_declared`, …).\n * @throws ConfigurationError when config or the declaration is invalid.\n * @throws AuthenticationError when the token cannot be minted or the push fails.\n */\nexport async function publishManifest(\n config: ManifestPublisherConfig,\n declaration: AuthzDeclaration,\n): Promise<ManifestSyncSummary> {\n if (!config.issuer || !config.clientId || !config.clientSecret) {\n throw new ConfigurationError('Publishing a manifest needs issuer, clientId and clientSecret.');\n }\n\n const timeoutMs = config.timeoutMs ?? 10_000;\n const manifest = await buildManifest(declaration);\n const discovery = new Discovery(config.issuer, timeoutMs, 3_600_000);\n\n const token = await mintToken(config, discovery, timeoutMs);\n\n const response = await fetchWithTimeout(\n `${config.issuer.replace(/\\/$/, '')}/api/v1/apps/manifest`,\n {\n method: 'POST',\n headers: {\n authorization: `Bearer ${token}`,\n accept: 'application/json',\n 'content-type': 'application/json',\n },\n body: JSON.stringify(manifest),\n },\n timeoutMs,\n );\n\n if (!response.ok) {\n throw new AuthenticationError(`Manifest push failed: HTTP ${response.status} ${await response.text()}`);\n }\n\n const json = (await response.json()) as unknown;\n return json !== null && typeof json === 'object' ? (json as ManifestSyncSummary) : {};\n}\n\nasync function mintToken(\n config: ManifestPublisherConfig,\n discovery: Discovery,\n timeoutMs: number,\n): Promise<string> {\n const response = await fetchWithTimeout(\n await discovery.endpoint('token_endpoint'),\n {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: config.clientId,\n client_secret: config.clientSecret,\n scope: 'apps.manifest',\n }),\n },\n timeoutMs,\n );\n\n const json = (await response.json().catch(() => ({}))) as { access_token?: unknown };\n if (typeof json.access_token !== 'string' || json.access_token === '') {\n throw new AuthenticationError(\n 'Could not obtain an apps.manifest access token — check the client credentials and that the client holds the apps.manifest scope.',\n );\n }\n return json.access_token;\n}\n\nfunction assertDeclaration(permissions: PermissionDefinition[], roles: RoleDefinition[]): void {\n const permissionKeys = new Set<string>();\n for (const permission of permissions) {\n if (!permission.key) {\n throw new ConfigurationError('Every permission needs a non-empty `key`.');\n }\n if (permissionKeys.has(permission.key)) {\n throw new ConfigurationError(`Permission \"${permission.key}\" is declared more than once.`);\n }\n permissionKeys.add(permission.key);\n }\n\n const roleKeys = new Set<string>();\n for (const role of roles) {\n if (!role.key) {\n throw new ConfigurationError('Every role needs a non-empty `key`.');\n }\n if (!role.name) {\n throw new ConfigurationError(`Role \"${role.key}\" needs a non-empty \\`name\\`.`);\n }\n if (roleKeys.has(role.key)) {\n throw new ConfigurationError(`Role \"${role.key}\" is declared more than once.`);\n }\n roleKeys.add(role.key);\n for (const reference of role.permissions) {\n if (!permissionKeys.has(reference)) {\n throw new ConfigurationError(\n `Role \"${role.key}\" references permission \"${reference}\", which is not declared.`,\n );\n }\n }\n }\n}\n\n/** A permission with keys in a fixed order and no `undefined` fields (stable to hash). */\nfunction canonicalPermission(permission: PermissionDefinition): PermissionDefinition {\n return permission.description === undefined\n ? { key: permission.key }\n : { key: permission.key, description: permission.description };\n}\n\n/** A role with keys in a fixed order, sorted permission refs, and no `undefined` fields. */\nfunction canonicalRole(role: RoleDefinition): RoleDefinition {\n const permissions = [...role.permissions].sort((a, b) => a.localeCompare(b));\n return role.description === undefined\n ? { key: role.key, name: role.name, permissions }\n : { key: role.key, name: role.name, description: role.description, permissions };\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n return Array.from(new Uint8Array(digest))\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n}\n\nasync function fetchWithTimeout(url: string, init: RequestInit, timeoutMs: number): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -34,4 +34,93 @@ declare function createVerifier(): string;
34
34
  /** The S256 code challenge for a verifier. */
35
35
  declare function challenge(verifier: string): Promise<string>;
36
36
 
37
- export { AuthenticationError, CboxIdError, ConfigurationError, InvalidStateError, challenge, createVerifier, randomToken };
37
+ /**
38
+ * A permission your app declares. `key` is a `feature:action` slug (e.g.
39
+ * `invoices:create`); `description` is human-facing copy for the Cbox ID console.
40
+ */
41
+ interface PermissionDefinition {
42
+ key: string;
43
+ description?: string;
44
+ }
45
+ /**
46
+ * A role your app declares. `permissions` lists the permission keys the role
47
+ * grants — each must reference a declared {@link PermissionDefinition}.
48
+ */
49
+ interface RoleDefinition {
50
+ key: string;
51
+ name: string;
52
+ description?: string;
53
+ permissions: string[];
54
+ }
55
+ /**
56
+ * The roles + permissions an app declares in code. Either list may be omitted.
57
+ * Pass this to {@link defineAuthz} (to validate up front) or straight to
58
+ * {@link buildManifest} / {@link publishManifest}.
59
+ */
60
+ interface AuthzDeclaration {
61
+ permissions?: PermissionDefinition[];
62
+ roles?: RoleDefinition[];
63
+ }
64
+ /**
65
+ * The manifest as it is sent to Cbox ID: the declared permissions + roles plus a
66
+ * content-derived `version`, so republishing an unchanged catalog is a no-op.
67
+ */
68
+ interface AuthzManifest {
69
+ version: string;
70
+ permissions: PermissionDefinition[];
71
+ roles: RoleDefinition[];
72
+ }
73
+ /** What {@link publishManifest} needs to authenticate the push. */
74
+ interface ManifestPublisherConfig {
75
+ /** Base URL (issuer) of the Cbox ID instance — the `token_endpoint` is discovered from it. */
76
+ issuer: string;
77
+ /** Your OAuth client id. The client must hold the `apps.manifest` scope. */
78
+ clientId: string;
79
+ /** Your OAuth client secret. The push uses the client-credentials grant. */
80
+ clientSecret: string;
81
+ /** Timeout (ms) for back-channel HTTP calls. Defaults to `10000`. */
82
+ timeoutMs?: number;
83
+ }
84
+ /**
85
+ * The server's sync summary. The named fields are the ones the SDK/CLI reads;
86
+ * the index signature keeps any extra fields the server returns.
87
+ */
88
+ interface ManifestSyncSummary {
89
+ unchanged?: boolean;
90
+ roles_declared?: number;
91
+ permissions_declared?: number;
92
+ version?: string;
93
+ [key: string]: unknown;
94
+ }
95
+ /**
96
+ * Validate a roles/permissions declaration and return it normalized (both lists
97
+ * always present). Call this where you declare your catalog so mistakes — a role
98
+ * that grants an undeclared permission, a duplicate key — surface immediately
99
+ * rather than on deploy.
100
+ *
101
+ * @throws ConfigurationError on a missing key/name, a duplicate, or a role that
102
+ * references a permission that was never declared.
103
+ */
104
+ declare function defineAuthz(declaration: AuthzDeclaration): Required<AuthzDeclaration>;
105
+ /**
106
+ * Build the manifest — the declared catalog plus a stable content hash `version`
107
+ * (first 16 hex chars of the sha256 of the canonicalized catalog). The catalog is
108
+ * sorted by key first, so declaration order never changes the version.
109
+ */
110
+ declare function buildManifest(declaration: AuthzDeclaration): Promise<AuthzManifest>;
111
+ /**
112
+ * Publish this app's authorization manifest (its declared roles + permissions) to
113
+ * Cbox ID. The app owns what a role means; Cbox ID owns identity and who holds it.
114
+ *
115
+ * It mints a client-credentials token with the `apps.manifest` scope (token
116
+ * endpoint discovered from the issuer's OIDC configuration), then POSTs the
117
+ * manifest to `{issuer}/api/v1/apps/manifest`. Run it on deploy or from a script;
118
+ * an unchanged catalog is a server-side no-op.
119
+ *
120
+ * @returns the server's sync summary (`unchanged`, `roles_declared`, …).
121
+ * @throws ConfigurationError when config or the declaration is invalid.
122
+ * @throws AuthenticationError when the token cannot be minted or the push fails.
123
+ */
124
+ declare function publishManifest(config: ManifestPublisherConfig, declaration: AuthzDeclaration): Promise<ManifestSyncSummary>;
125
+
126
+ export { AuthenticationError, type AuthzDeclaration, type AuthzManifest, CboxIdError, ConfigurationError, InvalidStateError, type ManifestPublisherConfig, type ManifestSyncSummary, type PermissionDefinition, type RoleDefinition, buildManifest, challenge, createVerifier, defineAuthz, publishManifest, randomToken };
package/dist/index.d.ts CHANGED
@@ -34,4 +34,93 @@ declare function createVerifier(): string;
34
34
  /** The S256 code challenge for a verifier. */
35
35
  declare function challenge(verifier: string): Promise<string>;
36
36
 
37
- export { AuthenticationError, CboxIdError, ConfigurationError, InvalidStateError, challenge, createVerifier, randomToken };
37
+ /**
38
+ * A permission your app declares. `key` is a `feature:action` slug (e.g.
39
+ * `invoices:create`); `description` is human-facing copy for the Cbox ID console.
40
+ */
41
+ interface PermissionDefinition {
42
+ key: string;
43
+ description?: string;
44
+ }
45
+ /**
46
+ * A role your app declares. `permissions` lists the permission keys the role
47
+ * grants — each must reference a declared {@link PermissionDefinition}.
48
+ */
49
+ interface RoleDefinition {
50
+ key: string;
51
+ name: string;
52
+ description?: string;
53
+ permissions: string[];
54
+ }
55
+ /**
56
+ * The roles + permissions an app declares in code. Either list may be omitted.
57
+ * Pass this to {@link defineAuthz} (to validate up front) or straight to
58
+ * {@link buildManifest} / {@link publishManifest}.
59
+ */
60
+ interface AuthzDeclaration {
61
+ permissions?: PermissionDefinition[];
62
+ roles?: RoleDefinition[];
63
+ }
64
+ /**
65
+ * The manifest as it is sent to Cbox ID: the declared permissions + roles plus a
66
+ * content-derived `version`, so republishing an unchanged catalog is a no-op.
67
+ */
68
+ interface AuthzManifest {
69
+ version: string;
70
+ permissions: PermissionDefinition[];
71
+ roles: RoleDefinition[];
72
+ }
73
+ /** What {@link publishManifest} needs to authenticate the push. */
74
+ interface ManifestPublisherConfig {
75
+ /** Base URL (issuer) of the Cbox ID instance — the `token_endpoint` is discovered from it. */
76
+ issuer: string;
77
+ /** Your OAuth client id. The client must hold the `apps.manifest` scope. */
78
+ clientId: string;
79
+ /** Your OAuth client secret. The push uses the client-credentials grant. */
80
+ clientSecret: string;
81
+ /** Timeout (ms) for back-channel HTTP calls. Defaults to `10000`. */
82
+ timeoutMs?: number;
83
+ }
84
+ /**
85
+ * The server's sync summary. The named fields are the ones the SDK/CLI reads;
86
+ * the index signature keeps any extra fields the server returns.
87
+ */
88
+ interface ManifestSyncSummary {
89
+ unchanged?: boolean;
90
+ roles_declared?: number;
91
+ permissions_declared?: number;
92
+ version?: string;
93
+ [key: string]: unknown;
94
+ }
95
+ /**
96
+ * Validate a roles/permissions declaration and return it normalized (both lists
97
+ * always present). Call this where you declare your catalog so mistakes — a role
98
+ * that grants an undeclared permission, a duplicate key — surface immediately
99
+ * rather than on deploy.
100
+ *
101
+ * @throws ConfigurationError on a missing key/name, a duplicate, or a role that
102
+ * references a permission that was never declared.
103
+ */
104
+ declare function defineAuthz(declaration: AuthzDeclaration): Required<AuthzDeclaration>;
105
+ /**
106
+ * Build the manifest — the declared catalog plus a stable content hash `version`
107
+ * (first 16 hex chars of the sha256 of the canonicalized catalog). The catalog is
108
+ * sorted by key first, so declaration order never changes the version.
109
+ */
110
+ declare function buildManifest(declaration: AuthzDeclaration): Promise<AuthzManifest>;
111
+ /**
112
+ * Publish this app's authorization manifest (its declared roles + permissions) to
113
+ * Cbox ID. The app owns what a role means; Cbox ID owns identity and who holds it.
114
+ *
115
+ * It mints a client-credentials token with the `apps.manifest` scope (token
116
+ * endpoint discovered from the issuer's OIDC configuration), then POSTs the
117
+ * manifest to `{issuer}/api/v1/apps/manifest`. Run it on deploy or from a script;
118
+ * an unchanged catalog is a server-side no-op.
119
+ *
120
+ * @returns the server's sync summary (`unchanged`, `roles_declared`, …).
121
+ * @throws ConfigurationError when config or the declaration is invalid.
122
+ * @throws AuthenticationError when the token cannot be minted or the push fails.
123
+ */
124
+ declare function publishManifest(config: ManifestPublisherConfig, declaration: AuthzDeclaration): Promise<ManifestSyncSummary>;
125
+
126
+ export { AuthenticationError, type AuthzDeclaration, type AuthzManifest, CboxIdError, ConfigurationError, InvalidStateError, type ManifestPublisherConfig, type ManifestSyncSummary, type PermissionDefinition, type RoleDefinition, buildManifest, challenge, createVerifier, defineAuthz, publishManifest, randomToken };
package/dist/index.js CHANGED
@@ -1,3 +1,125 @@
1
- export { AuthenticationError, CboxIdClient, CboxIdError, ConfigurationError, InvalidStateError, VaultClient, challenge, createVerifier, randomToken, verifyWebhook } from './chunk-X5XNYQAD.js';
1
+ import { ConfigurationError, Discovery, AuthenticationError } from './chunk-U6KYO2XA.js';
2
+ export { AuthenticationError, CboxIdClient, CboxIdError, ConfigurationError, InvalidStateError, VaultClient, challenge, createVerifier, randomToken, verifyWebhook } from './chunk-U6KYO2XA.js';
3
+
4
+ // src/authz.ts
5
+ function defineAuthz(declaration) {
6
+ const permissions = declaration.permissions ?? [];
7
+ const roles = declaration.roles ?? [];
8
+ assertDeclaration(permissions, roles);
9
+ return { permissions, roles };
10
+ }
11
+ async function buildManifest(declaration) {
12
+ const permissions = (declaration.permissions ?? []).map(canonicalPermission);
13
+ const roles = (declaration.roles ?? []).map(canonicalRole);
14
+ assertDeclaration(permissions, roles);
15
+ permissions.sort((a, b) => a.key.localeCompare(b.key));
16
+ roles.sort((a, b) => a.key.localeCompare(b.key));
17
+ const version = (await sha256Hex(JSON.stringify({ permissions, roles }))).slice(0, 16);
18
+ return { version, permissions, roles };
19
+ }
20
+ async function publishManifest(config, declaration) {
21
+ if (!config.issuer || !config.clientId || !config.clientSecret) {
22
+ throw new ConfigurationError("Publishing a manifest needs issuer, clientId and clientSecret.");
23
+ }
24
+ const timeoutMs = config.timeoutMs ?? 1e4;
25
+ const manifest = await buildManifest(declaration);
26
+ const discovery = new Discovery(config.issuer, timeoutMs, 36e5);
27
+ const token = await mintToken(config, discovery, timeoutMs);
28
+ const response = await fetchWithTimeout(
29
+ `${config.issuer.replace(/\/$/, "")}/api/v1/apps/manifest`,
30
+ {
31
+ method: "POST",
32
+ headers: {
33
+ authorization: `Bearer ${token}`,
34
+ accept: "application/json",
35
+ "content-type": "application/json"
36
+ },
37
+ body: JSON.stringify(manifest)
38
+ },
39
+ timeoutMs
40
+ );
41
+ if (!response.ok) {
42
+ throw new AuthenticationError(`Manifest push failed: HTTP ${response.status} ${await response.text()}`);
43
+ }
44
+ const json = await response.json();
45
+ return json !== null && typeof json === "object" ? json : {};
46
+ }
47
+ async function mintToken(config, discovery, timeoutMs) {
48
+ const response = await fetchWithTimeout(
49
+ await discovery.endpoint("token_endpoint"),
50
+ {
51
+ method: "POST",
52
+ headers: { "content-type": "application/x-www-form-urlencoded" },
53
+ body: new URLSearchParams({
54
+ grant_type: "client_credentials",
55
+ client_id: config.clientId,
56
+ client_secret: config.clientSecret,
57
+ scope: "apps.manifest"
58
+ })
59
+ },
60
+ timeoutMs
61
+ );
62
+ const json = await response.json().catch(() => ({}));
63
+ if (typeof json.access_token !== "string" || json.access_token === "") {
64
+ throw new AuthenticationError(
65
+ "Could not obtain an apps.manifest access token \u2014 check the client credentials and that the client holds the apps.manifest scope."
66
+ );
67
+ }
68
+ return json.access_token;
69
+ }
70
+ function assertDeclaration(permissions, roles) {
71
+ const permissionKeys = /* @__PURE__ */ new Set();
72
+ for (const permission of permissions) {
73
+ if (!permission.key) {
74
+ throw new ConfigurationError("Every permission needs a non-empty `key`.");
75
+ }
76
+ if (permissionKeys.has(permission.key)) {
77
+ throw new ConfigurationError(`Permission "${permission.key}" is declared more than once.`);
78
+ }
79
+ permissionKeys.add(permission.key);
80
+ }
81
+ const roleKeys = /* @__PURE__ */ new Set();
82
+ for (const role of roles) {
83
+ if (!role.key) {
84
+ throw new ConfigurationError("Every role needs a non-empty `key`.");
85
+ }
86
+ if (!role.name) {
87
+ throw new ConfigurationError(`Role "${role.key}" needs a non-empty \`name\`.`);
88
+ }
89
+ if (roleKeys.has(role.key)) {
90
+ throw new ConfigurationError(`Role "${role.key}" is declared more than once.`);
91
+ }
92
+ roleKeys.add(role.key);
93
+ for (const reference of role.permissions) {
94
+ if (!permissionKeys.has(reference)) {
95
+ throw new ConfigurationError(
96
+ `Role "${role.key}" references permission "${reference}", which is not declared.`
97
+ );
98
+ }
99
+ }
100
+ }
101
+ }
102
+ function canonicalPermission(permission) {
103
+ return permission.description === void 0 ? { key: permission.key } : { key: permission.key, description: permission.description };
104
+ }
105
+ function canonicalRole(role) {
106
+ const permissions = [...role.permissions].sort((a, b) => a.localeCompare(b));
107
+ return role.description === void 0 ? { key: role.key, name: role.name, permissions } : { key: role.key, name: role.name, description: role.description, permissions };
108
+ }
109
+ async function sha256Hex(input) {
110
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
111
+ return Array.from(new Uint8Array(digest)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
112
+ }
113
+ async function fetchWithTimeout(url, init, timeoutMs) {
114
+ const controller = new AbortController();
115
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
116
+ try {
117
+ return await fetch(url, { ...init, signal: controller.signal });
118
+ } finally {
119
+ clearTimeout(timer);
120
+ }
121
+ }
122
+
123
+ export { buildManifest, defineAuthz, publishManifest };
2
124
  //# sourceMappingURL=index.js.map
3
125
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
1
+ {"version":3,"sources":["../src/authz.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { Discovery } from './discovery.js';\nimport { AuthenticationError, ConfigurationError } from './errors.js';\n\n/**\n * A permission your app declares. `key` is a `feature:action` slug (e.g.\n * `invoices:create`); `description` is human-facing copy for the Cbox ID console.\n */\nexport interface PermissionDefinition {\n key: string;\n description?: string;\n}\n\n/**\n * A role your app declares. `permissions` lists the permission keys the role\n * grants — each must reference a declared {@link PermissionDefinition}.\n */\nexport interface RoleDefinition {\n key: string;\n name: string;\n description?: string;\n permissions: string[];\n}\n\n/**\n * The roles + permissions an app declares in code. Either list may be omitted.\n * Pass this to {@link defineAuthz} (to validate up front) or straight to\n * {@link buildManifest} / {@link publishManifest}.\n */\nexport interface AuthzDeclaration {\n permissions?: PermissionDefinition[];\n roles?: RoleDefinition[];\n}\n\n/**\n * The manifest as it is sent to Cbox ID: the declared permissions + roles plus a\n * content-derived `version`, so republishing an unchanged catalog is a no-op.\n */\nexport interface AuthzManifest {\n version: string;\n permissions: PermissionDefinition[];\n roles: RoleDefinition[];\n}\n\n/** What {@link publishManifest} needs to authenticate the push. */\nexport interface ManifestPublisherConfig {\n /** Base URL (issuer) of the Cbox ID instance — the `token_endpoint` is discovered from it. */\n issuer: string;\n /** Your OAuth client id. The client must hold the `apps.manifest` scope. */\n clientId: string;\n /** Your OAuth client secret. The push uses the client-credentials grant. */\n clientSecret: string;\n /** Timeout (ms) for back-channel HTTP calls. Defaults to `10000`. */\n timeoutMs?: number;\n}\n\n/**\n * The server's sync summary. The named fields are the ones the SDK/CLI reads;\n * the index signature keeps any extra fields the server returns.\n */\nexport interface ManifestSyncSummary {\n unchanged?: boolean;\n roles_declared?: number;\n permissions_declared?: number;\n version?: string;\n [key: string]: unknown;\n}\n\n/**\n * Validate a roles/permissions declaration and return it normalized (both lists\n * always present). Call this where you declare your catalog so mistakes — a role\n * that grants an undeclared permission, a duplicate key — surface immediately\n * rather than on deploy.\n *\n * @throws ConfigurationError on a missing key/name, a duplicate, or a role that\n * references a permission that was never declared.\n */\nexport function defineAuthz(declaration: AuthzDeclaration): Required<AuthzDeclaration> {\n const permissions = declaration.permissions ?? [];\n const roles = declaration.roles ?? [];\n assertDeclaration(permissions, roles);\n return { permissions, roles };\n}\n\n/**\n * Build the manifest — the declared catalog plus a stable content hash `version`\n * (first 16 hex chars of the sha256 of the canonicalized catalog). The catalog is\n * sorted by key first, so declaration order never changes the version.\n */\nexport async function buildManifest(declaration: AuthzDeclaration): Promise<AuthzManifest> {\n const permissions = (declaration.permissions ?? []).map(canonicalPermission);\n const roles = (declaration.roles ?? []).map(canonicalRole);\n assertDeclaration(permissions, roles);\n\n permissions.sort((a, b) => a.key.localeCompare(b.key));\n roles.sort((a, b) => a.key.localeCompare(b.key));\n\n const version = (await sha256Hex(JSON.stringify({ permissions, roles }))).slice(0, 16);\n return { version, permissions, roles };\n}\n\n/**\n * Publish this app's authorization manifest (its declared roles + permissions) to\n * Cbox ID. The app owns what a role means; Cbox ID owns identity and who holds it.\n *\n * It mints a client-credentials token with the `apps.manifest` scope (token\n * endpoint discovered from the issuer's OIDC configuration), then POSTs the\n * manifest to `{issuer}/api/v1/apps/manifest`. Run it on deploy or from a script;\n * an unchanged catalog is a server-side no-op.\n *\n * @returns the server's sync summary (`unchanged`, `roles_declared`, …).\n * @throws ConfigurationError when config or the declaration is invalid.\n * @throws AuthenticationError when the token cannot be minted or the push fails.\n */\nexport async function publishManifest(\n config: ManifestPublisherConfig,\n declaration: AuthzDeclaration,\n): Promise<ManifestSyncSummary> {\n if (!config.issuer || !config.clientId || !config.clientSecret) {\n throw new ConfigurationError('Publishing a manifest needs issuer, clientId and clientSecret.');\n }\n\n const timeoutMs = config.timeoutMs ?? 10_000;\n const manifest = await buildManifest(declaration);\n const discovery = new Discovery(config.issuer, timeoutMs, 3_600_000);\n\n const token = await mintToken(config, discovery, timeoutMs);\n\n const response = await fetchWithTimeout(\n `${config.issuer.replace(/\\/$/, '')}/api/v1/apps/manifest`,\n {\n method: 'POST',\n headers: {\n authorization: `Bearer ${token}`,\n accept: 'application/json',\n 'content-type': 'application/json',\n },\n body: JSON.stringify(manifest),\n },\n timeoutMs,\n );\n\n if (!response.ok) {\n throw new AuthenticationError(`Manifest push failed: HTTP ${response.status} ${await response.text()}`);\n }\n\n const json = (await response.json()) as unknown;\n return json !== null && typeof json === 'object' ? (json as ManifestSyncSummary) : {};\n}\n\nasync function mintToken(\n config: ManifestPublisherConfig,\n discovery: Discovery,\n timeoutMs: number,\n): Promise<string> {\n const response = await fetchWithTimeout(\n await discovery.endpoint('token_endpoint'),\n {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: config.clientId,\n client_secret: config.clientSecret,\n scope: 'apps.manifest',\n }),\n },\n timeoutMs,\n );\n\n const json = (await response.json().catch(() => ({}))) as { access_token?: unknown };\n if (typeof json.access_token !== 'string' || json.access_token === '') {\n throw new AuthenticationError(\n 'Could not obtain an apps.manifest access token — check the client credentials and that the client holds the apps.manifest scope.',\n );\n }\n return json.access_token;\n}\n\nfunction assertDeclaration(permissions: PermissionDefinition[], roles: RoleDefinition[]): void {\n const permissionKeys = new Set<string>();\n for (const permission of permissions) {\n if (!permission.key) {\n throw new ConfigurationError('Every permission needs a non-empty `key`.');\n }\n if (permissionKeys.has(permission.key)) {\n throw new ConfigurationError(`Permission \"${permission.key}\" is declared more than once.`);\n }\n permissionKeys.add(permission.key);\n }\n\n const roleKeys = new Set<string>();\n for (const role of roles) {\n if (!role.key) {\n throw new ConfigurationError('Every role needs a non-empty `key`.');\n }\n if (!role.name) {\n throw new ConfigurationError(`Role \"${role.key}\" needs a non-empty \\`name\\`.`);\n }\n if (roleKeys.has(role.key)) {\n throw new ConfigurationError(`Role \"${role.key}\" is declared more than once.`);\n }\n roleKeys.add(role.key);\n for (const reference of role.permissions) {\n if (!permissionKeys.has(reference)) {\n throw new ConfigurationError(\n `Role \"${role.key}\" references permission \"${reference}\", which is not declared.`,\n );\n }\n }\n }\n}\n\n/** A permission with keys in a fixed order and no `undefined` fields (stable to hash). */\nfunction canonicalPermission(permission: PermissionDefinition): PermissionDefinition {\n return permission.description === undefined\n ? { key: permission.key }\n : { key: permission.key, description: permission.description };\n}\n\n/** A role with keys in a fixed order, sorted permission refs, and no `undefined` fields. */\nfunction canonicalRole(role: RoleDefinition): RoleDefinition {\n const permissions = [...role.permissions].sort((a, b) => a.localeCompare(b));\n return role.description === undefined\n ? { key: role.key, name: role.name, permissions }\n : { key: role.key, name: role.name, description: role.description, permissions };\n}\n\nasync function sha256Hex(input: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(input));\n return Array.from(new Uint8Array(digest))\n .map((byte) => byte.toString(16).padStart(2, '0'))\n .join('');\n}\n\nasync function fetchWithTimeout(url: string, init: RequestInit, timeoutMs: number): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n}\n"]}
package/dist/nextjs.js CHANGED
@@ -1,4 +1,4 @@
1
- import { CboxIdClient, ConfigurationError } from './chunk-X5XNYQAD.js';
1
+ import { CboxIdClient, ConfigurationError } from './chunk-U6KYO2XA.js';
2
2
  import { NextResponse } from 'next/server';
3
3
 
4
4
  var COOKIE = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cboxdk/id-js",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Turnkey Cbox ID client for JavaScript/TypeScript — OpenID Connect login (PKCE + id_token verification via JWKS), hosted profile-management redirect, machine tokens, UserInfo, RFC 7662 introspection, and webhook signature verification. Runs on Node, edge, and the browser, with a first-class Next.js adapter.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/pkce.ts","../src/vault.ts","../src/webhook.ts","../src/discovery.ts","../src/client.ts"],"names":["key"],"mappings":";;;AAIO,IAAM,WAAA,GAAN,cAA0B,KAAA,CAAM;AAAA,EACrC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,OAAO,GAAA,CAAA,MAAA,CAAW,IAAA;AAAA,EACzB;AACF;AAGO,IAAM,kBAAA,GAAN,cAAiC,WAAA,CAAY;AAAC;AAM9C,IAAM,iBAAA,GAAN,cAAgC,WAAA,CAAY;AAAC;AAM7C,IAAM,mBAAA,GAAN,cAAkC,WAAA,CAAY;AAAC;;;ACnBtD,SAAS,UAAU,KAAA,EAA2B;AAC5C,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAA,IAAU,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC/E;AAGO,SAAS,WAAA,CAAY,QAAQ,EAAA,EAAY;AAC9C,EAAA,OAAO,UAAU,MAAA,CAAO,eAAA,CAAgB,IAAI,UAAA,CAAW,KAAK,CAAC,CAAC,CAAA;AAChE;AAGO,SAAS,cAAA,GAAyB;AACvC,EAAA,OAAO,YAAY,EAAE,CAAA;AACvB;AAGA,eAAsB,UAAU,QAAA,EAAmC;AACjE,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,SAAA,EAAW,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,QAAQ,CAAC,CAAA;AACvF,EAAA,OAAO,SAAA,CAAU,IAAI,UAAA,CAAW,MAAM,CAAC,CAAA;AACzC;;;ACQO,IAAM,cAAN,MAAkB;AAAA,EAGvB,WAAA,CACE,MAAA,EACiB,KAAA,EACA,SAAA,GAAY,GAAA,EAC7B;AAFiB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AAEjB,IAAA,IAAA,CAAK,OAAO,CAAA,EAAG,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,aAAA,CAAA;AAAA,EAC1C;AAAA,EAJmB,KAAA;AAAA,EACA,SAAA;AAAA,EALF,IAAA;AAAA;AAAA,EAWjB,MAAM,KAAA,EAAkD;AACtD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAqB,MAAA,EAAQ,UAAA,EAAY;AAAA,MACnD,MAAM,KAAA,CAAM,IAAA;AAAA,MACZ,UAAU,KAAA,CAAM,QAAA;AAAA,MAChB,QAAQ,KAAA,CAAM,MAAA;AAAA,MACd,YAAY,KAAA,CAAM,SAAA;AAAA,MAClB,UAAU,KAAA,CAAM,OAAA;AAAA,MAChB,YAAY,KAAA,CAAM;AAAA,KACnB,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAA,CAAO,UAAkB,MAAA,EAAyC;AAChE,IAAA,OAAO,IAAA,CAAK,IAAA,CAAqB,MAAA,EAAQ,CAAA,SAAA,EAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,OAAA,CAAA,EAAW,EAAE,MAAA,EAAQ,CAAA;AAAA,EACxG;AAAA;AAAA,EAGA,MAAM,OAAO,QAAA,EAAiC;AAC5C,IAAA,MAAM,KAAK,OAAA,CAAQ,QAAA,EAAU,YAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAE,CAAA;AAAA,EACzE;AAAA;AAAA,EAGA,KAAA,CACE,QAAA,EACA,QAAA,EACA,aAAA,EAC+E;AAC/E,IAAA,OAAO,KAAK,IAAA,CAAK,MAAA,EAAQ,YAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,OAAA,CAAA,EAAW;AAAA,MAC1E,SAAA,EAAW,QAAA;AAAA,MACX,eAAA,EAAiB;AAAA,KAClB,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACf,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,OAAO,EAAE,UAAU,CAAA,CAAE,SAAA,EAAW,UAAU,CAAA,CAAE,SAAA,EAAW,aAAA,EAAe,CAAA,CAAE,eAAA,EAAgB;AAAA,IAC1F,CAAC,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,WAAA,CAAY,QAAA,EAAkB,QAAA,EAAiC;AACnE,IAAA,MAAM,IAAA,CAAK,OAAA;AAAA,MACT,QAAA;AAAA,MACA,YAAY,kBAAA,CAAmB,QAAQ,CAAC,CAAA,QAAA,EAAW,kBAAA,CAAmB,QAAQ,CAAC,CAAA;AAAA,KACjF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAA,CAAM,UAAkB,OAAA,EAAsC;AAC5D,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAA,SAAA,EAAY,mBAAmB,QAAQ,CAAC,CAAA,MAAA,CAAA,EAAU,EAAE,OAAA,EAAS,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ;AACpG,MAAA,MAAM,CAAA,GAAI,GAAA;AACV,MAAA,OAAO,EAAE,QAAA,EAAU,CAAA,CAAE,SAAA,EAAW,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,SAAA,EAAW,CAAA,CAAE,UAAA,EAAW;AAAA,IAClG,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,IAAA,CAAQ,MAAA,EAAgB,IAAA,EAAc,IAAA,EAA2C;AAC7F,IAAA,MAAM,WAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,MAAA,EAAQ,MAAM,IAAI,CAAA;AACtD,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA,EAEA,MAAc,OAAA,CAAQ,MAAA,EAAgB,IAAA,EAAc,IAAA,EAAmD;AACrG,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AACjE,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAoB;AAAA,QACxB,MAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,aAAA,EAAe,CAAA,OAAA,EAAU,IAAA,CAAK,KAAK,CAAA,CAAA;AAAA,UACnC,GAAI,IAAA,GAAO,EAAE,cAAA,EAAgB,kBAAA,KAAuB;AAAC,SACvD;AAAA,QACA,QAAQ,UAAA,CAAW;AAAA,OACrB;AACA,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAAA,MACjC;AACA,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,IAAI,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA;AACxD,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,IAAI,oBAAoB,CAAA,MAAA,EAAS,MAAM,IAAI,IAAI,CAAA,oBAAA,EAAuB,QAAA,CAAS,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,MAChG;AACA,MAAA,OAAO,QAAA;AAAA,IACT,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AACF;;;AC3HA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAoB;AACtD,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,QAAA,IAAY,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC9C;AACA,EAAA,OAAO,QAAA,KAAa,CAAA;AACtB;AAEA,SAAS,MAAM,KAAA,EAA4B;AACzC,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,UAAA,CAAW,KAAK,CAAC,CAAA,CACpC,IAAI,CAAC,CAAA,KAAM,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAC1C,KAAK,EAAE,CAAA;AACZ;AAgBA,eAAsB,cAAc,OAAA,EAAiD;AACnF,EAAA,MAAM,EAAE,OAAA,EAAS,eAAA,EAAiB,MAAA,EAAO,GAAI,OAAA;AAC7C,EAAA,MAAM,gBAAA,GAAmB,QAAQ,gBAAA,IAAoB,GAAA;AACrD,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,IAAO,IAAA,CAAK,MAAM,IAAA,CAAK,GAAA,KAAQ,GAAI,CAAA;AAEvD,EAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,QAAgC,EAAC;AACvC,EAAA,KAAA,MAAW,OAAA,IAAW,eAAA,CAAgB,KAAA,CAAM,GAAG,CAAA,EAAG;AAChD,IAAA,MAAM,CAACA,MAAK,KAAK,CAAA,GAAI,QAAQ,IAAA,EAAK,CAAE,KAAA,CAAM,GAAA,EAAK,CAAC,CAAA;AAChD,IAAA,IAAIA,IAAAA,EAAK;AACP,MAAA,KAAA,CAAMA,IAAG,IAAI,KAAA,IAAS,EAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,GAAG,CAAA,IAAK,EAAA;AAChC,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAI,CAAA,IAAK,EAAA;AAEjC,EAAA,IAAI,SAAA,KAAc,MAAM,SAAA,KAAc,EAAA,IAAM,CAAC,OAAA,CAAQ,IAAA,CAAK,SAAS,CAAA,EAAG;AACpE,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAK,GAAA,CAAI,GAAA,GAAM,OAAO,SAAS,CAAC,IAAI,gBAAA,EAAkB;AACxD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA;AAAA,IAC9B,KAAA;AAAA,IACA,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,MAAM,CAAA;AAAA,IAC/B,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,KAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AACA,EAAA,MAAM,QAAA,GAAW,KAAA;AAAA,IACf,MAAM,MAAA,CAAO,MAAA,CAAO,IAAA,CAAK,QAAQ,GAAA,EAAK,IAAI,WAAA,EAAY,CAAE,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,OAAO,EAAE,CAAC;AAAA,GAC3F;AAEA,EAAA,OAAO,eAAA,CAAgB,UAAU,SAAS,CAAA;AAC5C;;;ACxEO,IAAM,YAAN,MAAgB;AAAA,EAGrB,YACmB,MAAA,EACA,SAAA,EACA,UAAA,EACA,GAAA,GAAoB,KAAK,GAAA,EAC1C;AAJiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,SAAA,GAAA,SAAA;AACA,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AACA,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AAAA,EAChB;AAAA,EAJgB,MAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,GAAA;AAAA,EANX,MAAA,GAA+D,IAAA;AAAA,EASvE,MAAM,QAAA,GAAuC;AAC3C,IAAA,IAAI,KAAK,MAAA,IAAU,IAAA,CAAK,OAAO,SAAA,GAAY,IAAA,CAAK,KAAI,EAAG;AACrD,MAAA,OAAO,KAAK,MAAA,CAAO,GAAA;AAAA,IACrB;AAEA,IAAA,MAAM,MAAM,CAAA,EAAG,IAAA,CAAK,OAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,iCAAA,CAAA;AAC7C,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,QAAQ,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,SAAS,CAAA;AAEjE,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK,EAAE,MAAA,EAAQ,UAAA,CAAW,QAAQ,CAAA;AAC/D,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,qCAAA,EAAwC,QAAA,CAAS,MAAM,CAAA,CAAA,CAAG,CAAA;AAAA,MAC1F;AACA,MAAA,GAAA,GAAO,MAAM,SAAS,IAAA,EAAK;AAAA,IAC7B,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,iBAAiB,mBAAA,EAAqB;AACxC,QAAA,MAAM,KAAA;AAAA,MACR;AACA,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,0BAAA,EAA6B,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IAC5E,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAEA,IAAA,IAAI,OAAO,GAAA,CAAI,MAAA,KAAW,QAAA,IAAY,GAAA,CAAI,WAAW,EAAA,EAAI;AACvD,MAAA,MAAM,IAAI,oBAAoB,+CAA+C,CAAA;AAAA,IAC/E;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,EAAE,GAAA,EAAK,SAAA,EAAW,KAAK,GAAA,EAAI,GAAI,KAAK,UAAA,EAAW;AAC7D,IAAA,OAAO,GAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,SAAS,IAAA,EAAgD;AAC7D,IAAA,MAAM,KAAA,GAAA,CAAS,MAAM,IAAA,CAAK,QAAA,IAAY,IAAI,CAAA;AAC1C,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,EAAA,EAAI;AAC7C,MAAA,MAAM,IAAI,kBAAA,CAAmB,CAAA,kCAAA,EAAqC,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,IAC3E;AACA,IAAA,OAAO,KAAA;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,iBAAiB,IAAA,EAAuD;AAC5E,IAAA,MAAM,KAAA,GAAA,CAAS,MAAM,IAAA,CAAK,QAAA,IAAY,IAAI,CAAA;AAC1C,IAAA,OAAO,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,KAAK,KAAA,GAAQ,IAAA;AAAA,EAC7D;AACF,CAAA;;;AClBO,IAAM,eAAN,MAAmB;AAAA,EAIxB,YAA6B,MAAA,EAAsB;AAAtB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAC3B,IAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AAClB,MAAA,MAAM,IAAI,mBAAmB,sCAAsC,CAAA;AAAA,IACrE;AACA,IAAA,IAAI,CAAC,OAAO,QAAA,EAAU;AACpB,MAAA,MAAM,IAAI,mBAAmB,wCAAwC,CAAA;AAAA,IACvE;AACA,IAAA,IAAI,CAAC,OAAO,WAAA,EAAa;AACvB,MAAA,MAAM,IAAI,mBAAmB,2CAA2C,CAAA;AAAA,IAC1E;AACA,IAAA,IAAA,CAAK,YAAY,IAAI,SAAA;AAAA,MACnB,MAAA,CAAO,MAAA;AAAA,MACP,OAAO,SAAA,IAAa,GAAA;AAAA,MACpB,OAAO,UAAA,IAAc;AAAA,KACvB;AAAA,EACF;AAAA,EAf6B,MAAA;AAAA,EAHZ,SAAA;AAAA,EACA,SAAA,uBAAgB,GAAA,EAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwB3D,MAAM,0BAAA,CAA2B,OAAA,GAO7B,EAAC,EAAkC;AACrC,IAAA,MAAM,eAAe,cAAA,EAAe;AACpC,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,WAAA,CAAY,EAAE,CAAA;AAC7C,IAAA,MAAM,KAAA,GAAQ,YAAY,EAAE,CAAA;AAE5B,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB;AAAA,MACjC,aAAA,EAAe,MAAA;AAAA,MACf,SAAA,EAAW,KAAK,MAAA,CAAO,QAAA;AAAA,MACvB,YAAA,EAAc,OAAA,CAAQ,WAAA,IAAe,IAAA,CAAK,MAAA,CAAO,WAAA;AAAA,MACjD,QAAQ,OAAA,CAAQ,MAAA,IAAU,KAAK,MAAA,EAAO,EAAG,KAAK,GAAG,CAAA;AAAA,MACjD,KAAA;AAAA,MACA,KAAA;AAAA,MACA,cAAA,EAAgB,MAAM,SAAA,CAAU,YAAY,CAAA;AAAA,MAC5C,qBAAA,EAAuB;AAAA,KACxB,CAAA;AACD,IAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,MAAA,MAAA,CAAO,GAAA,CAAI,QAAA,EAAU,OAAA,CAAQ,MAAM,CAAA;AAAA,IACrC;AACA,IAAA,IAAI,QAAQ,SAAA,EAAW;AACrB,MAAA,MAAA,CAAO,GAAA,CAAI,YAAA,EAAc,OAAA,CAAQ,SAAS,CAAA;AAAA,IAC5C;AACA,IAAA,IAAI,OAAO,OAAA,CAAQ,MAAA,KAAW,QAAA,EAAU;AACtC,MAAA,MAAA,CAAO,GAAA,CAAI,SAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,wBAAwB,CAAA;AACvE,IAAA,OAAO,EAAE,GAAA,EAAK,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,EAAU,CAAA,CAAA,EAAI,KAAA,EAAO,YAAA,EAAc,KAAA,EAAM;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,KAAA,EAIG;AACpB,IAAA,MAAM,EAAE,MAAA,EAAQ,MAAA,EAAO,GAAI,KAAA;AAE3B,IAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,qBAAA,CAAsB,MAAA,CAAO,KAAA,EAAO,MAAA,CAAO,KAAK,CAAA,EAAG;AACxF,MAAA,MAAM,IAAI,kBAAkB,0EAAqE,CAAA;AAAA,IACnG;AAEA,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,MAAM,IAAI,mBAAA;AAAA,QACR,CAAA,2BAAA,EAA8B,MAAA,CAAO,KAAK,CAAA,EAAG,MAAA,CAAO,oBAAoB,CAAA,EAAA,EAAK,MAAA,CAAO,iBAAiB,CAAA,CAAA,CAAA,GAAM,EAAE,CAAA;AAAA,OAC/G;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,OAAO,IAAA,EAAM;AAChB,MAAA,MAAM,IAAI,oBAAoB,iDAAiD,CAAA;AAAA,IACjF;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,QAAA,CAAS,OAAO,IAAA,EAAM,MAAA,CAAO,YAAA,EAAc,KAAA,CAAM,WAAW,CAAA;AAEtF,IAAA,IAAI,CAAC,OAAO,YAAA,EAAc;AACxB,MAAA,MAAM,IAAI,oBAAoB,+BAA+B,CAAA;AAAA,IAC/D;AAEA,IAAA,IAAI,SAAkC,EAAC;AACvC,IAAA,IAAI,OAAO,QAAA,EAAU;AACnB,MAAA,MAAA,GAAS,MAAM,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,QAAA,EAAU,OAAO,KAAK,CAAA;AAAA,IACjE;AAEA,IAAA,MAAA,GAAS,EAAE,GAAG,MAAA,EAAQ,GAAI,MAAM,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,YAAY,CAAA,EAAG;AAEpE,IAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,IAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,EAAA,EAAI;AACzC,MAAA,MAAM,IAAI,oBAAoB,wCAAwC,CAAA;AAAA,IACxE;AAEA,IAAA,OAAO;AAAA,MACL,EAAA,EAAI,GAAA;AAAA,MACJ,KAAA,EAAO,OAAO,MAAA,CAAO,OAAO,MAAM,QAAA,GAAW,MAAA,CAAO,OAAO,CAAA,GAAI,IAAA;AAAA,MAC/D,IAAA,EAAM,OAAO,MAAA,CAAO,MAAM,MAAM,QAAA,GAAW,MAAA,CAAO,MAAM,CAAA,GAAI,IAAA;AAAA,MAC5D,cAAA,EAAgB,OAAO,MAAA,CAAO,KAAK,MAAM,QAAA,GAAW,MAAA,CAAO,KAAK,CAAA,GAAI,IAAA;AAAA,MACpE,MAAA;AAAA,MACA,aAAa,MAAA,CAAO,YAAA;AAAA,MACpB,YAAA,EAAc,OAAO,aAAA,IAAiB,IAAA;AAAA,MACtC,OAAA,EAAS,OAAO,QAAA,IAAY,IAAA;AAAA,MAC5B,WAAW,OAAO,MAAA,CAAO,UAAA,KAAe,QAAA,GAAW,OAAO,UAAA,GAAa;AAAA,KACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,QAAA,EAA2B;AACpC,IAAA,MAAM,IAAA,GAAO,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,EAAG,IAAA,CAAK,WAAA,EAAa,CAAA,CAAA;AAC1E,IAAA,OAAO,QAAA,GAAW,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,IAAI,eAAA,CAAgB,EAAE,SAAA,EAAW,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,CAAA,CAAA,GAAK,IAAA;AAAA,EAC3F;AAAA;AAAA,EAGA,MAAM,UAAU,QAAA,EAA2C;AACzD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,iBAAiB,sBAAsB,CAAA;AAC7E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,IAAA;AAAA,IACT;AACA,IAAA,OAAO,QAAA,GACH,CAAA,EAAG,QAAQ,CAAA,CAAA,EAAI,IAAI,eAAA,CAAgB,EAAE,wBAAA,EAA0B,QAAA,EAAU,CAAA,CAAE,QAAA,EAAU,CAAA,CAAA,GACrF,QAAA;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAA,CAAa,OAAA,GAAoD,EAAC,EAAoB;AAC1F,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,CAAgB;AAAA,MAC/B,UAAA,EAAY,oBAAA;AAAA,MACZ,SAAA,EAAW,KAAK,MAAA,CAAO,QAAA;AAAA,MACvB,aAAA,EAAe,KAAK,aAAA;AAAc,KACnC,CAAA;AACD,IAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAA,EAAG;AAC/C,MAAA,IAAA,CAAK,IAAI,OAAA,EAAS,OAAA,CAAQ,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IAC5C;AACA,IAAA,IAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,OAAA,CAAQ,QAAQ,CAAA;AAAA,IACvC;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,KAAK,SAAA,CAAU,QAAA,CAAS,gBAAgB,CAAA,EAAG,IAAI,CAAA;AACtF,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,8BAAA,EAAiC,MAAM,QAAA,CAAS,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IACxF;AACA,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,IAAI,OAAO,IAAA,CAAK,YAAA,KAAiB,QAAA,EAAU;AACzC,MAAA,MAAM,IAAI,oBAAoB,yCAAyC,CAAA;AAAA,IACzE;AACA,IAAA,OAAO,IAAA,CAAK,YAAA;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,SAAS,WAAA,EAAuD;AACpE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,iBAAiB,mBAAmB,CAAA;AAC1E,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,OAAO,EAAC;AAAA,IACV;AACA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,gBAAA,CAAiB,QAAA,EAAU;AAAA,MACrD,OAAA,EAAS,EAAE,aAAA,EAAe,CAAA,OAAA,EAAU,WAAW,CAAA,CAAA;AAAG,KACnD,CAAA;AACD,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,oBAAoB,0BAA0B,CAAA;AAAA,IAC1D;AACA,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAAW,KAAA,EAAiD;AAChE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,wBAAwB,CAAA;AACvE,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA,CAAA,EAAI,IAAA,CAAK,aAAA,EAAe,CAAA,CAAE,CAAA;AACpE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA;AAAA,MAC1B,QAAA;AAAA,MACA,IAAI,eAAA,CAAgB,EAAE,KAAA,EAAO,CAAA;AAAA,MAC7B,EAAE,aAAA,EAAe,CAAA,MAAA,EAAS,KAAK,CAAA,CAAA;AAAG,KACpC;AACA,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,oBAAoB,+BAA+B,CAAA;AAAA,IAC/D;AACA,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA;AAAA,EAGA,cAAc,OAAA,EAAiD;AAC7D,IAAA,OAAO,cAAc,OAAO,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAAA,EAAkC;AACtC,IAAA,OAAO,IAAI,YAAY,IAAA,CAAK,MAAA,CAAO,QAAQ,WAAA,EAAa,IAAA,CAAK,MAAA,CAAO,SAAA,IAAa,GAAM,CAAA;AAAA,EACzF;AAAA,EAEA,MAAc,QAAA,CAAS,IAAA,EAAc,QAAA,EAAkB,WAAA,EAA8C;AACnG,IAAA,MAAM,IAAA,GAAO,IAAI,eAAA,CAAgB;AAAA,MAC/B,UAAA,EAAY,oBAAA;AAAA,MACZ,IAAA;AAAA,MACA,YAAA,EAAc,WAAA,IAAe,IAAA,CAAK,MAAA,CAAO,WAAA;AAAA,MACzC,SAAA,EAAW,KAAK,MAAA,CAAO,QAAA;AAAA,MACvB,aAAA,EAAe;AAAA,KAChB,CAAA;AACD,IAAA,IAAI,IAAA,CAAK,OAAO,YAAA,EAAc;AAC5B,MAAA,IAAA,CAAK,GAAA,CAAI,eAAA,EAAiB,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA;AAAA,IACpD;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,IAAA,CAAK,MAAM,KAAK,SAAA,CAAU,QAAA,CAAS,gBAAgB,CAAA,EAAG,IAAI,CAAA;AACtF,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,uBAAA,EAA0B,MAAM,QAAA,CAAS,IAAA,EAAM,CAAA,CAAE,CAAA;AAAA,IACjF;AACA,IAAA,OAAQ,MAAM,SAAS,IAAA,EAAK;AAAA,EAC9B;AAAA,EAEA,MAAc,aAAA,CAAc,OAAA,EAAiB,KAAA,EAAiD;AAC5F,IAAA,MAAM,OAAA,GAAU,MAAM,IAAA,CAAK,SAAA,CAAU,SAAS,UAAU,CAAA;AACxD,IAAA,IAAI,QAAA,GAAW,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAO,CAAA;AACzC,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,GAAW,kBAAA,CAAmB,IAAI,GAAA,CAAI,OAAO,CAAC,CAAA;AAC9C,MAAA,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,OAAA,EAAS,QAAQ,CAAA;AAAA,IACtC;AAEA,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI;AACF,MAAA,CAAC,EAAE,OAAA,EAAQ,GAAI,MAAM,SAAA,CAAU,SAAS,QAAA,EAAU;AAAA,QAChD,MAAA,EAAQ,KAAK,MAAA,CAAO,MAAA;AAAA,QACpB,QAAA,EAAU,KAAK,MAAA,CAAO;AAAA,OACvB,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,mBAAA,CAAoB,CAAA,oCAAA,EAAuC,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,IACtF;AAEA,IAAA,IAAI,KAAA,IAAS,OAAA,CAAQ,OAAO,CAAA,KAAM,KAAA,EAAO;AACvC,MAAA,MAAM,IAAI,oBAAoB,0DAAqD,CAAA;AAAA,IACrF;AAEA,IAAA,OAAO,OAAA;AAAA,EACT;AAAA,EAEQ,MAAA,GAAmB;AACzB,IAAA,MAAM,MAAA,GAAS,KAAK,MAAA,CAAO,MAAA;AAC3B,IAAA,OAAO,MAAA,IAAU,OAAO,MAAA,GAAS,CAAA,GAAI,SAAS,CAAC,QAAA,EAAU,WAAW,OAAO,CAAA;AAAA,EAC7E;AAAA,EAEQ,WAAA,GAAsB;AAC5B,IAAA,MAAM,IAAA,GAAO,KAAK,MAAA,CAAO,WAAA;AACzB,IAAA,OAAO,IAAA,IAAQ,SAAS,EAAA,GAAK,CAAA,CAAA,EAAI,KAAK,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,CAAA,GAAK,WAAA;AAAA,EAC/D;AAAA,EAEQ,aAAA,GAAwB;AAC9B,IAAA,IAAI,CAAC,IAAA,CAAK,MAAA,CAAO,YAAA,EAAc;AAC7B,MAAA,MAAM,IAAI,mBAAmB,8DAA8D,CAAA;AAAA,IAC7F;AACA,IAAA,OAAO,KAAK,MAAA,CAAO,YAAA;AAAA,EACrB;AAAA,EAEQ,IAAA,CAAK,GAAA,EAAa,IAAA,EAAuB,OAAA,GAAkC,EAAC,EAAsB;AACxG,IAAA,OAAO,IAAA,CAAK,iBAAiB,GAAA,EAAK;AAAA,MAChC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,mCAAA,EAAqC,GAAG,OAAA,EAAQ;AAAA,MAC3E;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,MAAc,gBAAA,CAAiB,GAAA,EAAa,IAAA,EAAsC;AAChF,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAM,UAAA,CAAW,OAAM,EAAG,IAAA,CAAK,MAAA,CAAO,SAAA,IAAa,GAAM,CAAA;AAClF,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,MAAM,GAAA,EAAK,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,UAAA,CAAW,MAAA,EAAQ,CAAA;AAAA,IAChE,CAAA,SAAE;AACA,MAAA,YAAA,CAAa,KAAK,CAAA;AAAA,IACpB;AAAA,EACF;AACF;AAGA,SAAS,qBAAA,CAAsB,GAAW,CAAA,EAAoB;AAC5D,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AACA,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,QAAA,IAAY,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC9C;AACA,EAAA,OAAO,QAAA,KAAa,CAAA;AACtB","file":"chunk-X5XNYQAD.js","sourcesContent":["/**\n * Base class for every error this SDK throws, so callers can `catch (e) { if (e\n * instanceof CboxIdError) ... }` in one branch.\n */\nexport class CboxIdError extends Error {\n constructor(message: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/** The client is misconfigured (a required option is missing or empty). */\nexport class ConfigurationError extends CboxIdError {}\n\n/**\n * The login `state` did not match what was stored — the callback is forged or\n * stale. Treat as a fresh start, not an error to surface to the user.\n */\nexport class InvalidStateError extends CboxIdError {}\n\n/**\n * Login could not be completed: the provider returned an error, the callback was\n * missing a code, or a token / id_token failed verification.\n */\nexport class AuthenticationError extends CboxIdError {}\n","/**\n * PKCE (RFC 7636) and the random values the login flow needs, built on Web Crypto\n * (`globalThis.crypto`) so the same code runs on Node, edge runtimes and browsers.\n */\n\nfunction base64url(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** A URL-safe random token of `bytes` bytes (default 32), for state and nonce. */\nexport function randomToken(bytes = 32): string {\n return base64url(crypto.getRandomValues(new Uint8Array(bytes)));\n}\n\n/** A high-entropy PKCE code verifier. */\nexport function createVerifier(): string {\n return randomToken(32);\n}\n\n/** The S256 code challenge for a verifier. */\nexport async function challenge(verifier: string): Promise<string> {\n const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier));\n return base64url(new Uint8Array(digest));\n}\n","import { AuthenticationError } from './errors.js';\n\n/** A stored vault secret's metadata (never its plaintext). */\nexport interface VaultSecretRef {\n id: string;\n name: string;\n provider: string;\n ownerType: string | null;\n ownerId: string | null;\n expiresAt: string | null;\n revoked: boolean;\n}\n\n/** A brokered credential — the plaintext, for immediate use. */\nexport interface VaultLease {\n secretId: string;\n provider: string;\n secret: string;\n expiresAt: string;\n}\n\nexport interface StoreSecretInput {\n name: string;\n provider: string;\n secret: string;\n ownerType?: 'organization' | 'user';\n ownerId?: string;\n expiresAt?: string;\n}\n\n/**\n * Client for a Cbox ID instance's Token Vault API. Bind it to an access token\n * (obtain one with {@link CboxIdClient.machineToken}, scoped `vault.manage` for\n * provisioning or `vault.lease` for redeeming). All calls are server-to-server.\n */\nexport class VaultClient {\n private readonly base: string;\n\n constructor(\n issuer: string,\n private readonly token: string,\n private readonly timeoutMs = 10_000,\n ) {\n this.base = `${issuer.replace(/\\/$/, '')}/api/v1/vault`;\n }\n\n /** Ingest a downstream credential, sealed at rest (scope `vault.manage`). */\n store(input: StoreSecretInput): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', '/secrets', {\n name: input.name,\n provider: input.provider,\n secret: input.secret,\n owner_type: input.ownerType,\n owner_id: input.ownerId,\n expires_at: input.expiresAt,\n });\n }\n\n /** Rotate a secret's value, keeping its id and grants (scope `vault.manage`). */\n rotate(secretId: string, secret: string): Promise<VaultSecretRef> {\n return this.json<VaultSecretRef>('POST', `/secrets/${encodeURIComponent(secretId)}/rotate`, { secret });\n }\n\n /** Revoke a secret permanently (scope `vault.manage`). */\n async revoke(secretId: string): Promise<void> {\n await this.request('DELETE', `/secrets/${encodeURIComponent(secretId)}`);\n }\n\n /** Authorize an agent client to lease a secret (scope `vault.manage`). */\n grant(\n secretId: string,\n clientId: string,\n maxTtlSeconds?: number,\n ): Promise<{ secretId: string; clientId: string; maxTtlSeconds: number | null }> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/grants`, {\n client_id: clientId,\n max_ttl_seconds: maxTtlSeconds,\n }).then((raw) => {\n const r = raw as { secret_id: string; client_id: string; max_ttl_seconds: number | null };\n return { secretId: r.secret_id, clientId: r.client_id, maxTtlSeconds: r.max_ttl_seconds };\n });\n }\n\n /** Revoke an agent's authorization (scope `vault.manage`). */\n async revokeGrant(secretId: string, clientId: string): Promise<void> {\n await this.request(\n 'DELETE',\n `/secrets/${encodeURIComponent(secretId)}/grants/${encodeURIComponent(clientId)}`,\n );\n }\n\n /**\n * Redeem a leased credential for immediate use (scope `vault.lease`). The caller\n * is identified by the token's client; a lease with no live grant is refused.\n */\n lease(secretId: string, purpose: string): Promise<VaultLease> {\n return this.json('POST', `/secrets/${encodeURIComponent(secretId)}/lease`, { purpose }).then((raw) => {\n const r = raw as { secret_id: string; provider: string; secret: string; expires_at: string };\n return { secretId: r.secret_id, provider: r.provider, secret: r.secret, expiresAt: r.expires_at };\n });\n }\n\n private async json<T>(method: string, path: string, body: Record<string, unknown>): Promise<T> {\n const response = await this.request(method, path, body);\n return (await response.json()) as T;\n }\n\n private async request(method: string, path: string, body?: Record<string, unknown>): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const init: RequestInit = {\n method,\n headers: {\n authorization: `Bearer ${this.token}`,\n ...(body ? { 'content-type': 'application/json' } : {}),\n },\n signal: controller.signal,\n };\n if (body) {\n init.body = JSON.stringify(body);\n }\n const response = await fetch(`${this.base}${path}`, init);\n if (!response.ok) {\n throw new AuthenticationError(`Vault ${method} ${path} failed with status ${response.status}.`);\n }\n return response;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n","/**\n * Verify a Cbox ID webhook / inline-action signature. The header is\n * `X-Cbox-Signature: t={unix},v1={hex hmac}` — an HMAC-SHA256 over\n * `\"{timestamp}.{raw body}\"`, valid within a freshness window. Built on Web Crypto\n * so it runs on Node, edge and the browser.\n */\n\n/** Constant-time compare of two hex strings. */\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n\nfunction toHex(bytes: ArrayBuffer): string {\n return Array.from(new Uint8Array(bytes))\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nexport interface VerifyWebhookOptions {\n /** The RAW request body — the exact bytes received, not a re-encoded copy. */\n payload: string;\n /** The value of the `X-Cbox-Signature` header. */\n signatureHeader: string | null | undefined;\n /** The signing secret issued when the webhook/action endpoint was registered. */\n secret: string;\n /** Freshness window in seconds. Defaults to 300 (5 minutes). */\n toleranceSeconds?: number;\n /** Injectable clock (unix seconds), for tests. Defaults to `Date.now()`. */\n now?: number;\n}\n\n/** Returns `true` only when the signature is present, fresh and valid. Never throws. */\nexport async function verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n const { payload, signatureHeader, secret } = options;\n const toleranceSeconds = options.toleranceSeconds ?? 300;\n const now = options.now ?? Math.floor(Date.now() / 1000);\n\n if (!signatureHeader) {\n return false;\n }\n\n const parts: Record<string, string> = {};\n for (const segment of signatureHeader.split(',')) {\n const [key, value] = segment.trim().split('=', 2);\n if (key) {\n parts[key] = value ?? '';\n }\n }\n\n const timestamp = parts['t'] ?? '';\n const signature = parts['v1'] ?? '';\n\n if (timestamp === '' || signature === '' || !/^\\d+$/.test(timestamp)) {\n return false;\n }\n\n if (Math.abs(now - Number(timestamp)) > toleranceSeconds) {\n return false;\n }\n\n const key = await crypto.subtle.importKey(\n 'raw',\n new TextEncoder().encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n const expected = toHex(\n await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`${timestamp}.${payload}`)),\n );\n\n return timingSafeEqual(expected, signature);\n}\n","import { AuthenticationError, ConfigurationError } from './errors.js';\nimport type { DiscoveryDocument } from './types.js';\n\n/**\n * Fetches and caches an instance's OIDC discovery document. One instance of this\n * lives per {@link CboxIdClient}; the document is refetched only after the TTL.\n */\nexport class Discovery {\n private cached: { doc: DiscoveryDocument; expiresAt: number } | null = null;\n\n constructor(\n private readonly issuer: string,\n private readonly timeoutMs: number,\n private readonly cacheTtlMs: number,\n private readonly now: () => number = Date.now,\n ) {}\n\n async document(): Promise<DiscoveryDocument> {\n if (this.cached && this.cached.expiresAt > this.now()) {\n return this.cached.doc;\n }\n\n const url = `${this.issuer.replace(/\\/$/, '')}/.well-known/openid-configuration`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n\n let doc: DiscoveryDocument;\n try {\n const response = await fetch(url, { signal: controller.signal });\n if (!response.ok) {\n throw new AuthenticationError(`Discovery request failed with status ${response.status}.`);\n }\n doc = (await response.json()) as DiscoveryDocument;\n } catch (error) {\n if (error instanceof AuthenticationError) {\n throw error;\n }\n throw new AuthenticationError(`Discovery request failed: ${String(error)}`);\n } finally {\n clearTimeout(timer);\n }\n\n if (typeof doc.issuer !== 'string' || doc.issuer === '') {\n throw new AuthenticationError('The discovery document was missing an issuer.');\n }\n\n this.cached = { doc, expiresAt: this.now() + this.cacheTtlMs };\n return doc;\n }\n\n /** A required endpoint from the discovery document. */\n async endpoint(name: keyof DiscoveryDocument): Promise<string> {\n const value = (await this.document())[name];\n if (typeof value !== 'string' || value === '') {\n throw new ConfigurationError(`The instance does not advertise a ${name}.`);\n }\n return value;\n }\n\n /** An optional endpoint, or null when the instance advertises none. */\n async optionalEndpoint(name: keyof DiscoveryDocument): Promise<string | null> {\n const value = (await this.document())[name];\n return typeof value === 'string' && value !== '' ? value : null;\n }\n}\n","import { createRemoteJWKSet, jwtVerify, type JWTPayload } from 'jose';\nimport { Discovery } from './discovery.js';\nimport { AuthenticationError, ConfigurationError, InvalidStateError } from './errors.js';\nimport { challenge, createVerifier, randomToken } from './pkce.js';\nimport type {\n AuthorizationRequest,\n CboxIdConfig,\n CboxUser,\n TokenResponse,\n} from './types.js';\nimport { VaultClient } from './vault.js';\nimport { verifyWebhook, type VerifyWebhookOptions } from './webhook.js';\n\ntype JwksResolver = ReturnType<typeof createRemoteJWKSet>;\n\n/** Query parameters as they arrive on your callback route. */\nexport interface CallbackParams {\n code?: string | null;\n state?: string | null;\n error?: string | null;\n error_description?: string | null;\n}\n\n/** The values you persisted from {@link CboxIdClient.createAuthorizationRequest}. */\nexport interface StoredAuthState {\n state: string;\n codeVerifier: string;\n nonce: string;\n}\n\n/**\n * Turnkey Cbox ID client for JavaScript/TypeScript. It speaks standard OpenID\n * Connect against a Cbox ID instance — so integrating is a redirect and a callback,\n * not a rewrite — and adds the conveniences a hosted-identity product needs: a\n * redirect to the instance's hosted profile page, and back-channel helpers (machine\n * tokens, userinfo, introspection, webhook verification).\n *\n * Login is hardened by default: PKCE (S256), a CSRF state check, a nonce, and full\n * id_token signature + issuer + audience verification against the instance's JWKS\n * (via `jose`).\n *\n * The class is framework-agnostic: {@link createAuthorizationRequest} hands you the\n * `state`, `codeVerifier` and `nonce` to persist however you like, and\n * {@link authenticate} takes them back. For Next.js, the `@cboxdk/id-js/nextjs`\n * entry wires this to cookies for you.\n */\nexport class CboxIdClient {\n private readonly discovery: Discovery;\n private readonly jwksByUri = new Map<string, JwksResolver>();\n\n constructor(private readonly config: CboxIdConfig) {\n if (!config.issuer) {\n throw new ConfigurationError('Cbox ID config `issuer` is required.');\n }\n if (!config.clientId) {\n throw new ConfigurationError('Cbox ID config `clientId` is required.');\n }\n if (!config.redirectUri) {\n throw new ConfigurationError('Cbox ID config `redirectUri` is required.');\n }\n this.discovery = new Discovery(\n config.issuer,\n config.timeoutMs ?? 10_000,\n config.cacheTtlMs ?? 3_600_000,\n );\n }\n\n /**\n * Begin login. Returns the authorize URL plus the `state`, `codeVerifier` and\n * `nonce` — persist those (signed, httpOnly cookies are ideal) and hand them back\n * to {@link authenticate} on the callback.\n */\n async createAuthorizationRequest(options: {\n scopes?: string[];\n redirectUri?: string;\n state?: string;\n prompt?: string;\n loginHint?: string;\n maxAge?: number;\n } = {}): Promise<AuthorizationRequest> {\n const codeVerifier = createVerifier();\n const state = options.state ?? randomToken(16);\n const nonce = randomToken(16);\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: this.config.clientId,\n redirect_uri: options.redirectUri ?? this.config.redirectUri,\n scope: (options.scopes ?? this.scopes()).join(' '),\n state,\n nonce,\n code_challenge: await challenge(codeVerifier),\n code_challenge_method: 'S256',\n });\n if (options.prompt) {\n params.set('prompt', options.prompt);\n }\n if (options.loginHint) {\n params.set('login_hint', options.loginHint);\n }\n if (typeof options.maxAge === 'number') {\n params.set('max_age', String(options.maxAge));\n }\n\n const endpoint = await this.discovery.endpoint('authorization_endpoint');\n return { url: `${endpoint}?${params.toString()}`, state, codeVerifier, nonce };\n }\n\n /**\n * Complete login on your callback route: verify state, exchange the code with the\n * PKCE verifier, verify the id_token, and return the authenticated user.\n *\n * @throws InvalidStateError when state does not match (forged/stale request)\n * @throws AuthenticationError on any other failure\n */\n async authenticate(input: {\n params: CallbackParams;\n stored: StoredAuthState;\n redirectUri?: string;\n }): Promise<CboxUser> {\n const { params, stored } = input;\n\n if (!params.state || !stored.state || !timingSafeEqualString(params.state, stored.state)) {\n throw new InvalidStateError('The login state did not match — the request may be forged or stale.');\n }\n\n if (params.error) {\n throw new AuthenticationError(\n `Cbox ID returned an error: ${params.error}${params.error_description ? ` (${params.error_description})` : ''}`,\n );\n }\n\n if (!params.code) {\n throw new AuthenticationError('The callback was missing an authorization code.');\n }\n\n const tokens = await this.exchange(params.code, stored.codeVerifier, input.redirectUri);\n\n if (!tokens.access_token) {\n throw new AuthenticationError('No access token was returned.');\n }\n\n let claims: Record<string, unknown> = {};\n if (tokens.id_token) {\n claims = await this.verifyIdToken(tokens.id_token, stored.nonce);\n }\n // Enrich with userinfo (email/name/org a minimal id_token may omit).\n claims = { ...claims, ...(await this.userinfo(tokens.access_token)) };\n\n const sub = claims['sub'];\n if (typeof sub !== 'string' || sub === '') {\n throw new AuthenticationError('The verified token carried no subject.');\n }\n\n return {\n id: sub,\n email: typeof claims['email'] === 'string' ? claims['email'] : null,\n name: typeof claims['name'] === 'string' ? claims['name'] : null,\n organizationId: typeof claims['org'] === 'string' ? claims['org'] : null,\n claims,\n accessToken: tokens.access_token,\n refreshToken: tokens.refresh_token ?? null,\n idToken: tokens.id_token ?? null,\n expiresIn: typeof tokens.expires_in === 'number' ? tokens.expires_in : 0,\n };\n }\n\n /**\n * The URL of the instance's hosted account/profile page (self-service password,\n * MFA, passkeys, sessions). A signed-in user is authenticated there by their Cbox\n * ID session; `returnTo` is passed so the page can link back to your app.\n */\n profileUrl(returnTo?: string): string {\n const base = `${this.config.issuer.replace(/\\/$/, '')}${this.accountPath()}`;\n return returnTo ? `${base}?${new URLSearchParams({ return_to: returnTo }).toString()}` : base;\n }\n\n /** The RP-initiated logout URL, or null when the instance advertises none. */\n async logoutUrl(returnTo?: string): Promise<string | null> {\n const endpoint = await this.discovery.optionalEndpoint('end_session_endpoint');\n if (!endpoint) {\n return null;\n }\n return returnTo\n ? `${endpoint}?${new URLSearchParams({ post_logout_redirect_uri: returnTo }).toString()}`\n : endpoint;\n }\n\n /**\n * A machine (client-credentials) access token for calling Cbox ID APIs as your\n * app, not on a user's behalf. Requires a client secret.\n */\n async machineToken(options: { scopes?: string[]; resource?: string } = {}): Promise<string> {\n const body = new URLSearchParams({\n grant_type: 'client_credentials',\n client_id: this.config.clientId,\n client_secret: this.requireSecret(),\n });\n if (options.scopes && options.scopes.length > 0) {\n body.set('scope', options.scopes.join(' '));\n }\n if (options.resource) {\n body.set('resource', options.resource);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Machine token request failed: ${await response.text()}`);\n }\n const json = (await response.json()) as { access_token?: unknown };\n if (typeof json.access_token !== 'string') {\n throw new AuthenticationError('The token response had no access_token.');\n }\n return json.access_token;\n }\n\n /** The OIDC userinfo claims for an access token. */\n async userinfo(accessToken: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.optionalEndpoint('userinfo_endpoint');\n if (!endpoint) {\n return {};\n }\n const response = await this.fetchWithTimeout(endpoint, {\n headers: { authorization: `Bearer ${accessToken}` },\n });\n if (!response.ok) {\n throw new AuthenticationError('Userinfo request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /**\n * RFC 7662 token introspection (confidential-client auth). Returns the raw\n * response; `active` tells you if the token is currently valid. Requires a secret.\n */\n async introspect(token: string): Promise<Record<string, unknown>> {\n const endpoint = await this.discovery.endpoint('introspection_endpoint');\n const basic = btoa(`${this.config.clientId}:${this.requireSecret()}`);\n const response = await this.post(\n endpoint,\n new URLSearchParams({ token }),\n { authorization: `Basic ${basic}` },\n );\n if (!response.ok) {\n throw new AuthenticationError('Introspection request failed.');\n }\n return (await response.json()) as Record<string, unknown>;\n }\n\n /** Verify a Cbox ID webhook / inline-action signature. See {@link verifyWebhook}. */\n verifyWebhook(options: VerifyWebhookOptions): Promise<boolean> {\n return verifyWebhook(options);\n }\n\n /**\n * A Token Vault client bound to an access token. Obtain the token with\n * {@link machineToken} (scope `vault.manage` to provision/grant, `vault.lease` to\n * redeem), then call `store` / `grant` / `lease` etc.\n */\n vault(accessToken: string): VaultClient {\n return new VaultClient(this.config.issuer, accessToken, this.config.timeoutMs ?? 10_000);\n }\n\n private async exchange(code: string, verifier: string, redirectUri?: string): Promise<TokenResponse> {\n const body = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n redirect_uri: redirectUri ?? this.config.redirectUri,\n client_id: this.config.clientId,\n code_verifier: verifier,\n });\n if (this.config.clientSecret) {\n body.set('client_secret', this.config.clientSecret);\n }\n\n const response = await this.post(await this.discovery.endpoint('token_endpoint'), body);\n if (!response.ok) {\n throw new AuthenticationError(`Token exchange failed: ${await response.text()}`);\n }\n return (await response.json()) as TokenResponse;\n }\n\n private async verifyIdToken(idToken: string, nonce: string): Promise<Record<string, unknown>> {\n const jwksUri = await this.discovery.endpoint('jwks_uri');\n let resolver = this.jwksByUri.get(jwksUri);\n if (!resolver) {\n resolver = createRemoteJWKSet(new URL(jwksUri));\n this.jwksByUri.set(jwksUri, resolver);\n }\n\n let payload: JWTPayload;\n try {\n ({ payload } = await jwtVerify(idToken, resolver, {\n issuer: this.config.issuer,\n audience: this.config.clientId,\n }));\n } catch (error) {\n throw new AuthenticationError(`The id_token could not be verified: ${String(error)}`);\n }\n\n if (nonce && payload['nonce'] !== nonce) {\n throw new AuthenticationError('The id_token nonce did not match — possible replay.');\n }\n\n return payload as Record<string, unknown>;\n }\n\n private scopes(): string[] {\n const scopes = this.config.scopes;\n return scopes && scopes.length > 0 ? scopes : ['openid', 'profile', 'email'];\n }\n\n private accountPath(): string {\n const path = this.config.accountPath;\n return path && path !== '' ? `/${path.replace(/^\\//, '')}` : '/settings';\n }\n\n private requireSecret(): string {\n if (!this.config.clientSecret) {\n throw new ConfigurationError('This call requires a `clientSecret`, but none is configured.');\n }\n return this.config.clientSecret;\n }\n\n private post(url: string, body: URLSearchParams, headers: Record<string, string> = {}): Promise<Response> {\n return this.fetchWithTimeout(url, {\n method: 'POST',\n headers: { 'content-type': 'application/x-www-form-urlencoded', ...headers },\n body,\n });\n }\n\n private async fetchWithTimeout(url: string, init: RequestInit): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.config.timeoutMs ?? 10_000);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/** Constant-time string compare, so state validation doesn't leak via timing. */\nfunction timingSafeEqualString(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n let mismatch = 0;\n for (let i = 0; i < a.length; i++) {\n mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return mismatch === 0;\n}\n"]}