kitsune-soc / kitsune

🦊 (fast) ActivityPub-federated microblogging
https://joinkitsune.org
Other
303 stars 19 forks source link

Full restructure #418

Open aumetra opened 10 months ago

aumetra commented 10 months ago

So, Kitsune right now is pretty intertwined with ActivityPub and Webfinger. Kinda makes sense since it started out by being built around those standards, but I think we can do better with minimal performance impact.

References #201 and #415

Rough plan

  1. Move ActivityPub logic into kitsune-activitypub
  2. Define traits in kitsune-core, such as the Federator, FederationFetcher, and Resolver trait
    • These three areas were chosen since they define pretty well how ActivityPub works:
      1. Resolve an actor via Webfinger
      2. Fetch them via a fetcher
      3. Use the federator to send out things such as post creation, deletion, favourites, etc.
  3. Instead of giving services a Fetcher or Deliverer, we give them a vector of these which they iterate over and perform the appropriate actions in the different federated networks
    • Enum dispatch required here since async traits aren't object-safe
  4. Restructure the database
    1. Create a separate key table to store the keys and their IDs and references to an account that owns them
    2. Move the ActivityPub-specific things, such as collection URLs into its seperate table
    3. Rename the actor_type field to something more generic (such as just type)
    4. Add a protocol marker to each account, post, like, etc. to identify from what network they originate from

I invite some bikeshedding to this issue since this is a large undertaking and will make significant changes to all parts of Kitsune


PRs:

aumetra commented 10 months ago

We still need to address here are system actors (cc @perillamint, if you have any suggestions).
Another unaddressed area is support for multiple domains.

Edit: Regarding the keys for the system actor, the design outlined here somewhat incorporates the idea of keys that aren't owned by an actual "account"

aumetra commented 10 months ago

For multiple domains, we could have a table such as this one:

CREATE TABLE domains (
    domain TEXT PRIMARY KEY,
    owner_id UUID REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
    globally_usable BOOLEAN NOT NULL, -- Name can be bikeshed. Marker on whether anyone from the instance can choose this as "their" domain
    verification_token TEXT NOT NULL,
    verified_at TIMESTAMPTZ
);

And accounts would reference them like so:

CREATE TABLE accounts (
    [...]
    domain TEXT NOT NULL REFERENCES domains(domain)
);

References #179

aumetra commented 10 months ago

(gonna try to land #405 before starting this because rebasing on these planned changes would be a pain)

zeerooth commented 10 months ago

If we're doing this then I think it's important to think about how to potentially tie https://github.com/kitsune-soc/kitsune/issues/134 into our future account schema

aumetra commented 10 months ago

it's important to think about how to potentially tie https://github.com/kitsune-soc/kitsune/issues/134 into our future account schema

Do you have any suggestions on how we can tie this in?
Potentially a new table, such as account_proofs with the structure of:

CREATE TABLE accounts_proofs (
    id UUID PRIMARY KEY,
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE ON UPDATE CASCADE,
    type TEXT NOT NULL,
    verification_method TEXT NOT NULL,
    value TEXT NOT NULL,
    purpose TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

That way we can have a 1:N relationship with accounts, allowing an account to display N proofs

aumetra commented 10 months ago

In general, I'd only store the "core" functionality inside the accounts table from now on.
Things that should go into a different table are:

By having that neat separation, we don't need to store everything into a single gigantic table

silverpill commented 10 months ago

That way we can have a 1:N relationship with accounts, allowing an account to display N proofs

The relationship between actors and proof subjects (DIDs) is "many to many". Each actor can have multiple proofs, and different actors can be linked to a single subject (this enables migration procedures like the one described in FEP-7628 (sub-type 2)).

ActivityPub 2.0 may look like that: https://codeberg.org/fediverse/fep/src/branch/main/fep/ae97/fep-ae97.md#server-independent-ids (DIDs instead of URLs).

I haven't yet decided how to represent all these possibilities in the database... Moving non-core functionality into separate tables sounds like a good idea.

aumetra commented 10 months ago

The relationship between actors and proof subjects (DIDs) is "many to many"

Yeah, I focussed way too much on the proof object. But yeah, the identity object itself should obviously be serialized to the database, too.

Something like:

CREATE TABLE accounts_proofs (
    id UUID PRIMARY KEY,
    type TEXT NOT NULL,
    verification_method TEXT NOT NULL,
    value TEXT NOT NULL,
    purpose TEXT NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE accounts_identities (
    id TEXT NOT NULL, -- Where this is the "id" value embedded in the identity attachment
    account_id UUID NOT NULL REFERENCES accounts(id) ON DELETE CASCADE ON UPDATE CASCADE,
    proof_id UUID NOT NULL REFERENCES accounts_proofs(id),
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,

    PRIMARY KEY (id, account_id)
);

That way we can map accounts to identities in an M:N way, and attach a link to a proof as metadata.
That way the proof themselves wouldn't need to reference an actor since this central identities table takes care of the mapping.

aumetra commented 10 months ago

Technically this design would be a logical 1:1 relationship between an identity and proof, while you could technically generate multiple proofs of the same identity.
Identity management is a pain.

perillamint commented 9 months ago

We still need to address here are system actors (cc @perillamint, if you have any suggestions). Another unaddressed area is support for multiple domains.

Edit: Regarding the keys for the system actor, the design outlined here somewhat incorporates the idea of keys that aren't owned by an actual "account"

I guess system actors could be implemented using some kind of roles table for the accounts, like Mastodon's user_roles table. (Well, actually, Mastodon does not use that table to mark system accounts, but I think we can take that way anyway.)

Also, I noticed there is a definition of user_roles table in crates/kitsune-db/src/model/user_role.rs. I think service account can be implemented using that.

erlend-sh commented 6 months ago

This doc gives a good idea of alternative protocol requirements: