Skip to content

feat(native): authenticated read-only consumer configuration (re-proposes #501 code) - #619

Merged
hanthor merged 7 commits into
mainfrom
claude/cool-hopper-zwie7w-winui-c-configuration
Oct 15, 2026
Merged

hanthor merged 7 commits into
mainfrom
claude/cool-hopper-zwie7w-winui-c-configuration

Conversation

@hanthor

@hanthor hanthor commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

Re-proposes the code from #501 (closed because ~170k of its 175k added lines were evidence blobs) on current main, with compact evidence only. Refs #344.

What it adds

Engine (app/)

  • One versioned, read-only GetNativeConfiguration RPC. It returns a NativeConfigurationSnapshot: admitted images, defaults, bundle metadata, the support policy and physically identified storage choices.
  • Only the authenticated native transport can register it (newConfigurationAssessmentServer). The original assessment constructor still allows only GetStatus, GetLastRun and GetRecoveryVerdict. The new method takes no parameters and runs the startup validation first.
  • Storage observation (native_storage_*, native_storage_query.ps1) runs the system PowerShell from its protected canonical path and imports modules from protected paths, not inherited PATH or PSModulePath. Observations bracket the metadata read and recheck GPT disk and partition GUIDs, protection state and the full NTFS serial. A missing protection observation is a refusal.
  • GetSupportPolicy and GetImages are split into pure functions (supportPolicyFor, resolveImageCatalogue) so legacy and native callers share one policy. Behaviour of the legacy methods does not change.

Shell (shell/)

  • ConsumerConfiguration / ConfigurationProjection (Core, Linux-testable): form state and an install-blocked reason. Install stays disabled; nothing in this PR can start an operation.
  • NativeConfigurationProtocol decodes the snapshot and refuses incomplete, duplicate, foreign-brand and false-authority observations.
  • MainWindow: a "Read Linux configuration" button and a configuration form inside the existing branded card. Private fields and selections clear on disconnect, on a failed read, and on window close. Diagnostics from a stale connection generation are dropped.
  • Generated Dto.cs is current (go generate makes no diff).

Checks

  • New native-configuration.yml (one windows-latest job, 10 min): runs the TestNativeConfiguration* Go controls against the runner's real storage and writes a receipt plus raw output as an artifact.
  • winui-preview.yml: path filters for the new files, plus the configuration flush control step and its artifact.

Changes from #501 beyond the rebase

  • MainWindow.xaml conflicted with feat(shell): native brand assets, minimum-OS gate and real UAC refusal #611's branded card. This keeps the card and puts the form inside it, under a ScrollViewer.
  • native-configuration.yml now uses the repo's SHA-pinned actions, a concurrency group and the Go module cache (Add authenticated native consumer configuration assessment #501 used tag refs and cache: false).
  • shell/.gitignore keeps dotnet bin/ and obj/ output out of commits (main has no such rule).
  • Cold-start budget (found by this PR's hosted runs). The first installed-package run on two brands (wootc, tunaos) ended the configuration read at the engine's own 10 s deadline. A cold Windows PowerShell 5.1 start plus module and CIM loads takes a little more than that on a runner whose steps use PowerShell 7. The budgets are now named and nested: storage query 30 s < whole read 40 s < shell wait 50 s < the 60 s diagnostic bound. A Go test checks the order and reads the shell's wait from NativeEngineSession.cs.
  • held-stderr fixture. The fixture's descendant powershell.exe received the helper's stdin, which is the session request pipe, so it could take the test's request lines. It now gets a private, closed stdin and signals readiness, and the fixture assembly is compiled outside the guarded session. The 5 s observation and all assertions are unchanged. The control script prints failing control names and their file:line messages in the job log.
  • No docs/experiments/evidence/2026-09-27-native-configuration/ tree (471 files, ~170k lines). The hosted receipts are workflow artifacts; a short summary with hashes goes in a comment here.

Validation (head 588e49e)

Local: go build/vet (Linux and GOOS=windows), go test ./..., GOOS=windows go test -c, go generate (no diff), dotnet test Wootc.Shell.Tests (47 passed), Linux builds of NativeTests/UiTests, actionlint, docs-truth.bats 51/51, STE 1231 within budget 1235.

Hosted, all green on 588e49e:

Check Run Result
Actual Windows configuration and storage controls 38812653272 "controls PASS; no skipped controls"
WinUI preview: native build (adapter tests, flush control, startup UIA) and branded package wootc (installed configuration view) 38812653247 pass
Assessment RPC, read-only status, standard-user ACL controls 38812653152, 38812653176 pass
Fast tier, lint, STE 38812653161 pass

The installed configuration view also passed for aurora and bluefin on earlier heads of this PR after the budget fix, and for bazzite and tunaos through #620.

Still unproven

  • This is not the Phase C install journey. It does not prove interactive UAC, Home edition, build 17763, or any installation. The Wails installer and its release assets stay the default.

🤖 Generated with Claude Code

https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN


Generated by Claude Code

…oses #501 code)

Re-proposes the ~4k lines of code from #501 on current main, without the
~170k lines of evidence blobs that closed it.

The engine gains one versioned, read-only GetNativeConfiguration snapshot
for the authenticated native transport: image admission, defaults, bundle
metadata and physically identified storage choices. Storage observations
bracket the metadata read and recheck GPT disk/partition GUIDs, protection
state and the full NTFS serial; the system PowerShell and its modules load
from protected canonical paths, not inherited PATH or module search. The
original three-read assessment constructor stays restricted, and the new
constructor refuses mutators before backend work.

The shell decodes the snapshot (refusing incomplete, duplicate,
foreign-brand and false-authority observations) and shows a configuration
form under the branded card. The form clears private fields on disconnect
or a failed read. Install stays disabled.

Changes from #501 beyond the rebase: MainWindow.xaml keeps main's branded
card and adds the form inside it under a ScrollViewer;
native-configuration.yml uses the repo's SHA-pinned actions, a concurrency
group, and the Go module cache. shell/.gitignore keeps dotnet bin/ and
obj/ output out of commits.

Refs #344, #501.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
@hanthor-hive-agent

Copy link
Copy Markdown
Contributor
26a8fdb

ℹ️ Sentinel notice — informational; author is trusted (owner), merge is not blocked

Hive flagged this PR (author @hanthor, head 26a8fdba93eb) because it matches behaviors that can override security controls, escalate privileges or damage the codebase. This is a heuristic, not an accusation — a maintainer should confirm the change is intended before it merges.

  • sensitive_path — changes 2 sensitive path(s) (Touches a sensitive path (OWNERS, workflows, policies, hive config, security docs, …))
    • .github/workflows/native-configuration.yml
    • .github/workflows/winui-preview.yml

Hive did not add the sentinel-alert label because this author is trusted. The finding remains recorded for audit and the dashboard Security tab; set sentinel.trusted_authors_block: true to require the blocking label for trusted authors too.

Picks up #618 (winui-preview restructure). The configuration flush
control step stays in native-build; no Windows job is added.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
hanthor pushed a commit that referenced this pull request Oct 15, 2026
…o claude/cool-hopper-zwie7w-winui-c-drive-contract

Picks up #618 through #619. The e2e-drive fixture path stays in the
winui-preview filter; the C# drive tests run in core (ubuntu) and in
native-build's Windows Wootc.Shell.Tests step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
@hanthor-hive-agent

Copy link
Copy Markdown
Contributor
5f4f2f0

ℹ️ Sentinel notice — informational; author is trusted (owner), merge is not blocked

Hive flagged this PR (author @hanthor, head 5f4f2f05d0ff) because it matches behaviors that can override security controls, escalate privileges or damage the codebase. This is a heuristic, not an accusation — a maintainer should confirm the change is intended before it merges.

  • sensitive_path — changes 2 sensitive path(s) (Touches a sensitive path (OWNERS, workflows, policies, hive config, security docs, …))
    • .github/workflows/native-configuration.yml
    • .github/workflows/winui-preview.yml

Hive did not add the sentinel-alert label because this author is trusted. The finding remains recorded for audit and the dashboard Security tab; set sentinel.trusted_authors_block: true to require the blocking label for trusted authors too.

Both branded installed-package runs on #619/#620 failed the first
GetNativeConfiguration with the engine's own deadline diagnostic at
about 10.9 s (storage-first-query, Context:deadline, Exit:1):
run 38801276457 (wootc) stopped in the script's last phase,
"serialize"; run 38801326196 (tunaos) stopped before its first phase.
The packaging job runs its steps in PowerShell 7, so the engine's
storage query is the first Windows PowerShell 5.1 start on that runner,
and the cold start plus module and CIM loads exceeds the 10 s budget.
The native-configuration job passes because its own steps already run
Windows PowerShell 5.1.

The budgets are now named and nested: storage query 30 s < whole
configuration read 40 s < shell wait 50 s < the 60 s bound both
diagnostic decoders enforce. A slow read therefore still ends with the
engine's typed diagnostic. A Go test checks the order and reads the
shell's wait from NativeEngineSession.cs; a mutant with a 35 s shell
wait fails it. The installed UI test waits 60 s for the view.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
hanthor pushed a commit that referenced this pull request Oct 15, 2026
…l-hopper-zwie7w-winui-c-drive-contract

Picks up the configuration cold-start budget fix from #619.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
native-configuration controls failed on 23e827e after the budget fix.
TestNativeConfigurationActualPreparedStorageSnapshots kept its own 10 s
context; it makes the first real storage query in the test binary, so it
meets the same Windows PowerShell cold start as the product. It now uses
nativeStorageQueryBudget.

The control script now prints the failing or missing control names and
the go test return code in the job log, so a failure is readable without
the artifact. The budget-nesting test joins the required set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
hanthor pushed a commit that referenced this pull request Oct 15, 2026
…l-hopper-zwie7w-winui-c-drive-contract

Picks up the storage-control budget fix from #619.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
With failing control names now in the log, run 38808993687 shows the
remaining native-configuration failure is
TestNativeConfigurationPreparedStorageTransportRefusals/held-stderr.
The fixture started a descendant powershell.exe and slept 1.5 s, then
the test required the descendant's "owned-descendant-started" marker in
the held stderr pipe. A slower descendant start loses that race without
any product fault. The case uses its own 5 s context, so the budget
change in this PR does not touch it.

The descendant now writes its stderr marker and then a readiness line on
its redirected stdout; the helper reads that line before it answers. The
marker is therefore in the pipe before the first query returns. The
five-second observation deadline and every assertion are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
hanthor pushed a commit that referenced this pull request Oct 15, 2026
…l-hopper-zwie7w-winui-c-drive-contract

Picks up the held-stderr fixture fix from #619.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
held-stderr failed on 65b9966 (fixed sleep) and 4b50d6d (readiness
handshake). Root cause: the fixture helper starts its descendant with
.NET Process.Start, UseShellExecute=false and only stdout redirected.
.NET then gives the descendant the helper's own stdin, which is the
session request pipe, and Windows PowerShell reads redirected stdin as
$input until EOF. The descendant therefore competes with the helper for
the test's "nonce|N" request lines. When it takes one, the helper never
answers, the query dies at the 5 s context, and the stderr marker races
the job cleanup. The earlier pass was a lucky ordering; the readiness
handshake made the theft certain, because the descendant was always
running before the helper read its first request.

The descendant now gets a private stdin that the helper closes at once,
so its read ends at EOF and it inherits only the stderr pipe this case
is about. The readiness line then orders the stderr marker before the
first answer. The five-second observation deadline and all assertions
are unchanged.

The control script now also prints the failing tests' own
file:line messages (at most 40 lines), because the artifact host is not
reachable from every reviewer environment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
hanthor pushed a commit that referenced this pull request Oct 15, 2026
…l-hopper-zwie7w-winui-c-drive-contract

Picks up the held-stderr stdin isolation fix from #619.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
…sion

held-stderr on cbdcb2f printed its reason (job 116687773615):
"native_storage_session_windows_test.go:122: bounded fixture compilation
failed storage observation command refused". Line 122 calls
prepareNativeHeldStderrAssembly, which compiled the P/Invoke fixture by
replacing nativeStorageQuery with an Add-Type script and running it
through the production storage session. That session refuses anything
off its contract with one fixed error class, so a slow or failed cold
Add-Type/csc compile could only show as a refusal, with the reason left
in the artifact.

The fixture assembly is scaffolding, not code under test. It is now
compiled by a plain exec.CommandContext of the system Windows
PowerShell, under its own 60 s bound, and a failure logs the elapsed
time, the error and up to 4 KiB of the compiler output. Only the timed
held-stderr observation still runs through the guarded session, with the
same exact assembly bytes (hash checked), the same five-second deadline
and the same assertions.

The control script's go test bound rises from 90 s to 150 s (subprocess
240 s), because the run now holds a 60 s fixture bound and 30 s storage
budgets; the job limit stays 10 minutes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
hanthor pushed a commit that referenced this pull request Oct 15, 2026
…l-hopper-zwie7w-winui-c-drive-contract

Picks up the held-stderr fixture compilation fix from #619.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
@hanthor

hanthor commented Oct 15, 2026

Copy link
Copy Markdown
Member Author

Compact evidence for head 588e49e (replaces the ~170k-line evidence tree from #501).

Actual Windows configuration and storage controls, run 38812653272, job 116689449714: Actual native configuration controls PASS; no skipped controls. The receipt and raw bytes are in artifact native-configuration-runtime (id 12009192699, 60,410 bytes, sha256 da74aa0522123560eda0aee9d3402b7a816c8d9dbab7da6937940607a23c51f2).

Source hashes printed by that job (SHA-256):

File SHA-256
app/native_storage_windows.go 47BDB740…92344B
app/native_storage_session_windows.go 2E0D19C7…65A348E
app/native_storage_session_windows_test.go 8932C161…B6CED301
app/native_storage_query.ps1 A0A0FA70…98541260
app/native_storage_windows_test.go 81041A12…92E717
app/native_configuration_rpc_test.go 1123A09C…BDF9A52C

Failure history on this PR, kept for review:

  • 5f4f2f0 / feat(shell): E2E drive contract in Core with goldens shared by engine, harness and shell #620 9158f45: installed configuration view failed for wootc (run 38801276457) and tunaos (run 38801326196) at the engine's 10 s storage deadline (Context:deadline, CallMs ≈ 11,040). Fixed in 23e827e with nested budgets.
  • 23e827e, 65b9966, 4b50d6d, cbdcb2f: held-stderr storage control. The fixture's descendant shared the request pipe as stdin, and the fixture compile went through the guarded session. Fixed in cbdcb2f and 588e49e.

Not proven here: interactive UAC, any installation, Home edition, build 17763.


Generated by Claude Code

@hanthor
hanthor merged commit e26ec5b into main Oct 15, 2026
23 checks passed
hanthor pushed a commit that referenced this pull request Oct 15, 2026
Conflicts: keep this branch's side, which is #619's final code plus this
PR's changes (the e2e-drive fixture path in winui-preview.yml, and the
storage mapping for a directive that names no storage).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F5v5GG4NYnpzMrfPCo3vWN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants