16 Commits

Author SHA1 Message Date
Prophet731
27cbe40c52 chore(release): 1.5.0
Some checks failed
Publish Release / release (push) Failing after 16s
Major client-area overhaul, WHMCS 9 + VirtFusion v7 compatibility, and a
hardening pass on every destructive client.php endpoint.

Tested against WHMCS 9.0.3 + VirtFusion v7.0.0 Build 9.

Features
- "On This Page" jump-link group injected into the WHMCS Actions sidebar
  via ClientAreaPrimarySidebar; auto-hides links for hidden panels.
- Monthly traffic chart (last 12 months) with rx/tx bars and centered
  legend; replaces the dead canvas that read non-existent JSON paths.
- Live Stats panel: CPU, memory, disk I/O from remoteState; 30s refresh
  while the panel is visible AND the page has focus.
- Filesystem usage rows in the Resources panel from qemu-guest-agent
  fsinfo; pseudo-FS filtered out.
- Server Overview meta chips: data-center location with country flag,
  OS template/agent name with kernel on hover, "Created N days ago".
- Hypervisor maintenance banner at the top of the page.
- Mask Sensitive screenshot mode: IPv4 keeps first two octets, IPv6
  keeps first two hextets, hostnames keep first char per dot-label.
  Inputs masked via text-security: disc; covers Server Name + Hostname
  + IP cells + rDNS panel rows.
- Per-IP copy buttons folded into the Server Overview cells (replaces
  the deleted standalone Network panel).
- VNC viewer popup served from a same-origin authenticated route
  (client.php?action=vncViewer) — POST + requireSameOrigin, rotates
  the wss token on every open, X-Frame-Options DENY, strict CSP.

Bug Fixes
- UsageUpdate cron silently no-op'd: read server.usage.traffic.used
  which doesn't exist. Bandwidth now from /servers/{id}/traffic;
  disk usage from remoteState.agent.fsinfo.
- WHMCS 9 multi-service order short-circuit: AfterModuleCreate's
  AcceptOrder fired after the first service and terminated the batch
  loop, orphaning siblings. Defer until every VF service in the order
  has a server_id.
- Orphaned services produced six generic 500s; new
  requireProvisionedService() helper emits one clean 409 with an
  actionable message. Wired into all 17 client.php cases.
- Server Overview Traffic showed "- / Unlimited"; now renders real
  bytes and "Unmetered" (limit=0 is per-period uncapped, not feature-off).
- Rename endpoint moved to PUT /servers/{id}/modify/name in VF v7
  (was 404'ing); response is HTTP 201 not 200/204.
- Rename was force-lowercasing the input; relaxed validation to
  preserve case + freeze the input row mid-flight to prevent
  double-submits.
- "Other" OS category icon override removed; uses VirtFusion's icon
  instead of a hardcoded SVG.
- Save button squish on the rename row fixed via flex-wrap layout.

Security
- CSRF protection (requirePost + requireSameOrigin) added to every
  destructive POST: rebuild, resetPassword, resetServerPassword,
  powerAction, rename, selfServiceAddCredit, toggleVnc, vncViewer.
  Previously only rdnsUpdate had it.
- Open-redirect defence in Module::fetchLoginTokens — refuses to
  return a redirect URL whose host doesn't match the configured VF
  panel hostname.
- Per-action rate limiting via new Module::requireRateLimit helper
  (Cache-backed): rebuild 60s, resetPassword/resetServerPassword 30s,
  powerAction 10s, vncViewer/toggleVnc/selfServiceAddCredit 5s.
- vncViewer route delivers strict Content-Security-Policy
  (default-src none, script-src self + VF panel, connect-src wss VF
  panel, frame-ancestors none).
- IPv6 examples in placeholder/comments switched to the IANA
  documentation prefix 2001:db8::/32 (RFC 3849).

Removed
- Network panel (duplicated Server Overview IP rows).
- VNC enable/disable toggle (VF firewall flag is non-functional;
  toggle was misleading).
- Network Speed row in Resources panel (always 0 from VF API).

Internal
- Module::fetchServerData now passes ?remoteState=true.
- ServerResource::process exposes osName/osPretty/osKernel/osDistro/
  osIcon/location/locationIcon/hypervisorMaintenance/createdAt/
  builtAt/live.* fields.
- Module::toggleVnc corrected to send {vnc:bool} (the actual API
  param) instead of {enabled:bool} (silent no-op).
- Module::getVncConsole + toggleVnc return baseUrl alongside the
  envelope so the viewer route can build the wss URL.
- Panel margins tightened mb-3 → mb-2 across all 11 panels.
2026-04-28 22:07:27 -04:00
Prophet731
1f09671fee feat(stock): dynamic VPS inventory driven by live hypervisor capacity
Opt-in per product via WHMCS's native tblproducts.stockcontrol toggle.
When enabled, the module overwrites tblproducts.qty with the number of
VPSes the panel can still actually provision, derived from two
authoritative sources:

  - GET /packages/{id} for the per-VPS resource footprint (memory,
    cpuCores, primaryStorage, primaryStorageProfile, enabled)
  - GET /compute/hypervisors/groups/{id}/resources for live
    free/allocated data per hypervisor in the group

Algorithm sums min(memory, cpu, storage) across eligible hypervisors
(enabled AND commissioned AND !prohibit) for every group the product
can be placed in (default configoption1 plus every numeric value of a
Location configurable option), capped by the group-level IPv4 pool
taken as max() within a group to avoid double-counting. Storage
matching is strict against package.primaryStorageProfile; hypervisors
without the named pool contribute 0.

FAIL-SAFE INVARIANT: transient API failures return null from
Module::fetchPackage / Module::fetchGroupResources, and the orchestrator
leaves tblproducts.qty UNCHANGED in that case. Confirmed-missing
conditions (HTTP 404, package.enabled=false) return qty=0. Without this
tri-state contract the module would either zero out inventory during
API blips, or show inventory for packages that have been deleted.

Triggers:
  - AfterModuleCreate: refresh + auto-accept pending order
  - AfterModuleTerminate: refresh (capacity came back)
  - AfterCronJob: every-2-hour safety net for out-of-band panel changes
  - ClientAreaPageCart: opportunistic per-product refresh in order flow
  - admin.php?action=stockRecalculate: on-demand full recalc

Shared 30s rate-limit (stockrefresh:event) coalesces provision bursts;
60s per-product limit (stockrefresh:{pid}) caps cart-page refreshes;
grpres:{id} 120s TTL caps upstream API reads per group regardless of
how often hooks fire.

Auto-accept: AfterModuleCreate calls WHMCS AcceptOrder with
autosetup=false when the parent order is still Pending. Idempotent;
already-accepted orders are skipped via strcasecmp status check.

New per-product config option stockSafetyBufferPct (configoption7,
default 10) reserves X% of each resource's max before computing fits.
Blank falls back to 10% so existing products get headroom without any
config change. Ignored for unlimited resources (max=0) and for IPv4
(no per-hypervisor max in the response).

TestConnection now probes /compute/hypervisors/groups to surface
missing compute:read scope at config time instead of as unexplained
nightly silence.
2026-04-24 12:14:26 -04:00
Prophet731
ad85439dfb feat: add PowerDNS reverse DNS (PTR) integration
Introduces an opt-in reverse DNS management subsystem backed by a PowerDNS
Authoritative HTTP API. Runs via a companion WHMCS addon module
(modules/addons/VirtFusionDns) that holds settings and a Test Connection
page; the server module reads those settings from tbladdonmodules and
short-circuits when the addon is absent or disabled, so provisioning is
unaffected for operators who don't use the feature.

Lifecycle hooks:
- createAccount creates PTRs for every assigned IP (forward DNS must
  already resolve to the IP — FCrDNS enforcement)
- renameServer updates only PTRs whose content matched the old hostname,
  preserving client-custom records
- terminateAccount deletes all PTRs before the local state is purged
- TestConnection merges PowerDNS health check with the existing VirtFusion
  check
- A DailyCronJob hook reconciles missing PTRs additive-only (never
  overwrites)

Client UI: new "Reverse DNS" panel on the service overview with one
editable PTR input per assigned IP, per-row status badges, and
forward-DNS rejection on save. Admin services tab gets a parallel
widget with Reconcile (additive) and Reconcile (force reset) buttons.

New subsystem at lib/PowerDns/:
- Client.php    PowerDNS API wrapper (X-API-Key, listZones/getZone/
                patchRRset/notifyZone), auto-NOTIFY on successful PATCH
- Config.php    Loads + decrypts addon settings from tbladdonmodules
- IpUtil.php    PTR-name generation (IPv4 + IPv6), zone matching,
                RFC 2317 classless parsing
- Resolver.php  FCrDNS verification via dns_get_record with CNAME-chain
                following and per-(hostname,ip) caching
- PtrManager.php Orchestrator: syncServer, deleteForServer, listPtrs,
                setPtr, reconcile, reconcileAll

Security hardening helpers added to Module and applied to the rDNS
endpoints:
- requirePost()           HTTP method gate (405 on non-POST mutations)
- requireSameOrigin()     Origin/Referer check against WHMCS host (CSRF
                          defence against cross-site form POST)
- requireServiceStatus()  tblhosting.domainstatus filter (Active for
                          writes, Active+Suspended for reads)

RFC 2317 classless delegations (e.g. 64/64.113.0.203.in-addr.arpa.)
supported with alignment validation: rejects misaligned start addresses
that don't correspond to any real delegation boundary.

PowerDNS zone IDs containing '/' are URL-encoded as '=2F' per the
PowerDNS API convention. PATCH success triggers PUT /zones/{id}/notify
so slaves pick up the SOA-bumped serial immediately.

Includes IPv4 + IPv6 support, per-IP write rate limit (10s), fresh
IP-ownership re-verification on every client write (defends against
stale-ownership after IP reassignment), and audit logging of every
successful edit to the WHMCS module log.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 21:08:22 -04:00
Prophet731
d253bd44e6 feat: auto-create custom fields, add try/catch coverage, PHPDoc, and Pint formatting
All checks were successful
Publish Release / release (push) Successful in 10s
- Auto-create 'Initial Operating System' and 'Initial SSH Key' custom fields
  via Database::ensureCustomFields() on module load, eliminating the manual
  modify.sql step
- Delete modify.sql (no longer needed)
- Add try/catch blocks around every DB operation and API call across all PHP
  files per CLAUDE.md error handling rules
- Add comprehensive PHPDoc to all classes, methods, and properties
- Set up Laravel Pint (laravel/pint) with Laravel-style preset for consistent
  code formatting across the codebase
- Add git pre-commit hook (hooks/pre-commit) that runs Pint on staged PHP
  files, auto-installed via Composer post-install/post-update scripts
- Simplify README installation to a single copy-paste command

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:03:17 -05:00
Prophet731
1ab2ef42a5 chore: full project audit cleanup, dead code removal, and documentation update
Dead code removed:
- Module.php: remove assignBackupPlan(), getSelfServiceCurrencies() (no callers)
- Cache.php: remove forgetPattern() (no callers, no-op on filesystem)
- module.js: remove vfLoadSelfServiceReport() (no UI trigger)

Stale files removed:
- .releaserc.json (orphaned, conflicts with tag-based workflow)
- .github/workflows/api-sync-check.yml (baseline never populated)
- docs/openapi-baseline.yaml (placeholder stub)
- scripts/generate-endpoint-doc.sh (broken grep patterns)

Security fixes:
- AdminHTML: cast $serverId to (int), cast $serviceId to (int)
- admin.php: add explicit break after every output() call, sanitize error msgs

File hygiene:
- Move modify.sql into modules/servers/VirtFusionDirect/ (matches README docs)
- Fix CHANGELOG.md: remove duplicate 1.0.0 entry, clean up mixed git host URLs

Documentation:
- CLAUDE.md: full rewrite with current architecture, Cache class, development
  rules (try/catch, ownership validation, HTTP methods, caching policy)
- README.md: remove stale IPv4 removal references, add new features (traffic,
  backups, VNC toggle, password reset, OS gallery, copy buttons), add Cache.php
  to file structure, remove "Primary IPv4 Protection" known issue

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:28:58 -05:00
Prophet731
3ca9eb60c3 fix: force generic icon on 'Other' category even when API provides linux_logo.png
VirtFusion API returns an 'Other' category with icon=linux_logo.png by default.
Null out the icon in groupOsTemplates() so the JS SVG fallback renders instead.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 14:18:12 -05:00
Prophet731
d3d75b4752 fix: remove dead code, update stale versions, tag-based release workflow
Dead code removed:
- Module.php: remove addIPv4() method (no endpoint, feature removed per CLAUDE.md)
- Curl.php: remove useCookies(), setLog() (security risk — wrote tokens to
  web-accessible CURL.log), head(), getHeadersData() — all unused
- module.css: remove .vf-button, .vf-button-small (never referenced in DOM)
- module.css: remove vestigial #vf-data-server-traffic-sep rule
- module.css: merge duplicate #vf-server-info-error declarations
- publish-release.yml: remove dead version.json generation step (nothing reads it)

Fixes:
- AdminHTML.php: update stale cache version strings 20260207 → 20260319
- hooks.php: update stale keygen.js version string
- hooks.php: remove unused `use WHMCS\User\User` import
- ConfigureService.php: remove unused `use JsonException` import
- module.css: fix .vf-os-details class selector → #vf-os-details ID selector
- client.php + admin.php: reuse existing $vf instead of new Module()
- Module.php: use Cache::forget() instead of forgetPattern() for known key
  (forgetPattern is a no-op on filesystem cache fallback)

Workflow:
- Rewrite publish-release.yml: tag-based triggers only (no automatic releases)
- Triggers on push of v* tags, creates GitHub release with auto-generated notes
- Uses softprops/action-gh-release@v2 — compatible with both Gitea and GitHub

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:59:28 -05:00
Prophet731
0ade74dd4e refactor: consolidate duplicate logic across codebase
Some checks failed
Automated Semantic Versioning Release / release (push) Failing after 44s
PHP (Module.php):
- Extract resolveServiceContext() helper — eliminates 15 repeated
  service/whmcsService/getCP/initCurl lookup chains (~200 lines saved)
- Extract static groupOsTemplates() — single source for OS template
  category grouping logic, used by both Module.php and hooks.php

PHP (Cache.php):
- Add filesystem cache fallback when Redis extension is unavailable
- Atomic writes with tmp+rename pattern for race condition safety
- extension_loaded() check instead of class_exists()

JS (module.js):
- Extract vfUrl() helper — replaces 18 identical URL construction strings
- Extract vfShowAlert() helper — replaces 25 repeated alert show/hide/class
  toggle patterns across all action functions

hooks.php:
- Use Module::groupOsTemplates(data, htmlEscape: true) instead of
  inline duplicate grouping logic (~40 lines removed)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 13:49:00 -05:00
Prophet731
90a97c4afb feat: major enhancement — OS gallery, server rename, traffic chart, backups, VNC toggle, password reset, Redis caching, UX improvements
- Remove client IP removal capability (keep backend methods removed too)
- Add copy-to-clipboard buttons for IP addresses with tooltip feedback
- Replace OS dropdown with tile gallery (grouped, searchable, brand colors, EOL badges) in rebuild panel and checkout page
- Add inline server rename with friendly name generator and RFC 1123 validation
- Add traffic statistics canvas chart with responsive resize in resources panel
- Add backup listing timeline in manage panel with show-all expansion
- Add VNC enable/disable toggle with connection details and password copy
- Add server root password reset with auto-clipboard copy (never displayed)
- Add skeleton loading placeholders, action cooldowns (power 3s, rebuild 30s), progress indicator with elapsed timer
- Sanitize all client-facing error messages (no raw API errors exposed)
- Convert all state-mutating AJAX calls from GET to POST
- Add explicit break after all output() calls in client.php
- Add Redis-backed API response caching (Cache.php): OS templates 10min, traffic/backups 2min, currencies 30min, packages 10min
- Add GitHub Actions workflow for weekly VirtFusion API change detection
- Move cache busting step after semantic-release in publish workflow
- Add endpoint doc generator script and OpenAPI baseline placeholder
- Improve hostname generation entropy (bin2hex random_bytes)
- Add .superpowers/ to .gitignore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 05:40:32 -05:00
EZSCALE
1e471affd0 feat: add VNC check, SSH key paste, resources panel, sliders, and self-service billing
- VNC panel auto-hides when VNC is disabled on the server
- SSH key paste textarea at checkout with API key creation during provisioning
- Resources panel with current allocation, traffic progress bar, and upgrade link
- changePackage() now applies individual resource modifications from configurable options
- Order form configurable option dropdowns replaced with styled range sliders
- Self-service billing: credit balance, usage breakdown, credit top-up from client area
- Self-service config options (mode, auto top-off threshold/amount) on products
- Auto top-off via WHMCS cron when credit falls below threshold
- CHANGELOG.md covering all versions from 0.0.6 to present

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 14:25:43 -06:00
EZSCALE
49fdd9e49b fix: add null/false guards, proper error handling, and VNC popup fix
- Add isset() guards before count() on ipv4/ipv6 arrays in ServerResource
  to prevent PHP 8.0+ TypeError
- Add null checks after getWhmcsService() and getCP() in 18 Module methods
  and 5 ModuleFunctions methods to prevent fatal null dereference errors
- Add null guards for $whmcsService and $cp in admin.php impersonateServerOwner
- Fix HTTP status codes throughout admin.php (404, 400, 500, 502 instead of 200)
- Guard ConfigureService methods against $this->cp === false
- Use null coalescing for customfields access in initServerBuild
- Check API response code in initServerBuild instead of always returning true
- Replace exit() with RuntimeException in Curl.php
- Change catch(Exception) to catch(Throwable) in hooks.php for PHP 8.0+
- Open VNC window before AJAX call to avoid popup blocker

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 13:49:12 -06:00
Claude
cfb1ddb4e5 Fix firewall API endpoints to use correct {interface} path parameter
- Firewall endpoints now use /firewall/{interface}/ where interface is
  "primary" or "secondary" (was missing the interface segment)
- Add applyFirewallRulesets() method for applying predefined rulesets by ID
- Add firewallApplyRulesets client endpoint (comma-separated ruleset IDs)
- Add sanitizeFirewallInterface() helper for input validation
- All firewall methods now accept optional interface parameter (default: primary)
- Document that VirtFusion uses ruleset-based firewall (no individual rule CRUD)
- Update README with correct API paths and ruleset documentation

https://claude.ai/code/session_01TCsJ4WZCGuEX3zqh1tQ2zx
2026-02-07 12:51:36 +00:00
Claude
cad1af18c1 Add firewall, network, VNC, backup, resource management and UsageUpdate
New features implemented:
- Firewall management: enable/disable, status display, apply rules
- IP address management: add/remove IPv4 and IPv6 with client UI
- VNC console access integration (VirtFusion v6.1.0+)
- Backup plan assignment/removal via API
- Resource modification: in-place memory/CPU/traffic changes
- UsageUpdate cron: automated bandwidth and disk usage sync to WHMCS
- Dry run validation: test server creation config before provisioning
- Admin "Validate Server Config" button for dry run testing

Client area additions:
- Firewall panel with enable/disable/apply controls and status badge
- Network panel with IPv4/IPv6 listing, add, and remove buttons
- VNC Console panel with browser-based access
- All panels load asynchronously with spinner indicators

Comprehensive README rewrite with:
- Table of contents, requirements matrix, step-by-step installation
- Detailed configuration guide for all features
- Theme compatibility documentation (Six, Twenty-One, Lagom)
- Complete API endpoints reference organized by category
- UsageUpdate cron documentation with data format details
- Troubleshooting tables for common issues
- Known issues section covering version requirements
- Security architecture documentation
- File structure reference

https://claude.ai/code/session_01TCsJ4WZCGuEX3zqh1tQ2zx
2026-02-07 12:43:02 +00:00
Claude
c93072b1c6 Enhance VirtFusion WHMCS module with security fixes, new features, and improved UX
Security improvements:
- Enable SSL/TLS certificate verification by default (was disabled, MITM risk)
- Remove error_reporting(0) that silenced all errors
- Add input sanitization on all user parameters (int casting, regex filtering)
- Return proper HTTP status codes (401, 403, 400, 500) instead of always 200
- Add XSS protection with htmlspecialchars and encodeURIComponent
- Add null checks on API response data before property access

New features:
- Power management: boot, shutdown, restart, and force power off controls
- Server rebuild: reinstall with any available OS template from client area
- Server rename: change server display name via PATCH API
- OS template fetching: client-side endpoint for rebuild OS selection
- TestConnection: validate API credentials from WHMCS server settings
- ServiceSingleSignOn: native WHMCS SSO integration for VirtFusion panel
- Server status badge: visual indicator of server state in overview
- Traffic usage display: show bandwidth used vs allocated
- Checkout validation: ShoppingCartValidateCheckout hook ensures OS selection

Ordering process improvements:
- Add default "Select Operating System" placeholder option
- Add "No SSH Key (Optional)" default for SSH dropdown
- Hide SSH key field/container when no keys available
- Wrap hook in try/catch to prevent checkout page breakage
- Sanitize template names with htmlspecialchars
- Use JSON_HEX_* flags for safe script injection

Theme compatibility:
- Properly formatted Smarty templates with readable indentation
- Dual panel/card CSS classes for Bootstrap 3/4/5 compatibility
- Responsive power button layout with mobile breakpoint
- Framework-agnostic HTML that works with Six, Twenty-One, Lagom, and custom themes
- Suspended service state messaging

Code quality:
- Readable, unminified JavaScript with JSDoc header
- Structured CSS with logical section organization
- Improved error messages throughout all provisioning functions
- Added PATCH method support to Curl wrapper
- Added curl error capture on connection failures
- Added connection and request timeouts (10s/30s)
- Fixed memory conversion to check key name instead of display name

Documentation:
- Complete README rewrite with installation, configuration, and troubleshooting guides
- API endpoint reference table
- Configurable options mapping documentation
- Theme override instructions
- Security considerations section

https://claude.ai/code/session_01TCsJ4WZCGuEX3zqh1tQ2zx
2026-02-07 12:18:11 +00:00
b25535ba5f Cleaned up code to make it OOP. 2023-09-10 19:48:18 -04:00
d95cf91361 changed structure to match WHMCS 2023-09-10 17:28:14 -04:00