nips/260.md
2024-03-12 15:39:05 -03:00

7.4 KiB

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 delegators client then pre-generates a set of Delegation Events that configure the account sharing, to be released on delegators 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 delegators "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:

{
  "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 section and specific NIPs) the delegator relays are expected to be used instead of the delegatees 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, 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 scheduler relays.

If a relay signals support for this NIP in their NIP-11 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 DMs 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).