- Helpdesk: fa-solid fa-handshake-angle (was icon-headphones, unmapped)
- .htaccess: fa-solid fa-file-code (was icon-file-code, unmapped)
- Query now finds ALL submenu items under the MokoWaaS parent menu,
including those linking to com_plugins, com_installer, com_checkin, com_cache
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Joomla's update finder sometimes fails to link #__updates records
to the installed extension. fixUpdateRecords() joins on element+type
to set the correct extension_id.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Joomla 6 + MySQL STRICT_TRANS_TABLES: the element column is NOT NULL
with no default. Package installer creates placeholder rows before
processing sub-extension manifests, causing INSERT failures. preflight()
adds DEFAULT '' so the INSERT succeeds.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Swap order: migrateStandalonePlugins() now runs before
removeRetiredExtensions() so TOS params are copied to
mokowaas_offline before the old plugin is deleted.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add to removeRetiredExtensions(): uninstalls plugins, removes update sites,
and deletes files on MokoWaaS install/update. These features are now built
into MokoWaaS directly.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add migrateUpdateServerUrls() to postflight: rewrites /raw/branch/main/updates.xml to /updates.xml for all Moko extensions
- Fix Helpdesk icon to fa-handshake-angle, .htaccess to fa-solid fa-file-code (unmapped in joomla-fontawesome.css)
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Joomla only renders img column icons for level-1 menu items. Level 2+
need menu_icon in the params JSON. This runs on every install/update.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Admin menu module now collapses by default, auto-expands on MokoWaaS pages (CB-style)
- Add mod_mokowaas_cache: one-click cache cleaner button in admin status bar (replaces Regular Labs Cache Cleaner)
- clearCache now purges all cache files (not just expired), matching RL behavior
- Update server URL changed to https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/updates.xml
- Add setupCacheModule() to package install script
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>