# ActivityPilot

A premium-grade WordPress activity log, observability, and audit-trail plugin built for developers, agencies, and security-conscious site owners. Tracks every meaningful change on the site — logins, post edits, plugin/theme operations, role changes, critical option updates, integrations, file changes, and more — and visualises them in a modern React-powered timeline UI with workflow, anomaly detection, rollback, and webhooks.

## Privacy Defaults

- External-service features are opt-in.
- Geolocation (`ip-api.com`) is disabled by default (`enable_geo = 0`).
- Outbound webhooks (Slack/Discord/Teams/custom URL) are disabled by default until configured.
- No third-party data transfer occurs unless an admin explicitly enables those features.

## Highlights

- **Modern admin SPA** built with `wp.element` (React) — no extra bundles needed.
- **Custom DB table** `wp_apwpm_activity_logs` (+ `wp_apwpm_comments`, `wp_apwpm_views`) with proper indexes and FULLTEXT search.
- **REST API** namespace `activitypilot/v1` (nonce + capability protected, sudo-gated for destructive ops).
- **Smart Insights** (statistical anomaly detection: bursts, off-hours, role escalation, z-score outliers).
- **Rollback** for option / user-role / post-trash / plugin / theme changes.
- **Workflow**: acknowledge / resolve / snooze, comments thread, assignee.
- **Live polling**, dark mode, date presets, keyboard shortcuts, bulk operations.
- **Analytics**: 7×24 heatmap, hour-of-day chart, top users with drill-down.
- **Reports**: daily / weekly / monthly HTML digest emails + Print-to-PDF.
- **Integrations**: WooCommerce, ACF, WPForms, Gravity Forms, Contact Form 7, Yoast, Rank Math, Elementor, Divi, Gutenberg reusable blocks.
- **Webhooks**: Slack, Discord, Microsoft Teams, generic HMAC-signed endpoint (optional, disabled by default).
- **Geolocation** of logins (IP → country/city), new-country detector (optional, disabled by default).
- **Tamper-proof hash chain** (HMAC-SHA256, per-site secret, Site Health verifiable).
- **Sudo mode** (short-lived re-auth) for purge / rollback / bulk-delete.
- **File integrity monitor** (wp-config, .htaccess, mu-plugins, theme functions, active plugins).
- **Brute-force IP throttle**.
- **PII redaction** + GDPR personal-data exporter / eraser.
- **Append-only / immutable mode** for regulated audit logs.
- **Async batched logging** (shutdown flush).
- **Multisite**: per-site tagging, network admin dashboard.
- **PSR-3 logger adapter** + custom event registry for 3rd-party developers.
- **WP-CLI** commands: list, count, verify, prune, purge, export, digest, scan-files.
- **Cron** retention with global + per-severity policies.
- **Site Health** panel and tests.
- **Cursor-based pagination** support (`since_id`).
- **Hardened**: capability checks, nonces, prepared statements, output escaping.

## REST endpoints (`/wp-json/activitypilot/v1`)

| Path                                | Method  | Purpose                                              |
| ----------------------------------- | ------- | ---------------------------------------------------- |
| `/logs`                             | GET     | Paginated, filterable log list                        |
| `/stats`                            | GET     | Dashboard stats                                       |
| `/insights`                         | GET     | Smart-Insights anomalies                              |
| `/analytics`                        | GET     | Heatmap / hour-of-day / top users                     |
| `/report?period=daily|weekly|monthly` | GET   | HTML digest                                           |
| `/rollback/{id}`                    | POST    | Revert an action (sudo)                               |
| `/network`                          | GET     | Multisite per-blog stats                              |
| `/filters`                          | GET     | Distinct facets                                       |
| `/export`                           | GET     | CSV / JSON download                                   |
| `/purge`                            | DELETE  | Wipe table (sudo)                                     |
| `/settings`                         | GET/POST| Read / update settings                                |
| `/views`                            | GET/POST| Saved filter views (per user)                         |
| `/views/{id}`                       | DELETE  | Delete saved view                                     |
| `/workflow/status/{id}`             | POST    | acknowledge / resolve / snooze / reopen               |
| `/workflow/assign/{id}`             | POST    | Set assignee                                          |
| `/comments/{id}`                    | GET/POST| Comments thread                                       |
| `/comments/{id}/{cid}`              | DELETE  | Remove a comment                                      |
| `/webhook-test`                     | POST    | Send a test message to Slack/Discord/Teams/generic    |
| `/sudo`                             | GET/POST/DELETE | Sudo session status / confirm / revoke         |
| `/integrity/verify`                 | GET     | Verify hash-chain integrity                           |
| `/bulk`                             | POST    | Bulk acknowledge / resolve / reopen / delete          |

## WP-CLI

```
wp apwpm list [--per_page=20] [--user_id=1] [--severity=critical] [--search=login]
wp apwpm count
wp apwpm verify [--limit=5000]
wp apwpm prune <days> [--yes]
wp apwpm purge --yes
wp apwpm export /tmp/apwpm.csv
wp apwpm digest [weekly]
wp apwpm scan_files
```

## PSR-3 example

```php
$logger = APWPM_PSR3::get_logger();
$logger->error( 'Order {id} failed', [ 'id' => 1234, '_action' => 'order_failed' ] );
```

## Custom events

```php
add_action( 'apwpm_register_event_types', function ( $registry ) {
    $registry->register( 'export_run', [
        'label'    => 'Export ran',
        'severity' => 'info',
        'icon'     => 'download',
    ] );
} );

APWPM_Logger::log( [ 'action_type' => 'export_run', 'description' => 'Nightly export complete' ] );
```

> **Note:** Legacy `APWPM_*` class names and `apwpm_*` hook names continue to work as backward-compatible aliases for any existing extensions.

## Keyboard shortcuts

- `?` show help
- `/` focus search
- `l` toggle live polling
- `r` refresh
- `g d` / `g t` / `g i` / `g a` / `g r` / `g s` jump to Dashboard / Timeline / Insights / Analytics / Reports / Settings
- `esc` clear bulk selection

## Multisite

Drop in a network. The plugin tags every event with `blog_id` and exposes a network-wide dashboard for network admins. Logs are stored in the network-prefixed `{base_prefix}apwpm_activity_logs` table.

## Security & integrity model

1. Every REST endpoint requires `manage_options` and a valid `wp_rest` nonce.
2. Destructive endpoints (`purge`, `rollback`, `bulk delete`) require **sudo mode** — a short-lived re-authentication.
3. With the **hash chain** enabled, every row stores an HMAC-SHA256 over `prev_hash + canonical_row`. Tampering is detected by `APWPM_Integrity::verify()` (Site Health + REST).
4. **Append-only mode** filters block any code path that would delete log rows.
5. PII redaction stores HMAC-hashed IP/UA instead of raw values; the GDPR exporter/eraser plugs into core WordPress privacy tools.

## Versions

`APWPM_VERSION = 1.0.0`, `APWPM_DB_VERSION = 1.3.0`.  Legacy `APWPM_VERSION` and `APWPM_DB_VERSION` constants remain defined as aliases.
