mirror of
https://github.com/block/buzz.git
synced 2026-11-05 00:41:28 +00:00
Keep authored intent in the scoped draft store independently of value deletion. Supersede recovery, sent cleanup and lifecycle persistence across reentry and remount while preserving ordinary destination-bound sends and untouched optimistic recovery. Keep editability and automatic prefix restoration programmatic. Exercise the real store, React lifecycle transition matrix and retained browser editor. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Signed-off-by: Logan Johnson <loganj@squareup.com> (cherry picked from commit ff140562c693147730d548582bc39a12d37ce210) Signed-off-by: Logan Johnson <loganj@squareup.com> (cherry picked from commit 4b99bc705ebb8a6920c114620360433556bf88f9) Signed-off-by: Logan Johnson <loganj@squareup.com>
84 lines
5.2 KiB
Markdown
84 lines
5.2 KiB
Markdown
# Remote mention preparation and publication
|
|
|
|
Owned relay agents can be selected and invited without local runtime custody.
|
|
The picker and preparation phase evaluate policy but may admit an owned
|
|
nonmember. Publication separately refreshes authorization for the exact eventual
|
|
destination, including a newly created DM. Ownership is not membership and
|
|
cached picker evidence is never publication authorization.
|
|
|
|
Selections are intent: a vanished/revoked key must fail visibly, retain the draft
|
|
and send nothing, rather than silently dropping a recipient. Captured agent keys
|
|
survive composer clearing, media upload, edits and asynchronous preparation.
|
|
A failed local inventory read cannot veto authenticated relay identities or
|
|
admit stale local runtimes. Locally managed runtime readiness remains a separate
|
|
existing path; remote identities never gain synthetic local management records.
|
|
|
|
Chat offers explicit Invite or reference-only send without inviting. Failed adds,
|
|
revoked policy, failed final authorization and cancellation preserve recoverable
|
|
drafts. Standalone forum sends report authorization failures, but standalone
|
|
forum invitation is a subsequent change reusing this phase contract.
|
|
|
|
Native discovery prerequisite: `docs/owned-agent-discovery.md` (PR6).
|
|
Regression coverage: `agentAutocompleteEligibility.test.mjs`,
|
|
`agentMentionRevalidation.test.mjs`, `useMentionSendFlow.helpers.test.mjs`,
|
|
`submitMessageEdit.test.mjs`, `mentions.spec.ts`, and
|
|
`remote-owned-mentions.spec.ts`. The new remote browser fixtures use a single-word
|
|
name deliberately: mention separator behavior belongs to the independent PR1.
|
|
|
|
NIP-OA establishes ownership, not physical hosting, availability, or lifecycle
|
|
control. Final native queries do not provide an atomic relay transaction with
|
|
message publication. Independent review of both native and publication boundaries
|
|
is required before landing.
|
|
|
|
## Invitation intent and cancellation
|
|
|
|
Each chat Invite owns one synchronous pending latch and abort signal, covering
|
|
preparation, inventory, adds and the eventual publication continuation. Escape,
|
|
navigation/unmount, reference-only selection or a replacement prompt invalidates
|
|
that attempt. Clearing the prompt when promoting it to send is not cancellation;
|
|
the signal remains live through final validation and queued media completion.
|
|
Check cancellation after asynchronous preparation and before subsequent mutations
|
|
(including nested local readiness), and again before publication. A completed add
|
|
cannot be undone, but its late response cannot revive cancelled message intent.
|
|
The pending state includes preparation, disabling both Invite and reference-only
|
|
buttons. Cancellation after optimistic clearing restores the captured draft and
|
|
exact mention refs without overwriting newer edits.
|
|
|
|
`useMentionSendFlow.cancellation.test.mjs` drives the actual hooks with React
|
|
StrictMode and deferred dependencies; `remote-owned-mentions.spec.ts` covers
|
|
visible pending, Escape/retry and route navigation at deferred IPC boundaries.
|
|
|
|
### Source draft ownership
|
|
|
|
Invitation intent belongs to one visit of the effective persistence key and
|
|
channel, not just the mounted composer or destination channel. Same-channel
|
|
thread changes and A → B → A invalidate the original visit. The visible owner gates
|
|
optimistic clear, editor recovery and pending state. Storage recovery instead
|
|
consults shared authored intent for the source draft key, even after exit,
|
|
re-entry or unmount. The draft store retains a revision and authoritative-empty
|
|
marker independently of the stored value. Later same-key authored text/deletion
|
|
or a new send revokes older recovery and sent-draft cleanup; editing B does not
|
|
change A's authority. A visit-specific accessor reads that shared authority while
|
|
preserving the separate visible-owner identity. Invalidation makes recovery durable
|
|
synchronously, before a later visit can load or edit the source draft; late async
|
|
completion cannot revive that recovery or release a newer attempt's latch.
|
|
|
|
The editor's authored revision distinguishes an intentional edit → clear from an
|
|
optimistic empty composer. Programmatic send clear/recovery runs inside the draft
|
|
lifecycle's restoration boundary, so it does not mark the source as authoritatively
|
|
deleted. Exact selected mention refs are captured before asynchronous preparation.
|
|
Persona preparation similarly consumes captured selections and returns resolved
|
|
refs, writing them into the editor only while the original visit/revision remains
|
|
current. Normal persona creation/reuse and ordinary destination-bound background
|
|
sends retain their existing behavior; accepted membership is never rolled back.
|
|
|
|
Recovery additionally compares stored content/media/exact refs before replacing
|
|
an existing record. Programmatic persistence does not itself change semantic
|
|
intent. Explicit inbox deletion and replacement do; scope reset invalidates old
|
|
handles. This is same-window authority for live continuations, not cross-window
|
|
synchronization or a versioned storage protocol. Reload destroys continuations;
|
|
authored deletion has already removed the durable value. Final membership/policy reads are not atomic with send,
|
|
and cancellation cannot retract an already dispatched publication. Standalone
|
|
forum transport-failure binding recovery and native compatibility remain separate
|
|
review/follow-up boundaries.
|