mirror of
https://github.com/versia-pub/docs.git
synced 2025-12-06 06:18:19 +01:00
feat: ✨ Move Delegation to an extension
Also adds a <Warning> MDX component.
This commit is contained in:
parent
3117b376c9
commit
72039874ab
|
|
@ -8,6 +8,10 @@ export const metadata = {
|
||||||
|
|
||||||
This page lists changes since Working Draft 3. {{ className: 'lead' }}
|
This page lists changes since Working Draft 3. {{ className: 'lead' }}
|
||||||
|
|
||||||
|
## Since WD 5
|
||||||
|
|
||||||
|
- Moved [Delegation](/extensions/delegation) to an extension
|
||||||
|
|
||||||
## Since WD 4
|
## Since WD 4
|
||||||
|
|
||||||
- Removed URI from [Report](/extensions/reports), and replaced `reason` with `tags`.
|
- Removed URI from [Report](/extensions/reports), and replaced `reason` with `tags`.
|
||||||
|
|
|
||||||
78
app/extensions/delegation/page.mdx
Normal file
78
app/extensions/delegation/page.mdx
Normal file
|
|
@ -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>
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
export const metadata = {
|
|
||||||
title: 'Delegation',
|
|
||||||
description: 'Delegation is used to authorize actions on behalf of another user',
|
|
||||||
}
|
|
||||||
|
|
||||||
# Delegation
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
## The `actor` Field on Public Keys
|
|
||||||
|
|
||||||
[Users](/entities/user)'s `public_key` property contains a field called `actor`. This field contains the URI to the **delegator** user, which is used to authorize actions on behalf of the **delegate** user.
|
|
||||||
|
|
||||||
This means that the **delegator** user can sign requests with their private key, and any implementations should consider the **delegate** user as equivalent to the **delegator** user.
|
|
||||||
|
|
||||||
## 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.
|
|
||||||
|
|
@ -267,7 +267,6 @@ export const navigation: NavGroup[] = [
|
||||||
{ title: "HTTP", href: "/federation/http" },
|
{ title: "HTTP", href: "/federation/http" },
|
||||||
{ title: "Validation", href: "/federation/validation" },
|
{ title: "Validation", href: "/federation/validation" },
|
||||||
{ title: "Discovery", href: "/federation/discovery" },
|
{ title: "Discovery", href: "/federation/discovery" },
|
||||||
{ title: "Delegation", href: "/federation/delegation" },
|
|
||||||
{ title: "Example", href: "/federation/example" },
|
{ title: "Example", href: "/federation/example" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -295,6 +294,7 @@ export const navigation: NavGroup[] = [
|
||||||
title: "Extensions",
|
title: "Extensions",
|
||||||
links: [
|
links: [
|
||||||
{ title: "Custom Emojis", href: "/extensions/custom-emojis" },
|
{ title: "Custom Emojis", href: "/extensions/custom-emojis" },
|
||||||
|
{ title: "Delegation", href: "/extensions/delegation" },
|
||||||
{ title: "Groups", href: "/extensions/groups" },
|
{ title: "Groups", href: "/extensions/groups" },
|
||||||
{
|
{
|
||||||
title: "Instance Messaging",
|
title: "Instance Messaging",
|
||||||
|
|
|
||||||
|
|
@ -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 }) {
|
export function Note({ children }: { children: ReactNode }) {
|
||||||
return (
|
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)]">
|
<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)]">
|
||||||
|
|
@ -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 }) {
|
export function Row({ children }: { children: ReactNode }) {
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
|
<div className="grid grid-cols-1 items-start gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue