# Auth Desk > Paste a Better Auth setup — the server `betterAuth({...})` configuration, the > `createAuthClient({...})` call, the route handler, any subset — and run one of four lanes over it: > audit the whole configuration, harden the email-and-password flows, add a second factor, or design > the organization and role model. A free in-browser prescan parses the configuration first and > every lane must reconcile its findings one by one. Live at https://auth-desk.skillsafe.ai/ · API tutorial at https://auth-desk.skillsafe.ai/api.html ## What it is A single-page web app on the SkillSafe platform. One work object — your Better Auth setup — and four lanes over it. The free half runs entirely in the browser; the paid half is one `gpt-terra` run per lane, billed in credits to the signed-in user. Auth Desk is a derived work built on four skills from the `@better-auth/skills` repository: `@better-auth/best-practices`, `@better-auth/emailandpassword`, `@better-auth/twofactor` and `@better-auth/organization`. It is not affiliated with, endorsed by, or operated by the Better Auth project. ## The free lane: what the browser works out on its own No account, no credits, no network. `authscan.js` masks comments and string literal contents, matches brackets on the masked copy, and reads the `betterAuth()` and `createAuthClient()` object literals at depth one. From that it reports: - the framework it can infer (Next.js, Hono, Express or Node, SvelteKit, Nuxt or h3, TanStack Start, Elysia, Deno, Cloudflare Workers) and whether a route handler is mounted at all; - the database adapter (Drizzle, Prisma, MongoDB, Kysely, memory, or a raw driver instance); - the OAuth providers, the server plugin list and the client plugin list; - **plugin parity** — every server plugin matched against the client plugin it requires. A `twoFactor()` on the server with no `twoFactorClient()` on the client compiles cleanly and then has no client methods at runtime; this is the defect the app exists to catch; - a **fourteen-check status table**, each check `present`, `weak`, `missing` or `n-a`: secret handling, database adapter, baseURL and trusted origins, email-and-password sign-in, email verification, password reset, length policy, OAuth provider secrets, session lifetime, cookie attributes, rate limiting, plugin parity, second factor, organization model; - **numbered flags**, each with a severity, a line number and a reason. Among them: `BA-SECRET-LITERAL`, `BA-DB-URL-CREDENTIALS`, `BA-NO-ADAPTER`, `BA-MEMORY-ADAPTER`, `BA-TRUSTED-ORIGINS-WILDCARD`, `BA-HTTP-BASEURL`, `BA-NO-EMAIL-VERIFICATION`, `BA-NO-VERIFY-SENDER`, `BA-NO-RESET-SENDER`, `BA-WEAK-MINLEN`, `BA-AUTOSIGNIN-CONFLICT`, `BA-CUSTOM-HASH`, `BA-OAUTH-LITERAL-SECRET`, `BA-LONG-SESSION`, `BA-INSECURE-COOKIES`, `BA-SAMESITE-NONE`, `BA-CROSS-SUBDOMAIN`, `BA-NO-RATELIMIT`, `BA-RATELIMIT-MEMORY`, `BA-PLUGIN-PARITY`, `BA-NO-2FA`, `BA-2FA-NO-OTP-SENDER`, `BA-NO-ORG`, `BA-ORG-NO-AC`, `BA-ORG-NO-INVITE-SENDER`, `BA-ACCOUNT-LINKING-OPEN`, `BA-NO-HANDLER`; - a **live edit delta**: after a run, the flags at that moment become a baseline and every keystroke since is recounted as cleared / still open / introduced — free, with no second run. ## The four lanes | `task` | What it returns | | --- | --- | | `audit` | Posture verdict, findings with corrected TypeScript, an ordered hardening plan, plugin parity notes, residual risks, and the whole corrected `auth.ts`. | | `password` | The policy numbers justified, all five credential flows (sign-up, verify email, sign-in, reset password, change password) with steps and gaps, and the transactional emails to send. | | `twofactor` | TOTP / OTP / backup-code methods with status, the enrolment sequence with code, the recovery story, and the client calls to wire. | | `organization` | Roles with inheritance, resources with actions, a complete role-by-resource access matrix, the invitation flow, and the gaps the model does not cover. | Every lane is a separate metered run, keyed on `(lane, input, attempt)` so two lanes over the same paste are two distinct runs and a retry can never double-bill. ## The output contract One JSON object per run, the same envelope in every lane: `lane`, `lane_inferred`, `title`, `posture` (`ship-ready` | `harden-first` | `not-production-safe`), `verdict`, `stack`, `adapter`, `summary`, `assumptions`, `open_questions`, `findings[]` (`id`, `title`, `severity`, `area`, `file`, `line`, `evidence`, `why`, `fix`, `fix_code`), `coverage_check[]` (`flag_id`, `status`, `finding_id`, `note`), `artifact` (`kind`, `filename`, `content`), `next_lane` (`lane`, `reason`), and a per-lane `body`. **The reconciliation rule is the point of the app.** `coverage_check` carries exactly one entry per prescan flag id that was sent — no more, no fewer. A flag the model never mentions is displayed to the user as *not accounted for*, so silence is not an option the model has. ## Cost and access Metered: each lane run costs credits against the signed-in user's SkillSafe balance, at the platform default 10% publisher markup. The prescan, the check table, the parity report, the edit delta, the exports and the bundled per-lane examples are free and need no account. `estimate` is called before every run and the reserved hold is shown before anything is charged; the run button is disabled rather than allowed to fail with a 402. ## Privacy The configuration you paste is sent to the model only when you press the run button. The prescan never leaves your browser. Past runs are stored in your own SkillSafe account (an `authruns` collection scoped to you) and mirrored into this browser's `localStorage` so the list paints offline. Nothing is shared with other users, and the app has no server of its own. Literal secrets are stripped before anything is sent or stored. The prescan already locates them exactly - the auth `secret`, each OAuth `clientSecret`, and any password inside a database connection URL - and those spans are replaced with a marker before the configuration is uploaded, before it is written to your account and before it is written to `localStorage`. The corresponding prescan flag is still sent, so the answer still tells you to rotate what leaked; the value itself never leaves the browser. What was removed is named on the page, because the secret is still in your textarea and has already been in your source. ## Links - App: https://auth-desk.skillsafe.ai/ - API and automation: https://auth-desk.skillsafe.ai/api.html - Token management: https://auth-desk.skillsafe.ai/tokens.html - Source skills: https://skillsafe.ai/skill/@better-auth/best-practices · https://skillsafe.ai/skill/@better-auth/emailandpassword · https://skillsafe.ai/skill/@better-auth/twofactor · https://skillsafe.ai/skill/@better-auth/organization - Platform: https://skillsafe.ai/