# Federation PrivaPub is an ActivityPub server written in C#. This document follows [FEP-67ff](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) and describes how it federates. ## Supported federation protocols and standards - [ActivityPub](https://www.w3.org/TR/activitypub/) (server-to-server) - [WebFinger](https://webfinger.net/) - [HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures), `rsa-sha256` / `hs2019` with RSA keys - [NodeInfo](https://nodeinfo.diaspora.software/) 2.0 and 2.1 ## Supported FEPs - [FEP-67ff: FEDERATION.md](https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md) - [FEP-f1d5: NodeInfo in Fediverse Software](https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md) - [FEP-2c59: Discovery of a WebFinger address from an ActivityPub actor](https://codeberg.org/fediverse/fep/src/branch/main/fep/2c59/fep-2c59.md) Planned: FEP-1b12 (communities), FEP-8fcf (followers synchronisation), FEP-5feb (`indexable`), FEP-7628 (Move), FEP-044f (quotes). ## Actors Every account is an *avatar*: one private login can own several, and they are deliberately unlinkable. Nothing in an actor document, a collection, NodeInfo or a delivery relates two avatars of the same login. | Thing | Address | |---|---| | Actor (Person, Group, Application) | `/peasants/{name}` (`/users/{name}` redirects) | | Inbox | `/peasants/{name}/mouth` | | Outbox | `/peasants/{name}/anus` | | Shared inbox | `/human-centipede` | | Followers / following | `/peasants/{name}/groupies`, `/peasants/{name}/stalking` | | Objects | `/peasants/{name}/scribbles/{id}` | | Activities | `/peasants/{name}/grunts/{id}` | | Direct-message context | `/peasants/{name}/whispers/{id}` | | Profile and post pages | `/@{name}`, `/@{name}/{id}` | The names are the project's own and are stable; resolve actors through WebFinger, not by guessing a path. - The key is `{actor}#main-key`, RSA 2048, served as SPKI PEM with `owner` set to the actor. - `published` on an actor is truncated to the day. `indexable` is `false`. - The instance actor is `/peasants/privapub` (type `Application`). It signs every fetch PrivaPub makes, so no avatar's key is used to read another server's content. ## Groups A group is either a **community** or a **circle**. - A community is a `Group` actor. It accepts `Follow` and re-shares (`Announce`) posts from its followers that address it. Full FEP-1b12 behaviour (announcing activities, `audience`, moderation) is planned. - A circle is private and does not federate yet: its actor, collections and WebFinger answer 404, and its posts are never delivered. ## Activities Received: | Activity | Effect | |---|---| | `Follow` | follows an avatar or community; `Accept` is sent unless the community approves members by hand | | `Accept{Follow}`, `Reject{Follow}` | completes or ends a follow an avatar requested | | `Undo{Follow, Like, Announce}` | reverses it | | `Create{Note, Article, Page, Question, …}` | stored when a local avatar follows the author, is addressed or mentioned, when it replies to a local post, or when it is addressed to a community the author follows; a public parent is fetched to complete the thread | | `Update{Note}` | replaces the content; the previous version is kept | | `Update{Person}` | refetches the actor | | `Like` | counted and notified, on posts the liker could see | | `Announce` | counted and notified for local posts; shown to followers of the announcer, with the original refetched from its origin | | `Delete` | deletes the object, or the actor and its follows | | `Flag` | becomes a report for this server's moderators | Sent: `Follow`, `Undo{Follow}`, `Create{Note}`, `Update{Note}`, `Update{Person}`, `Delete{Tombstone}`, `Accept{Follow}`, `Reject{Follow}`, `Like`, `Announce` and their `Undo`, `Flag`. A deleted post answers 410 with a `Tombstone`. - **Attachments** are `Document`s with `mediaType`, `name` (alt text), `blurhash`, `focalPoint`, `width` and `height`. Uploaded files have all metadata removed. - **Pinned posts** are the actor's `featured` collection (`/trophies`); `featuredTags` is `/tattoos`. - **Blocks are never sent.** A blocked account is sent `Reject{Follow}` if it followed, and is unfollowed. - **Reports** are sent as `Flag` by the instance actor, never by the reporting account. A `Create`'s `Note` carries Mastodon's `content`, `contentMap`, `summary` and `sensitive`, plus `Mention` and `Hashtag` tags. A post's title becomes `name` and is also the first, bold line of `content`, because Mastodon does not show `name`. A content warning without its own text uses the title, or "Content warning". Visibility is expressed in `to`/`cc` the way Mastodon does it: public, unlisted, followers-only and direct. Inbound followers-only posts are recognised by the author's own `followers` collection. ## Security rules a peer will notice - **Signatures.** Inbox POSTs must be signed over `(request-target)`, `host`, `digest` and `date` (or `(created)`). The date may be at most one hour old and fifteen minutes ahead. A bad signature gets 401, malformed input 400, an accepted activity 202, too many requests 429. Activities are processed after the 202. - **Origins.** An actor document is accepted only from the address it names as its `id`. A key only if its actor lists it with `owner` set to the actor and on the actor's origin. An activity's `id`, and any object it creates, updates or deletes, must be on its actor's origin. An embedded object from another origin is fetched from that origin. - **Fetching.** All fetches are signed by the instance actor. They go only to public addresses, follow at most three redirects and read at most 1 MB. - **HTML.** Received HTML is sanitised to Mastodon's allowlist. - **Delivery.** Failed deliveries are retried with Mastodon's backoff (16 attempts). A host that keeps failing is paused, starting at an hour and growing to a week. ## Known limitations - Polls and custom emoji are not implemented. - Remote media is fetched through this server's proxy when a local client displays it. - Collections expose counts, not members. - Only `rsa-sha256`-style keys are verified. RFC 9421 signatures are planned.