0108: Record owned installation continuity after verified changes¶
Context and Problem Statement¶
Core and plugins release independently. An initial application composition cannot describe every later authorized update or removal, so comparing every launch only with that composition can undo valid changes. Inspection must not start the managed interpreter or import its plugins before deciding which installation to launch. Software changes also need to preserve the daemon's existing off or paused state and distinguish reload requests from observed code.
Considered Options¶
- Record local installation continuity after verified mutations (chosen).
- Reapply the original composition on every mismatch: can downgrade independently updated packages or restore removals.
- Inspect installed names by starting the target interpreter: startup hooks can run before inspection finishes.
- Treat a service-manager success as proof of new code: does not establish which version or contributions ran.
Decision Outcome¶
Chosen option: record local installation continuity after verified mutations, because an offline launch should respect the person's current installation without inventing publisher trust or execution permissions.
- A public kernel helper inspects an existing genuine, owned uv tool prefix without executing it. A bounded, deterministic fingerprint covers its receipt, installed package content and startup files. Generated bytecode and the continuity record itself are excluded; unsafe paths or an incomplete observation fail closed. At most three captures require two consecutive matches under the same rechecked tool authority. This permits a later stable observation, not an atomic snapshot or uninterrupted history; comparison with recorded or expected generations remains a separate requirement.
- The record is bound to the verified prefix and written atomically as a private regular file. Reading or checking it never creates or refreshes it. A missing or changed record is not silently adopted.
- A caller may refresh the record only after its explicitly authorized installation, update or plugin mutation
has passed source, version and post-install checks. Failed or uncertain changes cannot create a successful record.
It captures the candidate fingerprint after mutation and before those independent checks, then supplies that exact
digest to the required
expectedparameter; recording refuses a different observed generation. Rollback may restore old evidence only when the current installation actually matches it. - A trusted installer may remove its exact verified transient wheel overrides from the owned uv receipt after its independent checks. The helper compares a projection of the entire prefix with only those receipt bytes changed; it preserves the remaining parsed receipt fields and does not create or refresh a continuity record. An uncertain replacement leaves the private pending marker for explicit repair. Removing an override establishes neither the artifact's provenance nor permission to run it: those remain the caller's separate obligations.
- Before a managed update, a trusted lifecycle scope serializes cooperating writers and schedule admission. It records a durable pending token before uv, and retains that token when the result or verification is uncertain. The caller captures the candidate fingerprint before host metadata and runtime checks, then refreshes an existing matching continuity checkpoint only for that exact generation. A plain SDK installation without a matching checkpoint is not silently enrolled. The token clears only after verification and the captured daemon handover request; a request for an active daemon remains pending until a fresh manager-bound tick is observed.
- Host metadata inspection checks the selected core and plugin distribution identities, versions and declared
sources without starting the managed interpreter, and compares a selected archive hash where applicable. These
metadata and local-generation observations do not authenticate a publisher, every dependency, or later execution.
Target probes run with isolated Python startup; host inspection rejects executable
.pthhooks, nonphysical or external path extensions and site/user customizers. It checks every permitted in-prefix startup path before the probe. It does not attest the external interpreter's standard library or shared libraries. - A failed update may clear its own pending token only if the original content fingerprint, strict filesystem identities and previous checkpoint state still match. A rebuilt inode, changed or unavailable evidence leaves recovery pending. Selections read before the lifecycle lock are compared again inside the lock before uv; a changed receipt is reported for explicit review rather than retried with stale requirements. Automatic release decisions first compare host-inspected installed core version with the version in the running process; a mismatch requires a reload. The generation is checked again under the lifecycle lock before uv, including when floating requirements leave the receipt text unchanged. Explicitly selected sources remain an intentional choice and can name an older release subject to the tool's existing constraints. For an unpinned index requirement, an operation-private uv constraints file preserves prior constraints and adds the observed version as a lower bound. The resulting constraint is stored separately in uv's receipt and may restrict a later explicit source; changing it intentionally needs an explicit uv command. For every automatic source, host metadata must show a result at least as new as the observed version before any changed interpreter starts; if uv has already changed the tool to an older result, the pending token remains for explicit recovery.
- This is local continuity evidence. It is not publisher attestation, a Python sandbox, a human approval, or a provider/model/schedule grant. An actor controlling the same user's files can replace both state and evidence.
- Initial verified composition installation can seed the record. Legacy exact composition inspection may remain supported without writing one; unverifiable later state needs explicit inspection, never automatic downgrade.
- Daemon handover uses the state observed before a package mutation. An uninstalled, unloaded or paused daemon stays off or paused. An existing active service can reload, but service-manager acceptance alone remains pending evidence. A fresh manager-bound tick records the local version, fingerprint and contribution inventory observed by that process; it does not attest every executed instruction or establish publisher trust.
- Job dispatch holds the same nonblocking lifecycle lock as a package mutation, before the tick and session locks. A pending mutation or concurrent lifecycle writer prevents dispatch; an already running tick prevents mutation. A timed-out job thread retains the lock until it finishes or its process exits. Interpreter startup, pre-lock job compilation and independently detached external processes are outside this lock's guarantee.
- A standard installer can hold a separate quiescence context through installation. On Darwin it requires a
bounded, consistently observed Aqua manager for the owner, no loaded Heinzel label, and either no unit or an
owned, verified stopped unit. On Linux it requires the owned private user-manager socket and repeated successful, bounded
systemctl --user showobservations of both service and timer, with inactive state and no queued job. A missing or unverifiable manager is unknown, never evidence of absence. A durable pending token denies cooperating lifecycle operations after an interrupted installation; clean completion or explicit recovery requires a matching selected-installation checkpoint and fresh quiescence. This does not fence interpreter startup or noncooperating operating-system actors, and does not install or start background work. - A tool mutation captures the selected tool's external Python executable, validates its physical path, ownership, bytes and identity, and supplies that exact executable to uv. Recovery keeps the captured executable even if uv removed the tool's Python link. Installed-version observation used for an automatic update decision does not establish source provenance; the resulting candidate must still match selected sources and captured constraints.
systemd documents show as computer-parsable and --user as the calling user's manager
and unit load and active states as independent.
In systemd v257, the unit property
represents no job as (0, "/"); show
maps zero to an empty value, and its property printer
emits Job= with --all. Other versions remain fail-closed if they differ; a real Linux user-bus proof remains
required before claiming portability.
In systemd v257, show uses the manager transport
and the local user transport connects directly to $XDG_RUNTIME_DIR/systemd/private,
with peer credentials checked. The environment supplies that directory and removes session-bus overrides, so this
route does not ask a session bus to activate a manager. Versions with different transport behavior require proof.
Consequences¶
A trusted caller may temporarily append an exact-version constraint to preserve the selected core during a plugin mutation. The caller captures the original parsed receipt policy before uv, independently verifies the resulting generation and metadata, then removes only that exact appended entry if the complete ordered policy matches the captured policy plus the guard. The projected receipt generation is rechecked before any checkpoint refresh or handover. Existing duplicate constraints remain intact, and uncertain or unexpected changes are not cleaned up automatically; they require explicit inspection and recovery. The constraint itself grants no authority.
- Good: independent updates and removals survive offline relaunch, while inspection remains separate from execution.
- Bad: continuity must be maintained by every successful supported mutation, and damaged or externally changed installations can require explicit repair. Bounded fingerprinting adds startup work.
Confirmation¶
The kernel helper's temporary-file tests cover deterministic observations, receipt and entrypoint validation, unsafe paths and records, missing or changed evidence, bytecode exclusion, and inspection without starting installed code. External Python links are bound to their resolved executable bytes; this does not cover the external interpreter's standard library or shared libraries. Tool files and directories must be owned by the current user and not writable by other users; the selected external executable and its parent directories may also be root-owned, with root-owned sticky directories permitted. Successful recording rechecks the original authority and current evidence after the atomic write. A durable pending marker makes checks fail closed after an interrupted or uncertain write until explicit repair or a newly verified reinstall; it is never automatically adopted. Its successful removal is the commit point, not a permission grant. A client that loses the acknowledgement cannot infer whether the commit occurred. Cooperating writers are serialized. A concurrent change can still occur after any check, and same-user control is outside this guarantee. Ordinary receipt queries accept canonical filesystem aliases, while continuity requires a physical prefix. Mutation hooks, uncertain changes, independent updates and daemon off-state preservation still need their own tests before integration. Installed-artifact UI and daemon tests remain release gates.