the-custodian/docs/changes/netkingdom-target-2026-10-17/native-runtime-install-r2/PROCESS-CONTRACT.md
codex ffd995213c
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Reject generated-only commits / generated-commit-guard (push) Successful in 8s
Record failed runtime trial and reviewed verification proposal (1/4)
2026-10-17 12:56:53 +02:00

68 lines
4.8 KiB
Markdown

# Revision 2 process ownership and cleanup contract
Proposal REINAH-WP-0008-T07-install-f599-r1, revision 2. No execution approval.
R1 is retained unchanged. No owner repository or immutable runtime is edited.
The public artifact retains its exact f599 digest. The pinned existing
rein_aharness.owner_rehearsal.rehearse(runtime, *, run=..., bwrap_bin=...) API
already admits a Runner callback. R2 supplies that callback rather than using
the default _run, whose subprocess.run timeout only waits/kills its immediate
process. The callback passes the same owner-built readonly/empty-egress argv
with /usr/bin/bwrap and one added --die-with-parent flag to the private bounded
runner. The source hash and all three generated arrays are frozen separately.
No default owner behavior elsewhere is claimed repaired. A future owner-wide
cleanup fix is separate; no source/authority migration is made here.
The one-action watchdog is not an installed service. Its code and private state
live only in the exact revision-2 staging directory. It is detached from the
SSH/controller session so controller SIGKILL does not prevent cleanup. It binds
the root controller with pidfd, becomes a child subreaper before spawning, and
spawns every phase plus every nested launcher itself in a distinct session.
All native job argv remain public. No shell, credentials, configurations,
provider, catalog, lease, ledger or queue is admitted to the runner.
A private JSON request includes caller PID/start/UID, argv, deadline and capture
choice. The caller must be the root or an actual watchdog descendant. Each job
is owned/waited by the watchdog; a nested launcher is a sibling of its requesting
phase, so outer timeout must abort all owned jobs rather than merely killing
the phase process group. PR_SET_PDEATHSIG prevents pre-exec parent-loss races.
The bwrap parent-death flag is defense for its sandbox descendants if their
watchdog/bwrap parent dies; the target's 0.9.0 help/manual confirm its support.
On timeout, root/caller loss, abandoned descendants, excess output or mapping
refusal, the watchdog stops the action. As a subreaper it adopts session-escaped
orphans. It enumerates actual PPID descendants, binds each with pidfd, checks UID
and start-time mapping, sends TERM, then KILL and reaps. It never signals by
name, guessed PID, shared session or global process group. Any uncertain mapping
fails the cleanup proof even if best-effort stopping appears complete. No
further launch can occur after that failure. New requests after abort are refused.
The controller closes the watchdog before staging deletion and requires BOTH its
waited successful exit and quiescent=true / no_live_or_waitable_descendants=true.
Exact staging identity and inventory checks still apply. A missing/negative
receipt, stuck watchdog or unexpected object retains staging. Abrupt watchdog
loss has no independent positive quiescence proof, so cannot enable deletion.
An SSH timeout does not establish controller death or permit cleanup.
| Event | Proof retained / allowed cleanup |
|---|---|
| Three launchers succeed and watchdog shuts down | Structured exits, full runtime rehash, waited positive quiescence; exact owned stage may be deleted |
| Phase/launcher timeout | All owned phase/nested descendants stopped/reaped first; positive proof permits only exact stage deletion; inactive artifact retained |
| Controller SIGKILL | Watchdog reacts through root pidfd, stops/reaps descendants, writes evidence; staging remains |
| Watchdog loss, uncertain mapping, missing receipt | Failed/unverified outcome, stage retained; no broad kill/delete |
| Upload failure proven before any exec | Separate conditional helper accepts only exact revision-2 before_transfer receipt/inode and four regular upload files |
| Remote exec started but SSH response lost | No retry or cleanup command; reconcile exact identities/quiescence/digest read-only and seek root recovery review |
The five local fixture cases use actual disposable Python descendants, including
setsid escape and a nested phase-to-runner request. Controller loss uses SIGKILL.
An unrelated sibling must remain alive. Results check positive/negative cleanup
receipts and discarded application stderr. The fixture does not call bwrap,
SSH, the runtime, a provider or any native owner interface. It tests process
ownership/cleanup behavior; native compatibility remains the proposed action.
Bounds: install phase 200 seconds / inner alarm 180; rehearsal phase 260 / inner
alarm 240; each unchanged launcher 60; output 64KiB; TERM grace 0.5 seconds;
KILL/reap 3 seconds; final watchdog wait 8 seconds. Scheduler or kernel failure
can exceed wall-clock expectations; missing proof fails closed. Host loss may
also leave the owner's independent .install-* copy. Its exact ownership cannot
be inferred from its prefix, so this packet authorizes no store sweep/removal.