Commit Graph

157 Commits

Author SHA1 Message Date
gitea-actions[bot] 2f8c81792d chore(release): build 02.05.00 [skip ci] 2026-05-25 03:59:33 +00:00
gitea-actions[bot] cff932dcbb chore(release): build 02.04.00 [skip ci] 2026-05-25 03:54:55 +00:00
Jonathan Miller b048b47e7c security: protected status prevents disable/uninstall
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
- 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>
2026-05-24 03:53:33 -05:00
gitea-actions[bot] 76bbf7ad85 chore: update development channel 02.03.10 [skip ci] 2026-05-24 08:47:22 +00:00
Jonathan Miller c6475ff29a feat: canonical URLs, alias heartbeats, package migration, cleanup
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
- 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>
2026-05-24 03:46:23 -05:00
Jonathan Miller d766b0568a fix: alias offline uses Joomla native offline mode (template offline.php)
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
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>
2026-05-24 03:38:01 -05:00
Jonathan Miller dca452e49d fix: alias detection, offline page, backend redirect working
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
- 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>
2026-05-24 03:35:06 -05:00
gitea-actions[bot] b827b3382a chore: update development channel 02.03.07 [skip ci] 2026-05-24 08:07:35 +00:00
Jonathan Miller b5e932d78b fix: backend redirect uses primary_domain setting instead of Uri::root
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
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>
2026-05-23 23:53:20 -05:00
Jonathan Miller ede07c6675 feat: dynamic plugin version + plugin protection (no lock)
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
- 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>
2026-05-23 23:39:46 -05:00
gitea-actions[bot] 1fe8422fc0 chore: update development channel 02.03.04 [skip ci] 2026-05-24 04:25:59 +00:00
Jonathan Miller 86e40fb978 chore: sync plugin manifest version to 02.03.04 [skip ci]
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-23 23:25:26 -05:00
gitea-actions[bot] b2f52c191b chore: update development channel 02.03.03 [skip ci] 2026-05-24 04:21:25 +00:00
gitea-actions[bot] c203e970b9 chore: update development channel 02.03.02 [skip ci] 2026-05-24 04:16:49 +00:00
gitea-actions[bot] 6929c636b9 chore(version): bump to 02.03.02 [skip ci] 2026-05-24 04:06:06 +00:00
gitea-actions[bot] 20797d663f chore(version): bump to 02.03.01 [skip ci] 2026-05-24 03:48:44 +00:00
Jonathan Miller aef5ca43f6 chore(version): bump to 02.03.00
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Extension CI / Lint & Validate (pull_request) Has been cancelled
Universal: PR Check / Branch Policy (pull_request) Has been cancelled
Joomla: Extension CI / Release Readiness Check (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Repo Health / Access control (pull_request) Has been cancelled
Universal: PR Check / Validate PR (pull_request) Has been cancelled
Universal: PR Check / Changelog Updated (pull_request) Has been cancelled
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
Joomla: Repo Health / Release configuration (pull_request) Has been cancelled
Joomla: Repo Health / Scripts governance (pull_request) Has been cancelled
Joomla: Repo Health / Repository health (pull_request) Has been cancelled
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-23 22:44:04 -05:00
Jonathan Miller 32236ad7ff feat(package): convert to package with webservices API plugin
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Update Server / Update updates.xml (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled
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>
2026-05-23 22:42:02 -05:00
gitea-actions[bot] 0b3e699f29 chore(version): bump to 02.01.44 [skip ci] 2026-05-24 03:33:52 +00:00
Jonathan Miller cc907a5aa2 fix(heartbeat): only send heartbeat for primary domain, not aliases
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 3s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 4s
Joomla: Extension CI / Release Readiness Check (pull_request) Successful in 4s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Universal: PR Check / Changelog Updated (pull_request) Successful in 3s
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>
2026-05-23 18:34:57 -05:00
gitea-actions[bot] ea934ba04b chore(version): bump to 02.01.43 [skip ci] 2026-05-23 23:12:30 +00:00
Jonathan Miller a92c1ce772 feat: site aliases tab with per-alias offline, robots, and backend redirect
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>
2026-05-23 18:11:07 -05:00
gitea-actions[bot] b32d91c446 chore(version): bump to 02.01.42 [skip ci] 2026-05-23 22:58:02 +00:00
Jonathan Miller 03e0b6d13b fix: accept any 200 status from heartbeat (registered/updated/ok)
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>
2026-05-23 17:30:52 -05:00
gitea-actions[bot] 8843f721e5 chore(version): bump to 02.01.41 [skip ci] 2026-05-23 21:56:33 +00:00
Jonathan Miller 0a6744644d fix: script.php uses heartbeat receiver instead of Grafana API
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>
2026-05-23 16:55:58 -05:00
gitea-actions[bot] f61e8e53b5 chore(version): bump to 02.01.40 [skip ci] 2026-05-23 21:52:53 +00:00
Jonathan Miller dff7d73009 feat: MokoWaaS API — 6 endpoints for remote management
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>
2026-05-23 16:51:32 -05:00
gitea-actions[bot] d825621502 chore(version): bump to 02.01.39 [skip ci] 2026-05-23 21:16:18 +00:00
Jonathan Miller 1aa1a8282f feat: rebuild with heartbeat receiver, 16 checks, multi-domain support
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>
2026-05-23 16:15:45 -05:00
jmiller dd57c23716 fix: sync manifest to 02.01.38 [skip ci] 2026-05-23 20:44:32 +00:00
jmiller 640114e00c fix: sync manifest version to 02.01.37 [skip ci] 2026-05-23 20:26:29 +00:00
Jonathan Miller e7de6e4c9a Revert "Merge remote-tracking branch 'origin/dev'"
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 3s
This reverts commit b27ef3aee3, reversing
changes made to c4d8381828.
2026-05-23 00:09:22 -05:00
Jonathan Miller f1f2785f0f feat: add 10 new health checks — SSL, cron, errors, DB size, content, users, mail, SEO, template, config
New checks:
- ssl: certificate expiry, days left, issuer
- cron: scheduled tasks, failed count, last run
- errors: PHP error log size, recent errors
- db_size: total MB, table count, largest tables
- content: articles, categories, menu items, modules
- users: total, active sessions, failed logins, last login
- mail: mailer type, from address, queue count
- seo: robots.txt, sitemap, htaccess, SEF
- template: site/admin template, override count
- config: debug mode, error reporting, force SSL, caching

Degraded reasons for SSL expiry, failed cron tasks, config drift.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 23:23:19 -05:00
Jonathan Miller 138af226d1 feat: add site size and total disk to filesystem health check
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>
2026-05-22 23:13:20 -05:00
Jonathan Miller 17eaaf2347 feat: add Akeeba Backup and Admin Tools checks to health endpoint
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>
2026-05-22 22:43:41 -05:00
Jonathan Miller 21020027d0 feat: add human-readable reason field to health endpoint
Status 'degraded' now includes reason like '3 extension updates available'
or 'Low disk space: 45 MB free'. Shows in dashboard Site Info table.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 22:00:33 -05:00
Jonathan Miller 0d280717f1 Revert "Merge pull request 'chore: merge dev to main' (#19) from dev into main"
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 1s
This reverts commit a45a6cb59c, reversing
changes made to 018b197147.
2026-05-22 20:12:46 -05:00
Jonathan Miller ea66ad4b4a security: hide MokoWaaS from plugin list for non-master users
Injects JS on com_plugins that removes the MokoWaaS row from the
plugin table. Combined with the edit/save block, non-master users
cannot see, edit, or save the plugin settings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 05:53:14 -05:00
Jonathan Miller 48cb040505 security: restrict plugin settings to master user + rename Gitea to MokoGitea
- Non-master users blocked from editing MokoWaaS plugin config
- isOurPlugin() helper checks extension_id against our plugin
- Blocks both edit view and save task for non-master users
- Renamed bare 'Gitea' references to 'MokoGitea' in docs

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 05:51:20 -05:00
Jonathan Miller b17b36e02e security: make plugin hard to disable + block uninstall
- 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>
2026-05-22 04:56:48 -05:00
Jonathan Miller b22842f302 refactor: replace Grafana API with heartbeat receiver provisioning
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>
2026-05-22 04:40:51 -05:00
Jonathan Miller 2e4fdcb07e fix: new Grafana SA token with datasource:create + visible heartbeat errors
- 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>
2026-05-21 23:01:33 -05:00
Jonathan Miller bfb159d0f0 fix: add SSL bypass and error logging to Grafana provisioning
- 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>
2026-05-21 22:48:49 -05:00
Jonathan Miller 47faa1b289 fix: update Grafana API token (Admin SA) [skip ci]
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-21 22:42:49 -05:00
gitea-actions[bot] 9ccd27e809 chore(version): bump 02.01.27 → 02.01.28 [skip ci] 2026-05-22 02:56:54 +00:00
gitea-actions[bot] 1c1b541bc5 chore(version): bump 02.01.26 → 02.01.27 [skip ci] 2026-05-22 02:25:30 +00:00
Jonathan Miller 0bc5504e16 security: obfuscate Grafana credentials with XOR+base64
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>
2026-05-21 21:25:01 -05:00
gitea-actions[bot] f63e46030d chore(version): bump 02.01.25 → 02.01.26 [skip ci] 2026-05-22 02:21:14 +00:00
Jonathan Miller 34df31b086 feat: hardcode Grafana credentials, always-on health endpoint
- 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>
2026-05-21 21:20:44 -05:00