feat(windows): add native ACP process lifecycle support - #1485
feat(windows): add native ACP process lifecycle support#1485smallgun01 wants to merge 22 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
Bound Unix shell post-kill pipe joins so timeout cannot hang on setsid descendants. Re-apply the restricted DACL after ReplaceFileW, create the auth temp with an explicit security descriptor, and take the trustee from the process token SID. Keep the Job Object controller alive for later terminate callers. Trigger the Windows gate on pull_request/main path filters and derive canary provenance from github context.
The Windows ACL test had two #[test] attributes, which fails to compile on Windows CI. Bound completed-path pipe joins as well so a setsid descendant cannot hang a normal exit.
|
Important CHANGES REQUESTED What This PR DoesAdds a Windows-native ACP process lifecycle to OpenAB: Job Object process-tree ownership, ACL-protected atomic How It Works (delta since round-1)
Findings
Finding Details🟡 F7: Unflagged cross-platform
|
| Round-1 finding | Status |
|---|---|
| F1 unbounded hang on timeout/cancel | Fixed: bounded joins (POST_KILL_PIPE_JOIN, POST_EXIT_PIPE_JOIN) + POST_TIMEOUT_CLEANUP around cancel_and_wait; two setsid-escape regression tests prove both paths return |
F2 ReplaceFileW discards restricted DACL |
Fixed: restrict_auth_dacl() after both ReplaceFileW and MoveFileExW paths |
F3 trustee from USERNAME/USERDOMAIN |
Fixed: process-token SID (GetTokenInformation(TokenUser), TRUSTEE_IS_SID via BuildTrusteeWithSidW); regression test spoofs the env vars and still succeeds |
| F4 single-shot terminate controller | Fixed: controller loops, later callers get Ok(()); second-terminate regression assertion added |
| F5 ACL-after-create window | Fixed: CreateFileW with explicit SECURITY_ATTRIBUTES, CREATE_NEW, FILE_SHARE_NONE -- no unprotected window |
| F6 no upstream CI gate | Fixed: main push + pull_request triggers with path filters; MANIFEST derives repository/branch from GITHUB_REPOSITORY / GITHUB_HEAD_REF |
Baseline Check
- PR opened: 2026-08-19; head
39cb67c8f2b8bb56764234ef4283cff5e7e14150; basemain(merge-base280db4db= base HEAD, clean) - Diff: 16 files, +2258 / -230; delta since round-1 head
2d805b9: 6 files, +408 / -82 - Round-1 (
2d805b9) already reviewed the full change; this round verifies the F1-F6 fixes and re-checks the open items - CI on head SHA: all green, including
windows-dual-layer-canary,check, and the full smoke-test matrix
What's Good (🟢)
- Every blocker fix ships with a regression test that encodes the exact failure mode (setsid pipe escape, spoofed env trustee, double terminate) -- this is how review findings should be closed
- The token-SID DACL rework is the correct Win32 pattern: create-with-descriptor removes the race entirely instead of narrowing it
- CI trigger fix includes path filters and a per-PR concurrency group, not just a blanket trigger
Three Reasons We Might Not Need This PR
- Deployment reality is Linux containers -- every upstream smoke gate is Docker/Linux; carrying security-critical Win32 code that maintainers cannot routinely exercise is standing risk, though the new upstream CI triggers (F6 fix) now mitigate this.
- WSL2 already covers Windows developers via the mature Unix path; native support mainly benefits installer-based end users, and installer/GA remains explicitly out of scope.
- Maintenance surface: ~1,900 lines of platform-specific lifecycle code with subtle Win32 semantics (Job Objects, DACL inheritance, ReplaceFileW) raises the bar for every future contributor touching these files.
All three are materially weaker than in round-1: the fixes were fast, test-backed, and correct, and the CI gate now runs upstream. The remaining items are small; with F7-F10 addressed this is a mergeable foundation.
- F7: document working_dir sandbox rejection on all platforms in PR body - F8: extract shared WINDOWS_RUNTIME_ENV_KEYS constant (openab-core -> agent) - F9: assert no-provider/no-credentials failure shape in canary - F10: preserve pipe bytes + truncation marker on bounded pipe join expiry
|
Caution This PR has been waiting on the author for more than 2 days (labeled @smallgun01 — You must add a new comment on this PR to remove the |
|
Still actively working this PR. Current head is On this head:
Please keep the PR open. I will continue from here. |
CI clippy 1.98 -D warnings fails on print_box's redundant
format!("{}", line) where line is already &&str.
Summary
This draft adds the Windows-native ACP process lifecycle implementation to OpenAB.
It is intended to make the ACP host reliable on Windows when an agent session is cancelled, times out, exits unexpectedly, or the parent process shuts down.
Review Contract
Goal
Add the Windows-native ACP lifecycle path to OpenAB with explicit process-tree ownership, credential isolation, shutdown coordination, and CI coverage, so upstream maintainers can review the implementation before any merge or release decision.
Non-goals
mainunless an upstream maintainer later merges it.Accepted Residual Risks
process-wrapWindows support.Acceptance Criteria
working_dirnow rejects absolute paths outside the sandbox on all platforms (Unix included), not just Windows.Follow-ups
process-wrapversion pin and its long-term Windows support.Discussion
Official group discussion thread:
https://discord.com/channels/1491295327620169908/1538116818462314606
Validation
smallgun01:spike/windows-acp-native-agent2d805b9Scope and status
This is intentionally a Draft PR for upstream maintainer review. It does not request merge or release approval yet.
The fork-only governance exception on PR #1 is separate from this upstream PR: the fork does not hold the upstream GitHub App credentials, so that fork-only check is not treated as a code failure.
This PR does not by itself publish a Windows installer or declare Native GA. After upstream review and any requested changes, a merge would still require post-merge Windows canary and release-artifact validation.