jampress.pw
PhilosophyDocsRoadmapPlaygroundGitHub

Documentation

PhilosophyThree tracks, modular scaling, and the foundation rules that shape every package.ArchitectureStable viewer contracts with swappable provider/storage internals.Astro Site BlueprintsFleet, collection, site, storage-topology, and downstream release boundaries.Capability FoundryReusable upstream capabilities with independent product and owner repositories.SecurityThreat model, token/session controls, and rate-limit requirements.RoadmapPhase-by-phase path from DIY auth to WordPress bridge and adapters.Auth Adoption PlanConcrete rollout order and milestones for zip, lobpress, inbox, DesBio, and DBScript.Host App IntegrationHow Astro and Workers apps wire middleware, hooks, and routes.Provider AdaptersThe AuthAdapter contract and migration path across login providers.Data ModelD1/MySQL schemas for identities, sessions, tokens, and rate limits.

Security

Threat model

This SDK handles authentication for web applications. The primary threats are:

  • Token theft/replay: Magic-link tokens intercepted in transit or stolen from storage
  • Session hijacking: Session cookies stolen via XSS, MITM, or cookie theft
  • Brute force: Automated attempts to guess magic-link tokens
  • Email enumeration: Attackers determining which emails have accounts
  • CSRF: State-changing auth endpoints called by malicious sites
  • Token reuse: Magic-link tokens consumed more than once
  • Audit trail poisoning: Tokens or sensitive data leaking into logs

Security requirements (v1)

Token security

  • Magic-link tokens MUST be hashed (SHA-256) before storage. Raw tokens are never persisted.
  • Tokens MUST have a configurable TTL (default: 15 minutes)
  • Tokens MUST be single-use. D1 consumption uses one ordered batch and requires a successful delete.
  • Creating a token invalidates every older outstanding token for the same email.
  • A failed email send deletes the newly issued token before returning the generic login response.
  • Token generation MUST use crypto.getRandomValues() with sufficient entropy (minimum 32 bytes, hex-encoded)
  • Email GETs MUST NOT consume auth tokens; consumption requires an explicit same-origin POST.
  • Expired tokens MUST be cleaned up on a schedule (D1: scheduled Worker, MySQL: cron/event)

Session security

  • Session cookies MUST be HttpOnly, Secure, SameSite=Lax, path /
  • Cookie name MUST be configurable per host app (default: jp_session)
  • Session IDs MUST be cryptographically random (minimum 32 bytes)
  • Only SHA-256 session hashes are persisted; raw bearer session IDs remain in the cookie only.
  • Sessions MUST have a configurable TTL (default: 7 days)
  • Session rotation: on every completeLogin, issue a new session ID (never reuse)
  • Session revocation: logout MUST delete the session from storage AND clear the cookie
  • Provide a revokeAllSessions(userId) method for emergency use

Rate limiting

  • requestLogin (magic-link send): rate limit per email (max 5 per 15 minutes) and per IP (max 20 per 15 minutes)
  • completeLogin (token verification): rate limit per IP (max 10 per 15 minutes)
  • The built-in D1 adapter atomically counts and decides each attempt; concurrent requests cannot all pass a separate check before incrementing.
  • Rate limit responses do not leak whether the email exists.
  • Third-party storage adapters should implement optional consumeRateLimit; the compatibility checkRateLimit/incrementRateLimit fallback remains non-atomic.

CSRF protection

  • All state-changing auth endpoints (requestLogin, completeLogin, logout) MUST require POST and verify origin
  • Use Origin header check against a configurable allowed-origins list
  • For the subscribe widget: the form submission endpoint MUST also be origin-checked

Email enumeration resistance

  • requestLogin MUST return the same response regardless of whether the email exists or is authorized
  • Host authorization MUST run before email, before session creation, and on every session resolution.

Redirect safety

  • redirectTo MUST be a same-origin application path, never an absolute URL.
  • Magic-link builders receive only normalized paths.
  • Logout and successful verification responses return only normalized paths.
  • The subscribe widget intentionally has a known enumeration characteristic (different email content for known vs unknown users). This is documented as a deliberate tradeoff. Mitigation: identical UI response, identical subject line, identical email template structure.

Logging hygiene

  • Auth adapter logs never receive raw tokens, token prefixes, session IDs, session prefixes, email addresses, or magic-link URLs.
  • Auth adapter warnings are structured JSON containing only action, safe error code, and error category; arbitrary exception messages are not logged.
  • Add a host-owned audit sink for timestamp, request metadata, and result without putting credentials or personal data in generic Worker logs.

Email delivery observability

  • Provider message IDs and non-secret delivery states are stored in the host-owned D1.
  • Cloudflare lifecycle events are schema-validated before storage.
  • Shared-domain events update only message IDs already correlated by the host; unknown recipients, subjects, and message bodies are never copied into its D1.
  • Queue logs exclude recipient addresses, subjects, SMTP details, and message IDs.
  • Repeated provider events are idempotent by provider event ID.

Dependency management

  • Renovate or Dependabot enabled on the repo
  • pnpm audit runs in CI on every PR
  • No runtime dependencies in auth-core (contracts only)
  • Minimize dependencies in provider packages — prefer Web Crypto API and platform primitives

Deployment exposure

  • Production Worker configs disable workers.dev and Preview URLs; private host apps should additionally use Worker-attached Cloudflare Access.

Security non-goals (v1)

Things we're explicitly not building yet:

  • MFA / TOTP / WebAuthn (defer to Firebase or BetterAuth adapters)
  • Account lockout (rate limiting is sufficient for magic-link flows)
  • IP allowlisting
  • WAF-level protections (handled by Cloudflare at the edge)
  • Penetration testing (manual review is sufficient at our current scale)

Security review process

Use .ai/prompts/security-review.md to run a security audit against any version of the codebase. The prompt is designed for a coding agent (Codex or Claude Code) to systematically check each item above.

Incident response

If a vulnerability is discovered:

  1. Determine blast radius (which host apps are affected)
  2. If token/session compromise: rotate all secrets, revoke all sessions via revokeAllSessions
  3. Fix in auth-core or relevant package
  4. Bump version, deploy to all affected host apps
  5. Document in SECURITY-CHANGELOG.md (create when first needed)