From 603ccefc791f42cfd9e09800aa8ee8539b35254a Mon Sep 17 00:00:00 2001 From: Fizz <400e8babadcee6a7f420103f10a2849d84c4a9c71d5bd04f3948c814216648a3@buzz.block.builderlab.xyz> Date: Sun, 20 Sep 2026 16:56:48 -0700 Subject: [PATCH] docs(protocol): make artifact specification standalone Signed-off-by: Fizz <400e8babadcee6a7f420103f10a2849d84c4a9c71d5bd04f3948c814216648a3@buzz.block.builderlab.xyz> --- VISION.md | 12 +- VISION_PROJECTS.md | 28 ++-- docs/nips/NIP-AR-CLIENTS.md | 30 ++-- docs/nips/NIP-AR.md | 274 +++++++++++++++--------------------- 4 files changed, 146 insertions(+), 198 deletions(-) diff --git a/VISION.md b/VISION.md index 78fcc2035c..8669e4dad9 100644 --- a/VISION.md +++ b/VISION.md @@ -152,13 +152,11 @@ Beyond chat: channels are workspaces. The relay hosts git repos. Smart HTTP — standard `git clone`, `git push`, nothing special. Your npub signs pushes. Same domain, same auth, same identity as everything else on the relay. -The proposed [channel artifact model](docs/nips/NIP-AR.md) replaces the earlier -“branches are channels” direction: channels contain work records and may host -several projects, tasks, or branches. A dedicated branch channel remains a useful -workspace choice, not a required identity or one-to-one relationship. Completing -one record does not automatically archive the shared channel. Existing Git -objects and review authority retain their separate protocol contracts during -migration. This is proposed direction, not shipped artifact support. +[Channel artifacts](docs/nips/NIP-AR.md) bring durable work records into channels +and threads. A channel can host several projects, tasks, or branches. Teams can +choose a dedicated branch channel when the work benefits from its own space. +Completing one record leaves the shared channel available for other work. +Git objects and review authority retain their own protocol contracts. See [VISION_PROJECTS.md](VISION_PROJECTS.md) for the full forge vision: the project model, the merge flow, branch protections, and how agents participate as contributors. diff --git a/VISION_PROJECTS.md b/VISION_PROJECTS.md index 8c2c87f483..5254146da6 100644 --- a/VISION_PROJECTS.md +++ b/VISION_PROJECTS.md @@ -8,23 +8,21 @@ This document is the software-forge slice of the broader Buzz platform. [VISION. --- -## Proposed evolution: channels contain work +## Channels contain work -The [channel artifact proposal](docs/nips/NIP-AR.md) and its -[client contracts](docs/nips/NIP-AR-CLIENTS.md) supersede this document's earlier -one-branch/one-channel assumption as proposed direction, not shipped behavior. -Projects and tasks are editable records inside channels or threads; a channel -may contain many of either. Projects organize related work without being a -prerequisite for a task or granting access to it. Dedicated workspaces remain -an option. Completing a task, retiring a branch record, or archiving a project -does not automatically archive its channel. +[Channel artifacts](docs/nips/NIP-AR.md) and their +[client contracts](docs/nips/NIP-AR-CLIENTS.md) give projects, tasks, and branch +collaboration records a home inside channels or threads. A channel may contain +many records of each type. Projects organize related work without being a +prerequisite for a task or granting access to it. Teams choose dedicated +workspaces when useful. Completing a task, retiring a branch record, or archiving +a project leaves the channel available for other work. -The forge workflows below remain useful examples of dedicated workspaces, -not mandatory identity/cardinality rules. NIP-34 remains authoritative for Git -identity and operations. Existing NIP-MP projects remain the current shipped -representation pending an explicit migration; the proposal must not create a -second competing project record. Private artifact access does not automatically -make existing repository metadata, code, or reviews private. +This model supersedes the one-branch/one-channel assumption; the forge workflows +below illustrate optional dedicated workspaces. NIP-34 remains authoritative +for Git identity and operations. Converting NIP-MP projects to artifacts +preserves one canonical record and its references. Private artifact access does +not automatically make repository metadata, code, or reviews private. For the intended experience without protocol details, see [Work lives alongside the conversation](docs/channel-artifacts-design-note.md). diff --git a/docs/nips/NIP-AR-CLIENTS.md b/docs/nips/NIP-AR-CLIENTS.md index 54fa70f73b..5846195bf3 100644 --- a/docs/nips/NIP-AR-CLIENTS.md +++ b/docs/nips/NIP-AR-CLIENTS.md @@ -1,6 +1,6 @@ # Artifact client contracts -`draft` `clients` `not implemented` +`draft` `clients` Depends on [NIP-AR](NIP-AR.md). These are shared desktop, mobile, CLI, SDK, and agent contracts, **not relay business validation rules**. All types use the same @@ -20,11 +20,10 @@ Clients use a bounded fallback rather than deeply parsing oversized content. A malformed known type uses the fallback card with a clear unavailable-details state. Unknown types/versions show type, title, last editor, and a route to the home conversation when available. They must not disappear from the workspace. -The default experience works without selecting or installing plugins. ## `buzz.project` -A grouping of related work, not a channel identity or access-control container. +A grouping of related work. | Payload field | Type | Meaning | |---------------|------|---------| @@ -54,8 +53,8 @@ A living definition of work, independent of any prerequisite project or repo. | `state` | string | `open`, `done`, or `cancelled` | | `status_label` | string, optional | Display refinement, e.g. “In review” | -The broad state supports common views; teams may use labels without a relay -deploy. Clients must not infer done/cancelled solely from an arbitrary label. +`state` supplies the common completion state; `status_label` refines its display. +Clients must not infer done/cancelled solely from an arbitrary label. Assignees use repeatable `assignee` tags containing public keys. Assignment here is task metadata, not permission to read or edit, and does not automatically notify or subscribe the assignee. `assignee` deliberately differs from `p`, @@ -80,8 +79,7 @@ it or widen its audience. The same task may appear in several project views. ## `buzz.branch` -A collaboration record concerning a Git branch; not the ref itself or a second -review/merge authority. +A collaboration record concerning a Git branch. | Payload field | Type | Meaning | |---------------|------|---------| @@ -92,12 +90,11 @@ review/merge authority. Required tags are `repository` (a NIP-34 `30617::` coordinate) and `ref` (a valid full `refs/heads/...` Git ref). Split the coordinate on its first two colons only. Clients validate Git ref syntax with established -Git-compatible validation, not an invented permissive approximation. +Git-compatible validation. A record may precede first push. Its repository/ref pair is immutable in this client contract: another ref or a recreated branch lifecycle gets a new record. -Retirement is terminal for this client version. These are client semantics; -the relay does not certify them. Multiple records may reference the same ref; +Retirement is terminal. Multiple records may reference the same ref; clients may offer duplicate cleanup without merging their identities silently. Git tips, push rights, checks, approval, and merge state come from authoritative @@ -108,7 +105,6 @@ Automatic summaries/notifications must respect the destination audience too. ## Example: task started in a conversation Standard signed-event fields are omitted. Placeholder IDs below are explanatory. -The numeric kind is proposed; see the allocation note in NIP-AR. ```json { @@ -130,11 +126,9 @@ Later adding `["project", ""]` uses `op=update` and `prev` naming the current accepted revision. It preserves `d`, `h`, and `root`. The project may live elsewhere; viewing that project does not grant access to this task. -## Compatibility release gate +## Conformance -Publish shared valid/invalid fixtures before shipping editors. Exercise them -in desktop, mobile, CLI/SDK, and agent tooling: unsupported versions, unknown -fields/tags, bad JSON, cycles, inaccessible links, and concurrent updates. -The relay suite should demonstrate both envelope rejection and acceptance of -opaque content that a business client declines to interpret. Acceptance by one -layer is not a correctness certificate from the other. +Clients MUST handle unsupported versions, unknown fields and tags, malformed +JSON, cyclic references, inaccessible links, and concurrent updates according +to the rules above. A relay-accepted revision whose content fails the client +contract MUST use the fallback display rather than a typed editor. diff --git a/docs/nips/NIP-AR.md b/docs/nips/NIP-AR.md index c3d1ef4bc6..77d5f844c4 100644 --- a/docs/nips/NIP-AR.md +++ b/docs/nips/NIP-AR.md @@ -4,45 +4,34 @@ NIP-AR Channel Artifacts ----------------- -`draft` `optional` `relay` `not implemented` +`draft` `optional` `relay` **Depends on:** NIP-01 (signed events), NIP-29 (channel access). -## Decision +## Abstract An **artifact** is a durable, editable record inside a channel, optionally -attached to a conversation within it. Channels contain artifacts; they are not -artifacts themselves. Projects, tasks, and branch collaboration records use the -same envelope, with client-defined content types. +attached to a conversation within it. This NIP defines a common envelope, +identity, revision chain, access rules, and lifecycle for artifacts with +client-defined content types. -- One current home channel determines an artifact's current audience. -- Any number of artifacts, including of the same type, may share a location. -- Relationships organize work; they never grant access or operational authority. -- The relay validates the common envelope and lifecycle, not business schemas. -- Clients share published contracts for first-party types; unknown types remain - readable as a basic card. - -This replaces the conversation-subject proposal in -[PR #7656](https://github.com/block/buzz/pull/7656): no exclusive/primary claims, -no type-specific event kinds or relay relationship validation, no required -project for a task, and no permanently fixed home. This is a specification PR, -not a claim that these behaviors are available in existing clients or relays. +The current home channel determines the artifact's audience. Any number of +artifacts, including of the same type, may share a channel or conversation. +Relationships between artifacts organize work without granting access or +operational authority. The relay validates the envelope and lifecycle; clients +interpret and validate content according to its type. MUST, MUST NOT, SHOULD, and MAY have their RFC 2119 meanings. ## Identity and envelope -The proposal uses one regular stored event kind, **45010**, for all artifact -revisions. This number is proposed, not allocated by this docs-only change; -implementation must reserve it in `crates/buzz-core/src/kind.rs`. It replaces, -not interoperates with, the unshipped project-kind proposal using that number. +Artifact revisions use regular stored event kind **45010**. Each revision is a complete snapshot, not a field patch. Common tags have exactly two string elements. Required tags occur exactly once; optional tags at most once. Duplicate common tags are invalid even if their values agree. The relay MUST reject more than 256 total tags per revision, including common and -unknown tags. This is a new artifact-specific bound; the advertised event-size -limit also applies. +unknown tags. The relay's advertised event-size limit also applies. | Tag | Count | Meaning | |-----|-------|---------| @@ -58,11 +47,11 @@ limit also applies. `content` is opaque UTF-8 to the relay, subject to the relay's advertised event size and rate limits. Type names are lowercase ASCII dot-separated components, each starting with a letter and otherwise containing letters, digits, `_`, or -`-`; total length is at most 128 bytes. `buzz.*` names are reserved by convention -for published Buzz contracts, not proof of trusted authorship. +`-`; total length is at most 128 bytes. `buzz.*` names are reserved by +convention for published Buzz contracts, not proof of trusted authorship. -Identity is `(community, d)`, independent of signer, type, and home. It is not a -NIP-01 addressable coordinate. The relay retains accepted revisions and an +Identity is `(community, d)`, independent of signer, type, and home. It is not +a NIP-01 addressable coordinate. The relay retains accepted revisions and an explicit current-head index; neither timestamps nor signer changes select a winner. `type` and `d` are immutable. A new business-schema version belongs in the content contract, not in a replacement artifact identity. @@ -72,13 +61,7 @@ confer authority. Business relationship tags are specified by clients, not resolved or validated by this NIP. Unsupported envelope versions are rejected. Missing `h` is a rejection, never a fallback to global visibility. -The existing canvas kind (40100) provides a channel-scoped, non-chat precedent; -see `required_scope_for_kind` and `requires_h_channel_scope` in -`crates/buzz-relay/src/handlers/ingest.rs`. Artifact implementation must explicitly -join that scoped class, not `is_global_only_kind`. Kind allocation alone does -not establish unread, quota, or fan-out behavior: implementation must audit and -test those paths. Artifacts remain subject to bounded storage/write quotas even -though they do not count as chat messages. +Artifacts remain subject to the relay's storage and write quotas. ## Conversations and multiple artifacts @@ -94,31 +77,26 @@ Replies use the conversation's existing protocol, not the latest artifact revision ID. An artifact revision is not a chat reply and MUST NOT increment reply counters, chat-message counts, or unread-chat state. -There is no exclusive slot, primary slot, or per-type singleton. Two tasks in -one thread are two records, not competing declarations of what the thread is. A -preferred card, pin, or dedicated workspace is a presentation choice, not -uniqueness or authority. Archiving one project MUST NOT archive its channel or -other artifacts in it. +Artifacts at the same location retain separate identities and revision chains. +Archiving an artifact MUST NOT archive its channel or other artifacts in it. ## Authorization and concurrency Channel read access controls artifact read access. Threads introduce no additional audience. This applies to direct-ID lookups, history, current state, search, counts, previews, exports, and live delivery, within the host-derived -community boundary. No title or relationship metadata may leak through errors or -unreadable search/count results. +community boundary. No title or relationship metadata may leak through errors +or unreadable search/count results. -The proposed generic write policy is **channel collaboration**. “Write -permission” means the same authorization that admits a kind-9 message in that -channel: channel membership of any role (including agents/Bot), or open -visibility, plus existing authentication, token-channel restrictions, -moderation, and archive gates. It is not a `MemberRole` threshold. Thus an -otherwise authorized community participant may create/edit in an open channel -without first joining it. “Administration” means Admin/Owner channel authority -under existing channel checks. Artifact writes require `Scope::ChannelsWrite`, -matching canvas, plus the operation-specific channel checks below. Clients and -agent tokens must request that scope; a numeric member-role threshold must not -exclude agents. +“Write permission” means the same authorization that admits a kind-9 message in +that channel: channel membership of any role (including agents/Bot), or open +visibility, plus authentication, token-channel restrictions, moderation, and +archive gates. An otherwise authorized community participant may create/edit in +an open channel without first joining it. “Administration” means Admin/Owner +channel authority under channel authorization rules. Artifact writes require +`Scope::ChannelsWrite` plus the operation-specific channel checks below. +Clients and agent tokens must request that scope; a numeric member-role +threshold must not exclude agents. | Operation | Required authority at commit time | |-----------|------------------------------------| @@ -127,36 +105,34 @@ exclude agents. | Delete | Administration in current home; in a DM, participant write permission | | Move to another channel | Write permission in source AND destination | -Being an artifact's creator is attribution, not a permanent exclusive editing -right. A reader without write permission cannot edit. Removed members lose -write permission in private channels even if they created the record; an open -channel still follows the open-channel admission rule above. These rules do not vary by -`type` and do not introduce per-artifact access lists or plugin-defined rules. -Existing authenticated-agent/channel authorization applies; provenance alone -must not create a new grant. Signed authorship remains the actual event signer. +Authorization is independent of the artifact's creator. A reader without write +permission cannot edit. Removed members lose write permission in private +channels even if they created the record; an open channel still follows the +open-channel admission rule above. These rules do not vary by `type`. +Authenticated-agent/channel authorization applies; provenance alone must not +create a new grant. Signed authorship remains the actual event signer. -Creation uses `op=create`, no `prev`, and an unused `d`. All subsequent operations -must name the current accepted head in `prev`. Ordinary updates and deletion -must keep `h`; only `move` may change it. A move must actually change channels. -`op` MUST agree with these structural constraints; it cannot disguise a move as -an update or an update as a new creation. -The relay checks permission, previous head, envelope, and anchor, then stores -the event and advances the head in one transaction. Two writes against the -same head cannot both succeed. Knowing `prev` is not edit authorization. -On conflict, clients must refetch the current accessible head and reconcile -their intended change, not blindly retry or silently overwrite newer state. Retrying an accepted event ID is idempotent; -permission to retrieve its contents is still checked. +Creation uses `op=create`, no `prev`, and an unused `d`. All subsequent +operations must name the current accepted head in `prev`. Ordinary updates and +deletion must keep `h`; only `move` may change it. A move must actually change +channels. `op` MUST agree with these structural constraints; it cannot disguise +a move as an update or an update as a new creation. The relay checks +permission, previous head, envelope, and anchor, then stores the event and +advances the head in one transaction. Two writes against the same head cannot +both succeed. Knowing `prev` is not edit authorization. On conflict, clients +must refetch the current accessible head and reconcile their intended change, +not blindly retry or silently overwrite newer state. Retrying an accepted event +ID is idempotent; permission to retrieve its contents is still checked. Rejected writes never enter history, search, or live delivery. Error responses -must not reveal an inaccessible current head or destination. The relay MUST reject NIP-09 -kind-5 requests targeting artifact revisions, with an explicit reason such as -`invalid: use artifact delete operation`; it must not report successful deletion -or release an artifact identity through that path. +must not reveal an inaccessible current head or destination. The relay MUST +reject NIP-09 kind-5 requests targeting artifact revisions, with an explicit +reason such as `invalid: use artifact delete operation`; it must not report +successful deletion or release an artifact identity through that path. Deletion is a terminal tombstone on the same identity, with empty content. -Delete events permit only the common envelope tags and the existing validated +Delete events permit only the common envelope tags and validated authentication/provenance tags (such as NIP-OA `auth`), not annotation tags. -This generic allowlist removes relationships without recognizing business types. Its type, `h`, `root`, and title must equal the head it deletes; deletion must not rename or relocate it. Its type and last title remain under its home permissions for an unavailable/deleted display. It is absent from active lists; @@ -164,6 +140,14 @@ subscribers receive a removal. Retained history follows retention/moderation policy; deletion is not a promise to erase downloaded copies. A deleted `d` is never reused. Business completion/archive is not deletion. +### Direct messages + +A DM channel is a valid home. Artifacts inherit its participant access rules. +DM participants are peers: deleting an artifact in a DM requires participant +write permission rather than an Admin/Owner role. The relay MUST determine +channel type from the stored channel, not an artifact tag. This rule applies to +every artifact type. + ## Moving and audience changes Moving preserves identity and publishes a complete current snapshot into the @@ -173,43 +157,39 @@ relationship labels, attachments, and any private material copied into content. A reference does not automatically authorize copying its resolved contents. The move revision is scoped to the destination. Its anchor must be absent or -belong to that destination; the old conversation does not move with it. **Moving -an artifact moves zero conversation messages.** Prior revisions stay under the -visibility of the channel in which each was published. A destination-only reader -can load the current snapshot without reading the old chain. A source-only -reader retains access to permitted source history, not later destination -revisions. Moves cannot revoke previously learned data. +belong to that destination; the old conversation does not move with it. +**Moving an artifact moves zero conversation messages.** Prior revisions stay +under the visibility of the channel in which each was published. A +destination-only reader can load the current snapshot without reading the old +chain. A source-only reader retains access to permitted source history, not +later destination revisions. Moves cannot revoke previously learned data. -One commit must advance the single head and durably record changes for both -scopes: removal/invalidation in the source and arrival in the destination. These -are two scoped change records, not one signed event pretending to have two `h` -values. The destination carries the client-signed revision; the source uses a -relay-authenticated invalidation in the platform sync change envelope. That -envelope must bind community, source scope, artifact identity, and replay -position, with no destination payload. If transported as a Nostr event instead, -it requires a separately allocated relay-only sidecar kind and rejection of -client-authored substitutes. Its wire schema is a sync-integration release gate, -not an already allocated part of kind 45010. Publication must be retryable after -a crash. The source removal must not contain the destination channel, title, or -payload; a forward link may resolve only with the requesting reader's -destination permissions. Concurrent edits/moves cannot create two active copies. -Moving back to a former home still uses the one current head. +One transaction MUST advance the current head and durably record removal from +the source scope and arrival in the destination scope. The destination carries +the client-signed revision. The source receives a separate relay-authenticated +invalidation that binds community, source scope, artifact identity, and replay +position. The invalidation MUST NOT contain the destination channel, title, or +payload. Clients MUST reject invalidations that lack relay authentication. + +Publication of both changes MUST be retryable after a crash. A forward link may +resolve only with the requesting reader's destination permissions. Concurrent +edits and moves MUST preserve a single current head. Moving back to a former +home uses that same head and identity. Channel membership and open/private visibility changes are also audience -changes: artifact access follows channel policy, rather than being frozen to the -membership at creation. Every subsequent read and delivery must honor the new -access policy; clients must invalidate cached views when access is revoked. +changes: artifact access follows channel policy, rather than being frozen to +the membership at creation. Every subsequent read and delivery must honor the +new access policy; clients must invalidate cached views when access is revoked. Offline copies cannot be recalled; UI must not promise otherwise. ## Current state, history, and sync -Use the generic signed-event ingestion path, not artifact-specific CRUD APIs. -Artifact changes belong in channel/thread sync alongside other scoped changes, -but **applied updates and human read positions are different state**. Receiving -an update neither marks conversation read nor necessarily notifies someone. -Explicit notification policy may call attention to meaningful changes. Clients -MUST NOT add the artifact kind to conversational-unread kind sets; rendering a -card alongside `root` is a separate presentation decision. +Revisions are submitted through signed Nostr event ingestion. Artifact changes +belong in channel/thread sync alongside other scoped changes, but **applied +updates and human read positions are different state**. Receiving an update +neither marks conversation read nor necessarily notifies someone. Explicit +notification policy may call attention to meaningful changes. Clients MUST NOT +count artifact revisions as unread conversation messages. A compliant implementation must offer: @@ -227,17 +207,18 @@ A compliant implementation must offer: must not require opening every thread. Channel visibility still gates results. Multi-character tag filters are a Buzz extension, not portable NIP-01 behavior. -Unsupported predicates must be rejected, never silently ignored. `EOSE` is not a -durable applied checkpoint. A cursor must identify its covered stream/filter; a -filtered result cannot stand in for a complete channel checkpoint. +Unsupported predicates must be rejected, never silently ignored. `EOSE` is not +a durable applied checkpoint. A cursor must identify its covered stream/filter; +a filtered result cannot stand in for a complete channel checkpoint. -**Implementation boundary:** this draft specifies those observable guarantees, -not a second sync protocol. The current-state query mode, snapshot/checkpoint -wire shape, move-removal delivery, and expired-cursor/reset response must be -bound to the platform sync specification before implementing or advertising NIP- -AR support. Ordinary timestamp-sorted `REQ` history alone does not satisfy this -contract. Until move delivery is supported, relays must reject `move`, not -approximate it as independent delete/create writes. +### Sync transport requirements + +A relay advertising support MUST provide a sync transport that satisfies the +current-state, replay, reset, and invalidation requirements above. This NIP +defines their required semantics; the transport's wire format is specified +separately. A relay MUST reject `move` until it supports atomic head +advancement and durable delivery to both scopes. Independent delete/create +writes do not satisfy move semantics. ## Client types and privileged operations @@ -247,39 +228,34 @@ validate before interpreting business fields; unsupported or malformed content falls back to a safe card. Render title/type as untrusted text, not executable markup. A type namespace is not a publisher identity or installed capability. -Unknown versions must not be edited destructively. Editors must preserve unknown -content fields and annotation tags when safe, or decline editing that version. -Relations may be missing, inaccessible, deleted, self-referential, or cyclic. -Traversals must be bounded and fail visibly without crashing. +Unknown versions must not be edited destructively. Editors must preserve +unknown content fields and annotation tags when safe, or decline editing that +version. Relations may be missing, inaccessible, deleted, self-referential, or +cyclic. Traversals must be bounded and fail visibly without crashing. Links and payloads cannot authorize push, merge, membership changes, payments, or another privileged action. Those actions require their own trusted service checks. A client-observed status is not a relay-certified operational fact. -## Existing Git and project objects +## Interoperability -This proposal does not create a second Git repository or replace NIP-34 -identity. Repository announcements (30617), ref state (30618), reviews, patches, -and their statuses remain their existing protocol objects. Branch artifacts -describe collaboration around a ref, not authoritative Git state. +NIP-34 repository announcements (30617), ref state (30618), reviews, patches, +and statuses retain their identities and access rules. An artifact referencing +one of these objects MUST NOT alter its access policy or confer Git authority. +Branch artifacts describe collaboration around a ref; Git state is obtained +from the referenced repository under its own access checks. -**Legacy exception, not completed consolidation:** existing global -project/issue/ repository objects do not acquire private channel reads or -channel sync simply because they contain `buzz-channel`. A push binding alone is -insufficient. NIP-34 read, search, clone/fetch, preview, and live-delivery -scoping require a separate coordinated migration before promising private -repository workspaces. This draft does not tighten or widen existing Git access -as a side effect. +A project event (30621) or issue event (1621) is not an artifact revision. A +`buzz-channel` tag on another event kind does not apply this NIP's access or +revision rules to it. Conversion between representations requires an explicit +identity mapping and an authoritative current record; it MUST NOT create two +independently writable representations of the same record. Conversion MUST +preserve references and ownership information, and MUST NOT change access +without authorization. -Existing 30621 projects and 1621 issues must not be dual-written as competing -new artifacts. Migration requires an explicit canonical mapping and cutover, -retaining old links, ownership information, and existing access until changed -through an authorized migration. Previously published data cannot be made secret -retroactively. No automatic conversion is specified here. +## Conformance scenarios -## Acceptance scenarios - -These are implementation requirements, not tests claimed to pass in this PR. +Implementations MUST satisfy the following scenarios. | Scenario | Required result | |----------|-----------------| @@ -300,21 +276,3 @@ These are implementation requirements, not tests claimed to pass in this PR. | Reconnect after deletion or filter exit | No ghost current records | | Background revision arrives | State updates; chat unread/read position unchanged | | Generic repository tag on a task | No push, clone, review, or membership capability gained | - -## Non-goals and naming - -No per-artifact audience lists, relay-executed plugins, schema-registration -service, generic automation engine, or one-record-per-room requirement. Existing Buzz DMs are channels: an artifact with their `h` inherits participant -access just like their messages (see `handle_dm_open` in -`crates/buzz-relay/src/handlers/command_executor.rs`). This is not a new DM ACL. -DM participants are peers (existing DM creation assigns `member` to all), so -artifact deletion in a DM requires participant write permission instead of an -Admin/Owner role. The relay must determine DM type from the stored channel, -never an artifact tag. This channel-type rule does not vary by artifact type. -Personal/no-room artifacts need a separately specified scope; missing `h` must not become an accidental -global/private mode. - -“Artifact” is the protocol/design term. User interfaces should usually say -“task,” “project,” or the specific type name. “Work item” sounds task-specific; -“card” describes a presentation. Neither is a better common identity name. -Build-output artifacts/files remain distinct from these editable records. \ No newline at end of file