Automate owner deletion preparation (#7830)

## Why

Owner deletion admission stops at `submitted`. Manual inventory and
approval still stand between owner intent and the existing deletion
executor, preventing self-serve deletion.

## What

The existing `buzz-admin deletions drain` process prepares and
automatically approves operator-attested owner requests. Operator-origin
requests retain manual approval.

## How

The drain prioritizes approved work, then claims one owner submission
with the existing generation lease. It freezes inventory and records
digest-bound `owner_automatic` approval in one transaction before
entering the unchanged executor.

Before approval, the transaction rechecks archived state and current
ownership. It locks the deletion advisory fence, community, owner
memberships, and request in that order. A regression test pins
privileged abort during a live preparation lease.

What got simpler: one drain still owns preparation and execution. There
is no second worker, queue, lifecycle, or retry authority. The rebased
branch contains only this feature and its review fixes.

## Risk

Automatic approval permits irreversible deletion without a human grace
period. Operator attestation is not a cryptographic owner signature.
Provenance, locked authority checks, generation fences, and digest-bound
approval constrain the operation.

This remains work in progress. Broad test failures and incomplete mobile
checks are disclosed below; publication is not a merge-ready verdict.

## Testing

Published head: `e059ae9056b447ca3b5d0c2893da86550ef16f5c`. All seven
commit trees match tested source
`5605f27eaece1e809f746cc1839b55c7ceef8d80`; only attribution metadata
changed. Source-SHA results below are not new-head execution receipts.

At source commit `5605f27eaece1e809f746cc1839b55c7ceef8d80`, isolated
PostgreSQL tests showed stale archive and ownership fixtures fail closed
after the fix. Before the fix both reached automatic approval. Removing
abort's generation increment or stage transition made the new live-lease
regression fail; restored production passed.

`just test` failed in two ACP native-git fixtures and one agent
body-timeout test. The failing source files match the pinned base, but
there is no exact-base execution comparison proving those failures
unrelated. `just test-unit` also failed in the ACP fixtures, leaving 18
tests unrun. `just ci` stopped in Flutter tooling package resolution;
separately run non-mobile lanes do not constitute a full `just ci` pass.

No live tenant deletion or human testing was performed. A dedicated
populated `0052` → `0053` approval-backfill fixture remains a coverage
gap. Final-head hosted CI and security review are required.

## Bigger picture

Rebased directly onto main `12670bd0f037c66a682272bb81c46c3f254fad74`;
prerequisite #7818/#7827 are already merged. Main owns
`0052_channel_artifacts`, so this feature's automatic-approval migration
is now `0053`. Client/KGoose and quota work are separate PRs and are not
part of this diff.

Generated with Codex

---------

Signed-off-by: Codex <noreply@openai.com>
Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
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>
This commit is contained in:
Luke Tornquist
2026-09-29 11:39:33 -04:00
committed by GitHub
parent 12670bd0f0
commit bba75a71eb
8 changed files with 1654 additions and 44 deletions

View File

@@ -18,8 +18,9 @@ Deployment-root community management uses operator-signed NIP-98 HTTP requests.
`POST /operator/communities/delete` accepts only an exact normalized, archived
community whose asserted pubkey is still its owner. The caller supplies the
request UUID as the stable correlation/idempotency identity; the durable row
records owner intent, mediating operator, and acknowledgement version. Admission
returns `202` at the `submitted` stage and performs no inventory, approval,
records operator-attested owner intent, mediating operator, and acknowledgement
version. Admission returns `202` at the `submitted` stage and performs no
inventory, approval,
quiescing, object-store access, or deletion execution synchronously. While that
non-aborted request exists, unarchive and ownership transfer conflict and owner
management lists suppress the archived row. Replaying the same UUID converges
@@ -45,6 +46,19 @@ on the row. Owner provenance pins `requested_by` to `owner_pubkey`, so passing
the operator's own pubkey does not converge — it conflicts with the existing
one-active-request invariant instead.
The privileged one-shot `buzz-admin deletions drain` process gives already-
approved work priority. When none is ready, it may claim only an
operator-attested owner-origin `submitted` request under the same durable
generation lease used for execution, inventory it with lease-loss cancellation,
and atomically freeze the inventory plus a digest-bound `owner_automatic`
approval. The mediating operator remains the approval actor; the owner
acknowledgement is pre-inventory
intent, not a claim that the owner reviewed the digest. The retained lease then
enters the unchanged approved-request executor. Operator-origin requests never
auto-progress and still require explicit inventory and approval. Owner
admission still has no owner-facing cancellation or grace period; the
privileged abort described above remains the recovery path.
Ownership is mutable only while a community is active. Archiving freezes the
current owner. Normal transfer and deployment-root legacy convergence take the
same community-row lock as owner-deletion admission, then reject archived,
@@ -762,6 +776,10 @@ Postgres/Redis clients and S3 client; it does not call relay HTTP. Durable
requests, leases, retry timing, and checkpoints in Postgres are the handoff and
execution authority, so Kubernetes uses `Forbid` concurrency and zero Job
retries rather than introducing a second retry system.
The same drain first claims runnable approved work and, only when none exists,
may prepare one owner-origin submission. Inventory, automatic approval, and
execution share one generation lease and the existing retry/block/checkpoint
records; there is no preparation worker, command, queue, or retry authority.
---