SaaS platform: one global account, payments on JackAI
CodeJackRabbit is a JackAI platform product. The signup journey starts on codejackrabbit.com, but the target authority model is managed-connected: the account is the one global JackAI account managed at jackaisaas.com — identity, profiles, organizations, plans, subscriptions, payments and entitlements all belong to the Hub. CodeJackRabbit stores no payment credentials, runs no local checkout, and in managed mode never creates a second password identity.
Authority split
| Concern | Owner |
|---|---|
| Product data: reviews, tasks, repositories, usage | CodeJackRabbit (Supabase Postgres) |
| Attachments, reports, release assets | R2 |
| Global identity, profiles, organizations, roles | JackAI platform |
| Payments, plans, subscriptions, entitlements, invoices | JackAI platform |
| Native product accounts and API keys | CodeJackRabbit, only in isolated/federated modes |
Modes (CJR_SAAS_MODE)
isolated-standalone(default;standalonealias): local accounts, no Hub calls. Self-hosted behavior.federated-autonomous: native product accounts stay sovereign and sync with the Hub through the Admin Provider read surface and signed webhooks. This is the transitional connected mode.managed-connected: the global JackAI account is required./signupand/account/loginrender the global-account entry (no local password form);POST /v1/accounts/signup|loginreturns409 global_account_requiredwith the account URL. Cloud features fail closed when the Hub cannot answer. Do not enable this mode in production until the platform completes the activation inintegrations/jackai-saas/README.md.
GET /v1/accounts/config always exposes the secret-free account authority (mode, product, environment, global-account flag, account/portal URLs, native origin) for the website and CLI. cjr auth signup reads it and directs managed users to the global account instead of asking for a local password.
Configuration
CJR_SAAS_MODE=isolated-standalone # federated-autonomous | managed-connected
CJR_SAAS_BASE_URL=https://jackaisaas.com
CJR_SAAS_PORTAL_URL=https://jackaisaas.com
CJR_SAAS_ACCOUNT_URL= # global account entry (default: portal)
CJR_SAAS_PRODUCT_ID=codejackrabbit
CJR_SAAS_ENVIRONMENT_KEY=production
CJR_SAAS_NATIVE_ORIGIN=codejackrabbit://localhost
CJR_SAAS_WEBHOOK_SECRET= # HMAC secret shared with the Hub
CJR_SAAS_SERVICE_TOKEN= # Hub-issued entitlement-read credential
CJR_SAAS_JWKS_URL= # default: <base>/.well-known/jwks.json
Accounts
Native accounts exist only in isolated and federated modes:
- Browser:
GET /signupandGET /account/loginon the API host. - API:
POST /v1/accounts/signupandPOST /v1/accounts/loginwith{ email, password, name?, organizationName? }. The response contains the user, the organization and a freshly issued API key (shown once, stored hashed server-side). - CLI:
cjr auth signup --email <email> [--org <name>].
Passwords are scrypt-hashed and stored apart from user records.
Sync with the platform
- Pull (Hub reads this product) under
/admin-provider/v1/:health(public),manifest,tenants,tenants/{id},tenants/{id}/members,tenants/{id}/entitlements,tenants/{id}/usage,usage/summary. In connected modes, requests must carry a Hub Ed25519 action token (aud=codejackrabbit, scopecodejackrabbit:<domain>:read), verified against the Hub JWKS. - Push (this product notifies the Hub): tenant and member lifecycle events go to
POST <hub>/webhooks/codejackrabbit, signedx-jackai-signature: t=<unix>,v1=<HMAC-SHA256>overt + "." + rawBody, with a monotonic per-productsequence. Events are queued in a durable outbox and retried in order.
Entitlements
Cloud reviews require cloud.reviews; cloud coding tasks require cloud.tasks. In connected modes the transitional gate resolves entitlements from the Hub (GET /v1/kernel/entitlements/organizations/{org}/codejackrabbit) and fails closed with 402 subscription_required and a portal link. The final managed mode authorizes every operation through managed-product-session introspection using the operation policy catalog in integrations/jackai-saas/operation-policy.production.json; the product never authorizes from a local entitlement cache. Local reviews are never gated.
Database
The durable product database is Supabase Postgres; the versioned schema lives in infra/supabase/ and the server connects to it when CJR_DATABASE_URL is set (npm run db:migrate, then GET /health reports storage: "supabase-postgres"). Without a database URL, self-hosted deployments keep the JSON store. Cloudflare deployments must set the database secret, because container disk is ephemeral; until then their data is disposable.
Inclusion package and status
Platform inclusion (deploying jackaisaas.com, registering the product, activating managed sessions) is owned by the JackAI platform team. Everything the product must prepare — connection descriptor (PAUSED), operation policy catalog, registration inputs, secrets to exchange and the activation checklist — lives in integrations/jackai-saas/.