Zunnesco Monitor
Zunnesco Monitor Core: detect outages, verify journeys, alert, and publish status.
by zunnesco-dev · github.com/teray234/zunnesco-monitor · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/teray234/zunnesco-monitor/archive/refs/heads/main.zipDetect outages before customers report them, verify critical business journeys, alert the right person, and publish transparent service status from one platform.
This tree is Core 1.0.0. Author: zunnesco-dev. Plugin URI: https://github.com/teray234/zunnesco-monitor
The authoritative monitoring control plane is Laravel with geographically distributed probe workers. The WordPress client consumes signed APIs when a control plane URL is configured; otherwise it runs local scheduler / sandbox probes labeled as a single region — not a global SLA.
Core vs later editions
| Core (this release) | Later / delayed |
|---|---|
| HTTP GET/HEAD (POST optional), status, latency, keyword, TLS verify | Playwright browser journeys |
| SSL expiry + hostname-match stub | Autonomous remediation |
| DNS A/AAAA/MX | Log ingestion |
Domain expiration via zunnesco_domains() or RDAP stub unknown |
Telephone on-call |
| TCP port with SSRF (private IPs always blocked) | Private-network probes |
| Heartbeats with signed URLs | SMS (capability is false) |
| Confirmed incidents (never page on the first blip) | AI root-cause claims without evidence |
Status pages + [zunnesco_status_page] |
|
| Basic SLA with documented rules |
Next module in the original suite spec is Files, but Zunnesco Files already exists in this suite. Do not rebuild Files here.
Delayed on purpose: autonomous remediation, log ingestion, telephone on-call, private network probes, Playwright browser journeys. Synthetics are stub definitions only and never execute real purchases or production emails.
Local WordPress checks vs distributed Laravel probes
- WordPress only: WP-Cron runs HTTP and related checks as region
sandbox. Useful for a single site. Results must not be advertised as multi-region uptime. - Laravel control plane +
probes/http: Probe workers poll signed assignments, validate SSRF, execute the check, sign the result, and POST to/api/v1/probes/results. A local worker can run asus-central. - When
control_plane_urlis set in WP settings, the client consumes signed APIs instead of running the local scheduler.
Ownership
- Mail owns delivery; Monitor verifies and sends alert content through
zunnesco_mail(),zunnesco_notifications(), orwp_mail. - Domains owns registrar truth; Monitor watches expiration/DNS only if
zunnesco_domains()exists. - Credentials go through Vault when
zunnesco_vault()exists; otherwise they are encrypted. Secrets are masked in logs. - AI returns 501 unless
zunnesco_ai()exists. AI must not claim a root cause without evidence and must not execute destructive remediation.
WordPress client
Activate Zunnesco Monitor. A homepage HTTP monitor is seeded from siteurl with a conservative 5-minute interval. Private IPs (loopback, metadata, RFC1918) are always blocked in Core.
Create an HTTP monitor
Admin → Monitor → Monitors, or:
$monitor = zunnesco_monitor()->monitors()->create([
'type' => 'http',
'name' => 'Commerce Checkout',
'target' => 'https://example.com/checkout',
'interval' => 60,
'regions' => ['us-central'],
'assertions' => [['type' => 'status', 'value' => 200]],
]);
Confirm an outage
A single failed check is recorded as unconfirmed (degraded). After N consecutive failures (default 3: initial → retry → sandbox second check) an incident opens and alerts fire. Acknowledge from Incidents (cap zunnesco_monitor_ack) or POST /wp-json/zunnesco-monitor/v1/incidents/{id}/acknowledge. Recovery requires N consecutive ups.
Publish a status page
Monitor → Status pages, map components to monitors, then embed [zunnesco_status_page]. Public pages are anonymous; private pages require login. Overall states: operational, degraded, partial, major, maintenance.
Send a heartbeat
zunnesco_monitor()->heartbeats()->complete($monitorId, ['duration_ms' => 1432]);
HTTP heartbeats require X-ZNMO-Signature and X-ZNMO-Timestamp (HMAC of timestamp.heartbeat:{token}).
REST: POST /wp-json/zunnesco-monitor/v1/heartbeats/{token}/complete
Private IPs
SSRF runs before every check. http://127.0.0.1/ and http://169.254.169.254/ are blocked. Core never allows private destinations (zunnesco_monitor/ssrf_allow_private is ignored in Core).
Laravel control plane
cd control-plane
cp .env.example .env
php artisan key:generate
touch database/database.sqlite
php artisan migrate --seed
php artisan serve
php artisan monitor:probe --region=us-central
Or run the CLI worker:
php probes/http/worker.php --url=https://example.com --region=us-central
php probes/http/worker.php --control-plane=http://127.0.0.1:8000 --probe-id=us-central-1 --secret=changeme
API (Bearer MONITOR_API_KEY except heartbeats and probe ingest):
POST /api/v1/monitors
GET /api/v1/monitors/{id}
GET /api/v1/monitors/{id}/checks
POST /api/v1/heartbeats/{token}/start|complete|fail
GET /api/v1/incidents
POST /api/v1/incidents/{id}/acknowledge
POST /api/v1/maintenance-windows
GET /api/v1/status-pages
POST /api/v1/probes/results (signed probe)
Tests
php tests/test-schema.php
Caps, hooks
- Caps:
zunnesco_monitor_manage,zunnesco_monitor_ack - Filters:
zunnesco_monitor/ssrf_allow_private,zunnesco_monitor/can_alert - Actions:
zunnesco_monitor/loaded,zunnesco_monitor/incident_opened,zunnesco_monitor/incident_resolved
SLA reports always expose interval, confirmation policy, maintenance treatment, and unknown-state handling. They never display 100% when unknown gaps exist.