Skip to content

Refactor: Extract Application from the shared actor pipeline#2926

Draft
pfefferle wants to merge 7 commits intotrunkfrom
refactor/extract-application-from-actor-system
Draft

Refactor: Extract Application from the shared actor pipeline#2926
pfefferle wants to merge 7 commits intotrunkfrom
refactor/extract-application-from-actor-system

Conversation

@pfefferle
Copy link
Member

Fixes #

Proposed changes:

  • Extract the Application actor from the shared actor pipeline into a standalone utility class (\Activitypub\Application) and self-contained REST controller.
  • The Application is no longer treated as a "virtual user" with ID -1 flowing through Actors::get_by_id(). It exists only as a JSON-LD document and HTTP signing identity.
  • Remove Actors::APPLICATION_USER_ID constant and all -1 guard clauses from Mailer, Follow handler, CLI, Health Check, Outbox, Stream integration, etc.
  • Add migration to rename keypair option from activitypub_keypair_for_-1 to activitypub_application_keypair, with legacy fallback.
  • Deprecate \Activitypub\Model\Application with _deprecated_class() notice pointing to the new classes.
  • Add dedicated @application rewrite rule so the pretty URL resolves outside the actor routing system.
  • Fix WP_Query parameter (numberposts_per_page) and guard strtotime() against empty post_date_gmt.

Other information:

  • Have you written new tests for your changes, if applicable?

Testing instructions:

  • Verify https://example.com/wp-json/activitypub/1.0/application returns a valid Application actor with publicKey, inbox, outbox, and proper @context.
  • Verify https://example.com/@application redirects/resolves to the Application endpoint.
  • Verify WebFinger for acct:application@example.com returns correct data.
  • On an existing installation, verify the Application keypair is preserved after upgrade (keys should not change).
  • Verify HTTP Signature verification still works for outbound GET requests (e.g., fetching remote actor profiles).
  • Run full PHPUnit suite — all tests should pass.

Changelog entry

  • Automatically create a changelog entry from the details below.
Changelog Entry Details

Significance

  • Patch

Type

  • Changed - for changes in existing functionality

Message

Extract Application from the shared actor pipeline into a standalone utility class.

The Application actor is not a real actor — it cannot be followed,
addressed, or interacted with. It exists only as a JSON-LD document
and a signing identity for outbound HTTP GET requests.

This introduces a standalone `Application` utility class with static
methods for identity (`get_id()`, `get_url()`, `get_webfinger()`) and
key management (`get_key_id()`, `get_public_key()`, `get_private_key()`).

- Remove `APPLICATION_USER_ID` (-1) from `Actors` collection
- Remove Application cases from `user_can_activitypub()`, Follow handler,
  Mailer, Outbox, CLI, Health Check, and Stream connector
- Make `Application_Controller` delegate to the new `Application` class
- Deprecate `Model\Application` (kept for backward compatibility)
- Rename option from `activitypub_keypair_for_-1` to
  `activitypub_application_keypair` with migration
- Add self-contained WebFinger discovery via `webfinger_data` filter,
  handling `acct:`, `/@application`, and REST API URL patterns
- Add missing backslash prefix on \_deprecated_class() call.
- Fix WP_Query parameter from 'number' to 'posts_per_page'.
- Guard strtotime() against false when post_date_gmt is empty.
- Add 'invisible' property to Application REST schema.
- Use pretty URL for Application 'url' field.
- Add @SInCE unreleased tags to new Application class.
- Add comment explaining @Application rewrite rule ordering.
- Remove Application user (ID -1) from Following test.
- Add backslash prefix to wp_cache_flush() in Migration.
- Add backslash prefix to is_string() in Application.
Run the Application WebFinger filter at priority 2 (after
Integration\Webfinger::add_pseudo_user_discovery at priority 1) so
the Application JRD is not overwritten by a WP_Error. Register a
/application/outbox route returning an empty OrderedCollection to
back the URL already advertised in the Application actor document.
- Backslash-prefix `is_string()` calls in Application::generate_key_pair().
- Use `update_option()` instead of `add_option()` to prevent keypair race.
- Use Application::get_webfinger() in health check so it works regardless
  of actor mode or authentication context.
- Add `@since unreleased` to generate_key_pair(), check_legacy_key_pair(),
  and Application_Controller::get_item().
- Add negative test for `acct:application@host` resolving to WP_Error in
  the Actors collection.
- Probe the Application endpoint (GET-readable) instead of the shared
  inbox (POST-only) in is_rest_api_accessible() health check.
- Guard strrchr() return in is_application_resource() to avoid passing
  false to substr() (PHP 8 deprecation).
- Fix migration docblock: clarify that legacy separate key options are
  migrated lazily, not by this function. Add missing @SInCE tag.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments