Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/changelog/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ This page lists changes since Working Draft 3. {{ className: 'lead' }}

- Added a new `content-type` for Versia entities: `application/vnd.versia+json`.
- Removed per-User keypairs: now, only the instance keypair is used for signing.
- Moved [Delegation](/extensions/delegation) to an extension
- Modified how URIs and references to other entities are handled:
- The `uri` field has been removed from all entities.
- Every field that used to be a URI now uses that entity's `id` field.
Expand Down
78 changes: 78 additions & 0 deletions app/extensions/delegation/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
export const metadata = {
title: 'Delegation Extension',
description: 'Lets users perform actions on other accounts\' behalf.'
}

# Delegation Extension

Delegation is used to authorize actions on behalf of another user. {{ className: 'lead '}}

## Vocabulary

- **Delegator**: The user that is delegating actions to another user. (The user that owns the key)
- **Delegate**: The user that is being delegated actions. (The user that the key is pointing to)

## Implementation Details

Any actions or entities created by the **delegate** should be attributed to the **delegator** user in clients transparently to end-users (e.g. showing the **delegator** user's name and avatar). This allows for a form of "consensual impersonation" that is authorized by the **delegators** and **delegates**.

This is useful as a way to centralize all of a user's many "alt accounts" into a single, unified feed.

<Warning>
If an instance encounters an action from a User that has a Delegator listed, but that Delegator does not allow the User to perform actions on their behalf, the actions **MUST** be shown as the User's own.

Also, if a User has a Delegator listed, but that Delegator does not allow the User to perform actions on their behalf, instances **SHOULD** mark the User with a warning about possible impersonation or fraud.
</Warning>

## Extension Definition

<Row>
<Col>
<Properties name="Delegation">
The Delegation extension uses an ID of `pub.versia:delegation`.

If the extension is present, exactly **one** of the fields **MUST** be specified:

<Property name="delegator" type="Reference">
If this user performs actions on behalf on another user, **MUST** have a reference to that user.
</Property>
<Property name="allowed_delegates" type="Reference[]">
If other users perform actions on behalf of this user, **MUST** have a list of references to all such users.
</Property>
</Properties>
</Col>

<Col sticky>

```jsonc {{ title: "Example Delegator" }}
{
// ...
"type": "User",
"id": "73cb1728-75d7-4080-8d28-4adf49bb0a0d",
// ...
"extensions": { // [!code focus:5]
"pub.versia:delegation": {
"delegator": "versia.example.com:bfb6bb39-bb08-4226-91ac-8adebc3da046"
}
}
}
```

```jsonc {{ title: "Example Delegates List" }}
{
// ...
"type": "User",
"id": "bfb6bb39-bb08-4226-91ac-8adebc3da046",
// ...
"extensions": { // [!code focus:7]
"pub.versia:delegation": {
"allowed_delegates": [
"versia.social:73cb1728-75d7-4080-8d28-4adf49bb0a0d"
]
}
}
}
```

</Col>
</Row>
25 changes: 0 additions & 25 deletions app/federation/delegation/page.mdx

This file was deleted.

2 changes: 1 addition & 1 deletion components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,6 @@ export const navigation: NavGroup[] = [
{ title: "HTTP", href: "/federation/http" },
{ title: "Validation", href: "/federation/validation" },
{ title: "Discovery", href: "/federation/discovery" },
{ title: "Delegation", href: "/federation/delegation" },
{ title: "Example", href: "/federation/example" },
],
},
Expand Down Expand Up @@ -295,6 +294,7 @@ export const navigation: NavGroup[] = [
title: "Extensions",
links: [
{ title: "Custom Emojis", href: "/extensions/custom-emojis" },
{ title: "Delegation", href: "/extensions/delegation" },
{ title: "Groups", href: "/extensions/groups" },
{
title: "Instance Messaging",
Expand Down
42 changes: 42 additions & 0 deletions components/mdx.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,37 @@ function InfoIcon(props: ComponentPropsWithoutRef<"svg">) {
);
}

function WarningIcon(props: ComponentPropsWithoutRef<"svg">) {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...props}>
<path
fill="none"
stroke="currentColor"
strokeWidth={1.5}
strokeLinecap="round"
strokeLinejoin="round"
d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
d="M12 9v4"
/>
<path
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M12 17h.01"
/>
</svg>
);
}

export function Note({ children }: { children: ReactNode }) {
return (
<div className="my-6 flex gap-2.5 rounded-md border border-brand-500/20 bg-brand-50/50 p-4 leading-6 text-brand-900 dark:border-brand-500/30 dark:bg-brand-500/5 dark:text-brand-200 dark:[--tw-prose-links-hover:theme(colors.brand.300)] dark:[--tw-prose-links:theme(colors.white)]">
Expand All @@ -55,6 +86,17 @@ export function Note({ children }: { children: ReactNode }) {
);
}

export function Warning({ children }: { children: ReactNode }) {
return (
<div className="my-6 flex gap-2.5 rounded-md border border-yellow-500/20 bg-yellow-50/50 p-4 leading-6 text-yellow-900 dark:border-yellow-500/30 dark:bg-yellow-500/5 dark:text-yellow-200 dark:[--tw-prose-links-hover:theme(colors.yellow.300)] dark:[--tw-prose-links:theme(colors.white)]">
<WarningIcon className="mt-1 h-4 w-4 flex-none fill-yellow-500 stroke-white dark:fill-yellow-200/20 dark:stroke-yellow-200" />
<div className="[&>:first-child]:mt-0 [&>:last-child]:mb-0">
{children}
</div>
</div>
);
}

export function Row({ children }: { children: ReactNode }) {
return (
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
Expand Down