mirror of
https://github.com/nostr-protocol/nips.git
synced 2024-12-23 00:45:53 -05:00
165 lines
7.4 KiB
Markdown
165 lines
7.4 KiB
Markdown
NIP-260
|
|
=======
|
|
|
|
Shared Account
|
|
--------------
|
|
|
|
`draft` `optional`
|
|
|
|
This NIP introduces a standard way to share account signing privileges
|
|
from a `delegator` to `delegatees` without revealing its privkey.
|
|
It uses time-released delegation events to be able to cancel sharing at any time.
|
|
|
|
Note that although `delegators` and `delegatees` terms are used,
|
|
the delegation setup is different from the NIP-26 one.
|
|
|
|
## "Share Account Access" Feature
|
|
|
|
The `delegator` user should be able to inform the `delegatee(s)`'s `pubkey` to the client through a "Share Account Access" feature.
|
|
|
|
The `delegator`s client then pre-generates a set of [Delegation Events](#delegated-events) that configure the account
|
|
sharing, to be released on `delegator`s [scheduler relays](#scheduler-relays) at each event's `.created_at` moments.
|
|
|
|
Each of these events has a time window, during which it is considered the current delegation configuration.
|
|
A time window starts at the `.created_at` timestamp, ends at the `expiration` tag value moment
|
|
and should be narrow (~3 hours). The complete set of time windows are expected to be continuous.
|
|
|
|
The `delegator` at any time should be able to ask the client to disable the "Share Account Access" feature.
|
|
Then their client should ask the Scheduler Relay to delete "Delegation Events" yet to be released, effectively
|
|
canceling the account sharing when no current (not expired) "Delegation Event" can be found.
|
|
|
|
## "Use Shared Account" Feature
|
|
|
|
The `delegatee` user should be able to inform the `delegator`'s `pubkey` to the client through a "Use Shared Account" feature.
|
|
|
|
Before publishing an event, the `delegatee`'s client should fetch the latest "Delegation Event" of the `delegator`
|
|
from one of the `delegator` scheduler relays to make sure they are still listed as a `delegatee`, to know when the
|
|
delegation expires, and which event kinds the `delegatee` can publish on behalf of the `delegator`.
|
|
|
|
After expiration, the `delegatee`'s client is expected to repeat the procedure of fetching and checking the latest available
|
|
`delegator`'s "Delegation Event".
|
|
|
|
Disabling the "Use Shared Account" feature means the `delegatee`'s client will stop fetching and checking `delegator`s
|
|
"Delegation Events" when publishing new events.
|
|
|
|
## Delegation Event
|
|
|
|
A "Delegation Event" is current (not-expired) between its `.created_at` and `expiration` tag time range.
|
|
|
|
If no current event is found for a specific `delegatee`, **all** past and future delegated events from the `delegatee`
|
|
are considered invalid.
|
|
|
|
The event is of `kind:1026`, the `.pubkey` is the `delegator` and a single `p` tag is set to the `delegatee`'s pubkey.
|
|
|
|
It must have atleast one `k` tag and each should be set to the kinds the `delegatee` is allowed to publish
|
|
on behalf of the `delegator`.
|
|
|
|
There is a `since` tag informing since when the p-tagged user became a `delegatee`.
|
|
A `delegatee` is allowed to publish events with a `.created_at` between the `since`
|
|
and `expiration` tag values.
|
|
|
|
A `scheduled` tag is present to hint to relays that the event should only be requestable by users
|
|
other than the author if the `.created_at` timestamp has been reached.
|
|
|
|
Event example:
|
|
|
|
```js
|
|
{
|
|
"kind": 1026,
|
|
"pubkey": "<delegator_pubkey>",
|
|
"tags": [
|
|
["p", "<delegatee_pubkey>"],
|
|
["k", "1"],
|
|
["k", "14"],
|
|
["since", "1702000000"], // may be inherited from the first `kind:1026` of a series
|
|
["expiration", "1702721800"],
|
|
["scheduled"]
|
|
],
|
|
"content": "",
|
|
"created_at": 1702711000 // time the event will be published to the relay
|
|
// ...other fields
|
|
}
|
|
```
|
|
|
|
## Delegated Events
|
|
|
|
Delegated events considered by this NIP are those with a `D` tag that is set to the `delegator` pubkey.
|
|
|
|
When a delegated event is replaceable, an extra `address_sig` tag must be added.
|
|
It is set to the signature of a `kind:1126` "Proof Event" that has no tags, `created_at` set to `0` and
|
|
the following string as `.content`: `"<event-kind>:<DELEGATOR-pubkey>:<event-d-tag>"`
|
|
(the string is similar to that of the event `address`, but with the `delegator` pubkey instead of the `delegatee`'s one).
|
|
|
|
### Relay Hint when Referencing
|
|
|
|
When publishing a delegated event, most times (see [Use Cases](#use-cases) section and specific NIPs)
|
|
the `delegator` relays are expected to be used instead of the `delegatee`s or the group chat's ones, for example.
|
|
|
|
When that's the case and an event referencing it has added
|
|
a `pubkey` hint for locating the referenced event with [NIP-65](65.md), it should be the `delegator` pubkey.
|
|
|
|
If it has added a direct `relay` url hint, it should be from one of the `delegator` relays.
|
|
|
|
### Validation
|
|
|
|
If no current (not expired) `kind:1026` event can be found,
|
|
**all** `delegatee`'s previous and future delegated events
|
|
should be considered invalid by clients.
|
|
|
|
The client should check if it can find a current `kind:1026` event from `delegator`
|
|
that p-tags the `delegatee`, has a `k` tag value with the same delegated event's `.kind` and
|
|
whose `since` to `expiration` tag time range includes the delegated event's `.created_at` timestamp.
|
|
|
|
### Copying Delegated Events
|
|
|
|
Before disabling the "Share Account Access" feature, i.e. before making all previous and future
|
|
delegated events of a specific `delegatee` invalid, the `delegator` may copy these events.
|
|
|
|
The event copy has the same field values, except for the `.pubkey` that is the `delegator`,
|
|
the `.sig` that changes accordingly and the `D` tag that is renamed to `D_copy`.
|
|
|
|
Also, a single `C` (canonical event identifier) tag is added.
|
|
If the event being copied is a regular event, it is set to its `.id`,
|
|
else if a replaceable one, it is set to its `address`.
|
|
The `C` tag's second value is the `delegatee` pubkey.
|
|
|
|
Clients must use the `C` tag value to load the copied event's replies/references. New references should
|
|
be made to the `C` tag value.
|
|
|
|
Clients should validate the `C` tag value before considering it the canonical event identifier.
|
|
|
|
### "C" Tag Validation
|
|
|
|
If the `C` tag is set to the copied event's `.id`, rebuild the copied event's structure
|
|
(remove the copy's `C` tag, replace the `.pubkey` to the `delegatee`'s one and rename `D_copy` tag to `D`)
|
|
and check if the hash matches. `D_copy` also must have been set to the `delegator` pubkey.
|
|
|
|
If the `C` tag is set to the copied event's `.address`,
|
|
generate and verify the `kind:1126` "Proof Event" with `"<event-kind>:<DELEGATOR-pubkey>:<event-d-tag>"`
|
|
`.content` by using the `address_sig` tag value.
|
|
|
|
## Scheduler Relays
|
|
|
|
A scheduler relay is expected to allow the publishing of events with future `.created_at` value
|
|
while also never sending such events with future timestamp and a `scheduled` tag
|
|
to users other than the author.
|
|
|
|
A client should use the `s` relay usage flag to set the user's [NIP-65](65.md)
|
|
scheduler relays.
|
|
|
|
If a relay signals support for this NIP in their [NIP-11](11.md) document, that means
|
|
it can be used as a scheduler relay when a `scheduled` tag is present on an event.
|
|
|
|
## Use Cases
|
|
|
|
- Enable employees to publish `kind:1` events on behalf of a business account.
|
|
`Delegatees` should publish to the `delegator` relays.
|
|
Reading client's interface should display the `delegator` as the delegated `kind:1` events' author
|
|
(e.g.: show just the `delegator`'s avatar picture);
|
|
|
|
- Enable employees to publish `DM`s on behalf of a business account.
|
|
`Delegatees` should publish to their own relays.
|
|
Reading client's interface should display the `delegatee` (**not the delegator**)
|
|
as the author of the delegated `DM` events and indicate they are speaking
|
|
on the company/`delegator`'s behalf (e.g.: show both accounts' avatar pictures).
|