# Remozio plan review: revision 12 (complete plan)

## Findings

### 1. HIGH: Root-executed code may be updated through a path the same user can write

**References:** §3 "Authenticate local process boundaries"; §17 "Sparkle release delivery" and "Feasibility gate: remote update continuity".

**Conflict.** §3 requires trusted bundles and update paths in "administrator-controlled locations." It also puts a malicious same-user process in scope. §17 prefers ordinary Sparkle app-bundle updates, with the service registered from inside that bundle, and notes this "does not automatically require a package installer."

On a typical personal Mac, the interactive user is an administrator. So "administrator-controlled" can mean "writable by the user's own processes without an authorization prompt." That is exactly how Sparkle can replace an app in `/Applications` without asking for credentials.

**Failure scenario.**
1. A coding agent running as that admin user modifies or swaps the bundle containing the privileged service, or races the staged update.
2. launchd later starts the replaced executable as root.
3. Live XPC peer checks do not help. They protect callers of the service, not the service's own launch. The attacker gains root and every Remozio authority.

The §17 feasibility gate only asks whether renewed administrator authorization is *needed*. It is framed as a UX question. It has no security pass criterion.

**Minimal correction.**
- State an invariant: code launched as root, and its update staging, must not be modifiable by the interactive user's unprivileged processes without administrator authorization.
- Make that invariant an explicit pass/fail criterion of the §17 gate.
- Accept only one of two outcomes:
  - root-owned, non-user-writable placement, or
  - a demonstrated platform launch-time signature enforcement for the registered service.
- Add a matching item to "Acceptance: upgrades and hostile peers."

**UX flag.** If the only safe path requires administrator authorization per update, remote and locked-Mac updates get a recurring manual step. This needs user consultation, as §17 already implies. It must not be silently adopted.

### 2. MEDIUM: Update continuity contradicts memory-only payloads and root-owned process I/O

**References:** §6 "Crash and uncertain-outcome handling"; §8 "Process I/O and terminal outcomes"; §17 "Activate a compatible component set".

**Two contradictions.**
- §6 keeps pending sensitive payloads in memory only, so a root-service restart cancels unconsumed requests. §17 says to resume pending requests "only if their original payload... remain valid." After a root-service replacement, the payload cannot remain; it was never persisted. The only ways to "resume" are:
  - persisting payloads, which violates §6 and §12, or
  - an unspecified handoff between old and new service instances.
- §8 makes the root service own streaming stdin/stdout/PTY and signal forwarding. Replacing that service severs the attached command. That conflicts with "do not kill active commands."

**Failure scenarios.**
- An implementer satisfies §17 by persisting payloads, breaking a privacy invariant.
- Alternatively, "defer activation when continuity cannot be guaranteed" defers indefinitely. A long-running remote PTY session, or a steady stream of pending requests, then blocks security-floor updates forever. The plan has no bound or user-visible resolution.

**Minimal correction.**
- Scope "resume" to restarts of the GUI adapter, transport, and app, where the root service retains state.
- For root-service replacement, choose one policy:
  - drain: stop accepting new requests, let active and pending work finish, then activate, or
  - cancel: cancel unconsumed requests with an explicit fresh-submission status.
- Never persist payloads.
- Define how deferral is surfaced when a security-floor update is waiting.

**UX flag.** The cancel policy discards pending requests during updates. Any forced interruption of active commands is also a UX regression. Both require user consultation. Drain-with-visible-status is the non-regressing default.

### 3. LOW: Request version selection with mixed-version phones is undefined

**Reference:** §18 "Authenticated negotiation".

**Gap.** Negotiation selects "the highest mutually supported version" for each peer. But §18 also mandates a single immutable request, with no re-encoding for other phones. With phone A on v1 and phone B on v1+v2, the plan does not say which version the authority signs.

**Failure scenario.** Choosing v2 needlessly strips actionable controls from a compatible, above-floor phone A. That reduces remote availability.

**Minimal correction.** Define request-version selection over the currently authorized recipient set. For example: the highest version that satisfies the action's required features and the security floor, and that maximizes the number of eligible phones. Add a two-phone mixed-version case to the acceptance list.

## Assessed without further findings

**Key and authority separation**
- Scope classification, and use of the biometric key versus the decision key, are consistent across §1, §6, §9 and the acceptance lists.
- The Little Snitch-only allow-once rule is not widened to commands or 1Password.
- Relay, push gateway and Access credentials cannot mint decisions, and they stay outside approval authority.

**Consumption, audit and expiry**
- The audit journal is derived from the consumption ledger without becoming a second authority.
- Target expiry is kept separate from Remozio expiry and from disappearance.
- Presence routing is delivery-only and consumes once across surfaces.

**Push and negotiation**
- Push payloads are opaque.
- Negotiation downgrade and domain separation are covered.

**Gates and deferred preferences**
- The local-command approval path, Access background authentication, the single-biometric credential release, sudoers compatibility, and descriptor-based execution are properly scheduled as gates with consultation paths.
- The idle threshold and retention duration are deferred preferences, not defects.

**Limits of this review:** this is a plan-only review. Platform behavior still has to be proven in implementation, including:
- Keystore invalidation behavior,
- AX atomicity,
- Tunnel/Access token renewal,
- whether SMAppService and Sparkle can update services without re-authorization.

**SUBSTANTIVE FINDINGS REMAIN**
