Rollout operations on real endpoints
An upgrade is blocked by a running app, a browser updates itself out from under the catalog, winget is broken on a machine, or you need the platform to stop at two in the morning.
These are the questions that come up once Attestree is running on real machines rather than in a demo. They used to sit on the trust page; they live here because they are about how the agent behaves on an endpoint, not about what gets signed.
When the app you need to upgrade is the one someone is using
It defers, honestly, and that is the default. A machine-scope upgrade blocked by a running app is recorded as “deferred — app in use”, not as a failure: it holds its own distinct state, backs off on a cooldown, and is excluded from the install-fail-rate, so one busy laptop cannot make a healthy rollout look like it is failing. Before this, that same case logged a hard failure and re-spawned an elevated installer roughly ninety-six times a day on a single endpoint.
Actually closing the app is opt-in and deliberately hard to arm: it takes both a per-package flag and an endpoint group you have marked unattended before anything closes without a person present. On an attended machine the user is notified in-session, with a grace window and the option to defer. If they do click “Close now” and the app ignores it — minimize-to-tray apps treat a close request as “hide” — escalating to a real terminate needs their explicit consent, bound to their own session and re-checked against the process owner at the moment it acts, so it can never reach past their own instance. It refuses outright when it cannot restore what it would close. After the upgrade, the app comes back through its own registered auto-start entry.
Stopping everything at two in the morning
There is a platform-wide emergency stop, tripped with a typed confirmation and cleared behind a step-up challenge, with the operator who did it and the reason recorded in a signed consent span that later refusals cite back.
Be clear on what it does, because the name invites the wrong assumption. It suppresses the platform from creating and serving new work — a rollout arm, a promotion, a heal — rather than reaching out and freezing machines. Endpoints keep checking in, keep receiving the desired state they were last served, and any step already in flight finishes. It is a stop on the platform acting, not a kill signal to the fleet, and the serving-side fences take a few seconds to propagate rather than being instantaneous.
Browser-class apps: per-user scope and a version floor
Apps like Chrome, Zoom and Edge raise two separate problems, and Attestree treats each as a first-class case rather than an edge case.
Per-user scope. Whether a package is machine- or user-scope is an attested catalog property — read from the manifest, corroborated by the detonation footprint, operator-overridable. User-scope apps install impersonated in the target user’s own session through the Apache-2.0 shim, never into the SYSTEM profile, so what executes on endpoints stays readable in one open-source component. Each endpoint converges for its primary user (auto-derived, operator-pinnable), or — flagged as a shared device — for every interactive user. A target user who is not signed in shows as an honest “pending logon”, not falsely converged, and inventory attributes every per-user install to the user who actually has it.
Self-updating apps. Pinning a self-updating browser is a treadmill: the app updates itself, the fleet reads it as drift, and the reconciler proposes a destructive cross-major uninstall-and-reinstall to drag it back to a version it will immediately leave again. Instead you declare an intent that says “present, at or above this floor”. Under that assert-present declaration, running ahead of the catalog is the normal state and produces no step and no attention item; a machine below the floor is upgraded in place, and a machine without the app installs it. This needs a recent agent — endpoints below the capability floor fall back to the ordinary install behaviour.
How the agent updates itself
Through the same machinery it enforces for your packages. Agent updates roll out ring by ring; a health evaluator watches each ring and pauses or aborts the rollout automatically on bad signals; and every endpoint keeps a known-good rollback floor on disk, so a misbehaving update rolls itself back — surviving reboots mid-handoff. An update parked on a pending reboot can finalize without one, once evidence shows the new version healthy, and endpoints that stall mid-update raise a fleet alarm instead of quietly falling behind. The rollout controls — pause, abort, resume — are in-product in every edition, Community included. We dogfood the ring-and-rollback primitive on our own binary before asking you to trust it with yours.
When winget itself breaks on an endpoint
It happens more than you would think — a stale App Installer package, a SYSTEM context winget was never provisioned for. The agent probes winget health on every endpoint and surfaces broken installations as a fleet-level signal, so “the package manager is down” is a tile you see, not a mystery you debug per machine.
A guarded self-heal, repairing the winget installation in place, ships behind an operator flag — default off, never auto-rebooting — so remediation is a decision you make, not a surprise. The repair works on stock endpoints: the agent installer carries the winget PowerShell client and the Microsoft VC++ redistributable it needs, so it can fix a machine that never had them staged. And the enable flag rides inside the signed desired state, so a tampered or injected response can never arm a repair you did not authorize.