# HexaHost GameCloud — Implementation Status Last updated: 2026-06-26 ## Current phase: WHMCS hardening — mTLS + Product mappings ✅ ### mTLS integration API | Area | Status | Notes | |------|--------|-------| | Optional enforcement | Done | `INTEGRATION_MTLS_ENABLED=true` | | Fingerprint binding | Done | Per `WhmcsInstallation` | | Guard | Done | HMAC + mTLS layered | | API | Done | `GET/PUT .../mtls/*` | | PHP clients | Done | Addon + server module curl mTLS | | nginx example | Done | `deploy/nginx/integration-mtls.conf.example` | | Docs | Done | `docs/integrations/whmcs/mtls.md` | ### Product mapping UI | Area | Status | Notes | |------|--------|-------| | Addon mappings page | Done | WHMCS product → GameCloud plan | | Validation API | Done | `POST /catalog/validate-plan` | | WHMCS table | Done | `mod_hexagamecloud_product_mappings` | | Server module hook | Done | `ProductMapping.php` resolver | | Docs | Done | `docs/integrations/whmcs/product-mappings.md` | ### Abnahmekriterium - [x] Addon maps WHMCS products to validated GameCloud plan slugs - [x] Provisioning uses mapping when active - [x] mTLS can be enabled without breaking dev (HMAC-only default) - [ ] Manual E2E: nginx mTLS + WHMCS provision --- ## WHMCS Addon Dashboard ✅ ### WHMCS Addon module completed | Area | Status | Notes | |------|--------|-------| | Addon PHP module | Done | Dashboard, events, reconciliation UI | | Module tables | Done | `mod_hexagamecloud_*` on activation | | Event poller | Done | Manual + daily cron hook | | Dashboard API | Done | `GET /integrations/whmcs/dashboard/stats` | | Cron hook | Done | `integrations/whmcs/hooks/hexagamecloud.php` | | Docs | Done | `docs/integrations/whmcs/addon-module.md` | ### Billing providers | Provider | Status | Notes | |----------|--------|-------| | WHMCS | Done | **Production default** (`BILLING_PROVIDER=whmcs`) | | Internal | Done | Dev / free tier credits | | Stripe | Stub | Optional fallback webhook — inactive unless `BILLING_PROVIDER=stripe` | See `docs/billing/providers.md`. ### Abnahmekriterium Addon - [x] WHMCS admin dashboard shows API health and sync stats - [x] Event poll + ack from addon UI and cron hook - [x] Reconciliation dry-run from addon UI - [ ] Manual E2E: activate addon on WHMCS host --- ## WHMCS Phase E + F — Sync & Usage Billing ✅ ### WHMCS Phase E completed | Area | Status | Notes | |------|--------|-------| | ListAccounts API | Done | `GET /integrations/whmcs/accounts` | | Service import | Done | `POST .../services/import` | | Reconciliation | Done | Full + per-service, severity classification | | Integration events | Done | Cursor poll + ack/dead-letter | | Worker daily sync | Done | 03:00 UTC reconciliation tick | | WHMCS PHP | Done | `ListAccounts`, reconcile/import client | | Docs | Done | `docs/integrations/whmcs/reconciliation.md` | ### WHMCS Phase F completed | Area | Status | Notes | |------|--------|-------| | Usage metrics API | Done | `GET .../services/:id/usage` | | Usage adjustments | Done | `POST .../usage/adjustments` | | Export audit | Done | `WhmcsUsageExport` + content hash | | Test mode | Done | `testMode=true` → DRAFT exports | | WHMCS PHP | Done | `MetricProvider`, `UsageUpdate` | | Docs | Done | `docs/integrations/whmcs/usage-billing.md` | ### Abnahmekriterium Phase E - [x] ListAccounts liefert alle verknüpften Services - [x] Reconciliation erkennt Status-, Plan- und Orphan-Drift - [x] Events cursorbasiert mit Ack/Dead-Letter - [x] Import bestehender Server möglich - [ ] Manual E2E: WHMCS Server-Sync + Reconcile-Button ### Abnahmekriterium Phase F - [x] Metriken aus `usage_records` aggregiert (UTC-Perioden) - [x] Idempotente Exporte mit Hash - [x] Adjustments ohne Rohdaten-Mutation - [x] WHMCS MetricProvider + UsageUpdate - [ ] Manual E2E: WHMCS Usage Metrics Abrechnungslauf --- ## WHMCS Phase D — SSO ✅ ### WHMCS Phase D completed | Area | Status | Notes | |------|--------|-------| | `SsoTicket` model | Done | Hashed token, 60s TTL, single use | | Impersonation sessions | Done | `UserSession.isImpersonation` + audit | | API create SSO | Done | `POST .../services/:id/sso` | | API consume SSO | Done | `POST /auth/sso/consume` → session cookie | | Path allowlist | Done | Server panel routes only | | Web SSO page | Done | `/auth/sso?ticket=` + impersonation banner | | WHMCS PHP SSO | Done | `ServiceSingleSignOn`, `AdminSingleSignOn` | | Docs | Done | `docs/integrations/whmcs/sso.md` | ### Abnahmekriterium Phase D - [x] WHMCS „Server verwalten“ erzeugt einmaliges SSO-Ticket - [x] Ticket-Einlösung setzt Session-Cookie und leitet auf Server-Panel weiter - [x] Admin-SSO markiert Impersonation-Session sichtbar im Panel - [x] Gesperrte/beendete Services erhalten kein SSO-Ticket - [ ] Manual E2E: WHMCS client area → panel → server detail ### Local SSO test 1. `pnpm db:migrate && pnpm db:seed` (includes `local-dev-whmcs`) 2. Provision a service via WHMCS API (`PUT .../clients/1`, `POST .../services`) 3. `POST /api/v1/integrations/whmcs/services/{externalServiceId}/sso` (signed) 4. Open `{APP_URL}/auth/sso?ticket={token}` → redirects to `/servers/{id}` 5. Admin SSO: same flow with `kind=admin` → impersonation banner visible See [docs/integrations/whmcs/sso.md](integrations/whmcs/sso.md). --- ## Phase 9 — WHMCS integration and production hardening ✅ ### Phase 9 completed | Area | Status | Notes | |------|--------|-------| | WHMCS Prisma models | Done | Installations, client/service links, idempotent operations | | `@hexahost/integration-auth` | Done | HMAC-SHA256 request signing | | WHMCS Integration API | Done | `/api/v1/integrations/whmcs/*` with nonce replay protection | | Billing suspension | Done | `billingSuspendedAt`, blocks start/join-to-start | | Billing provider mode | Done | `BILLING_PROVIDER=internal\|whmcs` | | RFC2136 DNS provider | Done | `nsupdate` + worker DNS sync tick | | WHMCS PHP module | Done | Create/Suspend/Unsuspend/Terminate/ChangePackage | | Ansible playbooks | Done | `site.yml`, `control-plane.yml`, `game-node.yml` | | Operations docs | Done | `dns.md`, `control-plane.md`, `game-node.md` | ### Abnahmekriterium Phase 9 - [x] WHMCS can provision/suspend/unsuspend/terminate via signed API - [x] Production DNS provider abstraction with RFC2136 - [x] Documented control plane + two-node deployment path - [x] Billing suspension enforced on panel and edge gateway - [ ] Manual E2E: WHMCS order → GameCloud server → suspend/unsuspend ### Local WHMCS API test 1. `pnpm db:migrate && pnpm db:seed` (creates `local-dev-whmcs` installation) 2. Set `BILLING_PROVIDER=whmcs` optional for credit-bypass mode 3. Sign requests with `WHMCS_API_SECRET` from seed output 4. `PUT /api/v1/integrations/whmcs/clients/1` then `POST .../services` ### WHMCS module install Copy `integrations/whmcs/modules/servers/hexagamecloud` to `/modules/servers/hexagamecloud` on your WHMCS host. Server entry fields: - Hostname: `https://api.example.net` - Username: integration ID (`WHMCS_INTEGRATION_ID`) - Password: API secret (`WHMCS_API_SECRET`) --- ## Phase 8 — DNS and join-to-start ✅ ### Phase 8 completed | Area | Status | Notes | |------|--------|-------| | Prisma join/DNS | Done | `joinSlug`, `joinToStartEnabled`, `ServerDnsRecord`, node port ranges | | `@hexahost/dns` | Done | Slug builder, DNS record sync (DB metadata), join address assignment | | API internal edge | Done | `GET/POST /internal/edge/v1/resolve|start/:slug` with API key + rate limits | | Join-to-start start | Done | Edge triggers `startServerInternal` with billing/queue checks | | Worker provision hook | Done | Assigns join slug + DNS after provision completes | | Edge gateway (Go) | Done | TCP listener, Minecraft handshake, proxy + join-to-start | | Web | Done | Join hostname on server card | | Contracts | Done | `join.ts` edge resolve/start schemas, server join fields | ### Abnahmekriterium Phase 8 - [x] Stable join hostname per server (`slug.play.example.net`) - [x] DNS metadata stored (A + SRV for Java) - [x] Edge gateway resolves slug and can start stopped servers - [x] Rate limiting on join-to-start (3/min per slug, 10/min per IP) - [x] Credits/tariff checks on edge-triggered start - [ ] Manual E2E: connect via fixed hostname while server stopped ### Local test 1. `pnpm db:migrate && pnpm db:seed` 2. Set in `.env`: `EDGE_GATEWAY_ENABLED=true`, matching `EDGE_INTERNAL_API_KEY` 3. `pnpm dev` (API + worker) and `cd apps/edge-gateway && go run ./cmd/gateway` 4. Provision server → note `joinHostname` on dashboard 5. Stop server → connect with Minecraft client to join hostname (or `slug.play.localhost` with hosts file) 6. Edge starts server and proxies connection when `RUNNING` ### Edge env defaults (`.env.example`) - `GAME_BASE_DOMAIN=play.example.net` - `EDGE_LISTEN_ADDR=:25565` - `EDGE_INTERNAL_API_KEY=local-dev-edge-key-change-me-32chars` --- ## Phase 7 — Idle shutdown and free tier ✅ ### Phase 7 completed | Area | Status | Notes | |------|--------|-------| | `@hexahost/metering` | Done | RAM-GB-minute credits, Minecraft `list` parser | | Prisma billing models | Done | `CreditWallet`, `CreditTransaction`, `UsageRecord` | | Plan idle/quota fields | Done | Timeouts, countdown, `maxServersPerUser`, `queuePriority` | | Idle controller (worker) | Done | Player poll, countdown, auto-stop | | Usage metering (worker) | Done | 60s tick debits wallet, writes `UsageRecord` | | API billing | Done | `GET /account/wallet`, `GET /account/usage` | | API idle | Done | `GET /servers/:id/idle`, `POST .../idle/extend` | | Quotas & credits | Done | Server create/start guards | | Web | Done | Credit balance on dashboard, idle countdown on server card | ### Abnahmekriterium Phase 7 - [x] Empty running server triggers idle countdown and auto-stop - [x] Player connection cancels countdown (via `list` poll) - [x] Usage debited to credit wallet with ledger + usage records - [x] Free plan grants credits on signup - [x] Server quota per plan enforced - [ ] Manual E2E: start server, wait idle, verify stop + usage ### Local test 1. `pnpm db:migrate && pnpm db:seed` 2. Register/login → dashboard shows **5000 credits** (free plan) 3. Create & start server → credits decrease while running 4. Leave server empty → after ~10 min idle + 60s countdown → auto-stop 5. `GET /account/usage` shows RAM-GB-minute records ### Free plan defaults (seed) - `idleTimeoutMinutes`: 10 - `idleCountdownSeconds`: 60 - `monthlyCreditGrant`: 5000 - `maxServersPerUser`: 3 --- ## Phase 6 — Multi-Node and queue ✅ --- ## Phase 5 — Software & add-ons ✅ --- ## Phase 4 — Worlds & backups ✅ --- ## Phase 3 — Console, files, settings ✅ --- ## Phase 2 — Single-Node Vertical Slice ✅ --- ## Phase 1 — Authentication ✅ --- ## Phase 0 — Monorepo foundation ✅ ### Next phase: Post-MVP hardening - Penetration test, configurable option mappings, IP allowlist for integration API