feat: wire on_unknown_activity to actually dispatch unknown inbound activities #22

Open
opened 2026-07-25 15:15:04 +00:00 by GKaszewski · 0 comments
Owner

Problem

ApObjectHandler::on_unknown_activity exists on the trait with a default no-op, but the inbox handler never calls it. Unknown activity types are silently accepted (200 response) but the consumer's implementation is never invoked.

The root cause: activitypub_federation's ActivityData consumes the request body during signature verification. When deserialization of the known InboxActivities enum fails, the raw body is gone — we can't re-parse it to extract the type and forward to on_unknown_activity.

Possible approaches

  1. Clone the body via middleware — buffer the request body before ActivityData consumes it. Pass a clone to ActivityData for signature verification, keep the original for fallback parsing on deserialization failure.

  2. Reimplement the inbox pipeline — bypass receive_activity entirely. Deserialize the raw body ourselves, try the known enum, fall back to on_unknown_activity, then use the federation library's lower-level signature verification primitives.

  3. Upstream PR — make ActivityData.body public or add an accessor, so we can read the body after receive_activity fails.

Current behavior

Unknown types get HTTP 200 (good — prevents remote retries) but the consumer is never notified. The trait method is documented with this limitation.

## Problem `ApObjectHandler::on_unknown_activity` exists on the trait with a default no-op, but the inbox handler never calls it. Unknown activity types are silently accepted (200 response) but the consumer's implementation is never invoked. The root cause: `activitypub_federation`'s `ActivityData` consumes the request body during signature verification. When deserialization of the known `InboxActivities` enum fails, the raw body is gone — we can't re-parse it to extract the type and forward to `on_unknown_activity`. ## Possible approaches 1. **Clone the body via middleware** — buffer the request body before `ActivityData` consumes it. Pass a clone to `ActivityData` for signature verification, keep the original for fallback parsing on deserialization failure. 2. **Reimplement the inbox pipeline** — bypass `receive_activity` entirely. Deserialize the raw body ourselves, try the known enum, fall back to `on_unknown_activity`, then use the federation library's lower-level signature verification primitives. 3. **Upstream PR** — make `ActivityData.body` public or add an accessor, so we can read the body after `receive_activity` fails. ## Current behavior Unknown types get HTTP 200 (good — prevents remote retries) but the consumer is never notified. The trait method is documented with this limitation.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GKaszewski/k-ap#22