Black Friday: 79% off every plugin Shop the sale →

Hooks & Filters

All extension points are filters. The plugin fires no custom actions of its own; the only action name it owns is the WP-Cron hook abau_scheduled_audit.

HookTypeArgumentsPurpose
abau_rulesfilterarray $rulesAdd, remove or replace audit rules. Each rule implements AbAu_Rule_Interface (or extends AbAu_Rule).
abau_audit_rolesfilterstring[] $rolesRoles checked by the matrix, least privileged first. anonymous means logged out.
abau_permission_call_budgetfilterint $secondsSeconds allowed per permission check. Default 2.
abau_audit_time_budgetfilterint $secondsSeconds allowed for all permission checks in one audit. Default 60.
abau_history_limitfilterint $limitNumber of audits kept in History. Default 20.
abau_notification_recipientsfilterstring[] $recipients, AbAu_Audit_Result $resultEmail addresses for alerts. Default: the site admin email.
abau_storeengine_product_idfilterint $product_idStoreEngine product ID used for licensing. 0 disables licensing.
abau_storeengine_store_urlfilterstring $store_urlStore URL used for licensing and updates.
abau_storeengine_allow_localfilterbool $allowWhether a license may be activated from a local or development site. Default true.
abau_store_dashboard_urlfilterstring $urlURL behind the Manage License button.
abau_scheduled_auditaction (WP-Cron)string $triggerThe cron event that runs automatic audits. Trigger your own run with wp cron event run abau_scheduled_audit.

The licensing product ID and store URL can also be set with the ABAU_STOREENGINE_PRODUCT_ID and ABAU_STOREENGINE_STORE_URL constants in wp-config.php.

Add a rule#

A rule receives only stored data (the ability record and its matrix row), never the WP_Ability object, so it cannot run an ability. A rule that throws is skipped and reported on the Report tab instead of stopping the audit.

<?php
/**
 * Flag abilities that are exposed to MCP but have no output schema.
 */
final class My_MCP_Output_Rule extends AbAu_Rule {

	public function get_id() {
		return 'my-mcp-output';
	}

	public function get_title() {
		return __( 'MCP ability has no output schema', 'my-plugin' );
	}

	public function get_severity() {
		return AbAu_Severity::MEDIUM;
	}

	public function get_explanation() {
		return __( 'AI agents rely on the output schema to understand what an ability returns.', 'my-plugin' );
	}

	public function get_fix() {
		return __( 'Add an output_schema to the ability registration.', 'my-plugin' );
	}

	public function get_docs_url() {
		return self::DOCS_SCHEMA;
	}

	public function evaluate( AbAu_Ability_Record $record, array $permissions ) {
		if ( empty( $record->exposure['mcp']['value'] ) || ! empty( $record->output_schema ) ) {
			return array();
		}

		return array(
			$this->finding( $record, __( 'Exposed to MCP without an output schema.', 'my-plugin' ) ),
		);
	}
}

add_filter( 'abau_rules', function ( array $rules ) {
	$rules[] = new My_MCP_Output_Rule();
	return $rules;
} );

$record->exposure holds one entry each for public, rest and mcp, with a value (bool) and a source (explicit, public, default or resolved). The base class also gives you $record->is_readonly(), $record->is_destructive(), $this->passing_roles( $permissions, $roles ) and $this->role_list( $roles ).

Remove a built-in rule#

add_filter( 'abau_rules', function ( array $rules ) {
	return array_filter( $rules, function ( $rule ) {
		return 'short-description' !== $rule->get_id();
	} );
} );

Audit a custom role#

add_filter( 'abau_audit_roles', function ( array $roles ) {
	// Insert "support_agent" between editor and administrator.
	$index = array_search( 'administrator', $roles, true );
	array_splice( $roles, $index, 0, array( 'support_agent' ) );
	return $roles;
} );

Send alerts to a security mailbox#

add_filter( 'abau_notification_recipients', function ( array $recipients, AbAu_Audit_Result $result ) {
	$recipients[] = 'security@example.com';
	return $recipients;
}, 10, 2 );

Give slow permission checks more time#

add_filter( 'abau_permission_call_budget', function () {
	return 5; // seconds per check
} );

add_filter( 'abau_audit_time_budget', function () {
	return 180; // seconds per audit
} );

Keep more history#

add_filter( 'abau_history_limit', function () {
	return 50;
} );
Was this article helpful?