feat(updates): add one-click upgrade experience - #840
Conversation
🔐 Codex Security Review
Review SummaryOverall Risk: MEDIUM Findings[MEDIUM] Unknown protobuf phases can lock recovery indefinitely
NotesThe authoritative diff applied cleanly in reverse against the pinned commit. The added tests cover Generated by Codex Security Review | |
f8c41ce to
9178649
Compare
9178649 to
4afd98a
Compare
2ce2ce5 to
5854595
Compare
5854595 to
586f9e7
Compare
6fc4d02 to
484cace
Compare
df405fc to
14a80be
Compare
There was a problem hiding this comment.
Pull request overview
Adds the operator-facing, one-click upgrade workflow to ProtoFleet’s Settings → Updates page, integrating the newly available backend capability and durable upgrade operation status into a route-owned UX (confirmation, progress, recovery, and explicit manual fallback).
Changes:
- Introduces a
useUpgradeOperationhook to trigger upgrades, poll durable status without overlap, and recover/lock state across expected restarts. - Adds
UpgradeOperationModalto guide operators through confirmation, RC warnings, progress/reconnect, failure recovery details, and success reload. - Extends the Updates settings page to surface capability-gated one-click actions, reconcile durable operations vs. newer offers, and lock competing controls appropriately.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/plans/archive/2026-07-29-one-click-upgrade-executor-plan.md | Archives the completed plan and documents final boundaries/ownership for the one-click executor workflow. |
| client/src/protoFleet/features/updates/copyInstallCommand.ts | Updates helper comment to reflect Settings-owned manual fallback usage. |
| client/src/protoFleet/features/updates/api/useUpgradeOperation.ts | Adds upgrade lifecycle hook: trigger, bounded reconciliation, non-overlapping polling, and session recovery. |
| client/src/protoFleet/features/updates/api/useUpgradeOperation.test.tsx | Adds focused unit tests for the upgrade operation hook behaviors (recovery, reconciliation, cadence, acknowledgements). |
| client/src/protoFleet/features/settings/components/UpgradeOperationModal.tsx | Implements modal UX for confirmation/progress/failure/success/manual unlock flows. |
| client/src/protoFleet/features/settings/components/UpgradeOperationModal.test.tsx | Adds modal behavior and accessibility assertions for the various states and actions. |
| client/src/protoFleet/features/settings/components/Updates.tsx | Wires one-click upgrade into Settings → Updates, including capability gating, locking, and durable status reconciliation. |
| client/src/protoFleet/features/settings/components/Updates.test.tsx | Extends Settings Updates integration tests for one-click upgrade states and permission revocation handling. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 14a80be769
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 789da4caf2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cfab18509e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81d998aa06
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33cc70a6c9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9fc5722fce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
🤖 Addressed the current Codex Security Review finding in a060c5f. Ambiguous no-ID reconciliation now accepts only a target-matching SUCCEEDED operation, so a completed upgrade is recovered and prompts reload; same-target failures still require exact operation-ID correlation and cannot unlock competing install controls. Added coverage where TriggerUpgrade loses its response and the first subsequent durable status is SUCCEEDED. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a060c5f3cb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cdc1a5fec3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bad5e6e0f5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 78375356e5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bbf954ebef
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Reviewable diff: +917/-8 across 5 files (excludes generated, test, and story files).
Summary
Adds the one-click upgrade workflow to Settings > Updates: exact-version confirmation, RC warnings, durable progress, expected restart recovery, failure guidance, and success reload. The normal application shell remains intentionally passive—it only advertises an available version and routes operators to Settings—while unsupported hosts retain the release-specific manual install command.
Stack: #841 → #842 → #843 → #844 → #845 → #835 → #836 → #837 → #838 → #839 → #840. This is 6/6 of the one-click phase and the diff is relative to #839. The merged ancestors provide release discovery, permission-gated APIs, durable host execution, and the passive update indicator; #839 installs that executor on supported hosts. Host mutation is intentionally out of scope here, and progress is intentionally not tracked across every Fleet view.
How it works
The passive version pill navigates an authorized operator to
/settings/updates. The route loads the current eligible release, capability, and manual command, while separately checking durable updater status so an operation started in another tab or recovered after navigation takes precedence over a newer offer. A one-click action appears only when Fleet reports a reachable executor; confirmation sends only the exact eligible version, and fleetd revalidates it before host mutation.During an operation the route uses completion-based polling, preserves the last phase through the expected Fleet restart, and recovers host state when the operator returns. Ambiguous trigger outcomes keep competing controls locked. If the executor remains unreachable after the bounded reconciliation window, the manual command stays locked until the operator explicitly confirms on-host that no upgrade is running; a reachable executor reporting no matching operation instead refreshes the eligible release before retry.
flowchart LR S["Passive version pill"] --> R["Settings > Updates"] R --> U["GetUpdateStatus: release, capability, manual command"] R --> O["GetUpgradeStatus: durable host operation"] U --> C{"Executor reachable?"} C -->|"yes"| X["Confirm exact target"] C -->|"no"| M["Copy manual install command"] X --> T["TriggerUpgrade(target version)"] T --> P["Route-owned progress and recovery"] O --> P P --> F["Failure details or explicit manual fallback"] P --> D["Success and reload"]sequenceDiagram participant U as "Authorized operator" participant S as "Fleet shell" participant R as "Updates route" participant F as "fleetd" participant X as "Host updater" S->>F: "Discover eligible version" F-->>S: "Version-only indicator" U->>S: "Open update" S->>R: "Navigate to /settings/updates" R->>F: "GetUpdateStatus + GetUpgradeStatus" F-->>R: "Offer, capability, durable operation" U->>R: "Confirm exact target" R->>F: "TriggerUpgrade(target version)" F->>X: "Start validated operation" R-->>F: "Poll without overlap" opt "Operator leaves the route" U->>R: "Return later" R->>F: "Recover durable status" end F-->>R: "Active, failed, or succeeded" R-->>U: "Progress, recovery, or reload"Areas of the code involved
features/settings/components/Updates.tsxfeatures/settings/components/UpgradeOperationModal.tsxfeatures/updates/api/useUpgradeOperation.tscopyInstallCommand.tsdocs/plans/archive/...one-click-upgrade...mdKey technical decisions & trade-offs
Testing & validation
npm run build:protoFleetpassed the production Vite build.node_modulespath and is left to the normal CI checkout.