| Earlier finding | Disposition at `726660f2` |
|---|---|
| R4.1 — Recovery bypasses the empty-bucket safeguard | **Fixed:** §2 applies the shared tripwire to absence-based finalization. |
| R4.2 — Trash UI/API promises 30 days | **Fixed:** §5 specifies one effective deadline for all displays and responses. |
| R5.1 — Route-only permanent service can be claimed temporary | **Not fixed completely:** the new check misses remote routes and routes whose account reconciliation changes. New counterexamples below also leave inherited R1.2 unresolved. |
| R5.2 — Expiry markers defeat the empty-bucket tripwire | **Fixed:** a tripped pass writes nothing, and markers do not count as bucket evidence. |

1. **P1 — §3: checking the console’s registry does not protect permanent services on another box.**

   The proposed account-scoped `appHasRoutes` still reads only `s.cfg.Registry` ([appsettings.go:711](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/console/appsettings.go:711)). The existing apex check explicitly documents that hand-added routes on another box are invisible ([apex.go:74](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/console/apex.go:74)).

   Put a permanent, route-only service on platform box B, with the console on box A. Its account/app prefixes and console row are absent. A successfully reads its own registry, finds nothing, and permits temporary creation using that identity. When B holds the housekeeper lease, it runs domains reconciliation against its own registry ([agent.go:2238](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/host/agent.go:2238), [agent.go:2257](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/host/agent.go:2257)). The temporary app’s tombstone then deletes the permanent service’s route ([reconcile.go:206](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/domains/reconcile.go:206)).

   **Fix:** require authoritative deployment-wide route inventory before granting temporary status. Refuse when coverage cannot be established; a successful local registry read is insufficient. Add a two-registry test with the permanent service on the non-console housekeeper.

2. **P1 — §3: the account predicate differs from the ownership rules applied before route deletion.**

   The new check matches `release.RouteAccount(rt)`, which returns the current valid account or falls back to ops ([adopt.go:862](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/release/adopt.go:862)). However, domains reconciliation can replace even an explicitly assigned account when that account has no objects and another account is the sole bucket owner of the app name ([reconcile.go:723](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/domains/reconcile.go:723), [reconcile.go:735](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/domains/reconcile.go:735)).

   A permanent TCP service named `report` belongs to account A and has no bucket objects. Account B creates temporary `report`. The proposed account-scoped check permits it. Creation normally writes B’s default pipeline ([server.go:3570](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/console/server.go:3570)), making B the sole bucket owner. Reconciliation stamps the existing service’s route as B **before** evaluating trash removal ([reconcile.go:189](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/temporary-sites/internal/domains/reconcile.go:189)). B’s expiry therefore removes A’s permanent service.

   **Fix:** check prospective reconciliation ownership, not just the route’s current account. Refuse temporary creation if introducing that account/app prefix would cause an existing same-name route to be adopted. Test both an explicitly different account and an unstamped route, with no objects under the permanent service’s prefix.

Verdict: **revise**.