PushHub Trial Approval Flow

Purpose

PushHub needs an approval-based onboarding path for companies. Public users should request a free trial from the marketing website. Keme super-admins should review the request, provision the company after approval, and send the requester a secure CTA to set the workspace password.

This protects the workspace from unapproved tenant creation, gives Keme visibility into demand, and keeps provisioning/audit trails inside the admin control plane.

Flow

sequenceDiagram
    participant Visitor
    participant Marketing as Marketing website
    participant API as PushHub API
    participant Admin as Keme Admin
    participant Email as Email service
    participant Workspace as Company workspace

    Visitor->>Marketing: Click Request free trial
    Marketing->>API: POST /api/v1/trial-requests
    API-->>Visitor: Request received
    Admin->>API: GET /api/v1/admin/trial-requests
    Admin->>API: POST /api/v1/admin/trial-requests/{id}/approve
    API->>API: Provision company, owner, membership, setup token
    API->>Email: Send setup-password CTA
    API->>API: Record setup-email delivery status
    Email-->>Visitor: Set workspace password
    Admin->>API: Optional POST /admin/trial-requests/{id}/setup-link
    Visitor->>Workspace: Open /setup-password?token=...
    Workspace->>API: Validate token and set password
    API-->>Workspace: Login token / activated account

Implemented API contracts

Public trial request

POST /api/v1/trial-requests

Request body:

{
  "companyName": "My Game Studio",
  "fullName": "Studio Owner",
  "email": "owner@example.com",
  "website": "https://example.com",
  "useCase": "Player lifecycle push campaigns",
  "expectedMonthlyNotifications": 50000,
  "requestedPlanSlug": "free"
}

Response should return a non-secret request summary:

{
  "id": "uuid",
  "status": "Submitted",
  "email": "owner@example.com",
  "createdAt": "2026-07-17T00:00:00Z"
}

Admin review

All admin review endpoints use the existing super-admin route and policy:

Approval should accept review/provisioning options:

{
  "planSlug": "free",
  "trialDays": 14,
  "adminNotes": "Approved for launch trial"
}

Rejection should accept a clear reason:

{
  "adminNotes": "Not a fit for the private beta yet. Follow up next quarter."
}

Setup password

The frontend CTA should use:

https://app.pushhub.kemegames.com/setup-password?token={rawToken}

The raw token must only be sent by email or returned in safe local/test log modes. It must never be stored unhashed.

Implemented setup endpoints:

Token-info response should return only non-secret context:

{
  "email": "owner@example.com",
  "fullName": "Studio Owner",
  "companyName": "My Game Studio",
  "expiresAt": "2026-07-24T00:00:00Z",
  "isValid": true
}

Password setup request:

{
  "token": "raw-token-from-email",
  "password": "new-password"
}

Admin website requirements

The Keme Admin website includes a Trial Requests module at /admin/trial-requests with:

Email delivery uses the configured transactional provider. Resend is preferred when RESEND_API_KEY is configured; SMTP remains available as a fallback provider. Without a configured provider, or if setup email delivery fails, the service writes a fallback message to logs for operational recovery.

Approved requests include a Keme Admin Resend setup action. Because raw setup tokens are never stored, this action creates a fresh setup-password token, invalidates existing open setup tokens for the owner, and sends the new CTA through the configured email provider.

Approved requests also include a Keme Admin Setup link recovery action. This action is super-admin-only, creates a fresh seven-day setup token, invalidates older open setup tokens for the owner, audits trial_request.setup_link_generated, and returns the raw setup URL only in that one response. The normal list/detail response never exposes raw setup tokens.

The admin table shows setup-email delivery state:

Each request also records setup-email attempt count, last attempt time, provider, provider message id when available, last error, and the latest manual link generation time.

Marketing and workspace requirements

Email requirements

Required templates:

Production email delivery prefers Resend when RESEND_API_KEY is configured, then SMTP when Email:Smtp:* is configured, then log fallback. Resend production delivery uses RESEND_API_KEY, RESEND_API_URL, EMAIL_FROM_EMAIL, and EMAIL_FROM_NAME. See docs/EMAIL_DELIVERY.md.

Security requirements

Production CORS requirements

The trial-request form is served from the public marketing host, while the API runs on api.pushhub.kemegames.com. Production must allow all first-party PushHub web origins at both layers:

If the proxy hardcodes only the app origin, browsers on the marketing site will block trial-request responses and show a generic submission failure even when the backend handled the request correctly.

Verification

Run the following before deployment:

npm --prefix frontend run build
docker build -f backend/PushHub.API/Dockerfile -t ghcr.io/kemegames-studio/pushhub-api:workspace-20260706 backend

Run the full smoke script after deployment:

API_BASE=https://api.pushhub.kemegames.com/api/v1 \
APP_BASE=https://app.pushhub.kemegames.com \
PUSHHUB_DIR=/opt/pushhub \
scripts/verify-trial-flow.sh

Production deployment on July 17, 2026 verified: