Use "key" tag instead of p-tag, add examples

This commit is contained in:
abhay-raizada 2024-05-25 18:10:58 +05:30
parent ddee4e8167
commit 08b44aea29

121
101.md
View File

@ -2,12 +2,12 @@
`draft` `optional` `author:abhay-raizada` `draft` `optional` `author:abhay-raizada`
The nip provides a way for users to create form templates on nostr, and for other users to be able to fill them. The nip provides a way for users to create form templates on nostr, and for other users to be able to fill them.
## Form Template - Public ## Form Template - Public
Event `30168` describes a form with `field` tags that contain the description of each form field, with optional settings Event `30168` describes a form as a parametrized replaceable event, with `field` tags that contain the description of each form field, with optional settings
```js ```js
{ {
"kind": 30168, "kind": 30168,
@ -17,7 +17,7 @@ Event `30168` describes a form with `field` tags that contain the description of
["name", "Name of the form"], ["name", "Name of the form"],
["settings", JSON.stringify({description: "<description of the form."})], ["settings", JSON.stringify({description: "<description of the form."})],
["field", "<fieldId>","<input-type>","<label for the field>","<Options (for option type)>", "<stringified JSON settings>"], ["field", "<fieldId>","<input-type>","<label for the field>","<Options (for option type)>", "<stringified JSON settings>"],
["field", "<fieldId>", "option", "label for options field", ["field", "<fieldId>", "option", "label for options field",
JSON.stringify([["<optionId1>", "option label", "<optionId2>", "option label"]]), JSON.stringify([["<optionId1>", "option label", "<optionId2>", "option label"]]),
"<stringified JSON settings>" "<stringified JSON settings>"
] ]
@ -26,78 +26,121 @@ Event `30168` describes a form with `field` tags that contain the description of
} }
``` ```
The different tags used to describe the form are described as: The different tags used to detail the form are described as:
|Tags|Description| | Tags | Description |
|----|-------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|d|The unique identifier of a form, for a user| | d | The unique identifier of a form, for a user |
|name| A text serving as the name of the form| | name | A text serving as the name of the form |
|settings| An optional global config for the form. | settings | An optional global config for the form. |
|field| Contains the following values<table><tr><th>index</th><th>name</th><th>description</th></tr><tbody><tr><td>1</td><td>FieldId</td><td>an id that uniqely identifies a field in the forn</td></tr><tr><td>2</td><td>input-type</td><td>A field that describes the type of value that can be expected as a response to this field, values can be: `text`, `option` or `label`</td></tr><tr><td>3</td><td>label</td><td>A label for the field</td></tr><tr><td>4</td><td>options</td> <td>Only used for input-type option, is a Json stringified array of strings containing [`<OptionId`>, <`label`>, `<optional config>`] </td> </tr><tr><td>5</td><td>fieldSettings</td><td>An optional JSON stringified object that contains settings specific to the field, for example `renderElement`, a setting which indicates what UI element to render to the client </td></tr> | field | Contains the following values<table><tr><th>index</th><th>name</th><th>description</th></tr><tbody><tr><td>1</td><td>FieldId</td><td>an id that uniqely identifies a field in the forn</td></tr><tr><td>2</td><td>input-type</td><td>A field that describes the type of value that can be expected as a response to this field, values can be: `text`, `option` or `label`</td></tr><tr><td>3</td><td>label</td><td>A label for the field</td></tr><tr><td>4</td><td>options</td> <td>Only used for input-type option, is a Json stringified array of strings containing [`<OptionId`>, <`label`>, `<optional config>`], optionId can be any any alphanumeric string </td> </tr><tr><td>5</td><td>fieldSettings</td><td>An optional JSON stringified object that contains settings specific to the field, for example `renderElement`, a setting which indicates what UI element to render to the client </td></tr> |
</tbody></table>
</tbody></table>
## Responses - Public ## Responses - Public
Response events are attached to a form(3068 kind event), and the event data is stored in a `kind: 30169` event Response events are also parametrized replaceable events that are attached to a form(3068 kind event), and the event data is stored in a `kind: 30169` event
Response structure: Response structure:
```js ```json
{ {
"kind": 30169, "kind": 30169,
"content" : "", "content": "",
"tags": [["a", "30168:<pubkey of the author>:<form identifier>"], "tags": [
["response", "<FieldId>", "<response as string>", "<stringified metadata object>"]], ["d", "<pubkey of the form author>:<form identifier>"],
"pubkey": "Author of Response" ["a", "30168:<pubkey of the author>:<form identifier>"],
[
"response",
"<FieldId>",
"<response as string>",
"<stringified metadata object>"
]
],
"pubkey": "Author of Response"
} }
``` ```
The Response tag contains a "response" tag identifier "fieldId" the Id of the field as mentioned in the `kind:30168` event, response for the field as a string value, and a stringified metadata object.
for option fields, the response is the id of the option selected. In case of multiple-choice fields these id's maybe delimited by a semi-colon, ";", For example: for option fields, the response is the id of the option selected. In case of multiple-choice fields these id's maybe delimited by a semi-colon, ";", For example:
```js ```json
{ {
"kind": 30169, "kind": 30169,
"content" : "", "content": "",
"tags": [["a", "30168:<pubkey of the author>:<form identifier>"], "tags": [
["response", "<FieldId>", "ZCZC;XCZXCZ;Z34Z", "<stringified metadata object>"]], ["a", "30168:<pubkey of the author>:<form identifier>"],
"pubkey": "Response author" [
"response",
"<FieldId>",
"ZCZC;XCZXCZ;Z34Z",
"<stringified metadata object>"
]
],
"pubkey": "Response author"
} }
``` ```
## Access Control ## Access Control
In general access is granted by signing the event and encrypting the content with different keys. In general access is granted by signing the event and encrypting the content with different keys.
the mechanism to share the keys is by encrypting the keys and adding it to the p-tag of the event. the mechanism to share the keys is by encrypting the keys and adding it as key-tags in the event, as well as adding p-tags to notify users.
The p-tag for `kind:30168` events, should look like. The key tag for `kind:30168` events, should look like.
`["p","<pubkey for the user>", "<optional relays>", "<Encrypted-View-Key>", "<Encrypted-Signing-key>"]` `["key","<pubkey for the user>", "<optional relays>", "<Encrypted-View-Key>", "<Encrypted-Signing-key>"]`
`View-key` : generated during form-creation, this key should used to encrypt/decrypt the `".content"` string in the form template. `View-key` : generated during form-creation, this key should used to encrypt/decrypt the `".content"` string in the form template.
`Edit-key/Signing-Key`: Is the key which is used to sign the 30168 event. `Edit-key/Signing-Key`: Is the key which is used to sign the 30168 event.
Encryption should be via [nip-44](./44.md) using the conversation key derived from the p-tags pubkey and the signing-key. Encryption should be via [nip-44](./44.md) using the conversation key derived from the p-tags pubkey and the signing-key.
`Encrypted View Key`: The view key should be encrypted as `nip44.encrypt(<View Key>, <Coversation Key derived from users public key and the signing key>)`
`Encrypted Signing Key`: The view key should be encrypted as `nip44.encrypt(<Signing Key>, <Coversation Key derived from users public key and the signing key>)`
In case a participant is a viewer and an editor, both the keys should be added in their "key" tag.
In case participant is only a viewer the editor key maybe left blank.
### Public Forms Public Responses ### Public Forms Public Responses
Both the form and the responses are kept in that `tags` array and signed by the respective users. Useful for cases like polls. Both the form and the responses are kept unencrypted in the `tags` array and signed by the respective users. Useful for cases like polls.
### Encrypted Responses. ### Encrypted Responses.
Response tags are added to the `.content` field of the event and encrypted as per the spec in [nip-44](./44.md) by the responders private key and the form authors public key. Response tags are added to the `.content` field of the event and encrypted as per the spec in [nip-44](./44.md) by the responders private key and the form authors public key.
### Private Forms only viewable by a group. ### Private Forms only viewable by a group.
Form fields should be placed in the `.content` key, nip-44 encrypted by the view-key, and the form-authors public-key. The selected responders can decrypt the form using the view key. The `tags` array is used to keep track of the allowed-responders identities.
Form fields should be placed in the `.content` key, nip-44 encrypted by the corresponding public key of the view-key, and the signing key. The selected responders can decrypt the form using the view key. The `tags` array is used to keep track of the allowed-responders identities.
```js
let encryptionKey = nip44.v2.utils.getConversationKey(
bytesToHex(signingKey),
getPublicKey(viewKey)
);
content = nip44.v2.encrypt(JSON.stringify(form), encryptionKey);
```
### Public forms editable by a group. ### Public forms editable by a group.
A signing key is generate for the group.
Form fields are in the tag array, and the signing-key is encrypted in the p-tag like: A signing key is generated for the group.
`["p", "<pub-key with edit access>", "<relays>","","<encrypted signing key>"]`. Form fields are in the tag array, and the signing-key is encrypted in the key tag like:
The key should be the same that the `30168` event is signed with. `["key", "<pub-key with edit access>", "<relays>","","<encrypted signing key>"]`.
The key should be the same that the `30168` event is signed with.
The pubkeys with edit access, will also be able to view the form responses. The pubkeys with edit access, will also be able to view the form responses.
Encrypted signing key can be calculated as:
```js
let conversationKey = nip44.v2.utils.getConversationKey(
bytesToHex(signingKey),
npubHex
);
let encyptedKey = nip44.v2.encrypt(bytesToHex(signingKey), conversationKey);
```
### Private forms editable by a group. ### Private forms editable by a group.
Form fields should be placed in the `.content` key, encrypted by a `view-key`, which is shared in the 3rd index of the p-tag for the viewers.
The signing key is encrypted and placed in the 4th index of the p-tag for the editors.
The rest of the mechanism remains same as in public forms editable by a group except that the
form fields should be placed in the `.content` key, encrypted by a `view-key`, which is shared in the 3rd index of the key tag for the viewers.