Dev is now ahead of main (02.07.00). All manifests, README, and
updates.xml aligned. Updates.xml has all 6 channels with correct
pkg_mokowaas element.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Joomla automatically disables update sites for extensions with
protected=1. ensureProtectedFlag() now also checks and re-enables
the MokoWaaS update site each admin session.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moved isMasterUser() check to top of enforceAdminRestrictions() so
master user is never blocked by any restriction including install
from URL, global config, sysinfo, installer, and template editing.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Non-master users navigating to the plugin edit page are redirected
back to the plugins list with a warning message.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Installer::install() expects a directory path, not a ZIP file. Now
downloads → extracts to tmp dir → installs from extracted dir → cleans up.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When an alias domain has offline=No, the plugin overrides Joomla's
configuration.php offline=1 setting. This allows the dev/staging alias
to remain accessible while the main site shows the offline page.
Use case: put clarksvillefurs.com offline for maintenance while
clarksvillefurs.dev.mokoconsulting.tech stays accessible for testing.
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>
Instead of rendering a custom HTML page, set config('offline', 1) at
onAfterRoute so Joomla renders the site template's offline.php layout.
Custom offline_message is passed via config if set.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Removed primaryHost check from getCurrentAlias() — just look up
current host in aliases list directly
- Handle Joomla subform stdClass→array conversion
- Strip trailing slashes from alias domains
- Moved handleSiteAlias() to onAfterRoute (client type resolved)
- Use http_response_code(503) + die() for offline page
- Cast offline value to string for comparison
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uri::root() returns the current request domain, so redirecting from an
alias to Uri::root()/administrator redirects back to the alias. Added
primary_domain field to Site Aliases tab and getPrimaryHost() method
that checks: plugin setting → $live_site → alias exclusion fallback.
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Read plugin_version from manifest XML instead of hardcoding
- Hide MokoWaaS from plugin/installer list for non-master users
- Block non-master uninstall and disable attempts
- No self-healing lock — master users can still disable if needed
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>
Alias domains were creating separate Grafana datasources with unique
UIDs, causing provisioning failures (duplicate UID) when Grafana
restarts. Only the primary domain should be registered.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move site aliases from a comma-separated text field in Diagnostics to its
own tab using Joomla's subform repeatable-table layout. Each alias entry
now supports: domain, offline toggle with custom message, robots meta
directive, and backend redirect to primary domain. Frontend stays on the
alias domain while admin requests can be redirected to the primary.
Authored-by: Moko Consulting
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>
New API endpoints (all token-authenticated, HTTPS-only):
?mokowaas=health — 16 diagnostic checks (GET)
?mokowaas=install — install extension from URL (POST)
?mokowaas=update — trigger Joomla update check (POST)
?mokowaas=cache — clear all caches + opcache (POST)
?mokowaas=backup — trigger Akeeba Backup (POST)
?mokowaas=info — compact site summary (GET)
Also adds:
- Centralized API router with shared token auth
- site_aliases config field for multi-domain support
- Each alias registers its own Grafana datasource
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reconstructed from git history after cascade revert wiped dev:
- 16 health checks (database, filesystem, cache, extensions, backup,
security, SSL, cron, errors, db_size, content, users, mail, SEO,
template, config)
- Heartbeat receiver provisioning (replaces Grafana API)
- Multi-domain support via site_aliases config field
- Each alias domain registers its own Grafana datasource
- Human-readable reason field for degraded status
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reports total_disk_mb and site_size_mb (images, media, tmp, cache, logs).
Shows in Infrastructure table on Grafana dashboard.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New health checks:
- backup: last backup date/status/size, days since, total count, 7d count
- security: Admin Tools WAF status, blocked requests 24h/7d
Degraded reasons:
- No backups found
- Last backup older than 7 days
- Last backup failed/incomplete
Dashboard updated with Backup and Security rows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>