Skip to content

Conversation

geralt-debugs
Copy link

@geralt-debugs geralt-debugs commented Aug 18, 2025

A sample implementation can be found here: https://calendar.formstr.app/
Code: https://github.com/geralt-debugs/nostr-calendar
This nip is enhanced to be able to perform google calendar features
FYI : @patrickulrich @abh3po

@staab
Copy link
Member

staab commented Aug 18, 2025

This is very similar to what I did with #875. A better approach would be to use some generic mechanism (like ad-hoc MLS groups) to cover all similar use cases. But this is also fine.

52.md Outdated
Apart from the public event tags, there is one more tag:
* `note` Note for the RSVP

The corresponding gift wrap is of `kind:1055`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could 1055s and 1052s be the same kind?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes actually they can be
because the client would need to fetch all gift wraps anyways

@fiatjaf
Copy link
Member

fiatjaf commented Aug 19, 2025

You need a way to share these private events, which is probably some kind of group. We're lacking on that front, but just ad-hoc encrypting these calendar events solves nothing.

@geralt-debugs
Copy link
Author

geralt-debugs commented Aug 19, 2025

I dont understand the concern. Sharing of events is working exactly like nip 17 DMs. Sharing in a group is restrictive as whenever you need to add/remove participants, you will need to create/delete groups which is an overhead.

https://calendar.formstr.app is meant as a replacement for google calendar and its working as expected.

@geralt-debugs
Copy link
Author

@fiatjaf
Copy link
Member

fiatjaf commented Aug 19, 2025

I see. It makes sense.

#### Viewing Private Events
1. Fetch all gift wraps in which the user's public key is referenced
2, Unwrap the gift wrap and get the `encrypted_event_id`, `encrypted_event_kind` and the `viewkey` from the rumor tags.
3. Fetch the encrypted event, decrypt it using the viewKey and show it to the user.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fetch from where? Which relay has this event?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calendar event should be published to the nip 65 relays of the participants. The encrypted events can be fetched from the current user's nip 65 relays. Will clarify it in the nip

1. Generate a private key. We will call this a `viewKey`. This key will be used to encrypt the event and will be sent to the viewers
2. Encrypt all the tags of the event with the `viewKey` and put the encrypted string in the content field of the final event.
3. Only include in the `d` tag in the final event. We will call the the unique calendar event id as `encrypted_event_id`
4. Now gift wrap(nip 59) the `viewKey` and the `encrypted_event_id` in a rumor. The `.content` field of the rumor will be an empty string. The rumor will contain the following tags
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should write an example json for this

Apart from the public event tags, there is one more tag:
* `description` Description of the event

The corresponding gift wrap is of `kind:1052`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we creating new wrap kinds? Then don't call it "gift" wrap. There is only one gift wrap kind.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the term "gift wrap" to easily explain the process. Will update the term. However the wrapping process is the same as gift wrap


The corresponding gift wrap is of `kind:1052`
The rumor for RSVP should contain the `a` tag for the encrypted RSVP event with value `<32069>:<viewer_pubkey>:<encrypted_rsvp_event_id>`
The rumor for RSVP should also contain another `a` tag which will have value `<32069 or 31923>:<calendar event author pubkey>:<d-identifier of calendar event>`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is all very difficult to understand what you mean. Can you provide examples?


Calendar events are _not_ required to be part of a [calendar](#calendar).

### Private events
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Private Events" is not a good name

1. `a` (required). Value should be `<encrypted_event_kind>:<viewer_pubkey>:<encrypted_event_id>`
2. `viewkey` (required). Value should be `viewKey`
5. The gift wrap itself should have a `p` tag with the viewer pubKey.
6. Separate gift wraps should be created for each viewer.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are encrypting the wrap to each user, why do you need the shared viewkey? You can just encrypt everything to each receiving user. There is no need to manage this separate key.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's because you need the ability to edit the previous event, something you lose if you just giftwrap the entire thing, or at-least you deal with a huge network overhead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will make editing the original event much easier. Once the wrap with the viewkey is sent, the participants will always have access to the event. Editing the original event/adding new participants will be very simple. It can be thought of as a 2 step process:

  1. Create an event
  2. Give access to the event

This way, the access management can also scale in the future. There can be different access levels like read/write etc(although this nip enhancement does not cover those scenarios).

@abh3po
Copy link
Contributor

abh3po commented Aug 19, 2025

The PR Title should be worded better, right now it feels like you're adding private events to the protocol, but the PR is only about NIP-52 calendar events.

@patrickulrich
Copy link

I've implemented private events in a much different way on nostrcal.

Instead of using a viewKey I'm just wrapping events like a normal gift wrap that includes the event. I'm also just using the same kinds for the private events as normal events but they are just wrapped.

@geralt-debugs
Copy link
Author

@patrickulrich Using viewKeys, we can scale it further.

It will make editing the original event much easier. Once the wrap with the viewkey is sent, the participants will always have access to the event. Editing the original event/adding new participants will be very simple. It can be thought of as a 2 step process:

  1. Create an event
  2. Give access to the event

This way, the access management can also scale in the future. There can be different access levels like read/write etc(although this nip enhancement does not cover those scenarios).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants