@crossplatformai/auth
v0.28.0
Published
Shared authentication module for CrossPlatform.ai projects.
Readme
@crossplatformai/auth
Shared authentication behavior for CrossPlatform.ai apps.
This package is frameworkless at its core. Apps wire it into Hono, Next.js, workers, Electron, React Native, or other runtimes with thin adapters.
What this module owns today
The module currently provides:
- auth domain types and contracts
- client auth utilities and API client helpers
- token lifecycle management
- JWT timing and introspection helpers
- auth storage abstractions for client platforms
- server-side JWT and session services
- storage and cache adapter interfaces and base classes
- verification and cache key utilities
Exports are organized as:
@crossplatformai/author@crossplatformai/auth/serverfor server-safe exports@crossplatformai/auth/clientfor client-side lifecycle and auth helpers@crossplatformai/auth/corefor storage and core auth manager primitives@crossplatformai/auth/typesfor shared contracts
Framework Boundary
The package is intentionally frameworkless.
Keep in this module:
- auth rules
- token and session lifecycle behavior
- typed contracts for storage, cache, device, email, JWT, and ID generation
- pure validation and orchestration logic
- optional behavioral bindings in framework-specific subpaths
Keep in apps:
- Hono route handlers
- Next.js route handlers
- cookies and SSR integration
- request parsing and response shaping
- Drizzle schema and migrations
- typed database clients
- storage adapter implementations against app-local tables
A good rule:
- module = auth behavior
- app = framework wiring and persistence ownership
Why this boundary matters
We want shared auth behavior across repos without recreating a shared database package.
That means:
crossplatform.aican use Hono wrappersmickythompson.comcan use Next.js route handlersthompsonmarkets.comcan reuse the same auth rules later- each app still owns its schema, DB client, and migrations locally
Current package surface
Server-side primitives
Use @crossplatformai/auth/server when you need:
JWTServiceSessionServiceBaseStorageAdapterBaseCacheAdapter- server auth types and guards
- cache and verification utilities
Client-side primitives
Use @crossplatformai/auth/client when you need:
- token lifecycle helpers
- JWT timing helpers
- auth client utilities for app auth flows
Core primitives
Use @crossplatformai/auth/core when you need:
AuthManagerAuthStorageApiClient- core auth state and manager types
Dependency Injection
This module prefers host-owned implementations.
Apps should provide:
- storage implementations
- cache implementations
- JWT signing and verification clients
- ID generators
- device and email implementations when needed
Example:
import { JWTService } from '@crossplatformai/auth/server';
import type {
StorageAdapter,
CacheAdapter,
JWTClient,
IdClient,
} from '@crossplatformai/auth/server';
const jwtService = new JWTService({
secret,
jwtClient,
idGenerator,
accessTokenExpiry: '15m',
refreshTokenExpiry: '30d',
});Storage and Cache Contracts
The server side of this package already defines interface boundaries for:
StorageAdapterCacheAdapterEmailProviderDeviceServiceStorageInterfacefor client-side token storage
These contracts are the right place to keep shared auth expectations.
App repos should implement those contracts against their own infrastructure.
Frameworkless auth orchestration
This package is the home for shared frameworkless auth orchestration across
crossplatform.ai, mickythompson.com, and thompsonmarkets.com.
Current shared server-side behavior includes:
- structured session validation helpers
- refresh token rotation orchestration
- verify/authenticate orchestration
- typed success and failure result objects for route adapters
- shared policy decisions like stale refresh handling and revocation semantics
This package should not add:
- shared Drizzle schema
- shared migrations
- shared DB clients
- framework-owned request handlers
Recommended route pattern
Apps should keep route handlers thin.
Example shape:
const result = await authService.refreshSession({
refreshToken,
storage,
cache,
jwt,
});
if (!result.ok) {
return mapAuthFailureToFrameworkResponse(result);
}
return mapAuthSuccessToFrameworkResponse(result);This lets the module own the auth rule while the app owns the framework response.
Refresh Rotation and Security Posture
Refresh token rotation stores the current refresh-token JTI on the session and uses adapter-owned atomic rotation to replace it. The immediately prior JTI is kept with a short grace window so duplicate refresh requests and lost refresh responses can recover without revoking the active session.
Refresh failures are classified by the shared client coordinator:
- typed auth failures such as invalid, expired, revoked, or stale refresh tokens stay non-retryable and are returned to the app as structured failures
- stale refresh-token failures do not revoke the session
- transport failures, malformed refresh responses, and HTTP
5xxrefresh responses are transient and do not clear stored tokens
Apps should log refresh outcomes without access tokens, refresh tokens, device fingerprints, or derived automation secrets. Safe fields include outcome, failure reason, recovery mode, user ID, session ID, and HTTP status.
Client Configuration
AuthClient exposes configuration for app-owned auth request wiring:
authEndpointCredentialscontrols thecredentialsmode for auth endpoints and defaults toincludegetRequestHeaderslets apps add request metadata while the client protects the authenticatedAuthorizationandContent-TypeheadersrefreshDeviceFingerprintcontrols whether a device fingerprint is included on refresh requests and whether a fingerprint returned by the refresh response is persisted
ApiClient wraps AuthClient for bearer-token API calls. On transient refresh
failures it throws a 503-style AuthError and keeps local tokens intact so a
later request can recover.
Test Auth Posture
@crossplatformai/auth/test-auth contains automation-only helpers for local,
development, and staging test auth flows. The helper derives a per-app secret
from APP_KEY and APP_SLUG, validates it with timing-safe comparison, and
standardizes test-auth headers.
Apps own the test-auth route, environment gate, user bootstrap, and storage writes. Production environments should treat test-auth routes as unavailable.
Release Posture
This package is source-exported. Publish preparation should keep files:
["src"], TypeScript source exports, and ESM-only package metadata intact unless
a real runtime requirement needs generated output.
For a .next or stable release, publish from the final reviewed HEAD after all
consumer-facing commits land and final QA passes. Do not publish from an
intermediate commit in the auth rollout stack, and do not run release or
registry-mutating commands while consumer repos still rely on temporary
link: dependencies.
React boundary
React is allowed only for behavioral bindings.
Good candidates:
- hooks
- providers
- lifecycle adapters
- context wiring
Not good candidates:
- branded forms
- auth pages
- styled components
- product-specific layouts
What this module should not become
This module should not become:
- a shared app
- a shared database package
- a place for product-specific auth UX
- a place for framework-specific route trees
- a home for presentation components
Guidance for consuming apps
If you are adding auth to a new app:
- use this module for shared auth behavior and contracts
- keep DB ownership in the app
- implement an app-local storage adapter over local schema
- keep route handlers thin and framework-specific
- add only the minimum app-local glue needed for cookies, headers, and SSR
Near-term DRY goal
For parity between crossplatform.ai and mickythompson.com, and to prepare thompsonmarkets.com, the next extraction target should be:
- shared auth domain orchestration in
@crossplatformai/auth - app-owned storage adapters and route wrappers in each consuming repo
That is the strongest reusable boundary we have identified so far.
License
Apache-2.0
