Keme Super-Admin Control Plane
Purpose
Keme Control is the restricted operational interface for PushHub platform administrators. It is served at https://admin.pushhub.kemegames.com/admin and is separate from customer workspaces.
Information architecture
The approval-based onboarding expansion adds Trial Requests as a required admin module. It should sit before Organizations because it is the intake queue that provisions new tenant workspaces after Keme review.
Implemented route: /admin/trial-requests. The module supports submitted/approved/rejected/expired filtering, requester/company search, approve with plan/trial settings, reject with admin notes, setup-email delivery state, resend setup email, admin-only setup-link recovery, and audit-backed review actions.
- Command Center — tenant, user, app, device, and notification totals; newest organizations; tenant health; core-service summary.
- Organizations — searchable tenant directory, status filters, footprint, plan visibility, suspension/reactivation, and plan changes.
- Apps & Environments — cross-tenant project inventory, platform/provider readiness, state, and device footprint.
- Users & Roles — workspace identities, verification/login state, and Keme super-admin operators.
- Plans & Billing — subscription plans, prices, features, and entitlement limits.
- Campaigns & Delivery — cross-tenant campaign activity and queued/sent/delivered/opened/failed delivery totals.
- API Credentials — safe key metadata, prefixes, scopes, last use, and revocation state; never plaintext secrets.
- Integrations — FCM/APNs readiness and the core data-plane connections.
- Audit Trail — system and super-admin events, ordered newest first.
- Data Governance — implemented safeguards and an explicit enterprise-governance backlog.
- Platform Health — API heartbeat and the operational boundary for PostgreSQL, Redis, storage, FCM, and APNs.
- Access & Security — named operators, role assignment, secure invitations, activation/deactivation, invitation history, and session posture.
- Delivery Engine — dedicated worker freshness, durable job states, leases, retry/dead-letter volume, secret-free provider attempts, and audited recovery.
- Provider Fleet — every FCM/APNs/HMS/ADM provider connection across tenants with mode, state, credential version and fingerprint prefix, latest provisioning job, managed company projects, cloud preflight history, the managed-provider emergency stop, and audited retry/suspend/resume. Route:
/admin/provider-fleet.
Competitive baseline
The control-plane scope follows recurring capabilities in OneSignal, Pushwoosh, Knock, Braze, CleverTap, and MoEngage administration: organization/app hierarchy, granular access, API-key governance, environment boundaries, billing and usage, message observability, audit logs, provider configuration, and privacy/security controls. Unsupported enterprise functions are identified as planned rather than represented as active.
Authorization
- Super-admin login uses
POST /api/v1/admin/login. - Administrators recover access at
/admin/forgot-password;POST /api/v1/admin/forgot-passwordsends a 30-minute, single-use Resend link andPOST /api/v1/admin/reset-passwordconsumes it. - Recovery responses are account-enumeration safe, stored tokens are SHA-256 hashes, and issuing or consuming a token revokes older open reset tokens for that operator.
- Super-admin JWTs include
is_super_admin=true,admin_role, and the standard role claim. Ownerhas full control and exclusively manages operator access.Operationsmay perform tenant, trial, and delivery recovery mutations.SupportandReadOnlycan investigate the control plane but cannot mutate production state.- Every authenticated administrator request is revalidated against the live operator record. A deactivated account or stale role claim receives
401and must sign in again. - Every new login creates a server-side session referenced by
admin_session_id. Missing, expired, or revoked sessions are rejected even when the JWT signature and lifetime are otherwise valid. - Optional TOTP MFA uses an encrypted enrollment secret, a five-minute hashed login challenge, and hashed one-time recovery codes. Recovery codes are shown only once.
- Five failed password or second-factor attempts within 15 minutes lock the operator for 15 minutes. Responses remain generic; successful login, password recovery, expiry, or an Owner unlock clears the state.
- At least one active Owner must remain, and an Owner cannot deactivate the account backing the current session.
- The frontend redirects unauthenticated admin routes to
/admin/login. - The public admin hostname redirects
/to/admin. - The configured
SuperAdmin__Emailvalue is the authoritative bootstrap and recovery address. When this address changes, update the matching database identity and production environment together, revoke open recovery tokens, then verify login and Resend delivery before handoff.
Administrative APIs
GET /api/v1/admin/statsPOST /api/v1/admin/forgot-passwordPOST /api/v1/admin/reset-passwordGET /api/v1/admin/trial-requestsGET /api/v1/admin/trial-requests/{id}POST /api/v1/admin/trial-requests/{id}/approvePOST /api/v1/admin/trial-requests/{id}/rejectPOST /api/v1/admin/trial-requests/{id}/resend-setup-emailPOST /api/v1/admin/trial-requests/{id}/setup-linkGET /api/v1/admin/companiesPOST /api/v1/admin/companies/{id}/suspendPOST /api/v1/admin/companies/{id}/activatePOST /api/v1/admin/companies/{id}/change-planGET /api/v1/admin/audit-logsGET /api/v1/admin/appsGET /api/v1/admin/usersGET /api/v1/admin/operatorsGET /api/v1/admin/operators/invitationsPOST /api/v1/admin/operators/invitationsPOST /api/v1/admin/operators/invitations/acceptPOST /api/v1/admin/operators/{id}/activatePOST /api/v1/admin/operators/{id}/deactivatePATCH /api/v1/admin/operators/{id}/rolePOST /api/v1/admin/operators/{id}/unlockGET /api/v1/admin/security/postureGET /api/v1/admin/sessionsDELETE /api/v1/admin/sessions/{id}POST /api/v1/admin/sessions/revoke-othersGET /api/v1/admin/mfa/statusPOST /api/v1/admin/mfa/enrollPOST /api/v1/admin/mfa/confirmPOST /api/v1/admin/mfa/verify-loginPOST /api/v1/admin/mfa/disableGET /api/v1/admin/api-keysGET /api/v1/admin/campaignsGET /api/v1/admin/delivery-summaryGET /api/v1/admin/delivery-engineGET /api/v1/admin/delivery-engine/jobs/{id}POST /api/v1/admin/delivery-engine/jobs/{id}/retryPOST /api/v1/admin/delivery-engine/jobs/{id}/dismissGET /api/v1/admin/provider-fleet— connections with company/app names, credential version, fingerprint prefix, and latest jobGET /api/v1/admin/provider-fleet/status— managed flag, effective emergency stop (deployment and operator sources), control-plane readiness, fleet summary, managed projects, preflightsGET /api/v1/admin/provider-fleet/preflights/{id}— sanitized preflight checksPOST /api/v1/admin/provider-fleet/preflight/{companyId}— read-only Google boundary check (Owner/Operations)POST /api/v1/admin/provider-fleet/emergency-stop— engage or release the operator emergency stop with a reason (Owner/Operations)POST /api/v1/admin/provider-fleet/jobs/{jobId}/retry(Owner/Operations)POST /api/v1/admin/provider-fleet/connections/{id}/suspend— reason required (Owner/Operations)POST /api/v1/admin/provider-fleet/connections/{id}/resume— reason required (Owner/Operations)POST /api/v1/admin/provider-fleet/connections/{id}/verify— non-delivering provider verification (Owner/Operations)GET /api/v1/admin/provider-fleet/connections/{id}/health— latest 25 sanitized health checks
High-risk workflows
Approve a trial request
- Open Trial Requests.
- Filter to submitted requests.
- Review company, requester, website, expected volume, and use case.
- Choose the initial plan and trial length.
- Approve the request.
- Verify the company, owner identity, owner membership, setup-password token, setup-email status, and audit event.
- If setup email shows
FallbackorFailed, use Resend setup after fixing provider configuration, or use Setup link as a manual recovery path.
Reject a trial request
- Open Trial Requests.
- Review the request details.
- Enter an internal note and customer-facing reason when required.
- Reject the request.
- Verify no workspace was provisioned and the rejection audit event exists.
Recover setup access for an approved request
- Open Trial Requests and filter to approved requests.
- Check the Setup email column for attempt count, provider, last attempt time, and error/fallback detail.
- Click Resend setup after email configuration is healthy.
- Click Setup link only when the owner needs manual recovery before email is healthy.
- Copy the generated link from the modal and share it only with the listed workspace owner.
- Verify the
trial_request.setup_link_generatedaudit event exists.
Suspend an organization
Suspension takes effect everywhere within 30 seconds: every provider send for the organization stops (CompanySuspended), scheduled campaigns fail instead of retrying, existing workspace sessions and API keys become read-only (403 COMPANY_SUSPENDED on changes), and SDK installations are refused.
- Locate the organization in Tenant Directory.
- Open its action control.
- Enter a meaningful reason of at least five characters.
- Confirm suspension.
- Verify the new status and the
admin.company.suspendedaudit event.
Reactivate an organization
- Locate the suspended organization.
- Confirm reactivation.
- Verify the active status and the
admin.company.activatedaudit event.
Change a plan
- Select the current plan badge in Tenant Directory.
- Choose the new plan.
- Confirm the entitlement change.
- Verify the organization plan and the
admin.company.plan_changedaudit event.
Stop managed providers in an emergency
- Open Provider Fleet.
- Select Engage emergency stop and enter a reason of at least five characters.
- Verify the banner reports the operator stop as engaged and the
admin.provider_emergency_stop.engagedaudit event exists. - New managed provisioning and every send through a PushHub-managed connection stop immediately on all API and worker instances. Customer-owned (BYO) connections keep sending.
- Releasing the operator stop does not override the deployment setting
MANAGED_PROVIDERS_EMERGENCY_STOP; both must be released before managed providers run.
Verify a provider connection
- Open Provider Fleet and select Verify on the connection.
- PushHub proves provider authority without delivering a notification and records a health check. A definitive rejection marks the connection
Failed; an unreachable provider marks itDegraded. - Verify the
admin.provider_connection.verifiedaudit event. Scheduled checks run automatically in the worker host every 24 hours (hourly forDegraded).
Suspend or resume a provider connection
- Open Provider Fleet and locate the connection.
- Select Suspend (or Resume) and enter an operator reason.
- A suspended connection stops new sends in any mode; campaigns targeting it fail with
ProviderSuspendedinstead of retrying. Credentials, bundles, and evidence are retained. - Resuming returns a previously verified connection to
Ready; a connection that never completed verification returns toPending. - Verify the
admin.provider_connection.suspendedoradmin.provider_connection.resumedaudit event.
Recover a dead-lettered dispatch job
- Open Delivery Engine and filter to DeadLettered.
- Inspect the job source, company/app ownership, normalized failure, and attempt history.
- Correct provider configuration or the reported operational fault before replay.
- Enter a recovery reason of at least five characters and retry the job. Final recipient outcomes remain skipped.
- Dismiss only when no replay should occur; this is terminal and audited.
- Verify
admin.dispatch_job_retriedoradmin.dispatch_job_dismissedin Audit Trail.
Invite and activate a Keme operator
- Sign in as an
Ownerand open Access & Security. - Enter the operator's individual email and name, then choose the least-privilege role that fits their work.
- Send the invitation and confirm it appears as Pending in invitation history.
- The recipient follows the emailed CTA within three days and creates a strong password.
- Confirm the named account appears as Active and the invitation shows Accepted.
- Verify
admin.operator.invitedandadmin.operator.invitation_acceptedin Audit Trail.
Role changes and deactivation take effect immediately for existing JWTs. Use deactivation when access must stop; do not share or repurpose another operator's credentials.
Enable MFA and store recovery codes
- Open Access & Security and choose Set up MFA.
- Add the displayed setup key to a standards-compatible authenticator application.
- Enter the current six-digit code and confirm enrollment.
- Copy all ten recovery codes immediately into the approved secrets manager. They are never displayed again.
- Verify MFA shows Enabled and confirm
admin.mfa.enabledin Audit Trail. - Sign out and confirm password login advances to the second-factor challenge.
Disabling MFA requires the current password and a valid authenticator or recovery code. The operation revokes other sessions and is audited.
Revoke an administrator session
- Open Access & Security and review Active sessions.
- Match the user agent, IP, and last-seen time before revoking a device.
- Use Sign out others for an incident response or after suspected credential exposure.
- Current and revoked tokens are checked against server state on every request.
Recover a locked administrator
- Confirm the operator through a separate trusted channel; do not rely on the lockout email alone.
- Review recent
admin.login.*andadmin.mfa.*events, source IPs, and sessions in Access & Security and Audit Trail. - For expected failures, an Owner can use Unlock. Otherwise revoke sessions, require password recovery, and preserve the audit evidence.
- Confirm the operator receives the unlock or password-change security alert and can complete MFA.
Rotate credentials and retire bootstrap access
- Maintain at least two active named
Owneridentities. Each must enable MFA, store recovery codes in the approved secrets manager, and test password recovery independently. - In Access & Security, wait for Bootstrap retirement ready. This requires two active non-bootstrap MFA-protected operators and two active Owners.
- Rotate
Jwt__Keyonly during a scheduled maintenance window; this signs out every workspace and administrator session. Redeploy all API instances together and verify authentication, health, workers, and callbacks. - Rotate
Security__DataEncryptionKeyby moving the current value intoSecurity__DataEncryptionKeysRetired, setting a new 32-byte primary key, redeploying, and verifying encrypted provider/MFA reads before removing any retired key. Never remove a retired key until all protected values have been rewritten. - Rotate the bootstrap password through administrator recovery, revoke all of its sessions, store the replacement only in the approved break-glass vault, and stop using it for daily operations.
- Final deactivation or removal of the environment bootstrap secret is a deliberate production-owner action after recovery drills pass. Do not automate it from a deployment.
- Record the rotation date, operator, affected secret version, verification evidence, and rollback owner in the operational change record—never the secret value.
Implementation
- Layout:
frontend/src/components/layout/AdminLayout.tsx - Sign-in:
frontend/src/pages/admin/AdminLoginPage.tsx - Password recovery:
frontend/src/pages/auth/PasswordRecoveryPage.tsx - Operator invitation activation:
frontend/src/pages/admin/AdminAcceptInvitationPage.tsx - Command Center:
frontend/src/pages/admin/AdminDashboardPage.tsx - Trial Requests:
frontend/src/pages/admin/AdminTrialRequestsPage.tsx - Tenant Directory:
frontend/src/pages/admin/AdminCompaniesPage.tsx - Remaining operations pages:
frontend/src/pages/admin/AdminOperationsPages.tsx - Cross-tenant platform modules:
frontend/src/pages/admin/AdminPlatformPages.tsx - Delivery engine:
frontend/src/pages/admin/AdminDeliveryEnginePage.tsx - API controller:
backend/PushHub.API/Controllers/SuperAdminController.cs - Live operator-session enforcement:
backend/PushHub.API/Middleware/ActiveSuperAdminMiddleware.cs - Trial request API controller:
backend/PushHub.API/Controllers/AdminTrialRequestsController.cs - Application handlers:
backend/PushHub.Application/Features/SuperAdmin/ - Trial request handlers:
backend/PushHub.Application/Features/TrialRequests/
Cross-tenant read-only inventory endpoints use a dedicated EF Core read model in the super-admin controller. Administrative writes continue through MediatR command handlers so validation and audit creation remain centralized.
Verification
- Build the API and frontend in Release/production mode.
- Confirm unauthenticated admin routes redirect to sign-in.
- Confirm valid super-admin login returns an access token.
- Confirm stats, companies, plans, audit, and health requests succeed under the admin token.
- Exercise destructive workflows only with a designated test tenant.
- Verify desktop and mobile layouts and check the browser console for runtime errors.
Production verification on July 17, 2026 confirmed admin authentication, trial request listing, protected unauthenticated access, public intake, and rejection workflow. The live smoke request was rejected immediately so no test tenant was provisioned.
Production identity verification on September 14, 2026 confirmed the corrected managed-studio administrator mailbox, unchanged password authentication, protected-module access, revocation of older recovery links, and successful Resend delivery to the corrected address. No credential or API key is stored in this repository.
Phase Three verification is documented in docs/PHASE_THREE.md. Delivery-engine smoke checks are read-only; retry and dismissal must use a designated test job.
Managed provider fleet
Keme operators can inspect every provider connection and its latest provisioning job at GET /api/v1/admin/provider-fleet. Failed or scheduled jobs may be requeued through the audited retry endpoint; credentials and configuration payloads are never returned. The feature remains disabled until the infrastructure and physical-device gates in docs/MANAGED_PUSH_INFRASTRUCTURE.md are complete.