diff --git a/34.md b/34.md index ab80a93649..96b5f24100 100644 --- a/34.md +++ b/34.md @@ -66,6 +66,38 @@ The `refs` tag can be optionally extended to enable clients to identify how many } ``` +## Multiple maintainers + +A repository MAY be announced by **each maintainer** publishing their own `kind:30617` (same `d` and same `"euc"` commit in the `r` tag). Likewise, each maintainer MAY publish their own `kind:30618` for the same repo (`d` matches). + +Clients SHOULD treat all `30617` events sharing the same `(d, euc)` as describing the **same project**, and aggregate their data. The `maintainers` tag SHOULD list all recognized maintainers (including the author); clients MAY use this to decide whose `30618` to trust. + +**Addressing note:** The standard Nostr address `a` for a repo remains `30617::`. With multiple maintainers, there will be multiple valid addresses for the same repo. Clients SHOULD group these by `(d, euc)`. + +## Repository state with multiple maintainers + +Each maintainer publishes their own view as a `kind:30618` sharing the same `d`. Clients SHOULD: + +* Accept `30618` only from pubkeys currently recognized as maintainers in at least one valid `30617` for `(d, euc)`. +* Prefer the **latest** `30618` per maintainer (by `created_at`). +* When refs differ across maintainers, either: + + * display a **merged view** (per ref, take the most recent value from any recognized maintainer), or + * display a **per-maintainer view** and mark refs as **contested** when heads differ. + +If maintainers disagree on the `"euc"` commit (`r` with `"euc"` marker), clients SHOULD treat them as **different repositories** (likely a fork). + +## Resolving ambiguities + +When `30617` fields differ (e.g., `web`, `clone`, `relays`, `description`): + +* Clients MAY show a **union** of values and highlight conflicts, or +* Prefer values from the **most recent** `30617` among recognized maintainers. + +For `30618` conflicts: + +* If a ref advances in multiple `30618`s, clients MAY adopt **last-write-wins** (latest `created_at`) or show a **contested** badge until the user selects a maintainer. + ## Patches Patches can be sent by anyone to any repository. Patches to a specific repository SHOULD be sent to the relays specified in that repository's announcement event's `"relays"` tag. Patch events SHOULD include an `a` tag pointing to that repository's announcement address. @@ -165,6 +197,53 @@ The most recent Status event (by `created_at` date) from either the issue/patch The Status of a patch-revision is to either that of the root-patch, or `1632` (_Closed_) if the root-patch's Status is `1631` (_Applied/Merged_) and the patch-revision isn't tagged in the `1631` (_Applied/Merged_) event. +## Labels, assignees, and reviewers (via NIP-32) + +Issue (`1621`) and patch (`1617`) metadata MAY be managed with [NIP-32](32.md) label events (`kind:1985`). + +**Targeting:** Each label event MUST reference the subject via `e` (event id) or `a` (address of `30617::` for repo-wide labels). + +**Freeform labels:** Use `l` (label, namespace, language) for arbitrary tagging, e.g.: + +``` +["l","priority/high","meta"] +["l","area/ui","meta"] +["l","triage/needed","meta"] +``` + +**Assignments and reviews:** Represent people/roles with NIP-32 by combining `p` and `l`: + +* Assign one or more users to an **issue**: + + ``` + ["p",""] + ["l","assignee","role"] + ``` +* Request review on a **patch**: + + ``` + ["p",""] + ["l","reviewer","role"] + ``` + +Multiple `p` tags MAY be present; each applies to the role indicated by accompanying `l` entries with namespace `"role"`. + +**Authorship & authority:** Clients SHOULD treat label events as effective when authored by: + +* the issue/patch author, or +* any recognized maintainer (per any valid `30617` for the same `(d,euc)`), or + +**Conflict handling:** When multiple `1985` events modify the same role/label on the same target: + +* Prefer the latest by `created_at`; +* If multiple maintainers disagree, show the state **per maintainer** or mark it **contested** (same guidance as for `30618`). + +**Unassign / remove:** To clear a role for a given user, publish a newer `1985` that omits that user for the `"role"` in question. To clear all assignees/reviewers, publish a newer `1985` that includes the role label (`"assignee"` or `"reviewer"`) with no corresponding `p` tags. + +**Display hints:** Clients MAY surface NIP-32 labels alongside the base event: + +* chips for `priority/*`, `area/*`, etc. +* “Assignees” and “Reviewers” lists derived from `("role", assignee|reviewer) + p`. ## Possible things to be added later