Milestone: ActivityPub [ActivityPub Plugin source](https://code.undefinedhackers.net/GNUsocial/gnu-social/src/branch/v3/plugins/ActivityPub). This milestone could be just this, what's different from any other ActivityPub plugin? How is it better than v2's? It's better in how it's organised and extensible. See the examples below to have an idea. To extend an Activity properties you do: public function onActivityPubValidateActivityStreamsTwoData(string $type_name, array &$validators): bool { if ($type_name === '{Type}') { $validators['attribute'] = myValidator::class; } return Event::next; } The Validator should be of the form: class myValidator extends Plugin\ActivityPub\Util\ModelValidator { /** * Validate Attribute's value * * @param mixed $value from JSON's attribute * @param mixed $container A {Type} * @return bool * @throws Exception */ public function validate($value, $container): bool { // Validate that container is a {Type} Util::subclassOf($container, Type\Extended\Object\{Type}::class, true); return {Validation Result}; To act on received activities do: public function onActivityPubNew{Type}(&$obj): bool { To add information to Activities being federated by ActivityPub do: public function ActivityPubAddActivityStreamsTwoData(string $type_name, &$type): bool { To implement an ActivityStreams 2.0 representation do: public function onActivityPubActivityStreamsTwoResponse(string $route, arrray $vars, ?TypeResponse &$response = null): bool { if ($route === '{Object route}') { $response = ModelResponse::handle($vars[{Object}]); return Event::stop; } return Event::next; }