fix(launcher): harden Campaign LA11 gate evidence
This commit is contained in:
parent
134edabed2
commit
accd01a008
16 changed files with 1820 additions and 210 deletions
|
|
@ -53,6 +53,7 @@ New-Item -ItemType Directory -Path $Gate | Out-Null
|
|||
|
||||
pwsh -NoProfile -File (Join-Path $Repo 'tools/run-campaign-la-preflight.ps1') `
|
||||
-Repository $Repo `
|
||||
-AllowedOutputRoot $Gate `
|
||||
-OutputDirectory $Preflight
|
||||
|
||||
$Report = Get-Content -LiteralPath (Join-Path $Preflight 'report.json') -Raw |
|
||||
|
|
@ -79,8 +80,13 @@ The expected matrix is:
|
|||
|
||||
`report.json` records the tested HEAD/dirty state, OS/RID, exact commands,
|
||||
durations, exits, redacted logs, and SHA-256/size inventory. A normal preflight
|
||||
plans 30 rows. It never launches App or Headless in connected mode and
|
||||
never reads a credential. Every child starts with all inherited `ACDREAM_*`
|
||||
plans 32 rows, including the connection-free PID/status/redaction and script-
|
||||
safety contract suites. `-AllowedOutputRoot` must be a fresh, explicit
|
||||
`campaign-la-*` gate root (or the repository `logs` root), and output must be a
|
||||
fresh, empty, non-reparse strict descendant; repository, home, source, payload,
|
||||
nonempty, and arbitrary existing directories are rejected. The helper never
|
||||
launches App or Headless in connected mode and never reads a credential. Every
|
||||
child starts with all inherited `ACDREAM_*`
|
||||
variables removed, so a developer shell cannot accidentally enable live,
|
||||
installed-DAT, fixture-regeneration, or diagnostic gates. Only the optional
|
||||
row below adds the two named DAT variables back for its three exact tests.
|
||||
|
|
@ -93,6 +99,7 @@ the DAT directory may be read by tests:
|
|||
```powershell
|
||||
pwsh -NoProfile -File (Join-Path $Repo 'tools/run-campaign-la-preflight.ps1') `
|
||||
-Repository $Repo `
|
||||
-AllowedOutputRoot $Gate `
|
||||
-OutputDirectory (Join-Path $Gate 'automated-preflight-with-dat') `
|
||||
-IncludeInstalledDat `
|
||||
-InstalledDatDirectory '<ABSOLUTE_RETAIL_DAT_DIRECTORY>'
|
||||
|
|
@ -103,7 +110,7 @@ The mandatory installed-DAT result is
|
|||
`ACDREAM_DAT_DIR` set inside the child environment. The helper reads the TRX
|
||||
and fails if the test skipped or did anything other than pass. The action-map
|
||||
and portal-asset probes are additional coverage, never substitutes. Expected
|
||||
matrix size: 34 rows.
|
||||
matrix size: 36 rows.
|
||||
|
||||
On Ubuntu/WSL, invoke the same script with native `pwsh`, a Linux repository
|
||||
path, and a Linux output path. Do not treat a Windows-hosted run over
|
||||
|
|
@ -170,8 +177,11 @@ pwsh -NoProfile -File (Join-Path $Repo 'tools/new-campaign-la-update-fixture.ps1
|
|||
```
|
||||
|
||||
The helper rejects nonempty output, invalid or non-monotonic versions, missing
|
||||
root executables (including the co-deployed Bake CLI), and nonabsolute inputs.
|
||||
It writes fixed-timestamp sorted ZIPs,
|
||||
root executables (including the co-deployed Bake CLI), nonabsolute inputs,
|
||||
output/source overlap in either direction, and any reparse point in source or
|
||||
output ancestry. It enumerates normalized relative paths with ordinal ordering,
|
||||
never its own output, and normalizes ZIP host metadata so Windows/Linux hashes
|
||||
are identical under multiple cultures. It writes fixed-timestamp sorted ZIPs,
|
||||
the exact LA10 v1 SHA/size manifest, `fixture-report.json`, a loopback-only
|
||||
server (with optional bounded `-MaximumRequests` smoke mode), and an atomic A/B
|
||||
selector. Both generated helpers reject a `-Root` other than their own fixture
|
||||
|
|
@ -221,24 +231,56 @@ must preserve the same validated suffix through helper and confirmation
|
|||
restarts. The launcher, profiles, installer, current-version store, updater,
|
||||
session composer, and orchestrator must all use this one exact path set.
|
||||
|
||||
For every play/probe row, copy the session id shown in the launcher's Sessions
|
||||
list into `<SESSION_ID>`, then run:
|
||||
For every play/probe row, start this gate-only PID watcher immediately before
|
||||
clicking Refresh/Play. It correlates only the unique isolated session-config
|
||||
path, records neither command line nor config contents, and must finish while
|
||||
the child is still live:
|
||||
|
||||
```powershell
|
||||
$Status = Join-Path $WinCache 'launcher/sessions/<SESSION_ID>/status.jsonl'
|
||||
$CapturePath = Join-Path $Evidence '<ROW>-process.capture.json'
|
||||
$CaptureStart = [DateTimeOffset]::UtcNow
|
||||
$CaptureInfo = [Diagnostics.ProcessStartInfo]::new()
|
||||
$CaptureInfo.FileName = (Get-Command pwsh).Source
|
||||
$CaptureInfo.UseShellExecute = $false
|
||||
$CaptureInfo.CreateNoWindow = $true
|
||||
foreach ($Value in @(
|
||||
'-NoProfile', '-File', (Join-Path $Repo 'tools/capture-campaign-la-session-process.ps1'),
|
||||
'-SessionsDirectory', (Join-Path $WinCache 'launcher/sessions'),
|
||||
'-CreatedAfterUtc', $CaptureStart.ToString('O'),
|
||||
'-ReportPath', $CapturePath, '-WaitSeconds', '60')) {
|
||||
$CaptureInfo.ArgumentList.Add($Value)
|
||||
}
|
||||
$CaptureProcess = [Diagnostics.Process]::Start($CaptureInfo)
|
||||
# Click exactly one Refresh/Play action now, then wait for capture.
|
||||
$CaptureProcess.WaitForExit()
|
||||
if ($CaptureProcess.ExitCode) { throw 'Stop: live child PID capture failed.' }
|
||||
$Capture = Get-Content -LiteralPath $CapturePath -Raw | ConvertFrom-Json
|
||||
$SessionConfig = Join-Path $WinCache "launcher/sessions/$($Capture.sessionId)/session.json"
|
||||
$Status = Join-Path $WinCache "launcher/sessions/$($Capture.sessionId)/status.jsonl"
|
||||
|
||||
# After Stop and terminal status:
|
||||
pwsh -NoProfile -File (Join-Path $Repo 'tools/test-campaign-la-session-status.ps1') `
|
||||
-StatusFile $Status `
|
||||
-Mode '<probe|guiSelect|gui|headless>' `
|
||||
-ExpectedSessionId '<SESSION_ID>' `
|
||||
-ExpectedProcessId $Capture.processId `
|
||||
-SessionConfigPath $SessionConfig `
|
||||
-CredentialProfilePath (Join-Path $WinConfig 'launcher-profiles.json') `
|
||||
-ExpectedSessionId $Capture.sessionId `
|
||||
-ReportPath (Join-Path $Evidence '<ROW>-status.validation.json')
|
||||
```
|
||||
|
||||
Add `-ExpectedPlugin acdream.smoke` to rows D–F. The validator enforces exact
|
||||
v1 fields **and property order**, one session id, UTC monotonic timestamps,
|
||||
mode-specific lifecycle order, exit code 0/reason, no unexpected plugin/login
|
||||
command failure, credential redaction, and no surviving App/Headless process.
|
||||
Its report contains event names and a hash, not account, character, command, or
|
||||
error payloads. Keep raw `session.json`/`status.jsonl` local; never upload them.
|
||||
command failure, exact terminal `disconnected.reason == stopped`, credential
|
||||
redaction, and that exact captured PID is gone. Optional config-path correlation
|
||||
uses Windows CIM or Linux `/proc/*/cmdline`; it never globally scans a process
|
||||
name, so unrelated same-name processes and Linux's 15-character names do not
|
||||
affect the result. The validator verifies owner-only profile access, reads only
|
||||
password/secret fields in memory, recursively checks every allowed status
|
||||
string (including command/error text), and reports only the forbidden-value
|
||||
count and status hash—never credential content or a credential hash. Keep the
|
||||
profile and raw `session.json`/`status.jsonl` local; never upload them.
|
||||
|
||||
## 5. Serial Windows user rows A–H
|
||||
|
||||
|
|
@ -374,8 +416,10 @@ called. This connected row proves the actual ACE graceful-logout half. Issue
|
|||
2. Confirm ordinary selection enables Enter/Delete and disables Restore. Click
|
||||
Delete, inspect the retail confirmation dialog, cancel once, and confirm no
|
||||
state change.
|
||||
3. Delete again and confirm. Verify the wait dialog, greyed roster row/countdown,
|
||||
disabled Enter/Delete, and enabled Restore. Save `G-deleted.png`.
|
||||
3. Delete again and confirm. Verify the wait dialog, greyed/pending-delete
|
||||
roster state, constant boolean-ish nonzero `secondsGreyedOut`, disabled
|
||||
Enter/Delete, and enabled Restore. The UI must display no countdown. Save
|
||||
`G-deleted.png`.
|
||||
4. Click Restore and confirm the same GUID returns to ordinary state with
|
||||
Enter/Delete enabled and Restore disabled. Save `G-restored.png`.
|
||||
5. Close through launcher **Stop**, confirm graceful terminal status and ACE
|
||||
|
|
@ -385,6 +429,9 @@ called. This connected row proves the actual ACE graceful-logout half. Issue
|
|||
pwsh -NoProfile -File (Join-Path $Repo 'tools/test-campaign-la-session-status.ps1') `
|
||||
-StatusFile (Join-Path $WinCache 'launcher/sessions/<SESSION_ID>/status.jsonl') `
|
||||
-Mode guiSelect `
|
||||
-ExpectedProcessId '<CAPTURED_CHILD_PID>' `
|
||||
-SessionConfigPath (Join-Path $WinCache 'launcher/sessions/<SESSION_ID>/session.json') `
|
||||
-CredentialProfilePath (Join-Path $WinConfig 'launcher-profiles.json') `
|
||||
-ExpectNoEnteredWorld `
|
||||
-ExpectedSessionId '<SESSION_ID>' `
|
||||
-ExpectedPlugin acdream.smoke `
|
||||
|
|
@ -489,7 +536,9 @@ Complete this exact serial matrix:
|
|||
`stat -c '%a' "$LinuxConfig/launcher-profiles.json"`; the exact result must
|
||||
be `600`.
|
||||
3. **Probe twice:** run Refresh twice, validate both status streams in `probe`
|
||||
mode with native `pwsh`, and confirm ACE clears the account after each.
|
||||
mode with native `pwsh`, using the same pre-action watcher and exact PID,
|
||||
Linux session-config path, and `$LinuxConfig/launcher-profiles.json`; confirm
|
||||
ACE clears the account after each.
|
||||
4. **Platform posture:** confirm GUI and GUI-select client buttons are disabled
|
||||
and show the explicit Modern Runtime Slice-L message. Do not bypass this
|
||||
disablement and do not claim a Linux graphical-client gate.
|
||||
|
|
@ -521,6 +570,7 @@ logs/campaign-la-user-gate-<timestamp>/
|
|||
evidence/A-install-hashes.json
|
||||
evidence/B-*.png
|
||||
evidence/C-probe-{1,2}-status.validation.json
|
||||
evidence/*-process.capture.json
|
||||
evidence/D-*.png + D-status.validation.json
|
||||
evidence/E-*.png + E-status.validation.json
|
||||
evidence/F-*.png + F-status.validation.json
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue