Tessera for the Abilities API

Description

Tessera is a developer library for plugin authors who register abilities via wp_register_ability() and want snapshot capture, audit logging, approval workflows, and one-click rollback for every invocation across REST, MCP, internal PHP, and WP-CLI without building it themselves.

Declare what state your ability touches; Tessera handles the safety wrapper.

What you get out of the box

  • Pre + post snapshots. Every safety-enabled invocation captures declared state before the callback and (on success) after, so the audit log can show a real diff.
  • Audit log. One row per invocation with ability name, caller (REST/MCP/CLI/internal), user, args, result, status, duration, pre/post hashes, and parent_invocation_id for nested calls.
  • One-click rollback. Restore captured state from post_meta, options, taxonomy term assignments, user roles + caps. File contents support tiered drift detection (mtime / mtime_size / critical_hash / full_hash) plus opt-in real byte-level rollback via full_content strategy.
  • Drift check on rollback. Live state is hashed and compared to the snapshot’s post-state before restoring; if they differ the rollback returns an error unless forced.
  • Concurrency lock. Capture + execute is serialised per surface set via a MySQL advisory lock so two simultaneous invocations do not capture each other’s mid-states.
  • Encrypted redaction. Scrub secrets out of args, results, and snapshots. Stores redacted values as AES-256-GCM envelopes so rollback can still restore them.
  • Approval queue. When safety.requires_approval is set, the wrapper blocks execution and returns a 202 pending response. A human approves or rejects via wp-admin, WP-CLI, or REST. Multi-stage sequential or parallel approval chains are supported.
  • Multisite support. Each subsite gets its own set of wp_<N>_abilityguard_* tables, with auto-install on wp_initialize_site and auto-drop on wpmu_drop_tables.
  • Retention. Daily WP-Cron prunes old log rows (defaults: 30 days normal, 180 days destructive) and orphaned snapshots.

Surfaces

  • PHP API with wp_register_ability( $name, [ ..., 'safety' => [...] ] ) and helpers abilityguard_rollback, abilityguard_snapshot_meta, abilityguard_snapshot_options.
  • REST: /abilityguard/v1/log, /log/<id>, /log/export, /rollback/<id>, /rollback/bulk, /approval, /approval/<id>/approve, /approval/<id>/reject, /approval/bulk, /approval/export, /retention, /retention/prune, /health.
  • WP-CLI: wp abilityguard log list/show, wp abilityguard rollback <id>, wp abilityguard approval list/approve/reject <id>, wp abilityguard prune.
  • wp-admin: Tools > Tessera. Hybrid timeline + command-palette search, snapshot drawer, JSON-highlighted Input/Result tabs, invocation chain navigation, and real rollback against the captured snapshot.

Example

wp_register_ability( 'my-plugin/update-product-price', array(
    'label'               => 'Update product price',
    'description'         => 'Updates the price on a WooCommerce product.',
    'category'            => 'woocommerce',
    'input_schema'        => array( /* ... */ ),
    'permission_callback' => fn() => current_user_can( 'manage_woocommerce' ),
    'execute_callback'    => fn( $args ) => update_post_meta( $args['product_id'], '_price', $args['price'] ),
    'safety' => array(
        'destructive'       => true,
        'requires_approval' => false,
        'snapshot'          => fn( $input ) => array(
            'post_meta' => array( $input['product_id'] => array( '_price', '_regular_price' ) ),
            'options'   => array( 'woocommerce_last_price_change' ),
        ),
    ),
) );

Documentation

Full plugin-author documentation lives at the GitHub repo: https://github.com/ibrahimhajjaj/abilityguard

Source Code

The full source for Tessera, including the unminified React source for the admin app, lives on GitHub: https://github.com/ibrahimhajjaj/abilityguard

  • The admin bundle assets/admin.js is compiled from assets/admin.jsx (React + JSX, no preprocessor magic beyond JSX).
  • The bundler is esbuild, configured in scripts/build.mjs.
  • To rebuild the admin bundle from a fresh checkout, run npm install once, then npm run build whenever assets/admin.jsx changes. This regenerates assets/admin.js in place.
  • The release zip published to the WordPress.org directory is produced by scripts/build-release.sh, which excludes development artifacts (tests, examples, build configs) but keeps everything required for the plugin to run.

Screenshots

  • Invocation timeline. Every ability call across REST, MCP, internal PHP, and WP-CLI, with caller attribution and per-row status.
  • Approvals queue. Pending requests waiting on a human, with the requesting context and a one-click approve or reject.
  • Invocation detail after a one-click rollback restored the captured pre-state.
  • Search-as-you-type in the log: ability name, caller, status.
  • Invocation detail, result tab, with redacted secret values restored on display when the encryption key is present.
  • Snapshot drawer showing the captured pre-state and post-state for a destructive invocation.
  • Multi-stage approval chain with per-stage capability and role routing.

Installation

  1. Upload the abilityguard-mcp folder to /wp-content/plugins/.
  2. Activate the plugin through the Plugins menu in WordPress (or network-activate on multisite).
  3. Visit Tools > Tessera to view the audit log.
  4. In your own plugin, register abilities via wp_register_ability() with a safety config.

Requires WordPress 6.9 or later (for the Abilities API) and PHP 8.1 or later.

FAQ-e

Does this work without other plugins?

It will activate without registered abilities, but it only does work when other plugins register abilities with a safety config via wp_register_ability().

What state surfaces are supported for snapshots?

post_meta, options, taxonomy term assignments, user roles + caps, and files (with five tiered strategies from mtime to full content rollback).

Does it support multisite?

Yes. Each subsite gets its own set of wp_<N>_abilityguard_* tables. New subsites are auto-installed via wp_initialize_site; deleted subsites have their tables dropped via wpmu_drop_tables.

How does it handle concurrent invocations?

Per-surface MySQL advisory locks (GET_LOCK) serialise capture + execute so simultaneous invocations do not capture each other’s mid-states.

Are secrets encrypted in the log?

Yes. Redaction uses AES-256-GCM envelopes so rollback can still restore the original value when the encryption key is intact.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“Tessera for the Abilities API” is open source software. The following people have contributed to this plugin.

Contributors

Changelog

1.3.5

  • Release zip no longer ships composer/installers and its unused installer adapters. Cuts the published zip from 909K to 824K and 206 files to 98.

1.3.4

  • Release zip now ships vendor/autoload.php so the plugin actually boots on a fresh install. (1.3.3 zip was missing the autoloader and fatal’d on activation.)

1.3.3

  • Display name changed to “Tessera for the Abilities API” to clearly distinguish this plugin from any future official safety library. Slug, text domain, and internal namespace are unchanged.
  • error_log() calls in the rate-limiter and concurrency lock are now gated behind WP_DEBUG, so production hosts no longer accumulate noise from fail-open paths.
  • readme.txt gains a Source Code section documenting the GitHub repository, the esbuild-based build pipeline, and the npm run build command used to regenerate assets/admin.js.

1.3.2

  • Slug renamed to abilityguard-mcp for the WordPress.org directory.
  • Snapshot file blobs now stored under wp-uploads/abilityguard-mcp/ instead of wp-content/abilityguard-staging/.
  • Admin page CSS folded into the existing enqueued bundle; no more inline <script>/<style> echoes.
  • $_SERVER['REMOTE_ADDR'] is unslashed and sanitized before being hashed for IP-keyed rate-limit principals.

1.3.1

  • Skipped (broken release-workflow build).

1.3.0

  • Sliding-window-counter rate limiter with multi-policy support (burst + sustained), pluggable storage (Redis / object cache / transient), and IETF draft RateLimit headers.
  • Dry-run mode: per-call safety.dry_run previews a destructive ability, persists the diff, auto-rolls-back, and surfaces details via /dry-run/<id> REST endpoint and abilityguard_get_dry_run_result() helper. Result returns untouched so it validates against output_schema.
  • Approval queue gains per-stage role routing (approval_roles) and separation-of-duties enforcement across the chain.
  • Per-status retention via abilityguard_retention_days_by_status.
  • /stats REST endpoint and admin dashboard widget (counts, p50/p95, top abilities).
  • Wrapper split into observability listeners on wp_before_execute_ability / wp_after_execute_ability plus an enforcement seam (abilityguard_pre_execute_decision filter) for plugin extensions.
  • Reads meta.annotations.destructive directly from core (WP 6.9 surface), no parallel safety metadata.
  • Requires WP 6.9; pre-6.9 fallback path removed.

1.2.0

  • Parallel multi-stage approval chains with optional per-stage user pinning.
  • /health REST endpoint and a pending-approvals badge in the admin bar.
  • WP-CLI: log show --diff, approval show, prune --all-sites.
  • JSONL export option for audit log.
  • Real byte-level file rollback via safety.snapshot.files.strategy = 'full_content' (AES-256-GCM, content-addressed sidecar staging dir, atomic writes, 256 KB per-file cap).
  • Full multisite support with auto-install on subsite creation and auto-drop on subsite deletion.
  • Sequential and parallel multi-stage approval chains.

1.1.0

  • Multi-stage approval queues.
  • Invocation correlation via parent_invocation_id and an admin-side invocation chain navigator.
  • log_meta table for extensible per-row metadata.

1.0.0

  • Initial public release.
  • Snapshot, audit, rollback, and approval middleware for the WordPress Abilities API.
  • Five collectors: post_meta, options, taxonomy, user_role, files.
  • REST + WP-CLI + wp-admin surfaces.
  • Encrypted redaction, payload caps, retention pruning.