diff --git a/history/fp-driver-d2-4229f9ac.sh b/fp-driver-d2.sh index d99ac9ad..e1783da1 100644 --- a/history/fp-driver-d2-4229f9ac.sh +++ b/fp-driver-d2.sh @@ -202,7 +202,13 @@ TEARDOWN_B64_SHA256='416280dbece2601203c74c3f8e2c46e13009125fa5870166894e079329f # Nothing is composed, and nothing unreviewed can ride along inside a literal that merely looks # right. RULE_PROBE="$PRESERVED_D2/rule-probe.ps1" -RULE_PROBE_SHA256='1e007cdc84582b4739137b06505b7e2f242581f6dafc8546a5ae89be2cf11756' +RULE_PROBE_SHA256='be016198d860076c58257953bf2342fc35fea54550e373aae7e0f2b60132bcee' + # STALE PIN, CAUGHT BY doyle 2026-09-13: this still named the + # probe as it was BEFORE its argument transport was corrected, + # so removal_check would have refused the shipped probe as + # UNPINNED at run time and no removal could ever be confirmed. + # The controls did not catch it because the harness recomputed + # this value instead of reading the driver's own. # THE INDEPENDENT POST-REMOVAL CHECK. The product reporting its # own success is the claim under test, and the census counts # ActiveStore rules by GROUP and PORT -- neither can say which @@ -502,7 +508,20 @@ handoff_request() { # NAME DESCRIPTION COMMAND-TEXT echo "run: $RUN_ID" echo "requested_utc: $(date -u +%Y-%m-%dT%H:%M:%SZ)" echo "for: $2" - echo "elevation: REQUIRED — the trial driver is unelevated by assertion (S0a) and will not run this itself" + # THE AUDIENCE IS PART OF THE REQUEST (doyle XS5VAWJQ). A request that says "elevation: + # REQUIRED" is addressed to the elevated executor. An AUTHORIZATION is not an action and is + # not the executor's to give: readiness comes from whoever would run the leg, authorization + # comes from the DRI, and stamping both with the same header made them one channel. + case "${4:-executor}" in + doyle) + echo "audience: doyle (the DRI) — THE ELEVATED EXECUTOR MUST NOT ANSWER THIS REQUEST" + echo "elevation: NOT_REQUIRED — this is an authorization, not an action; nothing is run to answer it" + ;; + *) + echo "audience: the elevated executor" + echo "elevation: REQUIRED — the trial driver is unelevated by assertion (S0a) and will not run this itself" + ;; + esac echo "run_exactly:" echo "$cmd_exact" echo "receipt_file: $HO_RECEIPT" @@ -600,6 +619,7 @@ CLEANUP_STOP_STATE=NOT_REACHED # which gate outcome step 1 took (IR-124) TEARDOWN_DISPATCH=NOT_REACHED # whether a teardown command was dispatched, and why not REMOVAL_CHECK=NOT_REACHED # the INDEPENDENT reading, by name and by store REMOVAL_PRE=NOT_REACHED # the same reading taken BEFORE any teardown was asked for +DAEMON_STOP_STATE=NOT_REACHED # which gate outcome the daemon stop took, reported either way # ---- THE PINNED REMOVAL INSTRUMENT, VERIFIED TWICE (doyle 2026-09-13) -------- # Once BEFORE GO -- a run that cannot remove what it is about to create must never open the # window -- and again immediately BEFORE USE, because the file can change in between and the @@ -1375,7 +1395,31 @@ cleanup() { # DAEMON_STOP_REFUSED is EXPECTED here (IR-122): the rig's isolated-daemon stop is # structurally unrunnable from an spt-hosted session, and that refusal is reported, # never worked around. + # THE SAME GATE AS THE LISTENER (doyle 2026-09-13). daemon_may_run is marked BEFORE the setup + # is dispatched, so it says what this run INTENDED, not what the host holds. The marker decides + # whether the question is asked; a FRESH measurement decides whether the command runs. + # attributed LIVE -- a tracked identity of this run is measured running: the reviewed stop path + # may be entered, because there is something to stop. + # measured ABSENT -- nothing of this run is running: SKIP. No command. + # UNREADABLE -- attribution could not be established: PENDING/review, and no action. + # THIS IS NOT A CLAIM THAT `daemon stop` SPAWNS ANYTHING. Nothing here measures that, and the + # gating mismatch alone would not establish it. The reason for the gate is narrower and enough: + # acting on a marker that was never a measurement is not justified by the marker. if has_state daemon_may_run; then + residue_scan pre-daemon-stop no + if [ "$RESIDUE_LIVE" -gt 0 ]; then + DAEMON_STOP_STATE=ADMITTED + record "DAEMON_STOP_ADMITTED - $RESIDUE_LIVE tracked identity/identities measured LIVE by pid + creation time; the stop has something to stop" + elif [ "$RESIDUE_UNREADABLE" -gt 0 ]; then + DAEMON_STOP_STATE=WITHHELD_UNREADABLE + CLEANUP_VERDICT=PENDING + record "DAEMON_STOP_WITHHELD residue=UNREADABLE ($RESIDUE_UNREADABLE identity/identities) - NO stop is issued on an unreadable measurement. Disposition PENDING/review." + else + DAEMON_STOP_STATE=NOT_NEEDED + record "DAEMON_STOP_NOT_NEEDED - daemon_may_run was marked, but every tracked identity measured GONE (live=0 unreadable=0). NO COMMAND IS ISSUED." + fi + fi + if [ "${DAEMON_STOP_STATE:-NOT_REACHED}" = ADMITTED ]; then run_cmd rig_daemon_stop "$R/rig-daemon-stop.out" "$R/rig-daemon-stop.err" -- \ env SPT_HOME="$H" "$EXE" daemon stop DAEMON_STOP_RC=$? @@ -1395,7 +1439,8 @@ cleanup() { record "DAEMON_STOP_REFUSED (expected, IR-122) — reported, never worked around. Whether anything REMAINS is decided by the residual-identity measurement below, not by this exit." DAEMON_STOP_REFUSED=1 fi - else + elif ! has_state daemon_may_run; then + DAEMON_STOP_STATE=NOT_MARKED record "CLEANUP_SKIP daemon — no daemon_may_run state was ever marked" fi @@ -1564,7 +1609,7 @@ d2_ledger() { echo " residual_state=$residual (CLEAR = measured gone; LIVE = seen; UNREADABLE = not measurable, and NOT the same claim)" echo " tracked_process_identities: live=${RESIDUE_LIVE:-0} gone=${RESIDUE_GONE:-0} unreadable=${RESIDUE_UNREADABLE:-0} (re-queried by pid + creation time + executable + command line)" echo " identity_capture=${CAPTURE_USABLE:-not-attempted} (${CAPTURE_INTEGRITY:-no capture was needed}) -- an incomplete capture can never support CLEAR" - echo " cleanup_stop_gate=${CLEANUP_STOP_STATE} teardown_dispatch=${TEARDOWN_DISPATCH}" + echo " cleanup_stop_gate=${CLEANUP_STOP_STATE} daemon_stop_gate=${DAEMON_STOP_STATE:-NOT_REACHED} teardown_dispatch=${TEARDOWN_DISPATCH} removal_pre=${REMOVAL_PRE:-NOT_REACHED} removal_post=${REMOVAL_CHECK:-NOT_REACHED}" echo " rig_daemon_stop_exit=${DAEMON_STOP_RC:-NOT_RUN} listener_after_cleanup=${LISTENER_STATE:-UNMEASURED}" echo " CLEANUP=$CLEANUP_VERDICT residue=${RESIDUE_COUNT:-UNMEASURED} daemon_stop_refused=${DAEMON_STOP_REFUSED:-0} (IR-122: expected from an spt-hosted session; the residue count is what decides whether anything remains)" echo " experimental_ended=[$EXPERIMENTAL_ENDED]" @@ -2042,6 +2087,11 @@ handoff_request prepare \ "ACKNOWLEDGE ONLY -- RUN NOTHING. Confirm you are prepared to execute the setup leg and that you have started nothing yet, and report the sha256 of BOTH subjects this leg would run, AS YOU MEASURE THEM NOW: the pinned executable and the capture script." \ "ACKNOWLEDGEMENT ONLY. Do not run the product. Reply in the receipt with these four tokens, EACH ON A LINE OF ITS OWN AND NOTHING ELSE ON THAT LINE: PREPARED, NOT_STARTED, executable_sha256=, capture_sha256=. If you are NOT prepared, say so in words -- do not write NOT_PREPARED on a line by itself and expect it to read as a refusal." PREPARED_ACK="$HO_RECEIPT" +# BOUNDED BY WHAT IS LEFT OF PREPARATION (doyle 2026-09-13). HANDOFF_WAIT_S is 900s and the whole +# preparation budget is 600s, so an unbounded-by-prep wait could sit past the deadline and then +# open a window the budget had already closed. Same narrowing the cleanup wait already does. +HANDOFF_WAIT_S=$(prep_left) +record "PREP_HANDOFF_WAIT bounded to ${HANDOFF_WAIT_S}s — what remains of the preparation budget" # NOT `if ! handoff_await trial`: that exact line is the anchor of an assembly-time correction # applied to the RETAINED setup wait, and the assembler asserts it appears exactly once. Same # call, same context, written so the anchor stays unique -- the rig refused this and was right. @@ -2077,12 +2127,21 @@ record "PREPARED_IS_NOT_AUTHORIZATION - readiness says the leg CAN act; it does # bound to THIS run and THIS request and cannot be a stale or reused token from another. prep_check go-authorization handoff_request go-authorization \ - "AUTHORIZE ONLY -- RUN NOTHING. This is not a readiness question; you have already answered that. Authorize the experimental window to OPEN for this run, knowing the 300s activity clock starts when it does." \ - "AUTHORIZATION ONLY. Do not run the product. Reply in the receipt with BOTH: the token GO_AUTHORIZED on a line of its own and nothing else on that line, and the nonce of THIS request quoted exactly (anywhere). To WITHHOLD authorization, say so in words -- there is no negative token this check reads." + "AUTHORIZE ONLY -- RUN NOTHING. FOR THE DRI, NOT FOR THE ELEVATED EXECUTOR: readiness has already been acknowledged by the leg that would run this, and that acknowledgment is not this decision. Authorize the experimental window to OPEN for this run, knowing the 300s activity clock starts when it does." \ + "AUTHORIZATION ONLY. Nothing is run to answer this. Reply in the receipt with THREE things: the token GO_AUTHORIZED on a line of its own and nothing else on that line; the line authorizer=doyle, likewise alone on its line; and the nonce of THIS request quoted exactly (anywhere). To WITHHOLD authorization, say so in words -- there is no negative token this check reads." \ + doyle GO_ACK="$HO_RECEIPT"; GO_ACK_NONCE="$HO_NONCE" +HANDOFF_WAIT_S=$(prep_left) +record "PREP_HANDOFF_WAIT bounded to ${HANDOFF_WAIT_S}s — what remains of the preparation budget" handoff_await trial || die "no GO authorization within the preparation budget. The experimental window is NEVER OPENED: readiness alone does not open it, nothing was dispatched, and there is nothing to tear down." go_missing='' ack_line "$GO_ACK" "GO_AUTHORIZED" || go_missing="$go_missing GO_AUTHORIZED" +# THE AUTHORIZER IS NAMED, AND THAT IS A ROUTING CHECK, NOT AUTHENTICATION (doyle XS5VAWJQ). +# It establishes that the receipt answering this request claims to be the DRI's decision rather +# than the executor's; it cannot establish WHO wrote the file, and nothing here should be read as +# if it could. The operational authorization is doyle's own run-and-nonce-bound message; this +# receipt RECORDS that decision and does not create it. +ack_line "$GO_ACK" "authorizer=doyle" || go_missing="$go_missing authorizer=doyle" # THE NONCE KEEPS ITS SUBSTRING MATCH, deliberately: it is quoted inside a line the executor # writes in its own words ("nonce: "), and it is a run-scoped value that nothing else on # the receipt can accidentally contain. @@ -2091,7 +2150,7 @@ if [ -n "$go_missing" ]; then record "GO_ACK_CONTENTS: [$(tr -d '\r' < "$GO_ACK" 2>/dev/null | tr "\n" " ")]" die "the GO authorization is missing:$go_missing. An authorization that cannot quote the nonce of the request it answers is not bound to this run, and this window does not open on it." fi -record "GO_AUTHORIZED_VERIFIED nonce=$GO_ACK_NONCE - a separate, run-bound authorization, distinct from the readiness acknowledgment" +record "GO_AUTHORIZED_VERIFIED nonce=$GO_ACK_NONCE authorizer=doyle - a separate, run-bound authorization from the DRI, distinct from the executor's readiness acknowledgment. The identity line is a routing and consistency check, not authentication: it records whose decision this receipt claims to carry." # THE REMOVAL INSTRUMENT IS REQUIRED BEFORE THE WINDOW OPENS (doyle 2026-09-13). # A run that cannot remove what it is about to create must never create it. The predecessor @@ -2106,6 +2165,12 @@ if ! teardown_pin_verify pre-go; then die "the reviewed rule-removal instrument is not available (state=$TEARDOWN_PIN_STATE). The experimental window is NEVER OPENED: nothing is dispatched, nothing is created, and there is nothing to tear down. This is a refusal to start, not a failed run." fi +# THE DEADLINE IS RE-READ IMMEDIATELY BEFORE THE WINDOW OPENS (doyle 2026-09-13). Every check +# above was taken when it ran; a receipt can arrive after the preparation budget has expired, and +# an authorization that is verified late must not open a window the budget had already closed. +# prep_check refuses with exit 8 -- a run that never started, with nothing to tear down. +prep_check window-open + # THE WINDOW OPENS HERE AND NOWHERE ELSE. go "GO authorization verified (run-bound), both subject hashes measured by the executor, and the reviewed removal instrument verified"