From 1d375491d14c374ab473ce3120e448ce2f8e450e Mon Sep 17 00:00:00 2001 From: Jesse Wierzbinski Date: Fri, 18 Oct 2024 16:36:04 +0200 Subject: [PATCH] feat: :sparkles: Add Interaction Controls Extension --- app/changelog/page.mdx | 1 + app/extensions/interaction-controls/page.mdx | 108 +++++++++++++++++++ app/extensions/likes/page.mdx | 13 ++- components/Navigation.tsx | 4 + 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 app/extensions/interaction-controls/page.mdx diff --git a/app/changelog/page.mdx b/app/changelog/page.mdx index 3e65512..dde3e1e 100644 --- a/app/changelog/page.mdx +++ b/app/changelog/page.mdx @@ -21,6 +21,7 @@ This page lists changes since Working Draft 3. {{ className: 'lead' }} - Switched from ISO 8601 to [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) for timestamps. - In most cases, the two are interchangeable, but RFC 3339 is more strict. Most implementations should not need to change anything. - Add optional `$schema` field to [Entities](/entities). +- Added [Interaction Controls Extensions](/extensions/interaction-controls) ## Since WD 3 diff --git a/app/extensions/interaction-controls/page.mdx b/app/extensions/interaction-controls/page.mdx new file mode 100644 index 0000000..baf6cc9 --- /dev/null +++ b/app/extensions/interaction-controls/page.mdx @@ -0,0 +1,108 @@ +export const metadata = { + title: "Interaction Controls Extension", + description: "Allows users to control who can interact with their Notes" +} + +# Interaction Controls + +Often, it is desirable to post a Note, but control who is allowed to interact with it (e.g. send replies, like, dislike, etc.). This has traditionally not been possible in most federated networks: the Interaction Controls extension adds this possibility. + +## Usage + +The entity defined in this document must be inserted in the `pub.versia:interaction_controls` key of a [Note](/entities/note)'s extensions field. + +```jsonc {{ title: "Example Usage" }} +{ + "id": "456df8ed-daf1-4062-abab-491071c7b8dd", + "type": "Note", + "uri": "https://versia.social/notes/456df8ed-daf1-4062-abab-491071c7b8dd", + "created_at": "2024-04-09T01:38:51.743Z", + "content": { + "text/plain": { + "content": "Hello, world :happy_face:!" + } + }, + "extensions": { // [!code focus:9] + "pub.versia:interaction_controls": { + "reply": { + "allowed": ["followers"], + }, + } + } +} +``` + +## Entity Definition + + + + + + Describes permissions for a specific interaction. + + ```typescript + type InteractionGroup = | + "everyone" | + "followers" | + "followed" | + "group" | + "mutuals"; + + type InteractionPermissions = { + allowed?: InteractionGroup[]; + disallowed?: InteractionGroup[]; + } + ``` + + Permissions can either be whitelist (`allowed` property) or blacklist (`disallowed` property). Both options are mutually exclusive. + + In order of priority: + - `everyone`: Includes every single User in the federation. + - `followers`: Includes every follower of the author. + - `following`: Includes every User that the author follows. + - `mutuals`: Includes every mutual of the author (that is, every User that is both a follower and followed by the author). + - `group`: Includes every User in the [Group](/entities/group) that this Note was posted to, if any. If Note is not posted to a [Group](/entities/group), this value has no effect. + + Permission groups are evaluated from highest to lowest priority: if two groups conflict each other, the group with the highest priority must be used. + + + + + + ```jsonc {{ title: "Example"}} + { + "reply": { + "allowed": [ + "group" + ], + }, + "pub.versia:likes#Like": { + "disallowed": [ + "everyone" + ] + } + } + ``` + + + +## Usage + +### Interaction Types + +The following interaction types are defined as part of the core Versia spec: + +- `reply`: Sending a Note with `replies_to` including this Note. +- `quote`: Sending a Note with `quotes` including this Note. + +Extensions **may** choose to register their own interaction types (such as `pub.versia:likes#Like` for the [Like Extension](/extensions/likes)). The naming scheme for interaction types is identical to [Extensions](/extensions)'s `type` property, but with a hashtag (`#`) in place of a forward slash (`/`). + +### Handling Permission Errors + +Implementations that find a user attempting to create an interaction they are not allowed to **MUST** return a `403 Forbidden` HTTP status code when processing the Note during federation. The Note **must** also be discarded. + +It is important for implementations to backfill any related [Collections](/structures/collection) (e.g. user followers) in order to not incorrectly reject Notes based off of outdated data. + + + To avoid server load from constant Collection refreshing, implementations **could** only refetch associated Collections when forbidden interactions are detected, then recalculate permissions again. + \ No newline at end of file diff --git a/app/extensions/likes/page.mdx b/app/extensions/likes/page.mdx index ee49ea4..6682831 100644 --- a/app/extensions/likes/page.mdx +++ b/app/extensions/likes/page.mdx @@ -104,4 +104,15 @@ The Likes extension adds the following collections to the [User](/entities/user) "pub.versia:likes/Likes": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe/likes", "pub.versia:likes/Dislikes": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe/dislikes" } -} \ No newline at end of file +} +``` + +## Interaction Types + + + This section only applies to implementors of the [Interaction Controls Extension](/extensions/interaction-controls). + + +This extension registers the following interaction types: +- `pub.versia:likes#Like`, for liking a Note +- `pub.versia:likes#Dislike`, for disliking a Note \ No newline at end of file diff --git a/components/Navigation.tsx b/components/Navigation.tsx index 062725f..9c00fd9 100644 --- a/components/Navigation.tsx +++ b/components/Navigation.tsx @@ -295,6 +295,10 @@ export const navigation: NavGroup[] = [ title: "Instance Messaging", href: "/extensions/instance-messaging", }, + { + title: "Interaction Controls", + href: "/extensions/interaction-controls", + }, { title: "Likes", href: "/extensions/likes" }, { title: "Migration", href: "/extensions/migration" }, { title: "Polls", href: "/extensions/polls" },