Skip to content
All packs

Capability pack

Accounts

The part that is expensive to get right and cheap to copy. Credentials and OAuth through one Auth.js configuration, password hashing that is not a hand-rolled hash, ownership checked server-side on every action rather than hidden in the UI, and the rights a person has over their own data: export everything, delete the account.

Capabilities

11

All of them are built.

Watched in production

0

11 have never been watched against a real provider.

Provider variables for a fresh project

3

Including the packs it sits on. 3 unset here, each running its documented fallback.

Needed regardless of providers

  • A Postgres database — accounts, sessions, tokens, and the audit log.
  • AUTH_SECRET, which is not a provider key: it is the site's own signing secret.

What is in it

Each row links to where it lives, and carries the state it has in THIS deployment.

  • Credentials sign-in with an httpOnly, encrypted session cookie.

    Auth.js v5 (beta)

  • OAuth providers

    Fallback

    Sign in with Google or GitHub beside email + password. A provider identity is linked to an existing account by email only when the provider verified that email; otherwise the person is told to sign in with their password first. Accounts created this way have no password until they set one.

    Needs AUTH_GOOGLE_ID, AUTH_GOOGLE_SECRET. Without it: Only email and password sign-in is offered; the provider buttons are hidden rather than shown broken.

    Auth.js — Google and GitHub, present only when configured

  • Password hashing

    Ready

    Per-user salt, a memory-hard KDF, and constant-time comparison.

    node:crypto scrypt

  • Email verification

    Fallback

    Sign-up sends a 24h link; recorded but not enforced at sign-in — by design here.

    Needs RESEND_API_KEY. Without it: The verification link prints to the server console.

    Single-use hashed tokens

  • A 30-minute link that burns on use; the change and the burn commit together.

    Needs RESEND_API_KEY. Without it: The reset link prints to the server console.

    Single-use hashed tokens

  • Edge-safe config, plus a second check the page makes for itself.

    Middleware + page checks

  • Authorization on every mutation, not just hidden buttons in the UI.

    Server Actions + Prisma

  • A person can download everything the site holds about them as one JSON file, and delete their account: typed-email confirmation, the password when there is one, the last-admin invariant, orders kept as records without a link, an audit entry that outlives the account, uploads removed from storage.

    Export route + deletion action under the admin-count lock

  • Records that outlive the rows they describe, via a nullable relation.

    Prisma + Server Actions

  • Written in the same transaction as the event they announce; mark-read scoped to the reader in the WHERE clause; the badge polls every 30s only while the tab is visible.

    Notification table + a polling bell

  • The important few notifications go out at once — queued in the same transaction as the notification, sent by the outbox drainer — and the rest arrive as a daily or weekly digest whose window and marker move together. Preferences live on the account so every device agrees; every email carries a signed link that turns both off.

    Needs RESEND_API_KEY. Without it: Digests and immediate mail print to the console.

    Account preferences, MailOutbox rows written with the notification, a digest cron, purpose-scoped signed stop links

First steps in a fork

  1. 1Set AUTH_SECRET and DATABASE_URL, then run the migrations.
  2. 2Create your own account through the site and promote it: npm run admin:grant you@example.com.
  3. 3Add Google or GitHub credentials only if you want them; the buttons appear when the keys do.

What to delete

  • Nothing — every other pack sits on this one.

Provider variables a fresh project would set

  • AUTH_GOOGLE_ID
  • AUTH_GOOGLE_SECRET
  • RESEND_API_KEY

Shaded green: set on this deployment.

The full inventory, with the tests that cover each capability and what has actually been watched working.

Capability inventory