Repository navigation
AIDA-2393: Allow owners to delete agent workflows - #2281
Conversation
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Carl, an automated reviewer, commenting via Wes's GitHub account.
No blocking code defects found; merge remains conditional on relay compatibility and acceptance.
The signing-boundary change holds. On relay main (fa7a3bfbda), validate_standard_deletion_event authorizes a-tag deletes only for the target author or the community's recorded agent owner, and admins get no extra authority. Both hosts still require exactly one canonical workflow a target before the first-tag exemption applies. Delete permission comes from a verified NIP-OA attestation, and edit, enable and run stay author-only.
Before merge:
- Confirm the production relay includes block/buzz#7735, or keep this feature off until it does. On an older relay, a "deleted" workflow may keep firing on its schedule. That is a correctness gate for a destructive operation, and the confirm text ("Work already running may continue") understates it.
- The description says this stays draft pending human native-app acceptance, but the PR is marked ready. Please return it to draft until the repository's acceptance checklist is complete, then record the evidence and add
buzz-review-completed.
Optional: the empty state still says "Workflows you own appear here" (WorkflowLanding.tsx:1668). Owning an agent now lets you delete its workflows, but they don't appear in that filter, so "Workflows you authored…" would be clearer.
Validation: source review at 6bceae828 plus green hosted CI. No local suites or live relay writes were run.
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Automated review at fff32730: no blocking findings.
I checked who can get a workflow delete signed:
- Ownership proof: the delete permission accepts the workflow's author, or the human whose ownership of that author the app has cryptographically verified (
profiles.owner, set only afterattestedOwnerverifies the agent's current signed profile). Ownership claims in display metadata don't count. - Checks along the way: the app checks the permission when it builds the command, before signing, and again in the synchronous publish step.
validateWorkflowEventstill allows exactly oneh, one canonical30620:<author>:<uuid>atag, an optionalclient-id, and empty content. - Signing hosts: they now let a correctly formed workflow delete targeting another author be signed. In
src-tauri/src/relay.rsthe exemption is reached only aftervalidate_workflow_template, and the other two kind-5 shapes it accepts can't carry a30620coordinate. So the hosts are shape gates, and the relay is the ownership gate. On relay main,validate_standard_deletion_eventaccepts ana-tag delete only from the target's author or recorded agent owner. - Guest guard: the new branch only exempts a kind-5 workflow delete the viewer may delete. Guests' ordinary posts are still refused.
- Recovery: a kept delete must still be signed by the viewer and sit in an accessible channel. Restored entries come back as unknown, not resent.
- Unchanged: edit, enable and run still require the viewer to be the author.
A live run against a local relay built from current main also passed:
- An owner deleted their agent's workflow, signed with the owner's own key, and a fresh read showed it gone.
- An unowned agent's workflow was refused before signing. A hand-built signed delete for it was rejected by the relay (
deletion target not found or not deletable by you). - A plain channel member couldn't delete.
- Edit, enable/disable and run stayed refused for the owner of the agent.
- A Guest could delete their own agent's workflow but still couldn't post a message.
- The deleted workflows' rows were removed from the executable
workflowstable; the untouched one remained.
One note for the description: the relay's recorded agent owner is first-write-wins and isn't cleared. Removing the owner attestation from an agent's profile takes away the app's local permission, but not the relay's.
Small items:
src/bundled/workflows/useWorkflowCanDelete.ts:14re-renders only when profiles change (permissions.subscribeis the profile subscription).canDeletealso depends on channel access and on the session being open, so losing channel access leaves Delete enabled until something else re-renders. The delete still fails safely, but it ends in the silent no-op already raised inline atWorkflowLanding.tsx:899.docs/workflows.md:34: the edited line is 114 columns among lines wrapped at about 80. Rewrap it.
Also still open from the earlier automated review at this head:
- The silent return when permission is lost with the confirm dialog open (
WorkflowLanding.tsx:899,WorkflowsPage.tsx:174-178,WorkflowChannel.tsx:237-246). - Delete disabled with no stated reason (
WorkflowLanding.tsx:682). - The empty state still reads "Workflows you own appear here" (
WorkflowLanding.tsx:1668). - The production relay needs block/buzz#7735 before this ships.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account, with independent Rocket, Mantis and Groot coverage.
No new code defects found in the Guest-deletion follow-up from 6bceae8284d3ebccf982ccb36427cbbf05914790 to fff32730792c38901c5445fef27090cba53b5037 (PR base 30502bccc12cc6959618079b85d4f0d64ed32b02).
The new Guest exception is limited to workflow-coordinate deletions allowed by the existing verified-owner permission. Full canonical command validation still runs before signing and in the synchronous check immediately before publisher entry, including after asynchronous signing. The added session tests cover member/Guest deletion, malformed and foreign targets, ordinary Guest contributions, and ownership/membership revocation during signing. These are source observations; we did not execute the tests.
The prior review is not cleared by this follow-up: the previously reported silent permission-loss path remains unchanged, and production relay compatibility plus human native-app acceptance remain unverified. Existing comments remain the action locations; no duplicate inline findings added.
Validation: source-only review of the follow-up, relevant permission/publish/recovery callers and existing UI error/retry/focus paths. One hosted-check snapshot showed 39 successful checks and two skipped checks, including Windows native validation. No local tests, app launch, relay writes or production checks. The public PR description and commit text were inspected; there are no attached images. The linked issue could not be read (403), so its contents were not verified. This COMMENT is not approval or a merge-readiness claim.
|
🤖 Review follow-up in 48e5765 also updates the My workflows empty state to “authored,” rewraps the workflow docs, and distinguishes local proof revocation from the relay’s retained first-write-wins owner record. Production relay #7735 deployment and human native-app acceptance remain unverified and are explicit release gates in the description. I preserved the PR’s existing ready state and have not added buzz-review-completed. |
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 One required browser-contract mismatch remains at this head.
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account, with independent Rocket, Mantis and Groot coverage.
No new actionable code findings in the follow-up from fff32730792c38901c5445fef27090cba53b5037 to 6ca11ed2c3ff5796b4ff7b2635a475963f352d17 (base ec09a37b480596f80eb5b181b666a7222ed28766).
The previously reported silent permission-loss path is addressed: confirmation now reports refusal without submitting a deletion, and the editor retains its draft when permission is lost. Delete permission subscribes to access/session changes as well as profile changes. Disabled actions explain the ownership requirement through the shared MenuNote, and the read-only journey now checks the menu’s keyboard and description contract. The merge preserves the verified-owner/Guest checks before signing and immediately before publication. These are source observations; tests were inspected, not executed.
The existing release conditions remain unresolved: confirm the target relay includes block/buzz#7735 and obtain human native-app acceptance. This review does not clear those conditions or establish merge readiness. A hosted-check snapshot showed CI required failing, with Chromium 2/9 and WebKit 3/14 failing; their causes were not diagnosed in this source-only cycle. Windows native validation was skipped.
Validation limits: no local tests, app launch, relay writes or production verification. Refusal-path focus restoration, assistive-technology announcements and rendered behavior remain unverified. The public description and feature commit text were inspected; no attached images. The linked Linear issue returned only its application shell, so its contents were not verified. This is a COMMENT, not approval.
6ca11ed to
3928a56
Compare
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account, with independent Rocket, Mantis and Groot coverage.
No new actionable findings in the rebase follow-up from 6ca11ed to 3928a56 (base 9c94152).
The feature diff is identical after removing Git object IDs and hunk offsets. We checked integration with the new workflow mention provider, profile retention and session read-state changes. The verified-owner and Guest deletion checks, final pre-publication recheck, recovery tracking, refusal messages and retained editor draft on permission loss remain intact. The earlier silent-refusal finding remains addressed.
The existing release conditions still apply: verify the target relay includes block/buzz#7735 and obtain human native-app acceptance. This source review does not clear those conditions or establish merge readiness.
Validation: one hosted-check snapshot showed all executed checks successful, including CI required; Windows native validation and the unselected browser flake lane were skipped. No local tests, builds, app execution or relay writes were performed. Runtime focus restoration, accessibility and deployment compatibility remain unverified. The public description and four feature commit messages were inspected; no attached images or new concrete privacy findings. The linked Linear issue returned only its application shell, so its contents were not verified. This is a COMMENT, not approval.
Permit verified human owners to delete agent-authored workflows while preserving author-only editing and execution. Keep deletion recovery visible across ownership changes. Co-authored-by: BuzzPRReviewAssistant1 <a581a7e8115222acdc32ffb14bfce55d48c24478d98e155f8eba126b69b83c7b@buzz.block.builderlab.xyz> Signed-off-by: Ravneet Arora <rarora@squareup.com>
Align the session Guest guard with workflow deletion permission and exercise real session/outbox signing, publication and revocation boundaries. Co-authored-by: BuzzPRReviewAssistant1 <a581a7e8115222acdc32ffb14bfce55d48c24478d98e155f8eba126b69b83c7b@buzz.block.builderlab.xyz> Signed-off-by: Ravneet Arora <rarora@squareup.com>
Refresh delete permission on access and session changes. Show confirmation-time refusal through existing error surfaces and explain unavailable deletion actions. Co-authored-by: BuzzPRReviewAssistant1 <a581a7e8115222acdc32ffb14bfce55d48c24478d98e155f8eba126b69b83c7b@buzz.block.builderlab.xyz> Signed-off-by: Ravneet Arora <rarora@squareup.com>
Check disabled Delete and its ownership explanation while retaining read-only keyboard and focus coverage. Co-authored-by: BuzzPRReviewAssistant1 <a581a7e8115222acdc32ffb14bfce55d48c24478d98e155f8eba126b69b83c7b@buzz.block.builderlab.xyz> Signed-off-by: Ravneet Arora <rarora@squareup.com>
3928a56 to
6d323d1
Compare
|
🤖 Completed the review-comment audit and rebase at 6d323d1. All four inline threads are resolved: confirmation-time permission loss, the disabled Delete explanation, the read-only keyboard journey, and the Guest channel-gate finding that the reviewer withdrew after independent WebSocket verification. Reactive permission updates, the authored empty-state copy, wrapped docs and relay-owner-record clarification are present. No additional product change was needed. The preceding head 3928a56 passed all 41 executed hosted checks, including CI required. This rebase onto main b621738 preserves identical feature patches. Local verification passed: TypeScript, 122 workflow regression tests, 16 browser-host broker tests and 72 browser checks in Chromium/WebKit. The initial concurrent unit run had two editor-test timeouts; the complete five-file serial rerun passed unchanged. Design, Clippy and machine-policy checks passed; the broad affected-unit lane remains excluded under the author’s prior instruction. Fresh CI currently has four inspected jobs that failed before tests on HTTP 504 while downloading pnpm from GitHub Releases. I attempted reruns; GitHub rejected them because the workflow was still running. Failed jobs need rerunning once that run finishes; no hosted-green claim is made for this head. The description now separates the remaining merge requirements from completed code work: verify production relay #7735 inclusion and obtain human native-app acceptance. Neither is attested by this comment. |
wesbillman
left a comment
There was a problem hiding this comment.
🤖 Star Lord’s automated source review via Wes’s account, with independent Rocket, Mantis and Groot coverage.
No new actionable findings in the rebase follow-up from 3928a56864ffe29298e1d5722e059f57366308d5 to 6d323d1a41f931cf6447d9caffa038097d95d898 (base b621738454064985fe42de0c077e8d381ca0037b).
The workflow feature patch is unchanged after removing object IDs and hunk offsets. We checked integration with the inherited channel /leave command and browser-test changes. The workflow permission checks before signing and publication, deletion receipt/readback ownership, and confirmation-time refusal with editor draft retention remain intact. The help changes occupy separate sections.
Existing release conditions still apply: confirm the target relay includes block/buzz#7735 and obtain human native-app acceptance. This review does not establish deployment compatibility or merge readiness.
Validation: source only. One hosted-check snapshot showed 28 successful, 11 failed and two skipped checks, including failing CI required; failure causes were not independently diagnosed in this cycle. No local tests, builds, app execution or relay writes. Runtime focus restoration, accessibility and human acceptance remain unverified. The public PR description and four feature commit messages were inspected; no attached images or new concrete privacy findings. The linked Linear issue returned only its application shell, so its contents were not verified. This is a COMMENT, not approval.
kalvinnchau
left a comment
There was a problem hiding this comment.
🤖 Approved at 6d323d1. The ownership-loss confirmation defect is fixed; no blocking source findings remain. Nonblocking P3: consider sharing the duplicated refusal messages. Target-relay compatibility (#7735) and human native acceptance remain required before merge/ship. The uncertain-deletion notice still disappears after reload despite journal persistence; attribution to this change is unproven.
| if (definition.owner !== viewer || !capability.availability.delete) return; | ||
| deleting.current = true; | ||
| try { | ||
| if (!capability.permissions.canDelete(definition)) |
There was a problem hiding this comment.
🤖 [P3, nonblocking] The permission-loss and unavailable messages are duplicated in WorkflowChannel.tsx:258. Consider shared constants so future wording changes remain consistent across grid and editor refusal paths.
…-service * origin/main: fix(communities): find self-hosted relays that predate host-bound NIP-11 (#2653) Run native Claude on remote execution targets (#2559) Add Narrow and Wide message width in Appearance (#2472) AIDA-2393: Allow owners to delete agent workflows (#2281) # Conflicts: # src/bundled/claude-code/runtime.ts
When the relay refused a workflow save, run or delete, or a custom emoji
add or remove, Buzz replaced its reason with fixed copy ("Workflow command
rejected; retain the draft…", "Failed to add emoji."). A member who adds a
Call Webhook step was never told that the step needs owner or admin, and a
timed-out member could not tell when to try again.
The relay's text is shown only for a real refusal: a PublishRejected that
is not a PublishNotSent. Timeouts, lost receipts, signer mismatches,
client-side checks and not-sent errors keep today's copy.
- transport: `forbidden:` joins the relay-shaped prefixes. The signed
writer's keep-filter dropped a 400 `{error:"forbidden: …"}` body, so the
reason arrived as "Relay rejected the message (400)". This also fixes
Hide conversation's "forbidden: not a member of this DM".
- outbox: onReceipt gains an optional `refusal` argument with the clipped
display text. The journaled error is unchanged: relay text can quote
event content, so it never reaches the journal.
- workflows capability: receipt() keeps the refusal as an in-memory
rejected result, so Recent activity shows the relay's words for this
session. After a reload the journal's fixed copy is the fallback.
- session.ts (FOUNDATION, approved for this one-line change): forward the
refusal to workflows.receipt.
- emoji directory: a refusal reads "Failed to add emoji. <reason>" (or the
remove equivalent). Timeouts and failed own-set reads are unchanged.
- docs: workflows.md and relay-queries.md describe the new behavior.
Built on main @ b621738. None of the touched lines changed since the
design note's 9c94152, and #2085, #2306 and #2281 have not landed, so
nothing needed adapting.
Not changed here:
- Browser host: the broker answers a socket `forbidden:`/`blocked:`/
`restricted:` refusal with 503 `sent:false`, which the client treats as
PublishNotSent, so those keep fixed copy there. `invalid:` refusals
arrive as 400 and show their reason.
- A stale save's 409 now shows the client's own "conflict: the relay
state changed; reload before writing again" instead of the fixed
workflow copy.
- The 200 `{accepted:false}` path still shows the raw prefixed text.
Tests: a `forbidden:` row in transport.test.ts; refusal and not-sent cases
in capability.test.ts through the real outbox, with saved() checked for
relay text; the refusal forward in outbox-receipts.test.ts; exact emoji
add/remove refusal copy and a not-sent case in emoji.test.ts and
CustomEmojiSettings.test.tsx; workflows.journey.mjs now expects the
fixture's refusal text. Each new or tightened assertion fails without the
production change. The journey fails without the session.ts forward.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mtoohey <mtoohey@squareup.com>
When the relay refused a workflow save, run or delete, or a custom emoji
add or remove, Buzz replaced its reason with fixed copy ("Workflow command
rejected; retain the draft…", "Failed to add emoji."). A member who adds a
Call Webhook step was never told that the step needs owner or admin, and a
timed-out member could not tell when to try again.
The relay's text is shown only for a real refusal: a PublishRejected that
is not a PublishNotSent. Timeouts, lost receipts, signer mismatches,
client-side checks and not-sent errors keep today's copy.
- transport: `forbidden:` joins the relay-shaped prefixes. The signed
writer's keep-filter dropped a 400 `{error:"forbidden: …"}` body, so the
reason arrived as "Relay rejected the message (400)". This also fixes
Hide conversation's "forbidden: not a member of this DM".
- outbox: onReceipt gains an optional `refusal` argument with the clipped
display text. The journaled error is unchanged: relay text can quote
event content, so it never reaches the journal.
- workflows capability: receipt() keeps the refusal as an in-memory
rejected result, so Recent activity shows the relay's words for this
session. After a reload the journal's fixed copy is the fallback.
- session.ts (FOUNDATION, approved for this one-line change): forward the
refusal to workflows.receipt.
- emoji directory: a refusal reads "Failed to add emoji. <reason>" (or the
remove equivalent). Timeouts and failed own-set reads are unchanged.
- docs: workflows.md and relay-queries.md describe the new behavior.
Built on main @ b621738. None of the touched lines changed since the
design note's 9c94152, and #2085, #2306 and #2281 have not landed, so
nothing needed adapting.
Not changed here:
- Browser host: the broker answers a socket `forbidden:`/`blocked:`/
`restricted:` refusal with 503 `sent:false`, which the client treats as
PublishNotSent, so those keep fixed copy there. `invalid:` refusals
arrive as 400 and show their reason.
- A stale save's 409 now shows the client's own "conflict: the relay
state changed; reload before writing again" instead of the fixed
workflow copy.
- The 200 `{accepted:false}` path still shows the raw prefixed text.
Tests: a `forbidden:` row in transport.test.ts; refusal and not-sent cases
in capability.test.ts through the real outbox, with saved() checked for
relay text; the refusal forward in outbox-receipts.test.ts; exact emoji
add/remove refusal copy and a not-sent case in emoji.test.ts and
CustomEmojiSettings.test.tsx; workflows.journey.mjs now expects the
fixture's refusal text. Each new or tightened assertion fails without the
production change. The journey fails without the session.ts forward.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mtoohey <mtoohey@squareup.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
When the relay refused a workflow save, run or delete, or a custom emoji
add or remove, Buzz replaced its reason with fixed copy ("Workflow command
rejected; retain the draft…", "Failed to add emoji."). A member who adds a
Call Webhook step was never told that the step needs owner or admin, and a
timed-out member could not tell when to try again.
The relay's text is shown only for a real refusal: a PublishRejected that
is not a PublishNotSent. Timeouts, lost receipts, signer mismatches,
client-side checks and not-sent errors keep today's copy.
- transport: `forbidden:` joins the relay-shaped prefixes. The signed
writer's keep-filter dropped a 400 `{error:"forbidden: …"}` body, so the
reason arrived as "Relay rejected the message (400)". This also fixes
Hide conversation's "forbidden: not a member of this DM".
- outbox: onReceipt gains an optional `refusal` argument with the clipped
display text. The journaled error is unchanged: relay text can quote
event content, so it never reaches the journal.
- workflows capability: receipt() keeps the refusal as an in-memory
rejected result, so Recent activity shows the relay's words for this
session. After a reload the journal's fixed copy is the fallback.
- session.ts (FOUNDATION, approved for this one-line change): forward the
refusal to workflows.receipt.
- emoji directory: a refusal reads "Failed to add emoji. <reason>" (or the
remove equivalent). Timeouts and failed own-set reads are unchanged.
- docs: workflows.md and relay-queries.md describe the new behavior.
Built on main @ b621738. None of the touched lines changed since the
design note's 9c94152, and #2085, #2306 and #2281 have not landed, so
nothing needed adapting.
Not changed here:
- Browser host: the broker answers a socket `forbidden:`/`blocked:`/
`restricted:` refusal with 503 `sent:false`, which the client treats as
PublishNotSent, so those keep fixed copy there. `invalid:` refusals
arrive as 400 and show their reason.
- A stale save's 409 now shows the client's own "conflict: the relay
state changed; reload before writing again" instead of the fixed
workflow copy.
- The 200 `{accepted:false}` path still shows the raw prefixed text.
Tests: a `forbidden:` row in transport.test.ts; refusal and not-sent cases
in capability.test.ts through the real outbox, with saved() checked for
relay text; the refusal forward in outbox-receipts.test.ts; exact emoji
add/remove refusal copy and a not-sent case in emoji.test.ts and
CustomEmojiSettings.test.tsx; workflows.journey.mjs now expects the
fixture's refusal text. Each new or tightened assertion fails without the
production change. The journey fails without the session.ts forward.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mtoohey <mtoohey@squareup.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
When the relay refused a workflow save, run or delete, or a custom emoji
add or remove, Buzz replaced its reason with fixed copy ("Workflow command
rejected; retain the draft…", "Failed to add emoji."). A member who adds a
Call Webhook step was never told that the step needs owner or admin, and a
timed-out member could not tell when to try again.
The relay's text is shown only for a real refusal: a PublishRejected that
is not a PublishNotSent. Timeouts, lost receipts, signer mismatches,
client-side checks and not-sent errors keep today's copy.
- transport: `forbidden:` joins the relay-shaped prefixes. The signed
writer's keep-filter dropped a 400 `{error:"forbidden: …"}` body, so the
reason arrived as "Relay rejected the message (400)". This also fixes
Hide conversation's "forbidden: not a member of this DM".
- outbox: onReceipt gains an optional `refusal` argument with the clipped
display text. The journaled error is unchanged: relay text can quote
event content, so it never reaches the journal.
- workflows capability: receipt() keeps the refusal as an in-memory
rejected result, so Recent activity shows the relay's words for this
session. After a reload the journal's fixed copy is the fallback.
- session.ts (FOUNDATION, approved for this one-line change): forward the
refusal to workflows.receipt.
- emoji directory: a refusal reads "Failed to add emoji. <reason>" (or the
remove equivalent). Timeouts and failed own-set reads are unchanged.
- docs: workflows.md and relay-queries.md describe the new behavior.
Built on main @ b621738. None of the touched lines changed since the
design note's 9c94152, and #2085, #2306 and #2281 have not landed, so
nothing needed adapting.
Not changed here:
- Browser host: the broker answers a socket `forbidden:`/`blocked:`/
`restricted:` refusal with 503 `sent:false`, which the client treats as
PublishNotSent, so those keep fixed copy there. `invalid:` refusals
arrive as 400 and show their reason.
- A stale save's 409 now shows the client's own "conflict: the relay
state changed; reload before writing again" instead of the fixed
workflow copy.
- The 200 `{accepted:false}` path still shows the raw prefixed text.
Tests: a `forbidden:` row in transport.test.ts; refusal and not-sent cases
in capability.test.ts through the real outbox, with saved() checked for
relay text; the refusal forward in outbox-receipts.test.ts; exact emoji
add/remove refusal copy and a not-sent case in emoji.test.ts and
CustomEmojiSettings.test.tsx; workflows.journey.mjs now expects the
fixture's refusal text. Each new or tightened assertion fails without the
production change. The journey fails without the session.ts forward.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: mtoohey <mtoohey@squareup.com>
Signed-off-by: Matt Toohey <contact@matttoohey.com>
Why
People cannot delete workflows created by agents they own, leaving obsolete scheduled automation outside their control. Fixes AIDA-2393.
What
Allow a verified agent owner to delete the agent’s workflow using the human’s signing identity, including with the channel’s Guest role. Editing, enabling and running remain author-only. Find agent-authored workflows under Owner → All channel workflows.
How
Reuse cryptographically verified ownership through the UI, command validation and the final check before publication. Both signing hosts admit only canonical workflow deletes; the relay authorizes ownership. Keep uncertain deletions visible and recoverable without automatic replay.
Refresh permissions on profile, access and session changes. Report confirmation-time refusal through the existing error surfaces, retain the editor draft, and explain disabled Delete actions accessibly. The read-only browser journey checks the menu, explanation and keyboard focus behavior. No browser cases were added or removed.
Risk
This changes a destructive permission boundary. Do not merge or ship until the target relay is confirmed to include block/buzz#7735. Older relays may accept deletion without stopping scheduled execution. The deployed SHA remains unverified.
Removing profile ownership proof revokes app permission but does not clear the relay’s first-write-wins owner record. Guest deletion was confirmed against a local relay; the reviewer also independently verified WebSocket deletion and restart cleanup, then withdrew the channel-gate finding. This does not establish channel-scoped-token compatibility.
Testing
At the prior published head
3928a5686, all 41 executed hosted checks passed, including CI required; Windows native validation and the unselected browser flake lane were skipped. Main’s #2493 fixed the independent sidebar test failure.Rebased onto main
b62173845at6d323d1a4; all four feature patches are unchanged. Local TypeScript, 122 workflow regression tests, 16 browser-host broker tests, and 72 Chromium/WebKit browser checks passed. The initial concurrent unit run hit two editor-test timeouts; the complete five-file serial rerun passed with unchanged assertions and limits. No test cases, retries or timeouts were removed or relaxed.Design, Clippy and machine push-policy checks passed. The broad affected-unit pre-push lane remains excluded under the author’s earlier instruction; no full local unit pass is claimed. The first hosted attempt failed before tests in ten jobs because pnpm release downloads returned HTTP 504. All ten failure logs confirm that cause. After the run finished, a failed-jobs rerun was accepted and attempt 2 is in progress; the rebased head is not yet hosted-green.
Earlier real-session checks against local relay
d44031f41confirmed owner deletion, unrelated-user rejection, fresh definition removal and scheduled execution stopping. These checks do not verify the production deployment.Before merge
Human acceptance is unconfirmed. The existing PR ready state is preserved; this description does not attest merge readiness.
Generated with Codex