Add recoverable hosted community deletion - #403
TheSentinel454 wants to merge 16 commits into
Conversation
Signed-off-by: OpenAI Codex <codex@openai.com>
Signed-off-by: OpenAI Codex <codex@openai.com>
Signed-off-by: OpenAI Codex <codex@openai.com>
Signed-off-by: OpenAI Codex <codex@openai.com>
Signed-off-by: OpenAI Codex <codex@openai.com>
Signed-off-by: OpenAI Codex <codex@openai.com>
|
Legolas review at Provenance (checked)
Base drift
Carried forward (unchanged)
Needs E2E confirmation from Gimli: native IPC and live backend status and body shapes. |
|
E2E coverage audit at Read-only inspection of checksummed raw receipts found Settings Chromium/WebKit 10/10, but just five logical Settings cases in two engines; only one deletion-specific per engine. The deletion browser case ( The normal full-browser gate at historical SHA Next, only with authorization: independently run the functional browser projects blocked by the measurement failure, keep the full-gate failure recorded, then run a real same-origin development broker against a local noncredentialed contract double for persist-before-send → dropped-response → restart → manual same-UUID receipt. A packaged-native test requires a separately implemented/approved backend and attended app verification; live backend/relay/deletion requires separate disposable nonproduction authorization. No tests or tenants touched for this audit. Report: (private test workspace), SHA-256 |
Signed-off-by: OpenAI Codex <codex@openai.com>
Signed-off-by: OpenAI Codex <codex@openai.com>
|
Gimli E2E verdict — EXERCISED AND WORKS (browser with mocked API), exact head |
Signed-off-by: OpenAI Codex <codex@openai.com>
|
Gimli E2E — EXERCISED AND WORKS, browser/UI lane only at exact tested head
Request ledgers, traces, fixture report and replay instructions: (private test workspace). Scope limitation: this does not exercise a replay 409 |
KGoose maps the relay's deletion_request_conflict and deletion_lifecycle_conflict to the client code deletion_conflict/409. The recovery branch keyed on the pre-mapping code and never fired, so a conflicted replay stayed pending forever. The same held for an owner who unarchived after an ambiguous submit (must_archive). Recovery now settles on every known rejection that proves the saved UUID has no relay reservation. KGoose preflights and the acknowledgement version, which the relay checks before its UUID lookup, stay fresh-only. Drop the unused 'accepted' progress stage. Signed-off-by: OpenAI Codex <codex@openai.com>
|
Gimli E2E — EXERCISED AND WORKS (MOCK-API Chromium/UI lane only) at exact head
Evidence: seven token-free request/response ledgers, seven Playwright traces, 13 running-UI screenshots and raw Chromium log at (private test workspace); integrity-checked portable evidence archive there has SHA-256 Scope: mocked Builderlab responses do not establish live backend/auth/relay/executor, actual owner-unarchive API behavior, packaged native transport, simultaneous-tab races, WebKit, or hosted CI. This is not an overall gate PASS. |
* origin/main: (58 commits) flake fix: keep restored reading anchor out of bottom follow (WebKit scroll measurement) (#407) Replace fixed browser-test waits with conditions, gates and the clock (#373) feat(updates): show installed version in Software Updates settings (#430) fix(desktop): allow deep-link delivery to the main webview (#432) feat(shell): open your profile from the account menu avatar (#390) Polish top bar and animate contextual sidebar toggle (#360) fix(profiles): preserve nonlocal agent identity in profile fallback (#327) test(agents): pause the status poll around the failed-Stop checks (#431) fix(sidebar): paint channel rows with the scroller contents (#428) feat(channels): archive and delete channels from settings (#385) feat(updates): add in-app auto-updates with restart toast (#312) fix(ui): keep background loading from shifting populated views (#418) Improve member and agent identity previews (#412) Fix initial emoji autocomplete selection (#419) Add community membership settings (#348) Keep nested replies compact and place actions above message text (#367) Import an exact inventory identity from its selected source with retry (#288) ci: add gated macOS preview updater feed promotion (#414) Set up incomplete inventory identities through a working Use here dialog (#287) Show saved local and relay inventory while retaining existing import controls (#286) ... Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
b7bddc1 to
b6c37cf
Compare
Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> * origin/main: ci: fix two main-branch vitest failures (#437)
wesbillman
left a comment
There was a problem hiding this comment.
Carl, an automated reviewer, commenting via Wes’s GitHub account.
Changes requested: one P2 recovery-lifecycle defect, detailed inline.
Reviewed head 47fa3cee19af92f0370e6ce6e2859830ea7d51b1 against base f3fe889eec574a4ecee9b3dfa10697378ef0faa9. Integrated independent UI and broker reviews with my persistence/protocol review.
- Required CI is green at this head. This review used source, tests, and existing CI; no local suites or live destructive workflow were run. The reported mock-API browser journeys do not establish live broker/backend/executor behavior.
- Merge criterion: preserve unresolved intent across account transitions and add the regression coverage described inline, with required CI green.
- Keep the documented backend-first rollout and default-off capability gate; packaged-native support remains outside this PR.
There was a problem hiding this comment.
🤖 Reviewed at 47fa3cee against main @ f3fe889e. Blocking: I agree with Carl's P2 on HostedCommunities.tsx:428, and it's the only blocker I found.
The UUID can also get dropped without the user doing anything. load() treats an unauthorized or setup_needed identity reply as "no owner" (line 100), and then clears the stored envelope because null doesn't match its owner (lines 115-120). So a lapsed Builderlab session can erase the recovery handle as well as Sign out, Unpair and Switch (lines 428, 500, 536). Whatever fix you pick should cover that path too.
One constraint on the fix: keep the owner check in checkPendingDeletion (line 271). A replay for a known UUID under a different owner comes back from the relay as deletion_request_conflict, which the Builderlab backend maps to deletion_conflict. That code only proves there's no reservation when the replay owner matches the envelope owner. So keep the envelope around across account changes, but only check it from the owner it belongs to.
The rest of the recovery logic matches the servers. I checked it against relay block/buzz#7969 at e21151f4 and the matching Builderlab backend change:
admit_owner_requestlooks up the UUID under its advisory lock before it checks owner, archive state or lifecycle. Sonot_owner,must_archiveand the absent-UUIDdeletion_conflictreally are reached only when that UUID has no reservation.protected_targetis the fixed deployment host and can never be admitted.- The backend's pre-lookup rejections (
missing_mapping,unsupported_acknowledgement_version,invalid_request,confirmation_mismatch) are exactlyFRESH_ONLY_DELETION_REJECTIONS, and the status pairs match. - The progress stages match the relay's
DeletionStage. - The relay's owned list hides communities with a non-aborted request, so an admitted community doesn't come back after a reload.
Persist-then-verify before the POST, the identical four-field replay, the literal-true capability gate and the quota projection all look right.
A few small things, none blocking:
- The
"bound abort"case in the generation-fence test (HostedCommunities.test.tsx:1478) releases a 409 witherror.code: deletion_aborted, not a tuple-bound 202 withstatus: "aborted". Production treats that response as ambiguous, so this case doesn't exercise the abort-clearing path. Using the real aborted-202 shape would fix it, keeping the assertion that the newer envelope survives. The standalone bound-abort test at line 1249 is fine. - Nothing tests the upstream-status passthrough in
dev/relay-broker.mjs:823through the real broker route. The card and API tests mockfetch, and the browser spec intercepts/api/builderlab/*. An HTTP-level case showing a tuple-bound 202 stays 202 and a structured 409 stays 409 would pin it. - The broker's field-length limit went from 200 to 253 for every string field, not just
host. The backend revalidates, so this is harmless.
CI at this head is green. Windows native validation was skipped. I didn't run the ambiguous-POST, sign-out, same-owner sign-in flow live, so Carl's P2 stands on the source, not a repro.
wesbillman
left a comment
There was a problem hiding this comment.
Carl, an automated reviewer, commenting via Wes’s GitHub account.
Changes requested: the existing P2 remains, plus one new P2 detailed inline. Reviewed head 47fa3cee19af92f0370e6ce6e2859830ea7d51b1 against base f3fe889eec574a4ecee9b3dfa10697378ef0faa9.
The existing recovery-envelope finding now has real-component, mocked-transport reproduction evidence: sign-out/same-owner sign-in, A → B → A, and setup-needed/same-owner recovery all lose the UUID; ordinary remount is the passing control. No duplicate finding thread added.
The new finding is independently verified against the client source and the relay’s explicit privileged-abort contract/regression. It is not a claim of a live end-to-end abort test. Required CI is green; Windows native validation is skipped. No live destructive workflow was run.
Merge criteria: address both P2 threads, add account-transition and post-admission-abort regressions without weakening stale-response/owner binding, and keep required CI green. Preserve the backend-first, default-off rollout. The retired-control candidate was not established as a reachable host-level failure and is not a merge condition.
…rvation (#7969) ## Summary This is the relay side of owner community deletion. - **Idempotent delete is the recovery call.** - `POST /operator/communities/delete` checks the request UUID first. - If the request already exists with the same host, owner and acknowledgement version, it returns `202` with the request's current `status`. That holds at any stage, even after membership is purged, and no new work is admitted. - The same UUID with a different host or owner returns `409 deletion_request_conflict`. An unsupported acknowledgement version is rejected first, with `400 unsupported_acknowledgement_version`. - There's **no receipt endpoint**. Clients recover by resending. - **Active quota reservation.** An incomplete owner deletion holds the owner's slot until the deletion logically completes. Migration `0054` adds the supporting index. Migrations 0052 and 0053 are unchanged. - **Lifetime cap.** Deleted communities keep their hosts as permanent tombstones. - On create and on transfer-in, the relay counts live ownership plus every non-aborted owner deletion, completed ones included. - That total is capped at an absolute 20, regardless of the active limit, and going over returns `limit_reached`. - This stops create-then-delete host squatting. - **Stable lifecycle conflict codes,** plus `acknowledgement_version` in the 202. - **Owner-list quota projection:** `quota_used`, `quota_limit` and `can_create`. - `can_create` reflects both caps. - The projection is advisory, and `limit_reached` is authoritative. - **Operator doc** (`docs/operator-community-deletion.md`): the acknowledgement version is a compile-time constant. Admission and the executor's claim/lease both filter on it. A version bump must keep replaying and executing old-version requests. This follows on from #7830. The foundation PRs #7818, #7827 and #7830 are merged. ## Testing New tests: - `owner_delete_resubmission_reports_current_status_without_new_intent` - A replay returns 202 `submitted`, including after membership purge. - Changing any field returns 409 `deletion_request_conflict`. - A non-operator gets 403. - A replay after abort returns 202 `aborted`. - No request rows are added. - `completed_owner_deletions_count_toward_lifetime_cap` - After 20 created-then-deleted communities, the active count is 0 but `can_create` is false. - The next create and a transfer-in both return `LimitReached`. - `owner_quota_admits_only_under_active_and_lifetime_caps`: a unit test. Fellowship gate: PASS at `59375c00`. The code review was clean. The E2E run covered authenticated KGoose → relay → the real drain executor. The later commits only change the operator doc. ## Rollout - Deploy order: this relay first, then KGoose squareup/cash-server#130634, then Web squareup/ext-builderbot-ui#241 and App block/buzz-app#403. - No shipped client ever called a receipt route, so removing it doesn't break any existing client. - The quota changes have no deploy-order requirement. - Keep owner deletion off until this relay and the drain executor are live. - If you need to roll back, turn deletion off before rolling back the relay. - Recreate any database that ran the earlier version of migration 0054. That only applies to disposable preview databases. Never apply this to a database holding real data. The earlier draft 0054 has a different checksum and index predicate. ## Complexity Net simpler: - One route, its handler and a writer-routed `get` are removed. Recovery reuses the existing idempotent admission path. - A single `OwnerQuota::admits()` backs create, transfer and the projection. - The stale "clients fail closed / strict deployment order" doc section is replaced by the advisory quota contract. --------- Signed-off-by: tornquist <tornquist@squareup.com> Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Signed-off-by: Codex <noreply@openai.com> Signed-off-by: Codex <codex@openai.com> Signed-off-by: OpenAI Codex <codex@openai.com> Co-authored-by: Codex <noreply@openai.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz> Co-authored-by: Codex <codex@openai.com>
* origin/main: (27 commits) Let plugin pages publish NIP-AR artifacts and embed the host thread view (#434) test(app): migrate entity-navigation test off removed buzz://open locator API (#463) Show agent activity in navigation (#423) test(browser): hold motion when it commits, not on its start event (#459) fix(navigation): ignore unknown query parameters on Buzz links and remove the buzz://open locator (#457) feat(design-system): distinguish controls on floating surfaces (#429) feat(native): add community extras and media preparation (#450) Clone inventory identities through reviewed text and fresh identity creation (#289) feat(communities): add right-click actions to the community rail (#400) fix(messages): keep a send reveal pending until its scroll runs (#454) fix(messages): reserve a stable scrollbar gutter on the channel feed (#451) fix(sidebar): list plugin pages as sidebar rows via an opt-in primary flag (#401) feat(channels): surface canvas content in channel settings (#426) fix(profiles): remove redundant presence status row (#394) test(browser): count live retries once the page handles startup controls (#443) feat(composer): host-owned resource links for the Projects picker (#445) feat: support native read state and recent channel activity (#444) feat(native): serve relay media and uploads in packaged builds (#433) feat(channels): suggest joined channels in the composer (#446) feat: support native agent activity, library, memories, and community resolution (#441) ... Signed-off-by: Codex <noreply@openai.com>
…anges Signed-off-by: Codex <noreply@openai.com> Co-authored-by: Codex <noreply@openai.com>
wesbillman
left a comment
There was a problem hiding this comment.
Changes needed:
- P2 — Finish the existing abort-recovery repair. A matching aborted replay now restores the row, but the new branch leaves “Deletion started” displayed for the same mounted owner. Reconcile that notice with the aborted outcome, and extend the new accepted→aborted→Refresh regression to check it; an owner should not be told deletion is continuing after its authoritative abort.
- P2 — Sanitize public PR material. The description exposes a private-repository rollout reference, and the screenshot evidence comments link an internal media host. Replace those with a portable dependency description and public-safe attachments; preserve the backend-first/default-off requirement. The twelve screenshots themselves show fixture data, not an observed secret.
The account-transition recovery finding is addressed in source, retaining owner/UUID checks.
Star Lord’s automated source follow-up via Wes’s account; head f579908773532e32790e39c93fb85bc536364cfb, base 516de46100e06e7176e015fd315b9665f1bc5b9d. No tests or app execution. One CI snapshot: JavaScript/Rust passed, browser checks incomplete, Windows skipped. Live deletion, native behavior and keyboard-focus outcomes remain unverified.
|
Gimli E2E — EXERCISED AND BROKEN at exact PR head Environment: a disposable Linux test host; fresh production Vite frontend, real development Builderlab broker and Chromium 153. Browser clicked the actual Settings → Hosted communities UI. The broker's upstream Builderlab responses were synthetic on loopback; local relay/identity were fixture-modeled. No live backend, native app, or real operator abort was exercised.
The worktree was restored clean at the exact head; test servers stopped. Trace ZIPs, genuine screenshots, synthetic request/status ledgers, fixture patches, raw Playwright logs, and checksums are archived under (private test workspace); sanitized primary archive SHA-256 |
There was a problem hiding this comment.
🤖 Reviewed at f5799087 against main @ 516de461. Blocking: one small gap left in the abort fix. Everything else from my last review is fixed.
When Refresh gets the bound aborted reply, it takes the community out of the hidden set (lines 138-145) but never touches deletionNotice. That notice was set to "Deletion started" when the 202 was accepted (line 170), and the only thing that clears it is an owner change (lines 107-111). So after accept → operator abort → Refresh, the archived row comes back with Delete enabled while the card still tells the owner the deletion is running. Clear or replace the notice when the abort lands, and keep the right text if another accepted deletion is still hidden. The new test at HostedCommunities.test.tsx:1036 should check the notice as well as the row. Star Lord raised the same thing on this head.
What's fixed:
- Sign out, Unpair, Switch and a lapsed
unauthorized/setup_neededsession now only hide the stored request.load()shows it again only for its owner and backend origin, andcheckPendingDeletionstill checks the owner before replaying. - Refresh replays only a hidden accepted ID that's back in the list, only for its own owner, and only when deletion is enabled. Replaying is safe on the relay:
admit_owner_requestreturns an existing UUID at its current stage before it ever looks at the community, so an aborted request stays aborted and can't be admitted again (block/buzzcrates/buzz-db/src/store/deletion.rs:908-936). A stale list that still shows a running deletion replays to202 submitted, so the row stays hidden. - Both of my earlier small notes are done: the "bound abort" case in the generation-fence test now uses the real aborted 202, and
dev/relay-broker-api.test.mjspins the 202 and 409 passthrough through the real broker route.
A couple of small things, none blocking:
- If the Refresh replay fails for any reason other than an abort (network error, auth, capability turned off), the error is dropped (lines 129-146). Keeping the row hidden is right, but Refresh then looks like it worked. A short message that the deletion status couldn't be checked would help.
- The device keeps one pending-deletion record, and
persistPendingDeletionwon't overwrite a different one. Now that another owner's record is kept (correctly), a new deletion by the current owner fails with "Deletion was not sent because its recovery record could not be saved", and nothing on screen says why or how to clear it. It fails safe and only happens when the device key or backend origin changes, but that error should say another account has a deletion pending on this device that has to be checked from that account.
Locally at this head: the two hosted-communities test files, broker API and Builderlab tests pass 243/243, and settings.spec.mjs passes 14/14 on Chromium and WebKit. I also removed each new guard one at a time. Going back to plain load() on Refresh, clearing the stored request on sign-out, and dropping the aborted-request map deletion each turn one test red. Dropping the accepted.owner_pubkey !== nextOwner check (line 134) keeps everything green. That's not a cross-owner hole. As far as I can tell the check is redundant, because an owner change clears the accepted map before replay (lines 106-112). Nonblocking: either drop it or add a one-line comment saying it's a backstop. On CI, CI required is red only because two WebKit shards (3/6 and 6/6) were cancelled at 19:39Z, not failed, in run 36765443532. They need a rerun.
…t state Signed-off-by: Codex <noreply@openai.com>
wesbillman
left a comment
There was a problem hiding this comment.
Changes needed: the existing P2 public-material cleanup remains unresolved in the description and evidence comments. Replace internal dependency/coordination references and media-host links with portable wording and public-safe attachments; the 15 inspected images show fixture data, not an observed secret.
One new error-path usability issue is detailed inline: the occupied-slot guard leaves the confirmation open without an explanation. The prior account-recovery and stale abort-notice defects are addressed in source and regression assertions.
Star Lord’s automated source follow-up via Wes’s account; head 26b919ad776f1f4911a9dbe1713108fe5b267f93, base 516de46100e06e7176e015fd315b9665f1bc5b9d. No tests or app execution. CI snapshot: JavaScript/Rust and 11 browser shards passed; one WebKit shard running, Windows skipped. Live deletion, native behavior and keyboard-focus outcomes remain unverified.
Signed-off-by: Codex <noreply@openai.com>
|
Gimli E2E — EXERCISED AND BROKEN (diagnostic at exact head
Earlier nine Chromium journeys at the same SHA passed their bounded mock-boundary assertions (e.g. accepted→modeled abort→Refresh restores archived row), but did not cover this rerender seam and do not overturn the failures. The follow-up's Playwright traces, request/response ledgers, first-attempt harness corrections, and audit are in (private test workspace) ( |
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 Thanks for the follow-ups. No blockers at 1178112e.
The stale "Deletion started" notice from my last review is fixed. When Refresh replays the request and gets a tuple-bound deletion_aborted, the card drops the accepted entry, restores the row, clears the notice once no accepted deletions remain, and names the stopped host (HostedCommunities.tsx:171-180).
The two smaller items from that review are fixed too. A non-abort replay failure now shows "Couldn't check deletion status." and keeps the row hidden. A slot held by another owner now gets its own notice with Delete disabled (:133-146, :666-673, :738-742), instead of the "could not be saved" message.
The occupied-slot P2 raised at 26b919ad also no longer holds. The final-confirmation reread sets error, and the dialog renders it through failure (:342-350, :856-878). We reproduced it in headless Chromium and WebKit with a second same-origin tab writing the envelope while the dialog was open. At 26b919ad the dialog stayed silent. At this head the alert shows inside the dialog, nothing is POSTed, and the saved envelope is unchanged.
unauthorized is no longer treated as the connect state, which matches the backend: NostrIdentityService.current returns 200 with identity: null for an unlinked account, and unauthorized only as a 403 when the session lacks the USER role.
Tests: 143/143 in the hosted-communities Vitest suite at head and 18/18 for Settings in headless Chromium and WebKit. Four mutations (dropping the abort notice clear, the foreign-owner slot detection, the stable active closure plus action-owner busy clear, and the occupied-slot early return) each failed 1-3 tests. The three new browser scenarios fail at f5799087 and pass here. CI is green; Windows native validation was skipped.
Minor, non-blocking:
- The shared error at
HostedCommunities.tsx:342-349overflows the dialog when it holds a full npub. At 1440×950 the text runs past the dialog edge in both engines (scrollWidth628 vsclientWidth446). Addingmin-w-0to the span and a break rule for long keys (break-all/overflow-wrap: anywhere) fixes it. api.ts:67"Your Builderlab session ended. Sign out, then sign in again." assumes an expired session. From the identity endpoint,unauthorizedmeans the account isn't authorized for Buzz identities, and signing in again won't fix that. Something like "This Builderlab account can't manage Buzz identities right now. Try signing in again." would cover both cases.- When another context clears the blocked slot while the dialog is open,
:858-860says "Refresh and try again.", but pressing Start deletion again sends immediately. "Try again." is accurate. blockedOwneralso triggers when the owner matches butbackend_origindiffers (:134-140). The notice then asks the user to switch to the identity they're already using. This is unlikely in the desktop app; a separate origin message, or ignoring origin in that copy, would fix it.
wesbillman
left a comment
There was a problem hiding this comment.
Changes needed: the existing P2 public-material cleanup remains in historical PR comments/reviews. The description’s dependency wording is fixed; sanitize the remaining internal links and workspace/private-dependency references, replacing evidence links with public-safe attachments.
The occupied-slot finding is fixed in source and regression assertions. The stable callback/busy-state repair also matches Settings’ caller lifecycle; no new material code defects found in this follow-up. All 19 linked screenshots were inspected and show fixture data, not an observed secret.
Star Lord’s automated source follow-up via Wes’s account; head 1178112e95df025499663576c4639a230f6cba22, base 516de46100e06e7176e015fd315b9665f1bc5b9d. No tests or app execution. CI snapshot green; Windows skipped. Live deletion, packaged-native behavior and current keyboard/focus outcomes remain unverified.
wesbillman
left a comment
There was a problem hiding this comment.
Carl, an automated reviewer, commenting via Wes’s GitHub account.
Code blockers addressed; the existing P2 public-material cleanup remains. Reviewed head 1178112e95df025499663576c4639a230f6cba22 against base 516de46100e06e7176e015fd315b9665f1bc5b9d, including independent UI and public-material follow-ups. No new material code findings.
The account-transition, accepted-abort/notice, occupied-dialog and parent-rerender repairs match their regression assertions. Owner/origin binding, same-UUID replay and stale-result protection remain intact.
Remaining scope of the existing cleanup finding:
- The author of this historical review needs to replace its private backend repository/PR/head locator with portable contract wording.
- Remove private coordination deep links from this evidence paragraph and this closing paragraph. The former’s claim that images require Buzz access is now obsolete. Preserve the public GitHub attachments.
The description, concrete workspace locators and internal media-host URLs are cleaned up. The media audit inspected all 26 linked images and found fixture UI, not an observed secret. No source/history rewrite is requested for this remaining cleanup.
Required CI is green; Windows native validation is skipped. This follow-up used source, regression assertions, existing CI and published browser evidence; no local suites or live destructive workflow were run. Keep the backend-first/default-off rollout: live backend/relay/executor and packaged-native behavior are not established by the mocked evidence.
Regarding “Probe parent rerender”: the diagnostic describes a temporary test button that forces a Settings rerender during a held request. It appears in the instrumented screenshots, not the tracked application at this head; the committed equivalent is the test-only Parent update helper. It is not a shipped control.
@wesbillman That's a temporary diagnostic button the E2E harness injected so it could force a Settings parent re-render while a request was held. It only appears in the instrumented screenshots and isn't in the app at |
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 approving at 1178112e. the code hasn't changed since my last review, it still merges cleanly with current main, the relay's deletion code hasn't changed in the meantime, and required CI is green.
the four nonblocking items from my last review are still open. fine to fix here or in a follow-up:
- the dialog error runs past the dialog edge when it holds a full npub (
HostedCommunities.tsx:342-349) - the
unauthorizedcopy atapi.ts:67assumes the session expired, but it can also mean the account isn't authorized for Buzz identities - "Refresh and try again." at
:858-860should just be "Try again.", since Start deletion sends right away blockedOwneralso fires when the owner matches butbackend_origindiffers (:134-140), so the notice asks you to switch to the identity you're already using
could you also remove the internal coordination links from this comment and this one, per Carl's cleanup note? I've removed the private backend reference from my first review.
all testing so far, ours included, ran against a mocked backend, so a real deletion still needs a check once the backend capability is turned on.







Summary
Adds archived-owner community deletion to the Hosted communities card. It sits behind a backend capability, which defaults to off.
abortedends recovery without announcing deletion.deletion_conflict,must_archive,not_ownerandprotected_targetprove the saved UUID holds no reservation, so they end the pending request.unsupported_acknowledgement_versionstay ambiguous, because they happen before the relay's UUID lookup.can_create: falsedisables Create and shows the generic limit copy. When it's absent, the server'slimit_reacheddecides.true.aborted202, and then replaces "Deletion started" with "Deletion of stopped. This community is not being deleted." A retired card sends no further replays.unauthorized: shown as an error, not as "not linked yet". The dev broker passesunauthorizedthrough for expired or invalid sessions too (dev/builderlab.mjs:172-237). Onlysetup_neededshows Connect.quota_limitN shows "You've reached your limit of N communities."; 0 shows "You can't create more communities right now."Verification (head
1178112e)26b919adplus one commit. The card now readsactivethrough a ref, so a Settings re-render no longer restarts loading or leaves the card busy. The final confirmation step shows an in-dialog error when the slot is occupied. A transferlimit_reachednames the recipient. The abort message names the host. A failed replay shows "Couldn't check deletion status."unauthorizedclears stale notices.pnpm check, lint and format pass. The Settings browser journey passes 14/14 on Chromium and WebKit with no retries.26b919ad, including parent re-render during a held delete and during a held login. Five guard mutations on the committed file each fail their test: theactivedependency, the in-dialog error, the catchactive()guard, the disabled gate and the final-confirmation early return.Rollout
Known limits: