Skip to content

Protect abilities: register status, threats, and Account Protection via Registrar#48737

Draft
enejb wants to merge 1 commit into
trunkfrom
add/ship-protect-abilities
Draft

Protect abilities: register status, threats, and Account Protection via Registrar#48737
enejb wants to merge 1 commit into
trunkfrom
add/ship-protect-abilities

Conversation

@enejb
Copy link
Copy Markdown
Member

@enejb enejb commented May 12, 2026

Summary

Registers the first slice of Jetpack Protect abilities with the WordPress Abilities API, following the plan in the Abilities Everywhere project (§2.3 plugin-core abilities surface). The class extends the shared Registrar base from automattic/jetpack-wp-abilities, so the jetpack_wp_abilities_enabled gate, late-load fallback, and per-ability allow-list filter all come for free.

This v1 surface is read-only plus one declarative state-setter. Destructive writes (fix-threat, ignore-threat, request-scan) are deliberately deferred to a follow-up — they need careful per-id capability scoping that the read paths don't.

Abilities registered

Slug Shape
jetpack-protect/get-status { has_plan, last_scan: { timestamp, status, threats_found }, threat_counts: { total, fixable, critical }, scan_in_progress }
jetpack-protect/list-threats Paginated [{ id, signature, title, description, severity, type, fixable, ignored, first_detected, source }], with severity (critical/high/medium/low) and type (core/plugin/theme/file) filters; per_page capped at 100
jetpack-protect/get-threat Single threat by id (consolidated-read pattern: unknown id → [], not WP_Error); adds recommended_action
jetpack-protect/get-account-protection-status { enabled, supported, last_event, attempt_count_24h, blocked_count_24h } (event/count fields are placeholder-shaped; tracked for the follow-up)
jetpack-protect/set-account-protection { enabled, changed } — idempotent toggle of the Account Protection module

Capability matching

All five abilities gate on current_user_can( 'manage_options' ), matching the existing capability on every route in projects/plugins/protect/src/class-rest-controller.php and the /status route in projects/packages/protect-status/src/class-rest-controller.php. No new caps invented.

Wiring

Case C (plugin-core ability — the REST surface lives in the plugin itself, not in a module). Protect_Abilities::init() is called from Jetpack_Protect::init() after the legacy REST_Controller::init(). The Registrar handles the jetpack_wp_abilities_enabled gate internally — no extra apply_filters at the call site.

Test coverage

projects/plugins/protect/tests/php/abilities/Protect_Abilities_Test.php (41 tests, 125 assertions):

  • Registrar wiring: gate-false short-circuit, gate-true hooks both lifecycle actions, per-ability allow-list filter, category auto-injection.
  • Abstract getters: slug/category/abilities map shape, surface enumeration, annotation correctness, per_page cap == 100.
  • Permission callbacks: admin allowed, subscriber denied, anonymous denied (for both view and manage gates).
  • Execute happy paths for all 5 abilities — mocked via a Protect_Abilities_Test_Stub that overrides the protected seams (fetch_status, fetch_account_protection_settings, account_protection, has_required_plan).
  • get-threat with unknown id returns [] (not WP_Error).
  • set-account-protection idempotency: desired==current → changed=false, no call to enable()/disable().
  • Schema edge cases: missing required input rejected; '0'-style string id accepted; non-boolean enabled rejected with distinct error code.

Test plan

  • cd projects/plugins/protect && composer phpunit -- --filter Protect_Abilities_Test passes (currently 41/41).
  • Manually flip jetpack_wp_abilities_enabled true on a Protect-connected site and confirm the 5 slugs appear in wp_get_abilities() / /wp-json/wp-abilities/v1/abilities.
  • Call jetpack-protect/get-status with admin auth and confirm the 4-key shape.
  • Call jetpack-protect/list-threats with { severity: 'critical' } and confirm filter applies.
  • Call jetpack-protect/set-account-protection twice with the same enabled value — second call returns changed=false.

@github-actions github-actions Bot added [Plugin] Protect A plugin with features to protect a site: brute force protection, security scanning, and a WAF. [Status] In Progress [Tests] Includes Tests labels May 12, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • 🔴 Add a "[Status]" label (In Progress, Needs Review, ...).
  • 🔴 Add testing instructions.
  • 🔴 Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


🔴 Action required: Please include detailed testing steps, explaining how to test your change, like so:

## Testing instructions:

* Go to '..'
*

🔴 Action required: We would recommend that you add a section to the PR description to specify whether this PR includes any changes to data or privacy, like so:

## Does this pull request change what data or activity we track or use?

My PR adds *x* and *y*.

Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@github-actions github-actions Bot added the [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. label May 12, 2026
@jp-launch-control
Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 1 file.

File Coverage Δ% Δ Uncovered
projects/plugins/protect/src/class-jetpack-protect.php 0/173 (0.00%) 0.00% 1 ❤️‍🩹

1 file is newly checked for coverage.

File Coverage
projects/plugins/protect/src/abilities/class-protect-abilities.php 355/368 (96.47%) 💚

Full summary · PHP report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Protect A plugin with features to protect a site: brute force protection, security scanning, and a WAF. [Status] In Progress [Status] Needs Author Reply We need more details from you. This label will be auto-added until the PR meets all requirements. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant