New module mod_mokowaas_menu renders a dedicated MokoWaaS section
in the admin sidebar at position=menu, ordering=0 (before CB at 1
and Joomla's mod_menu at 2).
Menu items: Dashboard, Helpdesk, Extensions, .htaccess Maker,
Privacy Guard, WAF Log, Feature Plugins
Active state highlighting on current view.
Auto-created on package install with access=Special.
Added to package manifest.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both frontend and admin ticket creation now show a KB search step
first. User types their issue, Smart Search (com_finder) returns
matching articles. If nothing helps, they click through to the
ticket form with the search query pre-filled as the subject.
Frontend (/support/submit-ticket):
- Search input with live results from #__finder_links
- Article links open in new tab
- "Submit Anyway" shows the ticket form
- Falls back to direct form if Smart Search has no indexed content
Admin (New Ticket modal):
- Same KB search step before the form
- Results as clickable list-group items
- Modal resets on close
Also:
- Added searchKb controller task (both frontend + admin)
- Added "Submit a Ticket" child menu item under Support on install
- Fixed innerHTML → safe DOM methods for search results
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Creates a frontend menu item at /support pointing to the customer
portal (com_mokowaas&view=tickets). Access level: Registered.
Idempotent — skips if already exists.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Renamed plugin element from mokowaas_tos to mokowaas_offline to better
reflect its purpose (offline bypass, not just TOS).
Added migrateStandalonePlugins() to package script:
- Detects if standalone mokojoomtos plugin is installed
- Copies its params (configured slugs) to mokowaas_offline
- Removes old extension record, update sites, and files
- Logs the migration
Future standalone-to-MokoWaaS migrations can be added to the
$migrations array.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New plugin: plg_system_mokowaas_tos (Offline Bypass)
- Keeps configured pages accessible during offline mode
- SEF path matching + Itemid fallback
- Custom MenuslugField for multi-select menu items
- Include children option for parent menu matching
- Renamed from MokoJoomTOS to MokoWaaS Offline Bypass
Also:
- Added MokoJoomOpenGraph to extension manager catalog
- Added to package manifest, script.php, dashboard, cascade list
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Added removeRetiredExtensions() to package postflight script.
On every install/update, it checks for retired extensions and
removes them (DB record + files). Currently retires:
- plg_system_mokowaas_monitor (merged into core in 02.32.00)
Future retired extensions can be added to the $retired array.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The health monitor/Grafana heartbeat is mandatory infrastructure that
must always be active. The core system plugin (plg_system_mokowaas)
already has handleGrafanaProvisioning() and sendHeartbeat(), making
the separate monitor plugin redundant.
- Removed plg_system_mokowaas_monitor from package manifest
- Removed from script.php enable/protect lists
- Removed from cascade enable/disable logic
- Removed from dashboard plugin metadata
- Excluded from dashboard plugin discovery query
- Disabled on dev server (can be uninstalled manually)
Health monitoring is now entirely handled by the core plugin which
is protected and cannot be disabled.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds MokoOnyx as a git submodule at src/packages/tpl_mokoonyx (pinned
to main branch) so it packages alongside all other MokoWaaS extensions.
Every WaaS site uses both, so installing them as a single package
ensures they stay in sync.
- Added submodule for MokoOnyx repo
- Added template entry to pkg_mokowaas.xml
- Added mokoonyx to protected extensions in script.php
- Added submodules: recursive to CI checkout steps
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Atum template has a 'top' position that renders full-width above the
component output inside the content section. Removed the column-span
CSS hack since top position is naturally full-width.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Joomla's cpanel view renders quickicon (icon position) modules above
regular cpanel modules. Changed from position=cpanel to position=icon
so MokoWaaS appears at the very top of the admin dashboard.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Article count, user count, pending updates with badges
- Disk usage progress bar with color coding
- Current IP display
- Clear Cache button with AJAX spinner
- Check Updates + update count button
- Module defaults to ordering=-1 (top) and access=Super Users
- Added padding to module container
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Admin dashboard module (mod_mokowaas_cpanel) showing:
- MokoWaaS version, debug/offline status badges
- Health indicator (database connectivity check)
- Feature plugin status badges (enabled/disabled)
- Link to full MokoWaaS control panel
- Auto-assigns to cpanel position on install
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add admin dashboard to com_mokowaas with site info bar, feature plugin
grid with AJAX toggles, and quick actions (clear cache, check updates)
- Split monolithic system plugin into 4 toggleable feature plugins:
Firewall, Tenant Restrictions, DevTools, and Health Monitor
- Add MokoWaaSHelper utility class for shared master-user detection
- Add static updates.xml (licensing system deferred)
- Restore universal moko-platform workflows
- Add param migration in package script for existing sites
- Fix license key warning to show once per session
- Rename license key messages to "Moko Consulting License Key"
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Version bump across all manifests and docs
- Auto-cleanup of legacy master users no longer in MASTER_KEYS
- Updated CHANGELOG with all 02.31.00 changes
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Persistent admin warning when no download key is set on the MokoWaaS
update site, with link to System → Update Sites
- Daily heartbeat validates the key against MokoGitea's dynamic endpoint;
shows error if key is invalid or expired
- Package postflight removes stale/duplicate update site entries and
orphaned #__updates rows
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update server now points to MokoGitea's dynamic endpoint which
validates license keys (dlid) and generates update XML from git
releases. Users enter the download key via Joomla's native
System → Update Sites interface. Legacy static URLs are auto-migrated
on install/update.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add plg_task_mokowaassync scheduled task plugin for automated content sync
- Fix demo banner countdown to show weeks/days/months for longer intervals
- Add Community Builder tables to DemoResetService safe reset list
- Remove all CI/CD workflow files (manual release process)
- Bump version to 02.28.00 across all manifests and updates.xml
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- protectExtensions() now covers all MokoWaaS elements (package, system
plugin, component, webservices, task, perfectpublisher)
- enableUpdateServer() ensures #__update_sites stays enabled for MokoWaaS
- cleanupLegacyExtensions() removes old mokowaasbrand entries from
#__extensions and deletes plugins/system/mokowaasbrand/ from filesystem
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds Demo Mode feature for configuring sites as demo instances with
automatic periodic reset to a saved baseline. Includes DemoResetService
for DB table + media snapshots, frontend warning banner, REST and
query-string API endpoints, admin toggles, and a Joomla Scheduled Task
plugin (plg_task_mokowaasdemo) for automatic reset.
Closes#88
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Set protected=1, locked=0 on MokoWaaS extensions via package script
- Self-healing: plugin checks and restores protected flag each session
- Block non-master disable via plugin list toggle (plugins.publish)
- Block non-master uninstall via installer manage
- Joomla framework natively enforces protected status (greys out toggles)
- Master users can still manage settings and updates
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- manifest.xml: package-type plugin → package
- Canonical URL injection for alias domains (prevents SEO duplication)
- Heartbeat registration for alias domains (each alias gets Grafana datasource)
- Package script.php: enable plugins on every install/update, heartbeat on postflight
- Remove accidentally committed profile.ps1 and TODO.md
- Add profile.ps1 and TODO.md to .gitignore
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Restructure MokoWaaS from a standalone system plugin into a Joomla
package containing:
- plg_system_mokowaas — existing system plugin (moved to packages/)
- com_mokowaas — minimal API-only component with health, cache, and
update controllers for Joomla Web Services API
- plg_webservices_mokowaas — registers /api/v1/mokowaas/* routes
Package script auto-enables both plugins on fresh install.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The receiver returns 'updated' when re-registering an existing site,
but the code only accepted 'registered', causing false 'HTTP 200 — Unknown' warnings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The postflight still had the old Grafana API code with obfuscated tokens,
causing 403 RBAC errors on install/update. Now uses the heartbeat receiver
at bench.mokoconsulting.tech/api/waas-heartbeat/register.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- enforceLocked() runs every page load — re-enables, re-locks, re-protects
if someone tampers with the database flags
- preflight() blocks uninstall attempts with error message
- Logs tampering attempts to mokowaas log category
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove all Grafana API code (630 lines), obfuscated tokens, SA tokens,
ensureGrafanaPlugin, provisionGrafanaDatasource, buildDashboardModel.
Replace with simple HTTP POST to heartbeat receiver on bench server.
Receiver writes Grafana provisioning YAML and restarts Grafana container.
No API tokens or RBAC permissions needed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- New service account token with correct RBAC permissions
- script.php postflight now shows success/failure messages to admin
- Logs all heartbeat attempts with HTTP code and cURL errors
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add CURLOPT_SSL_VERIFYPEER=false for shared hosting environments
- Add CURLOPT_FOLLOWLOCATION to handle redirects
- Log all Grafana heartbeat attempts with HTTP code and cURL errors
- Helps debug provisioning failures on DreamHost and similar hosts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
API key and URL stored as XOR-encoded base64 constants. Deobfuscated
at runtime only when needed. Prevents plain-text grep discovery.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Health endpoint always enabled when plugin is installed
- Grafana URL and API key hardcoded as constants
- Removed enable_health_endpoint, grafana_url, grafana_api_key from config UI
- Token still auto-generated and shown as read-only
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements heartbeat telemetry for WaaS dashboard monitoring:
- JSON health endpoint at /?mokowaas=health with token auth
- Database, filesystem, cache, and extension health checks
- Auto-generated API token (separate from Joomla user tokens)
- Grafana Infinity datasource auto-provisioning via REST API
- Shared dashboard with endpoint dropdown variable
- Auto-provision on plugin install/update via script.php
- Grafana plugin install via API (replaces deprecated CLI)
- Deprovisioning on disable (datasource cleanup)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
If MokoOnyx is installed, lock it and set as default.
Unlock MokoCassiopeia to allow uninstall.
Falls back to MokoCassiopeia if Onyx not present.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Updated version in all .ini, .php, .md files to 02.01.08.
Added SHA256 checksum to updates.xml for install integrity validation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- MokoCassiopeia zip shipped at src/payload/mokocassiopeia.zip
- Install script uses local payload instead of downloading
- Removed getDownloadUrlFromUpdates (no longer needed)
- Added update-payload.yml workflow to refresh payload on merge to main
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The release zip is properly structured for Joomla installation.
Simplified extraction logic — release zips have templateDetails.xml
at root or one level deep. Added better error messages with the
failing URL for debugging.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Send email to webmaster@mokoconsulting.tech on every install/update
with site name, version, PHP, Joomla version
- Changed locked=0 (allows uninstall by super users) but kept
protected=1 (prevents disabling)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Instead of hardcoding the zip URL, fetches MokoCassiopeia's updates.xml
from the repo main branch and parses the downloadurl. This way the
download location is controlled by the MokoCassiopeia repo.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Joomla Installer::install() expects a directory path, not a zip file.
Now extracts the zip to a temp folder, finds the templateDetails.xml,
and passes the correct directory to the installer.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Minor version bump to 02.01.01:
- Auto-install mokocassiopeia from GitHub if not present
- Lock and protect the template (cannot be disabled/uninstalled)
- Set mokocassiopeia as default site template
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On install/update, checks if mokocassiopeia template exists. If found,
locks and protects it. If missing, downloads latest release from
GitHub and installs it automatically.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>