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.
Background
FEP-ef61 requires gateways listed by a portable actor to accept
POSTrequests to the actor's inbox. For example, if a portable actor has this inbox:and one of its gateways is
https://server.example/, the gateway-compatible inbox endpoint would be: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/fedifyfor receiving portable actor inbox deliveries through the fixed FEP-ef61 gateway endpoint.The work should include:
POST /.well-known/apgateway/{did}/{path...}/inbox;ap+ef61:inbox IRI from the DID authority and gateway path;gatewaysproperty;404 Not Foundwhen the local server does not accept delivery for the target portable actor;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
gatewayslist, 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:
InboxContextexpose the portable target IRI or gateway request information?id?Scope
This issue is only about inbound portable inbox delivery through the fixed FEP-ef61 gateway endpoint.
It does not include:
Dependencies
This should depend on the lower-level portable URI, vocabulary, proof policy, and compatible identifier work under #288:
ap:andap+ef61:URI schemes in vocabulary codecs #826 forap:/ap+ef61:URI support in vocabulary codecs;ap:/ap+ef61:URIs #828 for portable URI canonicalization and comparison;ap:/ap+ef61:URIs #829 for FEP-fe34 cryptographic origins;gateways;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:
POST /.well-known/apgateway/did:key:.../actor/inboxinto the existing inbox delivery pipeline;ap+ef61:inbox IRI;404 Not Foundwhen the local server does not accept delivery for the target portable actor;This should be added as a sub-issue of #288.