FEP-ef61: Portable Objects

The benefit of well-known path is that you can use any server as a resolver without knowing its resolver endpoint in advance. It is now less important because hosts was replaced with aliases, but might be useful nevertheless. For example clients can try to resolve DID URLs on any big fedi instance if everything else fails.

If we learn from implementation experience that “following your nose” is enough, then path requirement can be relaxed.

Also, I’ll probably change “resolver” to “gateway” because I think it should accept POST requests as well. This will remove the step where client extracts URL from a Link header in order to POST to inbox.

1 Like

FEP-ef61 breaking change: #295 - FEP-ef61: Update proposal - fediverse/fep - Codeberg.org

Resolvers are now gateways and may accept POST requests.

Apart from that, I’m seriously considering switching to ap:// URL scheme as @bumblefudge suggested, to simplify the DID parser. The downside of a custom URL scheme is that most URL libraries will not work with such URLs. For example the Rust library I’m using thinks that multibase-encoded key is a port number and refuses to accept it.

Another idea: switch back from aliases to hosts (or gateways).

3 Likes

Can you provide design justifications for the “why” of the changes (so that the rationale—and the reason for why those choices were made—are more documented), each time changes are made?

Wouldn’t there be risk involved in using very vague property names (aliases, hosts, gateways) that could collide with other possible FEPs, for plain JSON (non-JSON-LD) implementations, instead of doing prefixed property names like “didHosts”, “didGateways”, etc?

Is there a use-case where multiple actors under one DID is justified, including potentially adding more complications (what if some actors, under the same DID, point to differing gateways/hosts/etc?)? I just had a system devised for storing actors and their respective objects with compacted identifiers, and that kind of nukes that idea, and creates more challenges to solve.

Whereas I had the concept of: the authority-part of the DID URL having 1:1 relationship with an actor in the database, and then being able to shorten any non-actor objects identified by DID, to the corresponding actor with the authority-part of the DID; therefore if did:ap:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2 corresponds with actor_id of 123, then an object authored by that actor under the DID URL of did:ap:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/posts/first-post could be compacted to a short-form of say $123/posts/first-post internally, for the database. But if the relationship is DID --(1:n)--> actor, then I can’t do that, and there’d have to be a separate resolver table between DIDs and actors next, if I were to achieve the same.

Additionally, if it’s multiple actors under the same DID, then any actor with the key has the capacity to impersonate other actors under the same DID.

The resolver → gateway change was discussed here earlier. This is needed to simplify inbox/outbox deliveries.
The identity → actor many to many relationship is not really a change, but a clarification. Identity (DID) is not tied to any particular object, it “owns” objects:

I updated description of the pull request with short explanations of the reasoning behind the breaking changes.

I think aliases property could be useful in other contexts (see FEP-d2a). I agree that hosts is too generic, a more specific name would be better.

Yes. Otherwise users will be forced to use a different key for each actor, even in cases where actors can’t exist separately from each other. Examples:

  • A group actor that is managed by a person.
  • A followable conversation context (a collection AND an actor at the same time) that is attributedTo another actor

1:1 relationship was never implied. Even in my prior work on nomadic identity, FEP-c390, there was many-to-many relationship between DIDs and actors. In FEP-ef61 it is limited to 1-to-N.

Yes, but is it really an impersonation if I own the private key that signs activities of both actors?

Am I missing something obvious here? The separation between identity and data is fundamental to this proposal, if we remove it everything falls apart.

Switching to ap:// URLs: #304 - FEP-ef61: Update proposal - fediverse/fep - Codeberg.org

This is an important change. The question of a canonical ID format should be settled as soon as possible, because several projects are already working on FEP-ef61 implementations, and the format can’t be changed once the code is deployed.

Replacing aliases with gateway property: #308 - FEP-ef61: Update proposal - fediverse/fep - Codeberg.org

Makes implementation simpler. Some projects may support aliases too - this option is still mentioned in the Discussion section of the proposal.

FEP update: https://codeberg.org/fediverse/fep/pulls/360

No breaking changes this time. This PR mostly contains clarifications based on our implementation experience. Streams and Mitra has been added to the implementation list.

Can I get some guidance on what you think a DID document for a did:web identity should look like so that signed actors can be verified against it? Here is an example of what I have so far:

{
  "@context": [
    "https://www.w3.org/ns/did/v1"
  ],
  "id": "did:web:example.com",
  "assertionMethod": [
    {
      "id": "did:web:example.com#key-1",
      "type": "Multikey",
      "controller": "did:web:example.com",
      "publicKeyMultibase": "z6MkiZhkFJN5Y94dCzvVyy9TBGUXUJhq8PvnL72Pp5FjAAyT"
    }
  ],
  "authentication": [
    "did:web:example.com#key-1"
  ]
}

EDIT: removed service since I made up that usage, and corrected verificationMethod to assertionMethod.

The “//” part of the “ap://” identifier appears to be unnecessary.

Your public key should be defined with assertionMethod verification relationship because FEP-8b32 requires it. I don’t know if definition of services is correct, FEP-ef61 doesn’t currently rely on them. Other than that, looks good.

(I noticed that proof.verificationMethod in FEP-ef61 examples is not correct, because it doesn’t include the fragment ID; will fix that in the next revision)

“//” is required by RFC-3986:

The authority component is preceded by a double slash (“//”) and is
terminated by the next slash (“/”), question mark (“?”), or number
sign (“#”) character, or by the end of the URI.

The services part was my attempt to enable discovery of actors controlled by the DID.

1 Like

Updating the FEP: #397 - FEP-ef61: Update proposal - fediverse/fep - Codeberg.org

I fixed verificationMethod values in examples (now they include fragments), added a normative reference to FEP-c7d3, and described WebFinger address reverse discovery in compatibility mode.

So from reading the FEP I’m a bit confused.

  1. Many implementations assume that the id field is a regular HTTP(S) URL that can be fetched. Is this assumption wrong? The ActivityPub spec does say that “The HTTP GET method may be dereferenced against an object’s id property to retrieve the activity”. If this assumption is wrong, what would the correct behavior be (with or without this FEP)? I.e. how should an implementation fetch a resource if they cannot assume that the id field is a HTTP(S) URL?

  2. How would an implementation that is unaware of this FEP (A) federate with an implementation that uses this FEP (B)? I mean, A would presumably try to fetch the ap://... as if it was an HTTP(S) URL and just get an error. So would B only be able to interact with other implementations that are aware of and supports this FEP?

1 Like

It is not a wrong assumption. Implementers are free to choose what features to support: they are not required to support all ActivityStreams types and properties, and similarly they are not required to support all URI schemes.

If they don’t know how to fetch an object, they should ignore it. The behavior would be similar to getting 404 Not Found when attempting to fetch an HTTP URL.

This is discussed in Compatibility section. Currently ef61-aware services use HTTP URLs constructed from ap:// URLs and gateway URLs:

https://social.example/.well-known/apgateway/did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/path/to/object

(the .well-known/apgateway prefix is kind of ugly, and some people consider well-known URLs to be an anti-pattern, so this part of the spec may change in the future)

1 Like

Of course - but when it comes to most extensions, they allow for backwards-compatibility or at least there are mitigating factors. For instance, an extension that adds a field to an object can still be used by implementations that are unaware of that extension; they will simply ignore that field. An extension that adds a new type may still allow federation with other unaffected types (and could even provide a fallback type to allow unaware implementers to still process the object somewhat).

So most extensions only provide something on top or in addition to the base specification, so the extension does not break federation for the most part.

However, changing the ID scheme of all objects, especially actors, would affect, well, all objects. No objects, no federation. Especially, no actors, no federation. So it would seem to me that this extension would divide the ecosystem into two groups: Those that are aware of and supports this extension and those that are unaware and unable to federate with the first group. And there would be no federation between these groups at all. That seems undesirable?

Perhaps this extension should add a new kind of id field rather than using the existing id field? Would that even be possible while still attaining the goals of the extension?

So short answer, they don’t, as far as I understand?

I, for one, prefer .well-known rather than follow-your-nose APIs, at least in this case.

They do. Compatible IDs are regular HTTP(S) URLs, and ef61-unaware implementations can handle them too.

There are 3 groups:

  1. ef61-unaware implementations
  2. ef61 implementations that use ‘ap’ IDs
  3. ef61 implementations that use compatible IDs

(2) can federate with (3), but not with (1)
(3) can federate with everyone

Streams and Mitra are (3), they use compatible IDs and can federate with Mastodon and other services. But they will also be able to communicate with (2) once they appear

1 Like

Update: #447 - FEP-ef61: Update proposal - fediverse/fep - Codeberg.org

The most important change here is a switch from FEP-c7d3 to FEP-fe34. An algorithm for computing origin of a DID URL has been specified (it is needed for same-origin checks).