Files
HexaHost-GameCloud/docs/IMPLEMENTATION_STATUS.md
smueller 316679a913
Some checks failed
CI / Node — lint, typecheck, test, build (push) Failing after 9s
CI / Go — node-agent tests (push) Failing after 8s
CI / Go — edge-gateway build (push) Successful in 18s
Enhance WHMCS integration with mTLS support and product mapping features. Added mTLS configuration options, updated API endpoints for mTLS status and fingerprint registration, and implemented product validation API. Updated database schema and documentation accordingly.
2026-06-30 13:17:12 +02:00

303 lines
11 KiB
Markdown

# 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