Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full restructure #418

Open
aumetra opened this issue Nov 11, 2023 · 11 comments
Open

Full restructure #418

aumetra opened this issue Nov 11, 2023 · 11 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@aumetra
Copy link
Member

aumetra commented Nov 11, 2023

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 aumetra added enhancement New feature or request help wanted Extra attention is needed labels Nov 11, 2023
@aumetra aumetra added this to the First alpha release milestone Nov 11, 2023
@aumetra
Copy link
Member Author

aumetra commented Nov 11, 2023

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
Copy link
Member Author

aumetra commented Nov 11, 2023

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
Copy link
Member Author

aumetra commented Nov 11, 2023

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

@zeerooth
Copy link
Collaborator

If we're doing this then I think it's important to think about how to potentially tie #134 into our future account schema

@aumetra
Copy link
Member Author

aumetra commented Nov 11, 2023

it's important to think about how to potentially tie #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
Copy link
Member Author

aumetra commented Nov 11, 2023

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:

  • Collection URLs (followers, following, inbox, outbox, etc.)
  • Cryptographic keys
  • Even (potentially) the URL of the actor, since we maybe want to serve the users from different URLs dependent on the protocol

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

@silverpill
Copy link

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
Copy link
Member Author

aumetra commented Nov 12, 2023

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
Copy link
Member Author

aumetra commented Nov 12, 2023

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
Copy link
Contributor

perillamint commented Nov 25, 2023

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.

@aumetra aumetra mentioned this issue Dec 16, 2023
9 tasks
@erlend-sh
Copy link

This doc gives a good idea of alternative protocol requirements:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

5 participants