FEP-ef61: Portable Objects

@silverpill would it be interesting to discuss with the Mastodon team, or possibly with misskey or pleroma/akkoma, how to implement this in existing implementations? Or what/where is the progress on that?

Implementing the receiving side of this is not difficult. I did that in Mitra and my server now can receive portable activities from Streams. Mastodon and others could probably do that as well.

But the producing side is more complicated, because it requires changing the way we build ActivityPub apps. Most Fediverse services today are both ActivityPub Server and Client crammed into one application, and they manage cryptographic keys on behalf of a user. FEP-ef61 network will probably look like Nostr: simple servers that store and transmit messages, and powerful clients. There might also be identity providers that take care of key management.

I don’t know what is the best way to build all of that. More experimentation is needed. I am planning to build a simple FEP-ef61 server to figure out how storage is supposed to work before doing anything serious in Mitra. I am also working on a Rust library that can be used to build FEP-ef61 servers and clients.

1 Like

Streams can produce portable activities, but I think they store secret keys on a server. This is fine if you host a single user instance on your own hardware, but in other situations this is roughly equivalent to status quo (trusting the server owner).

1 Like

I think I’ve heard this idea before and I still don’t think I understand it. The problem as I see it is that there are certain use cases that are not feasible to implement in a client. For instance, I don’t see how you could implement a Reddit-like social platform with a “simple server” and a “powerful client”. You simply could not implement the required sorting algorithms as a client.

I feel that this “simple servers, powerful clients” idea excludes many potential use cases and I fear that this would essentially reduce ActivityPub to some kind of glorified email, or at least make everything but the microblogging use case into a second-class citizen.

I keep federated groups in mind when I am working on this. I don’t think it limits ActivityPub in any way, but I guess we will see once implementations begin to emerge.
In any case, the idea here is not to replace existing ActivityPub network, but to complement it.

Can one use this combined with a HTTPS actor? e.g.

{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://w3id.org/security/data-integrity/v1",
    "https://w3id.org/fep/ef61"
  ],
  "type": "Note",
  "id": "ap://did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/objects/dc505858-08ec-4a80-81dd-e6670fd8c55f",
  "attributedTo": "http://host.example/actor",
  "content": "Hello!",
  "to": [
       "http://host.example/followers", "https://www.w3.org/ns/activitystreams#Public"
  ],
  "proof": {"...": "..."}
}

would be a message (with corresponding Create). http://host.example/actor would acknowledge did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2 by having it in its assertionMethod.

This would lead to portable objects without portable actors. In particular objects that don’t need to live on servers.

Yes, I think it might work:

  • The did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2 authority claims that object is attributed to http://host.example/actor
  • The host.example authority claims that did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2 can sign things on its behalf.

Authorities agree, therefore this object can be trusted.

Why not make actors portable too? FEP-ef61 can work in compatibility mode, in that case the actor ID would look like this:

http://host.example/.well-known/apgateway/did:key:z6MkrJVnaZkeFzdQyMZu1cgjg7k1pZZ6pvBQ7XJPt4swbTQ2/actor

It’s the entire evolution not revolution concept. Sending portable objects from an existing https actor is kind of an intermediate step, where one doesn’t have to change everything.

1 Like

Update: #529 - FEP-ef61: Endpoints and services - fediverse/fep - Forgejo: Beyond coding. We Forge.

Preferred gateways can be declared in a DID document (as DID services), and maybe in actor’s endpoints mapping too.

I think using endpoints for that makes a lot of sense because according to the ActivityPub spec, this object “
maps additional (typically server/domain-wide) endpoints which may be useful either for this actor or someone referencing this actor.” In FEP-ef61 world, these endpoints are “DID-wide”.

This is somewhat similar to FEP-c390 Identity proofs, where two authorities, domain-based and DID-based, are coordinating to create a verifiable link. I added a new section to FEP-fe34 called “Cross-origin relationships”, where such use cases will be covered.

1 Like

Hello! Just thought I’d share some early work I’ve done on adding FEP-ef61 support to my fork of Bluesky’s PDS server with ActivityPub support. More information on that project can be found here:

Anyway, as for FEP-ef61 support, it’s not in my draft PR yet, but below you can find a few sample screenshots of responses. Notably, my in implementation I convert AtProto DID’s into ActivityPub DID’s by storing the AtProto DID’s in did:key’s with the MultiDID encoding (as a base58 string).

The first is my updated webfinger, and a placeholder apgateway showcasing DID conversion.

Second, an A/B comparison of what my standard actor profile response looks like, and what it looks like in “FEP ef61” format. It’s currently only available behind a query parameter, at least until I finish the gateway.

EDIT: Click the GitHub link above. I’m not allowed to post 2 images or more than 2 links as a new user. :person_shrugging:

3 Likes

Hello @PoV !

You can use ATProto DIDs directly, without encoding them with multiDID.

FEP-ef61 is compatible with all DID methods, and did:key requirement was added only to facilitate implementation convergence. But existing FEP-ef61 implementations support only Ed25519 did:key, so we won’t be able to interoperate.

What do you think about did:web? As far as I know, this method is supported by ATProto, and we also considered supporting it in Fediverse.

That would be nice. As you’d expect, this lead me down this path:

DID Methods

Implementers MUST support the did:key method. Other DID methods SHOULD NOT be used, as it might hinder interoperability.

It might be worth clarifying that not using Multidid Ed25519 keys hinder interoperability, than simply not using did:key.

I’m curious what existing implementations use the Ed25519 keys for, besides unique identifiers? I do realize they’re also public keys, but I haven’t got to signing or validating yet in my implementation.

I’m indifferent as I haven’t personally used AtProto’s did:web support. That said, from my understanding, it doesn’t technically support the full did:web standard (domains and subdomains only, no URLs). Parts of the code support encoding URL slashes as :'s, which I’m not sure is the standard or not, but according to the team this isn’t the case everywhere. The only reliable part is the domain.

1 Like

The recommendation to use Ed25519 is there too, it’s in the next paragraph:

DID documents SHOULD contain Ed25519 public keys represented as verification methods with Multikey type (as defined in the Controlled Identifiers specification).

Both are SHOULD, however. This is to say: we are exploring various DID methods, but did:key + ed25519 is what is currently used in production.

Those Ed25519 keys are used to sign ActivityPub objects. Here’s an example of an actor:

https://mitra.social/.well-known/apgateway/did:key:z6MknVmyPtQmD2SaGnqyGgTVEqfqkkJJnY3YVKBmbzSUNCcX/actor

The signature is in the proof object, produced in accordance with Verifiable Credential Data Integrity 1.0 standard.

1 Like

Gotcha, thanks for that.

Curiously, I noticed that document has no JSON LD @context section. While I realize JSON LD doesn’t necessarily require it, I just haven’t seen any “valid” documents without it. Is that at all commonplace, or just a fluke that this specific implementation doesn’t use them?

EDIT: Mmm
 Is it omitted because the content type is application/ld+json; profile="https://www.w3.org/ns/activitystreams", thus "@content": "https://www.w3.org/ns/activitystreams" is implied?

It was a test, the @context is already restored.
ActivityPub says that “Implementers SHOULD include the ActivityPub context in their object definitions.” I think it means that @context could be omitted if you have a good reason do so. But Mastodon rejects actor documents without @context, so everyone includes it for compatibility reasons. Other implementations seem to be more forgiving - this is what I was testing :slight_smile: