Skip to content

Portable inbox endpoint for FEP-ef61 actors #839

Description

@dahlia

Background

FEP-ef61 requires gateways listed by a portable actor to accept POST requests to the actor's inbox. For example, if a portable actor has this inbox:

ap+ef61://did:key:z6MkAlice/actor/inbox

and one of its gateways is https://server.example/, the gateway-compatible inbox endpoint would be:

POST https://server.example/.well-known/apgateway/did:key:z6MkAlice/actor/inbox

Fedify should support this endpoint without introducing a separate public inbox API for portable actors. Applications that already configure inbox dispatchers and inbox listeners should get portable inbox delivery automatically once the corresponding portable actor can be resolved and accepted by the local gateway.

This issue is about routing gateway inbox requests into Fedify's existing inbox delivery pipeline.

Proposed work

Add support in @fedify/fedify for receiving portable actor inbox deliveries through the fixed FEP-ef61 gateway endpoint.

The work should include:

  • handling POST /.well-known/apgateway/{did}/{path...}/inbox;
  • reconstructing the canonical ap+ef61: inbox IRI from the DID authority and gateway path;
  • identifying the owning portable actor and resolving its gateways property;
  • deciding whether the local gateway accepts delivery for that actor;
  • returning 404 Not Found when the local server does not accept delivery for the target portable actor;
  • reusing the existing Fedify inbox dispatcher and inbox listener pipeline instead of adding a new portable inbox API;
  • applying the FEP-ef61 proof policy to portable activities and objects in the delivered payload;
  • preserving existing ordinary ActivityPub inbox delivery behavior;
  • defining status-code behavior for malformed portable IDs, unknown actors, unsupported actors, and invalid proofs.

Forwarding needs to be part of the design. When a gateway accepts an activity for a portable actor, Fedify should be able to forward that activity to the actor's other gateways so delivery can reach the other places where the actor's data is stored. Forwarding should use the actor's gateways list, skip the gateway that received the current request, and avoid sending the activity back to the gateway it came from when that can be identified.

Fedify also needs a loop-prevention and idempotency policy for gateway inbox forwarding. FEP-ef61 says an activity must not be forwarded from an inbox more than once. The implementation should define how to mark or recognize a forwarded gateway delivery, how long to remember forwarded activity IDs, and how this interacts with the existing inbox idempotency behavior. This should avoid both forwarding loops and duplicate application-level delivery.

Design questions

The implementation should settle these API and behavior details before finalizing the code path:

  • How should Fedify map the gateway path back to the existing actor/inbox dispatcher model?
  • Should accepting portable inbox delivery be implicit from serving the portable actor, or should there be an explicit opt-in?
  • Should InboxContext expose the portable target IRI or gateway request information?
  • Where should inbox-level idempotency and “forwarded once” tracking live?
  • What marker or request metadata should Fedify use to distinguish an original delivery from a gateway-forwarded delivery?
  • Should forwarded gateway deliveries use an HTTP header, a request signature property, local queue metadata, or some other mechanism to prevent re-forwarding?
  • Which activity identifier should be used for idempotency when the delivered activity has no stable id?
  • Which HTTP signature key should be used for gateway-to-gateway forwarding?
  • How should non-portable activities delivered to a portable actor inbox be handled?

Scope

This issue is only about inbound portable inbox delivery through the fixed FEP-ef61 gateway endpoint.

It does not include:

  • FEP-ae97 outbox posting;
  • actor registration;
  • media upload or deletion;
  • gateway discovery;
  • object serving endpoints;
  • media serving endpoints;
  • automatic storage for portable inbox payloads.

Dependencies

This should depend on the lower-level portable URI, vocabulary, proof policy, and compatible identifier work under #288:

It may also share gateway request handling code with #835, but portable inbox delivery should not require the object-serving endpoint to be implemented first.

Tests

Add regression tests for portable inbox delivery.

The tests should cover:

  • routing POST /.well-known/apgateway/did:key:.../actor/inbox into the existing inbox delivery pipeline;
  • reconstructing the expected ap+ef61: inbox IRI;
  • accepting delivery when the local server is an allowed gateway for the target portable actor;
  • returning 404 Not Found when the local server does not accept delivery for the target portable actor;
  • rejecting malformed DID/path requests;
  • applying the FEP-ef61 proof policy to portable activities and objects;
  • preserving existing ordinary ActivityPub inbox behavior;
  • forwarding an accepted activity to other actor gateways when appropriate;
  • skipping the current gateway and, where possible, the gateway that sent the forwarded delivery;
  • ensuring an activity is not forwarded from an inbox more than once;
  • avoiding duplicate listener execution for duplicate gateway deliveries.

This should be added as a sub-issue of #288.

Metadata

Metadata

Assignees

Priority

High

Effort

High

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions