| Finding | Disposition | Why |
|---|---|---|
| R2-1: stale alias authority | Partly fixed | Failed claim listings now stop renewal, but derived instance aliases can survive a failed dependency read while reconciliation returns success; see 1. |
| R2-2: fills from undeclaring builds | Fixed | Admission checks the answering build’s declaration, and the home signals rejection to the far edge with expiry `0`. |
| R2-3: billing for uncacheable fills | Fixed | Acknowledgement transfers billing independently of storage eligibility. |
| R2-4: response delay counted twice | Fixed | Initial expiry now uses response time plus lifetime minus corrected initial age. |
| R2-5: rejected responses shared among waiters | Fixed | Coalescing shares only admitted entries; rejected responses reach only their initiating requester. |
| R1-3: indefinitely renewed stale authority | Partly fixed | App-scope confirmation is addressed, but domain-derived eligibility still has uncovered dependencies; see 1 and 2. |
| R1-6: renewed lifetime at far edge | Fixed | Far copies inherit the home’s absolute deadline, and the initial-expiry calculation is corrected. |

1. **P1 — Instance catch-all aliases can still renew stale ownership indefinitely.**

   **Claim:** The revised alias freshness rule excludes a dependency that exists in the current code.

   **Evidence:** [Design:273](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:273) uses successful alias reconciliation to renew authority and states that catch-all aliases are never published. However, instance catch-alls produce ordinary exact-name aliases ([aliases.go:69](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/domains/aliases.go:69)); the publisher excludes only names beginning `*.` ([edgesfile.go:517](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/host/edgesfile.go:517)).

   When `InstanceLabelCounts` fails, derivation preserves existing aliases before checking whether an exact claim now supersedes them ([aliases.go:161](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/domains/aliases.go:161)). That failure is logged, and `ReconcileAliases` still returns nil ([aliases.go:594](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/domains/aliases.go:594)). Thus, an exact name reassigned to another account can remain served under its previous derived alias while successful instance confirmation and nominally successful alias passes keep renewing `at`.

   **Smallest fix:** Distinguish wildcard aliases from exact aliases derived by instance catch-alls. Require explicit dependency-completeness reporting, including the label-count read and registry writes, before advancing authority. Test an exact claim replacing a derived alias while label-count reads fail for over an hour.

2. **P1 — A primary hostname’s path-routing exclusion has no domain freshness bound.**

   **Claim:** Domain-read failures can leave a primary hostname caching the wrong route indefinitely, even after its authoritative configuration adds a path target.

   **Evidence:** [Design:184](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:184) excludes hostnames with path-prefix rows. Those rows come from domain claims through `ReconcileAliases` ([aliases.go:315](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/domains/aliases.go:315)), but [design:256](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:256) bounds a primary hostname only by its app-record scope; the domain-reconciliation bound applies specifically to aliases.

   Start with primary hostname H serving cached `/assets/` from A. Publish a domain path mapping directing `/assets/` to B, then fail domain listings while app-record confirmation continues succeeding. No path row appears, so H remains eligible and its authority keeps renewing. Cached A responses can continue indefinitely instead of reaching B and its gates.

   **Smallest fix:** Bound primary-host eligibility by successful domain reconciliation too, because proving the absence of path routing requires those reads. Add this failed-domain-listing case to §12, with a gated path target and both home and far caches.

3. **P2 — Coalesced waiters and fill duration are unbounded.**

   **Claim:** A stalled fill can retain disk reservations indefinitely and accumulate waiting requests outside the existing backhaul concurrency limit.

   **Evidence:** [Design:345](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:345) limits active fills but allows concurrent requests for one key to wait without any waiter limit or deadline. Reservations remain held until the fill exits ([design:554](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:554)). Existing backhaul deliberately has no response-body deadline ([edge.go:2837](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/edge/edge.go:2837)).

   An app can send admissible headers and then stall its body. Repeated requests for that key join the same fill indefinitely. Only the leader takes a backhaul slot; the waiters therefore escape the containment that otherwise refuses excess requests ([edge.go:2903](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/internal/edge/edge.go:2903)). A byte ceiling does not bound this case.

   **Smallest fix:** Specify a finite cache-fill deadline covering body consumption, bounded waiter counts, and reservation release when caching is abandoned. Test a stalled body with excess same-key requests and verify bounded waiters and timely reservation release.

4. **P2 — Cacheable HTML fallbacks still satisfy every admission rule.**

   **Claim:** A declared asset prefix can cache an SPA fallback for a year, contrary to the explicit anti-goal.

   **Evidence:** [Design:111](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:111) forbids caching `200 index.html` as a script. The admission rules at [design:417](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:417) contain no HTML exclusion. A declaring build returning `200 text/html`, `Cache-Control: public, max-age=31536000`, and no cookies or disallowed `Vary` passes them all. This can happen when asset-path cache headers also apply to the SPA fallback. The proposed test uses `no-cache` ([design:644](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:644)), so it cannot detect this omission.

   **Smallest fix:** Explicitly refuse HTML responses at admission and add a fallback test with a positive, long cache lifetime.

5. **P3 — The prescribed first rollout test cannot exercise the cache.**

   **Claim:** The rollout sequence asks for a successful far-edge fill before arming its home.

   **Evidence:** [Design:207](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:207) correctly requires an armed home to publish asset declarations. But [design:613](/home/paulca/amadan.net/carlos/platform-edge-asset-cache/docs/superpowers/specs/2026-10-24-edge-asset-cache-design.md:613) says to arm only a far dev box, prove the acceptance gate, then arm the rest. With the home unarmed, that first box cannot catch the test app’s assets.

   **Smallest fix:** Arm the test app’s home first, then one far dev edge, and run the two-edge acceptance gate before expanding.

reject