Experimental public releasev0.3.0Cloudflare Workers + D1

Share authentication policy. Never share identity state.

A focused email-code and passkey foundation for Santiago-owned Cloudflare applications. Better Auth handles the protocol; each product decides who may sign in and keeps its own users, sessions, secrets, cookies, and recovery path.

Available on npm as experimental 0.x. Pin the version and keep the existing login and recovery path while verifying a consumer on its real origin.npm package page

Architecture

One policy package, isolated applications

The reusable layer stays deliberately narrow. Product authorization and operational recovery remain local.

  1. 01

    Validate the boundary

    Reject unexpected origins and identities before protocol handlers touch state.

  2. 02

    Run proven protocols

    Better Auth manages hashed email codes, sessions, and WebAuthn verification.

  3. 03

    Persist per product

    Cloudflare D1 stores rate limits and authentication records for one application only.

  4. 04

    Authorize locally

    The consuming product resolves the session and applies its own domain permissions.

Security posture

Secure defaults that remain visible

Controls are explicit in code and tests so a consumer can review the boundary before adopting it.

A

Private email discovery

Rejected addresses receive the same success-shaped response without code delivery or user creation.

B

Phishing-resistant passkeys

Discoverable credentials and user verification are required for the exact application hostname.

C

Durable rate limits

Limits are persisted in D1 instead of disappearing whenever a Worker isolate is recycled.

D

Production transport

Non-local origins require HTTPS and secure cookies. Unsafe requests require an exact Origin match.

Integration

Small API, deliberate cutover

The package is public for controlled evaluation. Copy the canonical D1 schema into an app-owned additive migration, configure exact browser and auth server origins, then validate email delivery and passkeys before cutting over.

Read the multi-user integration guideCheck npm publication status

Install the pinned protocol packages

shell
pnpm add @santi020k/auth-cloudflare hono

Mount and protect routes

typescript
import { createOwnerAuth } from
  "@santi020k/auth-cloudflare";

app.all("/api/auth/*", (context) => {
  const ownerAuth = createOwnerAuth({
    appName: "Example owner workspace",
    applicationOrigin: context.env.APPLICATION_ORIGIN,
    authServerURL: context.env.AUTH_SERVER_URL,
    cookiePrefix: "example-owner",
    database: context.env.AUTH_DB,
    ownerEmail: context.env.OWNER_EMAIL,
    secret: context.env.AUTH_SECRET,
    sendVerificationOTP: ({ email, otp }) =>
      sendLoginCode(context.env, email, otp),
    waitUntil: (task) => {
      context.executionCtx.waitUntil(task);
    },
  });
  return ownerAuth.handler(context.req.raw);
});

Release discipline

Production is a verified state, not a label

The repository can prove package behavior and publish an experimental release. Consumer-origin evidence is still required before calling an integration production-ready or the package stable.

Automated now

Repository gates

  • Strict TypeScript, ESLint, spelling, formatting, and unused-code checks
  • D1 integration, package-contract, security, accessibility, and responsive browser tests
  • Quality-managed hooks, Commitprompt enforcement, PR labels, CodeQL, and dependency updates
  • Release-branch npm automation, provenance, immutable version tags, and GitHub Releases
Required before stable

Consumer adoption evidence

  • Separate additive migrations in PostLens Planner and Observatory
  • Email delivery and recovery rehearsal without exposing codes
  • Passkey registration and sign-in on each final HTTPS origin

Designed for controlled adoption

Make the shared part dependable—and the private parts unmistakable.

Start with the checklist