# Remozio plan review: revision 14

I reviewed the complete revision 14 against its own invariants and the round-7 disposition. I focused on the post-revision-5 additions (sections 12–18), especially the new update, security-generation and scheduling material in section 17. I checked how it interacts with the section 3 placement rules, the section 6 restart rules and the section 9 UI refresh rules. This is a document review only; nothing was tested or inspected.

## Findings

### 1. Medium: the plan never says when a raised security floor takes effect

**Where:** §17 "What each signature proves", §17 "Activate a compatible component set", §18 "Compatible additions and breaking changes".

**Conflict:** Each privileged XPC request is checked against a persisted minimum generation, and floors can come from "authenticated release policy" (§18). The plan does not say when a new floor becomes enforced. §17 also contemplates that "a mandatory security floor disables the old stack". Both conflict with:
- "keep the existing compatible stack working while downloading and staging";
- keeping the old GUI adapter alive "while its requests or permits need it".

**Failure scenario:**
1. A security release is staged, or the root authority is activated before the app-bundled adapter.
2. The new floor is persisted and applies to the adapter role.
3. The still-running old adapter's completion acknowledgment, or permit request, fails the generation check.
4. The live permit becomes Unknown (§6), and pending UI approvals stop working.

This happens without any forced-update decision by the user. That is the silent loss of remote functionality the plan forbids.

**Minimal correction:**
- A role's new floor is persisted only after a replacement build for that role has activated and passed the post-activation checks.
- The floor applies only after the old instance of that role has quiesced.
- Before then, a release-announced floor is shown as "security update ready/blocked by …", not enforced.
- Enforcing a floor early remains the already-noted forced-update policy that requires user consultation.

This correction does not worsen UX. Enforcing floors at staging time would.

### 2. Medium: root-code rollback to an older signed build is not covered

**Where:** §3 "Authenticate local process boundaries", §17 "Sparkle release delivery", §17 "Feasibility gate: remote update continuity", §18 floors.

**Gap:** §3 accepts "equivalent platform launch-time signature enforcement" in place of root-owned placement. The generation check is enforced *by* the root authority on its peers. Nothing checks the root authority's own generation, or stops an older validly signed build from being staged or activated.

**Failure scenario:**
1. The placement gate passes on signature enforcement alone, for example an app-bundle service registration.
2. A same-user process, or a compromised feed host serving an old EdDSA-signed archive, substitutes a correctly signed older app or helper.
3. launchd accepts it because the signature is valid.
4. Root now runs old vulnerable code, which is also the component expected to enforce the floors.

Sparkle's version ordering does not cover out-of-band substitution. The §18 acceptance list tests old signed *helpers* as peers, not the authority itself.

**Minimal correction:**
- Define "equivalent enforcement" as signature validity plus anti-rollback.
- The activation path checks every candidate role's signed generation against the persisted floors and the currently installed generation. It rejects downgrades except through the explicit administrative recovery already mentioned in §18.
- At startup, the root authority checks its own OS-validated generation against the persisted floor and refuses authority operations if it is below it.
- Add an acceptance case: replace the root helper with an older signed build.

No UX cost.

### 3. Low: UI dialogs can be silently stranded across a root-authority replacement or restart

**Where:** §17 activation ("Requests racing the brief replacement boundary receive an explicit retryable Update installing result"), §17 restart matrix ("Unexpected root-authority restart: Cancel unconsumed requests … explain fresh submission"), §9 "Compatibility and unsupported dialogs" / §13 "Refresh versus a new original operation".

**Gap:** For commands, the caller receives a retryable status. For UI requests, the "caller" is the adapter, and no rule tells it to resubmit. Refresh is user-initiated and defined only for *expired* requests.

**Failure scenario:**
1. A 1Password prompt appears during the replacement boundary, or remains after an unexpected root restart.
2. Its request is refused or cancelled.
3. No phone notification is produced, and the roughly 60-second prompt times out while the user is away.
4. The user is told to "submit fresh", but no submission surface exists for them.

**Minimal correction:**
- After Update installing, or after a root restart, the adapter automatically recaptures still-present dialogs as *new* requests.
- New requests get fresh challenges, preserved first-seen age and target deadline, and no carried-over authority.
- Otherwise the adapter reports disappearance per §13.

This does not worsen UX.

## Round-7 disposition

The accepted Opus 1 and Opus 3 fixes are consistent with the §6 restart rules and the §14 routing rules, except for the floor-timing interaction in Finding 1.

The Opus 2 fix is correct in intent. It is incomplete for the root authority itself (Finding 2).

The receiving-key isolation requirement is a defined gate with a consultation path, not a defect. However, it may be stricter than needed if credential ciphertext only ever arrives over generation-checked XPC. The gate evidence could evaluate that alternative before declaring failure.

## Assessed without findings

- **Scope and key separation:**
  - the section 1 action/scope table;
  - decision-key limits, including the new update-scheduling purpose;
  - status-versus-approval domain separation;
  - relay and gateway exclusion from authority;
  - the per-request Little Snitch "current request" definition.
- **Protocol:** negotiation transcript binding, and contract selection limited by the floor and features without re-encoding.
- **Other boundaries:**
  - multi-phone first-valid consumption;
  - audit atomicity and exclusions;
  - two-clock expiry;
  - presence routing as delivery-only;
  - push token handling;
  - Cloudflare Access as a transport-only gate.
- **Deferred items:** pending UX preferences (idle interval, retention) and feasibility gates (placement, single biometric, sudoers, local command approval, Access auth, AX fixtures) are correctly deferred.

Implementation must still demonstrate all gate evidence, particularly the §3 and §17 placement and rollback proofs.

**SUBSTANTIVE FINDINGS REMAIN**
