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": "", "tags": [ ["p", ""], ["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`: `"::"` (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 `"::"` `.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).