From fd3676c2512d0e3813562a9a0a80b85bf1470fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=E2=80=99Aquino?= Date: Fri, 7 Feb 2025 03:33:39 +0000 Subject: [PATCH 1/2] Task and workflow-related NIPs This commit introduces a few NIPs related to business use cases around tasks and workflows --- README.md | 10 ++++++ XXA.md | 90 +++++++++++++++++++++++++++++++++++++++++++++++ XXB.md | 57 ++++++++++++++++++++++++++++++ XXC.md | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ XXD.md | 76 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 335 insertions(+) create mode 100644 XXA.md create mode 100644 XXB.md create mode 100644 XXC.md create mode 100644 XXD.md diff --git a/README.md b/README.md index dd3c0f74..0da3ba26 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,10 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos - [NIP-99: Classified Listings](99.md) - [NIP-7D: Threads](7D.md) - [NIP-C7: Chats](C7.md) +- [NIP-XXA: Tasks](XXA.md) +- [NIP-XXB: Simple To-do Flow](XXB.md) +- [NIP-XXC: Kanban Board Flow](XXC.md) +- [NIP-XXD: Event Edit Requests](XXD.md) ## Event Kinds @@ -140,6 +144,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `1068` | Poll | [88](88.md) | | `1111` | Comment | [22](22.md) | | `1311` | Live Chat Message | [53](53.md) | +| `1500` | Simple To-do Update Event | [XXB](XXB.md) | +| `1501` | Event Edit Request | [XXD](XXD.md) | +| `1502` | Event Edit Response | [XXD](XXD.md) | | `1617` | Patches | [34](34.md) | | `1621` | Issues | [34](34.md) | | `1622` | Replies | [34](34.md) | @@ -233,6 +240,8 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `31990` | Handler information | [89](89.md) | | | `32267` | Software Application | | | | `34550` | Community Definition | [72](72.md) | +| `35000` | Task Event | [XXA](XXA.md) | +| `35001` | Kanban Board Event | [XXC](XXC.md) | | `38383` | Peer-to-peer Order events | [69](69.md) | | `39000-9` | Group metadata events | [29](29.md) | @@ -310,6 +319,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `clone` | git clone URL | -- | [34](34.md) | | `content-warning` | reason | -- | [36](36.md) | | `delegation` | pubkey, conditions, delegation token | -- | [26](26.md) | +| `due_at` | unix timestamp (string) | -- | [XXA](XXA.md) | | `description` | description | -- | [34](34.md), [57](57.md), [58](58.md) | | `emoji` | shortcode, image URL | -- | [30](30.md) | | `encrypted` | -- | -- | [90](90.md) | diff --git a/XXA.md b/XXA.md new file mode 100644 index 00000000..eb7ff006 --- /dev/null +++ b/XXA.md @@ -0,0 +1,90 @@ +NIP-XXA +======= + +Tasks +----- + +`draft` `optional` + +This NIP defines `kind:35000` (an _addressable event_) for tasks, generally referred to as "tasks", "to-do items", or "reminders". + +This NIP intentionally does not define any information about workflows, states, authorization mechanisms, or any other complex task management features, as the needs and requirements for these vary greatly between different applications and use cases. This NIP is meant to be used only as a base for more complex task management systems, and only focuses on the basic information that models a task itself. + +Workflows, states, and other task management features can be implemented on top of this NIP, and can be shared between different applications and services using the same base task model. + +## Format and Structure of Task Events + +### Event Kind + +The `kind` of these events MUST be `35000`, which is an _addressable event_ as defined in [NIP-01](01.md). + +### Content + +The `.content` of these events MUST be used as the description of a task, and should be a string text in [Github Flavored Markdown syntax](https://github.github.com/gfm), with the following constraints: +- MUST NOT hard line-break paragraphs of text, such as arbitrary line breaks at 80 column boundaries. +- MUST NOT support adding HTML to Markdown. +- MUST NOT support adding JavaScript to Markdown. + +Clients MAY render any inline [Nostr URI](21.md) into a rich interactive object or widget, to allow for easy navigation and interaction with the referenced content, or as simple hyperlinks. + +### Metadata and Tags + +- `"d"`, for a unique identifier for the task + +Other metadata fields can be added as tags to the event as necessary. Here we standardize a few that may be useful, although they remain strictly optional: +- `"title"`, for the task title +- `"image"`, for a URL pointing to an image to be shown along with the title +- `"published_at"`, for the timestamp in unix seconds (stringified) of the first time the task was created +- `"due_at"`, for the timestamp in unix seconds (stringified) of the due date of the task +- `"archived"`, for a boolean value indicating whether the task is archived or not. If the task is archived, it SHOULD be generally hidden from the user interface, unless the user specifically requests to see archived tasks. +- `"t"`, for generic tags that can be used to categorize the task, which can be any string (e.g. `"work"`, `"personal"`, `"urgent"`, etc.) +- `"p"`, for referencing other users and their roles in the task (See below) + +Other tags can be added as necessary, but they should be standardized and documented in a separate NIP. Clients SHOULD ignore any tags they do not understand. + +#### Referencing Users + +The `p` tag is used to reference other users and their roles in the task. The tag should be an array with the following structure: + +```jsonc +["p", "<32-bytes hex of a pubkey>", ""] +``` + +The role is optional, and this NIP only standardizes the following values: +- (Empty): The user is mentioned or CC'd in the task, but has no specific role. +- `"assignee"`: The user is assigned to the task. +- `"client"`: The user is the client or requester of the task. +- (Any other value): Any other role that is not standardized by this NIP, which for the purposes of this NIP is treated the same as an empty role. + +### Editability + +These tasks are meant to be editable, so they should include a `d` tag with an identifier for the task. Clients should take care to only publish and read these events from relays that implement that. If they don't do that they should also take care to hide old versions of the same tasks they may receive. + +For simplicity and flexibility, this NIP does not define a specific mechanism to allow groups of users to edit the same task. This is deliberately left out to allow for different implementations to be built on top of this NIP in a way that best suits the needs of a particular use case. Examples of possible implementations include: +- A single user is assigned to a task, and only that user can edit the task. +- The task is signed using a collaborative signing mechanism, such as a multi-signature or FROST-like scheme. +- The task is signed by an authoritative keypair representing a group/company, and members of a group need to request changes to the task from that entity using [edit requests](XXD.md) or other mechanisms. + +### Linking + +The task may be linked to using the [NIP-19](19.md) `naddr` code along with the `a` tag. + +## Example Event + +```json +{ + "kind": 35000, + "created_at": 1675642635, + "content": "This task is a placeholder for the description of the task. It should be written in [Markdown](https://github.github.com/gfm). Here is another task: nostr:naddr1qqzkjurnw4ksz9thwden5te0wfjkccte9ehx7um5wghx7un8qgs2d90kkcq3nk2jry62dyf50k0h36rhpdtd594my40w9pkal876jxgrqsqqqa28pccpzu. Please talk to this user for more information: nostr:npub13v47pg9dxjq96an8jfev9znhm0k7ntwtlh9y335paj9kyjsjpznqzzl3l8", + "tags": [ + ["d", "333e500a-7d80-4e7b-beb1-ad1956a6150a"], + ["title", "Example task"], + ["published_at", "1296962229"], + ["t", "examples"], + ["p", "b3e392b11f5d4f28321cedd09303a748acfd0487aea5a7450b3481c60b6e4f87", "assignee"], + ["due_at", "1298962229"] + ], + "pubkey": "...", + "id": "..." +} +``` diff --git a/XXB.md b/XXB.md new file mode 100644 index 00000000..2fdfd482 --- /dev/null +++ b/XXB.md @@ -0,0 +1,57 @@ +NIP-XXB +======= + +Simple To-do flow +----------------- + +`draft` `optional` + +This NIP defines a simple workflow for task management, using [NIP-XXA](XXA.md) as a base and requirement. + +This NIP is meant to model a very simple task workflow. Possible use cases include: +- Individual to-do-list-style applications (Similar to Apple Reminders, Google Keep, etc) +- Group to-do-list-style applications (Similar to Apple Reminders shared lists) +- Systems that need to model to-do items to be completed by multiple people (e.g. an educational course that requires students to complete the same tasks, some onboarding system that requires new several people to complete the same tasks, etc) +- Any other system that needs to model simple to-do items (although some may need to extend this NIP to support other features) + +### Workflow + +In this workflow, [tasks](XXA.md) have only two states: OPEN/TODO and COMPLETE/DONE. + +To update a task state, users signal updates using the task update event defined below. + +The exact interpretation of which task update events are valid (e.g. to compute a final global state for each task) is left to the implementation of specific clients and relays, or to other NIPs. + +### Task Update Event format + +A task update event is a **regular** ([NIP-01](01.md)) event of `kind:1500` that signals a change in the status of a task. + +The `.content` of these events MUST be one of two values: +- `"TODO"` to signal that the task is now open/pending/to-do. +- `"DONE"` to signal that the task is now closed/complete/done. + +The list of required tags are as follows: +- `a` _(required)_: Coordinates to the kind `35000` task being updated. + +Any other tags are strictly optional, and this NIP does not attach any specific meaning to them. + +```jsonc +{ + "id": <32-bytes lowercase hex-encoded SHA-256 of the the serialized event data>, + "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, + "created_at": , + "kind": 1500, + "content": <"TODO"/"DONE">, + "tags": [ + ["a", ":<32-bytes lowercase hex of a pubkey>:", ] // Coordinates to the task being updated + (...) // Any other tags are optional + ] +} +``` + +### Other notes + +1. Consensus on the global state of tasks is left to the implementation of specific clients and relays, or to other NIPs. This is done on purpose to allow for flexibility in the implementation of each use case. +2. The task update event format is a regular event (not replaceable or addressable) because — as mentioned above — the final state of whether a user has completed the task or not is not necessarily the most recent event. + - As an example, consider the example of some educational platform that assigns a task to a student, and no longer considers task updates after a due date. In this case, the final state of the task is not the most recent event, but the last one that was created before the due date. + - Another reason is that clients may want to display the task update events in a timeline, so having older events may be useful to understand the history of the task. diff --git a/XXC.md b/XXC.md new file mode 100644 index 00000000..9ccc0575 --- /dev/null +++ b/XXC.md @@ -0,0 +1,102 @@ +NIP-XXC +======= + +Simple Kanban Board Workflow +---------------------------- + +`draft` `optional` + +This NIP defines a Kanban board workflow, building on [NIP-XXA](XXA.md) for tasks. This proposal allows tasks to be organized within a Kanban board using definable states, linked tasks, and sorting order. + +The Kanban board is a simple workflow tool that allows users to visualize tasks in different states of completion. Each task is represented as a card that can be moved between different columns, each representing a different state of completion. + +This is useful for use cases similar to apps such as Trello, Asana, Jira, Github Projects, and to model business processes that require multiple stages of completion. + +# Kanban board event format + +## Event Kind + +The `kind` of these events MUST be `35001`, and this is meant to be an _addressable_ event as defined in [NIP-01](01.md). + +## Content + +The `.content` of a kanban board event MUST be a JSON string defining the permissible states for tasks. The JSON should be in the following format: + +```jsonc +{ + "title": , + "description": <OPTIONAL description string>, + "states": [ + {"id": <id string>, "label": <label string>, "color": <OPTIONAL color value>}, + <other possible states> + ] +} +``` + +The `states` array MUST contain at least one state object. Each state object MUST have the following fields: +- `id`: A unique identifier for the state within the board. This identifier MUST be unique within the board. (e.g., "todo", "in-progress", "in-review", "done") +- `label`: A human-readable label for the state. (e.g., "To Do", "In Progress", "In Review", "Done") +- `color`: An optional color value for the state, to provide a visual cue. See the "Colors" section below for allowed values. + +Other fields MAY be added to the Content JSON, on other NIPs that extend this one. + +### Colors + +The `color` field can have any of the following values: +- One of the following preset colors: + - "red" + - "orange" + - "yellow" + - "green" + - "cyan" + - "blue" + - "purple" +- A hex RGB color code (e.g., `#FF0000`). + +Clients MAY choose to display the color in the UI, but it is not required. The color is intended only to provide a visual cue to users. + +The exact color codes for the preset colors is not specified and is left to the discretion of the client to match their own color scheme. + +## Tags + +Each task on the Kanban board should be added using an `a` anchor tag. These tags reference the task events defined in [NIP-XXA](XXA.md). The tags are structured as follows, with one dedicated value for the task's current state within the Kanban board: + +```jsonc +"tags": [ + ["a", "35000:<32-bytes lowercase hex of task author's pubkey>:<task d-identifier>", "<state id string>"], + ["a", "35000:<32-bytes lowercase hex of task author's pubkey>:<task d-identifier>", "<state id string>"], + ["a", "35000:<32-bytes lowercase hex of task author's pubkey>:<task d-identifier>", "<state id string>"], + // Other tasks can be added similarly. +] +``` + +The `state id string` MUST match one of the `id` values defined in the Kanban board's `.content` JSON. + +Clients SHOULD by default display the tasks in the order they are listed in the `tags` array, from top to bottom. If the client allows users to reorder tasks, the client MUST update the `tags` array sorting order accordingly. However, the client MAY choose to display tasks in a different order based on other criteria, such as due date or priority, sorting filters, etc. + +Other required tags: +- `d`: The board's unique identifier + +Optional tags: +- `p`: MAY be interpreted as the board's participant list, which could be used by clients and relays to determine who is allowed to view or edit the board, but the exact interpretation is left to the implementation. + +### Linking Kanban and Tasks + +When a task's status changes within this board, the tag's state value should update to reflect its new position in the workflow sequence. + +### Multi-user editing + +This NIP explicitly does not define how different users can edit the same board, since different use cases may require different solutions. + +However, here are some possible approaches (listed here for inspiration, but not a requirement): +- A single authoritative private/public keypair that represents a group/team of users, and produce/sign new board updates, by having a program listen to [edit requests](XXD.md) from any of the group members, and automatically approving/rejecting them based on the group's rules. + - This program could be simple or very complex with a lot of rules on who can edit what, when, and how — to fit several business use cases. +- A FROST-like key scheme can be used to require multiple signatures from different users to approve a change to the board. +- A board can be owned and controlled by a single user, publishing the board to private relays (single-user apps) +- A board can be controlled by a single user, but allow other users to view it. +- A client could listen to board events from a group of users and choose to display the board based on the most recent event it has seen from any of the users, or somehow "merge" different users' boards. + +## Intended use cases + +- Trello-like boards for personal or team task management. +- Business process workflows that require multiple stages of completion. diff --git a/XXD.md b/XXD.md new file mode 100644 index 00000000..3129cc29 --- /dev/null +++ b/XXD.md @@ -0,0 +1,76 @@ +NIP-XXD +======= + +Event Edit Requests +------------------- + +`draft` `optional` + +This NIP introduces a protocol allowing any Nostr user to submit an edit request for any addressable event initially authored by another user. It aims to streamline collaborative editing while maintaining clear identification of original and requested contents. + +## Edit Request Event Kind + +Edit requests are a `kind: 1501` **regular** event with the following structure: + +### Event Structure + +An edit request consists of a JSON object with the following structure: + +```jsonc +{ + "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>, + "pubkey": <32-bytes lowercase hex-encoded public key of the edit requestor>, + "created_at": <Unix timestamp in seconds>, + "kind": 1501, + "content": "{ + \"tags\": <proposed new tag contents>, + \"content\": <proposed new content string> + }", + "tags": [ + ["a", "<kind integer>:<32-bytes lowercase hex of the original author pubkey>:<d tag value>", "<relay-url>"] // Coordinates to the event being edited + ], + "sig": <64-bytes lowercase hex of the signature of the sha256 hash of the serialized event data> +} +``` + +### Tags + +- `a` (anchor): Required. Points to the addressable event that the user wants to edit. + +### Content + +The `.content` field is a JSON string containing the proposed changes (new ".content" and ".tags") to the original event. It should contain all contents that the requestor would like to see in the updated event (i.e. Not just the changes, but the full new content). + +## Edit Request response event + +The author of the original event can respond to an edit request by creating a `kind: 1502` **regular** event with the following structure: + +```jsonc +{ + "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>, + "pubkey": <32-bytes lowercase hex-encoded public key>, + "created_at": <Unix timestamp in seconds>, + "kind": 1502, + "content": "<APPROVE|REJECT>", + "tags": [ + ["e", "<32-bytes lowercase hex of the kind:1501 edit request event id>", "<relay-url>"] // Reference to the edit request event + ], + "sig": <64-bytes lowercase hex of the signature of the sha256 hash of the serialized event data> +} +``` + +This event is used simply to communicate the author's decision on the edit request, in order to provide the requester with feedback on the proposed changes. Clients and relays SHOULD send these events to improve the user experience by providing feedback on the edit request, so that the requester's client can update the UI accordingly. + +## Edit Request Workflow + +1. A user creates an edit request event with the proposed changes and tags pointing to the event to be edited. +2. The edit request is broadcasted to the network. +3. The author of the original event receives the edit request. The author can either approve or reject the edit request: + - If the author approves the edit request, they create a response event with the `APPROVE` content, applies the proposed changes to the original event, and broadcasts the updated event. + - If the author rejects the edit request, they create a response event with the `REJECT` content. + +## Intended Use Cases + +- Apps/Features that enable collaborative enhancements in articles, posts, or any addressable nostr event. +- Enabling nostr entities to be collaboratively editable by multiple users (e.g. Tasks, Kanban boards, wikis, etc). + - This can be through a human editorial flow, or through automated systems that automatically approve or reject edit requests based on programmatic rules. From 19f650b38a4ca08aa01ef2c66d708cc8c14ffd9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=E2=80=99Aquino?= <daniel@daquino.me> Date: Sat, 22 Feb 2025 18:17:57 -0800 Subject: [PATCH 2/2] Version 2 draft for workflow-related NIPs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Race condition issues solved - Multi-user collaboration has a single well-defined consensus, without compromising flexibility — all use-cases are still possible to implement - Kanban board event modified to be very similar and almost compatible with Kanbanstr - Workflow architecture is now more scalable and extensible to cover even more use cases. --- README.md | 5 +- XXA.md | 24 ++--- XXC.md | 100 ++++++++--------- XXE.md | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+), 72 deletions(-) create mode 100644 XXE.md diff --git a/README.md b/README.md index 0da3ba26..2412ea56 100644 --- a/README.md +++ b/README.md @@ -240,8 +240,9 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | `31990` | Handler information | [89](89.md) | | | `32267` | Software Application | | | | `34550` | Community Definition | [72](72.md) | -| `35000` | Task Event | [XXA](XXA.md) | -| `35001` | Kanban Board Event | [XXC](XXC.md) | +| `35000` | Tracker Event | [XXE](XXE.md) | +| `35001` | Task Event | [XXA](XXA.md) | +| `35002` | Kanban Board Event | [XXC](XXC.md) | | `38383` | Peer-to-peer Order events | [69](69.md) | | `39000-9` | Group metadata events | [29](29.md) | diff --git a/XXA.md b/XXA.md index eb7ff006..cc4d1bcb 100644 --- a/XXA.md +++ b/XXA.md @@ -6,7 +6,7 @@ Tasks `draft` `optional` -This NIP defines `kind:35000` (an _addressable event_) for tasks, generally referred to as "tasks", "to-do items", or "reminders". +This NIP defines `kind:35001` (an _addressable event_) for tasks, generally referred to as "tasks", "to-do items", or "reminders". This NIP intentionally does not define any information about workflows, states, authorization mechanisms, or any other complex task management features, as the needs and requirements for these vary greatly between different applications and use cases. This NIP is meant to be used only as a base for more complex task management systems, and only focuses on the basic information that models a task itself. @@ -20,12 +20,9 @@ The `kind` of these events MUST be `35000`, which is an _addressable event_ as d ### Content -The `.content` of these events MUST be used as the description of a task, and should be a string text in [Github Flavored Markdown syntax](https://github.github.com/gfm), with the following constraints: -- MUST NOT hard line-break paragraphs of text, such as arbitrary line breaks at 80 column boundaries. -- MUST NOT support adding HTML to Markdown. -- MUST NOT support adding JavaScript to Markdown. +The `.content` of these events MUST be used as the description of a task, and should be a string text in Markdown format, following [NIP-23](23.md) conventions. -Clients MAY render any inline [Nostr URI](21.md) into a rich interactive object or widget, to allow for easy navigation and interaction with the referenced content, or as simple hyperlinks. +Clients MAY render any inline [Nostr URI](21.md) into a rich interactive object or widget, to allow for easy navigation and interaction with the referenced content with improved user experience, or as simple hyperlinks. ### Metadata and Tags @@ -56,18 +53,15 @@ The role is optional, and this NIP only standardizes the following values: - `"client"`: The user is the client or requester of the task. - (Any other value): Any other role that is not standardized by this NIP, which for the purposes of this NIP is treated the same as an empty role. -### Editability +### Editability and multi-user collaboration -These tasks are meant to be editable, so they should include a `d` tag with an identifier for the task. Clients should take care to only publish and read these events from relays that implement that. If they don't do that they should also take care to hide old versions of the same tasks they may receive. +These tasks are editable in the same way as any other addressable event. To keep in compliance with [NIP-01](01.md), the authoring pubkey is the ultimate authority on the source of truth for the task data. -For simplicity and flexibility, this NIP does not define a specific mechanism to allow groups of users to edit the same task. This is deliberately left out to allow for different implementations to be built on top of this NIP in a way that best suits the needs of a particular use case. Examples of possible implementations include: -- A single user is assigned to a task, and only that user can edit the task. -- The task is signed using a collaborative signing mechanism, such as a multi-signature or FROST-like scheme. -- The task is signed by an authoritative keypair representing a group/company, and members of a group need to request changes to the task from that entity using [edit requests](XXD.md) or other mechanisms. +For clarity, clients and servers MUST NOT decide on a source of truth based on a set of events signed by different pubkeys, because that will break anchor tags of addressable events and is in violation of [NIP-01](01.md). -### Linking - -The task may be linked to using the [NIP-19](19.md) `naddr` code along with the `a` tag. +This does not constrain the possibilities and use cases, because any possible multi-user editing logic can be implemented using some combination of: +- [Edit Requests](XXD.md) to propose changes to the task, with _(optionally)_ scripts that listens to them and approves/rejects based on any arbitrarily complex logic. +- FROST signature schemes (or any other multisig/key-splitting technique) to split the private key that signs these events and allow n-of-N multisig schemes ## Example Event diff --git a/XXC.md b/XXC.md index 9ccc0575..12bd5602 100644 --- a/XXC.md +++ b/XXC.md @@ -6,7 +6,9 @@ Simple Kanban Board Workflow `draft` `optional` -This NIP defines a Kanban board workflow, building on [NIP-XXA](XXA.md) for tasks. This proposal allows tasks to be organized within a Kanban board using definable states, linked tasks, and sorting order. +_Draft note: Some content was taken from https://github.com/nostr-protocol/nips/pull/1665/files, the credit to some of the content and ideas should go to the author_ + +This NIP defines a Kanban board workflow, and is a **Workflow** as described in [NIP-XXE](XXE.md). This proposal allows tasks to be organized within a Kanban board using definable states, linked tasks, and sorting order. The Kanban board is a simple workflow tool that allows users to visualize tasks in different states of completion. Each task is represented as a card that can be moved between different columns, each representing a different state of completion. @@ -14,35 +16,40 @@ This is useful for use cases similar to apps such as Trello, Asana, Jira, Github # Kanban board event format -## Event Kind +The Kanban board is an _addressable_ event as defined in [NIP-01](01.md), with `kind:35002`. Here is the format: -The `kind` of these events MUST be `35001`, and this is meant to be an _addressable_ event as defined in [NIP-01](01.md). - -## Content - -The `.content` of a kanban board event MUST be a JSON string defining the permissible states for tasks. The JSON should be in the following format: - -```jsonc +```javascript { - "title": <title string>, - "description": <OPTIONAL description string>, - "states": [ - {"id": <id string>, "label": <label string>, "color": <OPTIONAL color value>}, - <other possible states> - ] + "created_at": 1740274054, //<Unix timestamp in seconds> + "kind": 35002, + "content": "", // Not used + "tags": [ + ["d", "<board-d-identifier>"], + ["title", "<board-title>"], + ["description", "<board-description>"], // NIP-23 markdown + ["alt","A board to track my work"], // Human-readable plaintext summary to be shown in non-supporting clients — as per NIP-31 + + // List of all columns in the board below ["col","<column-id>","<column-label>", "<optional color value>"]. The order in which they appear MUST match the order here + ["col", "to-do", "To Do", "gray"], + ["col", "in-progress", "In Progress", "blue"], + ["col", "done", "Done", "green"], + + // Clients may designate a 'maintainers' list who can add/edit cards in this board + [ "p", "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2" ], + [ "p", "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" ], + [ "p", "460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c" ], + // other fields... + ] } ``` -The `states` array MUST contain at least one state object. Each state object MUST have the following fields: -- `id`: A unique identifier for the state within the board. This identifier MUST be unique within the board. (e.g., "todo", "in-progress", "in-review", "done") -- `label`: A human-readable label for the state. (e.g., "To Do", "In Progress", "In Review", "Done") -- `color`: An optional color value for the state, to provide a visual cue. See the "Colors" section below for allowed values. +To find out which tasks/cards are in the board, clients MUST query [Tracker events](XXE.md) authored by any of the maintainers list AND are linked back to this workflow. -Other fields MAY be added to the Content JSON, on other NIPs that extend this one. +In case there are no `p` tags to designate maintainers, the owner of the board is the only person who can publish cards on the boards. ### Colors -The `color` field can have any of the following values: +The `color` field for a column can have any of the following values: - One of the following preset colors: - "red" - "orange" @@ -51,52 +58,35 @@ The `color` field can have any of the following values: - "cyan" - "blue" - "purple" + - "gray" - A hex RGB color code (e.g., `#FF0000`). -Clients MAY choose to display the color in the UI, but it is not required. The color is intended only to provide a visual cue to users. +Clients MAY choose to display the color in the UI, but it is not required. The color is intended only to provide a visual cue to users, but text labels are always required — for accessibility purposes. The exact color codes for the preset colors is not specified and is left to the discretion of the client to match their own color scheme. -## Tags +## Tracker event -Each task on the Kanban board should be added using an `a` anchor tag. These tags reference the task events defined in [NIP-XXA](XXA.md). The tags are structured as follows, with one dedicated value for the task's current state within the Kanban board: +As per [NIP-XXE](XXE.md), `kind:35000` tracker events are used for tracking tasks/items within a kanban board. -```jsonc -"tags": [ - ["a", "35000:<32-bytes lowercase hex of task author's pubkey>:<task d-identifier>", "<state id string>"], - ["a", "35000:<32-bytes lowercase hex of task author's pubkey>:<task d-identifier>", "<state id string>"], - ["a", "35000:<32-bytes lowercase hex of task author's pubkey>:<task d-identifier>", "<state id string>"], - // Other tasks can be added similarly. -] -``` +Furthermore, this NIP makes use of the RESERVED fields in `kind:35000` tracker events, in the following manner: +1. `"content"` MUST be set to the column id representing the state of the task/item, or should be left EMPTY (`""`) + 1. If empty, and the `"tracked_item"` is a second `kind:35000` tracker event, the state/status of the task MUST be the one specified in the second tracker event. If it refers to a column id not present in the current board, the client MAY temporarily display those special columns, or in one catch-all "other" column. +2. The `"rank"` tag is used to denote manual ordering within columns — items MAY be displayed in the ascending order of rank by default + - **Example:** `["rank","10"]` +3. All other RESERVED tags have the same meaning and use as [NIP-XXA](XXA.md). + 1. If the `"tracked_item"` refers to a `kind:35001` task event ([NIP-XXA](XXA.md)), the Client SHOULD combine/merge tag content for display as follows: + - `"title"`, `"image"`, `"published_at"`, `"due_at"`, and `"archived"` fields in the tracker SHOULD override the fields on the original `kind:35001` event + - `"t"` and `"p"` tags SHOULD be combined in both events (set union operation) + 2. If `"tracked_item"` refers to a second `kind:35001` tracker event, the same rules as point `3.1` above apply — recursively — as in a chain. -The `state id string` MUST match one of the `id` values defined in the Kanban board's `.content` JSON. -Clients SHOULD by default display the tasks in the order they are listed in the `tags` array, from top to bottom. If the client allows users to reorder tasks, the client MUST update the `tags` array sorting order accordingly. However, the client MAY choose to display tasks in a different order based on other criteria, such as due date or priority, sorting filters, etc. +### Editability and multi-user collaboration -Other required tags: -- `d`: The board's unique identifier - -Optional tags: -- `p`: MAY be interpreted as the board's participant list, which could be used by clients and relays to determine who is allowed to view or edit the board, but the exact interpretation is left to the implementation. - -### Linking Kanban and Tasks - -When a task's status changes within this board, the tag's state value should update to reflect its new position in the workflow sequence. - -### Multi-user editing - -This NIP explicitly does not define how different users can edit the same board, since different use cases may require different solutions. - -However, here are some possible approaches (listed here for inspiration, but not a requirement): -- A single authoritative private/public keypair that represents a group/team of users, and produce/sign new board updates, by having a program listen to [edit requests](XXD.md) from any of the group members, and automatically approving/rejecting them based on the group's rules. - - This program could be simple or very complex with a lot of rules on who can edit what, when, and how — to fit several business use cases. -- A FROST-like key scheme can be used to require multiple signatures from different users to approve a change to the board. -- A board can be owned and controlled by a single user, publishing the board to private relays (single-user apps) -- A board can be controlled by a single user, but allow other users to view it. -- A client could listen to board events from a group of users and choose to display the board based on the most recent event it has seen from any of the users, or somehow "merge" different users' boards. +This NIP follows the same standards and rules for multi-user collaboration as [NIP-XXA](XXA.md). ## Intended use cases - Trello-like boards for personal or team task management. - Business process workflows that require multiple stages of completion. +- Executive kanban boards that would like to keep track of a specific subset of tasks in other kanban boards — with automatic state changes. diff --git a/XXE.md b/XXE.md new file mode 100644 index 00000000..fd2f95f9 --- /dev/null +++ b/XXE.md @@ -0,0 +1,312 @@ +NIP-XXE +======= + +Workflows +--------- + +`draft` `optional` + +This NIP defines a base scheme for productive workflows — in a way that is highly extensible, reusable, composable, and interoperable among several use-cases. + +### Motivation + +Needs and requirements for productive workflows vary greatly between different applications, teams, and use cases, which makes interoperability very challenging. + +It goes way beyond simple to-do lists. To illustrate this point, here are examples of such use-cases and needs: +- Kanban boards for developer teams +- A dashboard to track workflows between agency businesses and their clients +- Personal task trackers, to-do lists, shopping lists +- Customer relationship management software (CRMs) +- CI/CD pipelines +- Gantt charts for Project management/planning +- Multifaceted projects with several different teams and departments working on the same project from different angles +- Executive boards to track only a portion of work being done in other workflows +- Customer support workflows +- Editorial flows for longform content +- any other kind of use-case where some coordination is needed to help produce value or get things done + +Having a common base that allows for interoperability of those varied applications could greatly reduce work wasted on manual data entry, silos, re-inventing the wheel, and the necessity for N-choose-2 integrations between workflows/APIs. + +This NIP is meant to bridge and address those two seemingly opposing needs. + +### Main concept and definitions + +To achieve the goal of maximum interoperability with minimal coupling, we only need to introduce 3 concepts: + +1. A **Workflow** is a system by which people can work together (or alone) towards some goal. It enables communication and coordination towards productive work. +2. A **Tracked Item** (or **Item**) is any item that needs to be tracked within a productive workflow (e.g. A task to be done, a git issue, a customer message to reply to, a part to be manufactured, etc). +3. A **Tracker** is the glue that specifies exactly 3 things: + 1. what Item is being tracked + 2. in which workflow is it being tracked at + 3. any other metadata attached to the **Item** that is relevant to the **Workflow** (e.g. a status on a Kanban board, "dependencies" on a Gantt chart, etc) + +The way it works is that **Workflows** track **Items** using **Trackers**. This is a simple pattern, but several workflows can be implemented and composed with it. + +It is not a new concept. It is equivalent to the concept of "junction tables" in a database, which is widely used and proven pattern to implement flexible many-to-many relationships without introducing hard interdependencies. Furthermore, this avoids spec rigidity and race conditions at the same time. + +### Workflows + +**Workflows** are defined in separate NIPs (we will call them **Workflow NIPs** in this document). + +Clients and Relays are free to implement whichever Workflow NIP specifications are needed for their use-case. + +### Tracked Items + +A tracked item can be any _regular_ OR _addressable_ Nostr event — even other **Trackers** (more on this later). Clients MAY use whichever event types that best suits their use-case (e.g. [NIP-34 git issues](34.md), `kind:1` events, etc). [NIP-XXA](XXA.md) is provided as a general-purpose "task" type. + + +### Trackers + +Trackers are a `kind:35000` _addressable event_ with the following structure: + +```jsonc +{ + "kind": 35000, + "content": "<WORKFLOW_SPECIFIC_DATA>", + "tags": [ + ["d", "<unique addressable event identifier>"] + ["a", "<kind integer>:<32-bytes lowercase hex of the original author pubkey>:<d tag value>", "<relay-url>", "tracked_item"], // Or ["e", "<ID>", "tracked_item"] + ["a", "<kind integer>:<32-bytes lowercase hex of the original author pubkey>:<d tag value>", "<relay-url>", "workflow"] + // ... <WORKFLOW_SPECIFIC_DATA> + ], + "pubkey": "...", + "id": "..." + "created_at": 1675642635, + "sig": "...", +} +``` + +Clients MUST: +- define exactly one `"tracked_item"` tag. +- define exactly one `"workflow"` tag. +- interpret remaining content and tags according to the **Workflow NIP** of the event kind marked as `"workflow"`. In other words, those remaining tags/content are _RESERVED_. + +Clients MAY: +- ignore **Trackers** pointing to workflows that they do not understand + +Any **Workflow NIP** MUST: +- describe and specify an _addressable_ event kind as defined in [NIP-01](01.md), to model/describe the workflow. +- describe and specify the meaning and usage of the reserved fields, marked as `<WORKFLOW_SPECIFIC_DATA>`. They SHOULD use that to describe how the **Item** fits in the workflow (e.g. The state of the item, start/end date, or any other information) + +Any **Workflow NIP** SHOULD: +- Use content and tag information from both the **Tracked Item** as well as the **Tracker**, and make it composable (e.g. Use the tracker data to either complement or replace data/tags from the original item, but use item data when tracker data is not available). + - The reason for this is to make the system composable, by allowing tracking of other trackers, which significantly expands possible use-cases. + +### Editability and multi-user collaboration + +This NIP follows the same standards and recommendations for multi-user collaboration as [NIP-XXA](XXA.md). + +---- +This is the end of the spec. What follows is recommended OPTIONAL reading. + +---- + +# Use-case implementation guide + +This section will illustrate the spec in practice, and how it can be used and scaled nicely into ever-more-complex workflows. + +## Case 1: Simple kanban development workflow + +### Description + +A simple kanban to track development work, in a team of developers who have roughly equal authority. + +### General structure + +```mermaid +block-beta + +columns 1 + block:Items + I0["Items"] + I1["NIP-34 git issue"] + I2["Item: NIP-XXA task"] + I3["Item: NIP-34 git issue"] + end + space + block:Trackers + T0["Trackers"] + T1["Workflow data: 'To-do'"] + T2["Workflow data: 'In-progress'"] + T3["Workflow data: 'Done'"] + end + space + block:Workflows + W0["Workflows"] + W1["Dev team board (defines all columns, maintainers, etc)"] + space + space + end + + style I0 fill:#FFF + style T0 fill:#FFF + style W0 fill:#FFF + + T1-- "Tracks" -->I1 + T2-- "Tracks" -->I2 + T3-- "Tracks" -->I3 + + T1-- "In workflow" -->W1 + T2-- "In workflow" -->W1 + T3-- "In workflow" -->W1 +``` + +Notice how: +- NIP-XXA does not even need to know about kanban boards to exist +- NIP-34 git issues can be seamlessly integrated + +### Access controls + +Notice how, without much effort, several different access policies can be elegantly applied: + - Different authority schemes can be applied at any layer: + - Signing access to the Workflow event allows one to change the structure of the board (coluns, maintainers, etc) + - Signing access to any of the trackers allows one to change the status of such tasks, and other metadata + - Signing access to any of the task items allows one to change the description of the task itself, the title, etc. + - Each one of these Nostr events can be signed by any key, depending on the teams needs. + - A 1-of-N FROST key can be used if any member can edit things + - A 2-of-N FROST key can be used if something is more sensitive + - An authoritative key can be used when only one person/entity should control things + - Others can still try to edit via edit requests ([XXD.md]), which may be approved. + +## Case 2: Client/Service provider dashboards + +### Description + +A system provided by a service provider to some client (e.g. An agency/freelancer workflow, a package delivery system provided by a company, a ride-share system provided by one driver) + +### General structure + +(Very similar to Case 1) + +### Access controls + +The company could sign all of these Nostr events, and allow the client to edit _some_ information in _some_ cases (e.g. They can cancel only before a task is started), via a script that runs on a server, listening to [NIP-XXD](XXD.md) requests, and approving/rejecting based on arbitrary business logic. + + +## Case 3: Gantt chart for project managers + +### Description + +The development team grows, and a project management team is hired to do some planning. They like to use Gantt charts to plan things. + +### General structure + +```mermaid +block-beta + +columns 1 + block:Items + I0["Items"] + I1["NIP-34 git issue"] + I2["NIP-XXA task"] + I3["NIP-XXA task"] + end + space + block:Trackers + T0["Trackers"] + T1["Workflow data: 'To-do'"] + T2["Workflow data: 'In-progress'"] + T3["Workflow data: 'Done'"] + T4["Gantt chart item data"] + T5["Gantt chart item data"] + T6["Gantt chart item data"] + end + space + block:Workflows + W0["Workflows"] + W1["Dev Kanban board"] + W2["Project manager's gantt chart"] + + end + + style I0 fill:#FFF + style T0 fill:#FFF + style W0 fill:#FFF + + T1-- "Tracks" -->I1 + T2-- "Tracks" -->I2 + T3-- "Tracks" -->I3 + T4-- "Tracks" -->I1 + T5-- "Tracks" -->I2 + T6-- "Tracks" -->I3 + + T1-- "In workflow" -->W1 + T2-- "In workflow" -->W1 + T3-- "In workflow" -->W1 + T4-- "In workflow" -->W2 + T5-- "In workflow" -->W2 + T6-- "In workflow" -->W2 +``` + +Notice how: +- Gantt charts, a new workflow type, can be seamlessly integrated without changing the kanban board NIP. + +### Access controls + +The same principles as Case 1 applies here, with even more options: +- The project management team can have their own team keys, or edit request interfaces, to fine tune exactly who can do what. +- On the kanban side the dev team can have more control and autonomy, whereas on the gantt chart the project management team can have more control and autonomy. + + +## Case 4: Executive boards + +### Description + +The product team in Case 3 grows, and the executive team would like to track only a subset of the dev team tasks (e.g. critical bugs). + +### General structure + +```mermaid +block-beta + +columns 1 + block:Items + I0["Items"] + I1["Some random git issue"] + I2["Critical bug task"] + + end + space + block:Trackers + T0["Trackers"] + T3["''"] + space + T2["'In-progress'"] + T1["'To-do'"] + T5["Gantt chart item data"] + end + space + block:Workflows + W0["Workflows"] + W3["Executives' board"] + W1["Dev Kanban board"] + W2["Project manager's gantt chart"] + end + + style I0 fill:#FFF + style T0 fill:#FFF + style W0 fill:#FFF + + T1-- "Tracks" -->I1 + T2-- "Tracks" -->I2 + T3-- "Tracks" -->T2 + + T5-- "Tracks" -->I2 + + T1-- "In workflow" -->W1 + T2-- "In workflow" -->W1 + T3-- "In workflow" -->W3 + T5-- "In workflow" -->W2 +``` + +Notice how: +- one tracker tracks another tracker. +- the tracker for the executive board has an empty content. This is on purpose. The kanban workflow spec can be written so that an empty tracker content falls back to the content of what it tracks — which means the executive board will see the actual development state of the original task. + +### Access controls + +Same principles as all other cases. Very customizable, without breaking interoperability. + +---- + +As demonstrated, this way of building workflows allows for scale and modularity, without compromising interoperability, and without introducing race conditions seen in large lists.