Platform/26edge-auth

edge-auth

GitHub: Stackbilt-dev/edge-auth (private) · TypeScript

The auth and payment worker for the Stackbilt ecosystem. All session validation, API key checks, billing flows, and entitlement reads across the platform route through edge-auth via Cloudflare service binding RPC — no other worker holds Stripe credentials or manages auth state directly.

Powered by Better Auth + D1. OAuth 2.1, SSO, and API key auth supported.


Auth

Session Validation

Two paths in validateSession():

  1. Session cookiebetter-auth.session_token (dev) / __Secure-better-auth.session_token (prod) → validated via RPC
  2. API keyAuthorization: Bearer ea_*validateApiKey() RPC

Edge auth middleware runs at the nearest Cloudflare POP via the AUTH_SERVICE service binding — no origin round-trip for auth checks.

API Keys

API keys use the ea_* prefix. Each key resolves to a userId, orgId, and plan tier. Callers can use GET /api/account/me on the platform API to retrieve caller identity — useful for tier-aware routing in CI scripts and agent workflows.

img-forge API keys use the imgf_* prefix and are validated via a separate RPC path on the same service.


RPC Interface

All consumers (stackbilt-web, img-forge, tarotscript, codebeast) reach edge-auth via Cloudflare service binding, not HTTP. The binding is AUTH_SERVICE.

Key RPC methods:

Method Description
validateSession(cookie) Validate a session cookie, return user + plan
validateApiKey(key) Validate an ea_* or imgf_* API key, return user + plan
getEntitlements(userId) Return current plan tier, feature flags, quota state
createCheckoutSession(userId, plan) Create a Stripe Checkout URL for plan upgrade
createPortalSession(userId) Create a Stripe Billing Portal URL
downgradeToFree(userId) Cancel active subscription; returns canceled, no_subscription, or already_canceled

Billing

Stripe is in live mode (acct_1T8cxHL8cDQ0gdtT). All Stripe API calls live in edge-auth — consuming workers hold no Stripe credentials.

Checkout Flow

createCheckoutSession() performs a pre-flight getEntitlements() check and returns 409 {code: "already_subscribed"} if the tenant is already on a paid tier. Otherwise returns a Stripe Checkout URL.

Portal Flow

createPortalSession() returns a Stripe Billing Portal URL. Returns 422 with actionable copy if the tenant has no Stripe customer record (comp/admin/lapsed accounts).

Downgrade Flow

downgradeToFree() has three outcomes:

Outcome Meaning
canceled Active Stripe subscription — canceled immediately (DELETE /subscriptions/{id}), not at period end. Tier flips to free right away; effectiveAt is the cancellation time, not a future date.
no_subscription Admin/comp account; immediate tier flip
already_canceled Dangling stripe_subscription_id; immediate tier flip

For Agency tenants specifically, cancellation does not forfeit unused credits immediately — remaining balance stays spendable for a 45-day grace period even though the tier has already reverted to free. See img-forge’s Usage Limits for the credit-side behavior.

Stripe webhooks are handled entirely by edge-auth — there is no webhook handler in any consuming worker.


Storage

  • D1 — user records, session state, API key metadata, subscription state
  • KV — rate-limit state, entitlement cache

Auth Flow (OAuth)

OAuth sign-in (GitHub, Google) is handled at auth.stackbilt.dev. On completion, a session cookie is issued and the user is redirected back to the originating platform.

SSO is available on Pro and Agency tiers.


Consumers

Worker Binding Uses
stackbilt-web AUTH_SERVICE Session/API key validation, billing, entitlements
img-forge AUTH_SERVICE imgf_* key validation, quota
tarotscript (via platform routing) Plan-tier enforcement
codebeast AUTH_SERVICE Identity on review sessions