cauthy-auth 0.35.2 → 0.36.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/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react.tsx","../src/passkey.ts","../src/url.ts","../src/theme.ts","../src/validate.ts","../src/client.ts","../src/permissions.ts","../src/components.tsx"],"sourcesContent":["// React: who is signed in, in the browser.\n//\n// <CauthyProvider> // once, at the root\n// <App />\n// </CauthyProvider>\n//\n// const { session, status, signIn, signOut } = useSession()\n//\n// The browser never holds a token: it asks the application's own server\n// (`/api/auth/session`), which answers who is signed in and their\n// organizations. The session is kept current by asking again a little before\n// it expires and when the window comes back into view.\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { createAuthClient, type AuthClient } from './client'\nimport type { PublicSession } from './types'\nimport { withoutTrailingSlashes } from './url'\n\nexport type { JsonValue, PublicSession, SessionOrganization, SessionUser } from './types'\nexport { can, definePolicy, type PermissionOf, type Policy, type RoleOf } from './permissions'\n\nexport interface SessionContext {\n /** The signed-in person and their organizations, or null. */\n session: PublicSession | null\n status: 'loading' | 'authenticated' | 'unauthenticated'\n /** Sends the browser to sign in, and back to `returnTo` (default: where it is now). */\n signIn(options?: { returnTo?: string; locale?: string; prompt?: 'login' }): void\n /** Signs out of this application and of Cauthy in this browser. */\n signOut(): void\n /** Asks the server again who is signed in. */\n refresh(): Promise<PublicSession | null>\n /** Where the person looks after their account: password, second step, passkeys. */\n accountUrl(returnTo?: string): string\n /** Where the server mounted the routes. */\n basePath: string\n}\n\nexport interface CauthyProviderProps {\n children: ReactNode\n /** Where the server mounted the routes. Default: `/api/auth`. */\n basePath?: string\n /**\n * The session the server already read while rendering (SSR): the first\n * paint is then right, with no \"loading\". `null` means \"nobody\"; leave it\n * out when the server did not look.\n */\n initialSession?: PublicSession | null\n /**\n * The language the person reads, for what Cauthy mails them from\n * `useAuth()` and the ready-made forms (a sign-in link, a new password, a\n * confirmation): a tag like `es` or `es-CO`, or a function that answers it\n * when the person can change it. Default: the page's own (`<html lang>`),\n * else the browser's.\n */\n locale?: string | (() => string | undefined)\n}\n\nconst Ctx = createContext<SessionContext | null>(null)\n// The provider's `locale`, read when a request goes out: not part of what\n// `useSession()` answers.\nconst LocaleCtx = createContext<() => string | undefined>(() => undefined)\n\n/** Ask again this long before the session's token runs out. */\nconst AHEAD_MS = 60_000\n\nexport function CauthyProvider({ children, basePath = '/api/auth', initialSession, locale }: CauthyProviderProps) {\n const base = withoutTrailingSlashes(basePath)\n // The latest `locale`, behind one function that does not change: a new\n // language reaches the next request without making the clients again.\n const said = useRef(locale)\n said.current = locale\n const readLocale = useCallback(() => {\n const l = said.current\n return typeof l === 'function' ? l() : l\n }, [])\n const [session, setSession] = useState<PublicSession | null>(initialSession ?? null)\n const [status, setStatus] = useState<SessionContext['status']>(\n initialSession === undefined ? 'loading' : initialSession === null ? 'unauthenticated' : 'authenticated',\n )\n const asking = useRef<Promise<PublicSession | null> | null>(null)\n\n const refresh = useCallback((): Promise<PublicSession | null> => {\n asking.current ??= (async () => {\n try {\n const res = await fetch(`${base}/session`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(String(res.status))\n const body = (await res.json()) as { session: PublicSession | null; status: string }\n // \"expired\" is the server unable to reach Cauthy: what is on screen\n // stays, and the next ask settles it.\n if (body.status !== 'expired') {\n setSession(body.session)\n setStatus(body.session ? 'authenticated' : 'unauthenticated')\n }\n return body.session\n } catch {\n setStatus((s) => (s === 'loading' ? 'unauthenticated' : s))\n return null\n } finally {\n asking.current = null\n }\n })()\n return asking.current\n }, [base])\n\n useEffect(() => {\n if (initialSession === undefined) void refresh()\n }, [initialSession, refresh])\n\n useEffect(() => {\n if (!session) return\n const wait = Math.max(new Date(session.expiresAt).getTime() - Date.now() - AHEAD_MS, 5_000)\n const timer = setTimeout(() => void refresh(), wait)\n return () => clearTimeout(timer)\n }, [session, refresh])\n\n useEffect(() => {\n const onVisible = () => {\n if (document.visibilityState === 'visible') void refresh()\n }\n document.addEventListener('visibilitychange', onVisible)\n return () => document.removeEventListener('visibilitychange', onVisible)\n }, [refresh])\n\n const value = useMemo<SessionContext>(\n () => ({\n session,\n status,\n refresh,\n signIn(options = {}) {\n const q = new URLSearchParams({ return_to: options.returnTo ?? window.location.pathname + window.location.search })\n if (options.locale) q.set('locale', options.locale)\n if (options.prompt) q.set('prompt', options.prompt)\n window.location.assign(`${base}/login?${q}`)\n },\n signOut() {\n window.location.assign(`${base}/logout`)\n },\n accountUrl(returnTo) {\n const back = returnTo ?? (typeof window === 'undefined' ? '/' : window.location.pathname + window.location.search)\n return `${base}/account?return_to=${encodeURIComponent(back)}`\n },\n basePath: base,\n }),\n [session, status, refresh, base],\n )\n return <Ctx.Provider value={value}><LocaleCtx.Provider value={readLocale}>{children}</LocaleCtx.Provider></Ctx.Provider>\n}\n\nexport function useSession(): SessionContext {\n const ctx = useContext(Ctx)\n if (ctx === null) throw new Error('cauthy-auth: useSession needs <CauthyProvider> above it')\n return ctx\n}\n\n/**\n * The application's own sign-in screens: the functions a form calls.\n *\n * const { signIn, signUp, forgotPassword, signOut, session } = useAuth()\n * const r = await signIn.email({ email, password })\n *\n * They are `createAuthClient()`'s, and what is on screen follows them: after\n * a sign-in or a sign-out, `session` is the new one with no reload.\n */\nexport function useAuth(): AuthClient & Pick<SessionContext, 'session' | 'status' | 'refresh'> {\n const { session, status, refresh, basePath } = useSession()\n const locale = useContext(LocaleCtx)\n return useMemo(() => {\n const client = createAuthClient({ basePath, locale })\n const then = async <T,>(running: Promise<T>): Promise<T> => {\n const r = await running\n await refresh()\n return r\n }\n return {\n ...client,\n signIn: {\n ...client.signIn, anonymously: (f) => then(client.signIn.anonymously(f)), email: (f) => then(client.signIn.email(f)), mfa: (f) => then(client.signIn.mfa(f)), mfaPushWait: (o) => then(client.signIn.mfaPushWait(o)), magicLinkVerify: (f) => then(client.signIn.magicLinkVerify(f)), emailCode: (f) => then(client.signIn.emailCode(f)),\n passkey: (o) => then(client.signIn.passkey(o)), passkeyAutofill: (o) => then(client.signIn.passkeyAutofill(o)), googleOneTap: (o) => then(client.signIn.googleOneTap(o)),\n },\n signUp: { email: (f) => then(client.signUp.email(f)) },\n // The invited person is signed in once they accept.\n acceptInvitation: (token, password) => then(client.acceptInvitation(token, password)),\n signOut: () => then(client.signOut()),\n account: {\n ...client.account,\n // What is on screen says the new name, and knows when the session ended.\n update: (f) => then(client.account.update(f)),\n changePassword: (f) => then(client.account.changePassword(f)),\n signOutEverywhere: () => then(client.account.signOutEverywhere()),\n // The guest is now the account: what is on screen says so.\n upgrade: (f) => then(client.account.upgrade(f)),\n },\n session,\n status,\n refresh,\n }\n }, [basePath, locale, refresh, session, status])\n}\n\nexport { createAuthClient, type Account as AccountDetails, type AccountClient, type AccountSession, type AuthClient, type ConnectedAgent, type AuthError, type AuthMethods, type AuthResult, type Invitation, type LinkedIdentity, type OrganizationPerson, type OrganizationRoleChoice, type OrganizationSeat, type OrganizationsClient, type Passkey, type PasskeyKind, type PendingLegal, type SecondStep, type SSOConnection, canAutofillPasskeys, canUsePasskeys } from './client'\nexport {\n AcceptInvite, Account, AccountAgents, AccountEmail, AccountLinked, AccountPasskeys, AccountPassword, AccountPhone, AccountProfile, AccountSecondStep, AccountSessions,\n ForgotPassword, GoogleOneTap, OrganizationMembers, PendingTerms, ResetPassword, SignIn, SignUp, VerifyEmail,\n type AcceptInviteEvent, type AcceptInviteProps, type AccountEvent, type AccountPartProps, type AccountProps, type AccountSection,\n type OrganizationMembersAction, type OrganizationMembersEvent, type OrganizationMembersProps, type PendingTermsProps,\n type AuthAlertProps, type AuthBadgeProps, type AuthButtonProps, type AuthCheckboxProps, type AuthComponents, type AuthConfirmOptions, type AuthDividerProps,\n type AuthFieldProps, type AuthFormLayoutProps, type AuthFormProps, type AuthInputProps, type AuthLinkProps, type AuthSelectProps, type AuthTextProps, type AuthTexts, type GoogleOneTapProps,\n} from './components'\n","// A passkey ceremony in the browser: what Cauthy says to ask for, in the\n// shape the browser's WebAuthn API takes, and what the browser answers, in\n// the shape Cauthy reads. Both travel as JSON, with bytes in base64url.\n\nimport type { AuthError } from './client'\n\n/** Whether this browser can use a passkey at all. */\nexport function canUsePasskeys(): boolean {\n return typeof window !== 'undefined' && typeof window.PublicKeyCredential === 'function' &&\n typeof navigator !== 'undefined' && typeof navigator.credentials?.get === 'function'\n}\n\n/**\n * Whether this browser offers passkeys in the autofill of a field marked\n * `autocomplete=\"username webauthn\"`, so the person picks one without\n * looking for a button.\n */\nexport async function canAutofillPasskeys(): Promise<boolean> {\n if (!canUsePasskeys()) return false\n const pkc = window.PublicKeyCredential as unknown as { isConditionalMediationAvailable?: () => Promise<boolean> }\n try {\n return typeof pkc.isConditionalMediationAvailable === 'function' && (await pkc.isConditionalMediationAvailable()) === true\n } catch {\n return false\n }\n}\n\nfunction bytes(text: string): ArrayBuffer {\n const b64 = text.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(text.length / 4) * 4, '=')\n const bin = atob(b64)\n const out = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out.buffer\n}\n\nfunction text(buf: ArrayBuffer | null | undefined): string | null {\n if (!buf) return null\n const view = new Uint8Array(buf)\n let bin = ''\n for (let i = 0; i < view.byteLength; i++) bin += String.fromCharCode(view[i])\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nconst withId = (list: any[] | undefined) => (list ?? []).map((c) => ({ ...c, id: bytes(c.id) }))\n\n/**\n * Asks the browser for a passkey, with the options Cauthy sent. `conditional`:\n * in the autofill of the page's username field, waiting until the person\n * picks one or `signal` aborts.\n */\nexport async function getPasskey(options: any, how: { mediation?: 'conditional'; signal?: AbortSignal } = {}): Promise<Record<string, unknown>> {\n const publicKey = { ...options, challenge: bytes(options.challenge), allowCredentials: withId(options.allowCredentials) }\n const cred = (await navigator.credentials.get({ publicKey, ...how } as CredentialRequestOptions)) as PublicKeyCredential | null\n if (cred === null) throw new DOMException('No passkey was chosen.', 'NotAllowedError')\n const r = cred.response as AuthenticatorAssertionResponse\n return {\n id: cred.id, rawId: text(cred.rawId), type: cred.type,\n response: {\n authenticatorData: text(r.authenticatorData), clientDataJSON: text(r.clientDataJSON),\n signature: text(r.signature), userHandle: text(r.userHandle),\n },\n clientExtensionResults: cred.getClientExtensionResults?.() ?? {},\n }\n}\n\n/** Asks the browser to make a passkey, with the options Cauthy sent. */\nexport async function makePasskey(options: any): Promise<Record<string, unknown>> {\n const publicKey = {\n ...options,\n challenge: bytes(options.challenge),\n user: { ...options.user, id: bytes(options.user.id) },\n excludeCredentials: withId(options.excludeCredentials),\n }\n const cred = (await navigator.credentials.create({ publicKey })) as PublicKeyCredential | null\n if (cred === null) throw new DOMException('No passkey was made.', 'NotAllowedError')\n const r = cred.response as AuthenticatorAttestationResponse\n return {\n id: cred.id, rawId: text(cred.rawId), type: cred.type,\n response: {\n clientDataJSON: text(r.clientDataJSON), attestationObject: text(r.attestationObject),\n transports: typeof r.getTransports === 'function' ? r.getTransports() : [],\n },\n clientExtensionResults: cred.getClientExtensionResults?.() ?? {},\n }\n}\n\n/** What the browser's refusal means, for the screen. */\nexport function ceremonyError(e: unknown): AuthError {\n const name = e instanceof Error || e instanceof DOMException ? e.name : ''\n if (name === 'NotAllowedError' || name === 'AbortError') return { code: 'cancelled', message: 'The passkey was not used. Try again when you are ready.' }\n if (name === 'InvalidStateError') return { code: 'passkey_exists', message: 'This device already has a passkey for this account.' }\n if (name === 'SecurityError') return { code: 'passkey_unavailable', message: 'Passkeys cannot be used on this page.' }\n return { code: 'passkey_failed', message: 'The passkey could not be used. Try again, or sign in another way.' }\n}\n","/**\n * The address without its trailing slashes: `https://auth.example.com/` and\n * `https://auth.example.com` name the same issuer. A loop, not `/\\/+$/`,\n * which backtracks over a long run of slashes.\n */\nexport function withoutTrailingSlashes(s: string): string {\n let end = s.length\n while (end > 0 && s.charCodeAt(end - 1) === 47) end--\n return s.slice(0, end)\n}\n","// An application's look, for Cauthy's hosted pages.\n//\n// Cauthy's pages — sign-in, sign-up, the account page — can take the colours,\n// corners, typeface and logo of the application that sends its people there,\n// so signing in reads as a page of the application. A theme is a short list of\n// values, which Cauthy checks one by one; it is never CSS.\n//\n// An application built with Stackmyth already has those values, as its\n// `--sm-*` tokens. `themeFromStackmyth` reads them out of its stylesheets.\n\nimport { withoutTrailingSlashes } from './url'\n\n/** How an application looks on Cauthy's hosted pages. Every value is optional. */\n/** One font file the application serves: a family in one weight (or a range) and one style. */\nexport interface ThemeFont {\n family: string\n /** An https address of a `.woff2` file. It must answer with `Access-Control-Allow-Origin` for Cauthy's origin. */\n url: string\n /** `400`, or `\"100 900\"` for a variable font. Default: 400. */\n weight?: number | string\n style?: 'normal' | 'italic'\n}\n\n/** What an application says on its sign-in page, in one language. */\nexport interface ThemeTexts {\n /** Replaces \"Sign in\". */\n heading?: string\n /** Replaces \"to continue to …\". */\n subheading?: string\n /** The messages of the split layout's panel, shown one at a time (up to 5). */\n panel?: string[]\n /** Links at the foot of the split layout: privacy, terms (up to 4). */\n links?: { label: string; url: string }[]\n}\n\nexport interface CauthyTheme {\n /** The page. Colours are `#rrggbb` or `rgba(r, g, b, a)`. */\n background?: string\n /** The card, and inputs. */\n surface?: string\n /** Headings and what is typed. */\n text?: string\n /** Paragraphs, labels, small print. */\n textMuted?: string\n border?: string\n /** The fields and the secondary buttons, when they are not the card's colours. */\n inputBackground?: string\n inputBorder?: string\n /** The main button, and what is written on it. */\n primary?: string\n primaryText?: string\n /** Links, and the focus ring. */\n accent?: string\n error?: string\n errorBackground?: string\n success?: string\n successBackground?: string\n /** Corners of cards and inputs, in pixels (0–40). */\n radius?: number\n /** Corners of buttons, in pixels (0–40). */\n buttonRadius?: number\n /** A CSS font-family list: the application's typeface first, a system font after it. */\n fontFamily?: string\n /** The files of the typefaces `fontFamily` names, for people who do not have them installed. */\n fonts?: ThemeFont[]\n /** An image shown where \"Cauthy\" is, over https. */\n logoUrl?: string\n /**\n * How the sign-in pages are laid out: `card` (the default, one card in the\n * middle) or `split` (the form on one side, a panel that presents the\n * application on the other).\n */\n layout?: 'card' | 'split'\n /** The colours the split layout's backdrop blends, one to four. */\n panelColors?: string[]\n /** The colour of what is written on the panel. */\n panelText?: string\n /** An https image shown over the panel's messages. */\n panelIconUrl?: string\n /** The application's own words on the sign-in page, by language (`en`, `es`). */\n texts?: Record<string, ThemeTexts>\n /**\n * The application's Stackmyth tokens (`--sm-*`), from `tokensFromStackmyth`.\n * Cauthy's pages are drawn with Stackmyth's components, so these make its\n * buttons and fields the application's own. They are laid over the named values.\n */\n tokens?: Record<string, string>\n}\n\nexport interface StackmythThemeOptions {\n /**\n * The named theme to read, when the stylesheet keeps several under\n * `[data-theme=…]` (`\"vennet\"`). Without it only what applies to every\n * page (`:root`) is read.\n */\n theme?: string\n /** Which of the application's two modes to take. Default: `light`. */\n mode?: 'light' | 'dark'\n logoUrl?: string\n}\n\nexport interface ImportedTheme {\n theme: CauthyTheme\n /** Tokens that were there and could not be carried over, and why. */\n warnings: string[]\n}\n\nconst MAX_RADIUS = 40\n\n// ── Reading custom properties out of CSS ───────────────────────────────────\n\ninterface Declaration {\n name: string\n value: string\n /** The selectors and at-rules it sits inside, outermost first. */\n within: string[]\n}\n\n// The stylesheet without its /* comments */, read in one pass. An unclosed\n// comment runs to the end, as a browser reads it.\nfunction withoutComments(css: string): string {\n let out = ''\n let i = 0\n for (;;) {\n const open = css.indexOf('/*', i)\n if (open < 0) return out + css.slice(i)\n out += css.slice(i, open)\n const close = css.indexOf('*/', open + 2)\n if (close < 0) return out\n i = close + 2\n }\n}\n\nfunction declarations(css: string): Declaration[] {\n const text = withoutComments(css)\n const out: Declaration[] = []\n const within: string[] = []\n let chunk = ''\n let quote = ''\n let depth = 0 // parentheses, so a `;` inside url(…) does not end anything\n const flush = () => {\n const m = /^\\s*(--[\\w-]+)\\s*:\\s*([\\s\\S]+?)\\s*$/.exec(chunk)\n if (m) out.push({ name: m[1], value: m[2].replace(/\\s+/g, ' ').replace(/\\s*!important$/, ''), within: [...within] })\n chunk = ''\n }\n for (const ch of text) {\n if (quote) {\n chunk += ch\n if (ch === quote) quote = ''\n continue\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch\n chunk += ch\n } else if (ch === '(') {\n depth++\n chunk += ch\n } else if (ch === ')') {\n depth = Math.max(0, depth - 1)\n chunk += ch\n } else if (ch === '{' && depth === 0) {\n within.push(chunk.trim().replace(/\\s+/g, ' '))\n chunk = ''\n } else if (ch === '}' && depth === 0) {\n flush()\n within.pop()\n } else if (ch === ';' && depth === 0) {\n flush()\n } else {\n chunk += ch\n }\n }\n return out\n}\n\nconst DARK = /prefers-color-scheme:\\s*dark|data-(mode|theme|color-scheme)=[\"']?dark|\\.dark\\b/i\nconst LIGHT = /prefers-color-scheme:\\s*light|data-(mode|theme|color-scheme)=[\"']?light|\\.light\\b/i\nconst NAMED = /data-theme=[\"']?([\\w-]+)/i\n\n/** Whether a declaration applies to the page being themed. */\nfunction applies(d: Declaration, o: Required<Pick<StackmythThemeOptions, 'mode'>> & { theme?: string }): boolean {\n for (const scope of d.within) {\n if (o.mode === 'light' && DARK.test(scope)) return false\n if (o.mode === 'dark' && LIGHT.test(scope)) return false\n const named = NAMED.exec(scope)\n if (named && !/^(dark|light)$/i.test(named[1]) && named[1] !== o.theme) return false\n // Component-level rules (`.btn { --sm-… }`) are not the page's theme;\n // the class a mode is switched with (`.dark`, as shadcn/ui does) is.\n if (!scope.startsWith('@') && !/:root|^html\\b|^body\\b|\\[data-|^\\*$|:host|^\\.(dark|light)\\b/.test(scope)) return false\n }\n return true\n}\n\n// ── Tokens ─────────────────────────────────────────────────────────────────\n\n/** What a token's value may be written with, as Cauthy checks it. */\nconst TOKEN_CHARS = /^[A-Za-z0-9 #%.,()/'\"_+*-]+$/\nconst TOKEN_FUNCS = new Set(['var', 'calc', 'min', 'max', 'clamp', 'rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color',\n 'color-mix', 'light-dark', 'cubic-bezier', 'steps', 'linear', 'linear-gradient', 'radial-gradient', 'conic-gradient',\n 'repeating-linear-gradient', 'repeating-radial-gradient', 'drop-shadow', 'blur', 'translate', 'translatex', 'translatey', 'scale', 'rotate'])\n\nfunction tokenValue(value: string): string | null {\n const v = value.replace(/\\s+/g, ' ').trim()\n if (v === '' || v.length > 400 || !TOKEN_CHARS.test(v)) return null\n for (const m of v.matchAll(/([A-Za-z-]+)\\(/g)) if (!TOKEN_FUNCS.has(m[1].toLowerCase())) return null\n if (/^\\(|[ ,(]\\(/.test(v)) return null\n return v\n}\n\n/** A scope that is the page's theme itself: the root, or the theme and mode attributes — never a component inside it. */\nconst THEME_SELECTOR = /^(?::root|html|body|\\[data-(?:theme|mode|color-scheme)(?:=[\"']?[\\w-]+[\"']?)?\\])$/i\n// Checked a selector at a time (split on commas and spaces) rather than with\n// one pattern over the list, which backtracks on a long one.\nconst isThemeScope = (selectors: string) => {\n const parts = selectors.split(/[\\s,]+/).filter(Boolean)\n return parts.length > 0 && parts.every((one) => THEME_SELECTOR.test(one))\n}\n\nexport interface StackmythTokens {\n /** Every `--sm-*` token the stylesheets set for the page, ready for `theme.tokens`. */\n tokens: Record<string, string>\n /** Tokens that were there and Cauthy would not take, and why. */\n warnings: string[]\n}\n\n/**\n * Reads an application's Stackmyth tokens out of its stylesheets: every\n * `--sm-*` custom property its theme sets, in the order the sheets are given\n * (a later one wins). Its own names — a brand palette the tokens point at —\n * are written in, so what comes out stands on Stackmyth's names alone.\n *\n * Cauthy's sign-in pages are drawn with Stackmyth's components: these tokens\n * are what makes them look like the application.\n */\nexport function tokensFromStackmyth(css: string | string[], options: StackmythThemeOptions = {}): StackmythTokens {\n const mode = options.mode ?? 'light'\n const all = (Array.isArray(css) ? css : [css]).flatMap(declarations)\n const named = options.theme ?? all.map((d) => d.within.map((w) => NAMED.exec(w)?.[1]).find((n) => n && !/^(dark|light)$/i.test(n))).find(Boolean)\n const vars = new Map<string, string>()\n for (const d of all) {\n if (!applies(d, { mode, theme: named })) continue\n if (!d.within.every((w) => w.startsWith('@') || isThemeScope(w))) continue\n vars.set(d.name, d.value)\n }\n // The application's own names are written in; Stackmyth's are left as references.\n const inline = (value: string, depth = 0): string | null => {\n if (depth > 16) return null\n let failed = false\n let out = value\n for (let guard = 0; guard < 64; guard++) {\n const next = out.replace(/var\\(\\s*(--(?!sm-)[\\w-]+)\\s*(?:,\\s*([^()]*(?:\\([^()]*\\)[^()]*)*))?\\)/, (_m, name: string, fallback?: string) => {\n const known = vars.get(name)\n const got = known !== undefined ? inline(known, depth + 1) : fallback !== undefined ? inline(fallback.trim(), depth + 1) : null\n if (got === null) failed = true\n return got ?? ''\n })\n if (failed) return null\n if (next === out) break\n out = next\n }\n return out\n }\n const tokens: Record<string, string> = {}\n const warnings: string[] = []\n for (const [name, raw] of vars) {\n if (!/^--sm-[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) continue\n const written = inline(raw)\n const value = written === null ? null : tokenValue(written)\n if (value === null) warnings.push(`${name}: \"${raw.length > 60 ? raw.slice(0, 57) + '…' : raw}\" is not a value Cauthy takes`)\n else tokens[name] = value\n }\n if (Object.keys(tokens).length === 0) warnings.push('no --sm-* token was found in these stylesheets')\n return { tokens, warnings }\n}\n\n// ── Values ─────────────────────────────────────────────────────────────────\n\nfunction resolve(value: string, vars: Map<string, string>, seen = 0): string | null {\n if (seen > 16) return null\n let unresolved = false\n // Innermost var() first: fallbacks may hold another var().\n let out = value\n for (let guard = 0; guard < 32 && /var\\(/.test(out); guard++) {\n out = out.replace(/var\\(\\s*(--[\\w-]+)\\s*(?:,\\s*([^()]*(?:\\([^()]*\\)[^()]*)*))?\\)/, (_m, name: string, fallback?: string) => {\n const known = vars.get(name)\n const next = known !== undefined ? resolve(known, vars, seen + 1) : fallback !== undefined ? resolve(fallback.trim(), vars, seen + 1) : null\n if (next === null) unresolved = true\n return next ?? ''\n })\n if (unresolved) return null\n }\n return /var\\(/.test(out) ? null : out.trim()\n}\n\nconst clamp01 = (n: number) => Math.min(1, Math.max(0, n))\nconst hex2 = (n: number) => Math.round(clamp01(n) * 255).toString(16).padStart(2, '0')\nconst gamma = (c: number) => (c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055)\n\nfunction out(r: number, g: number, b: number, a = 1): string {\n if (a >= 1) return `#${hex2(r)}${hex2(g)}${hex2(b)}`\n return `rgba(${Math.round(clamp01(r) * 255)}, ${Math.round(clamp01(g) * 255)}, ${Math.round(clamp01(b) * 255)}, ${Math.round(clamp01(a) * 1000) / 1000})`\n}\n\nconst alpha = (s: string | undefined) => (s === undefined ? 1 : s.endsWith('%') ? parseFloat(s) / 100 : parseFloat(s))\n\nconst KEYWORDS: Record<string, string> = { white: '#ffffff', black: '#000000' }\n\n/** A colour as Cauthy takes it — `#rrggbb` or `rgba(…)` — or null when it is none it can read. */\nexport function toColor(value: string): string | null {\n const v = value.trim().toLowerCase()\n if (KEYWORDS[v]) return KEYWORDS[v]\n if (/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(v)) return v\n let m = /^rgba?\\(\\s*([\\d.]+%?)[\\s,]+([\\d.]+%?)[\\s,]+([\\d.]+%?)(?:\\s*[,/]\\s*([\\d.]+%?))?\\s*\\)$/.exec(v)\n if (m) {\n const ch = (s: string) => (s.endsWith('%') ? parseFloat(s) / 100 : parseFloat(s) / 255)\n return out(ch(m[1]), ch(m[2]), ch(m[3]), alpha(m[4]))\n }\n m = /^hsla?\\(\\s*([\\d.]+)(?:deg)?[\\s,]+([\\d.]+)%[\\s,]+([\\d.]+)%(?:\\s*[,/]\\s*([\\d.]+%?))?\\s*\\)$/.exec(v)\n if (m) {\n const h = ((parseFloat(m[1]) % 360) + 360) % 360\n const s = parseFloat(m[2]) / 100\n const l = parseFloat(m[3]) / 100\n const f = (n: number) => {\n const k = (n + h / 30) % 12\n return l - s * Math.min(l, 1 - l) * Math.max(-1, Math.min(k - 3, 9 - k, 1))\n }\n return out(f(0), f(8), f(4), alpha(m[4]))\n }\n m = /^oklch\\(\\s*([\\d.]+%?)\\s+([\\d.]+%?)\\s+([\\d.]+)(?:deg)?(?:\\s*\\/\\s*([\\d.]+%?))?\\s*\\)$/.exec(v)\n if (m) {\n const L = m[1].endsWith('%') ? parseFloat(m[1]) / 100 : parseFloat(m[1])\n const C = m[2].endsWith('%') ? (parseFloat(m[2]) / 100) * 0.4 : parseFloat(m[2])\n const H = (parseFloat(m[3]) * Math.PI) / 180\n const a = C * Math.cos(H)\n const b = C * Math.sin(H)\n const l = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3)\n const mm = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3)\n const s = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3)\n return out(\n gamma(4.0767416621 * l - 3.3077115913 * mm + 0.2309699292 * s),\n gamma(-1.2684380046 * l + 2.6097574011 * mm - 0.3413193965 * s),\n gamma(-0.0041960863 * l - 0.7034186147 * mm + 1.707614701 * s),\n alpha(m[4]),\n )\n }\n return null\n}\n\n/** A length in pixels, within what Cauthy takes, or null. */\nfunction toRadius(value: string): number | null {\n const m = /^([\\d.]+)(px|rem|em)?$/.exec(value.trim())\n if (!m) return null\n const px = parseFloat(m[1]) * (m[2] === 'rem' || m[2] === 'em' ? 16 : 1)\n return Number.isFinite(px) ? Math.min(MAX_RADIUS, Math.max(0, Math.round(px))) : null\n}\n\n/** A font list as Cauthy takes it, or null. */\nfunction toFont(value: string): string | null {\n const v = value.trim()\n return /^[A-Za-z0-9 ,'\"_-]{1,200}$/.test(v) && (v.match(/\"/g)?.length ?? 0) % 2 === 0 && (v.match(/'/g)?.length ?? 0) % 2 === 0 ? v : null\n}\n\n// ── Stackmyth ──────────────────────────────────────────────────────────────\n\n/** Which Stackmyth token each value of a theme is read from, first found wins. */\nconst COLORS: [keyof CauthyTheme, string[]][] = [\n ['background', ['--sm-bg-surface', '--sm-surface']],\n ['surface', ['--sm-bg-surface-raised', '--sm-surface-raised']],\n ['text', ['--sm-text-primary', '--sm-surface-text']],\n ['textMuted', ['--sm-text-secondary']],\n ['border', ['--sm-border-default', '--sm-surface-border']],\n ['primary', ['--sm-primary', '--sm-bg-interactive']],\n ['primaryText', ['--sm-primary-text', '--sm-text-inverse']],\n ['accent', ['--sm-text-brand', '--sm-border-focus', '--sm-accent']],\n ['error', ['--sm-error-soft-text', '--sm-error']],\n ['errorBackground', ['--sm-error-soft']],\n ['success', ['--sm-success-soft-text', '--sm-success']],\n ['successBackground', ['--sm-success-soft']],\n]\n\n/**\n * Reads an application's Stackmyth theme out of its stylesheets.\n *\n * Give it the CSS that declares the tokens, in the order the application\n * loads it — Stackmyth's own (`@stackmyth/core/core.vars.css`, or a theme\n * file) and then the application's brand file that re-points them. Tokens\n * that point at the application's own variables are followed. The\n * application's dark mode is left out unless asked for.\n */\nexport function themeFromStackmyth(css: string | string[], options: StackmythThemeOptions = {}): ImportedTheme {\n const o = { mode: options.mode ?? 'light', theme: options.theme }\n const vars = new Map<string, string>()\n for (const sheet of Array.isArray(css) ? css : [css]) {\n for (const d of declarations(sheet)) if (applies(d, o)) vars.set(d.name, d.value)\n }\n const theme: CauthyTheme = {}\n const warnings: string[] = []\n\n const read = <T>(tokens: string[], to: (v: string) => T | null, what: string): T | undefined => {\n for (const token of tokens) {\n const raw = vars.get(token)\n if (raw === undefined) continue\n const value = resolve(raw, vars)\n const got = value === null ? null : to(value)\n if (got !== null) return got\n warnings.push(`${token}: \"${raw}\" is not ${what} Cauthy can take`)\n }\n return undefined\n }\n\n for (const [field, tokens] of COLORS) {\n const c = read(tokens, toColor, 'a colour')\n if (c !== undefined) (theme as Record<string, unknown>)[field] = c\n }\n const radius = read(['--sm-radius-container', '--sm-radius-md'], toRadius, 'a length')\n if (radius !== undefined) theme.radius = radius\n const button = read(['--sm-radius-interactive', '--sm-radius-sm'], toRadius, 'a length')\n if (button !== undefined) theme.buttonRadius = button\n const font = read(['--sm-font-family'], toFont, 'a font list')\n if (font !== undefined) theme.fontFamily = font\n if (options.logoUrl) theme.logoUrl = options.logoUrl\n\n if (vars.size === 0) warnings.push('no custom properties were found: is this the stylesheet that declares the --sm-* tokens?')\n else if (![...vars.keys()].some((k) => k.startsWith('--sm-'))) warnings.push('no --sm-* token was found in these stylesheets')\n return { theme, warnings }\n}\n\n// ── Any stylesheet ─────────────────────────────────────────────────────────\n\n/** The values of a theme a stylesheet can say. */\nexport type ThemeField =\n | 'background' | 'surface' | 'text' | 'textMuted' | 'border' | 'inputBackground' | 'inputBorder'\n | 'primary' | 'primaryText' | 'accent' | 'error' | 'errorBackground' | 'success' | 'successBackground'\n | 'radius' | 'buttonRadius' | 'fontFamily'\n\n/** How a stylesheet names its look: Stackmyth's tokens, shadcn/ui's (and Tailwind's), or the application's own. */\nexport type CssFormat = 'stackmyth' | 'shadcn' | 'custom'\n\nexport interface CssThemeOptions {\n /** Which names to read. Default: `auto`, told from the stylesheet itself. */\n format?: CssFormat | 'auto'\n /** Which of the application's two modes to take. Default: `light`. */\n mode?: 'light' | 'dark'\n /** The named theme to read, when the stylesheet keeps several under `[data-theme=…]`. */\n theme?: string\n /** For `custom`: the variable each value is read from, `{ primary: '--brand' }`. */\n map?: Partial<Record<ThemeField, string>>\n}\n\nexport interface CssImportedTheme extends ImportedTheme {\n /** The names that were read. */\n format: CssFormat\n}\n\nconst RADII: ThemeField[] = ['radius', 'buttonRadius']\n\n/** shadcn/ui's names, as Tailwind 3 (`--primary`) and Tailwind 4 (`--color-primary`) write them. */\nconst SHADCN: [ThemeField, string[]][] = [\n ['background', ['--background', '--color-background']],\n ['surface', ['--card', '--color-card', '--popover', '--color-popover']],\n ['text', ['--foreground', '--color-foreground']],\n ['textMuted', ['--muted-foreground', '--color-muted-foreground']],\n ['border', ['--border', '--color-border']],\n ['inputBorder', ['--input', '--color-input']],\n ['primary', ['--primary', '--color-primary']],\n ['primaryText', ['--primary-foreground', '--color-primary-foreground']],\n ['accent', ['--ring', '--color-ring', '--primary', '--color-primary']],\n ['error', ['--destructive', '--color-destructive']],\n ['radius', ['--radius']],\n ['buttonRadius', ['--radius']],\n ['fontFamily', ['--font-sans', '--font-family']],\n]\n\n/** A colour as shadcn/ui writes it on Tailwind 3 — `222.2 84% 4.9%`, the inside of hsl() — or any other. */\nfunction shadcnColor(value: string): string | null {\n return /^[\\d.]+(?:deg)?\\s+[\\d.]+%\\s+[\\d.]+%(?:\\s*\\/\\s*[\\d.]+%?)?$/.test(value.trim()) ? toColor(`hsl(${value.trim()})`) : toColor(value)\n}\n\n/** Every custom property a stylesheet sets for the page, the last one winning. */\nfunction pageVariables(css: string | string[], mode: 'light' | 'dark', theme?: string): Map<string, string> {\n const vars = new Map<string, string>()\n for (const sheet of Array.isArray(css) ? css : [css]) {\n for (const d of declarations(sheet)) if (applies(d, { mode, theme })) vars.set(d.name, d.value)\n }\n return vars\n}\n\n/** The custom properties a stylesheet sets for the page, by name: what a person picks from to map their own. */\nexport function cssVariables(css: string | string[], options: Pick<CssThemeOptions, 'mode' | 'theme'> = {}): string[] {\n return [...pageVariables(css, options.mode ?? 'light', options.theme).keys()].sort()\n}\n\n/**\n * Reads an application's look out of its stylesheets, whatever names it uses:\n * Stackmyth's tokens, shadcn/ui's (`--primary`, `--radius`, on Tailwind 3 or\n * 4), or the application's own variables given in `map`. What comes out is a\n * theme of named values, never CSS.\n */\nexport function themeFromCss(css: string | string[], options: CssThemeOptions = {}): CssImportedTheme {\n const mode = options.mode ?? 'light'\n const vars = pageVariables(css, mode, options.theme)\n const names = [...vars.keys()]\n let format: CssFormat\n if (options.format && options.format !== 'auto') format = options.format\n else if (options.map && Object.keys(options.map).length > 0) format = 'custom'\n else if (names.some((n) => n.startsWith('--sm-'))) format = 'stackmyth'\n else if (names.some((n) => /^--(color-)?(primary|background|foreground)$/.test(n))) format = 'shadcn'\n else format = 'custom'\n\n if (format === 'stackmyth') return { ...themeFromStackmyth(css, { mode, theme: options.theme }), format }\n\n const spec: [ThemeField, string[]][] = format === 'shadcn'\n ? SHADCN\n : Object.entries(options.map ?? {}).filter(([, v]) => v).map(([k, v]) => [k as ThemeField, [String(v).startsWith('--') ? String(v) : `--${v}`]])\n const theme: CauthyTheme = {}\n const warnings: string[] = []\n for (const [field, tokens] of spec) {\n for (const token of tokens) {\n const raw = vars.get(token)\n if (raw === undefined) continue\n const value = resolve(raw, vars)\n const got = value === null ? null\n : RADII.includes(field) ? toRadius(value)\n : field === 'fontFamily' ? toFont(value)\n : format === 'shadcn' ? shadcnColor(value) : toColor(value)\n if (got !== null) {\n (theme as Record<string, unknown>)[field] = got\n break\n }\n warnings.push(`${token}: \"${raw.length > 60 ? raw.slice(0, 57) + '…' : raw}\" is not ${RADII.includes(field) ? 'a length' : field === 'fontFamily' ? 'a font list' : 'a colour'} Cauthy can take`)\n }\n }\n if (vars.size === 0) warnings.push('no custom properties were found in these stylesheets')\n else if (format === 'custom' && spec.length === 0) warnings.push('these stylesheets use names of their own: say which variable each value is read from')\n return { theme, warnings, format }\n}\n\n// ── On the application's own screens ───────────────────────────────────────\n\n/**\n * A theme as the CSS variables of `cauthy-auth/styles.css` (`--cauthy-*`), for\n * the forms an application shows on its own pages. The page's own background,\n * the layout and the words are Cauthy's pages' matter, and left out.\n */\nexport function themeVariables(theme: CauthyTheme): Record<string, string> {\n const vars: Record<string, string> = {}\n const put = (name: string, v: string | number | undefined) => {\n if (v === undefined || v === '') return\n vars[`--cauthy-${name}`] = typeof v === 'number' ? `${v}px` : v\n }\n put('surface', theme.surface)\n put('text', theme.text)\n put('text-muted', theme.textMuted)\n put('border', theme.border)\n put('input-background', theme.inputBackground)\n put('input-border', theme.inputBorder)\n put('primary', theme.primary)\n put('primary-text', theme.primaryText)\n put('accent', theme.accent)\n put('error', theme.error)\n put('error-background', theme.errorBackground)\n put('success', theme.success)\n put('success-background', theme.successBackground)\n put('radius', theme.radius)\n put('button-radius', theme.buttonRadius)\n put('font', theme.fontFamily)\n return vars\n}\n\n// ── Sending it to Cauthy ───────────────────────────────────────────────────\n\n/** A theme as Cauthy's API names its values. */\nexport function toWire(theme: CauthyTheme): Record<string, unknown> {\n const names: Record<keyof CauthyTheme, string> = {\n background: 'background', surface: 'surface', text: 'text', textMuted: 'text_muted', border: 'border',\n primary: 'primary', primaryText: 'primary_text', accent: 'accent', error: 'error', errorBackground: 'error_background',\n success: 'success', successBackground: 'success_background', radius: 'radius', buttonRadius: 'button_radius',\n fontFamily: 'font_family', logoUrl: 'logo_url', fonts: 'fonts', layout: 'layout', panelColors: 'panel_colors',\n panelText: 'panel_text', panelIconUrl: 'panel_icon_url', texts: 'texts', inputBackground: 'input_background', inputBorder: 'input_border', tokens: 'tokens',\n }\n const wire: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(theme)) {\n if (v === undefined || v === '' || (Array.isArray(v) && v.length === 0)) continue\n wire[names[k as keyof CauthyTheme]] = v\n }\n return wire\n}\n\n/** A theme as Cauthy answers it, in this package's names. */\nexport function fromWire(wire: Record<string, unknown>): CauthyTheme {\n const names: Record<string, keyof CauthyTheme> = {\n background: 'background', surface: 'surface', text: 'text', text_muted: 'textMuted', border: 'border',\n primary: 'primary', primary_text: 'primaryText', accent: 'accent', error: 'error', error_background: 'errorBackground',\n success: 'success', success_background: 'successBackground', radius: 'radius', button_radius: 'buttonRadius',\n font_family: 'fontFamily', logo_url: 'logoUrl', fonts: 'fonts', layout: 'layout', panel_colors: 'panelColors',\n panel_text: 'panelText', panel_icon_url: 'panelIconUrl', texts: 'texts', input_background: 'inputBackground', input_border: 'inputBorder', tokens: 'tokens',\n }\n const theme: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(wire ?? {})) if (names[k] && v !== undefined && v !== null && v !== '') theme[names[k]] = v\n return theme as CauthyTheme\n}\n\nexport interface PushThemeOptions {\n /** Cauthy's address. Default: `CAUTHY_ISSUER`. */\n issuer?: string\n /** The application's client id. Default: `CAUTHY_CLIENT_ID`. */\n clientId?: string\n /** The workspace's slug. Default: `CAUTHY_TENANT`. */\n tenant?: string\n /**\n * A personal access token with `oauth_clients:manage`. Default:\n * `CAUTHY_TOKEN`. It belongs in the deploy pipeline, never in the application.\n */\n token?: string\n theme: CauthyTheme\n fetch?: typeof fetch\n}\n\n/**\n * Gives the application its look on Cauthy's pages. It replaces the theme: a\n * value left out goes back to Cauthy's own. Run it when the brand changes —\n * from a script or the deploy — not on every request.\n */\nexport async function pushTheme(o: PushThemeOptions): Promise<void> {\n const env = (n: string) => (typeof process !== 'undefined' ? process.env?.[n] : undefined)\n const issuer = withoutTrailingSlashes(o.issuer ?? env('CAUTHY_ISSUER') ?? '')\n const clientId = o.clientId ?? env('CAUTHY_CLIENT_ID') ?? ''\n const tenant = o.tenant ?? env('CAUTHY_TENANT') ?? ''\n const token = o.token ?? env('CAUTHY_TOKEN') ?? ''\n for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_CLIENT_ID: clientId, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {\n if (v === '') throw new Error(`cauthy-auth: ${name} is required to push a theme`)\n }\n const res = await (o.fetch ?? fetch)(`${issuer}/v1/oauth/clients/${encodeURIComponent(clientId)}/theme`, {\n method: 'PUT',\n headers: { authorization: `Bearer ${token}`, 'x-tenant-key': tenant, 'content-type': 'application/json' },\n body: JSON.stringify(toWire(o.theme)),\n })\n if (!res.ok) {\n const body = (await res.json().catch(() => null)) as { errors?: { message?: string }[] } | null\n throw new Error(`cauthy-auth: Cauthy refused the theme (${res.status}): ${body?.errors?.[0]?.message ?? res.statusText}`)\n }\n}\n","// What a sign-in or sign-up form is checked for before anything is sent, in\n// the browser and again on the server: the same rules in both places, so the\n// form says what the server would.\n\nexport type AuthField = 'email' | 'password' | 'newPassword' | 'name' | 'code' | 'organization'\n\n/** A value of a form that cannot be sent as it is. */\nexport interface FieldProblem {\n field: AuthField\n /**\n * Stable, for translating: `required`, `invalid_email`, `too_short`,\n * `too_long`, and for a new password the rule of the workspace it fails:\n * `needs_lowercase`, `needs_uppercase`, `needs_digit`, `needs_symbol`,\n * `needs_classes`.\n */\n code: 'required' | 'invalid_email' | PasswordReason\n message: string\n}\n\n/** The shortest password Cauthy takes by default: a workspace's policy may ask otherwise (`methods().password`). */\nexport const MIN_PASSWORD = 12\n/** The longest: the API bounds what Argon2id is given, whatever the workspace asks. */\nconst MAX_PASSWORD = 128\n/** The shortest any workspace may allow. */\nconst FLOOR_PASSWORD = 8\nconst MAX_NAME = 120\n\n/** A kind of character a workspace's password policy can ask for. */\nexport type PasswordClass = 'lowercase' | 'uppercase' | 'digit' | 'symbol'\n\n/** Why a new password is refused: the API's `weak_password` `meta.reasons`. */\nexport type PasswordReason = 'too_short' | 'too_long' | 'needs_lowercase' | 'needs_uppercase' | 'needs_digit' | 'needs_symbol' | 'needs_classes' | 'breached'\n\n/**\n * What a new password must be in the workspace, as `methods().password` says\n * it. Length is counted in bytes of UTF-8, as Cauthy counts it. A symbol is\n * any character that is neither a letter nor a digit, a space included.\n */\nexport interface PasswordPolicy {\n min: number\n max: number\n /** The kinds the password must each carry at least once. */\n requires: PasswordClass[]\n /** At least this many of the four kinds; 0 asks none. */\n min_classes: number\n /** Cauthy refuses a password found in a published breach (checked by Cauthy alone). */\n reject_breached: boolean\n}\n\nconst CLASSES: PasswordClass[] = ['lowercase', 'uppercase', 'digit', 'symbol']\n\n/** The policy of a workspace that set none: what every one asked before they could choose. */\nexport const DEFAULT_PASSWORD_POLICY: PasswordPolicy = Object.freeze({ min: MIN_PASSWORD, max: MAX_PASSWORD, requires: [], min_classes: 0, reject_breached: false }) as PasswordPolicy\n\nconst int = (v: unknown, fallback: number) => (typeof v === 'number' && Number.isFinite(v) ? Math.trunc(v) : fallback)\n\n/**\n * A password policy as Cauthy sent it — `{ min_length, max_length, … }` from\n * the sign-in settings, or `{ min, max, … }` from `methods()` — made safe to\n * use: the defaults where nothing is said, and never outside 8–128.\n */\nexport function passwordPolicyOf(raw: unknown): PasswordPolicy {\n const r = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>\n const min = Math.min(Math.max(int(r.min ?? r.min_length, MIN_PASSWORD) || MIN_PASSWORD, FLOOR_PASSWORD), MAX_PASSWORD)\n const max = Math.max(Math.min(int(r.max ?? r.max_length, MAX_PASSWORD) || MAX_PASSWORD, MAX_PASSWORD), min)\n const asked = Array.isArray(r.requires) ? r.requires : []\n return {\n min, max,\n requires: CLASSES.filter((c) => asked.includes(c)),\n min_classes: Math.min(Math.max(int(r.min_classes ?? r.minClasses, 0), 0), CLASSES.length),\n reject_breached: (r.reject_breached ?? r.rejectBreached) === true,\n }\n}\n\n/** Bytes of UTF-8: what Cauthy counts a password's length in. */\nfunction utf8Length(v: string): number {\n let n = 0\n for (const ch of v) {\n const c = ch.codePointAt(0)!\n n += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4\n }\n return n\n}\n\n/** Which of the four kinds a password carries, as Cauthy tells them apart. */\nfunction classesOf(v: string): Set<PasswordClass> {\n const has = new Set<PasswordClass>()\n for (const ch of v) {\n if (/\\p{Ll}/u.test(ch)) has.add('lowercase')\n else if (/\\p{Lu}/u.test(ch)) has.add('uppercase')\n else if (/\\p{Nd}/u.test(ch)) has.add('digit')\n else if (!/\\p{L}/u.test(ch)) has.add('symbol') // a letter without case is neither\n }\n return has\n}\n\n/**\n * Every rule of the policy a new password fails, as the API names them;\n * empty when it meets them all. Whether it was in a breach only Cauthy knows.\n */\nexport function passwordProblems(value: string, policy: PasswordPolicy = DEFAULT_PASSWORD_POLICY): PasswordReason[] {\n const p = passwordPolicyOf(policy)\n const out: PasswordReason[] = []\n const length = utf8Length(value)\n if (length < p.min) out.push('too_short')\n if (length > p.max) out.push('too_long')\n const has = classesOf(value)\n for (const c of p.requires) if (!has.has(c)) out.push(`needs_${c}` as PasswordReason)\n if (p.min_classes > 0 && CLASSES.filter((c) => has.has(c)).length < p.min_classes) out.push('needs_classes')\n return out\n}\n\n/** The languages the rule is said in. */\nexport type PasswordLocale = 'en' | 'es'\n\nconst RULES: Record<PasswordLocale, {\n between: string; requires: string; classes: string; breached: string; and: string; kinds: Record<PasswordClass, string>\n reasons: Record<PasswordReason, string>\n}> = {\n en: {\n between: 'Between {min} and {max} characters.', requires: 'Include {kinds}.', and: 'and',\n classes: 'Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.',\n breached: 'Passwords found in known data breaches are not accepted.',\n kinds: { lowercase: 'a lowercase letter', uppercase: 'an uppercase letter', digit: 'a digit', symbol: 'a symbol' },\n reasons: {\n too_short: 'Use at least {min} characters.', too_long: 'Use at most {max} characters.',\n needs_lowercase: 'Include a lowercase letter.', needs_uppercase: 'Include an uppercase letter.', needs_digit: 'Include a digit.', needs_symbol: 'Include a symbol.',\n needs_classes: 'Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.',\n breached: 'This password appears in a known data breach. Choose a different one.',\n },\n },\n es: {\n between: 'Entre {min} y {max} caracteres.', requires: 'Incluye {kinds}.', and: 'y',\n classes: 'Usa al menos {n} de estos tipos: minúsculas, mayúsculas, números, símbolos.',\n breached: 'No se aceptan contraseñas que aparecen en filtraciones de datos conocidas.',\n kinds: { lowercase: 'una minúscula', uppercase: 'una mayúscula', digit: 'un número', symbol: 'un símbolo' },\n reasons: {\n too_short: 'Usa al menos {min} caracteres.', too_long: 'Usa como máximo {max} caracteres.',\n needs_lowercase: 'Incluye una minúscula.', needs_uppercase: 'Incluye una mayúscula.', needs_digit: 'Incluye un número.', needs_symbol: 'Incluye un símbolo.',\n needs_classes: 'Usa al menos {n} de estos tipos: minúsculas, mayúsculas, números, símbolos.',\n breached: 'Esta contraseña aparece en una filtración de datos conocida. Elige otra.',\n },\n },\n}\n\nconst fill = (s: string, p: PasswordPolicy) => s.replace('{min}', String(p.min)).replace('{max}', String(p.max)).replace('{n}', String(p.min_classes))\n\n/** What a new password must be, said for the person choosing it: \"Between 12 and 128 characters. Include a digit.\" */\nexport function describePasswordPolicy(policy: PasswordPolicy = DEFAULT_PASSWORD_POLICY, locale: PasswordLocale = 'en'): string {\n const p = passwordPolicyOf(policy)\n const t = RULES[locale] ?? RULES.en\n const parts = [fill(t.between, p)]\n if (p.requires.length > 0) {\n const kinds = p.requires.map((c) => t.kinds[c])\n const listed = kinds.length === 1 ? kinds[0] : `${kinds.slice(0, -1).join(', ')} ${t.and} ${kinds[kinds.length - 1]}`\n parts.push(t.requires.replace('{kinds}', listed))\n }\n if (p.min_classes > 0) parts.push(fill(t.classes, p))\n if (p.reject_breached) parts.push(t.breached)\n return parts.join(' ')\n}\n\n/** Why a new password was refused, rule by rule, for the person who typed it. */\nexport function explainPasswordProblems(reasons: readonly string[], policy: PasswordPolicy = DEFAULT_PASSWORD_POLICY, locale: PasswordLocale = 'en'): string {\n const p = passwordPolicyOf(policy)\n const t = RULES[locale] ?? RULES.en\n const said = reasons.filter((r): r is PasswordReason => r in t.reasons).map((r) => fill(t.reasons[r], p))\n return said.length > 0 ? said.join(' ') : describePasswordPolicy(p, locale)\n}\n\n// One @, something on each side, a dot in the domain, no spaces: what catches\n// a typo. Whether the address exists is Cauthy's to find out.\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport function checkEmail(value: unknown): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return { field: 'email', code: 'required', message: 'Enter your email address.' }\n if (v.length > 254 || !EMAIL.test(v)) return { field: 'email', code: 'invalid_email', message: 'That does not look like an email address.' }\n return null\n}\n\n/** A password being typed to sign in: only that there is one. */\nexport function checkPassword(value: unknown): FieldProblem | null {\n if (typeof value !== 'string' || value === '') return { field: 'password', code: 'required', message: 'Enter your password.' }\n if (value.length > MAX_PASSWORD) return { field: 'password', code: 'too_long', message: 'That password is too long.' }\n return null\n}\n\n/**\n * A password being chosen for a new account, or a new one for an account.\n * Held to the workspace's policy when it is given (`methods().password`),\n * otherwise to the defaults: 12 to 128 characters.\n */\nexport function checkNewPassword(value: unknown, policy?: PasswordPolicy | null): FieldProblem | null {\n if (typeof value !== 'string' || value === '') return { field: 'password', code: 'required', message: 'Enter your password.' }\n const p = policy ? passwordPolicyOf(policy) : DEFAULT_PASSWORD_POLICY\n const reasons = passwordProblems(value, p)\n if (reasons.length === 0) return null\n return { field: 'password', code: reasons[0], message: explainPasswordProblems(reasons, p) }\n}\n\nexport function checkName(value: unknown): FieldProblem | null {\n if (value === undefined || value === null || value === '') return null\n if (typeof value !== 'string' || value.trim().length > MAX_NAME) return { field: 'name', code: 'too_long', message: `Use at most ${MAX_NAME} characters.` }\n return null\n}\n\n/** The company's name a sign-up carries when the application's system makes an organization per sign-up. */\nexport const MAX_ORGANIZATION = 120\n\nexport function checkOrganization(value: unknown, required = false): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return required ? { field: 'organization', code: 'required', message: \"Enter your company's name.\" } : null\n if (v.length > MAX_ORGANIZATION) return { field: 'organization', code: 'too_long', message: `Use at most ${MAX_ORGANIZATION} characters.` }\n return null\n}\n\n/** An organization's new name, when a member renames it: the same rule as at sign-up, always required. */\nexport function checkOrganizationName(value: unknown): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return { field: 'name', code: 'required', message: \"Enter the organization's name.\" }\n if (v.length > MAX_ORGANIZATION) return { field: 'name', code: 'too_long', message: `Use at most ${MAX_ORGANIZATION} characters.` }\n return null\n}\n\nexport function checkCode(value: unknown): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return { field: 'code', code: 'required', message: 'Enter the code.' }\n if (v.length > 40) return { field: 'code', code: 'too_long', message: 'That is not a code.' }\n return null\n}\n\n/** The first problem of a form, or null when it can be sent. */\nexport function firstProblem(...checks: (FieldProblem | null)[]): FieldProblem | null {\n return checks.find((c) => c !== null) ?? null\n}\n","// The application's own sign-in screens, in the browser.\n//\n// const auth = createAuthClient()\n// const r = await auth.signIn.email({ email, password })\n// if (!r.ok) show(r.error.message) // r.error.field says which input\n// else if (r.status === 'mfa_required') askForTheCode()\n//\n// Every call goes to the application's own server (`/api/auth/*`), never to\n// Cauthy: the browser holds no token, before or after. A form is checked here\n// before it is sent, with the rules the server checks again.\n\nimport { canAutofillPasskeys, canUsePasskeys, ceremonyError, getPasskey, makePasskey } from './passkey'\nimport { fromWire, type CauthyTheme } from './theme'\nimport type { CheckQuestion, CheckResult, OrganizationRef, PublicSession } from './types'\nexport type { CheckQuestion, CheckResult, CheckRule, OrganizationRef } from './types'\nimport { checkCode, checkEmail, checkName, checkNewPassword, checkPassword, firstProblem, passwordPolicyOf, type AuthField, type FieldProblem, type PasswordPolicy, checkOrganization, checkOrganizationName } from './validate'\nimport { withoutTrailingSlashes } from './url'\n\nexport { checkCode, checkEmail, checkName, checkNewPassword, checkPassword, describePasswordPolicy, explainPasswordProblems, passwordPolicyOf, passwordProblems, DEFAULT_PASSWORD_POLICY, MIN_PASSWORD, type AuthField, type FieldProblem, type PasswordClass, type PasswordLocale, type PasswordPolicy, type PasswordReason } from './validate'\n\n/** What went wrong, in a form the screen can show. */\nexport interface AuthError {\n /** Stable, for translating: `invalid_credentials`, `invalid_email`, `too_short`, `email_taken`, `unavailable`… */\n code: string\n message: string\n /** The input it is about, when it is about one. */\n field?: AuthField\n /** `weak_password`: the rules of the workspace's password policy it failed (`too_short`, `needs_digit`, …). */\n reasons?: string[]\n}\n\nexport type AuthResult<S extends string, More = unknown> = ({ ok: true; status: S } & More) | { ok: false; error: AuthError }\n\n/** What the screen may offer. */\nexport interface AuthMethods {\n /**\n * The providers the workspace signs people in with and has turned on:\n * `{ id: 'google', name: 'Google', iconUrl: 'https://…/v1/social/icons/google.svg' }`.\n * `iconUrl` is the provider's logo, served by Cauthy; absent from a Cauthy\n * that does not serve logos.\n */\n providers: { id: string; name: string; iconUrl?: string }[]\n /**\n * Whether the workspace signs people in with a password. False: the\n * password field, \"forgot your password\" and a sign-up with a password are\n * not offered, and Cauthy refuses them (`password_disabled`). True from a\n * server that does not say. (`password` is something else: the policy a new\n * password must meet.)\n */\n passwordSignIn: boolean\n /** Whether people may create an account themselves. */\n signUp: boolean\n /** Set when the application's system makes an organization per sign-up: the form asks the company's name. */\n organization?: { ask: boolean; required: boolean }\n magicLink: boolean\n /** Whether to offer a passkey. False when the workspace turned passkeys off. */\n passkey: boolean\n /**\n * Whether the passkey is used on this page itself. False: `signIn.passkey`\n * sends the person to Cauthy's page for that step alone, and they come back\n * signed in. That happens only when this page is outside the domain the\n * workspace's passkeys belong to.\n */\n passkeyHere: boolean\n /**\n * Whether Cauthy's page can use the passkey, for that step alone: where a\n * page that cannot, or a browser that refuses to here, sends the person.\n */\n passkeyOnCauthy: boolean\n /**\n * The workspace's Cloudflare Turnstile site key, when it asks for the\n * challenge: signing in, creating an account, and asking for a sign-in link\n * or a new password then take its answer (`captchaToken`). The ready-made\n * forms show it themselves.\n */\n captchaSiteKey?: string\n /**\n * Whether the workspace signs some people in through their company's SSO,\n * found by their work address (`signIn.ssoDiscover`, `signIn.sso`).\n */\n sso: boolean\n /**\n * Set when the workspace asks something of a sign-up: the legal documents\n * to accept (the terms, the privacy policy: show the links and a box, send\n * `acceptLegal: true`) and the consents to ask (one box each, sent as\n * `consents`; a required one must be ticked). The ready-made form shows them.\n */\n legal?: { documents: { kind: string; version: string; url: string }[]; consentPurposes: { key: string; label: string; required: boolean }[] }\n /**\n * What a new password must be in the workspace. Once `methods()` has\n * answered, this client checks new passwords against it before sending\n * them; until then, against the defaults (12 to 128 characters). Absent\n * from a server that does not say.\n */\n password?: PasswordPolicy\n}\n\n/** An invitation, as its page shows it before the person chooses a password. */\nexport interface Invitation {\n /** The address invited: the account the person signs in as. */\n email: string\n /** The workspace's name. */\n workspace: string\n /** The organization the person was invited to, when there is one. */\n organization?: string\n}\n\n/** A legal document the person owes: not yet accepted in its current version. */\nexport interface PendingLegal { kind: string; version: string; url: string }\n\n/** A company's sign-in (an SSO connection of the workspace). */\nexport interface SSOConnection {\n /** What `signIn.sso({ connection })` takes. */\n id: string\n /** The company's name, for \"Continue with …\". */\n name: string\n /** The address can sign in no other way: a password, link or provider answers `sso_required`. */\n enforced: boolean\n}\n\n/**\n * What holds a passkey, as its authenticator says: a security key (a YubiKey),\n * one synced across the person's devices (iCloud Keychain, Google Password\n * Manager), one on a single device (Windows Hello), or unknown (made before\n * Cauthy kept this).\n */\nexport type PasskeyKind = 'security_key' | 'synced' | 'device' | 'unknown'\n\n/** A passkey of the signed-in account. Moments are UTC. */\nexport interface Passkey {\n id: string\n /** What the person called it (\"My laptop\"), or \"\". */\n name: string\n kind: PasskeyKind\n createdAt: string\n /** When it last signed the person in, or null. */\n lastUsedAt: string | null\n}\n\n/** A person's own account, as their account screen shows it. */\nexport interface Account {\n id: string\n email: string\n name: string\n emailVerified: boolean\n /** False for an account that only signs in through a provider: it has no current password to ask for. */\n hasPassword: boolean\n mfaEnabled: boolean\n}\n\n/** Somewhere the person is signed in. Moments are UTC. */\n/** An AI agent the person allowed to act for them on one of the workspace's servers. */\nexport interface ConnectedAgent {\n id: string\n /** The name the agent gave itself (Claude, Cursor…): not checked by anyone. */\n name: string\n /** Where the agent receives its access: the one thing about it that is sure. */\n redirectHost: string\n resource: { name: string; uri: string }\n /** What the person allowed it, in their words. */\n scopes: { name: string; description: string }[]\n /** UTC, ISO 8601. */\n connectedAt: string\n lastUsedAt: string\n}\n\n/** An organization the person belongs to, with what their role lets them do with it and its people. */\nexport interface OrganizationSeat {\n id: string\n /** The client system it is of (`acme-crm`). */\n system: string\n name: string\n kind: string\n /** The person's role in it. */\n role: string\n /**\n * Cauthy's reserved powers, from the system's catalog. `manageMembers`\n * (cauthy:members:manage) adds, invites and changes roles; removing another\n * member is `removeMembers` (cauthy:members:remove), and anybody may leave.\n * `update`, `archive` and `delete` are cauthy:organization's: rename it,\n * archive it, delete it for good.\n */\n can: { readMembers: boolean; manageMembers: boolean; removeMembers: boolean; update: boolean; archive: boolean; delete: boolean }\n}\n\n/** A person of an organization, as a member who may see them reads it. */\nexport interface OrganizationPerson {\n userId: string\n email: string\n name: string\n role: string\n /** The account's: `active`, `suspended`… A disabled member is still listed. */\n status: string\n /** Invited and not yet accepted. */\n invited: boolean\n /** Manages the organization's members. */\n manager: boolean\n /** The signed-in person. */\n you: boolean\n /** UTC, ISO 8601. */\n since: string\n}\n\n/** A role of the organization's system, as the catalog names it. */\nexport interface OrganizationRoleChoice {\n role: string\n name: string\n description: string\n /** Holding it manages the organization's members. */\n manager: boolean\n}\n\n/**\n * The signed-in person's organizations, and their people. Seeing them needs\n * cauthy:members read in the person's role; changing them needs manage, and\n * removing someone needs remove. The organization itself is renamed, archived\n * or deleted with cauthy:organization update, archive or delete. Only an\n * `owner` gives the owner role or changes an owner, and the last owner stays\n * (`last_owner`). Cauthy decides, with the person's own session: the\n * application authorizes nothing.\n */\nexport interface OrganizationsClient {\n /** The organizations the person belongs to; one system's only with `system`. */\n list(system?: string): Promise<OrganizationSeat[]>\n /** The people of one, or null when the person may not see them. */\n members(organizationId: string): Promise<OrganizationPerson[] | null>\n /** The roles a member may be given, or null when the person may not see them. */\n roles(organizationId: string): Promise<OrganizationRoleChoice[] | null>\n /**\n * Adds a person by their address; an address with no account gets one and\n * its invitation. It only adds: a person who already belongs keeps their\n * role and the result is the error `member_exists` (change it with `setRole`).\n */\n add(organizationId: string, form: { email: string; role: string; name?: string; locale?: string }): Promise<AuthResult<'added', { member: OrganizationPerson }>>\n setRole(organizationId: string, userId: string, role: string): Promise<AuthResult<'changed', { userId: string; role: string }>>\n /** Removes a member; the person themself may always leave. */\n remove(organizationId: string, userId: string): Promise<AuthResult<'removed', { userId: string }>>\n /** Sends a member's invitation again. */\n inviteAgain(organizationId: string, userId: string, form?: { locale?: string }): Promise<AuthResult<'sent', { userId: string }>>\n /** Gives the organization a new name (cauthy:organization update). */\n rename(organizationId: string, name: string): Promise<AuthResult<'renamed', { organization: OrganizationSeat }>>\n /** Archives the organization: its members no longer reach it, and only the workspace restores it. */\n archive(organizationId: string): Promise<AuthResult<'archived', { organizationId: string }>>\n /** Deletes the organization for good. */\n delete(organizationId: string): Promise<AuthResult<'deleted', { organizationId: string }>>\n /**\n * Asks Cauthy, through the application's server, whether the person may do\n * an action on a resource in the organization, with what its conditions\n * read. A question that could not be asked is a no, with `error` saying why.\n *\n * const r = await organizations.check({ organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })\n * if (r.allowed) showApprove()\n */\n check(question: CheckQuestion & { organization: OrganizationRef }): Promise<CheckResult & { error?: AuthError }>\n}\n\nexport interface AccountSession {\n /** \"Mac · Chrome\", or \"\" when the browser did not say. */\n device: string\n ip: string\n createdAt: string\n expiresAt: string\n}\n\n/**\n * The signed-in person's own account. What weakens it — the password, the\n * second step, its recovery codes — asks for the current password again.\n */\n/** A provider the account can also sign in with. */\nexport interface LinkedIdentity {\n provider: string\n /** The address the provider has for the person, when it said. */\n email: string\n name: string\n /** When it was linked, in UTC (ISO 8601). */\n linkedAt: string\n}\n\n/** How an account takes its second step. */\nexport interface SecondStep {\n totp: boolean\n /** The phone codes are sent to, masked (`+57 ••• ••• 4567`). */\n phone: { number: string; channel: string } | null\n /** The ways the workspace sends codes to phones. */\n phoneChannels: string[]\n}\n\nexport interface AccountClient {\n /** The account, or null when nobody is signed in. */\n get(): Promise<Account | null>\n update(form: { name: string }): Promise<AuthResult<'saved', { account: Account }>>\n /** Ends every other session of the account; this one stays signed in. */\n changePassword(form: { password: string; newPassword: string }): Promise<AuthResult<'changed', { signedIn: boolean }>>\n /**\n * The legal documents the person has not accepted in their current version\n * (a new version of the terms, say): show them and call `acceptLegal`.\n * Nothing stops the person meanwhile; the application decides what waits.\n */\n legal(): Promise<AuthResult<'ok', { pending: PendingLegal[] }>>\n /** Records the person's acceptance of the documents in force (the kinds named, or every one). */\n acceptLegal(form?: { kinds?: string[] }): Promise<AuthResult<'accepted'>>\n mfa: {\n /** Starts turning the second step on: show `secret` (or `otpauthUri` as a QR code) to add to an authenticator app, then call `verify`. */\n setup(form: { password: string }): Promise<AuthResult<'started', { secret: string; otpauthUri: string }>>\n /** Turns it on with a code from the app. `recoveryCodes` are shown this once. */\n verify(form: { code: string }): Promise<AuthResult<'enabled', { recoveryCodes: string[] }>>\n disable(form: { password: string }): Promise<AuthResult<'disabled'>>\n /** New recovery codes; the earlier ones stop working. */\n recoveryCodes(form: { password: string }): Promise<AuthResult<'renewed', { recoveryCodes: string[] }>>\n /**\n * How the account takes its second step: an authenticator app, a phone\n * (masked), and the ways the workspace sends codes to phones (`sms`,\n * `whatsapp`; none when it has no Twilio account for it).\n */\n factors(): Promise<SecondStep | null>\n /** Adds a phone as the second step: a code is sent to it, for `verifyPhone`. */\n addPhone(form: { phone: string; channel: 'sms' | 'whatsapp'; password: string }): Promise<AuthResult<'sent', { sentTo: string; channel: string }>>\n /** Proves the phone with the code it received. `recoveryCodes` come with a first second step, shown this once. */\n verifyPhone(form: { code: string }): Promise<AuthResult<'enabled', { recoveryCodes: string[] }>>\n removePhone(form: { password: string }): Promise<AuthResult<'removed'>>\n }\n /**\n * Asks to sign in with another address. Nothing changes yet: the new address\n * is mailed a link to confirm it, and once it is confirmed the old one is\n * told, with a link that undoes it. Both open Cauthy's own page.\n */\n changeEmail(form: { email: string; password: string }): Promise<AuthResult<'sent', { email: string }>>\n /** The providers (Google…) the account can also sign in with. */\n identities(): Promise<LinkedIdentity[]>\n /**\n * Sends the browser to the provider, to link it to the account; it comes back\n * at `returnTo` with `?linked=<provider>`, or `?auth_error=<code>`.\n */\n link(provider: string, options?: { returnTo?: string }): void\n /** Where `link` sends the browser, for a plain link. */\n linkUrl(provider: string, options?: { returnTo?: string }): string\n /** The account stops signing in with that provider. Refused when it would be left with no way to sign in. */\n unlink(provider: string): Promise<AuthResult<'unlinked', { provider: string }>>\n /**\n * A guest becomes an account of their own with an address and a password —\n * the same id, so what they did stays theirs. `email_taken`: the address has\n * an account already; offer to sign in with it.\n */\n upgrade(form: { email: string; password: string; name?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Where a guest goes to become the account of a provider's address (Google…). */\n upgradeUrl(provider: string, options?: { returnTo?: string }): string\n /** Sends a guest to `upgradeUrl`; they come back signed in as the account. */\n upgradeWith(provider: string, options?: { returnTo?: string }): void\n /** Where the account is signed in. */\n sessions(): Promise<AccountSession[]>\n /** Signs the account out everywhere, here too. */\n signOutEverywhere(): Promise<AuthResult<'signed_out'>>\n /** The AI agents the person connected. */\n agents(): Promise<ConnectedAgent[]>\n /** Disconnects an agent: it loses its access within minutes. */\n disconnectAgent(id: string): Promise<AuthResult<'disconnected', { id: string }>>\n /** The account's passkeys. */\n passkeys(): Promise<Passkey[]>\n /**\n * Makes a passkey on this device, on this page: the browser asks the person\n * for their fingerprint, face or screen lock. An account with a password\n * proves it again first. `cancelled`: the person closed the browser's prompt.\n * `kind` sends the browser straight to one: `'device'`, this device's\n * fingerprint, face or screen lock; `'security_key'`, a security key.\n * Without it, the browser offers all.\n */\n addPasskey(form?: { password?: string; name?: string; kind?: 'device' | 'security_key' }): Promise<AuthResult<'added', { passkey: Passkey }>>\n removePasskey(id: string): Promise<AuthResult<'removed', { id: string }>>\n}\n\nexport interface AuthClient {\n signIn: {\n /**\n * A guest session, before the visitor signs up: the application keeps what\n * they do under `session.user.id`, and `account.upgrade` (or\n * `account.upgradeWith`) makes it their account, same id. Only where the\n * workspace allows guests (`anonymous_disabled` otherwise).\n */\n anonymously(form?: { captchaToken?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /**\n * With address and password. `mfa_required`: ask for the code and call\n * `signIn.mfa`. `method: 'email'` says the code was just mailed to the\n * account's address (it has no factor of its own and the workspace, or\n * the sign-in's risk, asked a second step): say so, and offer\n * `mfaSendEmail` for another.\n */\n email(form: { email: string; password: string; captchaToken?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'mfa_required', { method?: 'email' }>>\n /** The second step: the code of the authenticator app, the phone, the email, or a recovery code. */\n mfa(form: { code: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /**\n * While the second step is asked for: whether the account has an\n * authenticator app, the phone (masked) a code can be sent to, phones\n * that approve sign-ins, and the address (masked) a code went to when\n * the step is by email.\n */\n mfaMethods(): Promise<AuthResult<'ok', { totp: boolean; phone: { number: string; channel: string } | null; push: { devices: number } | null; email: { to: string } | null }>>\n /** Mails the sign-in's code again, when its second step is by email; `mfa` takes it. A few per sign-in. */\n mfaSendEmail(): Promise<AuthResult<'sent', { sentTo: string }>>\n /**\n * Sends a push to the account's phones (the application's app, with\n * cauthy-expo): show `number`, which the person picks on the phone, then\n * call `mfaPushWait`.\n */\n mfaPush(): Promise<AuthResult<'sent', { number: number }>>\n /**\n * Waits for the phone's answer, listening (server-sent events) rather than\n * asking again and again, and signs in when it approves. `denied`: turned\n * down on the phone; `expired`: nobody answered in time.\n */\n mfaPushWait(o?: { signal?: AbortSignal }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Sends a code to the account's phone, by SMS or WhatsApp; `mfa` takes it. A few per sign-in. */\n mfaSendCode(): Promise<AuthResult<'sent', { sentTo: string; channel: string }>>\n /**\n * Mails a link (and a code) that signs the person in. The answer is the\n * same whether or not the address has an account. `create`: an address\n * with no account gets one when the link or code is used, if the\n * workspace accepts new accounts — one screen signs people in and up.\n * `returnTo` (a path of this site) travels in the link: the page it opens\n * gets it as `?return_to=`, and `emailCode` answers it.\n */\n magicLink(form: { email: string; captchaToken?: string; create?: boolean; returnTo?: string }): Promise<AuthResult<'sent'>>\n /** Signs in with the token the mailed link opened the page with (`ml_token`). */\n magicLinkVerify(form: { token: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Signs in with the code that came in the same mail as the link, for somebody reading it on another device. */\n emailCode(form: { code: string }): Promise<AuthResult<'signed_in', { session: PublicSession; returnTo?: string }>>\n /**\n * Signs in with a passkey, on this page: the browser asks the person for\n * their fingerprint, face or screen lock. When this page cannot use the\n * workspace's passkeys (`methods().passkeyHere` is false), the browser goes\n * to Cauthy's page for that step alone and comes back signed in, at\n * `returnTo`: then the answer is `redirected`. `cancelled`: the person\n * closed the browser's prompt. `email`, when the person typed it: the\n * browser is told which passkeys are theirs, so a security key that did\n * not keep its passkey (one made before cauthy-auth 0.18.0) is found too.\n */\n passkey(options?: { returnTo?: string; locale?: string; email?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'redirected'>>\n /**\n * Offers the person's passkeys in the browser's autofill of the email\n * field, which must carry `autocomplete=\"username webauthn\"`, and signs in\n * with the one they pick. It waits until they pick one or `signal`\n * aborts: abort it before calling `passkey` or sending the form.\n * `cancelled`: aborted, or this browser or page cannot (then there is\n * nothing to offer, and the passkey button still works).\n */\n passkeyAutofill(options?: { signal?: AbortSignal }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /**\n * Google One Tap: Google's prompt over the page offers the Google account\n * the browser already has, and signs in with it in one tap, as the Google\n * sign-in does (the same account). Needs the workspace's Google sign-in,\n * and the page's address among the Google client's authorized JavaScript\n * origins. Waits until the person picks an account or closes the prompt\n * (`cancelled`), or `signal` aborts. `one_tap_unavailable`: the workspace\n * has no Google sign-in.\n */\n googleOneTap(options?: { signal?: AbortSignal; context?: 'signin' | 'signup' | 'use' }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Where `passkey` sends the browser when this page cannot use the passkey itself. */\n passkeyUrl(options?: { returnTo?: string; locale?: string }): string\n /** Sends the browser to the provider; it comes back signed in, at `returnTo`. */\n social(provider: string, options?: { returnTo?: string }): void\n /**\n * Which company's sign-in a work address uses, if any (`found`), or\n * `none`. It says so of the address's domain, never whether the address\n * has an account.\n */\n ssoDiscover(form: { email: string }): Promise<AuthResult<'found', { connection: SSOConnection }> | AuthResult<'none'>>\n /**\n * Sends the browser to the person's company (found by `email`, or named\n * by `connection`); it comes back signed in, at `returnTo`. A sign-in the\n * company refused comes back with `?auth_error=`. Any other way of\n * signing in answers `sso_required` for an address its company holds to\n * SSO: send it here then.\n */\n sso(target: { email: string } | { connection: string }, options?: { returnTo?: string }): void\n /** Where `sso` sends the browser, for a plain link. */\n ssoUrl(target: { email: string } | { connection: string }, options?: { returnTo?: string }): string\n /** Where `social` sends the browser, for a plain link. */\n socialUrl(provider: string, options?: { returnTo?: string }): string\n }\n signUp: {\n /**\n * `verification_required`: the account exists and must open the link Cauthy mailed before it can sign in.\n * `acceptLegal` and `consents` answer what `methods().legal` asks; a sign-up that leaves them out is refused.\n */\n email(form: { email: string; password: string; name?: string; organization?: string; acceptLegal?: boolean; consents?: Record<string, boolean>; captchaToken?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'verification_required', { email: string }>>\n }\n /** Mails a link to choose a new password. The answer is the same whether or not the address has an account. */\n forgotPassword(form: { email: string; captchaToken?: string }): Promise<AuthResult<'sent'>>\n /** Sets the new password, with the token the mailed link opened the page with (`token`). */\n resetPassword(form: { token: string; password: string }): Promise<AuthResult<'changed'>>\n /**\n * Who an invitation is for and to what, with the token the mailed link\n * opened the page with (`token`). Reading it does not spend it.\n * `invalid_token`: unknown, spent or expired.\n */\n invitation(token: string): Promise<AuthResult<'ok', { invitation: Invitation }>>\n /**\n * Accepts an invitation with the password the person chose (the workspace's\n * policy, as for a sign-up) and signs them in. `mfa_required`: the account\n * owes a second step; ask for the code and call `signIn.mfa`, as after\n * `signIn.email`. A password refused leaves the invitation good.\n */\n acceptInvitation(token: string, password: string): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'mfa_required', { method?: 'email' }>>\n /** Confirms the address a mailed link is for. The person is signed in from the link when their account asks no second step. */\n verifyEmail(form: { token: string }): Promise<AuthResult<'verified'> | AuthResult<'signed_in', { session: PublicSession }>>\n signOut(): Promise<AuthResult<'signed_out'>>\n /** The signed-in person's own account. */\n account: AccountClient\n /** The signed-in person's organizations, and their people. */\n organizations: OrganizationsClient\n /** Who is signed in, or null. */\n getSession(): Promise<PublicSession | null>\n methods(): Promise<AuthMethods>\n /**\n * How the workspace's forms look — colours, corners, typeface — as a person\n * set it in Cauthy's dashboard. Read once per page; null when Cauthy cannot say.\n */\n look(): Promise<CauthyTheme | null>\n}\n\nexport interface AuthClientOptions {\n /** Where the server mounted the routes. Default: `/api/auth`. */\n basePath?: string\n fetch?: typeof fetch\n /**\n * The language the person reads, for what Cauthy mails them (a sign-in\n * link, a new password, a confirmation): a tag like `es` or `es-CO`, or a\n * function that answers it when the person can change it. Default: the\n * page's own (`<html lang>`), else the browser's.\n */\n locale?: string | (() => string | undefined)\n}\n\n/** Google Identity Services, as much of it as One Tap uses. */\ninterface GoogleMoment {\n isNotDisplayed?: () => boolean\n isSkippedMoment?: () => boolean\n isDismissedMoment?: () => boolean\n getDismissedReason?: () => string\n}\ninterface GoogleIdentity {\n initialize(config: Record<string, unknown>): void\n prompt(listener?: (moment: GoogleMoment) => void): void\n cancel(): void\n}\n\nlet googleScript: Promise<GoogleIdentity> | null = null\n\n/** Loads Google's script once per page. */\nfunction loadGoogleIdentity(): Promise<GoogleIdentity> {\n const ready = () => (window as unknown as { google?: { accounts?: { id?: GoogleIdentity } } }).google?.accounts?.id\n if (ready()) return Promise.resolve(ready()!)\n googleScript ??= new Promise<GoogleIdentity>((resolve, reject) => {\n const script = document.createElement('script')\n script.src = 'https://accounts.google.com/gsi/client'\n script.async = true\n script.onload = () => (ready() ? resolve(ready()!) : reject(new Error('google identity services did not load')))\n script.onerror = () => {\n googleScript = null\n reject(new Error('google identity services did not load'))\n }\n document.head.appendChild(script)\n })\n return googleScript\n}\n\n/** How long Cauthy waits for a passkey ceremony to be answered. */\nconst PASSKEY_SECONDS = 300\n\nconst UNAVAILABLE: AuthError = { code: 'unavailable', message: 'Sign-in is unavailable right now. Try again in a moment.' }\n\nexport function createAuthClient(options: AuthClientOptions = {}): AuthClient {\n const base = withoutTrailingSlashes(options.basePath ?? '/api/auth')\n const doFetch: typeof fetch = (...args) => (options.fetch ?? fetch)(...args)\n const locale = (): string => {\n const said = typeof options.locale === 'function' ? options.locale() : options.locale\n return (said ?? (typeof document === 'undefined' ? '' : document.documentElement?.lang) ?? '').trim()\n }\n\n async function post(path: string, form: Record<string, unknown>, bad: FieldProblem | null, captchaToken?: string): Promise<any> {\n if (bad) return { ok: false, error: { code: bad.code, message: bad.message, field: bad.field } }\n try {\n const res = await doFetch(`${base}${path}`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'content-type': 'application/json', accept: 'application/json', ...(locale() ? { 'x-cauthy-locale': locale() } : {}), ...(captchaToken ? { 'x-cauthy-captcha': captchaToken } : {}) },\n body: JSON.stringify(form),\n })\n const body = (await res.json().catch(() => null)) as any\n if (res.ok && body && typeof body.status === 'string') return { ok: true, ...body }\n const e = body?.error\n return { ok: false, error: e && typeof e.code === 'string' ? { code: e.code, message: String(e.message ?? ''), ...(e.field ? { field: e.field } : {}), ...(Array.isArray(e.reasons) ? { reasons: e.reasons.map(String) } : {}) } : UNAVAILABLE }\n } catch {\n return { ok: false, error: UNAVAILABLE }\n }\n }\n\n let looked: Promise<CauthyTheme | null> | undefined\n\n async function read(path: string): Promise<any> {\n try {\n const res = await doFetch(`${base}${path}`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n return res.ok ? await res.json() : null\n } catch {\n return null\n }\n }\n\n const upgradeUrl = (provider: string, o: { returnTo?: string } = {}) =>\n `${base}/me/upgrade/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ''}`\n const linkUrl = (provider: string, o: { returnTo?: string } = {}) =>\n `${base}/me/identities/link/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ''}`\n const socialUrl = (provider: string, o: { returnTo?: string } = {}) =>\n `${base}/sign-in/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ''}`\n\n const ssoUrl = (target: { email: string } | { connection: string }, o: { returnTo?: string } = {}) => {\n const q = new URLSearchParams('connection' in target ? { connection: target.connection } : { email: target.email.trim() })\n if (o.returnTo) q.set('return_to', o.returnTo)\n return `${base}/sign-in/sso?${q}`\n }\n\n const passkeyUrl = (o: { returnTo?: string; locale?: string } = {}) => {\n const q = new URLSearchParams({ method: 'passkey' })\n if (o.returnTo) q.set('return_to', o.returnTo)\n if (o.locale) q.set('locale', o.locale)\n return `${base}/login?${q}`\n }\n\n // The workspace's password policy, once methods() has said it.\n let policy: PasswordPolicy | undefined\n\n async function methods(): Promise<AuthMethods> {\n try {\n const res = await doFetch(`${base}/methods`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n if (res.ok) {\n // A server from before the passkey on the page does not say; then it is not.\n const m = (await res.json()) as Partial<AuthMethods>\n // The workspace's password rule, for the checks before a password is sent.\n if (m.password) policy = passwordPolicyOf(m.password)\n return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...(policy ? { password: policy } : {}), passwordSignIn: m.passwordSignIn !== false, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true }\n }\n } catch {\n // falls through\n }\n return { providers: [], signUp: true, passwordSignIn: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false }\n }\n\n /** The two steps of a ceremony: what to ask the browser, then its answer. */\n async function ceremony(begin: string, finish: string, form: Record<string, unknown>, run: (options: any) => Promise<Record<string, unknown>>, more: Record<string, unknown> = {}): Promise<any> {\n const begun = await post(begin, form, null)\n if (!begun.ok) return begun\n let credential: Record<string, unknown>\n try {\n credential = await run(begun.options)\n } catch (e) {\n return { ok: false, error: ceremonyError(e) }\n }\n return post(finish, { credential, ...more }, null)\n }\n\n return {\n signIn: {\n anonymously: (f = {}) => post('/sign-in/anonymous', {}, null, f.captchaToken),\n email: (f) => post('/sign-in/email', { email: f.email, password: f.password }, firstProblem(checkEmail(f.email), checkPassword(f.password)), f.captchaToken),\n mfa: (f) => post('/sign-in/mfa', { code: f.code }, checkCode(f.code)),\n mfaMethods: () => post('/sign-in/mfa/methods', {}, null),\n mfaSendCode: () => post('/sign-in/mfa/send', {}, null),\n mfaSendEmail: () => post('/sign-in/mfa/email', {}, null),\n mfaPush: () => post('/sign-in/mfa/push', {}, null),\n async mfaPushWait(o = {}) {\n const status = await new Promise<string>((resolve) => {\n if (typeof EventSource !== 'function') return resolve('approved') // finish says whether it was\n const source = new EventSource(`${base}/sign-in/mfa/push/events`, { withCredentials: true })\n const stop = (st: string) => {\n source.close()\n resolve(st)\n }\n o.signal?.addEventListener('abort', () => stop('aborted'))\n source.addEventListener('status', (e) => {\n const st = (() => {\n try {\n return String(JSON.parse((e as MessageEvent).data).status)\n } catch {\n return ''\n }\n })()\n if (st && st !== 'pending') stop(st)\n })\n source.onerror = () => {\n if (source.readyState === EventSource.CLOSED) stop('expired')\n }\n })\n if (status === 'aborted') return { ok: false, error: { code: 'aborted', message: 'Stopped waiting.' } }\n if (status === 'denied') return { ok: false, error: { code: 'push_denied', message: 'The sign-in was turned down on the phone.' } }\n if (status === 'expired') return { ok: false, error: { code: 'push_expired', message: 'Nobody answered on the phone in time.' } }\n return post('/sign-in/mfa/push/finish', {}, null)\n },\n magicLink: (f) => post('/sign-in/magic-link', { email: f.email, ...(f.create ? { create: true } : {}), ...(f.returnTo ? { returnTo: f.returnTo } : {}) }, checkEmail(f.email), f.captchaToken),\n magicLinkVerify: (f) => post('/sign-in/magic-link/verify', { token: f.token }, null),\n emailCode: (f) => post('/sign-in/email-code', { code: f.code }, checkCode(f.code)),\n passkeyUrl,\n async passkey(o) {\n const m = await methods()\n if (m.passkeyHere && canUsePasskeys()) {\n const email = o?.email?.trim() ?? ''\n const r = await ceremony('/sign-in/passkey/begin', '/sign-in/passkey/finish', email !== '' && checkEmail(email) === null ? { email } : {}, getPasskey)\n // A browser that does not read the domain's related origins refuses\n // this page: Cauthy's, then, when it can.\n if (r.ok || r.error.code !== 'passkey_unavailable' || !m.passkeyOnCauthy) return r\n } else if (!m.passkeyOnCauthy) {\n return { ok: false, error: { code: 'passkey_unavailable', message: 'Passkeys cannot be used here.' } }\n }\n window.location.assign(passkeyUrl(o))\n return { ok: true, status: 'redirected' }\n },\n async passkeyAutofill(o = {}) {\n const cancelled = { ok: false as const, error: { code: 'cancelled', message: 'No passkey was chosen.' } }\n const m = await methods()\n if (!m.passkeyHere || !(await canAutofillPasskeys())) return cancelled\n for (;;) {\n if (o.signal?.aborted) return cancelled\n const begun = await post('/sign-in/passkey/begin', {}, null)\n if (!begun.ok) return begun\n // Cauthy's challenge lives five minutes: a page left open asks for\n // a fresh one before it runs out.\n const renew = new AbortController()\n const stop = () => renew.abort()\n o.signal?.addEventListener('abort', stop, { once: true })\n const timer = setTimeout(stop, (PASSKEY_SECONDS - 30) * 1000)\n let credential: Record<string, unknown>\n try {\n credential = await getPasskey(begun.options, { mediation: 'conditional', signal: renew.signal })\n } catch (e) {\n if (o.signal?.aborted) return cancelled\n if (renew.signal.aborted) continue\n return { ok: false, error: ceremonyError(e) }\n } finally {\n clearTimeout(timer)\n o.signal?.removeEventListener('abort', stop)\n }\n return post('/sign-in/passkey/finish', { credential }, null)\n }\n },\n async googleOneTap(o = {}) {\n const cancelled = { ok: false as const, error: { code: 'cancelled', message: 'No Google account was chosen.' } }\n if (typeof window === 'undefined' || o.signal?.aborted) return cancelled\n const begun = await post('/sign-in/google-one-tap/begin', {}, null)\n if (!begun.ok) return begun\n let gis: GoogleIdentity\n try {\n gis = await loadGoogleIdentity()\n } catch {\n return { ok: false, error: { code: 'unavailable', message: 'Google could not be reached. Try again, or sign in another way.' } }\n }\n const credential = await new Promise<string | null>((done) => {\n o.signal?.addEventListener('abort', () => {\n gis.cancel()\n done(null)\n }, { once: true })\n gis.initialize({\n client_id: begun.clientId, nonce: begun.nonce, context: o.context ?? 'signin',\n callback: (r: { credential?: string }) => done(r.credential ?? null),\n auto_select: false, cancel_on_tap_outside: true, itp_support: true, use_fedcm_for_prompt: true,\n })\n gis.prompt((moment: GoogleMoment) => {\n // The prompt was not shown, or the person closed it.\n if (moment.isNotDisplayed?.() || moment.isSkippedMoment?.()) done(null)\n else if (moment.isDismissedMoment?.() && moment.getDismissedReason?.() !== 'credential_returned') done(null)\n })\n })\n if (credential === null) return cancelled\n return post('/sign-in/google-one-tap', { credential }, null)\n },\n socialUrl,\n social(provider, o) {\n window.location.assign(socialUrl(provider, o))\n },\n ssoDiscover: (f) => post('/sign-in/sso/discover', { email: f.email.trim() }, checkEmail(f.email)),\n ssoUrl,\n sso(target, o) {\n window.location.assign(ssoUrl(target, o))\n },\n },\n signUp: {\n email: (f) => post('/sign-up/email', { email: f.email, password: f.password, name: f.name, organization: f.organization, acceptLegal: f.acceptLegal, consents: f.consents },\n firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy), checkOrganization(f.organization)), f.captchaToken),\n },\n forgotPassword: (f) => post('/forgot-password', { email: f.email }, checkEmail(f.email), f.captchaToken),\n resetPassword: (f) => post('/reset-password', { token: f.token, password: f.password }, checkNewPassword(f.password, policy)),\n verifyEmail: (f) => post('/verify-email', { token: f.token }, null),\n async invitation(token) {\n const bad = { ok: false as const, error: { code: 'invalid_token', message: 'This invitation is not valid, or it has expired.' } }\n if (typeof token !== 'string' || token.trim() === '') return bad\n try {\n const res = await doFetch(`${base}/invitation?token=${encodeURIComponent(token.trim())}`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n const body = (await res.json().catch(() => null)) as any\n if (res.ok && body?.invitation) return { ok: true as const, status: 'ok' as const, invitation: body.invitation as Invitation }\n const e = body?.error\n return { ok: false as const, error: e && typeof e.code === 'string' ? { code: e.code, message: String(e.message ?? '') } : UNAVAILABLE }\n } catch {\n return { ok: false as const, error: UNAVAILABLE }\n }\n },\n acceptInvitation: (token, password) => post('/invitation/accept', { token, password }, checkNewPassword(password, policy)),\n signOut: () => post('/sign-out', {}, null),\n organizations: {\n async list(system) {\n const body = await read(`/me/organizations${system ? `?system=${encodeURIComponent(system)}` : ''}`)\n return body && Array.isArray(body.organizations) ? (body.organizations as OrganizationSeat[]) : []\n },\n async members(id) {\n const body = await read(`/me/organizations/members?id=${encodeURIComponent(id)}`)\n return body && Array.isArray(body.members) ? (body.members as OrganizationPerson[]) : null\n },\n async roles(id) {\n const body = await read(`/me/organizations/roles?id=${encodeURIComponent(id)}`)\n return body && Array.isArray(body.roles) ? (body.roles as OrganizationRoleChoice[]) : null\n },\n add: (id, f) => post('/me/organizations/members/add', { organizationId: id, email: f.email, role: f.role, name: f.name ?? '', locale: f.locale ?? '' }, checkEmail(f.email)),\n setRole: (id, userId, role) => post('/me/organizations/members/role', { organizationId: id, userId, role }, null),\n remove: (id, userId) => post('/me/organizations/members/remove', { organizationId: id, userId }, null),\n inviteAgain: (id, userId, f = {}) => post('/me/organizations/members/invite', { organizationId: id, userId, locale: f.locale ?? '' }, null),\n rename: (id, name) => post('/me/organizations/rename', { organizationId: id, name }, checkOrganizationName(name)),\n archive: (id) => post('/me/organizations/archive', { organizationId: id }, null),\n delete: (id) => post('/me/organizations/delete', { organizationId: id }, null),\n async check(q) {\n const organizationId = typeof q.organization === 'string' ? q.organization : (q.organization?.id ?? '')\n const r = await post('/me/organizations/check', {\n organizationId, resource: q.resource, action: q.action,\n ...(q.attributes !== undefined ? { attributes: q.attributes } : {}),\n ...(q.resourceId !== undefined ? { resourceId: q.resourceId } : {}),\n ...(q.ownerId !== undefined ? { ownerId: q.ownerId } : {}),\n }, null)\n if (!r.ok) return { allowed: false, reason: r.error.message, error: r.error }\n return { allowed: r.allowed === true, reason: String(r.reason ?? ''), ...(r.rule ? { rule: r.rule } : {}) }\n },\n },\n account: {\n async get() {\n const body = await read('/me')\n return body && typeof body.account === 'object' ? (body.account as Account) : null\n },\n update: (f) => post('/me', { name: f.name }, checkName(f.name)),\n async legal() {\n const body = await read('/me/legal')\n if (!body) return { ok: false as const, error: { code: 'not_signed_in', message: 'Nobody is signed in.' } }\n return { ok: true as const, status: 'ok' as const, pending: Array.isArray(body.pending) ? body.pending : [] }\n },\n acceptLegal: (f = {}) => post('/me/legal/accept', { kinds: f.kinds ?? [] }, null),\n changePassword: (f) => {\n const bad = checkNewPassword(f.newPassword, policy)\n return post('/me/password', { password: f.password, newPassword: f.newPassword }, bad ? { ...bad, field: 'newPassword' } : null)\n },\n mfa: {\n setup: (f) => post('/me/mfa/setup', { password: f.password }, null),\n verify: (f) => post('/me/mfa/verify', { code: f.code }, checkCode(f.code)),\n disable: (f) => post('/me/mfa/disable', { password: f.password }, null),\n recoveryCodes: (f) => post('/me/mfa/recovery-codes', { password: f.password }, null),\n async factors() {\n const body = await read('/me/mfa/factors')\n return body && typeof body.totp === 'boolean' ? (body as SecondStep) : null\n },\n addPhone: (f) => post('/me/mfa/phone', { phone: f.phone, channel: f.channel, password: f.password }, null),\n verifyPhone: (f) => post('/me/mfa/phone/verify', { code: f.code }, checkCode(f.code)),\n removePhone: (f) => post('/me/mfa/phone/remove', { password: f.password }, null),\n },\n changeEmail: (f) => post('/me/email', { email: f.email, password: f.password }, checkEmail(f.email)),\n async identities() {\n const body = await read('/me/identities')\n return body && Array.isArray(body.identities) ? (body.identities as LinkedIdentity[]) : []\n },\n linkUrl,\n link(provider, o) {\n window.location.assign(linkUrl(provider, o))\n },\n unlink: (provider) => post('/me/identities/unlink', { provider }, null),\n async sessions() {\n const body = await read('/me/sessions')\n return body && Array.isArray(body.sessions) ? (body.sessions as AccountSession[]) : []\n },\n signOutEverywhere: () => post('/me/sessions/end', {}, null),\n upgrade: (f) => post('/me/upgrade', { email: f.email, password: f.password, name: f.name ?? '' }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy))),\n upgradeUrl,\n upgradeWith(provider, o) {\n window.location.assign(upgradeUrl(provider, o))\n },\n async agents() {\n const body = await read('/me/agents')\n return body && Array.isArray(body.agents) ? (body.agents as ConnectedAgent[]) : []\n },\n disconnectAgent: (id) => post('/me/agents/disconnect', { id }, null),\n async passkeys() {\n const body = await read('/me/passkeys')\n return body && Array.isArray(body.passkeys) ? (body.passkeys as Passkey[]) : []\n },\n addPasskey(f = {}) {\n if (!canUsePasskeys()) return Promise.resolve({ ok: false, error: { code: 'passkey_unavailable', message: 'This browser cannot make passkeys.' } })\n return ceremony('/me/passkeys/add/begin', '/me/passkeys/add/finish', { password: f.password ?? '', ...(f.kind ? { kind: f.kind } : {}) }, makePasskey, { name: f.name ?? '' })\n },\n removePasskey: (id) => post('/me/passkeys/remove', { id }, null),\n },\n async getSession() {\n try {\n const res = await doFetch(`${base}/session`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n if (!res.ok) return null\n return ((await res.json()) as { session: PublicSession | null }).session\n } catch {\n return null\n }\n },\n look() {\n looked ??= read('/look').then((wire) => (wire && typeof wire === 'object' ? fromWire(wire) : null))\n return looked\n },\n methods,\n }\n}\n\nexport { canAutofillPasskeys, canUsePasskeys } from './passkey'\nexport { createSessionStore, type SessionState, type SessionStore, type SessionStoreOptions } from './store'\n","// What a person may do in an organization.\n//\n// When a system keeps its catalog of roles in Cauthy, each of a person's\n// organizations arrives with what their role — and anything given or denied to\n// them apart from it — lets them do. Checking is a lookup in that list: no\n// call to Cauthy, on the server or in the browser.\n\nimport type { CheckQuestion, CheckResult, CheckRule, ConditionalPermission, OrganizationRef } from './types'\nimport { withoutTrailingSlashes } from './url'\n\n/** The part of an organization that says what its member may do. */\nexport interface Permitted {\n /** \"resource:action\" entries the person is allowed; \"*\" is any. Absent when the system keeps no catalog in Cauthy. */\n permissions?: string[]\n /** Entries the person is denied whatever else allows them. */\n denied?: string[]\n /** Permissions with a condition: in neither list, so `can` never counts them. Ask with `auth.check`. */\n conditional?: ConditionalPermission[]\n}\n\nfunction matches(entry: string, resource: string, action: string): boolean {\n // The resource may itself hold a colon: the action is what follows the last one.\n const i = entry.lastIndexOf(':')\n if (i < 0) return false\n const r = entry.slice(0, i)\n const a = entry.slice(i + 1)\n return (r === '*' || r === resource) && (a === '*' || a === action)\n}\n\n/**\n * Whether the person may do an action on a resource in an organization:\n * allowed by some entry, and denied by none. A denial wins.\n *\n * An organization of a system that keeps no catalog in Cauthy carries no\n * permissions, and the answer is `false`: decide by its `role` instead.\n *\n * A permission with a condition (`organization.conditional`) is not in the\n * lists, so `can` answers `false` for what only it allows: the condition reads\n * the record at hand, which only Cauthy can weigh. Ask with `auth.check`\n * (`organizations.check` in the browser).\n *\n * if (!can(organization, 'invoicing', 'write')) return forbidden()\n */\nexport function can(organization: Permitted | null | undefined, resource: string, action: string): boolean {\n if (!organization?.permissions) return false\n if ((organization.denied ?? []).some((d) => matches(d, resource, action))) return false\n return organization.permissions.some((p) => matches(p, resource, action))\n}\n\n// ── A system's catalog of roles ────────────────────────────────────────────\n\n/** Something a role may do: an action on a resource, in organizations of a kind (\"*\", the default, is every kind). */\nexport interface PolicyPermission {\n kind?: string\n resource: string\n action: string\n /**\n * When it holds, in CEL: `resource.attrs.amount <= 1000000`. A permission\n * with one is decided by Cauthy per question (`auth.check`), never by `can`.\n */\n condition?: string\n}\n\n/** The type of an attribute a condition may read: `list` is any JSON array. */\nexport type AttributeType = 'string' | 'number' | 'bool' | 'list'\n\n/** A resource of a system's catalog: the actions done on it and the attributes its conditions read. */\nexport interface CatalogResource {\n resource: string\n description?: string\n actions: string[]\n /** Name → type, as `resource.attrs.<name>` in a condition. */\n attributes?: Record<string, AttributeType>\n}\n\nexport interface PolicyRole {\n role: string\n name?: string\n description?: string\n /** Roles whose permissions this one has as well. */\n inherits?: string[]\n permissions?: PolicyPermission[]\n}\n\n// ── The catalog, with its types ────────────────────────────────────────────\n//\n// A catalog written down once gives the roles and the permissions their\n// names: `can(org, 'ledger:write')` then takes only a permission the catalog\n// has, the editor offers them, and a typo does not compile.\n//\n// export const policy = definePolicy([\n// { role: 'reader', permissions: [{ resource: 'ledger', action: 'read' }] },\n// { role: 'accountant', inherits: ['reader'], permissions: [{ resource: 'ledger', action: 'write' }] },\n// ])\n// export const { can, hasRole } = policy\n//\n// can(organization, 'ledger:write') // 'ledger:wirte' does not compile\n// hasRole(organization, 'accountant')\n//\n// A system that declares its resources gives them too, with their actions and\n// the attributes a condition reads, and a check is typed by them:\n//\n// export const policy = definePolicy({\n// catalog: [{ resource: 'invoices', actions: ['read', 'approve'], attributes: { amount: 'number' } }],\n// roles: [{ role: 'accountant', permissions: [{ resource: 'invoices', action: 'approve', condition: 'resource.attrs.amount <= 1000' }] }],\n// })\n//\n// await policy.check(auth, request, { organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })\n//\n// Write it by hand, or let `cauthy-auth policy --pull` write it from the\n// catalog Cauthy has.\n\ntype PermissionShape = { readonly kind?: string; readonly resource: string; readonly action: string; readonly condition?: string }\n\n/** A role as `definePolicy` reads it: any `PolicyRole`, kept as written. */\ntype RoleShape = {\n readonly role: string\n readonly name?: string\n readonly description?: string\n readonly inherits?: readonly string[]\n readonly permissions?: readonly PermissionShape[]\n}\n\n/** A resource as `definePolicy` reads it: any `CatalogResource`, kept as written. */\ntype ResourceShape = {\n readonly resource: string\n readonly description?: string\n readonly actions: readonly string[]\n readonly attributes?: { readonly [name: string]: AttributeType }\n}\n\n// \"*\" in a catalog is \"any\": the name it stands for is any text.\ntype Named<S extends string> = S extends '*' ? string : S\n\ntype PermissionsIn<R> = R extends { readonly permissions: readonly (infer P)[] }\n ? P extends { readonly resource: infer Res extends string; readonly action: infer Act extends string } ? `${Named<Res>}:${Named<Act>}` : never\n : never\n\ntype ValueOf<T> = T extends 'string' ? string : T extends 'number' ? number : T extends 'bool' ? boolean : T extends 'list' ? unknown[] : never\n\n/** What a check may say about one declared resource. */\ntype QuestionAbout<E> = E extends { readonly resource: infer R extends string; readonly actions: readonly (infer A extends string)[] }\n ? {\n resource: R\n action: A\n attributes?: E extends { readonly attributes: infer T } ? { [K in keyof T]?: ValueOf<T[K]> } : Record<string, never>\n resourceId?: string\n ownerId?: string\n }\n : never\n\n/**\n * What a role of a catalog that declares its resources may name: a declared\n * resource with one of its actions, or \"*\", or one of Cauthy's own powers.\n */\ntype PermissionFor<C extends readonly ResourceShape[]> = { readonly kind?: string; readonly condition?: string } & (\n | (C[number] extends infer E ? E extends { readonly resource: infer R extends string; readonly actions: readonly (infer A extends string)[] } ? { readonly resource: R; readonly action: A | '*' } : never : never)\n | { readonly resource: '*'; readonly action: string }\n | { readonly resource: `cauthy:${string}`; readonly action: string }\n)\ntype RoleFor<C extends readonly ResourceShape[]> = Omit<RoleShape, 'permissions'> & { readonly permissions?: readonly PermissionFor<C>[] }\n\n/** The roles a catalog names: `RoleOf<typeof policy>`. */\nexport type RoleOf<P> = P extends Policy<infer R, any, any> ? R : never\n/** The \"resource:action\" permissions a catalog names: `PermissionOf<typeof policy>`. */\nexport type PermissionOf<P> = P extends Policy<any, infer X, any> ? X : never\n/** What a check about this catalog may ask: `CheckOf<typeof policy>`. Any resource when it declares none. */\nexport type CheckOf<P> = P extends Policy<any, any, infer Q> ? Q : never\n\n/** The fields of a question: whatever else the asker takes (the organization, the person) passes through. */\ntype QuestionKeys = keyof CheckQuestion\n\nexport interface Policy<Role extends string = string, Permission extends string = string, Question extends CheckQuestion = CheckQuestion> {\n /** The catalog as Cauthy takes it: `pushPolicy({ roles: policy.roles })`. */\n roles: PolicyRole[]\n /** The resources the system declares, as Cauthy takes them; empty when it declares none. */\n catalog: CatalogResource[]\n /** Every role's name. */\n roleNames: Role[]\n /** Every permission some role has, as \"resource:action\". */\n permissions: Permission[]\n /**\n * Whether the person may do this in the organization: `can(org, 'ledger:write')`.\n * It reads what Cauthy sent with the session, so a catalog edited in Cauthy\n * since this file was written is still what decides. A permission with a\n * condition is not there: ask with `check`.\n */\n can(organization: Permitted | null | undefined, permission: Permission): boolean\n /** Whether the person's role in the organization is one of these. */\n hasRole(organization: { role: string } | null | undefined, ...roles: Role[]): boolean\n /**\n * What a role may do by this catalog, with what it inherits: for showing a\n * role, never for deciding about a person (their exceptions are not here).\n */\n permissionsOf(role: Role): Permission[]\n /**\n * Asks Cauthy, with the resource, action and attributes typed by the\n * catalog. Give it whoever asks: the server's `auth` with the request,\n * the browser's `organizations`, or the application's `system`.\n *\n * await policy.check(auth, request, { organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })\n * await policy.check(auth.system, { organizationId, userId, resource: 'invoices', action: 'read' })\n */\n check<I extends CheckQuestion>(asker: { check(input: I): Promise<CheckResult> }, input: Omit<I, QuestionKeys> & Question): Promise<CheckResult>\n check<R, I extends CheckQuestion>(asker: { check(request: R, input: I): Promise<CheckResult> }, request: R, input: Omit<I, QuestionKeys> & Question): Promise<CheckResult>\n}\n\n/** A catalog with its resources declared, for `definePolicy`. */\nexport interface PolicyDefinition<C extends readonly ResourceShape[], T extends readonly RoleShape[]> {\n catalog: C\n roles: T\n}\n\n/** Gives a catalog of roles its types. See the top of this section. */\nexport function definePolicy<const T extends readonly RoleShape[]>(roles: T): Policy<T[number]['role'], PermissionsIn<T[number]>>\n/** Gives a catalog of resources and roles its types: a role names only what the catalog declares. */\nexport function definePolicy<const C extends readonly ResourceShape[], const T extends readonly RoleFor<C>[]>(\n definition: PolicyDefinition<C, T>,\n): Policy<T[number]['role'], PermissionsIn<T[number]>, QuestionAbout<C[number]>>\nexport function definePolicy(given: readonly RoleShape[] | PolicyDefinition<readonly ResourceShape[], readonly RoleShape[]>): Policy {\n const roles: readonly RoleShape[] = Array.isArray(given) ? given : (given as PolicyDefinition<readonly ResourceShape[], readonly RoleShape[]>).roles\n const resources: readonly ResourceShape[] = Array.isArray(given) ? [] : (given as PolicyDefinition<readonly ResourceShape[], readonly RoleShape[]>).catalog ?? []\n const entry = (p: { resource: string; action: string }) => `${p.resource}:${p.action}`\n const byName = new Map(roles.map((r) => [r.role, r]))\n const split = (permission: string): [string, string] => {\n const i = permission.lastIndexOf(':')\n return i < 0 ? [permission, ''] : [permission.slice(0, i), permission.slice(i + 1)]\n }\n return {\n roles: roles.map((r) => ({\n role: r.role,\n ...(r.name !== undefined ? { name: r.name } : {}),\n ...(r.description !== undefined ? { description: r.description } : {}),\n ...(r.inherits ? { inherits: [...r.inherits] } : {}),\n ...(r.permissions ? { permissions: r.permissions.map((p) => ({ ...p })) } : {}),\n })),\n catalog: resources.map((c) => ({\n resource: c.resource,\n ...(c.description !== undefined ? { description: c.description } : {}),\n actions: [...c.actions],\n ...(c.attributes ? { attributes: { ...c.attributes } } : {}),\n })),\n roleNames: roles.map((r) => r.role),\n permissions: [...new Set(roles.flatMap((r) => (r.permissions ?? []).map(entry)))],\n can(organization, permission) {\n const [resource, action] = split(permission)\n return can(organization, resource, action)\n },\n hasRole(organization, ...wanted) {\n return organization != null && wanted.includes(organization.role)\n },\n permissionsOf(role) {\n const seen = new Set<string>()\n const out = new Set<string>()\n const walk = (name: string) => {\n if (seen.has(name)) return // a catalog that inherits in a circle still ends\n seen.add(name)\n const r = byName.get(name)\n for (const p of r?.permissions ?? []) out.add(entry(p))\n for (const parent of r?.inherits ?? []) walk(parent)\n }\n walk(role)\n return [...out]\n },\n // The types did the work; this only hands the question on, as a method of\n // the asker so it keeps its `this`.\n check(asker: { check(...args: unknown[]): Promise<CheckResult> }, ...args: unknown[]) {\n return asker.check(...args)\n },\n }\n}\n\nconst IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/** A system's policy as Cauthy has it: the resources it declares (maybe none) and its roles. */\nexport interface SystemPolicy {\n catalog: CatalogResource[]\n roles: PolicyRole[]\n}\n\n/**\n * A TypeScript module that defines the catalog given, for `cauthy-auth policy\n * --pull` to write: the application's types then come from the catalog\n * Cauthy has. With resources declared it is `definePolicy({ catalog, roles })`;\n * without, the list of roles alone, as it always was.\n */\nexport function policySource(system: string, read: PolicyRole[] | { catalog?: CatalogResource[]; roles: PolicyRole[] }): string {\n const roles = Array.isArray(read) ? read : read.roles\n const catalog = Array.isArray(read) ? [] : (read.catalog ?? [])\n const text = (v: string) => JSON.stringify(v)\n const key = (k: string) => (IDENT.test(k) ? k : text(k))\n const one = (r: PolicyRole, pad: string) => {\n const parts = [`role: ${text(r.role)}`]\n if (r.name) parts.push(`name: ${text(r.name)}`)\n if (r.description) parts.push(`description: ${text(r.description)}`)\n if (r.inherits?.length) parts.push(`inherits: [${r.inherits.map(text).join(', ')}]`)\n if (r.permissions?.length) {\n const list = r.permissions.map((p) => `${pad} { ${[\n ...(p.kind && p.kind !== '*' ? [`${key('kind')}: ${text(p.kind)}`] : []),\n `resource: ${text(p.resource)}`,\n `action: ${text(p.action)}`,\n ...(p.condition ? [`condition: ${text(p.condition)}`] : []),\n ].join(', ')} },`)\n parts.push(`permissions: [\\n${list.join('\\n')}\\n${pad} ]`)\n }\n return `${pad} {\\n${pad} ${parts.join(`,\\n${pad} `)},\\n${pad} },`\n }\n const resource = (c: CatalogResource) => {\n const parts = [`resource: ${text(c.resource)}`]\n if (c.description) parts.push(`description: ${text(c.description)}`)\n parts.push(`actions: [${c.actions.map(text).join(', ')}]`)\n const attrs = Object.entries(c.attributes ?? {})\n if (attrs.length) parts.push(`attributes: { ${attrs.map(([k, v]) => `${key(k)}: ${text(v)}`).join(', ')} }`)\n return ` { ${parts.join(', ')} },`\n }\n const head = `// The catalog of roles of ${text(system)}, as Cauthy has it.\n// Written by \\`cauthy-auth policy --pull\\`: run it again after the catalog\n// changes, and do not edit this file by hand.\n`\n if (catalog.length === 0) {\n return `${head}\nimport { definePolicy, type PermissionOf, type RoleOf } from 'cauthy-auth'\n\nexport const policy = definePolicy([\n${roles.map((r) => one(r, '')).join('\\n')}\n])\n\nexport const { can, hasRole } = policy\nexport type Role = RoleOf<typeof policy>\nexport type Permission = PermissionOf<typeof policy>\n`\n }\n return `${head}\nimport { definePolicy, type CheckOf, type PermissionOf, type RoleOf } from 'cauthy-auth'\n\nexport const policy = definePolicy({\n catalog: [\n${catalog.map(resource).join('\\n')}\n ],\n roles: [\n${roles.map((r) => one(r, ' ')).join('\\n')}\n ],\n})\n\nexport const { can, hasRole } = policy\nexport type Role = RoleOf<typeof policy>\nexport type Permission = PermissionOf<typeof policy>\n/** What a check may ask: \\`policy.check(auth, request, { organization, ...question })\\`. */\nexport type Check = CheckOf<typeof policy>\n`\n}\n\n/** Who reads or writes a system's policy: Cauthy's address, the workspace, a person's token. */\ninterface Reach {\n issuer: string\n system: string\n tenant: string\n token: string\n fetch: typeof fetch\n}\n\nfunction reach(o: Omit<PushPolicyOptions, 'roles'>, doing: string): Reach {\n const env = (n: string) => (typeof process !== 'undefined' ? process.env?.[n] : undefined)\n const r = {\n issuer: withoutTrailingSlashes(o.issuer ?? env('CAUTHY_ISSUER') ?? ''),\n system: o.system ?? env('CAUTHY_SYSTEM') ?? '',\n tenant: o.tenant ?? env('CAUTHY_TENANT') ?? '',\n token: o.token ?? env('CAUTHY_TOKEN') ?? '',\n }\n for (const [name, v] of Object.entries({ CAUTHY_ISSUER: r.issuer, CAUTHY_SYSTEM: r.system, CAUTHY_TENANT: r.tenant, CAUTHY_TOKEN: r.token })) {\n if (v === '') throw new Error(`cauthy-auth: ${name} is required to ${doing}`)\n }\n return { ...r, fetch: o.fetch ?? fetch }\n}\n\nasync function systemCall(r: Reach, method: 'GET' | 'PUT', what: 'policy' | 'catalog', body?: unknown): Promise<any> {\n const res = await r.fetch(`${r.issuer}/v1/systems/${encodeURIComponent(r.system)}/${what}`, {\n ...(method === 'PUT' ? { method } : {}),\n headers: {\n authorization: `Bearer ${r.token}`, 'x-tenant-key': r.tenant,\n ...(body === undefined ? { accept: 'application/json' } : { 'content-type': 'application/json' }),\n },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n })\n const answer = (await res.json().catch(() => null)) as { data?: any; errors?: { message?: string }[] } | null\n if (!res.ok) {\n const verb = method === 'GET' ? `refused to give the ${what}` : `refused the ${what}`\n throw new Error(`cauthy-auth: Cauthy ${verb} (${res.status}): ${answer?.errors?.[0]?.message ?? res.statusText}`)\n }\n return answer?.data\n}\n\n/** Reads a system's catalog of roles from Cauthy, with a personal access token. */\nexport async function pullPolicy(o: Omit<PushPolicyOptions, 'roles'> = {}): Promise<PolicyRole[]> {\n const data = await systemCall(reach(o, 'read a policy'), 'GET', 'policy')\n return (data?.roles as PolicyRole[] | undefined) ?? []\n}\n\n/** Reads the resources a system declares (empty when it declares none), with a personal access token. */\nexport async function pullCatalog(o: Omit<PushPolicyOptions, 'roles'> = {}): Promise<CatalogResource[]> {\n const data = await systemCall(reach(o, 'read a catalog'), 'GET', 'catalog')\n return (data?.resources as CatalogResource[] | undefined) ?? []\n}\n\nexport interface PushPolicyOptions {\n /** The system whose catalog this is. Default: `CAUTHY_SYSTEM`. */\n system?: string\n roles: PolicyRole[]\n /**\n * The resources the system declares. Given, they are sent before the roles,\n * which Cauthy then checks against them; left out, the catalog Cauthy has\n * stays as it is.\n */\n catalog?: CatalogResource[]\n /** Cauthy's address. Default: `CAUTHY_ISSUER`. */\n issuer?: string\n /** The workspace's slug. Default: `CAUTHY_TENANT`. */\n tenant?: string\n /**\n * A personal access token: `organizations:manage` reads, and changing a\n * policy or a catalog takes `systems:policy`. Default: `CAUTHY_TOKEN`.\n */\n token?: string\n fetch?: typeof fetch\n}\n\n/**\n * Gives Cauthy a system's catalog of roles, replacing the one it has. It is\n * the way to load a first catalog from what a system already had; from then on\n * the catalog is Cauthy's, edited in its dashboard, and pushing again would\n * overwrite what was edited there. With `catalog` the declared resources go\n * first: the roles are checked against them.\n */\nexport async function pushPolicy(o: PushPolicyOptions): Promise<void> {\n const r = reach(o, 'push a policy')\n if (o.catalog !== undefined) await systemCall(r, 'PUT', 'catalog', { resources: o.catalog })\n await systemCall(r, 'PUT', 'policy', { roles: o.roles })\n}\n\n/**\n * Gives Cauthy the resources a system declares, replacing the ones it has.\n * Cauthy refuses (`catalog_in_use`) to drop a resource or an action the\n * policy still names.\n */\nexport async function pushCatalog(o: Omit<PushPolicyOptions, 'roles' | 'catalog'> & { resources: CatalogResource[] }): Promise<CatalogResource[]> {\n const data = await systemCall(reach(o, 'push a catalog'), 'PUT', 'catalog', { resources: o.resources })\n return (data?.resources as CatalogResource[] | undefined) ?? []\n}\n\n/** What a policy file holds: the roles alone (as it used to), or `{ catalog, roles }`. */\nexport function readPolicyFile(parsed: unknown): SystemPolicy {\n if (Array.isArray(parsed)) return { catalog: [], roles: parsed as PolicyRole[] }\n const o = (parsed ?? {}) as { roles?: unknown; catalog?: unknown }\n if (!Array.isArray(o.roles)) throw new Error('no \"roles\" list')\n if (o.catalog !== undefined && !Array.isArray(o.catalog)) throw new Error('\"catalog\" is not a list')\n return { catalog: (o.catalog as CatalogResource[] | undefined) ?? [], roles: o.roles as PolicyRole[] }\n}\n\n// ── Asking Cauthy ──────────────────────────────────────────────────────────\n\n/** A check's question as Cauthy reads it. */\nexport function checkWire(q: CheckQuestion): Record<string, unknown> {\n return {\n resource: q.resource,\n action: q.action,\n ...(q.resourceId !== undefined ? { resource_id: q.resourceId } : {}),\n ...(q.ownerId !== undefined ? { owner_id: q.ownerId } : {}),\n ...(q.attributes !== undefined ? { attributes: q.attributes } : {}),\n }\n}\n\n/** Cauthy's answer to a check, as the SDK gives it. Anything but a plain yes is a no. */\nexport function checkResultOf(d: any): CheckResult {\n const r = d?.rule\n const rule: CheckRule | undefined = r && typeof r === 'object'\n ? {\n source: r.source === 'exception' ? 'exception' : 'role',\n ...(r.role ? { role: String(r.role) } : {}),\n kind: String(r.kind ?? '*'),\n resource: String(r.resource ?? ''),\n action: String(r.action ?? ''),\n effect: r.effect === 'allow' ? 'allow' : 'deny',\n ...(r.condition ? { condition: String(r.condition) } : {}),\n }\n : undefined\n return { allowed: d?.allowed === true, reason: String(d?.reason ?? ''), ...(rule ? { rule } : {}) }\n}\n\n/** The id of an organization given by its id or as the session has it. */\nexport function organizationIdOf(o: OrganizationRef | null | undefined): string {\n return typeof o === 'string' ? o : typeof o?.id === 'string' ? o.id : ''\n}\n","// The sign-in screens, ready to use.\n//\n// <SignIn onSuccess={() => navigate('/')} />\n// <SignUp locale=\"es\" />\n// <ForgotPassword />\n//\n// They are plain forms — a label, an input, a button. Import\n// `cauthy-auth/styles.css` once and they are drawn with the colours, corners and\n// typeface a person set for the workspace in Cauthy's dashboard, the same as\n// Cauthy's own sign-in page. Or give them the application's own button and\n// input (`components`), or a class for each part (`classNames`), and pass\n// `unstyled` to leave all of that out. Everything they do is `useAuth()`: an\n// application that wants another form writes it with the same functions.\n\nimport { Fragment, useCallback, useEffect, useId, useRef, useState, useSyncExternalStore, type ComponentType, type CSSProperties, type FormEvent, type ReactNode } from 'react'\nimport { canUsePasskeys, checkEmail, checkName, checkNewPassword, checkPassword, createAuthClient, passwordProblems, describePasswordPolicy, explainPasswordProblems, MIN_PASSWORD, type PasswordPolicy, type Account as AccountDetails, type AccountSession, type AuthError, type ConnectedAgent, type AuthMethods, type Invitation, type LinkedIdentity, type OrganizationPerson, type OrganizationRoleChoice, type OrganizationSeat, type Passkey, type PendingLegal, type SecondStep, type SSOConnection } from './client'\nimport { useAuth, useSession } from './react'\nimport { themeVariables, type CauthyTheme, type ThemeFont } from './theme'\nimport { checkOrganization } from './validate'\n\n/** Every sentence the forms show. Give any of them to change it. */\nexport interface AuthTexts {\n email: string\n password: string\n name: string\n code: string\n signIn: string\n signUp: string\n continueWith: string // \"Continue with\" + the provider's name\n orWithEmail: string\n forgotPassword: string\n noAccount: string\n createAccount: string\n /** The label of the company's name, asked when the application's system makes an organization per sign-up. */\n company: string\n /** The legal box: \"I have read and accept\" + \"the Terms of Service\" + \"and\" + \"the Privacy Policy\", linked. */\n iAccept: string\n and: string\n termsOfService: string\n privacyPolicy: string\n haveAccount: string\n sendLink: string\n linkSent: string\n codeHelp: string\n /** The second step when it is a phone only. */\n codeHelpPhone: string\n /** The second step by email (the account has no factor): \"{to}\" is the address, masked. */\n codeHelpEmail: string\n sendEmailAgain: string\n /** \"{to}\" is the phone, masked. */\n sendCodeSms: string\n sendCodeWhatsapp: string\n codeSent: string\n /** The second step approved on the phone; \"{n}\" is the number to pick. */\n pushSend: string\n pushPick: string\n pushWaiting: string\n // The phone on the account screen.\n phone: string\n phoneHelp: string\n phoneOn: string // \"{to}\": the phone, masked\n phoneOff: string\n addPhone: string\n removePhone: string\n bySms: string\n byWhatsapp: string\n /** The label of the channel phone codes go by, where the application draws it as a select. */\n channel: string\n verify: string\n checkEmail: string\n backToSignIn: string\n emailMeALink: string\n usePasskey: string\n codeFromMail: string\n signInLinkSent: string\n newPassword: string\n savePassword: string\n passwordChanged: string\n confirming: string\n emailConfirmed: string\n // <AcceptInvite />: the page an invitation opens.\n invitedTo: string // \"{workspace}\" is replaced\n invitedToOrganization: string // \"{organization}\" and \"{workspace}\" are replaced\n invitedAs: string // \"{email}\" is replaced\n choosePassword: string\n acceptInvite: string\n openingInvitation: string\n invitationInvalid: string\n // The account screen.\n profile: string\n save: string\n saved: string\n currentPassword: string\n changePassword: string\n passwordChangedHere: string\n secondStep: string\n secondStepOn: string\n secondStepOff: string\n turnOn: string\n turnOff: string\n addToApp: string // above the secret to add to an authenticator app\n openInApp: string\n recoveryCodes: string\n newRecoveryCodes: string\n keepCodes: string\n passkeys: string\n managePasskeys: string\n passkeysHelp: string\n noPasskeys: string\n passkeyName: string\n /** @deprecated Unused since 0.19.0: the account screen offers `addPasskeyDevice` and `addSecurityKey`. */\n addPasskey: string\n addPasskeyDevice: string\n addSecurityKey: string\n passkeyKinds: Record<'security_key' | 'synced' | 'device', string>\n removePasskey: string\n passkeyAdded: string\n passkeyUnnamed: string\n sessions: string\n signOutEverywhere: string\n agents: string\n agentsHelp: string\n disconnect: string\n anAgent: string\n unknownDevice: string\n emailAddress: string\n newEmail: string\n changeEmail: string\n emailSent: string // after asking: \"{email}\" is replaced\n linkedAccounts: string\n noLinkedAccounts: string\n linkWith: string // + the provider's name\n unlink: string\n linked: string // after coming back linked\n ssoOnly: string // the address signs in through its company alone\n // <OrganizationMembers />: the people of the person's organization.\n members: string\n membersHidden: string\n organizationMissing: string\n memberYou: string\n memberInvited: string\n memberManager: string\n memberRole: string\n memberAdd: string\n memberAdded: string // \"{email}\" is replaced\n memberRemove: string\n memberRemoveConfirm: string // \"{who}\" is replaced\n memberLeave: string\n memberLeaveConfirm: string // \"{org}\" is replaced\n memberInviteAgain: string\n memberInvitationSent: string\n // The organization itself, for a member whose role may change it.\n organization: string\n organizationRename: string\n organizationRenamed: string // \"{name}\" is replaced\n organizationArchive: string\n organizationArchiveConfirm: string // \"{org}\" is replaced\n organizationArchived: string // \"{org}\" is replaced\n organizationDelete: string\n organizationDeleteConfirm: string // \"{org}\" is replaced\n organizationDeleted: string // \"{org}\" is replaced\n yes: string\n cancel: string\n // <PendingTerms />: documents a signed-in person still owes.\n termsChanged: string\n termsChangedHelp: string // followed by the documents, linked\n acceptTerms: string\n /** By error code; one missing shows what the server said. */\n errors: Record<string, string>\n}\n\nconst TEXTS: Record<'en' | 'es', AuthTexts> = {\n en: {\n email: 'Email', password: 'Password', name: 'Name', company: \"Your company's name\", code: 'Code', signIn: 'Sign in', signUp: 'Create account',\n continueWith: 'Continue with', orWithEmail: 'or with your email', forgotPassword: 'Forgot your password?',\n noAccount: 'No account yet?', createAccount: 'Create one', haveAccount: 'Already have an account?',\n iAccept: 'I have read and accept', and: 'and', termsOfService: 'the Terms of Service', privacyPolicy: 'the Privacy Policy',\n sendLink: 'Send the link', linkSent: 'If that address has an account, a link to choose a new password is on its way.',\n codeHelp: 'Enter the code from your authenticator app, or a recovery code.', verify: 'Verify',\n codeHelpPhone: 'We send a code to your phone. Ask for it, then type it here, or use a recovery code.',\n codeHelpEmail: 'We sent a code to {to}. Type it here.', sendEmailAgain: 'Send the code again',\n sendCodeSms: 'Send a code by SMS to {to}', sendCodeWhatsapp: 'Send a code by WhatsApp to {to}', codeSent: 'We sent a code to {to}. Type it here.',\n pushSend: 'Approve on my phone', pushPick: 'On your phone, pick {n}', pushWaiting: 'We sent a notification to your phone. Open it and pick this number.',\n phone: 'Phone, with its country code', phoneHelp: 'Get your codes by SMS or WhatsApp instead of an app.', phoneOn: 'Codes go to {to}.',\n phoneOff: 'No phone yet.', addPhone: 'Add phone', removePhone: 'Remove phone', bySms: 'SMS', byWhatsapp: 'WhatsApp', channel: 'Send codes by',\n checkEmail: 'Almost there: open the link we sent to confirm your address — it signs you in.', backToSignIn: 'Back to sign in',\n emailMeALink: 'Email me a sign-in link', usePasskey: 'Sign in with a passkey', codeFromMail: 'Reading it on another device? Enter the code from the email.', signInLinkSent: 'If that address has an account, a link to sign in is on its way.',\n newPassword: 'New password', savePassword: 'Save the password', passwordChanged: 'Your password was changed. You can sign in with it now.',\n confirming: 'Confirming your address…', emailConfirmed: 'Your address is confirmed. You can sign in now.',\n invitedTo: \"You've been invited to {workspace}\", invitedToOrganization: \"You've been invited to {organization} on {workspace}\",\n invitedAs: 'You will sign in as {email}.', choosePassword: 'Choose a password', acceptInvite: 'Accept and sign in',\n openingInvitation: 'Opening your invitation…', invitationInvalid: 'This invitation is not valid: it was already used, or it has expired. Ask whoever invited you to send it again.',\n profile: 'Profile', save: 'Save', saved: 'Saved.', currentPassword: 'Current password', changePassword: 'Change password',\n passwordChangedHere: 'Your password was changed. Every other session of your account was signed out.',\n secondStep: 'Second step', secondStepOn: 'On: signing in also asks for a code from your authenticator app.', secondStepOff: 'Off: signing in asks only for your password.',\n turnOn: 'Turn on', turnOff: 'Turn off', addToApp: 'Add this key to your authenticator app, then enter the code it shows.', openInApp: 'Open in an authenticator app',\n recoveryCodes: 'Recovery codes', newRecoveryCodes: 'New recovery codes', keepCodes: 'Keep these codes somewhere safe. Each works once, and they are not shown again.',\n passkeys: 'Passkeys', managePasskeys: 'Add or remove a passkey',\n passkeysHelp: 'Sign in with your fingerprint, your face or your device\\'s lock, without a password.', noPasskeys: 'No passkey yet.',\n passkeyName: 'A name for this device (optional)', addPasskey: 'Add a passkey on this device', removePasskey: 'Remove',\n addPasskeyDevice: 'Add this device (fingerprint or face)', addSecurityKey: 'Add a security key',\n passkeyKinds: { security_key: 'Security key', synced: 'Synced across your devices', device: 'On this device only' },\n passkeyAdded: 'The passkey was added. Next time, sign in with it.', passkeyUnnamed: 'Passkey', sessions: 'Where you are signed in', signOutEverywhere: 'Sign out everywhere',\n agents: 'AI agents', agentsHelp: 'Agents you allowed to act for you. Disconnect one and it loses its access within minutes.', disconnect: 'Disconnect', anAgent: 'An AI agent', unknownDevice: 'Unknown device',\n emailAddress: 'Email address', newEmail: 'New email address', changeEmail: 'Change email',\n emailSent: 'We sent a link to {email}. Your address changes once you open it.',\n linkedAccounts: 'Linked accounts', noLinkedAccounts: 'No account is linked.', linkWith: 'Link', unlink: 'Unlink', linked: 'The account was linked.',\n ssoOnly: 'Your company signs you in to this account.',\n members: 'Members', membersHidden: 'Your role here does not let you see the members.', organizationMissing: 'You do not belong to this organization.',\n memberYou: 'you', memberInvited: 'invited', memberManager: 'manages members', memberRole: 'Role', memberAdd: 'Add member',\n memberAdded: '{email} is a member now.', memberRemove: 'Remove', memberRemoveConfirm: 'Remove {who}?', memberLeave: 'Leave',\n memberLeaveConfirm: 'Leave {org}? You will need an invitation to come back.', memberInviteAgain: 'Send the invitation again',\n memberInvitationSent: 'The invitation is on its way.',\n organization: 'Organization', organizationRename: 'Rename', organizationRenamed: 'The organization is now called {name}.',\n organizationArchive: 'Archive', organizationArchiveConfirm: 'Archive {org}? Its members will no longer reach it, and only the workspace can restore it.',\n organizationArchived: '{org} was archived.', organizationDelete: 'Delete organization',\n organizationDeleteConfirm: 'Delete {org} for good? Its members lose it and this cannot be undone.', organizationDeleted: '{org} was deleted.',\n yes: 'Yes', cancel: 'Cancel',\n termsChanged: 'Our terms changed', termsChangedHelp: 'To go on, read and accept', acceptTerms: 'Accept',\n errors: {\n not_allowed: 'Your role in this organization does not allow that.', last_manager: 'Somebody else must manage the members first: give that role to another member.',\n last_owner: 'An organization keeps at least one owner: make another member owner first.', organization_not_found: 'That organization no longer exists.',\n member_exists: 'That person already belongs to the organization; their role was not changed. Change it in the list instead.',\n already_member: 'That person already belongs to the organization. Change their role instead.', unknown_role: 'Choose one of the roles offered.',\n user_not_active: 'That account is disabled.',\n required: 'This is required.', invalid_email: 'That does not look like an email address.', too_short: `Use at least ${MIN_PASSWORD} characters.`,\n invalid_credentials: 'The address or the password is not right.', unavailable: 'Sign-in is unavailable right now. Try again in a moment.',\n state_mismatch: 'That sign-in could not be completed. Try again.', cancelled: 'The sign-in was cancelled.',\n email_taken: 'That address already has an account.', email_unchanged: 'That is already your address.',\n last_sign_in_method: 'Add a password or link another account first: it is your only way to sign in.',\n identity_already_linked: 'That account is linked to someone else.', manual_linking_disabled: 'Linking accounts is turned off for this workspace.',\n invalid_token: 'This link is not valid, or it has expired. Ask for a new one.', invalid_code: 'That code is not right, or it has expired.', wrong_password: 'The current password is not right.', step_up_required: 'Enter your current password.', weak_password: 'Choose a stronger password.', unauthenticated: 'Sign in first.',\n phone_refused: 'The code could not be sent to that number.', too_many_codes: 'Enough codes were sent. Use the last one, or sign in again.', phone_unavailable: 'Codes cannot be sent that way here.', phone_already_set: 'Remove the phone you have first.', phone_codes_unavailable: 'Codes cannot be sent right now. Try again in a moment.',\n captcha_required: 'Complete the check that you are not a bot, then try again.', captcha_failed: 'The check that you are not a bot did not pass. Try it again.',\n passkey_failed: 'The passkey could not be used. Try again, or sign in another way.', passkey_exists: 'This device already has a passkey for your account.', passkey_unavailable: 'Passkeys cannot be used here.',\n sso_required: 'This address signs in through its company.', sso_not_found: 'No company sign-in answers for this address.',\n sso_failed: 'The sign-in with your company could not be completed. Try again.', sso_unavailable: 'Your company\\'s sign-in cannot be reached right now. Try again in a moment.',\n invalid_assertion: 'Your company\\'s answer could not be checked. Try again.', provisioning_disabled: 'Your company\\'s sign-in worked, but this workspace has no account for you. Ask its admin to add you.',\n connection_inactive: 'Your company\\'s sign-in is turned off for this workspace.', invalid_grant: 'That sign-in expired. Try again.',\n password_disabled: 'This workspace does not sign in with a password. Use one of the other ways.', passkeys_disabled: 'Passkeys are turned off for this workspace.',\n },\n },\n es: {\n email: 'Correo', password: 'Contraseña', name: 'Nombre', company: 'Nombre de tu empresa', code: 'Código', signIn: 'Entrar', signUp: 'Crear cuenta',\n continueWith: 'Continuar con', orWithEmail: 'o con tu correo', forgotPassword: '¿Olvidaste tu contraseña?',\n noAccount: '¿No tienes cuenta?', createAccount: 'Crear una', haveAccount: '¿Ya tienes cuenta?',\n iAccept: 'He leído y acepto', and: 'y', termsOfService: 'los Términos del servicio', privacyPolicy: 'la Política de privacidad',\n sendLink: 'Enviar el enlace', linkSent: 'Si ese correo tiene una cuenta, ya va en camino un enlace para elegir una contraseña nueva.',\n codeHelp: 'Escribe el código de tu aplicación de autenticación, o un código de recuperación.', verify: 'Verificar',\n codeHelpPhone: 'Te enviamos un código a tu teléfono. Pídelo y escríbelo aquí, o usa un código de recuperación.',\n codeHelpEmail: 'Te enviamos un código a {to}. Escríbelo aquí.', sendEmailAgain: 'Enviar el código de nuevo',\n sendCodeSms: 'Enviar un código por SMS a {to}', sendCodeWhatsapp: 'Enviar un código por WhatsApp a {to}', codeSent: 'Te enviamos un código a {to}. Escríbelo aquí.',\n pushSend: 'Aprobar en mi teléfono', pushPick: 'En tu teléfono, elige el {n}', pushWaiting: 'Enviamos una notificación a tu teléfono. Ábrela y elige este número.',\n phone: 'Teléfono, con su código de país', phoneHelp: 'Recibe tus códigos por SMS o WhatsApp en vez de una app.', phoneOn: 'Los códigos van a {to}.',\n phoneOff: 'Todavía no tienes un teléfono.', addPhone: 'Agregar teléfono', removePhone: 'Quitar teléfono', bySms: 'SMS', byWhatsapp: 'WhatsApp', channel: 'Enviar los códigos por',\n checkEmail: 'Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.', backToSignIn: 'Volver a entrar',\n emailMeALink: 'Envíame un enlace para entrar', usePasskey: 'Entrar con una llave de acceso', codeFromMail: '¿Lo estás leyendo en otro dispositivo? Escribe el código que trae el correo.', signInLinkSent: 'Si ese correo tiene una cuenta, ya va en camino un enlace para entrar.',\n newPassword: 'Contraseña nueva', savePassword: 'Guardar la contraseña', passwordChanged: 'Tu contraseña se cambió. Ya puedes entrar con ella.',\n confirming: 'Confirmando tu correo…', emailConfirmed: 'Tu correo quedó confirmado. Ya puedes entrar.',\n invitedTo: 'Te invitaron a {workspace}', invitedToOrganization: 'Te invitaron a {organization} en {workspace}',\n invitedAs: 'Vas a entrar como {email}.', choosePassword: 'Elige una contraseña', acceptInvite: 'Aceptar y entrar',\n openingInvitation: 'Abriendo tu invitación…', invitationInvalid: 'Esta invitación no es válida: ya se usó o venció. Pídele a quien te invitó que te la envíe de nuevo.',\n profile: 'Perfil', save: 'Guardar', saved: 'Guardado.', currentPassword: 'Contraseña actual', changePassword: 'Cambiar contraseña',\n passwordChangedHere: 'Tu contraseña se cambió. Se cerraron todas las demás sesiones de tu cuenta.',\n secondStep: 'Segundo paso', secondStepOn: 'Activo: al entrar también se pide un código de tu aplicación de autenticación.', secondStepOff: 'Inactivo: al entrar solo se pide tu contraseña.',\n turnOn: 'Activar', turnOff: 'Desactivar', addToApp: 'Agrega esta clave a tu aplicación de autenticación y escribe el código que muestra.', openInApp: 'Abrir en una aplicación de autenticación',\n recoveryCodes: 'Códigos de recuperación', newRecoveryCodes: 'Nuevos códigos de recuperación', keepCodes: 'Guarda estos códigos en un lugar seguro. Cada uno sirve una vez y no se vuelven a mostrar.',\n passkeys: 'Llaves de acceso', managePasskeys: 'Agregar o quitar una llave de acceso',\n passkeysHelp: 'Entra con tu huella, tu rostro o el bloqueo de tu dispositivo, sin contraseña.', noPasskeys: 'Todavía no tienes llaves de acceso.',\n passkeyName: 'Un nombre para este dispositivo (opcional)', addPasskey: 'Agregar una llave en este dispositivo', removePasskey: 'Quitar',\n addPasskeyDevice: 'Agregar este dispositivo (huella o rostro)', addSecurityKey: 'Agregar una llave física',\n passkeyKinds: { security_key: 'Llave física', synced: 'Sincronizada entre tus dispositivos', device: 'Solo en un dispositivo' },\n passkeyAdded: 'La llave de acceso quedó agregada. La próxima vez, entra con ella.', passkeyUnnamed: 'Llave de acceso', sessions: 'Dónde tienes la sesión abierta', signOutEverywhere: 'Cerrar sesión en todas partes',\n agents: 'Agentes de IA', agentsHelp: 'Los agentes a los que permitiste actuar por ti. Si desconectas uno, pierde el acceso en pocos minutos.', disconnect: 'Desconectar', anAgent: 'Un agente de IA', unknownDevice: 'Dispositivo desconocido',\n emailAddress: 'Correo', newEmail: 'Correo nuevo', changeEmail: 'Cambiar el correo',\n emailSent: 'Enviamos un enlace a {email}. Tu correo cambia cuando lo abras.',\n linkedAccounts: 'Cuentas vinculadas', noLinkedAccounts: 'No hay cuentas vinculadas.', linkWith: 'Vincular', unlink: 'Desvincular', linked: 'La cuenta quedó vinculada.',\n ssoOnly: 'A esta cuenta entras con el inicio de sesión de tu empresa.',\n members: 'Miembros', membersHidden: 'Tu rol aquí no te deja ver los miembros.', organizationMissing: 'No perteneces a esta organización.',\n memberYou: 'tú', memberInvited: 'invitado', memberManager: 'administra los miembros', memberRole: 'Rol', memberAdd: 'Agregar miembro',\n memberAdded: '{email} ya es miembro.', memberRemove: 'Quitar', memberRemoveConfirm: '¿Quitar a {who}?', memberLeave: 'Salir',\n memberLeaveConfirm: '¿Salir de {org}? Necesitarás una invitación para volver.', memberInviteAgain: 'Enviar la invitación de nuevo',\n memberInvitationSent: 'La invitación va en camino.',\n organization: 'Organización', organizationRename: 'Cambiar nombre', organizationRenamed: 'La organización ahora se llama {name}.',\n organizationArchive: 'Archivar', organizationArchiveConfirm: '¿Archivar {org}? Sus miembros ya no podrán entrar y solo el espacio de trabajo puede restaurarla.',\n organizationArchived: '{org} quedó archivada.', organizationDelete: 'Eliminar organización',\n organizationDeleteConfirm: '¿Eliminar {org} para siempre? Sus miembros la pierden y no se puede deshacer.', organizationDeleted: '{org} quedó eliminada.',\n yes: 'Sí', cancel: 'Cancelar',\n termsChanged: 'Nuestros términos cambiaron', termsChangedHelp: 'Para seguir, lee y acepta', acceptTerms: 'Aceptar',\n errors: {\n not_allowed: 'Tu rol en esta organización no permite eso.', last_manager: 'Primero alguien más debe administrar los miembros: dale ese rol a otro miembro.',\n last_owner: 'Una organización conserva al menos un propietario: primero haz propietario a otro miembro.', organization_not_found: 'Esa organización ya no existe.',\n member_exists: 'Esa persona ya pertenece a la organización; su rol no cambió. Cámbialo en la lista.',\n already_member: 'Esa persona ya pertenece a la organización. Cambia su rol.', unknown_role: 'Escoge uno de los roles ofrecidos.',\n user_not_active: 'Esa cuenta está desactivada.',\n required: 'Este dato es obligatorio.', invalid_email: 'Eso no parece un correo.', too_short: `Usa al menos ${MIN_PASSWORD} caracteres.`,\n invalid_credentials: 'El correo o la contraseña no son correctos.', unavailable: 'No se puede entrar en este momento. Intenta de nuevo en un momento.',\n state_mismatch: 'No se pudo completar el ingreso. Intenta de nuevo.', cancelled: 'El ingreso se canceló.',\n email_taken: 'Ese correo ya tiene una cuenta.', email_unchanged: 'Ese ya es tu correo.',\n last_sign_in_method: 'Primero agrega una contraseña o vincula otra cuenta: es tu única forma de entrar.',\n identity_already_linked: 'Esa cuenta está vinculada a otra persona.', manual_linking_disabled: 'Vincular cuentas está desactivado en este workspace.',\n invalid_token: 'Este enlace no es válido o ya venció. Pide uno nuevo.', invalid_code: 'Ese código no es correcto o ya venció.', wrong_password: 'La contraseña actual no es correcta.', step_up_required: 'Escribe tu contraseña actual.', weak_password: 'Elige una contraseña más fuerte.', unauthenticated: 'Inicia sesión primero.',\n phone_refused: 'No se pudo enviar el código a ese número.', too_many_codes: 'Ya se enviaron suficientes códigos. Usa el último o vuelve a entrar.', phone_unavailable: 'Aquí no se pueden enviar códigos de esa forma.', phone_already_set: 'Primero quita el teléfono que tienes.', phone_codes_unavailable: 'Ahora no se pueden enviar códigos. Inténtalo en un momento.',\n captcha_required: 'Completa la verificación de que no eres un robot y vuelve a intentarlo.', captcha_failed: 'La verificación de que no eres un robot no pasó. Inténtalo de nuevo.',\n passkey_failed: 'No se pudo usar la llave de acceso. Intenta de nuevo o entra de otra forma.', passkey_exists: 'Este dispositivo ya tiene una llave de acceso de tu cuenta.', passkey_unavailable: 'Aquí no se pueden usar llaves de acceso.',\n sso_required: 'Este correo entra con el inicio de sesión de su empresa.', sso_not_found: 'Ninguna empresa usa inicio de sesión propio con este correo.',\n sso_failed: 'No se pudo completar el ingreso con tu empresa. Intenta de nuevo.', sso_unavailable: 'Ahora no se puede llegar al inicio de sesión de tu empresa. Intenta en un momento.',\n invalid_assertion: 'No se pudo verificar la respuesta de tu empresa. Intenta de nuevo.', provisioning_disabled: 'El ingreso con tu empresa funcionó, pero este workspace no tiene una cuenta para ti. Pídele a su admin que te agregue.',\n connection_inactive: 'El inicio de sesión de tu empresa está apagado en este workspace.', invalid_grant: 'Ese ingreso venció. Intenta de nuevo.',\n password_disabled: 'En este workspace no se entra con contraseña. Usa una de las otras formas.', passkeys_disabled: 'Las llaves de acceso están desactivadas en este workspace.',\n },\n },\n}\n\ntype Slot = 'form' | 'field' | 'label' | 'input' | 'button' | 'providerButton' | 'providerIcon' | 'link' | 'error' | 'fieldError' | 'hint' | 'notice' | 'pending' | 'separator' | 'footer' | 'check' | 'account' | 'section' | 'heading' | 'secret' | 'codes' | 'sessions' | 'session'\n\nexport interface AuthFormProps {\n /** The language of the built-in sentences. Default: `en`. */\n locale?: 'en' | 'es'\n /** Sentences of the application's own, over the built-in ones. */\n texts?: Partial<Omit<AuthTexts, 'errors'>> & { errors?: Record<string, string> }\n /**\n * Called once the person is signed in, instead of going to `returnTo`. The\n * form stays busy (its button loading, every control disabled) until it\n * leaves the page. When the application keeps the form on screen while it\n * moves on (a router's navigation, loading the session), return a Promise:\n * the form waits for it, then is free again if it is still shown.\n */\n onSuccess?: () => void | Promise<unknown>\n /** Where to go after signing in, and where a provider returns to. Default: `/`. */\n returnTo?: string\n /**\n * `<SignIn />`: a sign-in link sent to an address with no account makes\n * one when it is used (if the workspace accepts new accounts), so this one\n * screen signs people in and up alike. Default: off.\n */\n createAccounts?: boolean\n /** Paths of the application's other screens, for the links between them. */\n links?: { signIn?: string; signUp?: string; forgotPassword?: string }\n /** A class for each part the form renders. A part given one is left to it by `styles.css`. */\n classNames?: Partial<Record<Slot, string>>\n /**\n * No look of Cauthy's at all: `styles.css` leaves the form alone and the\n * workspace's colours are not read. For a form drawn wholly with the\n * application's own `components` or `classNames`.\n */\n unstyled?: boolean\n /**\n * Take the colours, corners and typeface a person set for the workspace in\n * Cauthy's dashboard. Default: true. False keeps `styles.css`'s own, and\n * whatever `--cauthy-*` variables the application sets.\n */\n workspaceLook?: boolean\n /**\n * The application's own parts, to draw the form with: its form layout,\n * button, input, checkbox, select, field, text, badge, link, divider, alert\n * and confirmation. A part not given is drawn as before; with every part given\n * and `unstyled`, the form adds no element that carries a look of its own.\n */\n components?: AuthComponents\n}\n\n/**\n * What the application's button is given: what a `<button>` would be, and\n * what kind of button it is. `primary` sends the form; `secondary` is any\n * other action (a provider, a passkey, a sign-in link, cancel, send again);\n * `danger` removes, leaves, deletes, disconnects or turns something off.\n * `loading` is true on the one button whose action is under way; every\n * button is `disabled` meanwhile. Draw a spinner (or the like) on the button\n * while `loading` is true, and keep its label: after a sign-in it stays true\n * until the page is left, so the person sees the work go on.\n */\nexport interface AuthButtonProps {\n type: 'submit' | 'button'; disabled?: boolean; className?: string; onClick?: () => void; children: ReactNode\n variant?: 'primary' | 'secondary' | 'danger'\n loading?: boolean\n}\n\n/**\n * What the application's form layout is given: every element the forms put\n * around their parts — a whole form, each step of it, each part of the\n * account and members screens — so its own stack lays them out. `as` says\n * which element it stands for: a `form` sends with `onSubmit` (render a\n * `<form>` with it for Enter to submit), a `div` only groups.\n */\nexport interface AuthFormLayoutProps {\n as: 'form' | 'div'\n onSubmit?: (e: FormEvent) => void\n noValidate?: boolean\n 'aria-busy'?: boolean\n className?: string\n /**\n * Which part of `<Account />` or `<OrganizationMembers />` this is, for an\n * application that draws each as a card: an `AccountSection`\n * (`profile`, `passkeys`…), or `members`, `add-member`, `organization`\n * and `rename` (the form inside `organization`). Not set on a whole form.\n */\n section?: string\n children: ReactNode\n}\n\n/** What the application's input is given: what an `<input>` would be. */\nexport interface AuthInputProps {\n id: string; name: string; type: string; value: string; autoComplete?: string; required?: boolean; disabled?: boolean; className?: string\n 'aria-invalid'?: boolean; 'aria-describedby'?: string; onChange: (e: { target: { value: string } }) => void\n}\n\n/** A box to tick: the legal documents and each consent of a sign-up. `children` is its label. */\nexport interface AuthCheckboxProps {\n id: string; name: string; checked: boolean; required?: boolean; disabled?: boolean; className?: string\n onChange: (checked: boolean) => void; children: ReactNode\n}\n\n/** One choice of a few: a member's role, the channel of phone codes. Without a visible label it carries `aria-label`. */\nexport interface AuthSelectProps {\n id: string; name: string; value: string; options: { value: string; label: string }[]; disabled?: boolean; className?: string\n 'aria-label'?: string; onChange: (value: string) => void\n}\n\n/**\n * A label, its control (`children`) and what is said under it. The control's\n * `aria-describedby` names `${id}-hint` and `${id}-error`: give the help and\n * the error those ids for a screen reader to read them with it.\n */\nexport interface AuthFieldProps {\n id: string; label: ReactNode; children: ReactNode\n /** Beside the label: \"Forgot your password?\". */\n aside?: ReactNode\n /** What the field takes (a new password's rule). Not given while there is an error. */\n help?: ReactNode\n error?: ReactNode\n required?: boolean; className?: string\n}\n\n/** A sentence of the form: help, a state, the footer (`size: 'sm'`), a section's heading (`as: 'h2'`). */\nexport interface AuthTextProps { as?: 'p' | 'span' | 'h2'; tone?: 'muted' | 'danger' | 'success'; size?: 'sm' | 'md' | 'lg'; children: ReactNode }\n\n/** A short mark beside a name: \"you\", \"invited\", a role, a passkey's kind. */\nexport interface AuthBadgeProps { tone?: 'neutral' | 'success' | 'warning' | 'danger'; children: ReactNode }\n\n/** A link: to another screen, or a legal document (`newTab`). */\nexport interface AuthLinkProps { href?: string; onClick?: () => void; newTab?: boolean; children: ReactNode }\n\n/** The line between the providers and the address: \"or with your email\". */\nexport interface AuthDividerProps { label?: ReactNode }\n\n/**\n * What went wrong (`danger`), what was done (`success`) or what to know\n * (`info`). The built-in one is announced: `role=\"alert\"` for danger,\n * `role=\"status\"` otherwise; the application's should be too.\n */\nexport interface AuthAlertProps { tone: 'danger' | 'info' | 'success'; children: ReactNode }\n\n/** What a confirmation asks: removing a member, leaving, archiving or deleting the organization. */\nexport interface AuthConfirmOptions { title: string; body?: string; confirmLabel: string; cancelLabel: string; danger?: boolean }\n\n/** The parts a form may be drawn with. See `AuthFormProps.components`. */\nexport interface AuthComponents {\n /**\n * Every element around the form's parts: the form itself, each step, each\n * part of the account and members screens. Not given: the `form`, `div` or\n * `section` the forms have always drawn.\n */\n Form?: ComponentType<AuthFormLayoutProps>\n Button?: ComponentType<AuthButtonProps>\n Input?: ComponentType<AuthInputProps>\n Checkbox?: ComponentType<AuthCheckboxProps>\n Select?: ComponentType<AuthSelectProps>\n Field?: ComponentType<AuthFieldProps>\n Text?: ComponentType<AuthTextProps>\n Badge?: ComponentType<AuthBadgeProps>\n Link?: ComponentType<AuthLinkProps>\n Divider?: ComponentType<AuthDividerProps>\n Alert?: ComponentType<AuthAlertProps>\n /**\n * Asks before something that cannot be undone, and answers whether to go\n * on: the application's own dialog. Not given: the question shows inline,\n * with a yes and a cancel button. Never the browser's own dialog.\n */\n Confirm?: (options: AuthConfirmOptions) => Promise<boolean>\n}\n\n// Declared once: a component made anew on every render would be a different\n// input each time, and the one being typed in would lose its place.\n// The kind of a button is for the application's own button. The plain one\n// says it is under way with a spinner before its label, drawn by styles.css.\nconst PlainButton: ComponentType<AuthButtonProps> = ({ variant: _variant, loading, children, ...p }) => (\n <button {...p} aria-busy={loading || undefined}>{loading && <Spinner />}{children}</button>\n)\n// With `unstyled` no stylesheet draws a spinner: the icon draws and turns itself.\nconst UnstyledButton: ComponentType<AuthButtonProps> = ({ variant: _variant, loading, children, ...p }) => (\n <button {...p} aria-busy={loading || undefined}>{loading && <><Spinner plain />{' '}</>}{children}</button>\n)\n\n/**\n * Work under way, as an icon and never as words: the application may be in\n * any language. Styled, it is the ring styles.css draws (still under\n * `prefers-reduced-motion`). Unstyled, no stylesheet is there, so it is an SVG\n * that turns by itself (SMIL), and stands still when the person asked for less\n * motion. The button or form around it says `aria-busy`; the icon is hidden\n * from screen readers.\n */\nfunction Spinner({ plain }: { plain?: boolean }) {\n if (!plain) return <span className=\"cauthy-spinner\" aria-hidden=\"true\" />\n return <SpinnerIcon />\n}\n\nconst LESS_MOTION = '(prefers-reduced-motion: reduce)'\n\nfunction watchMotion(changed: () => void): () => void {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return () => {}\n const query = window.matchMedia(LESS_MOTION)\n query.addEventListener?.('change', changed)\n return () => query.removeEventListener?.('change', changed)\n}\n// A browser that cannot say has no preference to honour.\nconst stillHere = () => typeof window.matchMedia === 'function' && window.matchMedia(LESS_MOTION).matches\n// The server cannot know: its page draws the icon still, and the browser\n// sets it turning once it is there.\nconst stillOnServer = () => true\n\nfunction SpinnerIcon() {\n const still = useSyncExternalStore(watchMotion, stillHere, stillOnServer)\n return (\n <svg className=\"cauthy-spinner-icon\" width=\"1em\" height=\"1em\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" strokeOpacity=\"0.25\" strokeWidth=\"2\" />\n <path d=\"M14.5 8A6.5 6.5 0 0 0 8 1.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n {!still && <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 8 8\" to=\"360 8 8\" dur=\"0.7s\" repeatCount=\"indefinite\" />}\n </path>\n </svg>\n )\n}\nconst PlainInput: ComponentType<AuthInputProps> = (p) => <input {...p} />\n\n// The workspace's look, read once per page and per mount point of the routes.\nconst looks = new Map<string, Promise<CauthyTheme | null>>()\n\n// A typeface is loaded from where the workspace's look says, once per page.\nconst loaded = new Set<string>()\nfunction loadFonts(fonts: ThemeFont[] | undefined) {\n if (typeof document === 'undefined' || typeof FontFace === 'undefined') return\n for (const f of fonts ?? []) {\n const key = `${f.family}|${f.url}|${f.weight ?? ''}|${f.style ?? ''}`\n // The same checks Cauthy's pages make: a plain family name, an https .woff2.\n if (loaded.has(key) || !/^[A-Za-z0-9][A-Za-z0-9 _-]*$/.test(f.family) || !/^https:\\/\\/[^\\s\"'()]+\\.woff2$/i.test(f.url)) continue\n loaded.add(key)\n const face = new FontFace(f.family, `url(\"${f.url}\") format(\"woff2\")`, { weight: String(f.weight ?? '400'), style: f.style === 'italic' ? 'italic' : 'normal', display: 'swap' })\n void face.load().then((ready) => document.fonts.add(ready), () => loaded.delete(key))\n }\n}\n\n/**\n * What the outermost element of a form carries: the mark `styles.css` styles\n * (`data-cauthy`) and the workspace's look as its variables.\n */\nfunction useRoot(props: { unstyled?: boolean; workspaceLook?: boolean }): { 'data-cauthy'?: ''; style?: CSSProperties } {\n const { basePath } = useSession()\n const [vars, setVars] = useState<Record<string, string>>({})\n const wanted = !props.unstyled && props.workspaceLook !== false\n useEffect(() => {\n if (!wanted) return\n let live = true\n let look = looks.get(basePath)\n if (!look) {\n look = createAuthClient({ basePath }).look()\n looks.set(basePath, look)\n }\n void look.then((theme) => {\n if (!live || !theme) return\n setVars(themeVariables(theme))\n loadFonts(theme.fonts)\n })\n return () => { live = false }\n }, [basePath, wanted])\n if (props.unstyled) return {}\n return { 'data-cauthy': '', style: vars as CSSProperties }\n}\n\n/** Cloudflare Turnstile, as much of it as the forms use. */\ninterface TurnstileApi {\n render(el: HTMLElement, options: Record<string, unknown>): string\n reset(id: string): void\n remove(id: string): void\n}\n\nlet turnstileScript: Promise<TurnstileApi> | null = null\n\nfunction loadTurnstile(): Promise<TurnstileApi> {\n const ready = () => (window as unknown as { turnstile?: TurnstileApi }).turnstile\n if (ready()) return Promise.resolve(ready()!)\n turnstileScript ??= new Promise<TurnstileApi>((resolve, reject) => {\n const script = document.createElement('script')\n script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit'\n script.async = true\n script.onload = () => (ready() ? resolve(ready()!) : reject(new Error('turnstile did not load')))\n script.onerror = () => {\n turnstileScript = null\n reject(new Error('turnstile did not load'))\n }\n document.head.appendChild(script)\n })\n return turnstileScript\n}\n\n/**\n * The workspace's Turnstile challenge, when it asks for one: the widget to put\n * in the form, the answer to send with it, and `renew` for after a submit\n * (an answer is good once). Without a site key it draws nothing.\n */\nfunction useChallenge(siteKey: string | undefined, locale: string | undefined) {\n const box = useRef<HTMLDivElement | null>(null)\n const widget = useRef<{ api: TurnstileApi; id: string } | null>(null)\n const [token, setToken] = useState('')\n useEffect(() => {\n if (!siteKey || !box.current) return\n let gone = false\n void loadTurnstile().then((api) => {\n if (gone || !box.current) return\n const id = api.render(box.current, {\n sitekey: siteKey, language: locale ?? 'auto', size: 'flexible',\n callback: (t: string) => setToken(t), 'expired-callback': () => setToken(''), 'error-callback': () => setToken(''),\n })\n widget.current = { api, id }\n }).catch(() => {})\n return () => {\n gone = true\n if (widget.current) widget.current.api.remove(widget.current.id)\n widget.current = null\n }\n }, [siteKey, locale])\n const renew = () => {\n setToken('')\n if (widget.current) widget.current.api.reset(widget.current.id)\n }\n const node = siteKey ? <div ref={box} className=\"cauthy-challenge\" /> : null\n return { node, token: token || undefined, renew }\n}\n\n/** What the workspace offers, for a form that does not read it otherwise. */\nfunction useMethods(auth: ReturnType<typeof useAuth>) {\n const [methods, setMethods] = useState<AuthMethods | null>(null)\n useEffect(() => {\n void auth.methods().then(setMethods)\n // Once: what the workspace offers does not change while the form is open.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n return methods\n}\n\n/** A path of this site, or nothing: never sends the browser elsewhere. */\nfunction sitePath(to: string | null | undefined): string | undefined {\n return to && to.startsWith('/') && !to.startsWith('//') && !to.includes('\\\\') ? to : undefined\n}\n\n/**\n * Where to go once signed in: a path of this site, or an address on this\n * site's own origin. `returnTo` is the application's, but a page may fill it\n * from its query string, so another origin is never followed.\n */\nfunction sameOrigin(to: string | null | undefined): string | undefined {\n const path = sitePath(to)\n if (path || !to) return path\n try {\n const url = new URL(to)\n return url.origin === window.location.origin ? url.pathname + url.search + url.hash : undefined\n } catch {\n return undefined\n }\n}\n\n/** Whether what a callback answered is a Promise to wait for. */\nfunction isPending(v: unknown): v is PromiseLike<unknown> {\n return typeof (v as PromiseLike<unknown> | null)?.then === 'function'\n}\n\n/**\n * Exported for the tests: the package does not export it. `waiting`: the\n * form is not ready yet (what the workspace offers is on its way), so every\n * control waits. `part`: a part of a screen whose look is the screen's.\n */\nexport function useForm(props: AuthFormProps, opts: { waiting?: boolean; part?: boolean } = {}) {\n const t: AuthTexts = { ...TEXTS[props.locale ?? 'en'], ...props.texts, errors: { ...TEXTS[props.locale ?? 'en'].errors, ...props.texts?.errors } }\n const cx = (slot: Slot) => props.classNames?.[slot] ?? `cauthy-${slot}`\n // The class the application gave a part, alone: an application's own part\n // is not handed Cauthy's class names.\n const own = (slot: Slot) => props.classNames?.[slot]\n const C: AuthComponents = props.components ?? {}\n const Button = C.Button ?? (props.unstyled ? UnstyledButton : PlainButton)\n const Input = C.Input ?? PlainInput\n const [error, setOnlyError] = useState<AuthError | null>(null)\n // Every field the form found wrong before sending, in the order they are\n // drawn; `round` moves the focus to the first one again on each try.\n const [problems, setProblems] = useState<{ list: AuthError[]; round: number }>({ list: [], round: 0 })\n // What the server said replaces what the form found.\n const setError = useCallback((e: AuthError | null) => {\n setOnlyError(e)\n setProblems((p) => (p.list.length === 0 ? p : { list: [], round: p.round }))\n }, [])\n /**\n * Checks every field at once, in the order they are drawn: each one wrong\n * shows its error, and the first is focused. True when all can be sent.\n */\n const check = (...found: (AuthError | null | undefined | false)[]): boolean => {\n const list = found.filter((e): e is AuthError => Boolean(e))\n setOnlyError(null)\n setProblems((p) => ({ list, round: list.length > 0 ? p.round + 1 : p.round }))\n return list.length === 0\n }\n /** The error of one field: what the form found, or what the server said. */\n const fieldError = (name: string): AuthError | null => problems.list.find((e) => e.field === name) ?? (error?.field === name ? error : null)\n /** Whether this field is the one to focus after a try, and the try's number. */\n const firstWrong = (name: string): number => (problems.list[0]?.field === name ? problems.round : 0)\n // The action under way, by the key of its button: `true` is the form's own\n // submit. Every button waits while one runs; only its own says it loads.\n const [acting, setActing] = useState<string | null>(null)\n const busy = acting !== null || opts.waiting === true\n const setBusy = useCallback((on: boolean | string) => setActing(on === false ? null : on === true ? SUBMIT : on), [])\n const loading = (key: string = SUBMIT) => acting === key\n // Whether the form is still shown: a wait that ends after it left has nothing to free.\n const shown = useRef(true)\n useEffect(() => {\n shown.current = true\n // Back to a page the browser kept (back-forward cache): the form it left\n // waiting is free again.\n const back = (e: PageTransitionEvent) => { if (e.persisted) setActing(null) }\n window.addEventListener('pageshow', back)\n return () => {\n shown.current = false\n window.removeEventListener('pageshow', back)\n }\n }, [])\n /**\n * After an action that leaves the form: it stays busy until the page is\n * left. When `after` is a Promise (the application's own way on), until it\n * settles, and then it is free again if it is still shown.\n */\n const hold = (after: unknown) => {\n if (!isPending(after)) return\n const free = () => { if (shown.current) setActing(null) }\n after.then(free, free)\n }\n /** What went wrong: the form is free again, and says it. */\n const fail = (e: AuthError) => {\n setActing(null)\n setError(e)\n }\n // The workspace's password rule, once methods() said it: what a refused\n // new password is told, rule by rule.\n const [policy, setPolicy] = useState<PasswordPolicy | undefined>(undefined)\n const locale = props.locale ?? 'en'\n const say = (e: AuthError) => {\n if (props.texts?.errors?.[e.code] === undefined && isPasswordRule(e)) return explainPasswordProblems(e.reasons ?? [e.code], policy, locale)\n return t.errors[e.code] ?? e.message\n }\n /** What a new password must be, for under its field. */\n const passwordRule = describePasswordPolicy(policy, locale)\n // `to`: where a sign-in link or code says to go, over `returnTo`. Signed\n // in: the form stays busy, its pressed button loading (the submit when none\n // was, as after a passkey from the autofill), until the page is left or the\n // application's `onSuccess` settles.\n const done = (to?: string) => {\n setActing((a) => a ?? SUBMIT)\n if (props.onSuccess) hold(props.onSuccess())\n else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? '/')\n }\n const root = useRoot(opts.part ? { ...props, unstyled: true } : props)\n const plain = props.unstyled === true\n return { t, cx, own, C, Button, Input, error, setError, fail, check, fieldError, firstWrong, busy, setBusy, loading, hold, say, done, root, plain, policy, setPolicy, passwordRule }\n}\n\n/** The key of the form's own submit, for `setBusy` and `loading`. */\nconst SUBMIT = 'submit'\n\ntype Form = ReturnType<typeof useForm>\n\n/**\n * An element around the form's parts: the application's `Form` when it gave\n * one, otherwise the very element the forms have always drawn. `root` is the\n * outermost one's mark and look; with the application's own `Form` and a\n * look to wear, they go on a plain `div` around it, for `styles.css` to find.\n */\nfunction Wrap(p: {\n f: Form; as: 'form' | 'div' | 'section'; slot?: Slot; root?: ReturnType<typeof useRoot>; section?: string\n onSubmit?: (e: FormEvent) => void; noValidate?: boolean; busy?: boolean; children?: ReactNode\n}) {\n const { Form: OwnForm } = p.f.C\n // Busy while an action runs, or as the caller says (a step still opening).\n const busy = p.busy ?? (p.f.busy || undefined)\n if (OwnForm) {\n const own = (\n <OwnForm as={p.as === 'form' ? 'form' : 'div'} onSubmit={p.onSubmit} noValidate={p.noValidate} aria-busy={busy}\n className={p.slot ? p.f.own(p.slot) : undefined} section={p.section}>{p.children}</OwnForm>\n )\n return p.root?.['data-cauthy'] !== undefined ? <div {...p.root}>{own}</div> : own\n }\n const Tag = p.as\n // A form still opening, with nothing to show yet, says it is on its way.\n const children = p.busy && p.children === undefined ? <Pending f={p.f} /> : p.children\n return <Tag className={p.slot ? p.f.cx(p.slot) : undefined} {...p.root} onSubmit={p.onSubmit} noValidate={p.noValidate} aria-busy={busy}>{children}</Tag>\n}\n\n/**\n * Where a form waits before it can show anything: the spinner alone, no words,\n * centred by styles.css. The form around it says `aria-busy`. The\n * application's own `Form` is told `aria-busy` and draws its own.\n */\nfunction Pending({ f }: { f: Form }) {\n return <div className={f.cx('pending')}><Spinner plain={f.plain} /></div>\n}\n\n// The parts every form draws with: the application's own when it gave one,\n// otherwise the element the forms have always drawn, so nothing changes for\n// an application that gives none.\n\n/** A sentence the form says: help, a state. */\nfunction Note({ f, children, footer }: { f: Form; children: ReactNode; footer?: boolean }) {\n const { Text } = f.C\n if (Text) return <Text as=\"p\" tone=\"muted\" size={footer ? 'sm' : 'md'}>{children}</Text>\n return <p className={f.cx(footer ? 'footer' : 'notice')}>{children}</p>\n}\n\n/** A part's heading. */\nfunction Heading({ f, children }: { f: Form; children: ReactNode }) {\n const { Text } = f.C\n if (Text) return <Text as=\"h2\" size=\"lg\">{children}</Text>\n return <h2 className={f.cx('heading')}>{children}</h2>\n}\n\n/** What went wrong, or what was done: announced. */\nfunction Say({ f, tone, children }: { f: Form; tone: AuthAlertProps['tone']; children: ReactNode }) {\n const { Alert } = f.C\n if (Alert) return <Alert tone={tone}>{children}</Alert>\n if (tone === 'danger') return <p role=\"alert\" className={f.cx('error')}>{children}</p>\n return <p role=\"status\" className={f.cx('notice')}>{children}</p>\n}\n\n/** \"or with your email\", between the providers and the address. */\nfunction Or({ f, children }: { f: Form; children: ReactNode }) {\n const { Divider } = f.C\n if (Divider) return <Divider label={children} />\n return <p className={f.cx('separator')}>{children}</p>\n}\n\nfunction A({ f, href, newTab, children }: { f: Form; href?: string; newTab?: boolean; children: ReactNode }) {\n const { Link } = f.C\n if (Link) return <Link href={href} newTab={newTab}>{children}</Link>\n return <a className={f.cx('link')} href={href} target={newTab ? '_blank' : undefined} rel={newTab ? 'noopener' : undefined}>{children}</a>\n}\n\n/** A mark beside a name; without the application's badge, the words as they always read. */\nfunction Tag({ f, tone, children, plain }: { f: Form; tone?: AuthBadgeProps['tone']; children: ReactNode; plain: ReactNode }) {\n const { Badge } = f.C\n if (Badge) return <>{' '}<Badge tone={tone}>{children}</Badge></>\n return <>{plain}</>\n}\n\nfunction Check(p: { f: Form; name: string; checked: boolean; required?: boolean; onChange: (checked: boolean) => void; children: ReactNode }) {\n const id = useId()\n const { f } = p\n const { Checkbox } = f.C\n if (Checkbox) {\n return <Checkbox id={id} name={p.name} checked={p.checked} required={p.required} disabled={f.busy} className={f.own('check')} onChange={p.onChange}>{p.children}</Checkbox>\n }\n return (\n <label className={f.cx('check')}>\n <input type=\"checkbox\" name={p.name} checked={p.checked} required={p.required} disabled={f.busy} onChange={(e) => p.onChange(e.target.checked)} />\n <span>{p.children}</span>\n </label>\n )\n}\n\nfunction Pick(p: { f: Form; id?: string; name: string; value: string; options: { value: string; label: string }[]; disabled?: boolean; label?: string; onChange: (value: string) => void }) {\n const made = useId()\n const id = p.id ?? made\n const { f } = p\n const { Select } = f.C\n // Every control waits while an action runs.\n const disabled = p.disabled || f.busy\n if (Select) {\n return <Select id={id} name={p.name} value={p.value} options={p.options} disabled={disabled} aria-label={p.label} className={f.own('input')} onChange={p.onChange} />\n }\n return (\n <select id={id} name={p.name} aria-label={p.label} className={f.cx('input')} value={p.value} disabled={disabled} onChange={(e) => p.onChange(e.target.value)}>\n {p.options.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}\n </select>\n )\n}\n\n/** A label around a control that is not a text input: a role to give. */\nfunction Labelled({ f, id, label, children }: { f: Form; id: string; label: string; children: ReactNode }) {\n const { Field: OwnField } = f.C\n if (OwnField) return <OwnField id={id} label={label} className={f.own('field')}>{children}</OwnField>\n return (\n <label className={f.cx('field')}>\n <span className={f.cx('label')}>{label}</span>\n {children}\n </label>\n )\n}\n\n/** \"the Terms of Service and the Privacy Policy\", each linked, opening apart. */\nfunction Documents({ f, documents }: { f: Form; documents: { kind: string; url: string }[] }) {\n return (\n <>\n {documents.map((d, i) => (\n <span key={d.kind}>\n {i > 0 && <>{f.t.and} </>}\n <A f={f} href={d.url} newTab>{d.kind === 'terms' ? f.t.termsOfService : f.t.privacyPolicy}</A>{' '}\n </span>\n ))}\n </>\n )\n}\n\nconst PASSWORD_RULES = ['needs_lowercase', 'needs_uppercase', 'needs_digit', 'needs_symbol', 'needs_classes', 'breached']\n\n/** A new password refused by a rule of the workspace's policy, here or by Cauthy. */\nfunction isPasswordRule(e: AuthError): boolean {\n if (e.code === 'weak_password' || PASSWORD_RULES.includes(e.code)) return true\n return (e.code === 'too_short' || e.code === 'too_long') && (e.field === 'password' || e.field === 'newPassword')\n}\n\n/**\n * A new password the workspace's rule refuses, as the form says it: every\n * rule it fails, under the field it was typed in.\n */\nfunction newPasswordProblem(value: string, policy: PasswordPolicy | undefined, field: 'password' | 'newPassword' = 'password'): AuthError | null {\n const bad = checkNewPassword(value, policy)\n if (!bad) return null\n return { code: bad.code, message: bad.message, field, ...(bad.code === 'required' ? {} : { reasons: passwordProblems(value, policy) }) }\n}\n\n/** The workspace's password rule, into a form, once methods() has said it. */\nfunction usePasswordPolicy(f: ReturnType<typeof useForm>, methods: AuthMethods | null) {\n const { setPolicy } = f\n useEffect(() => {\n if (methods?.password) setPolicy(methods.password)\n }, [methods, setPolicy])\n}\n\nfunction Field(p: {\n f: ReturnType<typeof useForm>; name: 'email' | 'password' | 'newPassword' | 'name' | 'code' | 'phone' | 'organization'; type: string; label: string; value: string\n autoComplete: string; required?: boolean; onChange: (v: string) => void; aside?: ReactNode\n /** A line under the field saying what it takes (a new password's rule). */\n hint?: string\n}) {\n const id = useId()\n const { f } = p\n const bad = f.fieldError(p.name)\n // The first field found wrong takes the focus, on every try.\n const focus = f.firstWrong(p.name)\n useEffect(() => {\n if (focus > 0 && typeof document !== 'undefined') document.getElementById(id)?.focus()\n }, [focus, id])\n const described = [bad ? `${id}-error` : '', p.hint ? `${id}-hint` : ''].filter(Boolean).join(' ')\n const input = (\n <f.Input id={id} name={p.name} type={p.type} value={p.value} autoComplete={p.autoComplete} required={p.required} disabled={f.busy} className={f.cx('input')}\n aria-invalid={bad ? true : undefined} aria-describedby={described || undefined} onChange={(e) => p.onChange(e.target.value)} />\n )\n const { Field: OwnField } = f.C\n if (OwnField) {\n return (\n <OwnField id={id} label={p.label} aside={p.aside} help={p.hint && !bad ? p.hint : undefined} error={bad ? f.say(bad) : undefined}\n required={p.required} className={f.own('field')}>{input}</OwnField>\n )\n }\n return (\n <div className={f.cx('field')}>\n <label className={f.cx('label')} htmlFor={id}>{p.label}{p.aside}</label>\n {input}\n {p.hint && !bad && <span id={`${id}-hint`} className={f.cx('hint')}>{p.hint}</span>}\n {bad && <span id={`${id}-error`} role=\"alert\" className={f.cx('fieldError')}>{f.say(bad)}</span>}\n </div>\n )\n}\n\n/** The error a provider's trip came back with, read once from the address. */\nfunction returnedError(): AuthError | null {\n if (typeof window === 'undefined') return null\n const code = new URLSearchParams(window.location.search).get('auth_error')\n return code ? { code, message: 'That sign-in could not be completed. Try again.' } : null\n}\n\n/**\n * The token a mailed link opened this page with, taken out of the address so\n * it is not left in the history or sent on as a referrer.\n */\nfunction takeToken(name: string): string | null {\n if (typeof window === 'undefined') return null\n const url = new URL(window.location.href)\n const token = url.searchParams.get(name)\n if (token === null) return null\n url.searchParams.delete(name)\n window.history.replaceState(window.history.state, '', url.pathname + url.search + url.hash)\n return token\n}\n\n/**\n * Runs `open` once with the token this page was opened with, or with null.\n * Once per page, even where React runs an effect twice while developing: the\n * token is taken out of the address the first time and a link works once.\n */\nfunction useMailedToken(name: string, open: (token: string | null) => void): void {\n const opened = useRef(false)\n useEffect(() => {\n if (opened.current) return\n opened.current = true\n open(takeToken(name))\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n}\n\n/**\n * The second step of a sign-in, once Cauthy asked for it: the code of the\n * authenticator app, a code sent to the phone or the email, or a push\n * approved on the phone. `<SignIn />` and `<AcceptInvite />` both end here.\n */\nfunction SecondStepForm(p: { f: ReturnType<typeof useForm>; auth: ReturnType<typeof useAuth> }) {\n const { f, auth } = p\n const [code, setCode] = useState('')\n // The ways the account takes the step, and where a code went.\n const [phoneWay, setPhoneWay] = useState<{ totp: boolean; phone: { number: string; channel: string } | null; push: { devices: number } | null; email: { to: string } | null } | null>(null)\n const [phoneSent, setPhoneSent] = useState('')\n useEffect(() => {\n void auth.signIn.mfaMethods().then((r) => { if (r.ok) setPhoneWay({ totp: r.totp, phone: r.phone, push: r.push, email: r.email }) })\n // Once: asked when the step opens.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n // The second step by email: the code went with the first step; another can be asked for.\n const sendEmail = async () => {\n f.setBusy('email')\n f.setError(null)\n const r = await auth.signIn.mfaSendEmail()\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setPhoneSent(r.sentTo)\n }\n // The second step approved on the phone: the number to pick, while the page listens.\n const [pushNumber, setPushNumber] = useState(0)\n const pushWait = useRef<AbortController | null>(null)\n useEffect(() => () => pushWait.current?.abort(), [])\n const sendPush = async () => {\n f.setBusy('push')\n f.setError(null)\n const r = await auth.signIn.mfaPush()\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setPushNumber(r.number)\n pushWait.current?.abort()\n const ctl = new AbortController()\n pushWait.current = ctl\n const done = await auth.signIn.mfaPushWait({ signal: ctl.signal })\n if (ctl.signal.aborted) return\n setPushNumber(0)\n if (!done.ok) return f.setError(done.error)\n // Approved: its button says the sign-in goes on, until the page is left.\n f.setBusy('push')\n f.done()\n }\n const sendCode = async () => {\n f.setBusy('phone')\n f.setError(null)\n const r = await auth.signIn.mfaSendCode()\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setPhoneSent(r.sentTo)\n }\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.signIn.mfa({ code })\n // Signed in: the form stays busy until it leaves (see `done`).\n if (!r.ok) return f.fail(r.error)\n f.done()\n }\n const general = f.error && !f.error.field ? f.error : null\n const to = phoneWay?.phone?.number ?? ''\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n <Note f={f}>{phoneSent ? f.t.codeSent.replace('{to}', phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace('{to}', phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {phoneWay?.email && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('email')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void sendEmail()}>{f.t.sendEmailAgain}</f.Button>\n )}\n {pushNumber > 0 ? (f.C.Text ? (\n // The application's text: the number to pick drawn large, by its own rules.\n <div role=\"status\" aria-live=\"polite\">\n <f.C.Text as=\"p\">{f.t.pushPick.replace('{n}', String(pushNumber))}</f.C.Text>\n <f.C.Text as=\"p\" size=\"lg\">{pushNumber}</f.C.Text>\n <f.C.Text as=\"p\" tone=\"muted\">{f.t.pushWaiting}</f.C.Text>\n </div>\n ) : (\n <div className={f.cx('notice')} role=\"status\" aria-live=\"polite\">\n <p>{f.t.pushPick.replace('{n}', String(pushNumber))}</p>\n <p style={{ fontSize: 48, fontWeight: 700, margin: '4px 0', textAlign: 'center' }}>{pushNumber}</p>\n <p>{f.t.pushWaiting}</p>\n </div>\n )) : phoneWay?.push && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('push')} disabled={f.busy} className={f.cx('button')} onClick={() => void sendPush()}>{f.t.pushSend}</f.Button>\n )}\n {phoneWay?.phone && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('phone')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void sendCode()}>\n {(phoneWay.phone.channel === 'whatsapp' ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace('{to}', to)}\n </f.Button>\n )}\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n}\n\n/**\n * \"Continue with …\", one button per provider the workspace turned on, each\n * with the provider's logo when Cauthy serves one. The logo says nothing a\n * screen reader needs: the button's words name the provider.\n */\nexport function ProviderButtons(p: { f: ReturnType<typeof useForm>; providers: AuthMethods['providers']; onPick: (id: string) => void }) {\n const { f } = p\n // On the way to the provider: the button pressed loads, and the form waits\n // until the page is left.\n const pick = (id: string) => {\n f.setBusy(`provider:${id}`)\n p.onPick(id)\n }\n return (\n <>\n {p.providers.map((provider) => (\n <f.Button key={provider.id} type=\"button\" variant=\"secondary\" loading={f.loading(`provider:${provider.id}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => pick(provider.id)}>\n {provider.iconUrl && <img src={provider.iconUrl} alt=\"\" width={18} height={18} className={f.cx('providerIcon')} />}\n {f.t.continueWith} {provider.name}\n </f.Button>\n ))}\n </>\n )\n}\n\n/**\n * What `<SignIn />` offers, from what the workspace turned on: the password\n * (and with it \"forgot your password\"), the address (asked for the password,\n * a sign-in link, or finding the person's company) and the passkey button.\n * Until `methods()` answers, the usual form: a password and an address.\n */\nexport function signInOffers(methods: AuthMethods | null): { password: boolean; email: boolean; passkey: boolean } {\n const password = methods?.passwordSignIn !== false\n return { password, email: password || methods?.magicLink === true || methods?.sso === true, passkey: methods?.passkey === true }\n}\n\nexport function SignIn(props: AuthFormProps) {\n const auth = useAuth()\n const [methods, setMethods] = useState<AuthMethods | null>(null)\n // Until the workspace says what it offers, the form shows but waits: nothing\n // to press or type that the answer could still change.\n const f = useForm(props, { waiting: methods === null })\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [code, setCode] = useState('')\n const [step, setStep] = useState<'password' | 'code' | 'opening' | 'sent'>('password')\n const challenge = useChallenge(methods?.captchaSiteKey, props.locale)\n const offers = signInOffers(methods)\n // A workspace that turned the password off: no password field, no \"forgot\n // your password\". Until methods() answers, the form is the usual one.\n const passwordOn = offers.password\n // The passkeys offered in the email field's autofill, while the form waits.\n const autofill = useRef<AbortController | null>(null)\n const [offer, setOffer] = useState(0)\n // The person's company, when the address typed is one of its domains.\n const [company, setCompany] = useState<SSOConnection | null>(null)\n useEffect(() => {\n if (!methods?.sso || checkEmail(email) !== null) return setCompany(null)\n let current = true\n const t = setTimeout(() => {\n void auth.signIn.ssoDiscover({ email }).then((r) => { if (current) setCompany(r.ok && r.status === 'found' ? r.connection : null) })\n }, 350)\n return () => { current = false; clearTimeout(t) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [email, methods])\n const toCompany = () => {\n autofill.current?.abort()\n f.setBusy('sso')\n auth.signIn.sso({ email }, { returnTo: props.returnTo })\n }\n\n useEffect(() => {\n void auth.methods().then(setMethods)\n const back = returnedError()\n if (back) f.setError(back)\n // Once: what the workspace offers does not change while the form is open.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // Opened from a sign-in link: the token signs the person in.\n useMailedToken('ml_token', (token) => {\n if (!token) return\n setStep('opening')\n void auth.signIn.magicLinkVerify({ token }).then((r) => {\n // The link carries where the person was going, as `return_to`.\n if (r.ok) return f.done(new URLSearchParams(window.location.search).get('return_to') ?? undefined)\n f.setError(r.error)\n setStep('password')\n })\n })\n\n useEffect(() => {\n if (step !== 'password' || !methods?.passkeyHere) return\n const ctl = new AbortController()\n autofill.current = ctl\n void auth.signIn.passkeyAutofill({ signal: ctl.signal }).then((r) => {\n if (ctl.signal.aborted) return\n if (r.ok) return f.done()\n if (r.error.code === 'cancelled') return // nothing to offer here\n f.setError(r.error)\n // A passkey that failed: offer them again, for another try.\n if (r.error.code === 'passkey_failed' || r.error.code === 'step_expired') setOffer((n) => n + 1)\n })\n return () => ctl.abort()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [step, methods, offer])\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n autofill.current?.abort()\n // An address its company holds to SSO has nothing else to send.\n if (step === 'password' && company?.enforced) {\n f.setError(null)\n return toCompany()\n }\n // No password to send: the address asks for a link, when the workspace mails them.\n if (step === 'password' && !passwordOn) {\n if (company) return toCompany()\n if (methods?.magicLink) return sendLink()\n return\n }\n // Every field the step shows, checked at once.\n if (step === 'password' && !f.check(checkEmail(email), checkPassword(password))) return\n f.setBusy(true)\n f.setError(null)\n const r = step === 'sent' ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token })\n if (step === 'password') challenge.renew()\n if (!r.ok && r.error.code === 'sso_required') return toCompany()\n if (!r.ok) {\n setOffer((n) => n + 1)\n return f.fail(r.error)\n }\n if (r.status === 'mfa_required') {\n f.setBusy(false)\n return setStep('code')\n }\n f.done('returnTo' in r && typeof r.returnTo === 'string' ? r.returnTo : undefined)\n }\n const usePasskey = async () => {\n // The browser asks for one passkey at a time.\n autofill.current?.abort()\n f.setBusy('passkey')\n f.setError(null)\n const r = await auth.signIn.passkey({ returnTo: props.returnTo, locale: props.locale, email })\n // On its way to Cauthy's page, or signed in: the form waits until it leaves.\n if (r.ok && r.status === 'redirected') return\n if (r.ok) return f.done()\n f.setBusy(false)\n setOffer((n) => n + 1)\n // The person closed the browser's prompt: nothing to say.\n if (r.error.code !== 'cancelled') f.setError(r.error)\n }\n const sendLink = async () => {\n autofill.current?.abort()\n f.setBusy('link')\n f.setError(null)\n const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo })\n f.setBusy(false)\n challenge.renew()\n if (!r.ok && r.error.code === 'sso_required') return toCompany()\n if (!r.ok) return f.setError(r.error)\n setStep('sent')\n }\n const general = f.error && !f.error.field ? f.error : null\n const asksEmail = offers.email\n\n if (step === 'opening') return <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy />\n if (step === 'sent') {\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n <Note f={f}>{f.t.signInLinkSent}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Note f={f}>{f.t.codeFromMail}</Note>\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n }\n if (step === 'code') return <SecondStepForm f={f} auth={auth} />\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ProviderButtons f={f} providers={methods?.providers ?? []} onPick={(id) => auth.signIn.social(id, { returnTo: props.returnTo })} />\n {offers.passkey && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('passkey')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void usePasskey()}>{f.t.usePasskey}</f.Button>\n )}\n {asksEmail && ((methods?.providers.length ?? 0) > 0 || offers.passkey) && <Or f={f}>{f.t.orWithEmail}</Or>}\n {asksEmail && (\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete={methods?.passkeyHere ? 'username webauthn' : 'username'} required onChange={setEmail} />\n )}\n {company && (\n <f.Button type=\"button\" variant={company.enforced ? 'primary' : 'secondary'} loading={f.loading('sso')} disabled={f.busy} className={f.cx(company.enforced ? 'button' : 'providerButton')} onClick={toCompany}>\n {f.t.continueWith} {company.name}\n </f.Button>\n )}\n {company?.enforced && <Note f={f}>{f.t.ssoOnly}</Note>}\n {!company?.enforced && passwordOn && (\n <>\n <Field f={f} name=\"password\" type=\"password\" label={f.t.password} value={password} autoComplete=\"current-password\" required onChange={setPassword}\n aside={props.links?.forgotPassword ? <A f={f} href={props.links.forgotPassword}>{f.t.forgotPassword}</A> : undefined} />\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.signIn}</f.Button>\n </>\n )}\n {/* Without the password, the challenge goes with the sign-in link. */}\n {!company?.enforced && !passwordOn && methods?.magicLink && challenge.node}\n {methods?.magicLink && !company?.enforced && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('link')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void sendLink()}>{f.t.emailMeALink}</f.Button>\n )}\n {methods?.signUp !== false && props.links?.signUp && (\n <Note f={f} footer>{f.t.noAccount} <A f={f} href={props.links.signUp}>{f.t.createAccount}</A></Note>\n )}\n </Wrap>\n )\n}\n\nexport interface GoogleOneTapProps {\n /** Where to go once signed in. Without it (and without `onSuccess`), the page stays and its session updates. */\n returnTo?: string\n /** Called once signed in, instead of going to `returnTo`. */\n onSuccess?: () => void\n /** The prompt's words: sign in (default), sign up, or use the application. */\n context?: 'signin' | 'signup' | 'use'\n}\n\n/**\n * Google One Tap: put it on any page, and a person who is not signed in sees\n * Google's prompt with the Google account the browser has; one tap signs them\n * in. It draws nothing of its own, and shows nothing to somebody signed in or\n * where the workspace has no Google sign-in.\n */\nexport function GoogleOneTap(props: GoogleOneTapProps) {\n const auth = useAuth()\n const unauthenticated = auth.status === 'unauthenticated'\n useEffect(() => {\n if (!unauthenticated) return\n const ctl = new AbortController()\n void auth.signIn.googleOneTap({ signal: ctl.signal, context: props.context }).then((r) => {\n if (!r.ok || ctl.signal.aborted) return\n if (props.onSuccess) props.onSuccess()\n else {\n const to = sameOrigin(props.returnTo)\n if (to) window.location.assign(to)\n }\n })\n return () => ctl.abort()\n // Once per signed-out visit: the prompt is not shown again on every render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [unauthenticated])\n return null\n}\n\nexport function SignUp(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [name, setName] = useState('')\n const [organization, setOrganization] = useState('')\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [sent, setSent] = useState(false)\n const methods = useMethods(auth)\n usePasswordPolicy(f, methods)\n const challenge = useChallenge(methods?.captchaSiteKey, props.locale)\n // The law's boxes: the documents accepted, and each consent asked.\n const [acceptLegal, setAcceptLegal] = useState(false)\n const [consents, setConsents] = useState<Record<string, boolean>>({})\n const legal = methods?.legal\n\n const guest = auth.session?.user.isAnonymous === true\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n // Every field at once, in the order they are drawn.\n const asksCompany = methods?.organization?.ask === true\n if (!f.check(\n asksCompany && checkOrganization(organization, methods?.organization?.required === true),\n checkName(name), checkEmail(email), newPasswordProblem(password, f.policy),\n )) return\n f.setBusy(true)\n f.setError(null)\n // A guest signing up becomes the account they were using: same id.\n const r = guest\n ? await auth.account.upgrade({ name, email, password })\n : await auth.signUp.email({ name, email, password, ...(methods?.organization?.ask ? { organization } : {}),\n ...(legal ? { acceptLegal, consents } : {}), captchaToken: challenge.token })\n challenge.renew()\n if (!r.ok) return f.fail(r.error)\n if (r.status === 'verification_required') {\n f.setBusy(false)\n return setSent(true)\n }\n f.done()\n }\n const general = f.error && !f.error.field ? f.error : null\n // A workspace that turned the password off makes accounts through its\n // providers only. Not offered to a guest becoming an account (the provider\n // would sign them in as another), nor where the sign-up must name its\n // company: a provider has no field for it.\n const passwordOn = methods?.passwordSignIn !== false\n const providers = guest || methods?.organization?.required ? [] : (methods?.providers ?? [])\n\n if (sent) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Note f={f}>{f.t.checkEmail}</Note>\n {props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>}\n </Wrap>\n )\n }\n // Until the workspace says what it asks (a company's name, the password,\n // the legal boxes), the form waits: its fields would move as they came.\n if (methods === null) return <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy />\n const footer = props.links?.signIn && <Note f={f} footer>{f.t.haveAccount} <A f={f} href={props.links.signIn}>{f.t.signIn}</A></Note>\n if (!passwordOn) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ProviderButtons f={f} providers={providers} onPick={(id) => auth.signIn.social(id, { returnTo: props.returnTo })} />\n {footer}\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ProviderButtons f={f} providers={providers} onPick={(id) => auth.signIn.social(id, { returnTo: props.returnTo })} />\n {providers.length > 0 && <Or f={f}>{f.t.orWithEmail}</Or>}\n {methods.organization?.ask && (\n <Field f={f} name=\"organization\" type=\"text\" label={f.t.company} value={organization} autoComplete=\"organization\" required={methods.organization.required} onChange={setOrganization} />\n )}\n <Field f={f} name=\"name\" type=\"text\" label={f.t.name} value={name} autoComplete=\"name\" onChange={setName} />\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"username\" required onChange={setEmail} />\n <Field f={f} name=\"password\" type=\"password\" label={f.t.password} value={password} autoComplete=\"new-password\" required onChange={setPassword} hint={f.passwordRule} />\n {legal && legal.documents.length > 0 && (\n <Check f={f} name=\"acceptLegal\" checked={acceptLegal} required onChange={setAcceptLegal}>\n {f.t.iAccept}{' '}\n <Documents f={f} documents={legal.documents} />\n </Check>\n )}\n {legal?.consentPurposes.map((p) => (\n <Check key={p.key} f={f} name={`consent_${p.key}`} checked={consents[p.key] === true} required={p.required} onChange={(on) => setConsents({ ...consents, [p.key]: on })}>\n {p.label}\n </Check>\n ))}\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.signUp}</f.Button>\n {footer}\n </Wrap>\n )\n}\n\nexport function ForgotPassword(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [email, setEmail] = useState('')\n const [sent, setSent] = useState(false)\n const challenge = useChallenge(useMethods(auth)?.captchaSiteKey, props.locale)\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.forgotPassword({ email, captchaToken: challenge.token })\n f.setBusy(false)\n challenge.renew()\n if (!r.ok) return f.setError(r.error)\n setSent(true)\n }\n const general = f.error && !f.error.field ? f.error : null\n\n if (sent) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Note f={f}>{f.t.linkSent}</Note>\n {props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>}\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"username\" required onChange={setEmail} />\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.sendLink}</f.Button>\n {props.links?.signIn && <Note f={f} footer><A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A></Note>}\n </Wrap>\n )\n}\n\n/** The page a \"choose a new password\" link opens: `pages.resetPassword`. */\nexport function ResetPassword(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [token, setToken] = useState<string | null>(null)\n const [password, setPassword] = useState('')\n const [changed, setChanged] = useState(false)\n usePasswordPolicy(f, useMethods(auth))\n\n useMailedToken('token', (t) => {\n setToken(t ?? '')\n if (!t) f.setError({ code: 'invalid_token', message: 'This link is not valid, or it has expired.' })\n })\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.resetPassword({ token: token ?? '', password })\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setChanged(true)\n }\n const general = f.error && !f.error.field ? f.error : null\n const back = props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>\n\n if (changed) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Note f={f}>{f.t.passwordChanged}</Note>\n {back}\n </Wrap>\n )\n }\n if (token === '') {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {props.links?.forgotPassword && <A f={f} href={props.links.forgotPassword}>{f.t.forgotPassword}</A>}\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"password\" type=\"password\" label={f.t.newPassword} value={password} autoComplete=\"new-password\" required onChange={setPassword} hint={f.passwordRule} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy || token === null} className={f.cx('button')}>{f.t.savePassword}</f.Button>\n </Wrap>\n )\n}\n\n/** The page a \"confirm your address\" link opens: `pages.verifyEmail`. It confirms as it opens. */\nexport function VerifyEmail(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [state, setState] = useState<'confirming' | 'confirmed' | 'failed'>('confirming')\n\n useMailedToken('token', (token) => {\n if (!token) {\n f.setError({ code: 'invalid_token', message: 'This link is not valid, or it has expired.' })\n return setState('failed')\n }\n void auth.verifyEmail({ token }).then((r) => {\n // Signed in from the link: on to the application, nothing more to type.\n if (r.ok && r.status === 'signed_in') return f.done()\n if (r.ok) return setState('confirmed')\n f.setError(r.error)\n setState('failed')\n })\n })\n\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy={state === 'confirming'}>\n {state === 'confirming' && <Note f={f}>{f.t.confirming}</Note>}\n {state === 'confirmed' && <Note f={f}>{f.t.emailConfirmed}</Note>}\n {state === 'failed' && f.error && <Say f={f} tone=\"danger\">{f.say(f.error)}</Say>}\n {state !== 'confirming' && props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>}\n </Wrap>\n )\n}\n\n/**\n * The page an invitation opens: `pages.acceptInvite`. It says who is invited\n * to what, asks for a password under the workspace's policy, signs the person\n * in (with the second step, when their account owes one) and goes on to\n * `returnTo`. The invitation is good until it is accepted: reading it, or a\n * password refused, does not spend it.\n */\n/** What `<AcceptInvite />` tells the application once the invitation is accepted. */\nexport type AcceptInviteEvent = { kind: 'invitation.accepted'; email: string; organization?: string }\n\nexport interface AcceptInviteProps extends AuthFormProps {\n /** Called once the invitation is accepted, before the second step when the account owes one. */\n onSaved?: (event: AcceptInviteEvent) => void\n}\n\nexport function AcceptInvite(props: AcceptInviteProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [token, setToken] = useState('')\n const [invitation, setInvitation] = useState<Invitation | null>(null)\n const [state, setState] = useState<'opening' | 'ready' | 'invalid' | 'code'>('opening')\n const [password, setPassword] = useState('')\n usePasswordPolicy(f, useMethods(auth))\n\n useMailedToken('token', (t) => {\n if (!t) return setState('invalid')\n setToken(t)\n void auth.invitation(t).then((r) => {\n if (r.ok) {\n setInvitation(r.invitation)\n return setState('ready')\n }\n // A spent or unknown invitation says so; anything else, what it was.\n if (r.error.code !== 'invalid_token') f.setError(r.error)\n setState('invalid')\n })\n })\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.acceptInvitation(token, password)\n if (!r.ok) {\n f.setBusy(false)\n if (r.error.code === 'invalid_token') return setState('invalid')\n return f.setError(r.error)\n }\n props.onSaved?.({ kind: 'invitation.accepted', email: invitation?.email ?? '', ...(invitation?.organization ? { organization: invitation.organization } : {}) })\n if (r.status === 'mfa_required') {\n f.setBusy(false)\n return setState('code')\n }\n f.done()\n }\n const general = f.error && !f.error.field ? f.error : null\n const back = props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>\n\n if (state === 'opening') {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy>\n <Note f={f}>{f.t.openingInvitation}</Note>\n </Wrap>\n )\n }\n if (state === 'invalid') {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Say f={f} tone=\"danger\">{general ? f.say(general) : f.t.invitationInvalid}</Say>\n {back}\n </Wrap>\n )\n }\n if (state === 'code') return <SecondStepForm f={f} auth={auth} />\n const workspace = invitation?.workspace ?? ''\n const heading = invitation?.organization\n ? f.t.invitedToOrganization.replace('{organization}', invitation.organization).replace('{workspace}', workspace)\n : f.t.invitedTo.replace('{workspace}', workspace)\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n <Heading f={f}>{heading}</Heading>\n <Note f={f}>{f.t.invitedAs.replace('{email}', invitation?.email ?? '')}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {/* The address, for the browser's password manager to keep the new password under. */}\n <input type=\"email\" name=\"username\" autoComplete=\"username\" value={invitation?.email ?? ''} readOnly hidden />\n <Field f={f} name=\"password\" type=\"password\" label={f.t.choosePassword} value={password} autoComplete=\"new-password\" required onChange={setPassword} hint={f.passwordRule} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.acceptInvite}</f.Button>\n </Wrap>\n )\n}\n\nexport interface PendingTermsProps extends Omit<AuthFormProps, 'links' | 'returnTo' | 'createAccounts'> {\n /**\n * Called once the person accepted. Nothing else happens: the application\n * decides what follows. A Promise keeps the button loading until it settles.\n */\n onSuccess?: () => void | Promise<unknown>\n}\n\n/**\n * The legal documents the signed-in person still owes (a new version of the\n * terms, say), linked, with the action that accepts them. It shows nothing\n * while it reads them, when nothing is owed, and once they are accepted.\n * Nothing stops the person meanwhile: the application decides what waits.\n */\nexport function PendingTerms(props: PendingTermsProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [owed, setOwed] = useState<PendingLegal[] | null>(null)\n useEffect(() => {\n void auth.account.legal().then((r) => setOwed(r.ok ? r.pending : []))\n // Once: what is owed is read when the page opens.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (!owed || owed.length === 0) return null\n const accept = async () => {\n f.setBusy(true)\n f.setError(null)\n const r = await auth.account.acceptLegal({ kinds: owed.map((d) => d.kind) })\n if (!r.ok) return f.fail(r.error)\n // The application's own way on, when it waits for it: the button loads until then.\n const after = props.onSuccess?.()\n if (isPending(after)) await Promise.resolve(after).catch(() => undefined)\n f.setBusy(false)\n setOwed([])\n }\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Heading f={f}>{f.t.termsChanged}</Heading>\n <Note f={f}>{f.t.termsChangedHelp}{' '}<Documents f={f} documents={owed} /></Note>\n {f.error && <Say f={f} tone=\"danger\">{f.say(f.error)}</Say>}\n <f.Button type=\"button\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')} onClick={() => void accept()}>{f.t.acceptTerms}</f.Button>\n </Wrap>\n )\n}\n\n/** The parts of `<Account />`, by name: what `sections` lists. */\nexport type AccountSection = 'profile' | 'email' | 'password' | 'linked' | 'secondStep' | 'phone' | 'passkeys' | 'agents' | 'sessions'\n\nconst ACCOUNT_SECTIONS: AccountSection[] = ['profile', 'email', 'password', 'linked', 'secondStep', 'phone', 'passkeys', 'agents', 'sessions']\n\n/**\n * What `<Account />` tells the application after each change it saved, for\n * the application's own toast or its own data to follow.\n */\nexport type AccountEvent =\n | { kind: 'profile.saved'; name: string }\n | { kind: 'email.change_requested'; email: string }\n | { kind: 'password.changed' }\n | { kind: 'identity.linked'; provider: string }\n | { kind: 'identity.unlinked'; provider: string }\n | { kind: 'mfa.enabled' }\n | { kind: 'mfa.disabled' }\n | { kind: 'recovery_codes.regenerated' }\n | { kind: 'phone.added'; channel: 'sms' | 'whatsapp' }\n | { kind: 'phone.removed' }\n | { kind: 'passkey.added'; id: string }\n | { kind: 'passkey.removed'; id: string }\n | { kind: 'agent.disconnected'; id: string }\n | { kind: 'sessions.ended' }\n\nexport interface AccountProps extends Omit<AuthFormProps, 'links' | 'returnTo' | 'onSuccess'> {\n /** Called after \"sign out everywhere\". Default: go to `/`. A Promise keeps the button loading until it settles. */\n onSignedOut?: () => void | Promise<unknown>\n /** The moment of a session, as the application writes dates. Default: the browser's own way, in the reader's time zone. */\n formatDate?: (iso: string) => string\n /**\n * The parts shown, in this order. Default: all of them, as listed in\n * `AccountSection`. A part with nothing to show (the password of an account\n * without one, agents when none is connected) stays out either way.\n */\n sections?: AccountSection[]\n /** Called after every change saved, with what changed. */\n onSaved?: (event: AccountEvent) => void\n}\n\n/** One part of the account screen: its own form, its own error, its own \"saved\". */\nfunction useSection(props: AccountProps) {\n // The look is the account screen's, around every part: not read again here.\n const f = useForm(props, { part: true })\n const [done, setDone] = useState<string | null>(null)\n // `key`: the button the action belongs to, the one that says it loads.\n // `leaves`: done, the action leaves the page; the part stays busy (see `hold`).\n const run = async <T extends { ok: boolean }>(action: () => Promise<T>, key: string = SUBMIT, leaves = false): Promise<T> => {\n f.setBusy(key)\n f.setError(null)\n setDone(null)\n const r = await action()\n if (!r.ok) f.fail((r as unknown as { error: AuthError }).error)\n else if (!leaves) f.setBusy(false)\n return r\n }\n const general = f.error && !f.error.field ? f.error : null\n return { f, done, setDone, run, general }\n}\n\n/**\n * The signed-in person's account, in the application: their name, their\n * password, the second step, and where they are signed in. Each part saves on\n * its own. Like the other forms, it carries no styles.\n */\nexport function Account(props: AccountProps) {\n const auth = useAuth()\n const { accountUrl } = useSession()\n const f = useForm(props)\n const [account, setAccount] = useState<AccountDetails | null>(null)\n\n useEffect(() => {\n void auth.account.get().then(setAccount)\n // Once: the account is read when the screen opens, and after each change below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n if (account === null) return <Wrap f={f} as=\"div\" slot=\"account\" root={f.root} busy />\n const when = props.formatDate ?? ((iso: string) => new Date(iso).toLocaleString())\n const mfa = (mfaEnabled: boolean) => setAccount({ ...account, mfaEnabled })\n const part = (section: AccountSection): ReactNode => {\n switch (section) {\n case 'profile': return <ProfilePart props={props} account={account} onSaved={setAccount} />\n case 'email': return <EmailPart props={props} account={account} />\n case 'password': return account.hasPassword ? <PasswordPart props={props} /> : null\n case 'linked': return <LinkedPart props={props} />\n case 'secondStep': return <SecondStepPart props={props} account={account} onChanged={mfa} />\n case 'phone': return <PhonePart props={props} account={account} onChanged={mfa} />\n case 'passkeys': return <PasskeysPart props={props} account={account} accountUrl={accountUrl()} when={when} />\n case 'agents': return <AgentsPart props={props} when={when} />\n case 'sessions': return <SessionsPart props={props} when={when} />\n }\n }\n\n return (\n <Wrap f={f} as=\"div\" slot=\"account\" root={f.root}>\n {(props.sections ?? ACCOUNT_SECTIONS).map((section) => <Fragment key={section}>{part(section)}</Fragment>)}\n </Wrap>\n )\n}\n\n/** What each part of the account screen takes, shown on its own: `<Account />`'s props but `sections`. */\nexport type AccountPartProps = Omit<AccountProps, 'sections'>\n\n// Each part of the account screen on its own, for an application that puts\n// them on separate cards. Each reads the account it shows.\n\n/** The person's name. */\nexport function AccountProfile(props: AccountPartProps) { return <Account {...props} sections={['profile']} /> }\n/** Changing the address: a link goes to the new one. */\nexport function AccountEmail(props: AccountPartProps) { return <Account {...props} sections={['email']} /> }\n/** Changing the password, for an account that has one. */\nexport function AccountPassword(props: AccountPartProps) { return <Account {...props} sections={['password']} /> }\n/** The providers the account signs in with. */\nexport function AccountLinked(props: AccountPartProps) { return <Account {...props} sections={['linked']} /> }\n/** The second step with an authenticator app, and the recovery codes. */\nexport function AccountSecondStep(props: AccountPartProps) { return <Account {...props} sections={['secondStep']} /> }\n/** The phone codes go to, where the workspace sends them. */\nexport function AccountPhone(props: AccountPartProps) { return <Account {...props} sections={['phone']} /> }\n/** The account's passkeys. */\nexport function AccountPasskeys(props: AccountPartProps) { return <Account {...props} sections={['passkeys']} /> }\n/** The AI agents the person connected, when there is one. */\nexport function AccountAgents(props: AccountPartProps) { return <Account {...props} sections={['agents']} /> }\n/** Where the person is signed in, and \"sign out everywhere\". */\nexport function AccountSessions(props: AccountPartProps) { return <Account {...props} sections={['sessions']} /> }\n\n/** An action `<OrganizationMembers hide={...} />` never offers. */\nexport type OrganizationMembersAction = 'archive' | 'delete' | 'rename' | 'leave'\n\n/**\n * What `<OrganizationMembers />` tells the application after each change it\n * saved, for the application's own toast or its own data to follow.\n */\nexport type OrganizationMembersEvent =\n | { kind: 'member.added'; organizationId: string; userId: string; email: string; role: string }\n | { kind: 'member.role_changed'; organizationId: string; userId: string; role: string; previousRole: string }\n | { kind: 'member.removed'; organizationId: string; userId: string }\n | { kind: 'member.left'; organizationId: string; userId: string }\n | { kind: 'member.invited_again'; organizationId: string; userId: string }\n | { kind: 'organization.renamed'; organizationId: string; name: string }\n | { kind: 'organization.archived'; organizationId: string }\n | { kind: 'organization.deleted'; organizationId: string }\n\nexport interface OrganizationMembersProps extends Omit<AuthFormProps, 'links' | 'returnTo' | 'onSuccess' | 'createAccounts'> {\n /** The organization, by the id Cauthy gave it. */\n organizationId: string\n /** The moment of a membership, as the application writes dates. Default: the browser's own way. */\n formatDate?: (iso: string) => string\n /**\n * The roles offered when adding a member or changing one's role: those for\n * which it answers true. A member already holding another role keeps it,\n * and it shows. Default: every role the person may give.\n */\n roles?: (role: string, choice: OrganizationRoleChoice) => boolean\n /** Actions never offered, whatever the person's role allows. */\n hide?: OrganizationMembersAction[]\n /** A role's name wherever one shows: a member's, the role choices, adding one. Default: the name the catalog gives it. */\n roleLabel?: (choice: OrganizationRoleChoice) => string\n /** Called after every change saved, with what changed. */\n onSaved?: (event: OrganizationMembersEvent) => void\n}\n\n/** The role Cauthy keeps in every catalog: only its holders give it, or change and remove those who hold it. */\nconst OWNER = 'owner'\n\n/**\n * What the signed-in person may do to one member, by their own seat: the\n * buttons <OrganizationMembers /> shows. Cauthy refuses the rest anyway; this\n * only keeps from offering it.\n */\nexport function memberActions(seat: OrganizationSeat, m: OrganizationPerson): { changeRole: boolean; remove: boolean; inviteAgain: boolean } {\n // An owner is changed or removed by another owner alone.\n const reachable = m.role !== OWNER || seat.role === OWNER\n return {\n changeRole: seat.can.manageMembers && reachable,\n // Leaving is anybody's; removing somebody else is cauthy:members:remove.\n remove: m.you || (seat.can.removeMembers && reachable),\n inviteAgain: seat.can.manageMembers && m.invited,\n }\n}\n\n/**\n * The roles the person may give: the owner role only by an owner, and of\n * those, the ones the application's `only` lets through.\n */\nexport function rolesToGive(seat: OrganizationSeat, roles: OrganizationRoleChoice[], only?: (role: string, choice: OrganizationRoleChoice) => boolean): OrganizationRoleChoice[] {\n const mine = seat.role === OWNER ? roles : roles.filter((c) => c.role !== OWNER)\n return only ? mine.filter((c) => only(c.role, c)) : mine\n}\n\n/**\n * The people of one of the signed-in person's organizations, administered\n * from the application. What it offers follows the person's role in the\n * system's catalog: cauthy:members read lists the people; manage adds them by\n * address (one with no account is invited), changes their role and sends an\n * invitation again; remove removes them. Anybody may leave. Only an owner\n * gives the owner role or changes an owner. cauthy:organization update,\n * archive and delete rename the organization, archive it, delete it. Cauthy\n * checks each change with the person's own session; the application\n * authorizes nothing. Like the other forms, it carries no styles.\n */\nexport function OrganizationMembers(props: OrganizationMembersProps) {\n const auth = useAuth()\n // The mark styles.css draws is the screen's; each part below is unstyled inside it, as in <Account />.\n const { root } = useForm(props as AccountProps)\n const { f, done, setDone, run } = useSection(props as AccountProps)\n // A refusal about the address or the new name shows under its field; any\n // other — a role, the last owner, a power the person lacks — above the list.\n const problem = f.error && f.error.field !== 'email' && f.error.field !== 'name' ? f.error : null\n const [seat, setSeat] = useState<OrganizationSeat | null | undefined>(undefined)\n const [members, setMembers] = useState<OrganizationPerson[] | null>(null)\n const [roles, setRoles] = useState<OrganizationRoleChoice[]>([])\n const [email, setEmail] = useState('')\n const [role, setRole] = useState('')\n const [name, setName] = useState('')\n const [asking, setAsking] = useState<string | null>(null) // the member a removal waits on, or 'archive' / 'delete'\n // Said once the organization is archived or deleted: there is nothing left to show.\n const [gone, setGone] = useState<string | null>(null)\n const id = props.organizationId\n const when = props.formatDate ?? ((iso: string) => new Date(iso).toLocaleDateString())\n const hidden = (action: OrganizationMembersAction) => props.hide?.includes(action) === true\n const saved = (event: OrganizationMembersEvent) => props.onSaved?.(event)\n\n const load = async () => {\n const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)])\n const mine = list.find((o) => o.id === id) ?? null\n setSeat(mine)\n if (mine) setName(mine.name)\n setMembers(people)\n setRoles(choices ?? [])\n const offered = mine ? rolesToGive(mine, choices ?? [], props.roles) : []\n if (offered.length > 0 && !offered.some((c) => c.role === role)) setRole(offered[0].role)\n }\n useEffect(() => {\n void load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [id])\n\n if (gone !== null) return <Wrap f={f} as=\"div\" slot=\"account\" root={root}><Say f={f} tone=\"success\">{gone}</Say></Wrap>\n if (seat === undefined) return <Wrap f={f} as=\"div\" slot=\"account\" root={root} busy />\n if (seat === null) return <Wrap f={f} as=\"div\" slot=\"account\" root={root}><Note f={f}>{f.t.organizationMissing}</Note></Wrap>\n const manage = seat.can.manageMembers\n const giveable = rolesToGive(seat, roles, props.roles)\n const roleName = (c: OrganizationRoleChoice) => props.roleLabel?.(c) || c.name || c.role\n const label = (r: string) => {\n const c = roles.find((x) => x.role === r)\n return c ? roleName(c) : r\n }\n\n const add = async (e: FormEvent) => {\n e.preventDefault()\n if (!f.check(checkEmail(email))) return\n const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }), 'add')\n if (!r.ok) return\n setEmail('')\n setDone(f.t.memberAdded.replace('{email}', r.member.email))\n saved({ kind: 'member.added', organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role })\n await load()\n }\n const change = async (m: OrganizationPerson, next: string) => {\n const r = await run(() => auth.organizations.setRole(id, m.userId, next), `role:${m.userId}`)\n if (!r.ok) return\n saved({ kind: 'member.role_changed', organizationId: id, userId: m.userId, role: next, previousRole: m.role })\n await load()\n }\n const remove = async (m: OrganizationPerson) => {\n setAsking(null)\n const r = await run(() => auth.organizations.remove(id, m.userId), `remove:${m.userId}`)\n if (!r.ok) return\n saved({ kind: m.you ? 'member.left' : 'member.removed', organizationId: id, userId: m.userId })\n // Leaving: the organization is no longer the person's to see.\n if (m.you) setSeat(null)\n else await load()\n }\n const inviteAgain = async (m: OrganizationPerson) => {\n const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }), `invite:${m.userId}`)\n if (!r.ok) return\n setDone(f.t.memberInvitationSent)\n saved({ kind: 'member.invited_again', organizationId: id, userId: m.userId })\n }\n const rename = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.organizations.rename(id, name), 'rename')\n if (!r.ok) return\n setSeat(r.organization)\n setName(r.organization.name)\n setDone(f.t.organizationRenamed.replace('{name}', r.organization.name))\n saved({ kind: 'organization.renamed', organizationId: id, name: r.organization.name })\n }\n const close = async (how: 'archive' | 'delete') => {\n setAsking(null)\n const r = await run<{ ok: boolean }>(() => (how === 'archive' ? auth.organizations.archive(id) : auth.organizations.delete(id)), how)\n if (!r.ok) return\n setGone((how === 'archive' ? f.t.organizationArchived : f.t.organizationDeleted).replace('{org}', seat.name))\n saved({ kind: how === 'archive' ? 'organization.archived' : 'organization.deleted', organizationId: id })\n }\n // Before what cannot be undone: the application's own dialog when it gave\n // one, otherwise the question inline, where the button was.\n const ask = (key: string, title: string, question: string, yes: () => void) => {\n const { Confirm } = f.C\n if (!Confirm) return setAsking(key)\n void Confirm({ title, body: question, confirmLabel: title, cancelLabel: f.t.cancel, danger: true }).then((ok) => { if (ok) yes() })\n }\n const confirming = (text: string, label: string, yes: () => void) => (\n <span role=\"group\" aria-label={label}>\n <span>{text}</span>{' '}\n <f.Button type=\"button\" variant=\"danger\" disabled={f.busy} className={f.cx('providerButton')} onClick={yes}>{f.t.yes}</f.Button>\n <f.Button type=\"button\" variant=\"secondary\" disabled={f.busy} className={f.cx('providerButton')} onClick={() => setAsking(null)}>{f.t.cancel}</f.Button>\n </span>\n )\n const leaveQuestion = f.t.memberLeaveConfirm.replace('{org}', seat.name)\n const archiveQuestion = f.t.organizationArchiveConfirm.replace('{org}', seat.name)\n const deleteQuestion = f.t.organizationDeleteConfirm.replace('{org}', seat.name)\n const archiving = seat.can.archive && !hidden('archive')\n const deleting = seat.can.delete && !hidden('delete')\n const renaming = seat.can.update && !hidden('rename')\n\n return (\n <Wrap f={f} as=\"div\" slot=\"account\" root={root}>\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"members\">\n <Heading f={f}>{f.t.members} · {seat.name}</Heading>\n {problem && <Say f={f} tone=\"danger\">{f.say(problem)}</Say>}\n {members === null ? (\n <>\n <Note f={f}>{f.t.membersHidden}</Note>\n {/* Whoever cannot see the people may still leave. */}\n {auth.session && !hidden('leave') && (asking === auth.session.user.id\n ? confirming(leaveQuestion, f.t.memberLeave, () => void remove({ userId: auth.session!.user.id, you: true } as OrganizationPerson))\n : <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`remove:${auth.session.user.id}`)} disabled={f.busy} className={f.cx('providerButton')}\n onClick={() => ask(auth.session!.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session!.user.id, you: true } as OrganizationPerson))}>{f.t.memberLeave}</f.Button>)}\n </>\n ) : (\n <ul className={f.cx('sessions')}>\n {members.map((m) => {\n const who = m.name || m.email\n const may = memberActions(seat, m)\n const removable = may.remove && !(m.you && hidden('leave'))\n const question = m.you ? leaveQuestion : f.t.memberRemoveConfirm.replace('{who}', who)\n const action = m.you ? f.t.memberLeave : f.t.memberRemove\n // The member's own role stays listed, even one the person may not give.\n const choices = giveable.some((c) => c.role === m.role) ? giveable : [...roles.filter((c) => c.role === m.role), ...giveable]\n return (\n <li key={m.userId} className={f.cx('session')}>\n <span>\n {who}{m.name ? ` · ${m.email}` : ''}\n {m.you && <Tag f={f} plain={` (${f.t.memberYou})`}>{f.t.memberYou}</Tag>}\n {f.C.Badge ? (\n <>\n {m.invited && <Tag f={f} tone=\"warning\" plain=\"\">{f.t.memberInvited}</Tag>}\n {m.manager && <Tag f={f} tone=\"success\" plain=\"\">{f.t.memberManager}</Tag>}\n </>\n ) : `${m.invited ? ` · ${f.t.memberInvited}` : ''}${m.manager ? ` · ${f.t.memberManager}` : ''}`}\n {' · '}{when(m.since)}\n </span>{' '}\n {may.changeRole && giveable.length > 0 ? (\n <Pick f={f} name={`role_${m.userId}`} label={`${f.t.memberRole}: ${who}`} value={m.role} disabled={f.busy}\n options={choices.map((c) => ({ value: c.role, label: roleName(c) }))} onChange={(next) => void change(m, next)} />\n ) : f.C.Badge ? <f.C.Badge tone=\"neutral\">{label(m.role)}</f.C.Badge> : <span>{label(m.role)}</span>}{' '}\n {asking === m.userId ? (\n confirming(question, action, () => void remove(m))\n ) : (\n <>\n {may.inviteAgain && <f.Button type=\"button\" variant=\"secondary\" loading={f.loading(`invite:${m.userId}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void inviteAgain(m)}>{f.t.memberInviteAgain}</f.Button>}\n {removable && <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`remove:${m.userId}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => ask(m.userId, action, question, () => void remove(m))}>{action}</f.Button>}\n </>\n )}\n </li>\n )\n })}\n </ul>\n )}\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n {manage && giveable.length > 0 && (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"add-member\" onSubmit={add} noValidate>\n <Heading f={f}>{f.t.memberAdd}</Heading>\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"off\" required onChange={setEmail} />\n <AddRole f={f} value={role} options={giveable.map((c) => ({ value: c.role, label: roleName(c) }))} onChange={setRole} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading('add')} disabled={f.busy} className={f.cx('button')}>{f.t.memberAdd}</f.Button>\n </Wrap>\n )}\n {(renaming || archiving || deleting) && (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"organization\">\n <Heading f={f}>{f.t.organization}</Heading>\n {renaming && (\n <Wrap f={f} as=\"form\" section=\"rename\" onSubmit={rename} noValidate>\n <Field f={f} name=\"name\" type=\"text\" label={f.t.name} value={name} autoComplete=\"organization\" required onChange={setName} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading('rename')} disabled={f.busy} className={f.cx('button')}>{f.t.organizationRename}</f.Button>\n </Wrap>\n )}\n {asking === 'archive' ? confirming(archiveQuestion, f.t.organizationArchive, () => void close('archive'))\n : asking === 'delete' ? confirming(deleteQuestion, f.t.organizationDelete, () => void close('delete'))\n : (\n <>\n {archiving && <f.Button type=\"button\" variant=\"danger\" loading={f.loading('archive')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => ask('archive', f.t.organizationArchive, archiveQuestion, () => void close('archive'))}>{f.t.organizationArchive}</f.Button>}\n {deleting && <f.Button type=\"button\" variant=\"danger\" loading={f.loading('delete')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => ask('delete', f.t.organizationDelete, deleteQuestion, () => void close('delete'))}>{f.t.organizationDelete}</f.Button>}\n </>\n )}\n </Wrap>\n )}\n </Wrap>\n )\n}\n\n/** The role a new member gets, labelled like the address above it. */\nfunction AddRole({ f, value, options, onChange }: { f: Form; value: string; options: { value: string; label: string }[]; onChange: (role: string) => void }) {\n const id = useId()\n return (\n <Labelled f={f} id={id} label={f.t.memberRole}>\n <Pick f={f} id={id} name=\"role\" value={value} options={options} onChange={onChange} />\n </Labelled>\n )\n}\n\n/**\n * The account's passkeys: made and removed on this page. A page that cannot\n * use the workspace's passkeys links to Cauthy's account page instead.\n */\nfunction PasskeysPart({ props, account, accountUrl, when }: { props: AccountProps; account: AccountDetails; accountUrl: string; when: (iso: string) => string }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [here, setHere] = useState<boolean | null>(null)\n const [list, setList] = useState<Passkey[]>([])\n const [name, setName] = useState('')\n const [password, setPassword] = useState('')\n useEffect(() => {\n void auth.methods().then((m) => {\n const can = m.passkeyHere && canUsePasskeys()\n setHere(can)\n if (can) void auth.account.passkeys().then(setList)\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (here === null) return null\n if (!here) {\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"passkeys\">\n <Heading f={f}>{f.t.passkeys}</Heading>\n <A f={f} href={accountUrl}>{f.t.managePasskeys}</A>\n </Wrap>\n )\n }\n const add = async (e: FormEvent | null, kind: 'device' | 'security_key' = 'device') => {\n e?.preventDefault()\n if (account.hasPassword && !f.check(checkPassword(password))) return\n const r = await run(() => auth.account.addPasskey({ name, password, kind }), kind === 'security_key' ? 'security_key' : SUBMIT)\n if (!r.ok) {\n // The person closed the browser's prompt: nothing to say.\n if (r.error.code === 'cancelled') f.setError(null)\n return\n }\n setList([...list, r.passkey])\n setName('')\n setPassword('')\n setDone(f.t.passkeyAdded)\n props.onSaved?.({ kind: 'passkey.added', id: r.passkey.id })\n }\n const remove = async (id: string) => {\n const r = await run(() => auth.account.removePasskey(id), `remove:${id}`)\n if (!r.ok) return\n setList(list.filter((p) => p.id !== id))\n props.onSaved?.({ kind: 'passkey.removed', id })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"passkeys\" onSubmit={add} noValidate>\n <Heading f={f}>{f.t.passkeys}</Heading>\n <Note f={f}>{f.t.passkeysHelp}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {list.length === 0 ? <Note f={f}>{f.t.noPasskeys}</Note> : (\n <ul className={f.cx('sessions')}>\n {list.map((p) => (\n <li key={p.id} className={f.cx('session')}>\n {p.name || f.t.passkeyUnnamed}\n {p.kind !== 'unknown' && <Tag f={f} plain={` · ${f.t.passkeyKinds[p.kind]}`}>{f.t.passkeyKinds[p.kind]}</Tag>} · {when(p.createdAt)}{' '}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`remove:${p.id}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void remove(p.id)}>{f.t.removePasskey}</f.Button>\n </li>\n ))}\n </ul>\n )}\n <Field f={f} name=\"name\" type=\"text\" label={f.t.passkeyName} value={name} autoComplete=\"off\" onChange={setName} />\n {account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.addPasskeyDevice}</f.Button>\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('security_key')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void add(null, 'security_key')}>{f.t.addSecurityKey}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\nfunction ProfilePart({ props, account, onSaved }: { props: AccountProps; account: AccountDetails; onSaved: (a: AccountDetails) => void }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [name, setName] = useState(account.name)\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.update({ name }))\n if (!r.ok) return\n onSaved(r.account)\n setDone(f.t.saved)\n props.onSaved?.({ kind: 'profile.saved', name: r.account.name })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"profile\" onSubmit={submit} noValidate>\n <Heading f={f}>{f.t.profile}</Heading>\n <Note f={f}>{account.email}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"name\" type=\"text\" label={f.t.name} value={name} autoComplete=\"name\" onChange={setName} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.save}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\nfunction EmailPart({ props, account }: { props: AccountProps; account: AccountDetails }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n if (!f.check(checkEmail(email), account.hasPassword && checkPassword(password))) return\n const r = await run(() => auth.account.changeEmail({ email, password }))\n if (!r.ok) return\n setPassword('')\n setDone(f.t.emailSent.replace('{email}', r.email))\n props.onSaved?.({ kind: 'email.change_requested', email: r.email })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"email\" onSubmit={submit} noValidate>\n <Heading f={f}>{f.t.emailAddress}</Heading>\n <Note f={f}>{account.email}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"email\" type=\"email\" label={f.t.newEmail} value={email} autoComplete=\"email\" required onChange={setEmail} />\n {account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.changeEmail}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\n/** The providers the account signs in with, and the ones the workspace offers to link. */\nfunction LinkedPart({ props }: { props: AccountProps }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [linked, setLinked] = useState<LinkedIdentity[] | null>(null)\n const [offered, setOffered] = useState<{ id: string; name: string }[]>([])\n const [came, setCame] = useState<string | null>(null)\n useEffect(() => {\n void auth.account.identities().then(setLinked)\n void auth.methods().then((m) => setOffered(m.providers))\n // Back from a provider: say how it went, once.\n const back = typeof window === 'undefined' ? null : new URLSearchParams(window.location.search)\n const provider = back?.get('linked')\n if (provider) {\n setCame(provider)\n props.onSaved?.({ kind: 'identity.linked', provider })\n }\n else if (back?.get('auth_error')) f.setError({ code: back.get('auth_error') as string, message: 'That account could not be linked. Try again.' })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (linked === null) return null\n const name = (id: string) => offered.find((p) => p.id === id)?.name ?? id\n const unlink = async (provider: string) => {\n const r = await run(() => auth.account.unlink(provider), `unlink:${provider}`)\n if (!r.ok) return\n setLinked(linked.filter((x) => x.provider !== provider))\n props.onSaved?.({ kind: 'identity.unlinked', provider })\n }\n const here = typeof window === 'undefined' ? undefined : window.location.pathname\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"linked\">\n <Heading f={f}>{f.t.linkedAccounts}</Heading>\n {came && <Say f={f} tone=\"success\">{f.t.linked}</Say>}\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {linked.length === 0 ? <Note f={f}>{f.t.noLinkedAccounts}</Note> : (\n <ul className={f.cx('sessions')}>\n {linked.map((x) => (\n <li key={x.provider} className={f.cx('session')}>\n {name(x.provider)}{x.email ? ` · ${x.email}` : ''}{' '}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`unlink:${x.provider}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void unlink(x.provider)}>{f.t.unlink}</f.Button>\n </li>\n ))}\n </ul>\n )}\n {offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => (\n <f.Button key={p.id} type=\"button\" variant=\"secondary\" loading={f.loading(`link:${p.id}`)} disabled={f.busy} className={f.cx('providerButton')}\n onClick={() => { f.setBusy(`link:${p.id}`); auth.account.link(p.id, { returnTo: here }) }}>{f.t.linkWith} {p.name}</f.Button>\n ))}\n </Wrap>\n )\n}\n\nfunction PasswordPart({ props }: { props: AccountProps }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [password, setPassword] = useState('')\n const [newPassword, setNewPassword] = useState('')\n usePasswordPolicy(f, useMethods(auth))\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n if (!f.check(checkPassword(password), newPasswordProblem(newPassword, f.policy, 'newPassword'))) return\n const r = await run(() => auth.account.changePassword({ password, newPassword }))\n if (!r.ok) return\n setPassword('')\n setNewPassword('')\n setDone(f.t.passwordChangedHere)\n props.onSaved?.({ kind: 'password.changed' })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"password\" onSubmit={submit} noValidate>\n <Heading f={f}>{f.t.changePassword}</Heading>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n <Field f={f} name=\"newPassword\" type=\"password\" label={f.t.newPassword} value={newPassword} autoComplete=\"new-password\" required onChange={setNewPassword} hint={f.passwordRule} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.changePassword}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\nfunction SecondStepPart({ props, account, onChanged }: { props: AccountProps; account: AccountDetails; onChanged: (on: boolean) => void }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [password, setPassword] = useState('')\n const [code, setCode] = useState('')\n const [setup, setSetup] = useState<{ secret: string; otpauthUri: string } | null>(null)\n const [codes, setCodes] = useState<string[] | null>(null)\n\n const start = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.setup({ password }))\n if (r.ok) setSetup({ secret: r.secret, otpauthUri: r.otpauthUri })\n }\n const confirm = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.verify({ code }))\n if (!r.ok) return\n setSetup(null)\n setCode('')\n setPassword('')\n setCodes(r.recoveryCodes)\n onChanged(true)\n props.onSaved?.({ kind: 'mfa.enabled' })\n }\n const turnOff = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.disable({ password }))\n if (!r.ok) return\n setPassword('')\n setCodes(null)\n onChanged(false)\n props.onSaved?.({ kind: 'mfa.disabled' })\n }\n const renew = async () => {\n const r = await run(() => auth.account.mfa.recoveryCodes({ password }), 'codes')\n if (!r.ok) return\n setCodes(r.recoveryCodes)\n props.onSaved?.({ kind: 'recovery_codes.regenerated' })\n }\n const passwordField = account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )\n const shown = codes && (\n <>\n <Note f={f}>{f.t.keepCodes}</Note>\n <ul className={f.cx('codes')}>{codes.map((c) => <li key={c}><code>{c}</code></li>)}</ul>\n </>\n )\n\n if (setup) {\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"secondStep\" onSubmit={confirm} noValidate>\n <Heading f={f}>{f.t.secondStep}</Heading>\n <Note f={f}>{f.t.addToApp}</Note>\n <code className={f.cx('secret')}>{setup.secret}</code>\n <A f={f} href={setup.otpauthUri}>{f.t.openInApp}</A>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"secondStep\" onSubmit={account.mfaEnabled ? turnOff : start} noValidate>\n <Heading f={f}>{f.t.secondStep}</Heading>\n <Note f={f}>{account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff}</Note>\n {shown}\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {passwordField}\n <f.Button type=\"submit\" variant={account.mfaEnabled ? 'danger' : 'primary'} loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{account.mfaEnabled ? f.t.turnOff : f.t.turnOn}</f.Button>\n {account.mfaEnabled && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('codes')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void renew()}>{f.t.newRecoveryCodes}</f.Button>\n )}\n </Wrap>\n )\n}\n\n// The phone as the second step, where the workspace sends codes to phones:\n// added with the password, proven with the code it receives, removed.\nfunction PhonePart({ props, account, onChanged }: { props: AccountProps; account: AccountDetails; onChanged: (on: boolean) => void }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [ways, setWays] = useState<SecondStep | null>(null)\n const [number, setNumber] = useState('')\n const [channel, setChannel] = useState<'sms' | 'whatsapp'>('sms')\n const [password, setPassword] = useState('')\n const [code, setCode] = useState('')\n const [sentTo, setSentTo] = useState('')\n const [codes, setCodes] = useState<string[] | null>(null)\n const load = () => auth.account.mfa.factors().then((w) => {\n setWays(w)\n if (w && w.phoneChannels.length > 0 && !w.phoneChannels.includes(channel)) setChannel(w.phoneChannels[0] as 'sms' | 'whatsapp')\n })\n useEffect(() => {\n void load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (!ways || ways.phoneChannels.length === 0) return null\n\n const add = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.addPhone({ phone: number, channel, password }))\n if (r.ok) setSentTo(r.sentTo)\n }\n const confirm = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.verifyPhone({ code }))\n if (!r.ok) return\n setSentTo('')\n setCode('')\n setPassword('')\n if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes)\n onChanged(true)\n props.onSaved?.({ kind: 'phone.added', channel })\n await load()\n }\n const remove = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.removePhone({ password }))\n if (!r.ok) return\n setPassword('')\n await load()\n const left = await auth.account.mfa.factors()\n onChanged(Boolean(left?.totp))\n props.onSaved?.({ kind: 'phone.removed' })\n }\n const passwordField = account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )\n if (sentTo) {\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"phone\" onSubmit={confirm} noValidate>\n <Heading f={f}>{f.t.phone}</Heading>\n <Note f={f}>{f.t.codeSent.replace('{to}', sentTo)}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"phone\" onSubmit={ways.phone ? remove : add} noValidate>\n <Heading f={f}>{f.t.phone}</Heading>\n <Note f={f}>{ways.phone ? f.t.phoneOn.replace('{to}', ways.phone.number) : `${f.t.phoneOff} ${f.t.phoneHelp}`}</Note>\n {codes && (\n <>\n <Note f={f}>{f.t.keepCodes}</Note>\n <ul className={f.cx('codes')}>{codes.map((c) => <li key={c}><code>{c}</code></li>)}</ul>\n </>\n )}\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {!ways.phone && <Field f={f} name=\"phone\" type=\"tel\" label={f.t.phone} value={number} autoComplete=\"tel\" required onChange={setNumber} />}\n {!ways.phone && ways.phoneChannels.length > 1 && f.C.Select && (\n <ChannelPick f={f} value={channel} channels={ways.phoneChannels as ('sms' | 'whatsapp')[]} onChange={setChannel} />\n )}\n {!ways.phone && ways.phoneChannels.length > 1 && !f.C.Select && (\n <div className={f.cx('field')} role=\"radiogroup\">\n {(ways.phoneChannels as ('sms' | 'whatsapp')[]).map((c) => (\n <label key={c} className={f.cx('label')}>\n <input type=\"radio\" name=\"channel\" value={c} checked={channel === c} disabled={f.busy} onChange={() => setChannel(c)} /> {c === 'whatsapp' ? f.t.byWhatsapp : f.t.bySms}\n </label>\n ))}\n </div>\n )}\n {passwordField}\n <f.Button type=\"submit\" variant={ways.phone ? 'danger' : 'primary'} loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{ways.phone ? f.t.removePhone : f.t.addPhone}</f.Button>\n </Wrap>\n )\n}\n\n/** The AI agents the person connected. Shown only when there is one. */\nfunction AgentsPart({ props, when }: { props: AccountProps; when: (iso: string) => string }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [list, setList] = useState<ConnectedAgent[]>([])\n useEffect(() => {\n void auth.account.agents().then(setList)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (list.length === 0) return null\n const disconnect = async (id: string) => {\n const r = await run(() => auth.account.disconnectAgent(id), `disconnect:${id}`)\n if (!r.ok) return\n setList(list.filter((a) => a.id !== id))\n props.onSaved?.({ kind: 'agent.disconnected', id })\n }\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"agents\">\n <Heading f={f}>{f.t.agents}</Heading>\n <Note f={f}>{f.t.agentsHelp}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ul className={f.cx('sessions')}>\n {list.map((a) => (\n <li key={a.id} className={f.cx('session')}>\n {a.name || f.t.anAgent}{a.redirectHost ? ` (${a.redirectHost})` : ''} → {a.resource.name}\n {a.scopes.length > 0 ? ` · ${a.scopes.map((s) => s.description || s.name).join(', ')}` : ''} · {when(a.lastUsedAt)}{' '}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`disconnect:${a.id}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void disconnect(a.id)}>{f.t.disconnect}</f.Button>\n </li>\n ))}\n </ul>\n </Wrap>\n )\n}\n\n/** Where the person is signed in, and \"sign out everywhere\". */\nfunction SessionsPart({ props, when }: { props: AccountProps; when: (iso: string) => string }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [sessions, setSessions] = useState<AccountSession[]>([])\n useEffect(() => {\n void auth.account.sessions().then(setSessions)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n const end = async () => {\n const r = await run(() => auth.account.signOutEverywhere(), SUBMIT, true)\n if (!r.ok) return\n props.onSaved?.({ kind: 'sessions.ended' })\n // Signed out: the button loads until the page is left, or the application's own way on settles.\n if (props.onSignedOut) f.hold(props.onSignedOut())\n else window.location.assign('/')\n }\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"sessions\">\n <Heading f={f}>{f.t.sessions}</Heading>\n <ul className={f.cx('sessions')}>\n {sessions.map((s, i) => (\n <li key={i} className={f.cx('session')}>{s.device || f.t.unknownDevice} · {s.ip} · {when(s.createdAt)}</li>\n ))}\n </ul>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading()} disabled={f.busy} className={f.cx('button')} onClick={() => void end()}>{f.t.signOutEverywhere}</f.Button>\n </Wrap>\n )\n}\n\n/** The channel phone codes go by, with the application's select. */\nfunction ChannelPick({ f, value, channels, onChange }: { f: Form; value: 'sms' | 'whatsapp'; channels: ('sms' | 'whatsapp')[]; onChange: (c: 'sms' | 'whatsapp') => void }) {\n const id = useId()\n return (\n <Labelled f={f} id={id} label={f.t.channel}>\n <Pick f={f} id={id} name=\"channel\" value={value} options={channels.map((c) => ({ value: c, label: c === 'whatsapp' ? f.t.byWhatsapp : f.t.bySms }))}\n onChange={(c) => onChange(c as 'sms' | 'whatsapp')} />\n </Labelled>\n )\n}\n"],"mappings":"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","names":["import_react","text","Tag","text","label","can","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/react.tsx","../src/passkey.ts","../src/url.ts","../src/theme.ts","../src/validate.ts","../src/client.ts","../src/permissions.ts","../src/components.tsx"],"sourcesContent":["// React: who is signed in, in the browser.\n//\n// <CauthyProvider> // once, at the root\n// <App />\n// </CauthyProvider>\n//\n// const { session, status, signIn, signOut } = useSession()\n//\n// The browser never holds a token: it asks the application's own server\n// (`/api/auth/session`), which answers who is signed in and their\n// organizations. The session is kept current by asking again a little before\n// it expires and when the window comes back into view.\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { createAuthClient, type AuthClient } from './client'\nimport type { PublicSession } from './types'\nimport { withoutTrailingSlashes } from './url'\n\nexport type { JsonValue, PublicSession, SessionOrganization, SessionUser } from './types'\nexport { can, definePolicy, type PermissionOf, type Policy, type RoleOf } from './permissions'\n\nexport interface SessionContext {\n /** The signed-in person and their organizations, or null. */\n session: PublicSession | null\n status: 'loading' | 'authenticated' | 'unauthenticated'\n /** Sends the browser to sign in, and back to `returnTo` (default: where it is now). */\n signIn(options?: { returnTo?: string; locale?: string; prompt?: 'login' }): void\n /** Signs out of this application and of Cauthy in this browser. */\n signOut(): void\n /** Asks the server again who is signed in. */\n refresh(): Promise<PublicSession | null>\n /** Where the person looks after their account: password, second step, passkeys. */\n accountUrl(returnTo?: string): string\n /** Where the server mounted the routes. */\n basePath: string\n}\n\nexport interface CauthyProviderProps {\n children: ReactNode\n /** Where the server mounted the routes. Default: `/api/auth`. */\n basePath?: string\n /**\n * The session the server already read while rendering (SSR): the first\n * paint is then right, with no \"loading\". `null` means \"nobody\"; leave it\n * out when the server did not look.\n */\n initialSession?: PublicSession | null\n /**\n * The language the person reads, for what Cauthy mails them from\n * `useAuth()` and the ready-made forms (a sign-in link, a new password, a\n * confirmation): a tag like `es` or `es-CO`, or a function that answers it\n * when the person can change it. Default: the page's own (`<html lang>`),\n * else the browser's.\n */\n locale?: string | (() => string | undefined)\n}\n\nconst Ctx = createContext<SessionContext | null>(null)\n// The provider's `locale`, read when a request goes out: not part of what\n// `useSession()` answers.\nconst LocaleCtx = createContext<() => string | undefined>(() => undefined)\n\n/** Ask again this long before the session's token runs out. */\nconst AHEAD_MS = 60_000\n\nexport function CauthyProvider({ children, basePath = '/api/auth', initialSession, locale }: CauthyProviderProps) {\n const base = withoutTrailingSlashes(basePath)\n // The latest `locale`, behind one function that does not change: a new\n // language reaches the next request without making the clients again.\n const said = useRef(locale)\n said.current = locale\n const readLocale = useCallback(() => {\n const l = said.current\n return typeof l === 'function' ? l() : l\n }, [])\n const [session, setSession] = useState<PublicSession | null>(initialSession ?? null)\n const [status, setStatus] = useState<SessionContext['status']>(\n initialSession === undefined ? 'loading' : initialSession === null ? 'unauthenticated' : 'authenticated',\n )\n const asking = useRef<Promise<PublicSession | null> | null>(null)\n\n const refresh = useCallback((): Promise<PublicSession | null> => {\n asking.current ??= (async () => {\n try {\n const res = await fetch(`${base}/session`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(String(res.status))\n const body = (await res.json()) as { session: PublicSession | null; status: string }\n // \"expired\" is the server unable to reach Cauthy: what is on screen\n // stays, and the next ask settles it.\n if (body.status !== 'expired') {\n setSession(body.session)\n setStatus(body.session ? 'authenticated' : 'unauthenticated')\n }\n return body.session\n } catch {\n setStatus((s) => (s === 'loading' ? 'unauthenticated' : s))\n return null\n } finally {\n asking.current = null\n }\n })()\n return asking.current\n }, [base])\n\n useEffect(() => {\n if (initialSession === undefined) void refresh()\n }, [initialSession, refresh])\n\n useEffect(() => {\n if (!session) return\n const wait = Math.max(new Date(session.expiresAt).getTime() - Date.now() - AHEAD_MS, 5_000)\n const timer = setTimeout(() => void refresh(), wait)\n return () => clearTimeout(timer)\n }, [session, refresh])\n\n useEffect(() => {\n const onVisible = () => {\n if (document.visibilityState === 'visible') void refresh()\n }\n document.addEventListener('visibilitychange', onVisible)\n return () => document.removeEventListener('visibilitychange', onVisible)\n }, [refresh])\n\n const value = useMemo<SessionContext>(\n () => ({\n session,\n status,\n refresh,\n signIn(options = {}) {\n const q = new URLSearchParams({ return_to: options.returnTo ?? window.location.pathname + window.location.search })\n if (options.locale) q.set('locale', options.locale)\n if (options.prompt) q.set('prompt', options.prompt)\n window.location.assign(`${base}/login?${q}`)\n },\n signOut() {\n window.location.assign(`${base}/logout`)\n },\n accountUrl(returnTo) {\n const back = returnTo ?? (typeof window === 'undefined' ? '/' : window.location.pathname + window.location.search)\n return `${base}/account?return_to=${encodeURIComponent(back)}`\n },\n basePath: base,\n }),\n [session, status, refresh, base],\n )\n return <Ctx.Provider value={value}><LocaleCtx.Provider value={readLocale}>{children}</LocaleCtx.Provider></Ctx.Provider>\n}\n\nexport function useSession(): SessionContext {\n const ctx = useContext(Ctx)\n if (ctx === null) throw new Error('cauthy-auth: useSession needs <CauthyProvider> above it')\n return ctx\n}\n\n/**\n * The application's own sign-in screens: the functions a form calls.\n *\n * const { signIn, signUp, forgotPassword, signOut, session } = useAuth()\n * const r = await signIn.email({ email, password })\n *\n * They are `createAuthClient()`'s, and what is on screen follows them: after\n * a sign-in or a sign-out, `session` is the new one with no reload.\n */\nexport function useAuth(): AuthClient & Pick<SessionContext, 'session' | 'status' | 'refresh'> {\n const { session, status, refresh, basePath } = useSession()\n const locale = useContext(LocaleCtx)\n return useMemo(() => {\n const client = createAuthClient({ basePath, locale })\n const then = async <T,>(running: Promise<T>): Promise<T> => {\n const r = await running\n await refresh()\n return r\n }\n return {\n ...client,\n signIn: {\n ...client.signIn, anonymously: (f) => then(client.signIn.anonymously(f)), email: (f) => then(client.signIn.email(f)), mfa: (f) => then(client.signIn.mfa(f)), mfaPushWait: (o) => then(client.signIn.mfaPushWait(o)), magicLinkVerify: (f) => then(client.signIn.magicLinkVerify(f)), emailCode: (f) => then(client.signIn.emailCode(f)),\n passkey: (o) => then(client.signIn.passkey(o)), passkeyAutofill: (o) => then(client.signIn.passkeyAutofill(o)), googleOneTap: (o) => then(client.signIn.googleOneTap(o)),\n },\n signUp: { email: (f) => then(client.signUp.email(f)) },\n // The invited person is signed in once they accept.\n acceptInvitation: (token, password) => then(client.acceptInvitation(token, password)),\n signOut: () => then(client.signOut()),\n account: {\n ...client.account,\n // What is on screen says the new name, and knows when the session ended.\n update: (f) => then(client.account.update(f)),\n changePassword: (f) => then(client.account.changePassword(f)),\n signOutEverywhere: () => then(client.account.signOutEverywhere()),\n // The guest is now the account: what is on screen says so.\n upgrade: (f) => then(client.account.upgrade(f)),\n },\n session,\n status,\n refresh,\n }\n }, [basePath, locale, refresh, session, status])\n}\n\nexport { createAuthClient, type Account as AccountDetails, type AccountClient, type AccountSession, type AuthClient, type ConnectedAgent, type AuthError, type AuthMethods, type AuthResult, type Invitation, type LinkedIdentity, type OrganizationPerson, type OrganizationRoleChoice, type OrganizationSeat, type OrganizationsClient, type Passkey, type PasskeyKind, type PendingLegal, type SecondStep, type SSOConnection, canAutofillPasskeys, canUsePasskeys } from './client'\nexport {\n AcceptInvite, Account, AccountAgents, AccountEmail, AccountLinked, AccountPasskeys, AccountPassword, AccountPhone, AccountProfile, AccountSecondStep, AccountSessions,\n ForgotPassword, GoogleOneTap, OrganizationMembers, PendingTerms, ResetPassword, SignIn, SignUp, VerifyEmail,\n type AcceptInviteEvent, type AcceptInviteProps, type AccountEvent, type AccountPartProps, type AccountProps, type AccountSection,\n type OrganizationMembersAction, type OrganizationMembersEvent, type OrganizationMembersProps, type PendingTermsProps,\n type AuthAlertProps, type AuthBadgeProps, type AuthButtonProps, type AuthCheckboxProps, type AuthComponents, type AuthConfirmOptions, type AuthDividerProps,\n type AuthFieldProps, type AuthFormLayoutProps, type AuthFormProps, type AuthInputProps, type AuthLinkProps, type AuthSelectProps, type AuthTextProps, type AuthTexts, type GoogleOneTapProps,\n} from './components'\n","// A passkey ceremony in the browser: what Cauthy says to ask for, in the\n// shape the browser's WebAuthn API takes, and what the browser answers, in\n// the shape Cauthy reads. Both travel as JSON, with bytes in base64url.\n\nimport type { AuthError } from './client'\n\n/** Whether this browser can use a passkey at all. */\nexport function canUsePasskeys(): boolean {\n return typeof window !== 'undefined' && typeof window.PublicKeyCredential === 'function' &&\n typeof navigator !== 'undefined' && typeof navigator.credentials?.get === 'function'\n}\n\n/**\n * Whether this browser offers passkeys in the autofill of a field marked\n * `autocomplete=\"username webauthn\"`, so the person picks one without\n * looking for a button.\n */\nexport async function canAutofillPasskeys(): Promise<boolean> {\n if (!canUsePasskeys()) return false\n const pkc = window.PublicKeyCredential as unknown as { isConditionalMediationAvailable?: () => Promise<boolean> }\n try {\n return typeof pkc.isConditionalMediationAvailable === 'function' && (await pkc.isConditionalMediationAvailable()) === true\n } catch {\n return false\n }\n}\n\nfunction bytes(text: string): ArrayBuffer {\n const b64 = text.replace(/-/g, '+').replace(/_/g, '/').padEnd(Math.ceil(text.length / 4) * 4, '=')\n const bin = atob(b64)\n const out = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out.buffer\n}\n\nfunction text(buf: ArrayBuffer | null | undefined): string | null {\n if (!buf) return null\n const view = new Uint8Array(buf)\n let bin = ''\n for (let i = 0; i < view.byteLength; i++) bin += String.fromCharCode(view[i])\n return btoa(bin).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\nconst withId = (list: any[] | undefined) => (list ?? []).map((c) => ({ ...c, id: bytes(c.id) }))\n\n/**\n * Asks the browser for a passkey, with the options Cauthy sent. `conditional`:\n * in the autofill of the page's username field, waiting until the person\n * picks one or `signal` aborts.\n */\nexport async function getPasskey(options: any, how: { mediation?: 'conditional'; signal?: AbortSignal } = {}): Promise<Record<string, unknown>> {\n const publicKey = { ...options, challenge: bytes(options.challenge), allowCredentials: withId(options.allowCredentials) }\n const cred = (await navigator.credentials.get({ publicKey, ...how } as CredentialRequestOptions)) as PublicKeyCredential | null\n if (cred === null) throw new DOMException('No passkey was chosen.', 'NotAllowedError')\n const r = cred.response as AuthenticatorAssertionResponse\n return {\n id: cred.id, rawId: text(cred.rawId), type: cred.type,\n response: {\n authenticatorData: text(r.authenticatorData), clientDataJSON: text(r.clientDataJSON),\n signature: text(r.signature), userHandle: text(r.userHandle),\n },\n clientExtensionResults: cred.getClientExtensionResults?.() ?? {},\n }\n}\n\n/** Asks the browser to make a passkey, with the options Cauthy sent. */\nexport async function makePasskey(options: any): Promise<Record<string, unknown>> {\n const publicKey = {\n ...options,\n challenge: bytes(options.challenge),\n user: { ...options.user, id: bytes(options.user.id) },\n excludeCredentials: withId(options.excludeCredentials),\n }\n const cred = (await navigator.credentials.create({ publicKey })) as PublicKeyCredential | null\n if (cred === null) throw new DOMException('No passkey was made.', 'NotAllowedError')\n const r = cred.response as AuthenticatorAttestationResponse\n return {\n id: cred.id, rawId: text(cred.rawId), type: cred.type,\n response: {\n clientDataJSON: text(r.clientDataJSON), attestationObject: text(r.attestationObject),\n transports: typeof r.getTransports === 'function' ? r.getTransports() : [],\n },\n clientExtensionResults: cred.getClientExtensionResults?.() ?? {},\n }\n}\n\n/** What the browser's refusal means, for the screen. */\nexport function ceremonyError(e: unknown): AuthError {\n const name = e instanceof Error || e instanceof DOMException ? e.name : ''\n if (name === 'NotAllowedError' || name === 'AbortError') return { code: 'cancelled', message: 'The passkey was not used. Try again when you are ready.' }\n if (name === 'InvalidStateError') return { code: 'passkey_exists', message: 'This device already has a passkey for this account.' }\n if (name === 'SecurityError') return { code: 'passkey_unavailable', message: 'Passkeys cannot be used on this page.' }\n return { code: 'passkey_failed', message: 'The passkey could not be used. Try again, or sign in another way.' }\n}\n","/**\n * The address without its trailing slashes: `https://auth.example.com/` and\n * `https://auth.example.com` name the same issuer. A loop, not `/\\/+$/`,\n * which backtracks over a long run of slashes.\n */\nexport function withoutTrailingSlashes(s: string): string {\n let end = s.length\n while (end > 0 && s.charCodeAt(end - 1) === 47) end--\n return s.slice(0, end)\n}\n","// An application's look, for Cauthy's hosted pages.\n//\n// Cauthy's pages — sign-in, sign-up, the account page — can take the colours,\n// corners, typeface and logo of the application that sends its people there,\n// so signing in reads as a page of the application. A theme is a short list of\n// values, which Cauthy checks one by one; it is never CSS.\n//\n// An application built with Stackmyth already has those values, as its\n// `--sm-*` tokens. `themeFromStackmyth` reads them out of its stylesheets.\n\nimport { withoutTrailingSlashes } from './url'\n\n/** How an application looks on Cauthy's hosted pages. Every value is optional. */\n/** One font file the application serves: a family in one weight (or a range) and one style. */\nexport interface ThemeFont {\n family: string\n /** An https address of a `.woff2` file. It must answer with `Access-Control-Allow-Origin` for Cauthy's origin. */\n url: string\n /** `400`, or `\"100 900\"` for a variable font. Default: 400. */\n weight?: number | string\n style?: 'normal' | 'italic'\n}\n\n/** What an application says on its sign-in page, in one language. */\nexport interface ThemeTexts {\n /** Replaces \"Sign in\". */\n heading?: string\n /** Replaces \"to continue to …\". */\n subheading?: string\n /** The messages of the split layout's panel, shown one at a time (up to 5). */\n panel?: string[]\n /** Links at the foot of the split layout: privacy, terms (up to 4). */\n links?: { label: string; url: string }[]\n}\n\nexport interface CauthyTheme {\n /** The page. Colours are `#rrggbb` or `rgba(r, g, b, a)`. */\n background?: string\n /** The card, and inputs. */\n surface?: string\n /** Headings and what is typed. */\n text?: string\n /** Paragraphs, labels, small print. */\n textMuted?: string\n border?: string\n /** The fields and the secondary buttons, when they are not the card's colours. */\n inputBackground?: string\n inputBorder?: string\n /** The main button, and what is written on it. */\n primary?: string\n primaryText?: string\n /** Links, and the focus ring. */\n accent?: string\n error?: string\n errorBackground?: string\n success?: string\n successBackground?: string\n /** Corners of cards and inputs, in pixels (0–40). */\n radius?: number\n /** Corners of buttons, in pixels (0–40). */\n buttonRadius?: number\n /** A CSS font-family list: the application's typeface first, a system font after it. */\n fontFamily?: string\n /** The files of the typefaces `fontFamily` names, for people who do not have them installed. */\n fonts?: ThemeFont[]\n /** An image shown where \"Cauthy\" is, over https. */\n logoUrl?: string\n /**\n * How the sign-in pages are laid out: `card` (the default, one card in the\n * middle) or `split` (the form on one side, a panel that presents the\n * application on the other).\n */\n layout?: 'card' | 'split'\n /** The colours the split layout's backdrop blends, one to four. */\n panelColors?: string[]\n /** The colour of what is written on the panel. */\n panelText?: string\n /** An https image shown over the panel's messages. */\n panelIconUrl?: string\n /** The application's own words on the sign-in page, by language (`en`, `es`). */\n texts?: Record<string, ThemeTexts>\n /**\n * The application's Stackmyth tokens (`--sm-*`), from `tokensFromStackmyth`.\n * Cauthy's pages are drawn with Stackmyth's components, so these make its\n * buttons and fields the application's own. They are laid over the named values.\n */\n tokens?: Record<string, string>\n}\n\nexport interface StackmythThemeOptions {\n /**\n * The named theme to read, when the stylesheet keeps several under\n * `[data-theme=…]` (`\"vennet\"`). Without it only what applies to every\n * page (`:root`) is read.\n */\n theme?: string\n /** Which of the application's two modes to take. Default: `light`. */\n mode?: 'light' | 'dark'\n logoUrl?: string\n}\n\nexport interface ImportedTheme {\n theme: CauthyTheme\n /** Tokens that were there and could not be carried over, and why. */\n warnings: string[]\n}\n\nconst MAX_RADIUS = 40\n\n// ── Reading custom properties out of CSS ───────────────────────────────────\n\ninterface Declaration {\n name: string\n value: string\n /** The selectors and at-rules it sits inside, outermost first. */\n within: string[]\n}\n\n// The stylesheet without its /* comments */, read in one pass. An unclosed\n// comment runs to the end, as a browser reads it.\nfunction withoutComments(css: string): string {\n let out = ''\n let i = 0\n for (;;) {\n const open = css.indexOf('/*', i)\n if (open < 0) return out + css.slice(i)\n out += css.slice(i, open)\n const close = css.indexOf('*/', open + 2)\n if (close < 0) return out\n i = close + 2\n }\n}\n\nfunction declarations(css: string): Declaration[] {\n const text = withoutComments(css)\n const out: Declaration[] = []\n const within: string[] = []\n let chunk = ''\n let quote = ''\n let depth = 0 // parentheses, so a `;` inside url(…) does not end anything\n const flush = () => {\n const m = /^\\s*(--[\\w-]+)\\s*:\\s*([\\s\\S]+?)\\s*$/.exec(chunk)\n if (m) out.push({ name: m[1], value: m[2].replace(/\\s+/g, ' ').replace(/\\s*!important$/, ''), within: [...within] })\n chunk = ''\n }\n for (const ch of text) {\n if (quote) {\n chunk += ch\n if (ch === quote) quote = ''\n continue\n }\n if (ch === '\"' || ch === \"'\") {\n quote = ch\n chunk += ch\n } else if (ch === '(') {\n depth++\n chunk += ch\n } else if (ch === ')') {\n depth = Math.max(0, depth - 1)\n chunk += ch\n } else if (ch === '{' && depth === 0) {\n within.push(chunk.trim().replace(/\\s+/g, ' '))\n chunk = ''\n } else if (ch === '}' && depth === 0) {\n flush()\n within.pop()\n } else if (ch === ';' && depth === 0) {\n flush()\n } else {\n chunk += ch\n }\n }\n return out\n}\n\nconst DARK = /prefers-color-scheme:\\s*dark|data-(mode|theme|color-scheme)=[\"']?dark|\\.dark\\b/i\nconst LIGHT = /prefers-color-scheme:\\s*light|data-(mode|theme|color-scheme)=[\"']?light|\\.light\\b/i\nconst NAMED = /data-theme=[\"']?([\\w-]+)/i\n\n/** Whether a declaration applies to the page being themed. */\nfunction applies(d: Declaration, o: Required<Pick<StackmythThemeOptions, 'mode'>> & { theme?: string }): boolean {\n for (const scope of d.within) {\n if (o.mode === 'light' && DARK.test(scope)) return false\n if (o.mode === 'dark' && LIGHT.test(scope)) return false\n const named = NAMED.exec(scope)\n if (named && !/^(dark|light)$/i.test(named[1]) && named[1] !== o.theme) return false\n // Component-level rules (`.btn { --sm-… }`) are not the page's theme;\n // the class a mode is switched with (`.dark`, as shadcn/ui does) is.\n if (!scope.startsWith('@') && !/:root|^html\\b|^body\\b|\\[data-|^\\*$|:host|^\\.(dark|light)\\b/.test(scope)) return false\n }\n return true\n}\n\n// ── Tokens ─────────────────────────────────────────────────────────────────\n\n/** What a token's value may be written with, as Cauthy checks it. */\nconst TOKEN_CHARS = /^[A-Za-z0-9 #%.,()/'\"_+*-]+$/\nconst TOKEN_FUNCS = new Set(['var', 'calc', 'min', 'max', 'clamp', 'rgb', 'rgba', 'hsl', 'hsla', 'hwb', 'lab', 'lch', 'oklab', 'oklch', 'color',\n 'color-mix', 'light-dark', 'cubic-bezier', 'steps', 'linear', 'linear-gradient', 'radial-gradient', 'conic-gradient',\n 'repeating-linear-gradient', 'repeating-radial-gradient', 'drop-shadow', 'blur', 'translate', 'translatex', 'translatey', 'scale', 'rotate'])\n\nfunction tokenValue(value: string): string | null {\n const v = value.replace(/\\s+/g, ' ').trim()\n if (v === '' || v.length > 400 || !TOKEN_CHARS.test(v)) return null\n for (const m of v.matchAll(/([A-Za-z-]+)\\(/g)) if (!TOKEN_FUNCS.has(m[1].toLowerCase())) return null\n if (/^\\(|[ ,(]\\(/.test(v)) return null\n return v\n}\n\n/** A scope that is the page's theme itself: the root, or the theme and mode attributes — never a component inside it. */\nconst THEME_SELECTOR = /^(?::root|html|body|\\[data-(?:theme|mode|color-scheme)(?:=[\"']?[\\w-]+[\"']?)?\\])$/i\n// Checked a selector at a time (split on commas and spaces) rather than with\n// one pattern over the list, which backtracks on a long one.\nconst isThemeScope = (selectors: string) => {\n const parts = selectors.split(/[\\s,]+/).filter(Boolean)\n return parts.length > 0 && parts.every((one) => THEME_SELECTOR.test(one))\n}\n\nexport interface StackmythTokens {\n /** Every `--sm-*` token the stylesheets set for the page, ready for `theme.tokens`. */\n tokens: Record<string, string>\n /** Tokens that were there and Cauthy would not take, and why. */\n warnings: string[]\n}\n\n/**\n * Reads an application's Stackmyth tokens out of its stylesheets: every\n * `--sm-*` custom property its theme sets, in the order the sheets are given\n * (a later one wins). Its own names — a brand palette the tokens point at —\n * are written in, so what comes out stands on Stackmyth's names alone.\n *\n * Cauthy's sign-in pages are drawn with Stackmyth's components: these tokens\n * are what makes them look like the application.\n */\nexport function tokensFromStackmyth(css: string | string[], options: StackmythThemeOptions = {}): StackmythTokens {\n const mode = options.mode ?? 'light'\n const all = (Array.isArray(css) ? css : [css]).flatMap(declarations)\n const named = options.theme ?? all.map((d) => d.within.map((w) => NAMED.exec(w)?.[1]).find((n) => n && !/^(dark|light)$/i.test(n))).find(Boolean)\n const vars = new Map<string, string>()\n for (const d of all) {\n if (!applies(d, { mode, theme: named })) continue\n if (!d.within.every((w) => w.startsWith('@') || isThemeScope(w))) continue\n vars.set(d.name, d.value)\n }\n // The application's own names are written in; Stackmyth's are left as references.\n const inline = (value: string, depth = 0): string | null => {\n if (depth > 16) return null\n let failed = false\n let out = value\n for (let guard = 0; guard < 64; guard++) {\n const next = out.replace(/var\\(\\s*(--(?!sm-)[\\w-]+)\\s*(?:,\\s*([^()]*(?:\\([^()]*\\)[^()]*)*))?\\)/, (_m, name: string, fallback?: string) => {\n const known = vars.get(name)\n const got = known !== undefined ? inline(known, depth + 1) : fallback !== undefined ? inline(fallback.trim(), depth + 1) : null\n if (got === null) failed = true\n return got ?? ''\n })\n if (failed) return null\n if (next === out) break\n out = next\n }\n return out\n }\n const tokens: Record<string, string> = {}\n const warnings: string[] = []\n for (const [name, raw] of vars) {\n if (!/^--sm-[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name)) continue\n const written = inline(raw)\n const value = written === null ? null : tokenValue(written)\n if (value === null) warnings.push(`${name}: \"${raw.length > 60 ? raw.slice(0, 57) + '…' : raw}\" is not a value Cauthy takes`)\n else tokens[name] = value\n }\n if (Object.keys(tokens).length === 0) warnings.push('no --sm-* token was found in these stylesheets')\n return { tokens, warnings }\n}\n\n// ── Values ─────────────────────────────────────────────────────────────────\n\nfunction resolve(value: string, vars: Map<string, string>, seen = 0): string | null {\n if (seen > 16) return null\n let unresolved = false\n // Innermost var() first: fallbacks may hold another var().\n let out = value\n for (let guard = 0; guard < 32 && /var\\(/.test(out); guard++) {\n out = out.replace(/var\\(\\s*(--[\\w-]+)\\s*(?:,\\s*([^()]*(?:\\([^()]*\\)[^()]*)*))?\\)/, (_m, name: string, fallback?: string) => {\n const known = vars.get(name)\n const next = known !== undefined ? resolve(known, vars, seen + 1) : fallback !== undefined ? resolve(fallback.trim(), vars, seen + 1) : null\n if (next === null) unresolved = true\n return next ?? ''\n })\n if (unresolved) return null\n }\n return /var\\(/.test(out) ? null : out.trim()\n}\n\nconst clamp01 = (n: number) => Math.min(1, Math.max(0, n))\nconst hex2 = (n: number) => Math.round(clamp01(n) * 255).toString(16).padStart(2, '0')\nconst gamma = (c: number) => (c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055)\n\nfunction out(r: number, g: number, b: number, a = 1): string {\n if (a >= 1) return `#${hex2(r)}${hex2(g)}${hex2(b)}`\n return `rgba(${Math.round(clamp01(r) * 255)}, ${Math.round(clamp01(g) * 255)}, ${Math.round(clamp01(b) * 255)}, ${Math.round(clamp01(a) * 1000) / 1000})`\n}\n\nconst alpha = (s: string | undefined) => (s === undefined ? 1 : s.endsWith('%') ? parseFloat(s) / 100 : parseFloat(s))\n\nconst KEYWORDS: Record<string, string> = { white: '#ffffff', black: '#000000' }\n\n/** A colour as Cauthy takes it — `#rrggbb` or `rgba(…)` — or null when it is none it can read. */\nexport function toColor(value: string): string | null {\n const v = value.trim().toLowerCase()\n if (KEYWORDS[v]) return KEYWORDS[v]\n if (/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(v)) return v\n let m = /^rgba?\\(\\s*([\\d.]+%?)[\\s,]+([\\d.]+%?)[\\s,]+([\\d.]+%?)(?:\\s*[,/]\\s*([\\d.]+%?))?\\s*\\)$/.exec(v)\n if (m) {\n const ch = (s: string) => (s.endsWith('%') ? parseFloat(s) / 100 : parseFloat(s) / 255)\n return out(ch(m[1]), ch(m[2]), ch(m[3]), alpha(m[4]))\n }\n m = /^hsla?\\(\\s*([\\d.]+)(?:deg)?[\\s,]+([\\d.]+)%[\\s,]+([\\d.]+)%(?:\\s*[,/]\\s*([\\d.]+%?))?\\s*\\)$/.exec(v)\n if (m) {\n const h = ((parseFloat(m[1]) % 360) + 360) % 360\n const s = parseFloat(m[2]) / 100\n const l = parseFloat(m[3]) / 100\n const f = (n: number) => {\n const k = (n + h / 30) % 12\n return l - s * Math.min(l, 1 - l) * Math.max(-1, Math.min(k - 3, 9 - k, 1))\n }\n return out(f(0), f(8), f(4), alpha(m[4]))\n }\n m = /^oklch\\(\\s*([\\d.]+%?)\\s+([\\d.]+%?)\\s+([\\d.]+)(?:deg)?(?:\\s*\\/\\s*([\\d.]+%?))?\\s*\\)$/.exec(v)\n if (m) {\n const L = m[1].endsWith('%') ? parseFloat(m[1]) / 100 : parseFloat(m[1])\n const C = m[2].endsWith('%') ? (parseFloat(m[2]) / 100) * 0.4 : parseFloat(m[2])\n const H = (parseFloat(m[3]) * Math.PI) / 180\n const a = C * Math.cos(H)\n const b = C * Math.sin(H)\n const l = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3)\n const mm = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3)\n const s = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3)\n return out(\n gamma(4.0767416621 * l - 3.3077115913 * mm + 0.2309699292 * s),\n gamma(-1.2684380046 * l + 2.6097574011 * mm - 0.3413193965 * s),\n gamma(-0.0041960863 * l - 0.7034186147 * mm + 1.707614701 * s),\n alpha(m[4]),\n )\n }\n return null\n}\n\n/** A length in pixels, within what Cauthy takes, or null. */\nfunction toRadius(value: string): number | null {\n const m = /^([\\d.]+)(px|rem|em)?$/.exec(value.trim())\n if (!m) return null\n const px = parseFloat(m[1]) * (m[2] === 'rem' || m[2] === 'em' ? 16 : 1)\n return Number.isFinite(px) ? Math.min(MAX_RADIUS, Math.max(0, Math.round(px))) : null\n}\n\n/** A font list as Cauthy takes it, or null. */\nfunction toFont(value: string): string | null {\n const v = value.trim()\n return /^[A-Za-z0-9 ,'\"_-]{1,200}$/.test(v) && (v.match(/\"/g)?.length ?? 0) % 2 === 0 && (v.match(/'/g)?.length ?? 0) % 2 === 0 ? v : null\n}\n\n// ── Stackmyth ──────────────────────────────────────────────────────────────\n\n/** Which Stackmyth token each value of a theme is read from, first found wins. */\nconst COLORS: [keyof CauthyTheme, string[]][] = [\n ['background', ['--sm-bg-surface', '--sm-surface']],\n ['surface', ['--sm-bg-surface-raised', '--sm-surface-raised']],\n ['text', ['--sm-text-primary', '--sm-surface-text']],\n ['textMuted', ['--sm-text-secondary']],\n ['border', ['--sm-border-default', '--sm-surface-border']],\n ['primary', ['--sm-primary', '--sm-bg-interactive']],\n ['primaryText', ['--sm-primary-text', '--sm-text-inverse']],\n ['accent', ['--sm-text-brand', '--sm-border-focus', '--sm-accent']],\n ['error', ['--sm-error-soft-text', '--sm-error']],\n ['errorBackground', ['--sm-error-soft']],\n ['success', ['--sm-success-soft-text', '--sm-success']],\n ['successBackground', ['--sm-success-soft']],\n]\n\n/**\n * Reads an application's Stackmyth theme out of its stylesheets.\n *\n * Give it the CSS that declares the tokens, in the order the application\n * loads it — Stackmyth's own (`@stackmyth/core/core.vars.css`, or a theme\n * file) and then the application's brand file that re-points them. Tokens\n * that point at the application's own variables are followed. The\n * application's dark mode is left out unless asked for.\n */\nexport function themeFromStackmyth(css: string | string[], options: StackmythThemeOptions = {}): ImportedTheme {\n const o = { mode: options.mode ?? 'light', theme: options.theme }\n const vars = new Map<string, string>()\n for (const sheet of Array.isArray(css) ? css : [css]) {\n for (const d of declarations(sheet)) if (applies(d, o)) vars.set(d.name, d.value)\n }\n const theme: CauthyTheme = {}\n const warnings: string[] = []\n\n const read = <T>(tokens: string[], to: (v: string) => T | null, what: string): T | undefined => {\n for (const token of tokens) {\n const raw = vars.get(token)\n if (raw === undefined) continue\n const value = resolve(raw, vars)\n const got = value === null ? null : to(value)\n if (got !== null) return got\n warnings.push(`${token}: \"${raw}\" is not ${what} Cauthy can take`)\n }\n return undefined\n }\n\n for (const [field, tokens] of COLORS) {\n const c = read(tokens, toColor, 'a colour')\n if (c !== undefined) (theme as Record<string, unknown>)[field] = c\n }\n const radius = read(['--sm-radius-container', '--sm-radius-md'], toRadius, 'a length')\n if (radius !== undefined) theme.radius = radius\n const button = read(['--sm-radius-interactive', '--sm-radius-sm'], toRadius, 'a length')\n if (button !== undefined) theme.buttonRadius = button\n const font = read(['--sm-font-family'], toFont, 'a font list')\n if (font !== undefined) theme.fontFamily = font\n if (options.logoUrl) theme.logoUrl = options.logoUrl\n\n if (vars.size === 0) warnings.push('no custom properties were found: is this the stylesheet that declares the --sm-* tokens?')\n else if (![...vars.keys()].some((k) => k.startsWith('--sm-'))) warnings.push('no --sm-* token was found in these stylesheets')\n return { theme, warnings }\n}\n\n// ── Any stylesheet ─────────────────────────────────────────────────────────\n\n/** The values of a theme a stylesheet can say. */\nexport type ThemeField =\n | 'background' | 'surface' | 'text' | 'textMuted' | 'border' | 'inputBackground' | 'inputBorder'\n | 'primary' | 'primaryText' | 'accent' | 'error' | 'errorBackground' | 'success' | 'successBackground'\n | 'radius' | 'buttonRadius' | 'fontFamily'\n\n/** How a stylesheet names its look: Stackmyth's tokens, shadcn/ui's (and Tailwind's), or the application's own. */\nexport type CssFormat = 'stackmyth' | 'shadcn' | 'custom'\n\nexport interface CssThemeOptions {\n /** Which names to read. Default: `auto`, told from the stylesheet itself. */\n format?: CssFormat | 'auto'\n /** Which of the application's two modes to take. Default: `light`. */\n mode?: 'light' | 'dark'\n /** The named theme to read, when the stylesheet keeps several under `[data-theme=…]`. */\n theme?: string\n /** For `custom`: the variable each value is read from, `{ primary: '--brand' }`. */\n map?: Partial<Record<ThemeField, string>>\n}\n\nexport interface CssImportedTheme extends ImportedTheme {\n /** The names that were read. */\n format: CssFormat\n}\n\nconst RADII: ThemeField[] = ['radius', 'buttonRadius']\n\n/** shadcn/ui's names, as Tailwind 3 (`--primary`) and Tailwind 4 (`--color-primary`) write them. */\nconst SHADCN: [ThemeField, string[]][] = [\n ['background', ['--background', '--color-background']],\n ['surface', ['--card', '--color-card', '--popover', '--color-popover']],\n ['text', ['--foreground', '--color-foreground']],\n ['textMuted', ['--muted-foreground', '--color-muted-foreground']],\n ['border', ['--border', '--color-border']],\n ['inputBorder', ['--input', '--color-input']],\n ['primary', ['--primary', '--color-primary']],\n ['primaryText', ['--primary-foreground', '--color-primary-foreground']],\n ['accent', ['--ring', '--color-ring', '--primary', '--color-primary']],\n ['error', ['--destructive', '--color-destructive']],\n ['radius', ['--radius']],\n ['buttonRadius', ['--radius']],\n ['fontFamily', ['--font-sans', '--font-family']],\n]\n\n/** A colour as shadcn/ui writes it on Tailwind 3 — `222.2 84% 4.9%`, the inside of hsl() — or any other. */\nfunction shadcnColor(value: string): string | null {\n return /^[\\d.]+(?:deg)?\\s+[\\d.]+%\\s+[\\d.]+%(?:\\s*\\/\\s*[\\d.]+%?)?$/.test(value.trim()) ? toColor(`hsl(${value.trim()})`) : toColor(value)\n}\n\n/** Every custom property a stylesheet sets for the page, the last one winning. */\nfunction pageVariables(css: string | string[], mode: 'light' | 'dark', theme?: string): Map<string, string> {\n const vars = new Map<string, string>()\n for (const sheet of Array.isArray(css) ? css : [css]) {\n for (const d of declarations(sheet)) if (applies(d, { mode, theme })) vars.set(d.name, d.value)\n }\n return vars\n}\n\n/** The custom properties a stylesheet sets for the page, by name: what a person picks from to map their own. */\nexport function cssVariables(css: string | string[], options: Pick<CssThemeOptions, 'mode' | 'theme'> = {}): string[] {\n return [...pageVariables(css, options.mode ?? 'light', options.theme).keys()].sort()\n}\n\n/**\n * Reads an application's look out of its stylesheets, whatever names it uses:\n * Stackmyth's tokens, shadcn/ui's (`--primary`, `--radius`, on Tailwind 3 or\n * 4), or the application's own variables given in `map`. What comes out is a\n * theme of named values, never CSS.\n */\nexport function themeFromCss(css: string | string[], options: CssThemeOptions = {}): CssImportedTheme {\n const mode = options.mode ?? 'light'\n const vars = pageVariables(css, mode, options.theme)\n const names = [...vars.keys()]\n let format: CssFormat\n if (options.format && options.format !== 'auto') format = options.format\n else if (options.map && Object.keys(options.map).length > 0) format = 'custom'\n else if (names.some((n) => n.startsWith('--sm-'))) format = 'stackmyth'\n else if (names.some((n) => /^--(color-)?(primary|background|foreground)$/.test(n))) format = 'shadcn'\n else format = 'custom'\n\n if (format === 'stackmyth') return { ...themeFromStackmyth(css, { mode, theme: options.theme }), format }\n\n const spec: [ThemeField, string[]][] = format === 'shadcn'\n ? SHADCN\n : Object.entries(options.map ?? {}).filter(([, v]) => v).map(([k, v]) => [k as ThemeField, [String(v).startsWith('--') ? String(v) : `--${v}`]])\n const theme: CauthyTheme = {}\n const warnings: string[] = []\n for (const [field, tokens] of spec) {\n for (const token of tokens) {\n const raw = vars.get(token)\n if (raw === undefined) continue\n const value = resolve(raw, vars)\n const got = value === null ? null\n : RADII.includes(field) ? toRadius(value)\n : field === 'fontFamily' ? toFont(value)\n : format === 'shadcn' ? shadcnColor(value) : toColor(value)\n if (got !== null) {\n (theme as Record<string, unknown>)[field] = got\n break\n }\n warnings.push(`${token}: \"${raw.length > 60 ? raw.slice(0, 57) + '…' : raw}\" is not ${RADII.includes(field) ? 'a length' : field === 'fontFamily' ? 'a font list' : 'a colour'} Cauthy can take`)\n }\n }\n if (vars.size === 0) warnings.push('no custom properties were found in these stylesheets')\n else if (format === 'custom' && spec.length === 0) warnings.push('these stylesheets use names of their own: say which variable each value is read from')\n return { theme, warnings, format }\n}\n\n// ── On the application's own screens ───────────────────────────────────────\n\n/**\n * A theme as the CSS variables of `cauthy-auth/styles.css` (`--cauthy-*`), for\n * the forms an application shows on its own pages. The page's own background,\n * the layout and the words are Cauthy's pages' matter, and left out.\n */\nexport function themeVariables(theme: CauthyTheme): Record<string, string> {\n const vars: Record<string, string> = {}\n const put = (name: string, v: string | number | undefined) => {\n if (v === undefined || v === '') return\n vars[`--cauthy-${name}`] = typeof v === 'number' ? `${v}px` : v\n }\n put('surface', theme.surface)\n put('text', theme.text)\n put('text-muted', theme.textMuted)\n put('border', theme.border)\n put('input-background', theme.inputBackground)\n put('input-border', theme.inputBorder)\n put('primary', theme.primary)\n put('primary-text', theme.primaryText)\n put('accent', theme.accent)\n put('error', theme.error)\n put('error-background', theme.errorBackground)\n put('success', theme.success)\n put('success-background', theme.successBackground)\n put('radius', theme.radius)\n put('button-radius', theme.buttonRadius)\n put('font', theme.fontFamily)\n return vars\n}\n\n// ── Sending it to Cauthy ───────────────────────────────────────────────────\n\n/** A theme as Cauthy's API names its values. */\nexport function toWire(theme: CauthyTheme): Record<string, unknown> {\n const names: Record<keyof CauthyTheme, string> = {\n background: 'background', surface: 'surface', text: 'text', textMuted: 'text_muted', border: 'border',\n primary: 'primary', primaryText: 'primary_text', accent: 'accent', error: 'error', errorBackground: 'error_background',\n success: 'success', successBackground: 'success_background', radius: 'radius', buttonRadius: 'button_radius',\n fontFamily: 'font_family', logoUrl: 'logo_url', fonts: 'fonts', layout: 'layout', panelColors: 'panel_colors',\n panelText: 'panel_text', panelIconUrl: 'panel_icon_url', texts: 'texts', inputBackground: 'input_background', inputBorder: 'input_border', tokens: 'tokens',\n }\n const wire: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(theme)) {\n if (v === undefined || v === '' || (Array.isArray(v) && v.length === 0)) continue\n wire[names[k as keyof CauthyTheme]] = v\n }\n return wire\n}\n\n/** A theme as Cauthy answers it, in this package's names. */\nexport function fromWire(wire: Record<string, unknown>): CauthyTheme {\n const names: Record<string, keyof CauthyTheme> = {\n background: 'background', surface: 'surface', text: 'text', text_muted: 'textMuted', border: 'border',\n primary: 'primary', primary_text: 'primaryText', accent: 'accent', error: 'error', error_background: 'errorBackground',\n success: 'success', success_background: 'successBackground', radius: 'radius', button_radius: 'buttonRadius',\n font_family: 'fontFamily', logo_url: 'logoUrl', fonts: 'fonts', layout: 'layout', panel_colors: 'panelColors',\n panel_text: 'panelText', panel_icon_url: 'panelIconUrl', texts: 'texts', input_background: 'inputBackground', input_border: 'inputBorder', tokens: 'tokens',\n }\n const theme: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(wire ?? {})) if (names[k] && v !== undefined && v !== null && v !== '') theme[names[k]] = v\n return theme as CauthyTheme\n}\n\nexport interface PushThemeOptions {\n /** Cauthy's address. Default: `CAUTHY_ISSUER`. */\n issuer?: string\n /** The application's client id. Default: `CAUTHY_CLIENT_ID`. */\n clientId?: string\n /** The workspace's slug. Default: `CAUTHY_TENANT`. */\n tenant?: string\n /**\n * A personal access token with `oauth_clients:manage`. Default:\n * `CAUTHY_TOKEN`. It belongs in the deploy pipeline, never in the application.\n */\n token?: string\n theme: CauthyTheme\n fetch?: typeof fetch\n}\n\n/**\n * Gives the application its look on Cauthy's pages. It replaces the theme: a\n * value left out goes back to Cauthy's own. Run it when the brand changes —\n * from a script or the deploy — not on every request.\n */\nexport async function pushTheme(o: PushThemeOptions): Promise<void> {\n const env = (n: string) => (typeof process !== 'undefined' ? process.env?.[n] : undefined)\n const issuer = withoutTrailingSlashes(o.issuer ?? env('CAUTHY_ISSUER') ?? '')\n const clientId = o.clientId ?? env('CAUTHY_CLIENT_ID') ?? ''\n const tenant = o.tenant ?? env('CAUTHY_TENANT') ?? ''\n const token = o.token ?? env('CAUTHY_TOKEN') ?? ''\n for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_CLIENT_ID: clientId, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {\n if (v === '') throw new Error(`cauthy-auth: ${name} is required to push a theme`)\n }\n const res = await (o.fetch ?? fetch)(`${issuer}/v1/oauth/clients/${encodeURIComponent(clientId)}/theme`, {\n method: 'PUT',\n headers: { authorization: `Bearer ${token}`, 'x-tenant-key': tenant, 'content-type': 'application/json' },\n body: JSON.stringify(toWire(o.theme)),\n })\n if (!res.ok) {\n const body = (await res.json().catch(() => null)) as { errors?: { message?: string }[] } | null\n throw new Error(`cauthy-auth: Cauthy refused the theme (${res.status}): ${body?.errors?.[0]?.message ?? res.statusText}`)\n }\n}\n","// What a sign-in or sign-up form is checked for before anything is sent, in\n// the browser and again on the server: the same rules in both places, so the\n// form says what the server would.\n\nexport type AuthField = 'email' | 'password' | 'newPassword' | 'name' | 'code' | 'organization'\n\n/** A value of a form that cannot be sent as it is. */\nexport interface FieldProblem {\n field: AuthField\n /**\n * Stable, for translating: `required`, `invalid_email`, `too_short`,\n * `too_long`, and for a new password the rule of the workspace it fails:\n * `needs_lowercase`, `needs_uppercase`, `needs_digit`, `needs_symbol`,\n * `needs_classes`.\n */\n code: 'required' | 'invalid_email' | PasswordReason\n message: string\n}\n\n/** The shortest password Cauthy takes by default: a workspace's policy may ask otherwise (`methods().password`). */\nexport const MIN_PASSWORD = 12\n/** The longest: the API bounds what Argon2id is given, whatever the workspace asks. */\nconst MAX_PASSWORD = 128\n/** The shortest any workspace may allow. */\nconst FLOOR_PASSWORD = 8\nconst MAX_NAME = 120\n\n/** A kind of character a workspace's password policy can ask for. */\nexport type PasswordClass = 'lowercase' | 'uppercase' | 'digit' | 'symbol'\n\n/** Why a new password is refused: the API's `weak_password` `meta.reasons`. */\nexport type PasswordReason = 'too_short' | 'too_long' | 'needs_lowercase' | 'needs_uppercase' | 'needs_digit' | 'needs_symbol' | 'needs_classes' | 'breached'\n\n/**\n * What a new password must be in the workspace, as `methods().password` says\n * it. Length is counted in bytes of UTF-8, as Cauthy counts it. A symbol is\n * any character that is neither a letter nor a digit, a space included.\n */\nexport interface PasswordPolicy {\n min: number\n max: number\n /** The kinds the password must each carry at least once. */\n requires: PasswordClass[]\n /** At least this many of the four kinds; 0 asks none. */\n min_classes: number\n /** Cauthy refuses a password found in a published breach (checked by Cauthy alone). */\n reject_breached: boolean\n}\n\nconst CLASSES: PasswordClass[] = ['lowercase', 'uppercase', 'digit', 'symbol']\n\n/** The policy of a workspace that set none: what every one asked before they could choose. */\nexport const DEFAULT_PASSWORD_POLICY: PasswordPolicy = Object.freeze({ min: MIN_PASSWORD, max: MAX_PASSWORD, requires: [], min_classes: 0, reject_breached: false }) as PasswordPolicy\n\nconst int = (v: unknown, fallback: number) => (typeof v === 'number' && Number.isFinite(v) ? Math.trunc(v) : fallback)\n\n/**\n * A password policy as Cauthy sent it — `{ min_length, max_length, … }` from\n * the sign-in settings, or `{ min, max, … }` from `methods()` — made safe to\n * use: the defaults where nothing is said, and never outside 8–128.\n */\nexport function passwordPolicyOf(raw: unknown): PasswordPolicy {\n const r = (raw && typeof raw === 'object' ? raw : {}) as Record<string, unknown>\n const min = Math.min(Math.max(int(r.min ?? r.min_length, MIN_PASSWORD) || MIN_PASSWORD, FLOOR_PASSWORD), MAX_PASSWORD)\n const max = Math.max(Math.min(int(r.max ?? r.max_length, MAX_PASSWORD) || MAX_PASSWORD, MAX_PASSWORD), min)\n const asked = Array.isArray(r.requires) ? r.requires : []\n return {\n min, max,\n requires: CLASSES.filter((c) => asked.includes(c)),\n min_classes: Math.min(Math.max(int(r.min_classes ?? r.minClasses, 0), 0), CLASSES.length),\n reject_breached: (r.reject_breached ?? r.rejectBreached) === true,\n }\n}\n\n/** Bytes of UTF-8: what Cauthy counts a password's length in. */\nfunction utf8Length(v: string): number {\n let n = 0\n for (const ch of v) {\n const c = ch.codePointAt(0)!\n n += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4\n }\n return n\n}\n\n/** Which of the four kinds a password carries, as Cauthy tells them apart. */\nfunction classesOf(v: string): Set<PasswordClass> {\n const has = new Set<PasswordClass>()\n for (const ch of v) {\n if (/\\p{Ll}/u.test(ch)) has.add('lowercase')\n else if (/\\p{Lu}/u.test(ch)) has.add('uppercase')\n else if (/\\p{Nd}/u.test(ch)) has.add('digit')\n else if (!/\\p{L}/u.test(ch)) has.add('symbol') // a letter without case is neither\n }\n return has\n}\n\n/**\n * Every rule of the policy a new password fails, as the API names them;\n * empty when it meets them all. Whether it was in a breach only Cauthy knows.\n */\nexport function passwordProblems(value: string, policy: PasswordPolicy = DEFAULT_PASSWORD_POLICY): PasswordReason[] {\n const p = passwordPolicyOf(policy)\n const out: PasswordReason[] = []\n const length = utf8Length(value)\n if (length < p.min) out.push('too_short')\n if (length > p.max) out.push('too_long')\n const has = classesOf(value)\n for (const c of p.requires) if (!has.has(c)) out.push(`needs_${c}` as PasswordReason)\n if (p.min_classes > 0 && CLASSES.filter((c) => has.has(c)).length < p.min_classes) out.push('needs_classes')\n return out\n}\n\n/** The languages the rule is said in. */\nexport type PasswordLocale = 'en' | 'es'\n\nconst RULES: Record<PasswordLocale, {\n between: string; requires: string; classes: string; breached: string; and: string; kinds: Record<PasswordClass, string>\n reasons: Record<PasswordReason, string>\n}> = {\n en: {\n between: 'Between {min} and {max} characters.', requires: 'Include {kinds}.', and: 'and',\n classes: 'Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.',\n breached: 'Passwords found in known data breaches are not accepted.',\n kinds: { lowercase: 'a lowercase letter', uppercase: 'an uppercase letter', digit: 'a digit', symbol: 'a symbol' },\n reasons: {\n too_short: 'Use at least {min} characters.', too_long: 'Use at most {max} characters.',\n needs_lowercase: 'Include a lowercase letter.', needs_uppercase: 'Include an uppercase letter.', needs_digit: 'Include a digit.', needs_symbol: 'Include a symbol.',\n needs_classes: 'Use at least {n} of these: lowercase letters, uppercase letters, digits, symbols.',\n breached: 'This password appears in a known data breach. Choose a different one.',\n },\n },\n es: {\n between: 'Entre {min} y {max} caracteres.', requires: 'Incluye {kinds}.', and: 'y',\n classes: 'Usa al menos {n} de estos tipos: minúsculas, mayúsculas, números, símbolos.',\n breached: 'No se aceptan contraseñas que aparecen en filtraciones de datos conocidas.',\n kinds: { lowercase: 'una minúscula', uppercase: 'una mayúscula', digit: 'un número', symbol: 'un símbolo' },\n reasons: {\n too_short: 'Usa al menos {min} caracteres.', too_long: 'Usa como máximo {max} caracteres.',\n needs_lowercase: 'Incluye una minúscula.', needs_uppercase: 'Incluye una mayúscula.', needs_digit: 'Incluye un número.', needs_symbol: 'Incluye un símbolo.',\n needs_classes: 'Usa al menos {n} de estos tipos: minúsculas, mayúsculas, números, símbolos.',\n breached: 'Esta contraseña aparece en una filtración de datos conocida. Elige otra.',\n },\n },\n}\n\nconst fill = (s: string, p: PasswordPolicy) => s.replace('{min}', String(p.min)).replace('{max}', String(p.max)).replace('{n}', String(p.min_classes))\n\n/** What a new password must be, said for the person choosing it: \"Between 12 and 128 characters. Include a digit.\" */\nexport function describePasswordPolicy(policy: PasswordPolicy = DEFAULT_PASSWORD_POLICY, locale: PasswordLocale = 'en'): string {\n const p = passwordPolicyOf(policy)\n const t = RULES[locale] ?? RULES.en\n const parts = [fill(t.between, p)]\n if (p.requires.length > 0) {\n const kinds = p.requires.map((c) => t.kinds[c])\n const listed = kinds.length === 1 ? kinds[0] : `${kinds.slice(0, -1).join(', ')} ${t.and} ${kinds[kinds.length - 1]}`\n parts.push(t.requires.replace('{kinds}', listed))\n }\n if (p.min_classes > 0) parts.push(fill(t.classes, p))\n if (p.reject_breached) parts.push(t.breached)\n return parts.join(' ')\n}\n\n/** Why a new password was refused, rule by rule, for the person who typed it. */\nexport function explainPasswordProblems(reasons: readonly string[], policy: PasswordPolicy = DEFAULT_PASSWORD_POLICY, locale: PasswordLocale = 'en'): string {\n const p = passwordPolicyOf(policy)\n const t = RULES[locale] ?? RULES.en\n const said = reasons.filter((r): r is PasswordReason => r in t.reasons).map((r) => fill(t.reasons[r], p))\n return said.length > 0 ? said.join(' ') : describePasswordPolicy(p, locale)\n}\n\n// One @, something on each side, a dot in the domain, no spaces: what catches\n// a typo. Whether the address exists is Cauthy's to find out.\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport function checkEmail(value: unknown): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return { field: 'email', code: 'required', message: 'Enter your email address.' }\n if (v.length > 254 || !EMAIL.test(v)) return { field: 'email', code: 'invalid_email', message: 'That does not look like an email address.' }\n return null\n}\n\n/** A password being typed to sign in: only that there is one. */\nexport function checkPassword(value: unknown): FieldProblem | null {\n if (typeof value !== 'string' || value === '') return { field: 'password', code: 'required', message: 'Enter your password.' }\n if (value.length > MAX_PASSWORD) return { field: 'password', code: 'too_long', message: 'That password is too long.' }\n return null\n}\n\n/**\n * A password being chosen for a new account, or a new one for an account.\n * Held to the workspace's policy when it is given (`methods().password`),\n * otherwise to the defaults: 12 to 128 characters.\n */\nexport function checkNewPassword(value: unknown, policy?: PasswordPolicy | null): FieldProblem | null {\n if (typeof value !== 'string' || value === '') return { field: 'password', code: 'required', message: 'Enter your password.' }\n const p = policy ? passwordPolicyOf(policy) : DEFAULT_PASSWORD_POLICY\n const reasons = passwordProblems(value, p)\n if (reasons.length === 0) return null\n return { field: 'password', code: reasons[0], message: explainPasswordProblems(reasons, p) }\n}\n\nexport function checkName(value: unknown): FieldProblem | null {\n if (value === undefined || value === null || value === '') return null\n if (typeof value !== 'string' || value.trim().length > MAX_NAME) return { field: 'name', code: 'too_long', message: `Use at most ${MAX_NAME} characters.` }\n return null\n}\n\n/** The company's name a sign-up carries when the application's system makes an organization per sign-up. */\nexport const MAX_ORGANIZATION = 120\n\nexport function checkOrganization(value: unknown, required = false): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return required ? { field: 'organization', code: 'required', message: \"Enter your company's name.\" } : null\n if (v.length > MAX_ORGANIZATION) return { field: 'organization', code: 'too_long', message: `Use at most ${MAX_ORGANIZATION} characters.` }\n return null\n}\n\n/** An organization's new name, when a member renames it: the same rule as at sign-up, always required. */\nexport function checkOrganizationName(value: unknown): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return { field: 'name', code: 'required', message: \"Enter the organization's name.\" }\n if (v.length > MAX_ORGANIZATION) return { field: 'name', code: 'too_long', message: `Use at most ${MAX_ORGANIZATION} characters.` }\n return null\n}\n\nexport function checkCode(value: unknown): FieldProblem | null {\n const v = typeof value === 'string' ? value.trim() : ''\n if (v === '') return { field: 'code', code: 'required', message: 'Enter the code.' }\n if (v.length > 40) return { field: 'code', code: 'too_long', message: 'That is not a code.' }\n return null\n}\n\n/** The first problem of a form, or null when it can be sent. */\nexport function firstProblem(...checks: (FieldProblem | null)[]): FieldProblem | null {\n return checks.find((c) => c !== null) ?? null\n}\n","// The application's own sign-in screens, in the browser.\n//\n// const auth = createAuthClient()\n// const r = await auth.signIn.email({ email, password })\n// if (!r.ok) show(r.error.message) // r.error.field says which input\n// else if (r.status === 'mfa_required') askForTheCode()\n//\n// Every call goes to the application's own server (`/api/auth/*`), never to\n// Cauthy: the browser holds no token, before or after. A form is checked here\n// before it is sent, with the rules the server checks again.\n\nimport { canAutofillPasskeys, canUsePasskeys, ceremonyError, getPasskey, makePasskey } from './passkey'\nimport { fromWire, type CauthyTheme } from './theme'\nimport type { CheckQuestion, CheckResult, OrganizationRef, PublicSession } from './types'\nexport type { CheckQuestion, CheckResult, CheckRule, OrganizationRef } from './types'\nimport { checkCode, checkEmail, checkName, checkNewPassword, checkPassword, firstProblem, passwordPolicyOf, type AuthField, type FieldProblem, type PasswordPolicy, checkOrganization, checkOrganizationName } from './validate'\nimport { withoutTrailingSlashes } from './url'\n\nexport { checkCode, checkEmail, checkName, checkNewPassword, checkPassword, describePasswordPolicy, explainPasswordProblems, passwordPolicyOf, passwordProblems, DEFAULT_PASSWORD_POLICY, MIN_PASSWORD, type AuthField, type FieldProblem, type PasswordClass, type PasswordLocale, type PasswordPolicy, type PasswordReason } from './validate'\n\n/** What went wrong, in a form the screen can show. */\nexport interface AuthError {\n /** Stable, for translating: `invalid_credentials`, `invalid_email`, `too_short`, `email_taken`, `unavailable`… */\n code: string\n message: string\n /** The input it is about, when it is about one. */\n field?: AuthField\n /** `weak_password`: the rules of the workspace's password policy it failed (`too_short`, `needs_digit`, …). */\n reasons?: string[]\n}\n\nexport type AuthResult<S extends string, More = unknown> = ({ ok: true; status: S } & More) | { ok: false; error: AuthError }\n\n/** What the screen may offer. */\nexport interface AuthMethods {\n /**\n * The providers the workspace signs people in with and has turned on:\n * `{ id: 'google', name: 'Google', iconUrl: 'https://…/v1/social/icons/google.svg' }`.\n * `iconUrl` is the provider's logo, served by Cauthy; absent from a Cauthy\n * that does not serve logos.\n */\n providers: { id: string; name: string; iconUrl?: string }[]\n /**\n * Whether the workspace signs people in with a password. False: the\n * password field, \"forgot your password\" and a sign-up with a password are\n * not offered, and Cauthy refuses them (`password_disabled`). True from a\n * server that does not say. (`password` is something else: the policy a new\n * password must meet.)\n */\n passwordSignIn: boolean\n /** Whether people may create an account themselves. */\n signUp: boolean\n /** Set when the application's system makes an organization per sign-up: the form asks the company's name. */\n organization?: { ask: boolean; required: boolean }\n magicLink: boolean\n /** Whether to offer a passkey. False when the workspace turned passkeys off. */\n passkey: boolean\n /**\n * Whether the passkey is used on this page itself. False: `signIn.passkey`\n * sends the person to Cauthy's page for that step alone, and they come back\n * signed in. That happens only when this page is outside the domain the\n * workspace's passkeys belong to.\n */\n passkeyHere: boolean\n /**\n * Whether Cauthy's page can use the passkey, for that step alone: where a\n * page that cannot, or a browser that refuses to here, sends the person.\n */\n passkeyOnCauthy: boolean\n /**\n * The workspace's Cloudflare Turnstile site key, when it asks for the\n * challenge: signing in, creating an account, and asking for a sign-in link\n * or a new password then take its answer (`captchaToken`). The ready-made\n * forms show it themselves.\n */\n captchaSiteKey?: string\n /**\n * Whether the workspace signs some people in through their company's SSO,\n * found by their work address (`signIn.ssoDiscover`, `signIn.sso`).\n */\n sso: boolean\n /**\n * Set when the workspace asks something of a sign-up: the legal documents\n * to accept (the terms, the privacy policy: show the links and a box, send\n * `acceptLegal: true`) and the consents to ask (one box each, sent as\n * `consents`; a required one must be ticked). The ready-made form shows them.\n */\n legal?: { documents: { kind: string; version: string; url: string }[]; consentPurposes: { key: string; label: string; required: boolean }[] }\n /**\n * What a new password must be in the workspace. Once `methods()` has\n * answered, this client checks new passwords against it before sending\n * them; until then, against the defaults (12 to 128 characters). Absent\n * from a server that does not say.\n */\n password?: PasswordPolicy\n}\n\n/** An invitation, as its page shows it before the person chooses a password. */\nexport interface Invitation {\n /** The address invited: the account the person signs in as. */\n email: string\n /** The workspace's name. */\n workspace: string\n /** The organization the person was invited to, when there is one. */\n organization?: string\n}\n\n/** A legal document the person owes: not yet accepted in its current version. */\nexport interface PendingLegal { kind: string; version: string; url: string }\n\n/** A company's sign-in (an SSO connection of the workspace). */\nexport interface SSOConnection {\n /** What `signIn.sso({ connection })` takes. */\n id: string\n /** The company's name, for \"Continue with …\". */\n name: string\n /** The address can sign in no other way: a password, link or provider answers `sso_required`. */\n enforced: boolean\n}\n\n/**\n * What holds a passkey, as its authenticator says: a security key (a YubiKey),\n * one synced across the person's devices (iCloud Keychain, Google Password\n * Manager), one on a single device (Windows Hello), or unknown (made before\n * Cauthy kept this).\n */\nexport type PasskeyKind = 'security_key' | 'synced' | 'device' | 'unknown'\n\n/** A passkey of the signed-in account. Moments are UTC. */\nexport interface Passkey {\n id: string\n /** What the person called it (\"My laptop\"), or \"\". */\n name: string\n kind: PasskeyKind\n createdAt: string\n /** When it last signed the person in, or null. */\n lastUsedAt: string | null\n}\n\n/** A person's own account, as their account screen shows it. */\nexport interface Account {\n id: string\n email: string\n name: string\n emailVerified: boolean\n /** False for an account that only signs in through a provider: it has no current password to ask for. */\n hasPassword: boolean\n mfaEnabled: boolean\n}\n\n/** Somewhere the person is signed in. Moments are UTC. */\n/** An AI agent the person allowed to act for them on one of the workspace's servers. */\nexport interface ConnectedAgent {\n id: string\n /** The name the agent gave itself (Claude, Cursor…): not checked by anyone. */\n name: string\n /** Where the agent receives its access: the one thing about it that is sure. */\n redirectHost: string\n resource: { name: string; uri: string }\n /** What the person allowed it, in their words. */\n scopes: { name: string; description: string }[]\n /** UTC, ISO 8601. */\n connectedAt: string\n lastUsedAt: string\n}\n\n/** An organization the person belongs to, with what their role lets them do with it and its people. */\nexport interface OrganizationSeat {\n id: string\n /** The client system it is of (`acme-crm`). */\n system: string\n name: string\n kind: string\n /** The person's role in it. */\n role: string\n /**\n * Cauthy's reserved powers, from the system's catalog. `manageMembers`\n * (cauthy:members:manage) adds, invites and changes roles; removing another\n * member is `removeMembers` (cauthy:members:remove), and anybody may leave.\n * `update`, `archive` and `delete` are cauthy:organization's: rename it,\n * archive it, delete it for good.\n */\n can: { readMembers: boolean; manageMembers: boolean; removeMembers: boolean; update: boolean; archive: boolean; delete: boolean }\n}\n\n/** A person of an organization, as a member who may see them reads it. */\nexport interface OrganizationPerson {\n userId: string\n email: string\n name: string\n role: string\n /** The account's: `active`, `suspended`… A disabled member is still listed. */\n status: string\n /** Invited and not yet accepted. */\n invited: boolean\n /** Manages the organization's members. */\n manager: boolean\n /** The signed-in person. */\n you: boolean\n /** UTC, ISO 8601. */\n since: string\n}\n\n/** A role of the organization's system, as the catalog names it. */\nexport interface OrganizationRoleChoice {\n role: string\n name: string\n description: string\n /** Holding it manages the organization's members. */\n manager: boolean\n}\n\n/**\n * The signed-in person's organizations, and their people. Seeing them needs\n * cauthy:members read in the person's role; changing them needs manage, and\n * removing someone needs remove. The organization itself is renamed, archived\n * or deleted with cauthy:organization update, archive or delete. Only an\n * `owner` gives the owner role or changes an owner, and the last owner stays\n * (`last_owner`). Cauthy decides, with the person's own session: the\n * application authorizes nothing.\n */\nexport interface OrganizationsClient {\n /** The organizations the person belongs to; one system's only with `system`. */\n list(system?: string): Promise<OrganizationSeat[]>\n /** The people of one, or null when the person may not see them. */\n members(organizationId: string): Promise<OrganizationPerson[] | null>\n /** The roles a member may be given, or null when the person may not see them. */\n roles(organizationId: string): Promise<OrganizationRoleChoice[] | null>\n /**\n * Adds a person by their address; an address with no account gets one and\n * its invitation. It only adds: a person who already belongs keeps their\n * role and the result is the error `member_exists` (change it with `setRole`).\n */\n add(organizationId: string, form: { email: string; role: string; name?: string; locale?: string }): Promise<AuthResult<'added', { member: OrganizationPerson }>>\n setRole(organizationId: string, userId: string, role: string): Promise<AuthResult<'changed', { userId: string; role: string }>>\n /** Removes a member; the person themself may always leave. */\n remove(organizationId: string, userId: string): Promise<AuthResult<'removed', { userId: string }>>\n /** Sends a member's invitation again. */\n inviteAgain(organizationId: string, userId: string, form?: { locale?: string }): Promise<AuthResult<'sent', { userId: string }>>\n /** Gives the organization a new name (cauthy:organization update). */\n rename(organizationId: string, name: string): Promise<AuthResult<'renamed', { organization: OrganizationSeat }>>\n /** Archives the organization: its members no longer reach it, and only the workspace restores it. */\n archive(organizationId: string): Promise<AuthResult<'archived', { organizationId: string }>>\n /** Deletes the organization for good. */\n delete(organizationId: string): Promise<AuthResult<'deleted', { organizationId: string }>>\n /**\n * Asks Cauthy, through the application's server, whether the person may do\n * an action on a resource in the organization, with what its conditions\n * read. A question that could not be asked is a no, with `error` saying why.\n *\n * const r = await organizations.check({ organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })\n * if (r.allowed) showApprove()\n */\n check(question: CheckQuestion & { organization: OrganizationRef }): Promise<CheckResult & { error?: AuthError }>\n}\n\nexport interface AccountSession {\n /** \"Mac · Chrome\", or \"\" when the browser did not say. */\n device: string\n ip: string\n createdAt: string\n expiresAt: string\n}\n\n/**\n * The signed-in person's own account. What weakens it — the password, the\n * second step, its recovery codes — asks for the current password again.\n */\n/** A provider the account can also sign in with. */\nexport interface LinkedIdentity {\n provider: string\n /** The address the provider has for the person, when it said. */\n email: string\n name: string\n /** When it was linked, in UTC (ISO 8601). */\n linkedAt: string\n}\n\n/** How an account takes its second step. */\nexport interface SecondStep {\n totp: boolean\n /** The phone codes are sent to, masked (`+57 ••• ••• 4567`). */\n phone: { number: string; channel: string } | null\n /** The ways the workspace sends codes to phones. */\n phoneChannels: string[]\n}\n\nexport interface AccountClient {\n /** The account, or null when nobody is signed in. */\n get(): Promise<Account | null>\n update(form: { name: string }): Promise<AuthResult<'saved', { account: Account }>>\n /** Ends every other session of the account; this one stays signed in. */\n changePassword(form: { password: string; newPassword: string }): Promise<AuthResult<'changed', { signedIn: boolean }>>\n /**\n * The legal documents the person has not accepted in their current version\n * (a new version of the terms, say): show them and call `acceptLegal`.\n * Nothing stops the person meanwhile; the application decides what waits.\n */\n legal(): Promise<AuthResult<'ok', { pending: PendingLegal[] }>>\n /** Records the person's acceptance of the documents in force (the kinds named, or every one). */\n acceptLegal(form?: { kinds?: string[] }): Promise<AuthResult<'accepted'>>\n mfa: {\n /** Starts turning the second step on: show `secret` (or `otpauthUri` as a QR code) to add to an authenticator app, then call `verify`. */\n setup(form: { password: string }): Promise<AuthResult<'started', { secret: string; otpauthUri: string }>>\n /** Turns it on with a code from the app. `recoveryCodes` are shown this once. */\n verify(form: { code: string }): Promise<AuthResult<'enabled', { recoveryCodes: string[] }>>\n disable(form: { password: string }): Promise<AuthResult<'disabled'>>\n /** New recovery codes; the earlier ones stop working. */\n recoveryCodes(form: { password: string }): Promise<AuthResult<'renewed', { recoveryCodes: string[] }>>\n /**\n * How the account takes its second step: an authenticator app, a phone\n * (masked), and the ways the workspace sends codes to phones (`sms`,\n * `whatsapp`; none when it has no Twilio account for it).\n */\n factors(): Promise<SecondStep | null>\n /** Adds a phone as the second step: a code is sent to it, for `verifyPhone`. */\n addPhone(form: { phone: string; channel: 'sms' | 'whatsapp'; password: string }): Promise<AuthResult<'sent', { sentTo: string; channel: string }>>\n /** Proves the phone with the code it received. `recoveryCodes` come with a first second step, shown this once. */\n verifyPhone(form: { code: string }): Promise<AuthResult<'enabled', { recoveryCodes: string[] }>>\n removePhone(form: { password: string }): Promise<AuthResult<'removed'>>\n }\n /**\n * Asks to sign in with another address. Nothing changes yet: the new address\n * is mailed a link to confirm it, and once it is confirmed the old one is\n * told, with a link that undoes it. Both open Cauthy's own page.\n */\n changeEmail(form: { email: string; password: string }): Promise<AuthResult<'sent', { email: string }>>\n /** The providers (Google…) the account can also sign in with. */\n identities(): Promise<LinkedIdentity[]>\n /**\n * Sends the browser to the provider, to link it to the account; it comes back\n * at `returnTo` with `?linked=<provider>`, or `?auth_error=<code>`.\n */\n link(provider: string, options?: { returnTo?: string }): void\n /** Where `link` sends the browser, for a plain link. */\n linkUrl(provider: string, options?: { returnTo?: string }): string\n /** The account stops signing in with that provider. Refused when it would be left with no way to sign in. */\n unlink(provider: string): Promise<AuthResult<'unlinked', { provider: string }>>\n /**\n * A guest becomes an account of their own with an address and a password —\n * the same id, so what they did stays theirs. `email_taken`: the address has\n * an account already; offer to sign in with it.\n */\n upgrade(form: { email: string; password: string; name?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Where a guest goes to become the account of a provider's address (Google…). */\n upgradeUrl(provider: string, options?: { returnTo?: string }): string\n /** Sends a guest to `upgradeUrl`; they come back signed in as the account. */\n upgradeWith(provider: string, options?: { returnTo?: string }): void\n /** Where the account is signed in. */\n sessions(): Promise<AccountSession[]>\n /** Signs the account out everywhere, here too. */\n signOutEverywhere(): Promise<AuthResult<'signed_out'>>\n /** The AI agents the person connected. */\n agents(): Promise<ConnectedAgent[]>\n /** Disconnects an agent: it loses its access within minutes. */\n disconnectAgent(id: string): Promise<AuthResult<'disconnected', { id: string }>>\n /** The account's passkeys. */\n passkeys(): Promise<Passkey[]>\n /**\n * Makes a passkey on this device, on this page: the browser asks the person\n * for their fingerprint, face or screen lock. An account with a password\n * proves it again first. `cancelled`: the person closed the browser's prompt.\n * `kind` sends the browser straight to one: `'device'`, this device's\n * fingerprint, face or screen lock; `'security_key'`, a security key.\n * Without it, the browser offers all.\n */\n addPasskey(form?: { password?: string; name?: string; kind?: 'device' | 'security_key' }): Promise<AuthResult<'added', { passkey: Passkey }>>\n removePasskey(id: string): Promise<AuthResult<'removed', { id: string }>>\n}\n\nexport interface AuthClient {\n signIn: {\n /**\n * A guest session, before the visitor signs up: the application keeps what\n * they do under `session.user.id`, and `account.upgrade` (or\n * `account.upgradeWith`) makes it their account, same id. Only where the\n * workspace allows guests (`anonymous_disabled` otherwise).\n */\n anonymously(form?: { captchaToken?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /**\n * With address and password. `mfa_required`: ask for the code and call\n * `signIn.mfa`. `method: 'email'` says the code was just mailed to the\n * account's address (it has no factor of its own and the workspace, or\n * the sign-in's risk, asked a second step): say so, and offer\n * `mfaSendEmail` for another.\n */\n email(form: { email: string; password: string; captchaToken?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'mfa_required', { method?: 'email' }>>\n /** The second step: the code of the authenticator app, the phone, the email, or a recovery code. */\n mfa(form: { code: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /**\n * While the second step is asked for: whether the account has an\n * authenticator app, the phone (masked) a code can be sent to, phones\n * that approve sign-ins, and the address (masked) a code went to when\n * the step is by email.\n */\n mfaMethods(): Promise<AuthResult<'ok', { totp: boolean; phone: { number: string; channel: string } | null; push: { devices: number } | null; email: { to: string } | null }>>\n /** Mails the sign-in's code again, when its second step is by email; `mfa` takes it. A few per sign-in. */\n mfaSendEmail(): Promise<AuthResult<'sent', { sentTo: string }>>\n /**\n * Sends a push to the account's phones (the application's app, with\n * cauthy-expo): show `number`, which the person picks on the phone, then\n * call `mfaPushWait`.\n */\n mfaPush(): Promise<AuthResult<'sent', { number: number }>>\n /**\n * Waits for the phone's answer, listening (server-sent events) rather than\n * asking again and again, and signs in when it approves. `denied`: turned\n * down on the phone; `expired`: nobody answered in time.\n */\n mfaPushWait(o?: { signal?: AbortSignal }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Sends a code to the account's phone, by SMS or WhatsApp; `mfa` takes it. A few per sign-in. */\n mfaSendCode(): Promise<AuthResult<'sent', { sentTo: string; channel: string }>>\n /**\n * Mails a link (and a code) that signs the person in. The answer is the\n * same whether or not the address has an account. `create`: an address\n * with no account gets one when the link or code is used, if the\n * workspace accepts new accounts — one screen signs people in and up.\n * `returnTo` (a path of this site) travels in the link: the page it opens\n * gets it as `?return_to=`, and `emailCode` answers it.\n */\n magicLink(form: { email: string; captchaToken?: string; create?: boolean; returnTo?: string }): Promise<AuthResult<'sent'>>\n /** Signs in with the token the mailed link opened the page with (`ml_token`). */\n magicLinkVerify(form: { token: string }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Signs in with the code that came in the same mail as the link, for somebody reading it on another device. */\n emailCode(form: { code: string }): Promise<AuthResult<'signed_in', { session: PublicSession; returnTo?: string }>>\n /**\n * Signs in with a passkey, on this page: the browser asks the person for\n * their fingerprint, face or screen lock. When this page cannot use the\n * workspace's passkeys (`methods().passkeyHere` is false), the browser goes\n * to Cauthy's page for that step alone and comes back signed in, at\n * `returnTo`: then the answer is `redirected`. `cancelled`: the person\n * closed the browser's prompt. `email`, when the person typed it: the\n * browser is told which passkeys are theirs, so a security key that did\n * not keep its passkey (one made before cauthy-auth 0.18.0) is found too.\n */\n passkey(options?: { returnTo?: string; locale?: string; email?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'redirected'>>\n /**\n * Offers the person's passkeys in the browser's autofill of the email\n * field, which must carry `autocomplete=\"username webauthn\"`, and signs in\n * with the one they pick. It waits until they pick one or `signal`\n * aborts: abort it before calling `passkey` or sending the form.\n * `cancelled`: aborted, or this browser or page cannot (then there is\n * nothing to offer, and the passkey button still works).\n */\n passkeyAutofill(options?: { signal?: AbortSignal }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /**\n * Google One Tap: Google's prompt over the page offers the Google account\n * the browser already has, and signs in with it in one tap, as the Google\n * sign-in does (the same account). Needs the workspace's Google sign-in,\n * and the page's address among the Google client's authorized JavaScript\n * origins. Waits until the person picks an account or closes the prompt\n * (`cancelled`), or `signal` aborts. `one_tap_unavailable`: the workspace\n * has no Google sign-in.\n */\n googleOneTap(options?: { signal?: AbortSignal; context?: 'signin' | 'signup' | 'use' }): Promise<AuthResult<'signed_in', { session: PublicSession }>>\n /** Where `passkey` sends the browser when this page cannot use the passkey itself. */\n passkeyUrl(options?: { returnTo?: string; locale?: string }): string\n /** Sends the browser to the provider; it comes back signed in, at `returnTo`. */\n social(provider: string, options?: { returnTo?: string }): void\n /**\n * Which company's sign-in a work address uses, if any (`found`), or\n * `none`. It says so of the address's domain, never whether the address\n * has an account.\n */\n ssoDiscover(form: { email: string }): Promise<AuthResult<'found', { connection: SSOConnection }> | AuthResult<'none'>>\n /**\n * Sends the browser to the person's company (found by `email`, or named\n * by `connection`); it comes back signed in, at `returnTo`. A sign-in the\n * company refused comes back with `?auth_error=`. Any other way of\n * signing in answers `sso_required` for an address its company holds to\n * SSO: send it here then.\n */\n sso(target: { email: string } | { connection: string }, options?: { returnTo?: string }): void\n /** Where `sso` sends the browser, for a plain link. */\n ssoUrl(target: { email: string } | { connection: string }, options?: { returnTo?: string }): string\n /** Where `social` sends the browser, for a plain link. */\n socialUrl(provider: string, options?: { returnTo?: string }): string\n }\n signUp: {\n /**\n * `verification_required`: the account exists and must open the link Cauthy mailed before it can sign in.\n * `acceptLegal` and `consents` answer what `methods().legal` asks; a sign-up that leaves them out is refused.\n */\n email(form: { email: string; password: string; name?: string; organization?: string; acceptLegal?: boolean; consents?: Record<string, boolean>; captchaToken?: string }): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'verification_required', { email: string }>>\n }\n /** Mails a link to choose a new password. The answer is the same whether or not the address has an account. */\n forgotPassword(form: { email: string; captchaToken?: string }): Promise<AuthResult<'sent'>>\n /** Sets the new password, with the token the mailed link opened the page with (`token`). */\n resetPassword(form: { token: string; password: string }): Promise<AuthResult<'changed'>>\n /**\n * Who an invitation is for and to what, with the token the mailed link\n * opened the page with (`token`). Reading it does not spend it.\n * `invalid_token`: unknown, spent or expired.\n */\n invitation(token: string): Promise<AuthResult<'ok', { invitation: Invitation }>>\n /**\n * Accepts an invitation with the password the person chose (the workspace's\n * policy, as for a sign-up) and signs them in. `mfa_required`: the account\n * owes a second step; ask for the code and call `signIn.mfa`, as after\n * `signIn.email`. A password refused leaves the invitation good.\n */\n acceptInvitation(token: string, password: string): Promise<AuthResult<'signed_in', { session: PublicSession }> | AuthResult<'mfa_required', { method?: 'email' }>>\n /** Confirms the address a mailed link is for. The person is signed in from the link when their account asks no second step. */\n verifyEmail(form: { token: string }): Promise<AuthResult<'verified'> | AuthResult<'signed_in', { session: PublicSession }>>\n signOut(): Promise<AuthResult<'signed_out'>>\n /** The signed-in person's own account. */\n account: AccountClient\n /** The signed-in person's organizations, and their people. */\n organizations: OrganizationsClient\n /** Who is signed in, or null. */\n getSession(): Promise<PublicSession | null>\n methods(): Promise<AuthMethods>\n /**\n * How the workspace's forms look — colours, corners, typeface — as a person\n * set it in Cauthy's dashboard. Read once per page; null when Cauthy cannot say.\n */\n look(): Promise<CauthyTheme | null>\n}\n\nexport interface AuthClientOptions {\n /** Where the server mounted the routes. Default: `/api/auth`. */\n basePath?: string\n fetch?: typeof fetch\n /**\n * The language the person reads, for what Cauthy mails them (a sign-in\n * link, a new password, a confirmation): a tag like `es` or `es-CO`, or a\n * function that answers it when the person can change it. Default: the\n * page's own (`<html lang>`), else the browser's.\n */\n locale?: string | (() => string | undefined)\n}\n\n/** Google Identity Services, as much of it as One Tap uses. */\ninterface GoogleMoment {\n isNotDisplayed?: () => boolean\n isSkippedMoment?: () => boolean\n isDismissedMoment?: () => boolean\n getDismissedReason?: () => string\n}\ninterface GoogleIdentity {\n initialize(config: Record<string, unknown>): void\n prompt(listener?: (moment: GoogleMoment) => void): void\n cancel(): void\n}\n\nlet googleScript: Promise<GoogleIdentity> | null = null\n\n/** Loads Google's script once per page. */\nfunction loadGoogleIdentity(): Promise<GoogleIdentity> {\n const ready = () => (window as unknown as { google?: { accounts?: { id?: GoogleIdentity } } }).google?.accounts?.id\n if (ready()) return Promise.resolve(ready()!)\n googleScript ??= new Promise<GoogleIdentity>((resolve, reject) => {\n const script = document.createElement('script')\n script.src = 'https://accounts.google.com/gsi/client'\n script.async = true\n script.onload = () => (ready() ? resolve(ready()!) : reject(new Error('google identity services did not load')))\n script.onerror = () => {\n googleScript = null\n reject(new Error('google identity services did not load'))\n }\n document.head.appendChild(script)\n })\n return googleScript\n}\n\n/** How long Cauthy waits for a passkey ceremony to be answered. */\nconst PASSKEY_SECONDS = 300\n\nconst UNAVAILABLE: AuthError = { code: 'unavailable', message: 'Sign-in is unavailable right now. Try again in a moment.' }\n\nexport function createAuthClient(options: AuthClientOptions = {}): AuthClient {\n const base = withoutTrailingSlashes(options.basePath ?? '/api/auth')\n const doFetch: typeof fetch = (...args) => (options.fetch ?? fetch)(...args)\n const locale = (): string => {\n const said = typeof options.locale === 'function' ? options.locale() : options.locale\n return (said ?? (typeof document === 'undefined' ? '' : document.documentElement?.lang) ?? '').trim()\n }\n\n async function post(path: string, form: Record<string, unknown>, bad: FieldProblem | null, captchaToken?: string): Promise<any> {\n if (bad) return { ok: false, error: { code: bad.code, message: bad.message, field: bad.field } }\n try {\n const res = await doFetch(`${base}${path}`, {\n method: 'POST',\n credentials: 'same-origin',\n headers: { 'content-type': 'application/json', accept: 'application/json', ...(locale() ? { 'x-cauthy-locale': locale() } : {}), ...(captchaToken ? { 'x-cauthy-captcha': captchaToken } : {}) },\n body: JSON.stringify(form),\n })\n const body = (await res.json().catch(() => null)) as any\n if (res.ok && body && typeof body.status === 'string') return { ok: true, ...body }\n const e = body?.error\n return { ok: false, error: e && typeof e.code === 'string' ? { code: e.code, message: String(e.message ?? ''), ...(e.field ? { field: e.field } : {}), ...(Array.isArray(e.reasons) ? { reasons: e.reasons.map(String) } : {}) } : UNAVAILABLE }\n } catch {\n return { ok: false, error: UNAVAILABLE }\n }\n }\n\n let looked: Promise<CauthyTheme | null> | undefined\n\n async function read(path: string): Promise<any> {\n try {\n const res = await doFetch(`${base}${path}`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n return res.ok ? await res.json() : null\n } catch {\n return null\n }\n }\n\n const upgradeUrl = (provider: string, o: { returnTo?: string } = {}) =>\n `${base}/me/upgrade/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ''}`\n const linkUrl = (provider: string, o: { returnTo?: string } = {}) =>\n `${base}/me/identities/link/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ''}`\n const socialUrl = (provider: string, o: { returnTo?: string } = {}) =>\n `${base}/sign-in/social/${encodeURIComponent(provider)}${o.returnTo ? `?return_to=${encodeURIComponent(o.returnTo)}` : ''}`\n\n const ssoUrl = (target: { email: string } | { connection: string }, o: { returnTo?: string } = {}) => {\n const q = new URLSearchParams('connection' in target ? { connection: target.connection } : { email: target.email.trim() })\n if (o.returnTo) q.set('return_to', o.returnTo)\n return `${base}/sign-in/sso?${q}`\n }\n\n const passkeyUrl = (o: { returnTo?: string; locale?: string } = {}) => {\n const q = new URLSearchParams({ method: 'passkey' })\n if (o.returnTo) q.set('return_to', o.returnTo)\n if (o.locale) q.set('locale', o.locale)\n return `${base}/login?${q}`\n }\n\n // The workspace's password policy, once methods() has said it.\n let policy: PasswordPolicy | undefined\n\n async function methods(): Promise<AuthMethods> {\n try {\n const res = await doFetch(`${base}/methods`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n if (res.ok) {\n // A server from before the passkey on the page does not say; then it is not.\n const m = (await res.json()) as Partial<AuthMethods>\n // The workspace's password rule, for the checks before a password is sent.\n if (m.password) policy = passwordPolicyOf(m.password)\n return { providers: [], signUp: true, magicLink: false, passkey: false, ...m, ...(policy ? { password: policy } : {}), passwordSignIn: m.passwordSignIn !== false, passkeyHere: m.passkeyHere === true, passkeyOnCauthy: m.passkeyOnCauthy ?? m.passkey === true, sso: m.sso === true }\n }\n } catch {\n // falls through\n }\n return { providers: [], signUp: true, passwordSignIn: true, magicLink: false, passkey: false, passkeyHere: false, passkeyOnCauthy: false, sso: false }\n }\n\n /** The two steps of a ceremony: what to ask the browser, then its answer. */\n async function ceremony(begin: string, finish: string, form: Record<string, unknown>, run: (options: any) => Promise<Record<string, unknown>>, more: Record<string, unknown> = {}): Promise<any> {\n const begun = await post(begin, form, null)\n if (!begun.ok) return begun\n let credential: Record<string, unknown>\n try {\n credential = await run(begun.options)\n } catch (e) {\n return { ok: false, error: ceremonyError(e) }\n }\n return post(finish, { credential, ...more }, null)\n }\n\n return {\n signIn: {\n anonymously: (f = {}) => post('/sign-in/anonymous', {}, null, f.captchaToken),\n email: (f) => post('/sign-in/email', { email: f.email, password: f.password }, firstProblem(checkEmail(f.email), checkPassword(f.password)), f.captchaToken),\n mfa: (f) => post('/sign-in/mfa', { code: f.code }, checkCode(f.code)),\n mfaMethods: () => post('/sign-in/mfa/methods', {}, null),\n mfaSendCode: () => post('/sign-in/mfa/send', {}, null),\n mfaSendEmail: () => post('/sign-in/mfa/email', {}, null),\n mfaPush: () => post('/sign-in/mfa/push', {}, null),\n async mfaPushWait(o = {}) {\n const status = await new Promise<string>((resolve) => {\n if (typeof EventSource !== 'function') return resolve('approved') // finish says whether it was\n const source = new EventSource(`${base}/sign-in/mfa/push/events`, { withCredentials: true })\n const stop = (st: string) => {\n source.close()\n resolve(st)\n }\n o.signal?.addEventListener('abort', () => stop('aborted'))\n source.addEventListener('status', (e) => {\n const st = (() => {\n try {\n return String(JSON.parse((e as MessageEvent).data).status)\n } catch {\n return ''\n }\n })()\n if (st && st !== 'pending') stop(st)\n })\n source.onerror = () => {\n if (source.readyState === EventSource.CLOSED) stop('expired')\n }\n })\n if (status === 'aborted') return { ok: false, error: { code: 'aborted', message: 'Stopped waiting.' } }\n if (status === 'denied') return { ok: false, error: { code: 'push_denied', message: 'The sign-in was turned down on the phone.' } }\n if (status === 'expired') return { ok: false, error: { code: 'push_expired', message: 'Nobody answered on the phone in time.' } }\n return post('/sign-in/mfa/push/finish', {}, null)\n },\n magicLink: (f) => post('/sign-in/magic-link', { email: f.email, ...(f.create ? { create: true } : {}), ...(f.returnTo ? { returnTo: f.returnTo } : {}) }, checkEmail(f.email), f.captchaToken),\n magicLinkVerify: (f) => post('/sign-in/magic-link/verify', { token: f.token }, null),\n emailCode: (f) => post('/sign-in/email-code', { code: f.code }, checkCode(f.code)),\n passkeyUrl,\n async passkey(o) {\n const m = await methods()\n if (m.passkeyHere && canUsePasskeys()) {\n const email = o?.email?.trim() ?? ''\n const r = await ceremony('/sign-in/passkey/begin', '/sign-in/passkey/finish', email !== '' && checkEmail(email) === null ? { email } : {}, getPasskey)\n // A browser that does not read the domain's related origins refuses\n // this page: Cauthy's, then, when it can.\n if (r.ok || r.error.code !== 'passkey_unavailable' || !m.passkeyOnCauthy) return r\n } else if (!m.passkeyOnCauthy) {\n return { ok: false, error: { code: 'passkey_unavailable', message: 'Passkeys cannot be used here.' } }\n }\n window.location.assign(passkeyUrl(o))\n return { ok: true, status: 'redirected' }\n },\n async passkeyAutofill(o = {}) {\n const cancelled = { ok: false as const, error: { code: 'cancelled', message: 'No passkey was chosen.' } }\n const m = await methods()\n if (!m.passkeyHere || !(await canAutofillPasskeys())) return cancelled\n for (;;) {\n if (o.signal?.aborted) return cancelled\n const begun = await post('/sign-in/passkey/begin', {}, null)\n if (!begun.ok) return begun\n // Cauthy's challenge lives five minutes: a page left open asks for\n // a fresh one before it runs out.\n const renew = new AbortController()\n const stop = () => renew.abort()\n o.signal?.addEventListener('abort', stop, { once: true })\n const timer = setTimeout(stop, (PASSKEY_SECONDS - 30) * 1000)\n let credential: Record<string, unknown>\n try {\n credential = await getPasskey(begun.options, { mediation: 'conditional', signal: renew.signal })\n } catch (e) {\n if (o.signal?.aborted) return cancelled\n if (renew.signal.aborted) continue\n return { ok: false, error: ceremonyError(e) }\n } finally {\n clearTimeout(timer)\n o.signal?.removeEventListener('abort', stop)\n }\n return post('/sign-in/passkey/finish', { credential }, null)\n }\n },\n async googleOneTap(o = {}) {\n const cancelled = { ok: false as const, error: { code: 'cancelled', message: 'No Google account was chosen.' } }\n if (typeof window === 'undefined' || o.signal?.aborted) return cancelled\n const begun = await post('/sign-in/google-one-tap/begin', {}, null)\n if (!begun.ok) return begun\n let gis: GoogleIdentity\n try {\n gis = await loadGoogleIdentity()\n } catch {\n return { ok: false, error: { code: 'unavailable', message: 'Google could not be reached. Try again, or sign in another way.' } }\n }\n const credential = await new Promise<string | null>((done) => {\n o.signal?.addEventListener('abort', () => {\n gis.cancel()\n done(null)\n }, { once: true })\n gis.initialize({\n client_id: begun.clientId, nonce: begun.nonce, context: o.context ?? 'signin',\n callback: (r: { credential?: string }) => done(r.credential ?? null),\n auto_select: false, cancel_on_tap_outside: true, itp_support: true, use_fedcm_for_prompt: true,\n })\n gis.prompt((moment: GoogleMoment) => {\n // The prompt was not shown, or the person closed it.\n if (moment.isNotDisplayed?.() || moment.isSkippedMoment?.()) done(null)\n else if (moment.isDismissedMoment?.() && moment.getDismissedReason?.() !== 'credential_returned') done(null)\n })\n })\n if (credential === null) return cancelled\n return post('/sign-in/google-one-tap', { credential }, null)\n },\n socialUrl,\n social(provider, o) {\n window.location.assign(socialUrl(provider, o))\n },\n ssoDiscover: (f) => post('/sign-in/sso/discover', { email: f.email.trim() }, checkEmail(f.email)),\n ssoUrl,\n sso(target, o) {\n window.location.assign(ssoUrl(target, o))\n },\n },\n signUp: {\n email: (f) => post('/sign-up/email', { email: f.email, password: f.password, name: f.name, organization: f.organization, acceptLegal: f.acceptLegal, consents: f.consents },\n firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy), checkOrganization(f.organization)), f.captchaToken),\n },\n forgotPassword: (f) => post('/forgot-password', { email: f.email }, checkEmail(f.email), f.captchaToken),\n resetPassword: (f) => post('/reset-password', { token: f.token, password: f.password }, checkNewPassword(f.password, policy)),\n verifyEmail: (f) => post('/verify-email', { token: f.token }, null),\n async invitation(token) {\n const bad = { ok: false as const, error: { code: 'invalid_token', message: 'This invitation is not valid, or it has expired.' } }\n if (typeof token !== 'string' || token.trim() === '') return bad\n try {\n const res = await doFetch(`${base}/invitation?token=${encodeURIComponent(token.trim())}`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n const body = (await res.json().catch(() => null)) as any\n if (res.ok && body?.invitation) return { ok: true as const, status: 'ok' as const, invitation: body.invitation as Invitation }\n const e = body?.error\n return { ok: false as const, error: e && typeof e.code === 'string' ? { code: e.code, message: String(e.message ?? '') } : UNAVAILABLE }\n } catch {\n return { ok: false as const, error: UNAVAILABLE }\n }\n },\n acceptInvitation: (token, password) => post('/invitation/accept', { token, password }, checkNewPassword(password, policy)),\n signOut: () => post('/sign-out', {}, null),\n organizations: {\n async list(system) {\n const body = await read(`/me/organizations${system ? `?system=${encodeURIComponent(system)}` : ''}`)\n return body && Array.isArray(body.organizations) ? (body.organizations as OrganizationSeat[]) : []\n },\n async members(id) {\n const body = await read(`/me/organizations/members?id=${encodeURIComponent(id)}`)\n return body && Array.isArray(body.members) ? (body.members as OrganizationPerson[]) : null\n },\n async roles(id) {\n const body = await read(`/me/organizations/roles?id=${encodeURIComponent(id)}`)\n return body && Array.isArray(body.roles) ? (body.roles as OrganizationRoleChoice[]) : null\n },\n add: (id, f) => post('/me/organizations/members/add', { organizationId: id, email: f.email, role: f.role, name: f.name ?? '', locale: f.locale ?? '' }, checkEmail(f.email)),\n setRole: (id, userId, role) => post('/me/organizations/members/role', { organizationId: id, userId, role }, null),\n remove: (id, userId) => post('/me/organizations/members/remove', { organizationId: id, userId }, null),\n inviteAgain: (id, userId, f = {}) => post('/me/organizations/members/invite', { organizationId: id, userId, locale: f.locale ?? '' }, null),\n rename: (id, name) => post('/me/organizations/rename', { organizationId: id, name }, checkOrganizationName(name)),\n archive: (id) => post('/me/organizations/archive', { organizationId: id }, null),\n delete: (id) => post('/me/organizations/delete', { organizationId: id }, null),\n async check(q) {\n const organizationId = typeof q.organization === 'string' ? q.organization : (q.organization?.id ?? '')\n const r = await post('/me/organizations/check', {\n organizationId, resource: q.resource, action: q.action,\n ...(q.attributes !== undefined ? { attributes: q.attributes } : {}),\n ...(q.resourceId !== undefined ? { resourceId: q.resourceId } : {}),\n ...(q.ownerId !== undefined ? { ownerId: q.ownerId } : {}),\n }, null)\n if (!r.ok) return { allowed: false, reason: r.error.message, error: r.error }\n return { allowed: r.allowed === true, reason: String(r.reason ?? ''), ...(r.rule ? { rule: r.rule } : {}) }\n },\n },\n account: {\n async get() {\n const body = await read('/me')\n return body && typeof body.account === 'object' ? (body.account as Account) : null\n },\n update: (f) => post('/me', { name: f.name }, checkName(f.name)),\n async legal() {\n const body = await read('/me/legal')\n if (!body) return { ok: false as const, error: { code: 'not_signed_in', message: 'Nobody is signed in.' } }\n return { ok: true as const, status: 'ok' as const, pending: Array.isArray(body.pending) ? body.pending : [] }\n },\n acceptLegal: (f = {}) => post('/me/legal/accept', { kinds: f.kinds ?? [] }, null),\n changePassword: (f) => {\n const bad = checkNewPassword(f.newPassword, policy)\n return post('/me/password', { password: f.password, newPassword: f.newPassword }, bad ? { ...bad, field: 'newPassword' } : null)\n },\n mfa: {\n setup: (f) => post('/me/mfa/setup', { password: f.password }, null),\n verify: (f) => post('/me/mfa/verify', { code: f.code }, checkCode(f.code)),\n disable: (f) => post('/me/mfa/disable', { password: f.password }, null),\n recoveryCodes: (f) => post('/me/mfa/recovery-codes', { password: f.password }, null),\n async factors() {\n const body = await read('/me/mfa/factors')\n return body && typeof body.totp === 'boolean' ? (body as SecondStep) : null\n },\n addPhone: (f) => post('/me/mfa/phone', { phone: f.phone, channel: f.channel, password: f.password }, null),\n verifyPhone: (f) => post('/me/mfa/phone/verify', { code: f.code }, checkCode(f.code)),\n removePhone: (f) => post('/me/mfa/phone/remove', { password: f.password }, null),\n },\n changeEmail: (f) => post('/me/email', { email: f.email, password: f.password }, checkEmail(f.email)),\n async identities() {\n const body = await read('/me/identities')\n return body && Array.isArray(body.identities) ? (body.identities as LinkedIdentity[]) : []\n },\n linkUrl,\n link(provider, o) {\n window.location.assign(linkUrl(provider, o))\n },\n unlink: (provider) => post('/me/identities/unlink', { provider }, null),\n async sessions() {\n const body = await read('/me/sessions')\n return body && Array.isArray(body.sessions) ? (body.sessions as AccountSession[]) : []\n },\n signOutEverywhere: () => post('/me/sessions/end', {}, null),\n upgrade: (f) => post('/me/upgrade', { email: f.email, password: f.password, name: f.name ?? '' }, firstProblem(checkName(f.name), checkEmail(f.email), checkNewPassword(f.password, policy))),\n upgradeUrl,\n upgradeWith(provider, o) {\n window.location.assign(upgradeUrl(provider, o))\n },\n async agents() {\n const body = await read('/me/agents')\n return body && Array.isArray(body.agents) ? (body.agents as ConnectedAgent[]) : []\n },\n disconnectAgent: (id) => post('/me/agents/disconnect', { id }, null),\n async passkeys() {\n const body = await read('/me/passkeys')\n return body && Array.isArray(body.passkeys) ? (body.passkeys as Passkey[]) : []\n },\n addPasskey(f = {}) {\n if (!canUsePasskeys()) return Promise.resolve({ ok: false, error: { code: 'passkey_unavailable', message: 'This browser cannot make passkeys.' } })\n return ceremony('/me/passkeys/add/begin', '/me/passkeys/add/finish', { password: f.password ?? '', ...(f.kind ? { kind: f.kind } : {}) }, makePasskey, { name: f.name ?? '' })\n },\n removePasskey: (id) => post('/me/passkeys/remove', { id }, null),\n },\n async getSession() {\n try {\n const res = await doFetch(`${base}/session`, { credentials: 'same-origin', headers: { accept: 'application/json' } })\n if (!res.ok) return null\n return ((await res.json()) as { session: PublicSession | null }).session\n } catch {\n return null\n }\n },\n look() {\n looked ??= read('/look').then((wire) => (wire && typeof wire === 'object' ? fromWire(wire) : null))\n return looked\n },\n methods,\n }\n}\n\nexport { canAutofillPasskeys, canUsePasskeys } from './passkey'\nexport { createSessionStore, type SessionState, type SessionStore, type SessionStoreOptions } from './store'\n","// What a person may do in an organization.\n//\n// When a system keeps its catalog of roles in Cauthy, each of a person's\n// organizations arrives with what their role — and anything given or denied to\n// them apart from it — lets them do. Checking is a lookup in that list: no\n// call to Cauthy, on the server or in the browser.\n\nimport type { CheckQuestion, CheckResult, CheckRule, ConditionalPermission, OrganizationRef } from './types'\nimport { withoutTrailingSlashes } from './url'\n\n/** The part of an organization that says what its member may do. */\nexport interface Permitted {\n /** \"resource:action\" entries the person is allowed; \"*\" is any. Absent when the system keeps no catalog in Cauthy. */\n permissions?: string[]\n /** Entries the person is denied whatever else allows them. */\n denied?: string[]\n /** Permissions with a condition: in neither list, so `can` never counts them. Ask with `auth.check`. */\n conditional?: ConditionalPermission[]\n}\n\nfunction matches(entry: string, resource: string, action: string): boolean {\n // The resource may itself hold a colon: the action is what follows the last one.\n const i = entry.lastIndexOf(':')\n if (i < 0) return false\n const r = entry.slice(0, i)\n const a = entry.slice(i + 1)\n return (r === '*' || r === resource) && (a === '*' || a === action)\n}\n\n/**\n * Whether the person may do an action on a resource in an organization:\n * allowed by some entry, and denied by none. A denial wins.\n *\n * An organization of a system that keeps no catalog in Cauthy carries no\n * permissions, and the answer is `false`: decide by its `role` instead.\n *\n * A permission with a condition (`organization.conditional`) is not in the\n * lists, so `can` answers `false` for what only it allows: the condition reads\n * the record at hand, which only Cauthy can weigh. Ask with `auth.check`\n * (`organizations.check` in the browser).\n *\n * if (!can(organization, 'invoicing', 'write')) return forbidden()\n */\nexport function can(organization: Permitted | null | undefined, resource: string, action: string): boolean {\n if (!organization?.permissions) return false\n if ((organization.denied ?? []).some((d) => matches(d, resource, action))) return false\n return organization.permissions.some((p) => matches(p, resource, action))\n}\n\n// ── A system's catalog of roles ────────────────────────────────────────────\n\n/** Something a role may do: an action on a resource, in organizations of a kind (\"*\", the default, is every kind). */\nexport interface PolicyPermission {\n kind?: string\n resource: string\n action: string\n /**\n * When it holds, in CEL: `resource.attrs.amount <= 1000000`. A permission\n * with one is decided by Cauthy per question (`auth.check`), never by `can`.\n */\n condition?: string\n}\n\n/** The type of an attribute a condition may read: `list` is any JSON array. */\nexport type AttributeType = 'string' | 'number' | 'bool' | 'list'\n\n/** A resource of a system's catalog: the actions done on it and the attributes its conditions read. */\nexport interface CatalogResource {\n resource: string\n description?: string\n actions: string[]\n /** Name → type, as `resource.attrs.<name>` in a condition. */\n attributes?: Record<string, AttributeType>\n}\n\nexport interface PolicyRole {\n role: string\n name?: string\n description?: string\n /** Roles whose permissions this one has as well. */\n inherits?: string[]\n permissions?: PolicyPermission[]\n}\n\n// ── The catalog, with its types ────────────────────────────────────────────\n//\n// A catalog written down once gives the roles and the permissions their\n// names: `can(org, 'ledger:write')` then takes only a permission the catalog\n// has, the editor offers them, and a typo does not compile.\n//\n// export const policy = definePolicy([\n// { role: 'reader', permissions: [{ resource: 'ledger', action: 'read' }] },\n// { role: 'accountant', inherits: ['reader'], permissions: [{ resource: 'ledger', action: 'write' }] },\n// ])\n// export const { can, hasRole } = policy\n//\n// can(organization, 'ledger:write') // 'ledger:wirte' does not compile\n// hasRole(organization, 'accountant')\n//\n// A system that declares its resources gives them too, with their actions and\n// the attributes a condition reads, and a check is typed by them:\n//\n// export const policy = definePolicy({\n// catalog: [{ resource: 'invoices', actions: ['read', 'approve'], attributes: { amount: 'number' } }],\n// roles: [{ role: 'accountant', permissions: [{ resource: 'invoices', action: 'approve', condition: 'resource.attrs.amount <= 1000' }] }],\n// })\n//\n// await policy.check(auth, request, { organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })\n//\n// Write it by hand, or let `cauthy-auth policy --pull` write it from the\n// catalog Cauthy has.\n\ntype PermissionShape = { readonly kind?: string; readonly resource: string; readonly action: string; readonly condition?: string }\n\n/** A role as `definePolicy` reads it: any `PolicyRole`, kept as written. */\ntype RoleShape = {\n readonly role: string\n readonly name?: string\n readonly description?: string\n readonly inherits?: readonly string[]\n readonly permissions?: readonly PermissionShape[]\n}\n\n/** A resource as `definePolicy` reads it: any `CatalogResource`, kept as written. */\ntype ResourceShape = {\n readonly resource: string\n readonly description?: string\n readonly actions: readonly string[]\n readonly attributes?: { readonly [name: string]: AttributeType }\n}\n\n// \"*\" in a catalog is \"any\": the name it stands for is any text.\ntype Named<S extends string> = S extends '*' ? string : S\n\ntype PermissionsIn<R> = R extends { readonly permissions: readonly (infer P)[] }\n ? P extends { readonly resource: infer Res extends string; readonly action: infer Act extends string } ? `${Named<Res>}:${Named<Act>}` : never\n : never\n\ntype ValueOf<T> = T extends 'string' ? string : T extends 'number' ? number : T extends 'bool' ? boolean : T extends 'list' ? unknown[] : never\n\n/** What a check may say about one declared resource. */\ntype QuestionAbout<E> = E extends { readonly resource: infer R extends string; readonly actions: readonly (infer A extends string)[] }\n ? {\n resource: R\n action: A\n attributes?: E extends { readonly attributes: infer T } ? { [K in keyof T]?: ValueOf<T[K]> } : Record<string, never>\n resourceId?: string\n ownerId?: string\n }\n : never\n\n/**\n * What a role of a catalog that declares its resources may name: a declared\n * resource with one of its actions, or \"*\", or one of Cauthy's own powers.\n */\ntype PermissionFor<C extends readonly ResourceShape[]> = { readonly kind?: string; readonly condition?: string } & (\n | (C[number] extends infer E ? E extends { readonly resource: infer R extends string; readonly actions: readonly (infer A extends string)[] } ? { readonly resource: R; readonly action: A | '*' } : never : never)\n | { readonly resource: '*'; readonly action: string }\n | { readonly resource: `cauthy:${string}`; readonly action: string }\n)\ntype RoleFor<C extends readonly ResourceShape[]> = Omit<RoleShape, 'permissions'> & { readonly permissions?: readonly PermissionFor<C>[] }\n\n/** The roles a catalog names: `RoleOf<typeof policy>`. */\nexport type RoleOf<P> = P extends Policy<infer R, any, any> ? R : never\n/** The \"resource:action\" permissions a catalog names: `PermissionOf<typeof policy>`. */\nexport type PermissionOf<P> = P extends Policy<any, infer X, any> ? X : never\n/** What a check about this catalog may ask: `CheckOf<typeof policy>`. Any resource when it declares none. */\nexport type CheckOf<P> = P extends Policy<any, any, infer Q> ? Q : never\n\n/** The fields of a question: whatever else the asker takes (the organization, the person) passes through. */\ntype QuestionKeys = keyof CheckQuestion\n\nexport interface Policy<Role extends string = string, Permission extends string = string, Question extends CheckQuestion = CheckQuestion> {\n /** The catalog as Cauthy takes it: `pushPolicy({ roles: policy.roles })`. */\n roles: PolicyRole[]\n /** The resources the system declares, as Cauthy takes them; empty when it declares none. */\n catalog: CatalogResource[]\n /** Every role's name. */\n roleNames: Role[]\n /** Every permission some role has, as \"resource:action\". */\n permissions: Permission[]\n /**\n * Whether the person may do this in the organization: `can(org, 'ledger:write')`.\n * It reads what Cauthy sent with the session, so a catalog edited in Cauthy\n * since this file was written is still what decides. A permission with a\n * condition is not there: ask with `check`.\n */\n can(organization: Permitted | null | undefined, permission: Permission): boolean\n /** Whether the person's role in the organization is one of these. */\n hasRole(organization: { role: string } | null | undefined, ...roles: Role[]): boolean\n /**\n * What a role may do by this catalog, with what it inherits: for showing a\n * role, never for deciding about a person (their exceptions are not here).\n */\n permissionsOf(role: Role): Permission[]\n /**\n * Asks Cauthy, with the resource, action and attributes typed by the\n * catalog. Give it whoever asks: the server's `auth` with the request,\n * the browser's `organizations`, or the application's `system`.\n *\n * await policy.check(auth, request, { organization, resource: 'invoices', action: 'approve', attributes: { amount: 500 } })\n * await policy.check(auth.system, { organizationId, userId, resource: 'invoices', action: 'read' })\n */\n check<I extends CheckQuestion>(asker: { check(input: I): Promise<CheckResult> }, input: Omit<I, QuestionKeys> & Question): Promise<CheckResult>\n check<R, I extends CheckQuestion>(asker: { check(request: R, input: I): Promise<CheckResult> }, request: R, input: Omit<I, QuestionKeys> & Question): Promise<CheckResult>\n}\n\n/** A catalog with its resources declared, for `definePolicy`. */\nexport interface PolicyDefinition<C extends readonly ResourceShape[], T extends readonly RoleShape[]> {\n catalog: C\n roles: T\n}\n\n/** Gives a catalog of roles its types. See the top of this section. */\nexport function definePolicy<const T extends readonly RoleShape[]>(roles: T): Policy<T[number]['role'], PermissionsIn<T[number]>>\n/** Gives a catalog of resources and roles its types: a role names only what the catalog declares. */\nexport function definePolicy<const C extends readonly ResourceShape[], const T extends readonly RoleFor<C>[]>(\n definition: PolicyDefinition<C, T>,\n): Policy<T[number]['role'], PermissionsIn<T[number]>, QuestionAbout<C[number]>>\nexport function definePolicy(given: readonly RoleShape[] | PolicyDefinition<readonly ResourceShape[], readonly RoleShape[]>): Policy {\n const roles: readonly RoleShape[] = Array.isArray(given) ? given : (given as PolicyDefinition<readonly ResourceShape[], readonly RoleShape[]>).roles\n const resources: readonly ResourceShape[] = Array.isArray(given) ? [] : (given as PolicyDefinition<readonly ResourceShape[], readonly RoleShape[]>).catalog ?? []\n const entry = (p: { resource: string; action: string }) => `${p.resource}:${p.action}`\n const byName = new Map(roles.map((r) => [r.role, r]))\n const split = (permission: string): [string, string] => {\n const i = permission.lastIndexOf(':')\n return i < 0 ? [permission, ''] : [permission.slice(0, i), permission.slice(i + 1)]\n }\n return {\n roles: roles.map((r) => ({\n role: r.role,\n ...(r.name !== undefined ? { name: r.name } : {}),\n ...(r.description !== undefined ? { description: r.description } : {}),\n ...(r.inherits ? { inherits: [...r.inherits] } : {}),\n ...(r.permissions ? { permissions: r.permissions.map((p) => ({ ...p })) } : {}),\n })),\n catalog: resources.map((c) => ({\n resource: c.resource,\n ...(c.description !== undefined ? { description: c.description } : {}),\n actions: [...c.actions],\n ...(c.attributes ? { attributes: { ...c.attributes } } : {}),\n })),\n roleNames: roles.map((r) => r.role),\n permissions: [...new Set(roles.flatMap((r) => (r.permissions ?? []).map(entry)))],\n can(organization, permission) {\n const [resource, action] = split(permission)\n return can(organization, resource, action)\n },\n hasRole(organization, ...wanted) {\n return organization != null && wanted.includes(organization.role)\n },\n permissionsOf(role) {\n const seen = new Set<string>()\n const out = new Set<string>()\n const walk = (name: string) => {\n if (seen.has(name)) return // a catalog that inherits in a circle still ends\n seen.add(name)\n const r = byName.get(name)\n for (const p of r?.permissions ?? []) out.add(entry(p))\n for (const parent of r?.inherits ?? []) walk(parent)\n }\n walk(role)\n return [...out]\n },\n // The types did the work; this only hands the question on, as a method of\n // the asker so it keeps its `this`.\n check(asker: { check(...args: unknown[]): Promise<CheckResult> }, ...args: unknown[]) {\n return asker.check(...args)\n },\n }\n}\n\nconst IDENT = /^[A-Za-z_$][A-Za-z0-9_$]*$/\n\n/** A system's policy as Cauthy has it: the resources it declares (maybe none) and its roles. */\nexport interface SystemPolicy {\n catalog: CatalogResource[]\n roles: PolicyRole[]\n}\n\n/**\n * A TypeScript module that defines the catalog given, for `cauthy-auth policy\n * --pull` to write: the application's types then come from the catalog\n * Cauthy has. With resources declared it is `definePolicy({ catalog, roles })`;\n * without, the list of roles alone, as it always was.\n */\nexport function policySource(system: string, read: PolicyRole[] | { catalog?: CatalogResource[]; roles: PolicyRole[] }): string {\n const roles = Array.isArray(read) ? read : read.roles\n const catalog = Array.isArray(read) ? [] : (read.catalog ?? [])\n const text = (v: string) => JSON.stringify(v)\n const key = (k: string) => (IDENT.test(k) ? k : text(k))\n const one = (r: PolicyRole, pad: string) => {\n const parts = [`role: ${text(r.role)}`]\n if (r.name) parts.push(`name: ${text(r.name)}`)\n if (r.description) parts.push(`description: ${text(r.description)}`)\n if (r.inherits?.length) parts.push(`inherits: [${r.inherits.map(text).join(', ')}]`)\n if (r.permissions?.length) {\n const list = r.permissions.map((p) => `${pad} { ${[\n ...(p.kind && p.kind !== '*' ? [`${key('kind')}: ${text(p.kind)}`] : []),\n `resource: ${text(p.resource)}`,\n `action: ${text(p.action)}`,\n ...(p.condition ? [`condition: ${text(p.condition)}`] : []),\n ].join(', ')} },`)\n parts.push(`permissions: [\\n${list.join('\\n')}\\n${pad} ]`)\n }\n return `${pad} {\\n${pad} ${parts.join(`,\\n${pad} `)},\\n${pad} },`\n }\n const resource = (c: CatalogResource) => {\n const parts = [`resource: ${text(c.resource)}`]\n if (c.description) parts.push(`description: ${text(c.description)}`)\n parts.push(`actions: [${c.actions.map(text).join(', ')}]`)\n const attrs = Object.entries(c.attributes ?? {})\n if (attrs.length) parts.push(`attributes: { ${attrs.map(([k, v]) => `${key(k)}: ${text(v)}`).join(', ')} }`)\n return ` { ${parts.join(', ')} },`\n }\n const head = `// The catalog of roles of ${text(system)}, as Cauthy has it.\n// Written by \\`cauthy-auth policy --pull\\`: run it again after the catalog\n// changes, and do not edit this file by hand.\n`\n if (catalog.length === 0) {\n return `${head}\nimport { definePolicy, type PermissionOf, type RoleOf } from 'cauthy-auth'\n\nexport const policy = definePolicy([\n${roles.map((r) => one(r, '')).join('\\n')}\n])\n\nexport const { can, hasRole } = policy\nexport type Role = RoleOf<typeof policy>\nexport type Permission = PermissionOf<typeof policy>\n`\n }\n return `${head}\nimport { definePolicy, type CheckOf, type PermissionOf, type RoleOf } from 'cauthy-auth'\n\nexport const policy = definePolicy({\n catalog: [\n${catalog.map(resource).join('\\n')}\n ],\n roles: [\n${roles.map((r) => one(r, ' ')).join('\\n')}\n ],\n})\n\nexport const { can, hasRole } = policy\nexport type Role = RoleOf<typeof policy>\nexport type Permission = PermissionOf<typeof policy>\n/** What a check may ask: \\`policy.check(auth, request, { organization, ...question })\\`. */\nexport type Check = CheckOf<typeof policy>\n`\n}\n\n/** Who reads or writes a system's policy: Cauthy's address, the workspace, a person's token. */\ninterface Reach {\n issuer: string\n system: string\n tenant: string\n token: string\n fetch: typeof fetch\n}\n\nfunction reach(o: Omit<PushPolicyOptions, 'roles'>, doing: string): Reach {\n const env = (n: string) => (typeof process !== 'undefined' ? process.env?.[n] : undefined)\n const r = {\n issuer: withoutTrailingSlashes(o.issuer ?? env('CAUTHY_ISSUER') ?? ''),\n system: o.system ?? env('CAUTHY_SYSTEM') ?? '',\n tenant: o.tenant ?? env('CAUTHY_TENANT') ?? '',\n token: o.token ?? env('CAUTHY_TOKEN') ?? '',\n }\n for (const [name, v] of Object.entries({ CAUTHY_ISSUER: r.issuer, CAUTHY_SYSTEM: r.system, CAUTHY_TENANT: r.tenant, CAUTHY_TOKEN: r.token })) {\n if (v === '') throw new Error(`cauthy-auth: ${name} is required to ${doing}`)\n }\n return { ...r, fetch: o.fetch ?? fetch }\n}\n\nasync function systemCall(r: Reach, method: 'GET' | 'PUT', what: 'policy' | 'catalog', body?: unknown): Promise<any> {\n const res = await r.fetch(`${r.issuer}/v1/systems/${encodeURIComponent(r.system)}/${what}`, {\n ...(method === 'PUT' ? { method } : {}),\n headers: {\n authorization: `Bearer ${r.token}`, 'x-tenant-key': r.tenant,\n ...(body === undefined ? { accept: 'application/json' } : { 'content-type': 'application/json' }),\n },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n })\n const answer = (await res.json().catch(() => null)) as { data?: any; errors?: { message?: string }[] } | null\n if (!res.ok) {\n const verb = method === 'GET' ? `refused to give the ${what}` : `refused the ${what}`\n throw new Error(`cauthy-auth: Cauthy ${verb} (${res.status}): ${answer?.errors?.[0]?.message ?? res.statusText}`)\n }\n return answer?.data\n}\n\n/** Reads a system's catalog of roles from Cauthy, with a personal access token. */\nexport async function pullPolicy(o: Omit<PushPolicyOptions, 'roles'> = {}): Promise<PolicyRole[]> {\n const data = await systemCall(reach(o, 'read a policy'), 'GET', 'policy')\n return (data?.roles as PolicyRole[] | undefined) ?? []\n}\n\n/** Reads the resources a system declares (empty when it declares none), with a personal access token. */\nexport async function pullCatalog(o: Omit<PushPolicyOptions, 'roles'> = {}): Promise<CatalogResource[]> {\n const data = await systemCall(reach(o, 'read a catalog'), 'GET', 'catalog')\n return (data?.resources as CatalogResource[] | undefined) ?? []\n}\n\nexport interface PushPolicyOptions {\n /** The system whose catalog this is. Default: `CAUTHY_SYSTEM`. */\n system?: string\n roles: PolicyRole[]\n /**\n * The resources the system declares. Given, they are sent before the roles,\n * which Cauthy then checks against them; left out, the catalog Cauthy has\n * stays as it is.\n */\n catalog?: CatalogResource[]\n /** Cauthy's address. Default: `CAUTHY_ISSUER`. */\n issuer?: string\n /** The workspace's slug. Default: `CAUTHY_TENANT`. */\n tenant?: string\n /**\n * A personal access token: `organizations:manage` reads, and changing a\n * policy or a catalog takes `systems:policy`. Default: `CAUTHY_TOKEN`.\n */\n token?: string\n fetch?: typeof fetch\n}\n\n/**\n * Gives Cauthy a system's catalog of roles, replacing the one it has. It is\n * the way to load a first catalog from what a system already had; from then on\n * the catalog is Cauthy's, edited in its dashboard, and pushing again would\n * overwrite what was edited there. With `catalog` the declared resources go\n * first: the roles are checked against them.\n */\nexport async function pushPolicy(o: PushPolicyOptions): Promise<void> {\n const r = reach(o, 'push a policy')\n if (o.catalog !== undefined) await systemCall(r, 'PUT', 'catalog', { resources: o.catalog })\n await systemCall(r, 'PUT', 'policy', { roles: o.roles })\n}\n\n/**\n * Gives Cauthy the resources a system declares, replacing the ones it has.\n * Cauthy refuses (`catalog_in_use`) to drop a resource or an action the\n * policy still names.\n */\nexport async function pushCatalog(o: Omit<PushPolicyOptions, 'roles' | 'catalog'> & { resources: CatalogResource[] }): Promise<CatalogResource[]> {\n const data = await systemCall(reach(o, 'push a catalog'), 'PUT', 'catalog', { resources: o.resources })\n return (data?.resources as CatalogResource[] | undefined) ?? []\n}\n\n/** What a policy file holds: the roles alone (as it used to), or `{ catalog, roles }`. */\nexport function readPolicyFile(parsed: unknown): SystemPolicy {\n if (Array.isArray(parsed)) return { catalog: [], roles: parsed as PolicyRole[] }\n const o = (parsed ?? {}) as { roles?: unknown; catalog?: unknown }\n if (!Array.isArray(o.roles)) throw new Error('no \"roles\" list')\n if (o.catalog !== undefined && !Array.isArray(o.catalog)) throw new Error('\"catalog\" is not a list')\n return { catalog: (o.catalog as CatalogResource[] | undefined) ?? [], roles: o.roles as PolicyRole[] }\n}\n\n// ── Asking Cauthy ──────────────────────────────────────────────────────────\n\n/** A check's question as Cauthy reads it. */\nexport function checkWire(q: CheckQuestion): Record<string, unknown> {\n return {\n resource: q.resource,\n action: q.action,\n ...(q.resourceId !== undefined ? { resource_id: q.resourceId } : {}),\n ...(q.ownerId !== undefined ? { owner_id: q.ownerId } : {}),\n ...(q.attributes !== undefined ? { attributes: q.attributes } : {}),\n }\n}\n\n/** Cauthy's answer to a check, as the SDK gives it. Anything but a plain yes is a no. */\nexport function checkResultOf(d: any): CheckResult {\n const r = d?.rule\n const rule: CheckRule | undefined = r && typeof r === 'object'\n ? {\n source: r.source === 'exception' ? 'exception' : 'role',\n ...(r.role ? { role: String(r.role) } : {}),\n kind: String(r.kind ?? '*'),\n resource: String(r.resource ?? ''),\n action: String(r.action ?? ''),\n effect: r.effect === 'allow' ? 'allow' : 'deny',\n ...(r.condition ? { condition: String(r.condition) } : {}),\n }\n : undefined\n return { allowed: d?.allowed === true, reason: String(d?.reason ?? ''), ...(rule ? { rule } : {}) }\n}\n\n/** The id of an organization given by its id or as the session has it. */\nexport function organizationIdOf(o: OrganizationRef | null | undefined): string {\n return typeof o === 'string' ? o : typeof o?.id === 'string' ? o.id : ''\n}\n","// The sign-in screens, ready to use.\n//\n// <SignIn onSuccess={() => navigate('/')} />\n// <SignUp locale=\"es\" />\n// <ForgotPassword />\n//\n// They are plain forms — a label, an input, a button. Import\n// `cauthy-auth/styles.css` once and they are drawn with the colours, corners and\n// typeface a person set for the workspace in Cauthy's dashboard, the same as\n// Cauthy's own sign-in page. Or give them the application's own button and\n// input (`components`), or a class for each part (`classNames`), and pass\n// `unstyled` to leave all of that out. Everything they do is `useAuth()`: an\n// application that wants another form writes it with the same functions.\n\nimport { Fragment, useCallback, useEffect, useId, useRef, useState, useSyncExternalStore, type ComponentType, type CSSProperties, type FormEvent, type ReactNode } from 'react'\nimport { canUsePasskeys, checkEmail, checkName, checkNewPassword, checkPassword, createAuthClient, passwordProblems, describePasswordPolicy, explainPasswordProblems, MIN_PASSWORD, type PasswordPolicy, type Account as AccountDetails, type AccountSession, type AuthError, type ConnectedAgent, type AuthMethods, type Invitation, type LinkedIdentity, type OrganizationPerson, type OrganizationRoleChoice, type OrganizationSeat, type Passkey, type PendingLegal, type SecondStep, type SSOConnection } from './client'\nimport { useAuth, useSession } from './react'\nimport { themeVariables, type CauthyTheme, type ThemeFont } from './theme'\nimport { checkOrganization } from './validate'\n\n/** Every sentence the forms show. Give any of them to change it. */\nexport interface AuthTexts {\n email: string\n password: string\n name: string\n code: string\n signIn: string\n signUp: string\n continueWith: string // \"Continue with\" + the provider's name\n orWithEmail: string\n forgotPassword: string\n noAccount: string\n createAccount: string\n /** The label of the company's name, asked when the application's system makes an organization per sign-up. */\n company: string\n /** The legal box: \"I have read and accept\" + \"the Terms of Service\" + \"and\" + \"the Privacy Policy\", linked. */\n iAccept: string\n and: string\n termsOfService: string\n privacyPolicy: string\n haveAccount: string\n sendLink: string\n linkSent: string\n codeHelp: string\n /** The second step when it is a phone only. */\n codeHelpPhone: string\n /** The second step by email (the account has no factor): \"{to}\" is the address, masked. */\n codeHelpEmail: string\n sendEmailAgain: string\n /** \"{to}\" is the phone, masked. */\n sendCodeSms: string\n sendCodeWhatsapp: string\n codeSent: string\n /** The second step approved on the phone; \"{n}\" is the number to pick. */\n pushSend: string\n pushPick: string\n pushWaiting: string\n // The phone on the account screen.\n phone: string\n phoneHelp: string\n phoneOn: string // \"{to}\": the phone, masked\n phoneOff: string\n addPhone: string\n removePhone: string\n bySms: string\n byWhatsapp: string\n /** The label of the channel phone codes go by, where the application draws it as a select. */\n channel: string\n verify: string\n checkEmail: string\n backToSignIn: string\n emailMeALink: string\n /** The sign-in link's own step: what it does, its send button, the way back. */\n linkHelp: string\n sendMeTheLink: string\n back: string\n usePasskey: string\n codeFromMail: string\n signInLinkSent: string\n newPassword: string\n savePassword: string\n passwordChanged: string\n confirming: string\n emailConfirmed: string\n // <AcceptInvite />: the page an invitation opens.\n invitedTo: string // \"{workspace}\" is replaced\n invitedToOrganization: string // \"{organization}\" and \"{workspace}\" are replaced\n invitedAs: string // \"{email}\" is replaced\n choosePassword: string\n acceptInvite: string\n openingInvitation: string\n invitationInvalid: string\n // The account screen.\n profile: string\n save: string\n saved: string\n currentPassword: string\n changePassword: string\n passwordChangedHere: string\n secondStep: string\n secondStepOn: string\n secondStepOff: string\n turnOn: string\n turnOff: string\n addToApp: string // above the secret to add to an authenticator app\n openInApp: string\n recoveryCodes: string\n newRecoveryCodes: string\n keepCodes: string\n passkeys: string\n managePasskeys: string\n passkeysHelp: string\n noPasskeys: string\n passkeyName: string\n /** @deprecated Unused since 0.19.0: the account screen offers `addPasskeyDevice` and `addSecurityKey`. */\n addPasskey: string\n addPasskeyDevice: string\n addSecurityKey: string\n passkeyKinds: Record<'security_key' | 'synced' | 'device', string>\n removePasskey: string\n passkeyAdded: string\n passkeyUnnamed: string\n sessions: string\n signOutEverywhere: string\n agents: string\n agentsHelp: string\n disconnect: string\n anAgent: string\n unknownDevice: string\n emailAddress: string\n newEmail: string\n changeEmail: string\n emailSent: string // after asking: \"{email}\" is replaced\n linkedAccounts: string\n noLinkedAccounts: string\n linkWith: string // + the provider's name\n unlink: string\n linked: string // after coming back linked\n ssoOnly: string // the address signs in through its company alone\n // <OrganizationMembers />: the people of the person's organization.\n members: string\n membersHidden: string\n organizationMissing: string\n memberYou: string\n memberInvited: string\n memberManager: string\n memberRole: string\n memberAdd: string\n memberAdded: string // \"{email}\" is replaced\n memberRemove: string\n memberRemoveConfirm: string // \"{who}\" is replaced\n memberLeave: string\n memberLeaveConfirm: string // \"{org}\" is replaced\n memberInviteAgain: string\n memberInvitationSent: string\n // The organization itself, for a member whose role may change it.\n organization: string\n organizationRename: string\n organizationRenamed: string // \"{name}\" is replaced\n organizationArchive: string\n organizationArchiveConfirm: string // \"{org}\" is replaced\n organizationArchived: string // \"{org}\" is replaced\n organizationDelete: string\n organizationDeleteConfirm: string // \"{org}\" is replaced\n organizationDeleted: string // \"{org}\" is replaced\n yes: string\n cancel: string\n // <PendingTerms />: documents a signed-in person still owes.\n termsChanged: string\n termsChangedHelp: string // followed by the documents, linked\n acceptTerms: string\n /** By error code; one missing shows what the server said. */\n errors: Record<string, string>\n}\n\nconst TEXTS: Record<'en' | 'es', AuthTexts> = {\n en: {\n email: 'Email', password: 'Password', name: 'Name', company: \"Your company's name\", code: 'Code', signIn: 'Sign in', signUp: 'Create account',\n continueWith: 'Continue with', orWithEmail: 'or with your email', forgotPassword: 'Forgot your password?',\n noAccount: 'No account yet?', createAccount: 'Create one', haveAccount: 'Already have an account?',\n iAccept: 'I have read and accept', and: 'and', termsOfService: 'the Terms of Service', privacyPolicy: 'the Privacy Policy',\n sendLink: 'Send the link', linkSent: 'If that address has an account, a link to choose a new password is on its way.',\n codeHelp: 'Enter the code from your authenticator app, or a recovery code.', verify: 'Verify',\n codeHelpPhone: 'We send a code to your phone. Ask for it, then type it here, or use a recovery code.',\n codeHelpEmail: 'We sent a code to {to}. Type it here.', sendEmailAgain: 'Send the code again',\n sendCodeSms: 'Send a code by SMS to {to}', sendCodeWhatsapp: 'Send a code by WhatsApp to {to}', codeSent: 'We sent a code to {to}. Type it here.',\n pushSend: 'Approve on my phone', pushPick: 'On your phone, pick {n}', pushWaiting: 'We sent a notification to your phone. Open it and pick this number.',\n phone: 'Phone, with its country code', phoneHelp: 'Get your codes by SMS or WhatsApp instead of an app.', phoneOn: 'Codes go to {to}.',\n phoneOff: 'No phone yet.', addPhone: 'Add phone', removePhone: 'Remove phone', bySms: 'SMS', byWhatsapp: 'WhatsApp', channel: 'Send codes by',\n checkEmail: 'Almost there: open the link we sent to confirm your address — it signs you in.', backToSignIn: 'Back to sign in',\n emailMeALink: 'Email me a sign-in link', linkHelp: 'We will email you a link that signs you in, no password needed.', sendMeTheLink: 'Send me the link', back: 'Back', usePasskey: 'Sign in with a passkey', codeFromMail: 'Reading it on another device? Enter the code from the email.', signInLinkSent: 'If that address has an account, a link to sign in is on its way.',\n newPassword: 'New password', savePassword: 'Save the password', passwordChanged: 'Your password was changed. You can sign in with it now.',\n confirming: 'Confirming your address…', emailConfirmed: 'Your address is confirmed. You can sign in now.',\n invitedTo: \"You've been invited to {workspace}\", invitedToOrganization: \"You've been invited to {organization} on {workspace}\",\n invitedAs: 'You will sign in as {email}.', choosePassword: 'Choose a password', acceptInvite: 'Accept and sign in',\n openingInvitation: 'Opening your invitation…', invitationInvalid: 'This invitation is not valid: it was already used, or it has expired. Ask whoever invited you to send it again.',\n profile: 'Profile', save: 'Save', saved: 'Saved.', currentPassword: 'Current password', changePassword: 'Change password',\n passwordChangedHere: 'Your password was changed. Every other session of your account was signed out.',\n secondStep: 'Second step', secondStepOn: 'On: signing in also asks for a code from your authenticator app.', secondStepOff: 'Off: signing in asks only for your password.',\n turnOn: 'Turn on', turnOff: 'Turn off', addToApp: 'Add this key to your authenticator app, then enter the code it shows.', openInApp: 'Open in an authenticator app',\n recoveryCodes: 'Recovery codes', newRecoveryCodes: 'New recovery codes', keepCodes: 'Keep these codes somewhere safe. Each works once, and they are not shown again.',\n passkeys: 'Passkeys', managePasskeys: 'Add or remove a passkey',\n passkeysHelp: 'Sign in with your fingerprint, your face or your device\\'s lock, without a password.', noPasskeys: 'No passkey yet.',\n passkeyName: 'A name for this device (optional)', addPasskey: 'Add a passkey on this device', removePasskey: 'Remove',\n addPasskeyDevice: 'Add this device (fingerprint or face)', addSecurityKey: 'Add a security key',\n passkeyKinds: { security_key: 'Security key', synced: 'Synced across your devices', device: 'On this device only' },\n passkeyAdded: 'The passkey was added. Next time, sign in with it.', passkeyUnnamed: 'Passkey', sessions: 'Where you are signed in', signOutEverywhere: 'Sign out everywhere',\n agents: 'AI agents', agentsHelp: 'Agents you allowed to act for you. Disconnect one and it loses its access within minutes.', disconnect: 'Disconnect', anAgent: 'An AI agent', unknownDevice: 'Unknown device',\n emailAddress: 'Email address', newEmail: 'New email address', changeEmail: 'Change email',\n emailSent: 'We sent a link to {email}. Your address changes once you open it.',\n linkedAccounts: 'Linked accounts', noLinkedAccounts: 'No account is linked.', linkWith: 'Link', unlink: 'Unlink', linked: 'The account was linked.',\n ssoOnly: 'Your company signs you in to this account.',\n members: 'Members', membersHidden: 'Your role here does not let you see the members.', organizationMissing: 'You do not belong to this organization.',\n memberYou: 'you', memberInvited: 'invited', memberManager: 'manages members', memberRole: 'Role', memberAdd: 'Add member',\n memberAdded: '{email} is a member now.', memberRemove: 'Remove', memberRemoveConfirm: 'Remove {who}?', memberLeave: 'Leave',\n memberLeaveConfirm: 'Leave {org}? You will need an invitation to come back.', memberInviteAgain: 'Send the invitation again',\n memberInvitationSent: 'The invitation is on its way.',\n organization: 'Organization', organizationRename: 'Rename', organizationRenamed: 'The organization is now called {name}.',\n organizationArchive: 'Archive', organizationArchiveConfirm: 'Archive {org}? Its members will no longer reach it, and only the workspace can restore it.',\n organizationArchived: '{org} was archived.', organizationDelete: 'Delete organization',\n organizationDeleteConfirm: 'Delete {org} for good? Its members lose it and this cannot be undone.', organizationDeleted: '{org} was deleted.',\n yes: 'Yes', cancel: 'Cancel',\n termsChanged: 'Our terms changed', termsChangedHelp: 'To go on, read and accept', acceptTerms: 'Accept',\n errors: {\n not_allowed: 'Your role in this organization does not allow that.', last_manager: 'Somebody else must manage the members first: give that role to another member.',\n last_owner: 'An organization keeps at least one owner: make another member owner first.', organization_not_found: 'That organization no longer exists.',\n member_exists: 'That person already belongs to the organization; their role was not changed. Change it in the list instead.',\n already_member: 'That person already belongs to the organization. Change their role instead.', unknown_role: 'Choose one of the roles offered.',\n user_not_active: 'That account is disabled.',\n required: 'This is required.', invalid_email: 'That does not look like an email address.', too_short: `Use at least ${MIN_PASSWORD} characters.`,\n invalid_credentials: 'The address or the password is not right.', unavailable: 'Sign-in is unavailable right now. Try again in a moment.',\n state_mismatch: 'That sign-in could not be completed. Try again.', cancelled: 'The sign-in was cancelled.',\n email_taken: 'That address already has an account.', email_unchanged: 'That is already your address.',\n last_sign_in_method: 'Add a password or link another account first: it is your only way to sign in.',\n identity_already_linked: 'That account is linked to someone else.', manual_linking_disabled: 'Linking accounts is turned off for this workspace.',\n invalid_token: 'This link is not valid, or it has expired. Ask for a new one.', invalid_code: 'That code is not right, or it has expired.', wrong_password: 'The current password is not right.', step_up_required: 'Enter your current password.', weak_password: 'Choose a stronger password.', unauthenticated: 'Sign in first.',\n phone_refused: 'The code could not be sent to that number.', too_many_codes: 'Enough codes were sent. Use the last one, or sign in again.', phone_unavailable: 'Codes cannot be sent that way here.', phone_already_set: 'Remove the phone you have first.', phone_codes_unavailable: 'Codes cannot be sent right now. Try again in a moment.',\n captcha_required: 'Complete the check that you are not a bot, then try again.', captcha_failed: 'The check that you are not a bot did not pass. Try it again.',\n passkey_failed: 'The passkey could not be used. Try again, or sign in another way.', passkey_exists: 'This device already has a passkey for your account.', passkey_unavailable: 'Passkeys cannot be used here.',\n sso_required: 'This address signs in through its company.', sso_not_found: 'No company sign-in answers for this address.',\n sso_failed: 'The sign-in with your company could not be completed. Try again.', sso_unavailable: 'Your company\\'s sign-in cannot be reached right now. Try again in a moment.',\n invalid_assertion: 'Your company\\'s answer could not be checked. Try again.', provisioning_disabled: 'Your company\\'s sign-in worked, but this workspace has no account for you. Ask its admin to add you.',\n connection_inactive: 'Your company\\'s sign-in is turned off for this workspace.', invalid_grant: 'That sign-in expired. Try again.',\n password_disabled: 'This workspace does not sign in with a password. Use one of the other ways.', passkeys_disabled: 'Passkeys are turned off for this workspace.',\n },\n },\n es: {\n email: 'Correo', password: 'Contraseña', name: 'Nombre', company: 'Nombre de tu empresa', code: 'Código', signIn: 'Entrar', signUp: 'Crear cuenta',\n continueWith: 'Continuar con', orWithEmail: 'o con tu correo', forgotPassword: '¿Olvidaste tu contraseña?',\n noAccount: '¿No tienes cuenta?', createAccount: 'Crear una', haveAccount: '¿Ya tienes cuenta?',\n iAccept: 'He leído y acepto', and: 'y', termsOfService: 'los Términos del servicio', privacyPolicy: 'la Política de privacidad',\n sendLink: 'Enviar el enlace', linkSent: 'Si ese correo tiene una cuenta, ya va en camino un enlace para elegir una contraseña nueva.',\n codeHelp: 'Escribe el código de tu aplicación de autenticación, o un código de recuperación.', verify: 'Verificar',\n codeHelpPhone: 'Te enviamos un código a tu teléfono. Pídelo y escríbelo aquí, o usa un código de recuperación.',\n codeHelpEmail: 'Te enviamos un código a {to}. Escríbelo aquí.', sendEmailAgain: 'Enviar el código de nuevo',\n sendCodeSms: 'Enviar un código por SMS a {to}', sendCodeWhatsapp: 'Enviar un código por WhatsApp a {to}', codeSent: 'Te enviamos un código a {to}. Escríbelo aquí.',\n pushSend: 'Aprobar en mi teléfono', pushPick: 'En tu teléfono, elige el {n}', pushWaiting: 'Enviamos una notificación a tu teléfono. Ábrela y elige este número.',\n phone: 'Teléfono, con su código de país', phoneHelp: 'Recibe tus códigos por SMS o WhatsApp en vez de una app.', phoneOn: 'Los códigos van a {to}.',\n phoneOff: 'Todavía no tienes un teléfono.', addPhone: 'Agregar teléfono', removePhone: 'Quitar teléfono', bySms: 'SMS', byWhatsapp: 'WhatsApp', channel: 'Enviar los códigos por',\n checkEmail: 'Casi listo: abre el enlace que te enviamos para confirmar tu correo; te deja adentro.', backToSignIn: 'Volver a entrar',\n emailMeALink: 'Envíame un enlace para entrar', linkHelp: 'Te enviamos un enlace al correo que te deja entrar, sin contraseña.', sendMeTheLink: 'Envíame el enlace', back: 'Volver', usePasskey: 'Entrar con una llave de acceso', codeFromMail: '¿Lo estás leyendo en otro dispositivo? Escribe el código que trae el correo.', signInLinkSent: 'Si ese correo tiene una cuenta, ya va en camino un enlace para entrar.',\n newPassword: 'Contraseña nueva', savePassword: 'Guardar la contraseña', passwordChanged: 'Tu contraseña se cambió. Ya puedes entrar con ella.',\n confirming: 'Confirmando tu correo…', emailConfirmed: 'Tu correo quedó confirmado. Ya puedes entrar.',\n invitedTo: 'Te invitaron a {workspace}', invitedToOrganization: 'Te invitaron a {organization} en {workspace}',\n invitedAs: 'Vas a entrar como {email}.', choosePassword: 'Elige una contraseña', acceptInvite: 'Aceptar y entrar',\n openingInvitation: 'Abriendo tu invitación…', invitationInvalid: 'Esta invitación no es válida: ya se usó o venció. Pídele a quien te invitó que te la envíe de nuevo.',\n profile: 'Perfil', save: 'Guardar', saved: 'Guardado.', currentPassword: 'Contraseña actual', changePassword: 'Cambiar contraseña',\n passwordChangedHere: 'Tu contraseña se cambió. Se cerraron todas las demás sesiones de tu cuenta.',\n secondStep: 'Segundo paso', secondStepOn: 'Activo: al entrar también se pide un código de tu aplicación de autenticación.', secondStepOff: 'Inactivo: al entrar solo se pide tu contraseña.',\n turnOn: 'Activar', turnOff: 'Desactivar', addToApp: 'Agrega esta clave a tu aplicación de autenticación y escribe el código que muestra.', openInApp: 'Abrir en una aplicación de autenticación',\n recoveryCodes: 'Códigos de recuperación', newRecoveryCodes: 'Nuevos códigos de recuperación', keepCodes: 'Guarda estos códigos en un lugar seguro. Cada uno sirve una vez y no se vuelven a mostrar.',\n passkeys: 'Llaves de acceso', managePasskeys: 'Agregar o quitar una llave de acceso',\n passkeysHelp: 'Entra con tu huella, tu rostro o el bloqueo de tu dispositivo, sin contraseña.', noPasskeys: 'Todavía no tienes llaves de acceso.',\n passkeyName: 'Un nombre para este dispositivo (opcional)', addPasskey: 'Agregar una llave en este dispositivo', removePasskey: 'Quitar',\n addPasskeyDevice: 'Agregar este dispositivo (huella o rostro)', addSecurityKey: 'Agregar una llave física',\n passkeyKinds: { security_key: 'Llave física', synced: 'Sincronizada entre tus dispositivos', device: 'Solo en un dispositivo' },\n passkeyAdded: 'La llave de acceso quedó agregada. La próxima vez, entra con ella.', passkeyUnnamed: 'Llave de acceso', sessions: 'Dónde tienes la sesión abierta', signOutEverywhere: 'Cerrar sesión en todas partes',\n agents: 'Agentes de IA', agentsHelp: 'Los agentes a los que permitiste actuar por ti. Si desconectas uno, pierde el acceso en pocos minutos.', disconnect: 'Desconectar', anAgent: 'Un agente de IA', unknownDevice: 'Dispositivo desconocido',\n emailAddress: 'Correo', newEmail: 'Correo nuevo', changeEmail: 'Cambiar el correo',\n emailSent: 'Enviamos un enlace a {email}. Tu correo cambia cuando lo abras.',\n linkedAccounts: 'Cuentas vinculadas', noLinkedAccounts: 'No hay cuentas vinculadas.', linkWith: 'Vincular', unlink: 'Desvincular', linked: 'La cuenta quedó vinculada.',\n ssoOnly: 'A esta cuenta entras con el inicio de sesión de tu empresa.',\n members: 'Miembros', membersHidden: 'Tu rol aquí no te deja ver los miembros.', organizationMissing: 'No perteneces a esta organización.',\n memberYou: 'tú', memberInvited: 'invitado', memberManager: 'administra los miembros', memberRole: 'Rol', memberAdd: 'Agregar miembro',\n memberAdded: '{email} ya es miembro.', memberRemove: 'Quitar', memberRemoveConfirm: '¿Quitar a {who}?', memberLeave: 'Salir',\n memberLeaveConfirm: '¿Salir de {org}? Necesitarás una invitación para volver.', memberInviteAgain: 'Enviar la invitación de nuevo',\n memberInvitationSent: 'La invitación va en camino.',\n organization: 'Organización', organizationRename: 'Cambiar nombre', organizationRenamed: 'La organización ahora se llama {name}.',\n organizationArchive: 'Archivar', organizationArchiveConfirm: '¿Archivar {org}? Sus miembros ya no podrán entrar y solo el espacio de trabajo puede restaurarla.',\n organizationArchived: '{org} quedó archivada.', organizationDelete: 'Eliminar organización',\n organizationDeleteConfirm: '¿Eliminar {org} para siempre? Sus miembros la pierden y no se puede deshacer.', organizationDeleted: '{org} quedó eliminada.',\n yes: 'Sí', cancel: 'Cancelar',\n termsChanged: 'Nuestros términos cambiaron', termsChangedHelp: 'Para seguir, lee y acepta', acceptTerms: 'Aceptar',\n errors: {\n not_allowed: 'Tu rol en esta organización no permite eso.', last_manager: 'Primero alguien más debe administrar los miembros: dale ese rol a otro miembro.',\n last_owner: 'Una organización conserva al menos un propietario: primero haz propietario a otro miembro.', organization_not_found: 'Esa organización ya no existe.',\n member_exists: 'Esa persona ya pertenece a la organización; su rol no cambió. Cámbialo en la lista.',\n already_member: 'Esa persona ya pertenece a la organización. Cambia su rol.', unknown_role: 'Escoge uno de los roles ofrecidos.',\n user_not_active: 'Esa cuenta está desactivada.',\n required: 'Este dato es obligatorio.', invalid_email: 'Eso no parece un correo.', too_short: `Usa al menos ${MIN_PASSWORD} caracteres.`,\n invalid_credentials: 'El correo o la contraseña no son correctos.', unavailable: 'No se puede entrar en este momento. Intenta de nuevo en un momento.',\n state_mismatch: 'No se pudo completar el ingreso. Intenta de nuevo.', cancelled: 'El ingreso se canceló.',\n email_taken: 'Ese correo ya tiene una cuenta.', email_unchanged: 'Ese ya es tu correo.',\n last_sign_in_method: 'Primero agrega una contraseña o vincula otra cuenta: es tu única forma de entrar.',\n identity_already_linked: 'Esa cuenta está vinculada a otra persona.', manual_linking_disabled: 'Vincular cuentas está desactivado en este workspace.',\n invalid_token: 'Este enlace no es válido o ya venció. Pide uno nuevo.', invalid_code: 'Ese código no es correcto o ya venció.', wrong_password: 'La contraseña actual no es correcta.', step_up_required: 'Escribe tu contraseña actual.', weak_password: 'Elige una contraseña más fuerte.', unauthenticated: 'Inicia sesión primero.',\n phone_refused: 'No se pudo enviar el código a ese número.', too_many_codes: 'Ya se enviaron suficientes códigos. Usa el último o vuelve a entrar.', phone_unavailable: 'Aquí no se pueden enviar códigos de esa forma.', phone_already_set: 'Primero quita el teléfono que tienes.', phone_codes_unavailable: 'Ahora no se pueden enviar códigos. Inténtalo en un momento.',\n captcha_required: 'Completa la verificación de que no eres un robot y vuelve a intentarlo.', captcha_failed: 'La verificación de que no eres un robot no pasó. Inténtalo de nuevo.',\n passkey_failed: 'No se pudo usar la llave de acceso. Intenta de nuevo o entra de otra forma.', passkey_exists: 'Este dispositivo ya tiene una llave de acceso de tu cuenta.', passkey_unavailable: 'Aquí no se pueden usar llaves de acceso.',\n sso_required: 'Este correo entra con el inicio de sesión de su empresa.', sso_not_found: 'Ninguna empresa usa inicio de sesión propio con este correo.',\n sso_failed: 'No se pudo completar el ingreso con tu empresa. Intenta de nuevo.', sso_unavailable: 'Ahora no se puede llegar al inicio de sesión de tu empresa. Intenta en un momento.',\n invalid_assertion: 'No se pudo verificar la respuesta de tu empresa. Intenta de nuevo.', provisioning_disabled: 'El ingreso con tu empresa funcionó, pero este workspace no tiene una cuenta para ti. Pídele a su admin que te agregue.',\n connection_inactive: 'El inicio de sesión de tu empresa está apagado en este workspace.', invalid_grant: 'Ese ingreso venció. Intenta de nuevo.',\n password_disabled: 'En este workspace no se entra con contraseña. Usa una de las otras formas.', passkeys_disabled: 'Las llaves de acceso están desactivadas en este workspace.',\n },\n },\n}\n\ntype Slot = 'form' | 'field' | 'label' | 'input' | 'button' | 'providerButton' | 'providerIcon' | 'link' | 'error' | 'fieldError' | 'hint' | 'notice' | 'pending' | 'separator' | 'footer' | 'check' | 'account' | 'section' | 'heading' | 'secret' | 'codes' | 'sessions' | 'session'\n\nexport interface AuthFormProps {\n /** The language of the built-in sentences. Default: `en`. */\n locale?: 'en' | 'es'\n /** Sentences of the application's own, over the built-in ones. */\n texts?: Partial<Omit<AuthTexts, 'errors'>> & { errors?: Record<string, string> }\n /**\n * Called once the person is signed in, instead of going to `returnTo`. The\n * form stays busy (its button loading, every control disabled) until it\n * leaves the page. When the application keeps the form on screen while it\n * moves on (a router's navigation, loading the session), return a Promise:\n * the form waits for it, then is free again if it is still shown.\n */\n onSuccess?: () => void | Promise<unknown>\n /** Where to go after signing in, and where a provider returns to. Default: `/`. */\n returnTo?: string\n /**\n * `<SignIn />`: a sign-in link sent to an address with no account makes\n * one when it is used (if the workspace accepts new accounts), so this one\n * screen signs people in and up alike. Default: off.\n */\n createAccounts?: boolean\n /** Paths of the application's other screens, for the links between them. */\n links?: { signIn?: string; signUp?: string; forgotPassword?: string }\n /** A class for each part the form renders. A part given one is left to it by `styles.css`. */\n classNames?: Partial<Record<Slot, string>>\n /**\n * No look of Cauthy's at all: `styles.css` leaves the form alone and the\n * workspace's colours are not read. For a form drawn wholly with the\n * application's own `components` or `classNames`.\n */\n unstyled?: boolean\n /**\n * Take the colours, corners and typeface a person set for the workspace in\n * Cauthy's dashboard. Default: true. False keeps `styles.css`'s own, and\n * whatever `--cauthy-*` variables the application sets.\n */\n workspaceLook?: boolean\n /**\n * The application's own parts, to draw the form with: its form layout,\n * button, input, checkbox, select, field, text, badge, link, divider, alert\n * and confirmation. A part not given is drawn as before; with every part given\n * and `unstyled`, the form adds no element that carries a look of its own.\n */\n components?: AuthComponents\n}\n\n/**\n * What the application's button is given: what a `<button>` would be, and\n * what kind of button it is. `primary` sends the form; `secondary` is any\n * other action (a provider, a passkey, a sign-in link, cancel, send again);\n * `danger` removes, leaves, deletes, disconnects or turns something off.\n * `loading` is true on the one button whose action is under way; every\n * button is `disabled` meanwhile. Draw a spinner (or the like) on the button\n * while `loading` is true, and keep its label: after a sign-in it stays true\n * until the page is left, so the person sees the work go on.\n */\nexport interface AuthButtonProps {\n type: 'submit' | 'button'; disabled?: boolean; className?: string; onClick?: () => void; children: ReactNode\n variant?: 'primary' | 'secondary' | 'danger'\n loading?: boolean\n}\n\n/**\n * What the application's form layout is given: every element the forms put\n * around their parts — a whole form, each step of it, each part of the\n * account and members screens — so its own stack lays them out. `as` says\n * which element it stands for: a `form` sends with `onSubmit` (render a\n * `<form>` with it for Enter to submit), a `div` only groups.\n */\nexport interface AuthFormLayoutProps {\n as: 'form' | 'div'\n onSubmit?: (e: FormEvent) => void\n noValidate?: boolean\n 'aria-busy'?: boolean\n className?: string\n /**\n * Which part of `<Account />` or `<OrganizationMembers />` this is, for an\n * application that draws each as a card: an `AccountSection`\n * (`profile`, `passkeys`…), or `members`, `add-member`, `organization`\n * and `rename` (the form inside `organization`). Not set on a whole form.\n */\n section?: string\n children: ReactNode\n}\n\n/** What the application's input is given: what an `<input>` would be. */\nexport interface AuthInputProps {\n id: string; name: string; type: string; value: string; autoComplete?: string; required?: boolean; disabled?: boolean; className?: string\n 'aria-invalid'?: boolean; 'aria-describedby'?: string; onChange: (e: { target: { value: string } }) => void\n}\n\n/** A box to tick: the legal documents and each consent of a sign-up. `children` is its label. */\nexport interface AuthCheckboxProps {\n id: string; name: string; checked: boolean; required?: boolean; disabled?: boolean; className?: string\n onChange: (checked: boolean) => void; children: ReactNode\n}\n\n/** One choice of a few: a member's role, the channel of phone codes. Without a visible label it carries `aria-label`. */\nexport interface AuthSelectProps {\n id: string; name: string; value: string; options: { value: string; label: string }[]; disabled?: boolean; className?: string\n 'aria-label'?: string; onChange: (value: string) => void\n}\n\n/**\n * A label, its control (`children`) and what is said under it. The control's\n * `aria-describedby` names `${id}-hint` and `${id}-error`: give the help and\n * the error those ids for a screen reader to read them with it.\n */\nexport interface AuthFieldProps {\n id: string; label: ReactNode; children: ReactNode\n /** Beside the label: \"Forgot your password?\". */\n aside?: ReactNode\n /** What the field takes (a new password's rule). Not given while there is an error. */\n help?: ReactNode\n error?: ReactNode\n required?: boolean; className?: string\n}\n\n/** A sentence of the form: help, a state, the footer (`size: 'sm'`), a section's heading (`as: 'h2'`). */\nexport interface AuthTextProps { as?: 'p' | 'span' | 'h2'; tone?: 'muted' | 'danger' | 'success'; size?: 'sm' | 'md' | 'lg'; children: ReactNode }\n\n/** A short mark beside a name: \"you\", \"invited\", a role, a passkey's kind. */\nexport interface AuthBadgeProps { tone?: 'neutral' | 'success' | 'warning' | 'danger'; children: ReactNode }\n\n/** A link: to another screen, or a legal document (`newTab`). */\nexport interface AuthLinkProps { href?: string; onClick?: () => void; newTab?: boolean; children: ReactNode }\n\n/** The line between the providers and the address: \"or with your email\". */\nexport interface AuthDividerProps { label?: ReactNode }\n\n/**\n * What went wrong (`danger`), what was done (`success`) or what to know\n * (`info`). The built-in one is announced: `role=\"alert\"` for danger,\n * `role=\"status\"` otherwise; the application's should be too.\n */\nexport interface AuthAlertProps { tone: 'danger' | 'info' | 'success'; children: ReactNode }\n\n/** What a confirmation asks: removing a member, leaving, archiving or deleting the organization. */\nexport interface AuthConfirmOptions { title: string; body?: string; confirmLabel: string; cancelLabel: string; danger?: boolean }\n\n/** The parts a form may be drawn with. See `AuthFormProps.components`. */\nexport interface AuthComponents {\n /**\n * Every element around the form's parts: the form itself, each step, each\n * part of the account and members screens. Not given: the `form`, `div` or\n * `section` the forms have always drawn.\n */\n Form?: ComponentType<AuthFormLayoutProps>\n Button?: ComponentType<AuthButtonProps>\n Input?: ComponentType<AuthInputProps>\n Checkbox?: ComponentType<AuthCheckboxProps>\n Select?: ComponentType<AuthSelectProps>\n Field?: ComponentType<AuthFieldProps>\n Text?: ComponentType<AuthTextProps>\n Badge?: ComponentType<AuthBadgeProps>\n Link?: ComponentType<AuthLinkProps>\n Divider?: ComponentType<AuthDividerProps>\n Alert?: ComponentType<AuthAlertProps>\n /**\n * Asks before something that cannot be undone, and answers whether to go\n * on: the application's own dialog. Not given: the question shows inline,\n * with a yes and a cancel button. Never the browser's own dialog.\n */\n Confirm?: (options: AuthConfirmOptions) => Promise<boolean>\n}\n\n// Declared once: a component made anew on every render would be a different\n// input each time, and the one being typed in would lose its place.\n// The kind of a button is for the application's own button. The plain one\n// says it is under way with a spinner before its label, drawn by styles.css.\nconst PlainButton: ComponentType<AuthButtonProps> = ({ variant: _variant, loading, children, ...p }) => (\n <button {...p} aria-busy={loading || undefined}>{loading && <Spinner />}{children}</button>\n)\n// With `unstyled` no stylesheet draws a spinner: the icon draws and turns itself.\nconst UnstyledButton: ComponentType<AuthButtonProps> = ({ variant: _variant, loading, children, ...p }) => (\n <button {...p} aria-busy={loading || undefined}>{loading && <><Spinner plain />{' '}</>}{children}</button>\n)\n\n/**\n * Work under way, as an icon and never as words: the application may be in\n * any language. Styled, it is the ring styles.css draws (still under\n * `prefers-reduced-motion`). Unstyled, no stylesheet is there, so it is an SVG\n * that turns by itself (SMIL), and stands still when the person asked for less\n * motion. The button or form around it says `aria-busy`; the icon is hidden\n * from screen readers.\n */\nfunction Spinner({ plain }: { plain?: boolean }) {\n if (!plain) return <span className=\"cauthy-spinner\" aria-hidden=\"true\" />\n return <SpinnerIcon />\n}\n\nconst LESS_MOTION = '(prefers-reduced-motion: reduce)'\n\nfunction watchMotion(changed: () => void): () => void {\n if (typeof window === 'undefined' || typeof window.matchMedia !== 'function') return () => {}\n const query = window.matchMedia(LESS_MOTION)\n query.addEventListener?.('change', changed)\n return () => query.removeEventListener?.('change', changed)\n}\n// A browser that cannot say has no preference to honour.\nconst stillHere = () => typeof window.matchMedia === 'function' && window.matchMedia(LESS_MOTION).matches\n// The server cannot know: its page draws the icon still, and the browser\n// sets it turning once it is there.\nconst stillOnServer = () => true\n\nfunction SpinnerIcon() {\n const still = useSyncExternalStore(watchMotion, stillHere, stillOnServer)\n return (\n <svg className=\"cauthy-spinner-icon\" width=\"1em\" height=\"1em\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\" focusable=\"false\">\n <circle cx=\"8\" cy=\"8\" r=\"6.5\" stroke=\"currentColor\" strokeOpacity=\"0.25\" strokeWidth=\"2\" />\n <path d=\"M14.5 8A6.5 6.5 0 0 0 8 1.5\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\">\n {!still && <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 8 8\" to=\"360 8 8\" dur=\"0.7s\" repeatCount=\"indefinite\" />}\n </path>\n </svg>\n )\n}\nconst PlainInput: ComponentType<AuthInputProps> = (p) => <input {...p} />\n\n// The workspace's look, read once per page and per mount point of the routes.\nconst looks = new Map<string, Promise<CauthyTheme | null>>()\n\n// A typeface is loaded from where the workspace's look says, once per page.\nconst loaded = new Set<string>()\nfunction loadFonts(fonts: ThemeFont[] | undefined) {\n if (typeof document === 'undefined' || typeof FontFace === 'undefined') return\n for (const f of fonts ?? []) {\n const key = `${f.family}|${f.url}|${f.weight ?? ''}|${f.style ?? ''}`\n // The same checks Cauthy's pages make: a plain family name, an https .woff2.\n if (loaded.has(key) || !/^[A-Za-z0-9][A-Za-z0-9 _-]*$/.test(f.family) || !/^https:\\/\\/[^\\s\"'()]+\\.woff2$/i.test(f.url)) continue\n loaded.add(key)\n const face = new FontFace(f.family, `url(\"${f.url}\") format(\"woff2\")`, { weight: String(f.weight ?? '400'), style: f.style === 'italic' ? 'italic' : 'normal', display: 'swap' })\n void face.load().then((ready) => document.fonts.add(ready), () => loaded.delete(key))\n }\n}\n\n/**\n * What the outermost element of a form carries: the mark `styles.css` styles\n * (`data-cauthy`) and the workspace's look as its variables.\n */\nfunction useRoot(props: { unstyled?: boolean; workspaceLook?: boolean }): { 'data-cauthy'?: ''; style?: CSSProperties } {\n const { basePath } = useSession()\n const [vars, setVars] = useState<Record<string, string>>({})\n const wanted = !props.unstyled && props.workspaceLook !== false\n useEffect(() => {\n if (!wanted) return\n let live = true\n let look = looks.get(basePath)\n if (!look) {\n look = createAuthClient({ basePath }).look()\n looks.set(basePath, look)\n }\n void look.then((theme) => {\n if (!live || !theme) return\n setVars(themeVariables(theme))\n loadFonts(theme.fonts)\n })\n return () => { live = false }\n }, [basePath, wanted])\n if (props.unstyled) return {}\n return { 'data-cauthy': '', style: vars as CSSProperties }\n}\n\n/** Cloudflare Turnstile, as much of it as the forms use. */\ninterface TurnstileApi {\n render(el: HTMLElement, options: Record<string, unknown>): string\n reset(id: string): void\n remove(id: string): void\n}\n\nlet turnstileScript: Promise<TurnstileApi> | null = null\n\nfunction loadTurnstile(): Promise<TurnstileApi> {\n const ready = () => (window as unknown as { turnstile?: TurnstileApi }).turnstile\n if (ready()) return Promise.resolve(ready()!)\n turnstileScript ??= new Promise<TurnstileApi>((resolve, reject) => {\n const script = document.createElement('script')\n script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit'\n script.async = true\n script.onload = () => (ready() ? resolve(ready()!) : reject(new Error('turnstile did not load')))\n script.onerror = () => {\n turnstileScript = null\n reject(new Error('turnstile did not load'))\n }\n document.head.appendChild(script)\n })\n return turnstileScript\n}\n\n/**\n * The workspace's Turnstile challenge, when it asks for one: the widget to put\n * in the form, the answer to send with it, and `renew` for after a submit\n * (an answer is good once). Without a site key it draws nothing.\n */\nfunction useChallenge(siteKey: string | undefined, locale: string | undefined) {\n const box = useRef<HTMLDivElement | null>(null)\n const widget = useRef<{ api: TurnstileApi; id: string } | null>(null)\n const [token, setToken] = useState('')\n useEffect(() => {\n if (!siteKey || !box.current) return\n let gone = false\n void loadTurnstile().then((api) => {\n if (gone || !box.current) return\n const id = api.render(box.current, {\n sitekey: siteKey, language: locale ?? 'auto', size: 'flexible',\n callback: (t: string) => setToken(t), 'expired-callback': () => setToken(''), 'error-callback': () => setToken(''),\n })\n widget.current = { api, id }\n }).catch(() => {})\n return () => {\n gone = true\n if (widget.current) widget.current.api.remove(widget.current.id)\n widget.current = null\n }\n }, [siteKey, locale])\n const renew = () => {\n setToken('')\n if (widget.current) widget.current.api.reset(widget.current.id)\n }\n const node = siteKey ? <div ref={box} className=\"cauthy-challenge\" /> : null\n return { node, token: token || undefined, renew }\n}\n\n/** What the workspace offers, for a form that does not read it otherwise. */\nfunction useMethods(auth: ReturnType<typeof useAuth>) {\n const [methods, setMethods] = useState<AuthMethods | null>(null)\n useEffect(() => {\n void auth.methods().then(setMethods)\n // Once: what the workspace offers does not change while the form is open.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n return methods\n}\n\n/** A path of this site, or nothing: never sends the browser elsewhere. */\nfunction sitePath(to: string | null | undefined): string | undefined {\n return to && to.startsWith('/') && !to.startsWith('//') && !to.includes('\\\\') ? to : undefined\n}\n\n/**\n * Where to go once signed in: a path of this site, or an address on this\n * site's own origin. `returnTo` is the application's, but a page may fill it\n * from its query string, so another origin is never followed.\n */\nfunction sameOrigin(to: string | null | undefined): string | undefined {\n const path = sitePath(to)\n if (path || !to) return path\n try {\n const url = new URL(to)\n return url.origin === window.location.origin ? url.pathname + url.search + url.hash : undefined\n } catch {\n return undefined\n }\n}\n\n/** Whether what a callback answered is a Promise to wait for. */\nfunction isPending(v: unknown): v is PromiseLike<unknown> {\n return typeof (v as PromiseLike<unknown> | null)?.then === 'function'\n}\n\n/**\n * Exported for the tests: the package does not export it. `waiting`: the\n * form is not ready yet (what the workspace offers is on its way), so every\n * control waits. `part`: a part of a screen whose look is the screen's.\n */\nexport function useForm(props: AuthFormProps, opts: { waiting?: boolean; part?: boolean } = {}) {\n const t: AuthTexts = { ...TEXTS[props.locale ?? 'en'], ...props.texts, errors: { ...TEXTS[props.locale ?? 'en'].errors, ...props.texts?.errors } }\n const cx = (slot: Slot) => props.classNames?.[slot] ?? `cauthy-${slot}`\n // The class the application gave a part, alone: an application's own part\n // is not handed Cauthy's class names.\n const own = (slot: Slot) => props.classNames?.[slot]\n const C: AuthComponents = props.components ?? {}\n const Button = C.Button ?? (props.unstyled ? UnstyledButton : PlainButton)\n const Input = C.Input ?? PlainInput\n const [error, setOnlyError] = useState<AuthError | null>(null)\n // Every field the form found wrong before sending, in the order they are\n // drawn; `round` moves the focus to the first one again on each try.\n const [problems, setProblems] = useState<{ list: AuthError[]; round: number }>({ list: [], round: 0 })\n // What the server said replaces what the form found.\n const setError = useCallback((e: AuthError | null) => {\n setOnlyError(e)\n setProblems((p) => (p.list.length === 0 ? p : { list: [], round: p.round }))\n }, [])\n /**\n * Checks every field at once, in the order they are drawn: each one wrong\n * shows its error, and the first is focused. True when all can be sent.\n */\n const check = (...found: (AuthError | null | undefined | false)[]): boolean => {\n const list = found.filter((e): e is AuthError => Boolean(e))\n setOnlyError(null)\n setProblems((p) => ({ list, round: list.length > 0 ? p.round + 1 : p.round }))\n return list.length === 0\n }\n /** The error of one field: what the form found, or what the server said. */\n const fieldError = (name: string): AuthError | null => problems.list.find((e) => e.field === name) ?? (error?.field === name ? error : null)\n /** Whether this field is the one to focus after a try, and the try's number. */\n const firstWrong = (name: string): number => (problems.list[0]?.field === name ? problems.round : 0)\n // The action under way, by the key of its button: `true` is the form's own\n // submit. Every button waits while one runs; only its own says it loads.\n const [acting, setActing] = useState<string | null>(null)\n const busy = acting !== null || opts.waiting === true\n const setBusy = useCallback((on: boolean | string) => setActing(on === false ? null : on === true ? SUBMIT : on), [])\n const loading = (key: string = SUBMIT) => acting === key\n // Whether the form is still shown: a wait that ends after it left has nothing to free.\n const shown = useRef(true)\n useEffect(() => {\n shown.current = true\n // Back to a page the browser kept (back-forward cache): the form it left\n // waiting is free again.\n const back = (e: PageTransitionEvent) => { if (e.persisted) setActing(null) }\n window.addEventListener('pageshow', back)\n return () => {\n shown.current = false\n window.removeEventListener('pageshow', back)\n }\n }, [])\n /**\n * After an action that leaves the form: it stays busy until the page is\n * left. When `after` is a Promise (the application's own way on), until it\n * settles, and then it is free again if it is still shown.\n */\n const hold = (after: unknown) => {\n if (!isPending(after)) return\n const free = () => { if (shown.current) setActing(null) }\n after.then(free, free)\n }\n /** What went wrong: the form is free again, and says it. */\n const fail = (e: AuthError) => {\n setActing(null)\n setError(e)\n }\n // The workspace's password rule, once methods() said it: what a refused\n // new password is told, rule by rule.\n const [policy, setPolicy] = useState<PasswordPolicy | undefined>(undefined)\n const locale = props.locale ?? 'en'\n const say = (e: AuthError) => {\n if (props.texts?.errors?.[e.code] === undefined && isPasswordRule(e)) return explainPasswordProblems(e.reasons ?? [e.code], policy, locale)\n return t.errors[e.code] ?? e.message\n }\n /** What a new password must be, for under its field. */\n const passwordRule = describePasswordPolicy(policy, locale)\n // `to`: where a sign-in link or code says to go, over `returnTo`. Signed\n // in: the form stays busy, its pressed button loading (the submit when none\n // was, as after a passkey from the autofill), until the page is left or the\n // application's `onSuccess` settles.\n const done = (to?: string) => {\n setActing((a) => a ?? SUBMIT)\n if (props.onSuccess) hold(props.onSuccess())\n else window.location.assign(sitePath(to) ?? sameOrigin(props.returnTo) ?? '/')\n }\n const root = useRoot(opts.part ? { ...props, unstyled: true } : props)\n const plain = props.unstyled === true\n return { t, cx, own, C, Button, Input, error, setError, fail, check, fieldError, firstWrong, busy, setBusy, loading, hold, say, done, root, plain, policy, setPolicy, passwordRule }\n}\n\n/** The key of the form's own submit, for `setBusy` and `loading`. */\nconst SUBMIT = 'submit'\n\ntype Form = ReturnType<typeof useForm>\n\n/**\n * An element around the form's parts: the application's `Form` when it gave\n * one, otherwise the very element the forms have always drawn. `root` is the\n * outermost one's mark and look; with the application's own `Form` and a\n * look to wear, they go on a plain `div` around it, for `styles.css` to find.\n */\nfunction Wrap(p: {\n f: Form; as: 'form' | 'div' | 'section'; slot?: Slot; root?: ReturnType<typeof useRoot>; section?: string\n onSubmit?: (e: FormEvent) => void; noValidate?: boolean; busy?: boolean; children?: ReactNode\n}) {\n const { Form: OwnForm } = p.f.C\n // Busy while an action runs, or as the caller says (a step still opening).\n const busy = p.busy ?? (p.f.busy || undefined)\n if (OwnForm) {\n const own = (\n <OwnForm as={p.as === 'form' ? 'form' : 'div'} onSubmit={p.onSubmit} noValidate={p.noValidate} aria-busy={busy}\n className={p.slot ? p.f.own(p.slot) : undefined} section={p.section}>{p.children}</OwnForm>\n )\n return p.root?.['data-cauthy'] !== undefined ? <div {...p.root}>{own}</div> : own\n }\n const Tag = p.as\n // A form still opening, with nothing to show yet, says it is on its way.\n const children = p.busy && p.children === undefined ? <Pending f={p.f} /> : p.children\n return <Tag className={p.slot ? p.f.cx(p.slot) : undefined} {...p.root} onSubmit={p.onSubmit} noValidate={p.noValidate} aria-busy={busy}>{children}</Tag>\n}\n\n/**\n * Where a form waits before it can show anything: the spinner alone, no words,\n * centred by styles.css. The form around it says `aria-busy`. The\n * application's own `Form` is told `aria-busy` and draws its own.\n */\nfunction Pending({ f }: { f: Form }) {\n return <div className={f.cx('pending')}><Spinner plain={f.plain} /></div>\n}\n\n// The parts every form draws with: the application's own when it gave one,\n// otherwise the element the forms have always drawn, so nothing changes for\n// an application that gives none.\n\n/** A sentence the form says: help, a state. */\nfunction Note({ f, children, footer }: { f: Form; children: ReactNode; footer?: boolean }) {\n const { Text } = f.C\n if (Text) return <Text as=\"p\" tone=\"muted\" size={footer ? 'sm' : 'md'}>{children}</Text>\n return <p className={f.cx(footer ? 'footer' : 'notice')}>{children}</p>\n}\n\n/** A part's heading. */\nfunction Heading({ f, children }: { f: Form; children: ReactNode }) {\n const { Text } = f.C\n if (Text) return <Text as=\"h2\" size=\"lg\">{children}</Text>\n return <h2 className={f.cx('heading')}>{children}</h2>\n}\n\n/** What went wrong, or what was done: announced. */\nfunction Say({ f, tone, children }: { f: Form; tone: AuthAlertProps['tone']; children: ReactNode }) {\n const { Alert } = f.C\n if (Alert) return <Alert tone={tone}>{children}</Alert>\n if (tone === 'danger') return <p role=\"alert\" className={f.cx('error')}>{children}</p>\n return <p role=\"status\" className={f.cx('notice')}>{children}</p>\n}\n\n/** \"or with your email\", between the providers and the address. */\nfunction Or({ f, children }: { f: Form; children: ReactNode }) {\n const { Divider } = f.C\n if (Divider) return <Divider label={children} />\n return <p className={f.cx('separator')}>{children}</p>\n}\n\nfunction A({ f, href, newTab, children }: { f: Form; href?: string; newTab?: boolean; children: ReactNode }) {\n const { Link } = f.C\n if (Link) return <Link href={href} newTab={newTab}>{children}</Link>\n return <a className={f.cx('link')} href={href} target={newTab ? '_blank' : undefined} rel={newTab ? 'noopener' : undefined}>{children}</a>\n}\n\n/** A mark beside a name; without the application's badge, the words as they always read. */\nfunction Tag({ f, tone, children, plain }: { f: Form; tone?: AuthBadgeProps['tone']; children: ReactNode; plain: ReactNode }) {\n const { Badge } = f.C\n if (Badge) return <>{' '}<Badge tone={tone}>{children}</Badge></>\n return <>{plain}</>\n}\n\nfunction Check(p: { f: Form; name: string; checked: boolean; required?: boolean; onChange: (checked: boolean) => void; children: ReactNode }) {\n const id = useId()\n const { f } = p\n const { Checkbox } = f.C\n if (Checkbox) {\n return <Checkbox id={id} name={p.name} checked={p.checked} required={p.required} disabled={f.busy} className={f.own('check')} onChange={p.onChange}>{p.children}</Checkbox>\n }\n return (\n <label className={f.cx('check')}>\n <input type=\"checkbox\" name={p.name} checked={p.checked} required={p.required} disabled={f.busy} onChange={(e) => p.onChange(e.target.checked)} />\n <span>{p.children}</span>\n </label>\n )\n}\n\nfunction Pick(p: { f: Form; id?: string; name: string; value: string; options: { value: string; label: string }[]; disabled?: boolean; label?: string; onChange: (value: string) => void }) {\n const made = useId()\n const id = p.id ?? made\n const { f } = p\n const { Select } = f.C\n // Every control waits while an action runs.\n const disabled = p.disabled || f.busy\n if (Select) {\n return <Select id={id} name={p.name} value={p.value} options={p.options} disabled={disabled} aria-label={p.label} className={f.own('input')} onChange={p.onChange} />\n }\n return (\n <select id={id} name={p.name} aria-label={p.label} className={f.cx('input')} value={p.value} disabled={disabled} onChange={(e) => p.onChange(e.target.value)}>\n {p.options.map((o) => <option key={o.value} value={o.value}>{o.label}</option>)}\n </select>\n )\n}\n\n/** A label around a control that is not a text input: a role to give. */\nfunction Labelled({ f, id, label, children }: { f: Form; id: string; label: string; children: ReactNode }) {\n const { Field: OwnField } = f.C\n if (OwnField) return <OwnField id={id} label={label} className={f.own('field')}>{children}</OwnField>\n return (\n <label className={f.cx('field')}>\n <span className={f.cx('label')}>{label}</span>\n {children}\n </label>\n )\n}\n\n/** \"the Terms of Service and the Privacy Policy\", each linked, opening apart. */\nfunction Documents({ f, documents }: { f: Form; documents: { kind: string; url: string }[] }) {\n return (\n <>\n {documents.map((d, i) => (\n <span key={d.kind}>\n {i > 0 && <>{f.t.and} </>}\n <A f={f} href={d.url} newTab>{d.kind === 'terms' ? f.t.termsOfService : f.t.privacyPolicy}</A>{' '}\n </span>\n ))}\n </>\n )\n}\n\nconst PASSWORD_RULES = ['needs_lowercase', 'needs_uppercase', 'needs_digit', 'needs_symbol', 'needs_classes', 'breached']\n\n/** A new password refused by a rule of the workspace's policy, here or by Cauthy. */\nfunction isPasswordRule(e: AuthError): boolean {\n if (e.code === 'weak_password' || PASSWORD_RULES.includes(e.code)) return true\n return (e.code === 'too_short' || e.code === 'too_long') && (e.field === 'password' || e.field === 'newPassword')\n}\n\n/**\n * A new password the workspace's rule refuses, as the form says it: every\n * rule it fails, under the field it was typed in.\n */\nfunction newPasswordProblem(value: string, policy: PasswordPolicy | undefined, field: 'password' | 'newPassword' = 'password'): AuthError | null {\n const bad = checkNewPassword(value, policy)\n if (!bad) return null\n return { code: bad.code, message: bad.message, field, ...(bad.code === 'required' ? {} : { reasons: passwordProblems(value, policy) }) }\n}\n\n/** The workspace's password rule, into a form, once methods() has said it. */\nfunction usePasswordPolicy(f: ReturnType<typeof useForm>, methods: AuthMethods | null) {\n const { setPolicy } = f\n useEffect(() => {\n if (methods?.password) setPolicy(methods.password)\n }, [methods, setPolicy])\n}\n\nfunction Field(p: {\n f: ReturnType<typeof useForm>; name: 'email' | 'password' | 'newPassword' | 'name' | 'code' | 'phone' | 'organization'; type: string; label: string; value: string\n autoComplete: string; required?: boolean; onChange: (v: string) => void; aside?: ReactNode\n /** A line under the field saying what it takes (a new password's rule). */\n hint?: string\n}) {\n const id = useId()\n const { f } = p\n const bad = f.fieldError(p.name)\n // The first field found wrong takes the focus, on every try.\n const focus = f.firstWrong(p.name)\n useEffect(() => {\n if (focus > 0 && typeof document !== 'undefined') document.getElementById(id)?.focus()\n }, [focus, id])\n const described = [bad ? `${id}-error` : '', p.hint ? `${id}-hint` : ''].filter(Boolean).join(' ')\n const input = (\n <f.Input id={id} name={p.name} type={p.type} value={p.value} autoComplete={p.autoComplete} required={p.required} disabled={f.busy} className={f.cx('input')}\n aria-invalid={bad ? true : undefined} aria-describedby={described || undefined} onChange={(e) => p.onChange(e.target.value)} />\n )\n const { Field: OwnField } = f.C\n if (OwnField) {\n return (\n <OwnField id={id} label={p.label} aside={p.aside} help={p.hint && !bad ? p.hint : undefined} error={bad ? f.say(bad) : undefined}\n required={p.required} className={f.own('field')}>{input}</OwnField>\n )\n }\n return (\n <div className={f.cx('field')}>\n <label className={f.cx('label')} htmlFor={id}>{p.label}{p.aside}</label>\n {input}\n {p.hint && !bad && <span id={`${id}-hint`} className={f.cx('hint')}>{p.hint}</span>}\n {bad && <span id={`${id}-error`} role=\"alert\" className={f.cx('fieldError')}>{f.say(bad)}</span>}\n </div>\n )\n}\n\n/** The error a provider's trip came back with, read once from the address. */\nfunction returnedError(): AuthError | null {\n if (typeof window === 'undefined') return null\n const code = new URLSearchParams(window.location.search).get('auth_error')\n return code ? { code, message: 'That sign-in could not be completed. Try again.' } : null\n}\n\n/**\n * The token a mailed link opened this page with, taken out of the address so\n * it is not left in the history or sent on as a referrer.\n */\nfunction takeToken(name: string): string | null {\n if (typeof window === 'undefined') return null\n const url = new URL(window.location.href)\n const token = url.searchParams.get(name)\n if (token === null) return null\n url.searchParams.delete(name)\n window.history.replaceState(window.history.state, '', url.pathname + url.search + url.hash)\n return token\n}\n\n/**\n * Runs `open` once with the token this page was opened with, or with null.\n * Once per page, even where React runs an effect twice while developing: the\n * token is taken out of the address the first time and a link works once.\n */\nfunction useMailedToken(name: string, open: (token: string | null) => void): void {\n const opened = useRef(false)\n useEffect(() => {\n if (opened.current) return\n opened.current = true\n open(takeToken(name))\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n}\n\n/**\n * The second step of a sign-in, once Cauthy asked for it: the code of the\n * authenticator app, a code sent to the phone or the email, or a push\n * approved on the phone. `<SignIn />` and `<AcceptInvite />` both end here.\n */\nfunction SecondStepForm(p: { f: ReturnType<typeof useForm>; auth: ReturnType<typeof useAuth> }) {\n const { f, auth } = p\n const [code, setCode] = useState('')\n // The ways the account takes the step, and where a code went.\n const [phoneWay, setPhoneWay] = useState<{ totp: boolean; phone: { number: string; channel: string } | null; push: { devices: number } | null; email: { to: string } | null } | null>(null)\n const [phoneSent, setPhoneSent] = useState('')\n useEffect(() => {\n void auth.signIn.mfaMethods().then((r) => { if (r.ok) setPhoneWay({ totp: r.totp, phone: r.phone, push: r.push, email: r.email }) })\n // Once: asked when the step opens.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n // The second step by email: the code went with the first step; another can be asked for.\n const sendEmail = async () => {\n f.setBusy('email')\n f.setError(null)\n const r = await auth.signIn.mfaSendEmail()\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setPhoneSent(r.sentTo)\n }\n // The second step approved on the phone: the number to pick, while the page listens.\n const [pushNumber, setPushNumber] = useState(0)\n const pushWait = useRef<AbortController | null>(null)\n useEffect(() => () => pushWait.current?.abort(), [])\n const sendPush = async () => {\n f.setBusy('push')\n f.setError(null)\n const r = await auth.signIn.mfaPush()\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setPushNumber(r.number)\n pushWait.current?.abort()\n const ctl = new AbortController()\n pushWait.current = ctl\n const done = await auth.signIn.mfaPushWait({ signal: ctl.signal })\n if (ctl.signal.aborted) return\n setPushNumber(0)\n if (!done.ok) return f.setError(done.error)\n // Approved: its button says the sign-in goes on, until the page is left.\n f.setBusy('push')\n f.done()\n }\n const sendCode = async () => {\n f.setBusy('phone')\n f.setError(null)\n const r = await auth.signIn.mfaSendCode()\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setPhoneSent(r.sentTo)\n }\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.signIn.mfa({ code })\n // Signed in: the form stays busy until it leaves (see `done`).\n if (!r.ok) return f.fail(r.error)\n f.done()\n }\n const general = f.error && !f.error.field ? f.error : null\n const to = phoneWay?.phone?.number ?? ''\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n <Note f={f}>{phoneSent ? f.t.codeSent.replace('{to}', phoneSent) : phoneWay?.email ? f.t.codeHelpEmail.replace('{to}', phoneWay.email.to) : phoneWay?.phone && !phoneWay.totp ? f.t.codeHelpPhone : f.t.codeHelp}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {phoneWay?.email && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('email')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void sendEmail()}>{f.t.sendEmailAgain}</f.Button>\n )}\n {pushNumber > 0 ? (f.C.Text ? (\n // The application's text: the number to pick drawn large, by its own rules.\n <div role=\"status\" aria-live=\"polite\">\n <f.C.Text as=\"p\">{f.t.pushPick.replace('{n}', String(pushNumber))}</f.C.Text>\n <f.C.Text as=\"p\" size=\"lg\">{pushNumber}</f.C.Text>\n <f.C.Text as=\"p\" tone=\"muted\">{f.t.pushWaiting}</f.C.Text>\n </div>\n ) : (\n <div className={f.cx('notice')} role=\"status\" aria-live=\"polite\">\n <p>{f.t.pushPick.replace('{n}', String(pushNumber))}</p>\n <p style={{ fontSize: 48, fontWeight: 700, margin: '4px 0', textAlign: 'center' }}>{pushNumber}</p>\n <p>{f.t.pushWaiting}</p>\n </div>\n )) : phoneWay?.push && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('push')} disabled={f.busy} className={f.cx('button')} onClick={() => void sendPush()}>{f.t.pushSend}</f.Button>\n )}\n {phoneWay?.phone && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('phone')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void sendCode()}>\n {(phoneWay.phone.channel === 'whatsapp' ? f.t.sendCodeWhatsapp : f.t.sendCodeSms).replace('{to}', to)}\n </f.Button>\n )}\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n}\n\n/**\n * \"Continue with …\", one button per provider the workspace turned on, each\n * with the provider's logo when Cauthy serves one. The logo says nothing a\n * screen reader needs: the button's words name the provider.\n */\nexport function ProviderButtons(p: { f: ReturnType<typeof useForm>; providers: AuthMethods['providers']; onPick: (id: string) => void }) {\n const { f } = p\n // On the way to the provider: the button pressed loads, and the form waits\n // until the page is left.\n const pick = (id: string) => {\n f.setBusy(`provider:${id}`)\n p.onPick(id)\n }\n return (\n <>\n {p.providers.map((provider) => (\n <f.Button key={provider.id} type=\"button\" variant=\"secondary\" loading={f.loading(`provider:${provider.id}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => pick(provider.id)}>\n {provider.iconUrl && <img src={provider.iconUrl} alt=\"\" width={18} height={18} className={f.cx('providerIcon')} />}\n {f.t.continueWith} {provider.name}\n </f.Button>\n ))}\n </>\n )\n}\n\n/**\n * What `<SignIn />` offers, from what the workspace turned on: the password\n * (and with it \"forgot your password\"), the address (asked for the password,\n * a sign-in link, or finding the person's company) and the passkey button.\n * Until `methods()` answers, the usual form: a password and an address.\n */\nexport function signInOffers(methods: AuthMethods | null): { password: boolean; email: boolean; passkey: boolean } {\n const password = methods?.passwordSignIn !== false\n return { password, email: password || methods?.magicLink === true || methods?.sso === true, passkey: methods?.passkey === true }\n}\n\nexport function SignIn(props: AuthFormProps) {\n const auth = useAuth()\n const [methods, setMethods] = useState<AuthMethods | null>(null)\n // Until the workspace says what it offers, the form shows but waits: nothing\n // to press or type that the answer could still change.\n const f = useForm(props, { waiting: methods === null })\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [code, setCode] = useState('')\n // 'link': the sign-in link's own step, opened from the quick ways in.\n const [step, setStep] = useState<'password' | 'link' | 'code' | 'opening' | 'sent'>('password')\n const challenge = useChallenge(methods?.captchaSiteKey, props.locale)\n const offers = signInOffers(methods)\n // A workspace that turned the password off: no password field, no \"forgot\n // your password\". Until methods() answers, the form is the usual one.\n const passwordOn = offers.password\n // The passkeys offered in the email field's autofill, while the form waits.\n const autofill = useRef<AbortController | null>(null)\n const [offer, setOffer] = useState(0)\n // The person's company, when the address typed is one of its domains.\n const [company, setCompany] = useState<SSOConnection | null>(null)\n useEffect(() => {\n if (!methods?.sso || checkEmail(email) !== null) return setCompany(null)\n let current = true\n const t = setTimeout(() => {\n void auth.signIn.ssoDiscover({ email }).then((r) => { if (current) setCompany(r.ok && r.status === 'found' ? r.connection : null) })\n }, 350)\n return () => { current = false; clearTimeout(t) }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [email, methods])\n const toCompany = () => {\n autofill.current?.abort()\n f.setBusy('sso')\n auth.signIn.sso({ email }, { returnTo: props.returnTo })\n }\n\n useEffect(() => {\n void auth.methods().then(setMethods)\n const back = returnedError()\n if (back) f.setError(back)\n // Once: what the workspace offers does not change while the form is open.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n // Opened from a sign-in link: the token signs the person in.\n useMailedToken('ml_token', (token) => {\n if (!token) return\n setStep('opening')\n void auth.signIn.magicLinkVerify({ token }).then((r) => {\n // The link carries where the person was going, as `return_to`.\n if (r.ok) return f.done(new URLSearchParams(window.location.search).get('return_to') ?? undefined)\n f.setError(r.error)\n setStep('password')\n })\n })\n\n useEffect(() => {\n if (step !== 'password' || !methods?.passkeyHere) return\n const ctl = new AbortController()\n autofill.current = ctl\n void auth.signIn.passkeyAutofill({ signal: ctl.signal }).then((r) => {\n if (ctl.signal.aborted) return\n if (r.ok) return f.done()\n if (r.error.code === 'cancelled') return // nothing to offer here\n f.setError(r.error)\n // A passkey that failed: offer them again, for another try.\n if (r.error.code === 'passkey_failed' || r.error.code === 'step_expired') setOffer((n) => n + 1)\n })\n return () => ctl.abort()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [step, methods, offer])\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n autofill.current?.abort()\n // An address its company holds to SSO has nothing else to send.\n if (step === 'password' && company?.enforced) {\n f.setError(null)\n return toCompany()\n }\n // The sign-in link's own step: the link, unless the company holds the address.\n if (step === 'link') {\n if (company?.enforced) return toCompany()\n if (f.check(checkEmail(email))) return sendLink()\n return\n }\n // No password to send: the address asks for a link, when the workspace mails them.\n if (step === 'password' && !passwordOn) {\n if (company) return toCompany()\n if (methods?.magicLink && f.check(checkEmail(email))) return sendLink()\n return\n }\n // Every field the step shows, checked at once.\n if (step === 'password' && !f.check(checkEmail(email), checkPassword(password))) return\n f.setBusy(true)\n f.setError(null)\n const r = step === 'sent' ? await auth.signIn.emailCode({ code }) : await auth.signIn.email({ email, password, captchaToken: challenge.token })\n if (step === 'password') challenge.renew()\n if (!r.ok && r.error.code === 'sso_required') return toCompany()\n if (!r.ok) {\n setOffer((n) => n + 1)\n return f.fail(r.error)\n }\n if (r.status === 'mfa_required') {\n f.setBusy(false)\n return setStep('code')\n }\n f.done('returnTo' in r && typeof r.returnTo === 'string' ? r.returnTo : undefined)\n }\n const usePasskey = async () => {\n // The browser asks for one passkey at a time.\n autofill.current?.abort()\n f.setBusy('passkey')\n f.setError(null)\n const r = await auth.signIn.passkey({ returnTo: props.returnTo, locale: props.locale, email })\n // On its way to Cauthy's page, or signed in: the form waits until it leaves.\n if (r.ok && r.status === 'redirected') return\n if (r.ok) return f.done()\n f.setBusy(false)\n setOffer((n) => n + 1)\n // The person closed the browser's prompt: nothing to say.\n if (r.error.code !== 'cancelled') f.setError(r.error)\n }\n const sendLink = async () => {\n autofill.current?.abort()\n f.setBusy('link')\n f.setError(null)\n const r = await auth.signIn.magicLink({ email, captchaToken: challenge.token, create: props.createAccounts, returnTo: props.returnTo })\n f.setBusy(false)\n challenge.renew()\n if (!r.ok && r.error.code === 'sso_required') return toCompany()\n if (!r.ok) return f.setError(r.error)\n setStep('sent')\n }\n // The sign-in link's step, with the address typed so far.\n const openLink = () => {\n autofill.current?.abort()\n f.setError(null)\n setStep('link')\n }\n const general = f.error && !f.error.field ? f.error : null\n const asksEmail = offers.email\n\n if (step === 'opening') return <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy />\n if (step === 'sent') {\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n <Note f={f}>{f.t.signInLinkSent}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Note f={f}>{f.t.codeFromMail}</Note>\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n }\n if (step === 'code') return <SecondStepForm f={f} auth={auth} />\n // The sign-in link, asked from the quick ways in: the address (the one\n // typed in the form, if any) and the button that sends it.\n if (step === 'link') {\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Note f={f}>{f.t.linkHelp}</Note>\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"username\" required onChange={setEmail} />\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading('link')} disabled={f.busy} className={f.cx('button')}>{f.t.sendMeTheLink}</f.Button>\n <f.Button type=\"button\" variant=\"secondary\" disabled={f.busy} className={f.cx('providerButton')} onClick={() => { f.setError(null); setStep('password') }}>{f.t.back}</f.Button>\n </Wrap>\n )\n }\n // The quick ways in come first: the passkey, the providers, the sign-in\n // link (opening its own step). Then \"or\", and the address and password.\n // Without the password, the address below is the sign-in link's.\n const quickLink = methods?.magicLink === true && passwordOn\n const quick = offers.passkey || (methods?.providers.length ?? 0) > 0 || quickLink\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {offers.passkey && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('passkey')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void usePasskey()}>{f.t.usePasskey}</f.Button>\n )}\n <ProviderButtons f={f} providers={methods?.providers ?? []} onPick={(id) => auth.signIn.social(id, { returnTo: props.returnTo })} />\n {quickLink && (\n <f.Button type=\"button\" variant=\"secondary\" disabled={f.busy} className={f.cx('providerButton')} onClick={openLink}>{f.t.emailMeALink}</f.Button>\n )}\n {asksEmail && quick && <Or f={f}>{f.t.orWithEmail}</Or>}\n {asksEmail && (\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete={methods?.passkeyHere ? 'username webauthn' : 'username'} required onChange={setEmail} />\n )}\n {company && (\n <f.Button type=\"button\" variant={company.enforced ? 'primary' : 'secondary'} loading={f.loading('sso')} disabled={f.busy} className={f.cx(company.enforced ? 'button' : 'providerButton')} onClick={toCompany}>\n {f.t.continueWith} {company.name}\n </f.Button>\n )}\n {company?.enforced && <Note f={f}>{f.t.ssoOnly}</Note>}\n {!company?.enforced && passwordOn && (\n <>\n <Field f={f} name=\"password\" type=\"password\" label={f.t.password} value={password} autoComplete=\"current-password\" required onChange={setPassword}\n aside={props.links?.forgotPassword ? <A f={f} href={props.links.forgotPassword}>{f.t.forgotPassword}</A> : undefined} />\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.signIn}</f.Button>\n </>\n )}\n {/* Without the password, the address asks for the sign-in link. */}\n {!company?.enforced && !passwordOn && methods?.magicLink && (\n <>\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading('link')} disabled={f.busy} className={f.cx('button')}>{f.t.sendMeTheLink}</f.Button>\n </>\n )}\n {methods?.signUp !== false && props.links?.signUp && (\n <Note f={f} footer>{f.t.noAccount} <A f={f} href={props.links.signUp}>{f.t.createAccount}</A></Note>\n )}\n </Wrap>\n )\n}\n\nexport interface GoogleOneTapProps {\n /** Where to go once signed in. Without it (and without `onSuccess`), the page stays and its session updates. */\n returnTo?: string\n /** Called once signed in, instead of going to `returnTo`. */\n onSuccess?: () => void\n /** The prompt's words: sign in (default), sign up, or use the application. */\n context?: 'signin' | 'signup' | 'use'\n}\n\n/**\n * Google One Tap: put it on any page, and a person who is not signed in sees\n * Google's prompt with the Google account the browser has; one tap signs them\n * in. It draws nothing of its own, and shows nothing to somebody signed in or\n * where the workspace has no Google sign-in.\n */\nexport function GoogleOneTap(props: GoogleOneTapProps) {\n const auth = useAuth()\n const unauthenticated = auth.status === 'unauthenticated'\n useEffect(() => {\n if (!unauthenticated) return\n const ctl = new AbortController()\n void auth.signIn.googleOneTap({ signal: ctl.signal, context: props.context }).then((r) => {\n if (!r.ok || ctl.signal.aborted) return\n if (props.onSuccess) props.onSuccess()\n else {\n const to = sameOrigin(props.returnTo)\n if (to) window.location.assign(to)\n }\n })\n return () => ctl.abort()\n // Once per signed-out visit: the prompt is not shown again on every render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [unauthenticated])\n return null\n}\n\nexport function SignUp(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [name, setName] = useState('')\n const [organization, setOrganization] = useState('')\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [sent, setSent] = useState(false)\n const methods = useMethods(auth)\n usePasswordPolicy(f, methods)\n const challenge = useChallenge(methods?.captchaSiteKey, props.locale)\n // The law's boxes: the documents accepted, and each consent asked.\n const [acceptLegal, setAcceptLegal] = useState(false)\n const [consents, setConsents] = useState<Record<string, boolean>>({})\n const legal = methods?.legal\n\n const guest = auth.session?.user.isAnonymous === true\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n // Every field at once, in the order they are drawn.\n const asksCompany = methods?.organization?.ask === true\n if (!f.check(\n asksCompany && checkOrganization(organization, methods?.organization?.required === true),\n checkName(name), checkEmail(email), newPasswordProblem(password, f.policy),\n )) return\n f.setBusy(true)\n f.setError(null)\n // A guest signing up becomes the account they were using: same id.\n const r = guest\n ? await auth.account.upgrade({ name, email, password })\n : await auth.signUp.email({ name, email, password, ...(methods?.organization?.ask ? { organization } : {}),\n ...(legal ? { acceptLegal, consents } : {}), captchaToken: challenge.token })\n challenge.renew()\n if (!r.ok) return f.fail(r.error)\n if (r.status === 'verification_required') {\n f.setBusy(false)\n return setSent(true)\n }\n f.done()\n }\n const general = f.error && !f.error.field ? f.error : null\n // A workspace that turned the password off makes accounts through its\n // providers only. Not offered to a guest becoming an account (the provider\n // would sign them in as another), nor where the sign-up must name its\n // company: a provider has no field for it.\n const passwordOn = methods?.passwordSignIn !== false\n const providers = guest || methods?.organization?.required ? [] : (methods?.providers ?? [])\n\n if (sent) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Note f={f}>{f.t.checkEmail}</Note>\n {props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>}\n </Wrap>\n )\n }\n // Until the workspace says what it asks (a company's name, the password,\n // the legal boxes), the form waits: its fields would move as they came.\n if (methods === null) return <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy />\n const footer = props.links?.signIn && <Note f={f} footer>{f.t.haveAccount} <A f={f} href={props.links.signIn}>{f.t.signIn}</A></Note>\n if (!passwordOn) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ProviderButtons f={f} providers={providers} onPick={(id) => auth.signIn.social(id, { returnTo: props.returnTo })} />\n {footer}\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ProviderButtons f={f} providers={providers} onPick={(id) => auth.signIn.social(id, { returnTo: props.returnTo })} />\n {providers.length > 0 && <Or f={f}>{f.t.orWithEmail}</Or>}\n {methods.organization?.ask && (\n <Field f={f} name=\"organization\" type=\"text\" label={f.t.company} value={organization} autoComplete=\"organization\" required={methods.organization.required} onChange={setOrganization} />\n )}\n <Field f={f} name=\"name\" type=\"text\" label={f.t.name} value={name} autoComplete=\"name\" onChange={setName} />\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"username\" required onChange={setEmail} />\n <Field f={f} name=\"password\" type=\"password\" label={f.t.password} value={password} autoComplete=\"new-password\" required onChange={setPassword} hint={f.passwordRule} />\n {legal && legal.documents.length > 0 && (\n <Check f={f} name=\"acceptLegal\" checked={acceptLegal} required onChange={setAcceptLegal}>\n {f.t.iAccept}{' '}\n <Documents f={f} documents={legal.documents} />\n </Check>\n )}\n {legal?.consentPurposes.map((p) => (\n <Check key={p.key} f={f} name={`consent_${p.key}`} checked={consents[p.key] === true} required={p.required} onChange={(on) => setConsents({ ...consents, [p.key]: on })}>\n {p.label}\n </Check>\n ))}\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.signUp}</f.Button>\n {footer}\n </Wrap>\n )\n}\n\nexport function ForgotPassword(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [email, setEmail] = useState('')\n const [sent, setSent] = useState(false)\n const challenge = useChallenge(useMethods(auth)?.captchaSiteKey, props.locale)\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.forgotPassword({ email, captchaToken: challenge.token })\n f.setBusy(false)\n challenge.renew()\n if (!r.ok) return f.setError(r.error)\n setSent(true)\n }\n const general = f.error && !f.error.field ? f.error : null\n\n if (sent) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Note f={f}>{f.t.linkSent}</Note>\n {props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>}\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"username\" required onChange={setEmail} />\n {challenge.node}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.sendLink}</f.Button>\n {props.links?.signIn && <Note f={f} footer><A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A></Note>}\n </Wrap>\n )\n}\n\n/** The page a \"choose a new password\" link opens: `pages.resetPassword`. */\nexport function ResetPassword(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [token, setToken] = useState<string | null>(null)\n const [password, setPassword] = useState('')\n const [changed, setChanged] = useState(false)\n usePasswordPolicy(f, useMethods(auth))\n\n useMailedToken('token', (t) => {\n setToken(t ?? '')\n if (!t) f.setError({ code: 'invalid_token', message: 'This link is not valid, or it has expired.' })\n })\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.resetPassword({ token: token ?? '', password })\n f.setBusy(false)\n if (!r.ok) return f.setError(r.error)\n setChanged(true)\n }\n const general = f.error && !f.error.field ? f.error : null\n const back = props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>\n\n if (changed) {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Note f={f}>{f.t.passwordChanged}</Note>\n {back}\n </Wrap>\n )\n }\n if (token === '') {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {props.links?.forgotPassword && <A f={f} href={props.links.forgotPassword}>{f.t.forgotPassword}</A>}\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"password\" type=\"password\" label={f.t.newPassword} value={password} autoComplete=\"new-password\" required onChange={setPassword} hint={f.passwordRule} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy || token === null} className={f.cx('button')}>{f.t.savePassword}</f.Button>\n </Wrap>\n )\n}\n\n/** The page a \"confirm your address\" link opens: `pages.verifyEmail`. It confirms as it opens. */\nexport function VerifyEmail(props: AuthFormProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [state, setState] = useState<'confirming' | 'confirmed' | 'failed'>('confirming')\n\n useMailedToken('token', (token) => {\n if (!token) {\n f.setError({ code: 'invalid_token', message: 'This link is not valid, or it has expired.' })\n return setState('failed')\n }\n void auth.verifyEmail({ token }).then((r) => {\n // Signed in from the link: on to the application, nothing more to type.\n if (r.ok && r.status === 'signed_in') return f.done()\n if (r.ok) return setState('confirmed')\n f.setError(r.error)\n setState('failed')\n })\n })\n\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy={state === 'confirming'}>\n {state === 'confirming' && <Note f={f}>{f.t.confirming}</Note>}\n {state === 'confirmed' && <Note f={f}>{f.t.emailConfirmed}</Note>}\n {state === 'failed' && f.error && <Say f={f} tone=\"danger\">{f.say(f.error)}</Say>}\n {state !== 'confirming' && props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>}\n </Wrap>\n )\n}\n\n/**\n * The page an invitation opens: `pages.acceptInvite`. It says who is invited\n * to what, asks for a password under the workspace's policy, signs the person\n * in (with the second step, when their account owes one) and goes on to\n * `returnTo`. The invitation is good until it is accepted: reading it, or a\n * password refused, does not spend it.\n */\n/** What `<AcceptInvite />` tells the application once the invitation is accepted. */\nexport type AcceptInviteEvent = { kind: 'invitation.accepted'; email: string; organization?: string }\n\nexport interface AcceptInviteProps extends AuthFormProps {\n /** Called once the invitation is accepted, before the second step when the account owes one. */\n onSaved?: (event: AcceptInviteEvent) => void\n}\n\nexport function AcceptInvite(props: AcceptInviteProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [token, setToken] = useState('')\n const [invitation, setInvitation] = useState<Invitation | null>(null)\n const [state, setState] = useState<'opening' | 'ready' | 'invalid' | 'code'>('opening')\n const [password, setPassword] = useState('')\n usePasswordPolicy(f, useMethods(auth))\n\n useMailedToken('token', (t) => {\n if (!t) return setState('invalid')\n setToken(t)\n void auth.invitation(t).then((r) => {\n if (r.ok) {\n setInvitation(r.invitation)\n return setState('ready')\n }\n // A spent or unknown invitation says so; anything else, what it was.\n if (r.error.code !== 'invalid_token') f.setError(r.error)\n setState('invalid')\n })\n })\n\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n f.setBusy(true)\n f.setError(null)\n const r = await auth.acceptInvitation(token, password)\n if (!r.ok) {\n f.setBusy(false)\n if (r.error.code === 'invalid_token') return setState('invalid')\n return f.setError(r.error)\n }\n props.onSaved?.({ kind: 'invitation.accepted', email: invitation?.email ?? '', ...(invitation?.organization ? { organization: invitation.organization } : {}) })\n if (r.status === 'mfa_required') {\n f.setBusy(false)\n return setState('code')\n }\n f.done()\n }\n const general = f.error && !f.error.field ? f.error : null\n const back = props.links?.signIn && <A f={f} href={props.links.signIn}>{f.t.backToSignIn}</A>\n\n if (state === 'opening') {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root} busy>\n <Note f={f}>{f.t.openingInvitation}</Note>\n </Wrap>\n )\n }\n if (state === 'invalid') {\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Say f={f} tone=\"danger\">{general ? f.say(general) : f.t.invitationInvalid}</Say>\n {back}\n </Wrap>\n )\n }\n if (state === 'code') return <SecondStepForm f={f} auth={auth} />\n const workspace = invitation?.workspace ?? ''\n const heading = invitation?.organization\n ? f.t.invitedToOrganization.replace('{organization}', invitation.organization).replace('{workspace}', workspace)\n : f.t.invitedTo.replace('{workspace}', workspace)\n return (\n <Wrap f={f} as=\"form\" slot=\"form\" root={f.root} onSubmit={submit} noValidate>\n <Heading f={f}>{heading}</Heading>\n <Note f={f}>{f.t.invitedAs.replace('{email}', invitation?.email ?? '')}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {/* The address, for the browser's password manager to keep the new password under. */}\n <input type=\"email\" name=\"username\" autoComplete=\"username\" value={invitation?.email ?? ''} readOnly hidden />\n <Field f={f} name=\"password\" type=\"password\" label={f.t.choosePassword} value={password} autoComplete=\"new-password\" required onChange={setPassword} hint={f.passwordRule} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.acceptInvite}</f.Button>\n </Wrap>\n )\n}\n\nexport interface PendingTermsProps extends Omit<AuthFormProps, 'links' | 'returnTo' | 'createAccounts'> {\n /**\n * Called once the person accepted. Nothing else happens: the application\n * decides what follows. A Promise keeps the button loading until it settles.\n */\n onSuccess?: () => void | Promise<unknown>\n}\n\n/**\n * The legal documents the signed-in person still owes (a new version of the\n * terms, say), linked, with the action that accepts them. It shows nothing\n * while it reads them, when nothing is owed, and once they are accepted.\n * Nothing stops the person meanwhile: the application decides what waits.\n */\nexport function PendingTerms(props: PendingTermsProps) {\n const auth = useAuth()\n const f = useForm(props)\n const [owed, setOwed] = useState<PendingLegal[] | null>(null)\n useEffect(() => {\n void auth.account.legal().then((r) => setOwed(r.ok ? r.pending : []))\n // Once: what is owed is read when the page opens.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (!owed || owed.length === 0) return null\n const accept = async () => {\n f.setBusy(true)\n f.setError(null)\n const r = await auth.account.acceptLegal({ kinds: owed.map((d) => d.kind) })\n if (!r.ok) return f.fail(r.error)\n // The application's own way on, when it waits for it: the button loads until then.\n const after = props.onSuccess?.()\n if (isPending(after)) await Promise.resolve(after).catch(() => undefined)\n f.setBusy(false)\n setOwed([])\n }\n return (\n <Wrap f={f} as=\"div\" slot=\"form\" root={f.root}>\n <Heading f={f}>{f.t.termsChanged}</Heading>\n <Note f={f}>{f.t.termsChangedHelp}{' '}<Documents f={f} documents={owed} /></Note>\n {f.error && <Say f={f} tone=\"danger\">{f.say(f.error)}</Say>}\n <f.Button type=\"button\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')} onClick={() => void accept()}>{f.t.acceptTerms}</f.Button>\n </Wrap>\n )\n}\n\n/** The parts of `<Account />`, by name: what `sections` lists. */\nexport type AccountSection = 'profile' | 'email' | 'password' | 'linked' | 'secondStep' | 'phone' | 'passkeys' | 'agents' | 'sessions'\n\nconst ACCOUNT_SECTIONS: AccountSection[] = ['profile', 'email', 'password', 'linked', 'secondStep', 'phone', 'passkeys', 'agents', 'sessions']\n\n/**\n * What `<Account />` tells the application after each change it saved, for\n * the application's own toast or its own data to follow.\n */\nexport type AccountEvent =\n | { kind: 'profile.saved'; name: string }\n | { kind: 'email.change_requested'; email: string }\n | { kind: 'password.changed' }\n | { kind: 'identity.linked'; provider: string }\n | { kind: 'identity.unlinked'; provider: string }\n | { kind: 'mfa.enabled' }\n | { kind: 'mfa.disabled' }\n | { kind: 'recovery_codes.regenerated' }\n | { kind: 'phone.added'; channel: 'sms' | 'whatsapp' }\n | { kind: 'phone.removed' }\n | { kind: 'passkey.added'; id: string }\n | { kind: 'passkey.removed'; id: string }\n | { kind: 'agent.disconnected'; id: string }\n | { kind: 'sessions.ended' }\n\nexport interface AccountProps extends Omit<AuthFormProps, 'links' | 'returnTo' | 'onSuccess'> {\n /** Called after \"sign out everywhere\". Default: go to `/`. A Promise keeps the button loading until it settles. */\n onSignedOut?: () => void | Promise<unknown>\n /** The moment of a session, as the application writes dates. Default: the browser's own way, in the reader's time zone. */\n formatDate?: (iso: string) => string\n /**\n * The parts shown, in this order. Default: all of them, as listed in\n * `AccountSection`. A part with nothing to show (the password of an account\n * without one, agents when none is connected) stays out either way.\n */\n sections?: AccountSection[]\n /** Called after every change saved, with what changed. */\n onSaved?: (event: AccountEvent) => void\n}\n\n/** One part of the account screen: its own form, its own error, its own \"saved\". */\nfunction useSection(props: AccountProps) {\n // The look is the account screen's, around every part: not read again here.\n const f = useForm(props, { part: true })\n const [done, setDone] = useState<string | null>(null)\n // `key`: the button the action belongs to, the one that says it loads.\n // `leaves`: done, the action leaves the page; the part stays busy (see `hold`).\n const run = async <T extends { ok: boolean }>(action: () => Promise<T>, key: string = SUBMIT, leaves = false): Promise<T> => {\n f.setBusy(key)\n f.setError(null)\n setDone(null)\n const r = await action()\n if (!r.ok) f.fail((r as unknown as { error: AuthError }).error)\n else if (!leaves) f.setBusy(false)\n return r\n }\n const general = f.error && !f.error.field ? f.error : null\n return { f, done, setDone, run, general }\n}\n\n/**\n * The signed-in person's account, in the application: their name, their\n * password, the second step, and where they are signed in. Each part saves on\n * its own. Like the other forms, it carries no styles.\n */\nexport function Account(props: AccountProps) {\n const auth = useAuth()\n const { accountUrl } = useSession()\n const f = useForm(props)\n const [account, setAccount] = useState<AccountDetails | null>(null)\n\n useEffect(() => {\n void auth.account.get().then(setAccount)\n // Once: the account is read when the screen opens, and after each change below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n if (account === null) return <Wrap f={f} as=\"div\" slot=\"account\" root={f.root} busy />\n const when = props.formatDate ?? ((iso: string) => new Date(iso).toLocaleString())\n const mfa = (mfaEnabled: boolean) => setAccount({ ...account, mfaEnabled })\n const part = (section: AccountSection): ReactNode => {\n switch (section) {\n case 'profile': return <ProfilePart props={props} account={account} onSaved={setAccount} />\n case 'email': return <EmailPart props={props} account={account} />\n case 'password': return account.hasPassword ? <PasswordPart props={props} /> : null\n case 'linked': return <LinkedPart props={props} />\n case 'secondStep': return <SecondStepPart props={props} account={account} onChanged={mfa} />\n case 'phone': return <PhonePart props={props} account={account} onChanged={mfa} />\n case 'passkeys': return <PasskeysPart props={props} account={account} accountUrl={accountUrl()} when={when} />\n case 'agents': return <AgentsPart props={props} when={when} />\n case 'sessions': return <SessionsPart props={props} when={when} />\n }\n }\n\n return (\n <Wrap f={f} as=\"div\" slot=\"account\" root={f.root}>\n {(props.sections ?? ACCOUNT_SECTIONS).map((section) => <Fragment key={section}>{part(section)}</Fragment>)}\n </Wrap>\n )\n}\n\n/** What each part of the account screen takes, shown on its own: `<Account />`'s props but `sections`. */\nexport type AccountPartProps = Omit<AccountProps, 'sections'>\n\n// Each part of the account screen on its own, for an application that puts\n// them on separate cards. Each reads the account it shows.\n\n/** The person's name. */\nexport function AccountProfile(props: AccountPartProps) { return <Account {...props} sections={['profile']} /> }\n/** Changing the address: a link goes to the new one. */\nexport function AccountEmail(props: AccountPartProps) { return <Account {...props} sections={['email']} /> }\n/** Changing the password, for an account that has one. */\nexport function AccountPassword(props: AccountPartProps) { return <Account {...props} sections={['password']} /> }\n/** The providers the account signs in with. */\nexport function AccountLinked(props: AccountPartProps) { return <Account {...props} sections={['linked']} /> }\n/** The second step with an authenticator app, and the recovery codes. */\nexport function AccountSecondStep(props: AccountPartProps) { return <Account {...props} sections={['secondStep']} /> }\n/** The phone codes go to, where the workspace sends them. */\nexport function AccountPhone(props: AccountPartProps) { return <Account {...props} sections={['phone']} /> }\n/** The account's passkeys. */\nexport function AccountPasskeys(props: AccountPartProps) { return <Account {...props} sections={['passkeys']} /> }\n/** The AI agents the person connected, when there is one. */\nexport function AccountAgents(props: AccountPartProps) { return <Account {...props} sections={['agents']} /> }\n/** Where the person is signed in, and \"sign out everywhere\". */\nexport function AccountSessions(props: AccountPartProps) { return <Account {...props} sections={['sessions']} /> }\n\n/** An action `<OrganizationMembers hide={...} />` never offers. */\nexport type OrganizationMembersAction = 'archive' | 'delete' | 'rename' | 'leave'\n\n/**\n * What `<OrganizationMembers />` tells the application after each change it\n * saved, for the application's own toast or its own data to follow.\n */\nexport type OrganizationMembersEvent =\n | { kind: 'member.added'; organizationId: string; userId: string; email: string; role: string }\n | { kind: 'member.role_changed'; organizationId: string; userId: string; role: string; previousRole: string }\n | { kind: 'member.removed'; organizationId: string; userId: string }\n | { kind: 'member.left'; organizationId: string; userId: string }\n | { kind: 'member.invited_again'; organizationId: string; userId: string }\n | { kind: 'organization.renamed'; organizationId: string; name: string }\n | { kind: 'organization.archived'; organizationId: string }\n | { kind: 'organization.deleted'; organizationId: string }\n\nexport interface OrganizationMembersProps extends Omit<AuthFormProps, 'links' | 'returnTo' | 'onSuccess' | 'createAccounts'> {\n /** The organization, by the id Cauthy gave it. */\n organizationId: string\n /** The moment of a membership, as the application writes dates. Default: the browser's own way. */\n formatDate?: (iso: string) => string\n /**\n * The roles offered when adding a member or changing one's role: those for\n * which it answers true. A member already holding another role keeps it,\n * and it shows. Default: every role the person may give.\n */\n roles?: (role: string, choice: OrganizationRoleChoice) => boolean\n /** Actions never offered, whatever the person's role allows. */\n hide?: OrganizationMembersAction[]\n /** A role's name wherever one shows: a member's, the role choices, adding one. Default: the name the catalog gives it. */\n roleLabel?: (choice: OrganizationRoleChoice) => string\n /** Called after every change saved, with what changed. */\n onSaved?: (event: OrganizationMembersEvent) => void\n}\n\n/** The role Cauthy keeps in every catalog: only its holders give it, or change and remove those who hold it. */\nconst OWNER = 'owner'\n\n/**\n * What the signed-in person may do to one member, by their own seat: the\n * buttons <OrganizationMembers /> shows. Cauthy refuses the rest anyway; this\n * only keeps from offering it.\n */\nexport function memberActions(seat: OrganizationSeat, m: OrganizationPerson): { changeRole: boolean; remove: boolean; inviteAgain: boolean } {\n // An owner is changed or removed by another owner alone.\n const reachable = m.role !== OWNER || seat.role === OWNER\n return {\n changeRole: seat.can.manageMembers && reachable,\n // Leaving is anybody's; removing somebody else is cauthy:members:remove.\n remove: m.you || (seat.can.removeMembers && reachable),\n inviteAgain: seat.can.manageMembers && m.invited,\n }\n}\n\n/**\n * The roles the person may give: the owner role only by an owner, and of\n * those, the ones the application's `only` lets through.\n */\nexport function rolesToGive(seat: OrganizationSeat, roles: OrganizationRoleChoice[], only?: (role: string, choice: OrganizationRoleChoice) => boolean): OrganizationRoleChoice[] {\n const mine = seat.role === OWNER ? roles : roles.filter((c) => c.role !== OWNER)\n return only ? mine.filter((c) => only(c.role, c)) : mine\n}\n\n/**\n * The people of one of the signed-in person's organizations, administered\n * from the application. What it offers follows the person's role in the\n * system's catalog: cauthy:members read lists the people; manage adds them by\n * address (one with no account is invited), changes their role and sends an\n * invitation again; remove removes them. Anybody may leave. Only an owner\n * gives the owner role or changes an owner. cauthy:organization update,\n * archive and delete rename the organization, archive it, delete it. Cauthy\n * checks each change with the person's own session; the application\n * authorizes nothing. Like the other forms, it carries no styles.\n */\nexport function OrganizationMembers(props: OrganizationMembersProps) {\n const auth = useAuth()\n // The mark styles.css draws is the screen's; each part below is unstyled inside it, as in <Account />.\n const { root } = useForm(props as AccountProps)\n const { f, done, setDone, run } = useSection(props as AccountProps)\n // A refusal about the address or the new name shows under its field; any\n // other — a role, the last owner, a power the person lacks — above the list.\n const problem = f.error && f.error.field !== 'email' && f.error.field !== 'name' ? f.error : null\n const [seat, setSeat] = useState<OrganizationSeat | null | undefined>(undefined)\n const [members, setMembers] = useState<OrganizationPerson[] | null>(null)\n const [roles, setRoles] = useState<OrganizationRoleChoice[]>([])\n const [email, setEmail] = useState('')\n const [role, setRole] = useState('')\n const [name, setName] = useState('')\n const [asking, setAsking] = useState<string | null>(null) // the member a removal waits on, or 'archive' / 'delete'\n // Said once the organization is archived or deleted: there is nothing left to show.\n const [gone, setGone] = useState<string | null>(null)\n const id = props.organizationId\n const when = props.formatDate ?? ((iso: string) => new Date(iso).toLocaleDateString())\n const hidden = (action: OrganizationMembersAction) => props.hide?.includes(action) === true\n const saved = (event: OrganizationMembersEvent) => props.onSaved?.(event)\n\n const load = async () => {\n const [list, people, choices] = await Promise.all([auth.organizations.list(), auth.organizations.members(id), auth.organizations.roles(id)])\n const mine = list.find((o) => o.id === id) ?? null\n setSeat(mine)\n if (mine) setName(mine.name)\n setMembers(people)\n setRoles(choices ?? [])\n const offered = mine ? rolesToGive(mine, choices ?? [], props.roles) : []\n if (offered.length > 0 && !offered.some((c) => c.role === role)) setRole(offered[0].role)\n }\n useEffect(() => {\n void load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [id])\n\n if (gone !== null) return <Wrap f={f} as=\"div\" slot=\"account\" root={root}><Say f={f} tone=\"success\">{gone}</Say></Wrap>\n if (seat === undefined) return <Wrap f={f} as=\"div\" slot=\"account\" root={root} busy />\n if (seat === null) return <Wrap f={f} as=\"div\" slot=\"account\" root={root}><Note f={f}>{f.t.organizationMissing}</Note></Wrap>\n const manage = seat.can.manageMembers\n const giveable = rolesToGive(seat, roles, props.roles)\n const roleName = (c: OrganizationRoleChoice) => props.roleLabel?.(c) || c.name || c.role\n const label = (r: string) => {\n const c = roles.find((x) => x.role === r)\n return c ? roleName(c) : r\n }\n\n const add = async (e: FormEvent) => {\n e.preventDefault()\n if (!f.check(checkEmail(email))) return\n const r = await run(() => auth.organizations.add(id, { email, role, locale: props.locale }), 'add')\n if (!r.ok) return\n setEmail('')\n setDone(f.t.memberAdded.replace('{email}', r.member.email))\n saved({ kind: 'member.added', organizationId: id, userId: r.member.userId, email: r.member.email, role: r.member.role || role })\n await load()\n }\n const change = async (m: OrganizationPerson, next: string) => {\n const r = await run(() => auth.organizations.setRole(id, m.userId, next), `role:${m.userId}`)\n if (!r.ok) return\n saved({ kind: 'member.role_changed', organizationId: id, userId: m.userId, role: next, previousRole: m.role })\n await load()\n }\n const remove = async (m: OrganizationPerson) => {\n setAsking(null)\n const r = await run(() => auth.organizations.remove(id, m.userId), `remove:${m.userId}`)\n if (!r.ok) return\n saved({ kind: m.you ? 'member.left' : 'member.removed', organizationId: id, userId: m.userId })\n // Leaving: the organization is no longer the person's to see.\n if (m.you) setSeat(null)\n else await load()\n }\n const inviteAgain = async (m: OrganizationPerson) => {\n const r = await run(() => auth.organizations.inviteAgain(id, m.userId, { locale: props.locale }), `invite:${m.userId}`)\n if (!r.ok) return\n setDone(f.t.memberInvitationSent)\n saved({ kind: 'member.invited_again', organizationId: id, userId: m.userId })\n }\n const rename = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.organizations.rename(id, name), 'rename')\n if (!r.ok) return\n setSeat(r.organization)\n setName(r.organization.name)\n setDone(f.t.organizationRenamed.replace('{name}', r.organization.name))\n saved({ kind: 'organization.renamed', organizationId: id, name: r.organization.name })\n }\n const close = async (how: 'archive' | 'delete') => {\n setAsking(null)\n const r = await run<{ ok: boolean }>(() => (how === 'archive' ? auth.organizations.archive(id) : auth.organizations.delete(id)), how)\n if (!r.ok) return\n setGone((how === 'archive' ? f.t.organizationArchived : f.t.organizationDeleted).replace('{org}', seat.name))\n saved({ kind: how === 'archive' ? 'organization.archived' : 'organization.deleted', organizationId: id })\n }\n // Before what cannot be undone: the application's own dialog when it gave\n // one, otherwise the question inline, where the button was.\n const ask = (key: string, title: string, question: string, yes: () => void) => {\n const { Confirm } = f.C\n if (!Confirm) return setAsking(key)\n void Confirm({ title, body: question, confirmLabel: title, cancelLabel: f.t.cancel, danger: true }).then((ok) => { if (ok) yes() })\n }\n const confirming = (text: string, label: string, yes: () => void) => (\n <span role=\"group\" aria-label={label}>\n <span>{text}</span>{' '}\n <f.Button type=\"button\" variant=\"danger\" disabled={f.busy} className={f.cx('providerButton')} onClick={yes}>{f.t.yes}</f.Button>\n <f.Button type=\"button\" variant=\"secondary\" disabled={f.busy} className={f.cx('providerButton')} onClick={() => setAsking(null)}>{f.t.cancel}</f.Button>\n </span>\n )\n const leaveQuestion = f.t.memberLeaveConfirm.replace('{org}', seat.name)\n const archiveQuestion = f.t.organizationArchiveConfirm.replace('{org}', seat.name)\n const deleteQuestion = f.t.organizationDeleteConfirm.replace('{org}', seat.name)\n const archiving = seat.can.archive && !hidden('archive')\n const deleting = seat.can.delete && !hidden('delete')\n const renaming = seat.can.update && !hidden('rename')\n\n return (\n <Wrap f={f} as=\"div\" slot=\"account\" root={root}>\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"members\">\n <Heading f={f}>{f.t.members} · {seat.name}</Heading>\n {problem && <Say f={f} tone=\"danger\">{f.say(problem)}</Say>}\n {members === null ? (\n <>\n <Note f={f}>{f.t.membersHidden}</Note>\n {/* Whoever cannot see the people may still leave. */}\n {auth.session && !hidden('leave') && (asking === auth.session.user.id\n ? confirming(leaveQuestion, f.t.memberLeave, () => void remove({ userId: auth.session!.user.id, you: true } as OrganizationPerson))\n : <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`remove:${auth.session.user.id}`)} disabled={f.busy} className={f.cx('providerButton')}\n onClick={() => ask(auth.session!.user.id, f.t.memberLeave, leaveQuestion, () => void remove({ userId: auth.session!.user.id, you: true } as OrganizationPerson))}>{f.t.memberLeave}</f.Button>)}\n </>\n ) : (\n <ul className={f.cx('sessions')}>\n {members.map((m) => {\n const who = m.name || m.email\n const may = memberActions(seat, m)\n const removable = may.remove && !(m.you && hidden('leave'))\n const question = m.you ? leaveQuestion : f.t.memberRemoveConfirm.replace('{who}', who)\n const action = m.you ? f.t.memberLeave : f.t.memberRemove\n // The member's own role stays listed, even one the person may not give.\n const choices = giveable.some((c) => c.role === m.role) ? giveable : [...roles.filter((c) => c.role === m.role), ...giveable]\n return (\n <li key={m.userId} className={f.cx('session')}>\n <span>\n {who}{m.name ? ` · ${m.email}` : ''}\n {m.you && <Tag f={f} plain={` (${f.t.memberYou})`}>{f.t.memberYou}</Tag>}\n {f.C.Badge ? (\n <>\n {m.invited && <Tag f={f} tone=\"warning\" plain=\"\">{f.t.memberInvited}</Tag>}\n {m.manager && <Tag f={f} tone=\"success\" plain=\"\">{f.t.memberManager}</Tag>}\n </>\n ) : `${m.invited ? ` · ${f.t.memberInvited}` : ''}${m.manager ? ` · ${f.t.memberManager}` : ''}`}\n {' · '}{when(m.since)}\n </span>{' '}\n {may.changeRole && giveable.length > 0 ? (\n <Pick f={f} name={`role_${m.userId}`} label={`${f.t.memberRole}: ${who}`} value={m.role} disabled={f.busy}\n options={choices.map((c) => ({ value: c.role, label: roleName(c) }))} onChange={(next) => void change(m, next)} />\n ) : f.C.Badge ? <f.C.Badge tone=\"neutral\">{label(m.role)}</f.C.Badge> : <span>{label(m.role)}</span>}{' '}\n {asking === m.userId ? (\n confirming(question, action, () => void remove(m))\n ) : (\n <>\n {may.inviteAgain && <f.Button type=\"button\" variant=\"secondary\" loading={f.loading(`invite:${m.userId}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void inviteAgain(m)}>{f.t.memberInviteAgain}</f.Button>}\n {removable && <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`remove:${m.userId}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => ask(m.userId, action, question, () => void remove(m))}>{action}</f.Button>}\n </>\n )}\n </li>\n )\n })}\n </ul>\n )}\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n {manage && giveable.length > 0 && (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"add-member\" onSubmit={add} noValidate>\n <Heading f={f}>{f.t.memberAdd}</Heading>\n <Field f={f} name=\"email\" type=\"email\" label={f.t.email} value={email} autoComplete=\"off\" required onChange={setEmail} />\n <AddRole f={f} value={role} options={giveable.map((c) => ({ value: c.role, label: roleName(c) }))} onChange={setRole} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading('add')} disabled={f.busy} className={f.cx('button')}>{f.t.memberAdd}</f.Button>\n </Wrap>\n )}\n {(renaming || archiving || deleting) && (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"organization\">\n <Heading f={f}>{f.t.organization}</Heading>\n {renaming && (\n <Wrap f={f} as=\"form\" section=\"rename\" onSubmit={rename} noValidate>\n <Field f={f} name=\"name\" type=\"text\" label={f.t.name} value={name} autoComplete=\"organization\" required onChange={setName} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading('rename')} disabled={f.busy} className={f.cx('button')}>{f.t.organizationRename}</f.Button>\n </Wrap>\n )}\n {asking === 'archive' ? confirming(archiveQuestion, f.t.organizationArchive, () => void close('archive'))\n : asking === 'delete' ? confirming(deleteQuestion, f.t.organizationDelete, () => void close('delete'))\n : (\n <>\n {archiving && <f.Button type=\"button\" variant=\"danger\" loading={f.loading('archive')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => ask('archive', f.t.organizationArchive, archiveQuestion, () => void close('archive'))}>{f.t.organizationArchive}</f.Button>}\n {deleting && <f.Button type=\"button\" variant=\"danger\" loading={f.loading('delete')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => ask('delete', f.t.organizationDelete, deleteQuestion, () => void close('delete'))}>{f.t.organizationDelete}</f.Button>}\n </>\n )}\n </Wrap>\n )}\n </Wrap>\n )\n}\n\n/** The role a new member gets, labelled like the address above it. */\nfunction AddRole({ f, value, options, onChange }: { f: Form; value: string; options: { value: string; label: string }[]; onChange: (role: string) => void }) {\n const id = useId()\n return (\n <Labelled f={f} id={id} label={f.t.memberRole}>\n <Pick f={f} id={id} name=\"role\" value={value} options={options} onChange={onChange} />\n </Labelled>\n )\n}\n\n/**\n * The account's passkeys: made and removed on this page. A page that cannot\n * use the workspace's passkeys links to Cauthy's account page instead.\n */\nfunction PasskeysPart({ props, account, accountUrl, when }: { props: AccountProps; account: AccountDetails; accountUrl: string; when: (iso: string) => string }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [here, setHere] = useState<boolean | null>(null)\n const [list, setList] = useState<Passkey[]>([])\n const [name, setName] = useState('')\n const [password, setPassword] = useState('')\n useEffect(() => {\n void auth.methods().then((m) => {\n const can = m.passkeyHere && canUsePasskeys()\n setHere(can)\n if (can) void auth.account.passkeys().then(setList)\n })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (here === null) return null\n if (!here) {\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"passkeys\">\n <Heading f={f}>{f.t.passkeys}</Heading>\n <A f={f} href={accountUrl}>{f.t.managePasskeys}</A>\n </Wrap>\n )\n }\n const add = async (e: FormEvent | null, kind: 'device' | 'security_key' = 'device') => {\n e?.preventDefault()\n if (account.hasPassword && !f.check(checkPassword(password))) return\n const r = await run(() => auth.account.addPasskey({ name, password, kind }), kind === 'security_key' ? 'security_key' : SUBMIT)\n if (!r.ok) {\n // The person closed the browser's prompt: nothing to say.\n if (r.error.code === 'cancelled') f.setError(null)\n return\n }\n setList([...list, r.passkey])\n setName('')\n setPassword('')\n setDone(f.t.passkeyAdded)\n props.onSaved?.({ kind: 'passkey.added', id: r.passkey.id })\n }\n const remove = async (id: string) => {\n const r = await run(() => auth.account.removePasskey(id), `remove:${id}`)\n if (!r.ok) return\n setList(list.filter((p) => p.id !== id))\n props.onSaved?.({ kind: 'passkey.removed', id })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"passkeys\" onSubmit={add} noValidate>\n <Heading f={f}>{f.t.passkeys}</Heading>\n <Note f={f}>{f.t.passkeysHelp}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {list.length === 0 ? <Note f={f}>{f.t.noPasskeys}</Note> : (\n <ul className={f.cx('sessions')}>\n {list.map((p) => (\n <li key={p.id} className={f.cx('session')}>\n {p.name || f.t.passkeyUnnamed}\n {p.kind !== 'unknown' && <Tag f={f} plain={` · ${f.t.passkeyKinds[p.kind]}`}>{f.t.passkeyKinds[p.kind]}</Tag>} · {when(p.createdAt)}{' '}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`remove:${p.id}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void remove(p.id)}>{f.t.removePasskey}</f.Button>\n </li>\n ))}\n </ul>\n )}\n <Field f={f} name=\"name\" type=\"text\" label={f.t.passkeyName} value={name} autoComplete=\"off\" onChange={setName} />\n {account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.addPasskeyDevice}</f.Button>\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('security_key')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void add(null, 'security_key')}>{f.t.addSecurityKey}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\nfunction ProfilePart({ props, account, onSaved }: { props: AccountProps; account: AccountDetails; onSaved: (a: AccountDetails) => void }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [name, setName] = useState(account.name)\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.update({ name }))\n if (!r.ok) return\n onSaved(r.account)\n setDone(f.t.saved)\n props.onSaved?.({ kind: 'profile.saved', name: r.account.name })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"profile\" onSubmit={submit} noValidate>\n <Heading f={f}>{f.t.profile}</Heading>\n <Note f={f}>{account.email}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"name\" type=\"text\" label={f.t.name} value={name} autoComplete=\"name\" onChange={setName} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.save}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\nfunction EmailPart({ props, account }: { props: AccountProps; account: AccountDetails }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n if (!f.check(checkEmail(email), account.hasPassword && checkPassword(password))) return\n const r = await run(() => auth.account.changeEmail({ email, password }))\n if (!r.ok) return\n setPassword('')\n setDone(f.t.emailSent.replace('{email}', r.email))\n props.onSaved?.({ kind: 'email.change_requested', email: r.email })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"email\" onSubmit={submit} noValidate>\n <Heading f={f}>{f.t.emailAddress}</Heading>\n <Note f={f}>{account.email}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"email\" type=\"email\" label={f.t.newEmail} value={email} autoComplete=\"email\" required onChange={setEmail} />\n {account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )}\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.changeEmail}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\n/** The providers the account signs in with, and the ones the workspace offers to link. */\nfunction LinkedPart({ props }: { props: AccountProps }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [linked, setLinked] = useState<LinkedIdentity[] | null>(null)\n const [offered, setOffered] = useState<{ id: string; name: string }[]>([])\n const [came, setCame] = useState<string | null>(null)\n useEffect(() => {\n void auth.account.identities().then(setLinked)\n void auth.methods().then((m) => setOffered(m.providers))\n // Back from a provider: say how it went, once.\n const back = typeof window === 'undefined' ? null : new URLSearchParams(window.location.search)\n const provider = back?.get('linked')\n if (provider) {\n setCame(provider)\n props.onSaved?.({ kind: 'identity.linked', provider })\n }\n else if (back?.get('auth_error')) f.setError({ code: back.get('auth_error') as string, message: 'That account could not be linked. Try again.' })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (linked === null) return null\n const name = (id: string) => offered.find((p) => p.id === id)?.name ?? id\n const unlink = async (provider: string) => {\n const r = await run(() => auth.account.unlink(provider), `unlink:${provider}`)\n if (!r.ok) return\n setLinked(linked.filter((x) => x.provider !== provider))\n props.onSaved?.({ kind: 'identity.unlinked', provider })\n }\n const here = typeof window === 'undefined' ? undefined : window.location.pathname\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"linked\">\n <Heading f={f}>{f.t.linkedAccounts}</Heading>\n {came && <Say f={f} tone=\"success\">{f.t.linked}</Say>}\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {linked.length === 0 ? <Note f={f}>{f.t.noLinkedAccounts}</Note> : (\n <ul className={f.cx('sessions')}>\n {linked.map((x) => (\n <li key={x.provider} className={f.cx('session')}>\n {name(x.provider)}{x.email ? ` · ${x.email}` : ''}{' '}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`unlink:${x.provider}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void unlink(x.provider)}>{f.t.unlink}</f.Button>\n </li>\n ))}\n </ul>\n )}\n {offered.filter((p) => !linked.some((x) => x.provider === p.id)).map((p) => (\n <f.Button key={p.id} type=\"button\" variant=\"secondary\" loading={f.loading(`link:${p.id}`)} disabled={f.busy} className={f.cx('providerButton')}\n onClick={() => { f.setBusy(`link:${p.id}`); auth.account.link(p.id, { returnTo: here }) }}>{f.t.linkWith} {p.name}</f.Button>\n ))}\n </Wrap>\n )\n}\n\nfunction PasswordPart({ props }: { props: AccountProps }) {\n const auth = useAuth()\n const { f, done, setDone, run, general } = useSection(props)\n const [password, setPassword] = useState('')\n const [newPassword, setNewPassword] = useState('')\n usePasswordPolicy(f, useMethods(auth))\n const submit = async (e: FormEvent) => {\n e.preventDefault()\n if (!f.check(checkPassword(password), newPasswordProblem(newPassword, f.policy, 'newPassword'))) return\n const r = await run(() => auth.account.changePassword({ password, newPassword }))\n if (!r.ok) return\n setPassword('')\n setNewPassword('')\n setDone(f.t.passwordChangedHere)\n props.onSaved?.({ kind: 'password.changed' })\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"password\" onSubmit={submit} noValidate>\n <Heading f={f}>{f.t.changePassword}</Heading>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n <Field f={f} name=\"newPassword\" type=\"password\" label={f.t.newPassword} value={newPassword} autoComplete=\"new-password\" required onChange={setNewPassword} hint={f.passwordRule} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.changePassword}</f.Button>\n {done && <Say f={f} tone=\"success\">{done}</Say>}\n </Wrap>\n )\n}\n\nfunction SecondStepPart({ props, account, onChanged }: { props: AccountProps; account: AccountDetails; onChanged: (on: boolean) => void }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [password, setPassword] = useState('')\n const [code, setCode] = useState('')\n const [setup, setSetup] = useState<{ secret: string; otpauthUri: string } | null>(null)\n const [codes, setCodes] = useState<string[] | null>(null)\n\n const start = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.setup({ password }))\n if (r.ok) setSetup({ secret: r.secret, otpauthUri: r.otpauthUri })\n }\n const confirm = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.verify({ code }))\n if (!r.ok) return\n setSetup(null)\n setCode('')\n setPassword('')\n setCodes(r.recoveryCodes)\n onChanged(true)\n props.onSaved?.({ kind: 'mfa.enabled' })\n }\n const turnOff = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.disable({ password }))\n if (!r.ok) return\n setPassword('')\n setCodes(null)\n onChanged(false)\n props.onSaved?.({ kind: 'mfa.disabled' })\n }\n const renew = async () => {\n const r = await run(() => auth.account.mfa.recoveryCodes({ password }), 'codes')\n if (!r.ok) return\n setCodes(r.recoveryCodes)\n props.onSaved?.({ kind: 'recovery_codes.regenerated' })\n }\n const passwordField = account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )\n const shown = codes && (\n <>\n <Note f={f}>{f.t.keepCodes}</Note>\n <ul className={f.cx('codes')}>{codes.map((c) => <li key={c}><code>{c}</code></li>)}</ul>\n </>\n )\n\n if (setup) {\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"secondStep\" onSubmit={confirm} noValidate>\n <Heading f={f}>{f.t.secondStep}</Heading>\n <Note f={f}>{f.t.addToApp}</Note>\n <code className={f.cx('secret')}>{setup.secret}</code>\n <A f={f} href={setup.otpauthUri}>{f.t.openInApp}</A>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"secondStep\" onSubmit={account.mfaEnabled ? turnOff : start} noValidate>\n <Heading f={f}>{f.t.secondStep}</Heading>\n <Note f={f}>{account.mfaEnabled ? f.t.secondStepOn : f.t.secondStepOff}</Note>\n {shown}\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {passwordField}\n <f.Button type=\"submit\" variant={account.mfaEnabled ? 'danger' : 'primary'} loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{account.mfaEnabled ? f.t.turnOff : f.t.turnOn}</f.Button>\n {account.mfaEnabled && (\n <f.Button type=\"button\" variant=\"secondary\" loading={f.loading('codes')} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void renew()}>{f.t.newRecoveryCodes}</f.Button>\n )}\n </Wrap>\n )\n}\n\n// The phone as the second step, where the workspace sends codes to phones:\n// added with the password, proven with the code it receives, removed.\nfunction PhonePart({ props, account, onChanged }: { props: AccountProps; account: AccountDetails; onChanged: (on: boolean) => void }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [ways, setWays] = useState<SecondStep | null>(null)\n const [number, setNumber] = useState('')\n const [channel, setChannel] = useState<'sms' | 'whatsapp'>('sms')\n const [password, setPassword] = useState('')\n const [code, setCode] = useState('')\n const [sentTo, setSentTo] = useState('')\n const [codes, setCodes] = useState<string[] | null>(null)\n const load = () => auth.account.mfa.factors().then((w) => {\n setWays(w)\n if (w && w.phoneChannels.length > 0 && !w.phoneChannels.includes(channel)) setChannel(w.phoneChannels[0] as 'sms' | 'whatsapp')\n })\n useEffect(() => {\n void load()\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (!ways || ways.phoneChannels.length === 0) return null\n\n const add = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.addPhone({ phone: number, channel, password }))\n if (r.ok) setSentTo(r.sentTo)\n }\n const confirm = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.verifyPhone({ code }))\n if (!r.ok) return\n setSentTo('')\n setCode('')\n setPassword('')\n if (r.recoveryCodes.length > 0) setCodes(r.recoveryCodes)\n onChanged(true)\n props.onSaved?.({ kind: 'phone.added', channel })\n await load()\n }\n const remove = async (e: FormEvent) => {\n e.preventDefault()\n const r = await run(() => auth.account.mfa.removePhone({ password }))\n if (!r.ok) return\n setPassword('')\n await load()\n const left = await auth.account.mfa.factors()\n onChanged(Boolean(left?.totp))\n props.onSaved?.({ kind: 'phone.removed' })\n }\n const passwordField = account.hasPassword && (\n <Field f={f} name=\"password\" type=\"password\" label={f.t.currentPassword} value={password} autoComplete=\"current-password\" required onChange={setPassword} />\n )\n if (sentTo) {\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"phone\" onSubmit={confirm} noValidate>\n <Heading f={f}>{f.t.phone}</Heading>\n <Note f={f}>{f.t.codeSent.replace('{to}', sentTo)}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <Field f={f} name=\"code\" type=\"text\" label={f.t.code} value={code} autoComplete=\"one-time-code\" required onChange={setCode} />\n <f.Button type=\"submit\" variant=\"primary\" loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{f.t.verify}</f.Button>\n </Wrap>\n )\n }\n return (\n <Wrap f={f} as=\"form\" slot=\"section\" section=\"phone\" onSubmit={ways.phone ? remove : add} noValidate>\n <Heading f={f}>{f.t.phone}</Heading>\n <Note f={f}>{ways.phone ? f.t.phoneOn.replace('{to}', ways.phone.number) : `${f.t.phoneOff} ${f.t.phoneHelp}`}</Note>\n {codes && (\n <>\n <Note f={f}>{f.t.keepCodes}</Note>\n <ul className={f.cx('codes')}>{codes.map((c) => <li key={c}><code>{c}</code></li>)}</ul>\n </>\n )}\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n {!ways.phone && <Field f={f} name=\"phone\" type=\"tel\" label={f.t.phone} value={number} autoComplete=\"tel\" required onChange={setNumber} />}\n {!ways.phone && ways.phoneChannels.length > 1 && f.C.Select && (\n <ChannelPick f={f} value={channel} channels={ways.phoneChannels as ('sms' | 'whatsapp')[]} onChange={setChannel} />\n )}\n {!ways.phone && ways.phoneChannels.length > 1 && !f.C.Select && (\n <div className={f.cx('field')} role=\"radiogroup\">\n {(ways.phoneChannels as ('sms' | 'whatsapp')[]).map((c) => (\n <label key={c} className={f.cx('label')}>\n <input type=\"radio\" name=\"channel\" value={c} checked={channel === c} disabled={f.busy} onChange={() => setChannel(c)} /> {c === 'whatsapp' ? f.t.byWhatsapp : f.t.bySms}\n </label>\n ))}\n </div>\n )}\n {passwordField}\n <f.Button type=\"submit\" variant={ways.phone ? 'danger' : 'primary'} loading={f.loading()} disabled={f.busy} className={f.cx('button')}>{ways.phone ? f.t.removePhone : f.t.addPhone}</f.Button>\n </Wrap>\n )\n}\n\n/** The AI agents the person connected. Shown only when there is one. */\nfunction AgentsPart({ props, when }: { props: AccountProps; when: (iso: string) => string }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [list, setList] = useState<ConnectedAgent[]>([])\n useEffect(() => {\n void auth.account.agents().then(setList)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n if (list.length === 0) return null\n const disconnect = async (id: string) => {\n const r = await run(() => auth.account.disconnectAgent(id), `disconnect:${id}`)\n if (!r.ok) return\n setList(list.filter((a) => a.id !== id))\n props.onSaved?.({ kind: 'agent.disconnected', id })\n }\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"agents\">\n <Heading f={f}>{f.t.agents}</Heading>\n <Note f={f}>{f.t.agentsHelp}</Note>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <ul className={f.cx('sessions')}>\n {list.map((a) => (\n <li key={a.id} className={f.cx('session')}>\n {a.name || f.t.anAgent}{a.redirectHost ? ` (${a.redirectHost})` : ''} → {a.resource.name}\n {a.scopes.length > 0 ? ` · ${a.scopes.map((s) => s.description || s.name).join(', ')}` : ''} · {when(a.lastUsedAt)}{' '}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading(`disconnect:${a.id}`)} disabled={f.busy} className={f.cx('providerButton')} onClick={() => void disconnect(a.id)}>{f.t.disconnect}</f.Button>\n </li>\n ))}\n </ul>\n </Wrap>\n )\n}\n\n/** Where the person is signed in, and \"sign out everywhere\". */\nfunction SessionsPart({ props, when }: { props: AccountProps; when: (iso: string) => string }) {\n const auth = useAuth()\n const { f, run, general } = useSection(props)\n const [sessions, setSessions] = useState<AccountSession[]>([])\n useEffect(() => {\n void auth.account.sessions().then(setSessions)\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n const end = async () => {\n const r = await run(() => auth.account.signOutEverywhere(), SUBMIT, true)\n if (!r.ok) return\n props.onSaved?.({ kind: 'sessions.ended' })\n // Signed out: the button loads until the page is left, or the application's own way on settles.\n if (props.onSignedOut) f.hold(props.onSignedOut())\n else window.location.assign('/')\n }\n return (\n <Wrap f={f} as=\"section\" slot=\"section\" section=\"sessions\">\n <Heading f={f}>{f.t.sessions}</Heading>\n <ul className={f.cx('sessions')}>\n {sessions.map((s, i) => (\n <li key={i} className={f.cx('session')}>{s.device || f.t.unknownDevice} · {s.ip} · {when(s.createdAt)}</li>\n ))}\n </ul>\n {general && <Say f={f} tone=\"danger\">{f.say(general)}</Say>}\n <f.Button type=\"button\" variant=\"danger\" loading={f.loading()} disabled={f.busy} className={f.cx('button')} onClick={() => void end()}>{f.t.signOutEverywhere}</f.Button>\n </Wrap>\n )\n}\n\n/** The channel phone codes go by, with the application's select. */\nfunction ChannelPick({ f, value, channels, onChange }: { f: Form; value: 'sms' | 'whatsapp'; channels: ('sms' | 'whatsapp')[]; onChange: (c: 'sms' | 'whatsapp') => void }) {\n const id = useId()\n return (\n <Labelled f={f} id={id} label={f.t.channel}>\n <Pick f={f} id={id} name=\"channel\" value={value} options={channels.map((c) => ({ value: c, label: c === 'whatsapp' ? f.t.byWhatsapp : f.t.bySms }))}\n onChange={(c) => onChange(c as 'sms' | 'whatsapp')} />\n </Labelled>\n )\n}\n"],"mappings":"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","names":["import_react","text","Tag","text","label","can","import_jsx_runtime"]}