On this page

Native scope membership during handover

API-listener takeover and resident release handover need to know whether launchd actually holds an exact service label. A matching metadata word, an installed plist, enablement policy or an unrelated live process cannot establish that. The existing handover paths share one read-only membership check rather than making separate guesses about the domain listing.

What is observed

The check names one concrete native domain: system, gui/UID or user/UID. Invalid scope input is refused before a native query. Domain listing keeps its existing unprivileged authority; this check adds no sudo, login, session or retry. A later privileged service-detail read remains the caller's separate operation and is not authorized merely by matching text elsewhere in the dump.

A usable listing must identify the exact requested domain and contain one complete recognized root services table inside a complete domain display. The supported table profile has PID, status and label columns. Only an exact label in an actual service row establishes membership. Other domain properties are not searched for matching values.

PID zero or the native no-process placeholder does not make a registered job absent. Membership says that the supervisor holds the job; it does not prove a running process, a serving port or application readiness. Those remain separate lifecycle observations.

Refusals, not guessed absence

An unreadable domain retains the attempted native operation, domain and actual exit/stderr cause. Non-UTF-8 output, a wrong domain header, missing or repeated services blocks, malformed rows, ambiguous escaped names, duplicate target records, incomplete output or trailing data refuse membership judgment. A successful process exit alone does not make an unsupported display usable.

Even when an early row matches, the complete table and domain display must be read successfully. A malformed later row does not turn a partial observation into a successful prerequisite. A complete recognized table with no matching record establishes absence; an unknown or unreadable table does not.

launchctl print is diagnostic output, not a stable native API. Unknown profiles are reported as observation failures rather than silently treated as empty. There is no second metadata-scanning fallback and no new privileged probe to hide a refused listing.

Where the result appears

These checks are prerequisites of existing takeover and release-handover flows, not a new command or another lifecycle controller. Their normal failure keeps the native scope and cause. See Keeping installed surfaces current for the existing installation/status commands and Desktop Products and Services observations, and Service reconciliation receipts for lifecycle failure provenance.

The check itself changes no registration, process, file or declaration. It does not replace readiness proof, expand scope selection, or claim that an enabled systemd unit is running. This domain-table contract is specific to launchd.

Linux systemd roster membership

Release handover reads the concrete system manager's in-memory unit roster, then the calling-account manager only if no loaded system entry matched. It uses systemctl list-units --all --full --plain --no-legend --no-pager with terminal decoration disabled. It compares the exact unit identifier locally rather than passing a unit-name glob, searching descriptions or reading installed-file policy. It does not use is-enabled or activate a definition just to inspect membership.

The complete supported roster must be readable UTF-8 with unit, load, activity and substate columns. A matching entry must have native load state loaded; an inactive loaded entry remains a membership observation, not a running verdict. A masked, missing or broken target entry, unknown load profile, duplicate target, malformed row, failed native query, or empty roster accompanied by diagnostic stderr refuses judgment. Errors retain manager scope, exact unit, calling UID, native status when available and stderr, including zero-exit unusable responses.

One positive exact scope satisfies this any-scope prerequisite. Reporting no loaded exact entry requires both scope queries to answer; an unreadable user manager is not an empty user manager. No sudo, account creation, unit load, start, retry or wait is added. File aliases and enablement do not substitute for a registration under the requested exact manager identifier. The calling-account query binds the observed effective UID's standard runtime bus, rather than accepting an inherited address as another account's observation.

The existing per-product reconcile lock owns handover reads and journal writes. Pending and refused membership observations retain the serving records in the host journal. A native read refusal records phase failed and the actual cause without stopping the proxy or recorded processes. A journal-write failure keeps that original observation beside its own cause. This does not diagnose those retained processes as dead, alive or ready.

Read that evidence with stado release doctor <product> --target <host> --json or Stado Desktop → Releases, in the selected row's phase and Detail. Recorded handover work under a replace policy remains in flight even if desired and recorded active versions match. The shared published status may instead describe the ordinary managed-service activation; it is not overwritten by a stale blue-green observation. The release-agent log also keeps the refusal, readable with stado service unit logs <label> --host <target> --lines <N>. Membership alone does not prove readiness, restart policy, port ownership or an atomic transfer; those remain separate lifecycle checks.

Listener ownership before proxy-free handover

When the release proxy no longer owns the declared loopback port, a different PID is not proof that the catalog unit took over. Every observed matching listener must establish exact native unit ownership before recorded release processes are ended or their serving state is cleared. This requirement still applies when the journal contains no proxy PID. A missing listener leaves work pending; an unreadable, foreign or ambiguous owner refuses the attempt.

The process-parent snapshot must be complete, readable and structurally valid. Malformed, repeated or missing PID rows are not silently dropped. The captured roster's own cardinality bounds ancestry walks rather than an arbitrary depth. A listener descended from a retained release PID is still retained release work, not an independent successor. Neither an executable path nor matching argv can substitute for native ownership.

On macOS the reader reuses the checked domain services-table grammar. It resolves the nearest registered native root in the concrete scope that established the prerequisite; a zero-PID registration owns no process. On Linux native unit, uunit and session-owner ouid fields must answer in the supported profile. A user-unit name alone is insufficient: its owner UID must match the calling account. Unavailable systemd support, unknown metadata or an unsupported profile refuses judgment instead of falling back to a process name.

Socket reads use explicit PID/file/name records from lsof, not its first PID. Every selected file must carry a valid local listener port. Failed, partial, malformed or diagnostic-bearing responses are not an empty socket inventory; only the documented diagnostic-free no-match result is absence. All observed holders are checked. Callers requiring one holder refuse multiple PIDs rather than selecting one arbitrarily.

The declared legacy-system predecessor uses the same positive socket/ancestry proof, without broadening its system-only admission or mutation authority. Legacy stop and restore read complete native membership rather than guessing absence from an exit code; failed verification retains the native command's status and stderr. Its other-port guard reads the captured job root's ports, not every orphan or detached descendant.

Pending and refused successor observations use the same locked journal, release doctor and Desktop Releases Phase/Detail path described above. An unknown owner does not authorize cleanup. These are ownership observations, not application readiness, PID-reuse binding, global socket visibility, termination proof or an atomic handover guarantee.

Keep the prerequisite's native scope

Release handover carries the exact native unit name and concrete scope from membership into listener ownership. A same-named job in another domain is not the observed successor. Linux system ownership cannot be satisfied by the calling account's user unit, or vice versa. A macOS GUI observation cannot be satisfied by a same-named system registration.

The existing search order remains: macOS reads the effective calling UID's gui/UID domain and then system membership only after a usable negative GUI observation; Linux reads system membership, then the calling user manager only after a usable negative system observation. Failed or unsupported reads refuse selection rather than silently trying another account or manager. This does not infer a system-only deployment from an unavailable GUI domain.

Later ownership reads stay within the selected concrete scope. They do not widen to any, query unrelated domains or create a login. The local process ownership observer rejects non-concrete scopes before querying; other lifecycle operations retain their own scope contracts. Canonical systemd unit naming is carried with the selected scope rather than re-created for each observation.

Scope and owner refusals keep their original native context in the journal, release doctor and Desktop Releases Phase/Detail. Missing registration means recorded work is retained; it does not prove that a proxy or old process is currently serving. Platform support and readiness still require their own real observations.

Retain every pre-stop refusal

After a valid host-journal load, handover retains failures in directory/service binding, catalog lookup, proxy inspection, endpoint decoding, native membership and successor ownership through the same terminal prerequisite recorder. The failed observation names its operation and actual cause, sets phase failed and preserves proxy, active, candidate and previous serving records. It does not authorize cleanup or diagnose those records as live or ready.

This recorder applies only before an explicit proxy stop or release-process termination attempt. Its statement that this attempt stopped nothing cannot be used as evidence about an operation that has already been attempted.

If saving fails, the returned failure keeps both the original observation and the journal-write cause. The stored journal was not refreshed: an older row is not evidence that the new observation was saved. Read the release-agent failure with stado service unit logs <label> --host <target> --lines <N>. An unreadable initial journal is not replaced with a manufactured empty state; its own load error remains, without a fabricated durable refusal.

Saved stop intent and uncertain outcomes

When the release proxy owns the bind, handover saves intent before requesting its stop. A failed intent write returns before that request. The detail keeps the owner PID seen during inspection as an observation, not a guarantee that the next control connection reaches that same PID.

A refused or unreadable stop result records phase failed, its actual control cause and unverified proxy effects, preserving every serving record. It does not claim that the proxy was untouched: shutdown may precede a lost reply. No recorded release-process termination is attempted on that failure path.

After a successful control acknowledgement, handover saves that observation before entering recorded release-process cleanup. If saving fails, the returned error keeps the acknowledgement beside the write cause and cleanup does not proceed. The stored row may still show intent only; neither intent nor a failed save is a completed handover receipt.

Intent and acknowledgement details keep the existing rollout phase; they do not invent a readiness or completed-handover phase. Recorded work remains in flight through the existing doctor/API/Desktop path. The journal holds the latest observation, not an append-only history or exactly-once protocol. Control acknowledgement is not connection drainage, application readiness, PID-reuse binding, verified release-process termination or atomic transfer.

Source: this website