main
Drew Owens 0.6.9 source: launch resilience, honest counts, ownership persistence, drain, quit ladder — 21 adversary passes, 303 te… cf16621 1mo ago
//! ADVERSARIAL REVIEW OF 0.5.3 — final pass.
//!
//! Every pass-7 closure holds AT THE MECHANISM, not just at the test:
//!
//!   D-1  the `canonical` arm is gone; `temp_root: None` returns false before
//!        anything else is examined; the root is normalised for separators,
//!        trailing slash and case; segment COUNTS must be equal (no prefix
//!        trickery); and `is_short_form_of` requires the 8.3 head to be exactly
//!        `min(len, 6)` characters, so `a~1` cannot stand in for `adversary`.
//!   Q-1  `StopEvidence::sweep` + `check(force)` run before EVERY rung after the
//!        first, with an identity comparison that yields `stop_identity_changed`.
//!   Q-2  the mock has `exitAfterMs`; the ladder polls rather than taking one
//!        sample.
//!   Q-3  only a `swCefSubProc.exe` whose `ppid` IS this session's pid counts.
//!   Q-4  `listed_documents` is now a parameter of `check_preconditions`.
//!   Q-5  `GetWindowThreadProcessId` re-verifies the hwnd before a message rung.
//!   G-1  `require_bridge_launched` exists in the gate.
//!   plus `censusReadable` on the evidence block.
//!
//! What is left is the risk the tightening itself created, and it is the one
//! that decides whether tomorrow's drain step means anything.

mod common;

use common::{Bridge, TempDir};
use serde_json::{json, Value};

fn s(v: &Value) -> String {
    serde_json::to_string_pretty(v).unwrap_or_default()
}

/// THE ANCHOR IS ONLY AS GOOD AS THE ROOT IT RESOLVES.
///
/// `temp_root()` reads the BRIDGE PROCESS's `%TEMP%`, and `is_import_temp_under`
/// then requires the document's path to sit exactly under it. That is right, and
/// it closes the data-loss hole. But the two can legitimately differ: the com
/// host inherits ab's environment, and ab may run under a service profile, a
/// redirected `TEMP`, or simply a different account from the interactive session
/// SOLIDWORKS lives in. More to the point, the 1342 leaked temps this verb
/// exists for were written by a DIFFERENT, DEAD bridge process — the design
/// deliberately does not check the pid, but it does now assume that process's
/// `%TEMP%` is ours.
///
/// When the roots disagree the drain matches nothing. It then reports
/// `success:true`, `closed:0`, `done:true`, and a hint that says **"Every open
/// STEP/IGES import temporary was closed."** Three of them are open. That is a
/// confident wrong claim about the user's session, and the operator running
/// launch → drain → quit tomorrow would read step 2 as done and be surprised by
/// the quit gate refusing on 1342 open documents.
///
/// A miss is the safe direction for the CLOSE. It is not the safe direction for
/// the REPORT.
#[test]
fn a_drain_that_matched_nothing_does_not_claim_it_drained_everything() {
    // The bridge's %TEMP% is not the one the documents' paths sit under.
    let b = Bridge::start_with(&[("SWX_TEMP_ROOT", r"C:\Windows\Temp")]);
    b.call("swx_start", json!({"reason": "importing"}));
    let steps = TempDir::new("adv8-steps");
    for i in 0..3 {
        let p = steps.join(&format!("Widget{i}.step"));
        std::fs::write(&p, b"ISO-10303-21;\n").unwrap();
        b.call("swx_import", json!({"filePath": p.to_string_lossy()}));
    }
    let docs = b.call("swx_docs", json!({}));
    assert!(
        docs["count"].as_u64().unwrap_or(0) >= 3,
        "precondition: import temporaries are open: {}",
        s(&docs)
    );

    let r = b.call("swx_close_import_temps", json!({"reason": "draining leaked temps"}));
    let closed = r["closed"].as_u64().unwrap_or(0);
    let hint = r["_hint"].as_str().unwrap_or("");
    assert!(
        !(closed == 0 && hint.contains("Every open STEP/IGES import temporary was closed")),
        "the drain matched NOTHING (closed:0) with {} documents open whose paths carry the \
         launcher's swx<pid>\\IC~~\\<file> tail, and reported that every import temporary was \
         closed. The %TEMP% this bridge resolved is not the one those paths sit under, and the \
         response says nothing about it: no tempRoot, no count of tail-matching documents that \
         failed the root test. A caller cannot tell 'there was nothing to drain' from 'I compared \
         against the wrong directory'.\n{}\n--- server log ---\n{}",
        docs["count"],
        s(&r),
        b.log()
    );
}

/// The same fact stated for the operator: whatever the drain concludes, the
/// response has to name the root it compared against, or a mismatch is
/// undiagnosable from the output.
#[test]
fn the_drain_reports_the_temp_root_it_compared_against() {
    let b = Bridge::start_with(&[("SWX_TEMP_ROOT", r"C:\Windows\Temp")]);
    b.call("swx_start", json!({"reason": "importing"}));
    let steps = TempDir::new("adv8-steps2");
    let p = steps.join("Widget.step");
    std::fs::write(&p, b"ISO-10303-21;\n").unwrap();
    b.call("swx_import", json!({"filePath": p.to_string_lossy()}));

    let r = b.call("swx_close_import_temps", json!({"reason": "draining leaked temps"}));
    let text = s(&r).to_lowercase();
    assert!(
        text.contains("temproot") || text.contains("windows\\\\temp") || text.contains("temp root"),
        "the drain's response does not say which %TEMP% it required the documents to sit under, \
         so a no-op cannot be told from a root mismatch. One field (`tempRoot`) makes the \
         difference diagnosable on a live machine where nobody can attach a debugger.\n{}",
        s(&r)
    );
}