Skip to content

Commit 3ec7fdf

Browse files
feat(windows): Windows Gap Closure (v2.0 milestone)
Squash of 212 commits on windows-squash that delivered Windows/Unix parity for everyday CLI usage, network policy, and developer tooling. Milestone: v2.0 Windows Gap Closure (tag `v2.0` on source branch). Shipped 2026-04-18. See .planning/milestones/v2.0-ROADMAP.md for the full 11-phase, 29-plan archive. Scope: - Phase 5: Windows detach readiness fix (WaitNamedPipeW readiness probe in run_detached_launch). - Phase 6: WFP enforcement activation — SID-based kernel filtering promoted to primary network backend; driver gate removed; duplicate activation path cleaned. - Phase 7: Quick wins — `nono wrap` (Direct strategy + Job Object + WFP) and `nono logs` / `nono inspect` / `nono prune` session commands on Windows. - Phase 8: Interactive `nono shell` via ConPTY (CreatePseudoConsole) inside Job Object + WFP sandbox on Windows 10 build 17763+. - Phase 9: Port-granular WFP policy (--allow-port with bind/connect independence) + proxy credential injection (--network-profile / --credential / --upstream-proxy). - Phase 10: `nono learn` on Windows via ETW (ferrisetw + Win32-format path conversion, file + network events, admin-gated). - Phase 11 (stretch): Runtime capability expansion over named pipe with constant-time token auth + interactive approval. - Phase 12: Milestone bookkeeping cleanup. - Phase 13: v2.0 human verification UAT — 10 items resolved to terminal verdicts (3 pass, 7 waived). - Phase 14: v2.0 fix pass (detached-console-grandchild partial fix + help-text correction + runbook flag repair). - Phase 15: Detached Console + ConPTY architecture investigation — direction-b closure of the v2.0 carry-forward (gated PTY-disable + null-token + AppID WFP on detached Windows path only). 5-row smoke gate pass; 4 Phase 13 UAT items promoted to pass. Also includes earlier upstream sync work (WSL2 feature matrix + security hardening, release 0.26.0-0.29.1 bookkeeping, keystore file:// URI support, macOS proxy NO_PROXY fix, other fork maintenance) that lived on the same branch. Security-critical notes: - Direction-b scoped waivers for detached Windows path: Low-IL isolation waived on detached path (Job Object + filesystem sandbox remain primary); per-session-SID WFP replaced by AppID WFP on detached path (still kernel-enforced; requires nono-wfp-service). Non-detached path keeps WRITE_RESTRICTED + session-SID + ConPTY unchanged. - WRITE_RESTRICTED narrows the restricting-SID access-check gate to writes only so DLL loads and console init aren't blocked. - All paths canonicalized at grant time; path-component comparison (not string starts_with) used throughout to prevent `/home-evil/...` style escapes. 191 files changed, +50,204 / -5,244. Supersedes pre-squash branches: - pr/windows-epic12-clean-v2 (PR nolabs-ai#555) - pr555/windows-epic12-clean-v3 (PR nolabs-ai#583) - win-101-windows-build-foundation (PR nolabs-ai#530) Signed-off-by: oscarmackjr-twg <oscar.mack.jr@gmail.com>
1 parent 063ebad commit 3ec7fdf

191 files changed

Lines changed: 50350 additions & 5244 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.continue-here.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
phase: 04-state-integrity-deployment
3+
task: 0
4+
total_tasks: 0
5+
status: in_progress
6+
last_updated: 2026-04-05T03:53:00.494Z
7+
---
8+
9+
<current_state>
10+
Phase 4 planning is complete. The roadmap and state have been reconciled. All research, validation strategy, and planning documents are created and verified.
11+
</current_state>
12+
13+
<completed_work>
14+
- Context gathered and reconciled for Windows Parity milestone.
15+
- Phase 4 research completed (`04-RESEARCH.md`).
16+
- Phase 4 context and decisions locked (`04-CONTEXT.md`).
17+
- Phase 4 validation strategy established (`04-VALIDATION.md`).
18+
- Phase 4 plans 01 and 02 generated and verified (`04-01-PLAN.md`, `04-02-PLAN.md`).
19+
</completed_work>
20+
21+
<remaining_work>
22+
- Execute Plan 04-01: Windows Filesystem Snapshot & Rollback Integration.
23+
- Execute Plan 04-02: MSI Signing Pipeline and WFP Cleanup.
24+
</remaining_work>
25+
26+
<decisions_made>
27+
- **Merkle Trees for Snapshots**: Consistent with Unix, but will require mapping `fs_capabilities` to the Windows execution strategy.
28+
- **Soft Limits**: Log warnings for large workspaces rather than aborting.
29+
- **GitHub Secrets for Signing**: Simplified CI integration.
30+
- **Tag-Only Signing**: Quota conservation.
31+
- **WFP Dynamic Sessions**: OS-level automated cleanup.
32+
</decisions_made>
33+
34+
<blockers>
35+
- None.
36+
</blockers>
37+
38+
<context>
39+
The goal of Phase 4 is to finalize the "State Integrity & Deployment" pillar of the Windows Parity milestone. We've established the plan to bring Merkle tree-based rollbacks to Windows and automate the signed MSI distribution.
40+
</context>
41+
42+
<next_action>
43+
Start with: `/gsd:execute-phase 4`
44+
</next_action>

.gitattributes

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Default: LF for all text files
2+
* text=auto eol=lf
3+
4+
# Force LF line endings for shell scripts (required for WSL2/Linux execution)
5+
*.sh text eol=lf
6+
7+
# Source and doc files — LF everywhere for consistency
8+
*.rs text eol=lf
9+
*.toml text eol=lf
10+
*.md text eol=lf
11+
*.mdx text eol=lf
12+
*.json text eol=lf
13+
*.yaml text eol=lf
14+
*.yml text eol=lf
15+
16+
# Keep Windows batch files as CRLF
17+
*.bat text eol=crlf
18+
*.cmd text eol=crlf

.github/workflows/ci.yml

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,224 @@ jobs:
124124
- name: Run tests
125125
run: cargo test --workspace --verbose
126126

127+
windows-build:
128+
name: Windows Build
129+
needs: changes
130+
if: ${{ !startsWith(github.head_ref, 'dependabot/github_actions/') && needs.changes.outputs.run_code_jobs == 'true' }}
131+
runs-on: windows-latest
132+
steps:
133+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
134+
135+
- name: Install Rust toolchain
136+
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
137+
with:
138+
toolchain: stable
139+
140+
- name: Cache cargo registry
141+
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
142+
with:
143+
path: |
144+
~\.cargo\registry
145+
~\.cargo\git
146+
target
147+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
148+
restore-keys: |
149+
${{ runner.os }}-cargo-
150+
151+
- name: Run Windows build harness
152+
shell: pwsh
153+
run: .\scripts\windows-test-harness.ps1 -Suite build -LogDir ci-logs
154+
155+
- name: Upload Windows build logs
156+
if: ${{ always() }}
157+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
158+
with:
159+
name: windows-build-logs
160+
path: |
161+
ci-logs\windows-build.log
162+
if-no-files-found: warn
163+
164+
windows-smoke:
165+
name: Windows Smoke
166+
needs: changes
167+
if: ${{ !startsWith(github.head_ref, 'dependabot/github_actions/') && needs.changes.outputs.run_code_jobs == 'true' }}
168+
runs-on: windows-latest
169+
steps:
170+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
171+
172+
- name: Install Rust toolchain
173+
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
174+
with:
175+
toolchain: stable
176+
177+
- name: Cache cargo registry
178+
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
179+
with:
180+
path: |
181+
~\.cargo\registry
182+
~\.cargo\git
183+
target
184+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
185+
restore-keys: |
186+
${{ runner.os }}-cargo-
187+
188+
- name: Run Windows smoke harness
189+
shell: pwsh
190+
run: .\scripts\windows-test-harness.ps1 -Suite smoke -LogDir ci-logs
191+
192+
- name: Upload Windows smoke logs
193+
if: ${{ always() }}
194+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
195+
with:
196+
name: windows-smoke-logs
197+
path: ci-logs\windows-smoke.log
198+
if-no-files-found: warn
199+
200+
windows-integration:
201+
name: Windows Integration
202+
needs: changes
203+
if: ${{ !startsWith(github.head_ref, 'dependabot/github_actions/') && needs.changes.outputs.run_code_jobs == 'true' }}
204+
runs-on: windows-latest
205+
steps:
206+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
207+
208+
- name: Install Rust toolchain
209+
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
210+
with:
211+
toolchain: stable
212+
213+
- name: Cache cargo registry
214+
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
215+
with:
216+
path: |
217+
~\.cargo\registry
218+
~\.cargo\git
219+
target
220+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
221+
restore-keys: |
222+
${{ runner.os }}-cargo-
223+
224+
- name: Run Windows integration harness
225+
shell: pwsh
226+
run: .\scripts\windows-test-harness.ps1 -Suite integration -LogDir ci-logs
227+
228+
- name: Upload Windows integration logs
229+
if: ${{ always() }}
230+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
231+
with:
232+
name: windows-integration-logs
233+
path: ci-logs\windows-integration.log
234+
if-no-files-found: warn
235+
236+
windows-security:
237+
name: Windows Security
238+
needs: changes
239+
if: ${{ !startsWith(github.head_ref, 'dependabot/github_actions/') && needs.changes.outputs.run_code_jobs == 'true' }}
240+
runs-on: windows-latest
241+
env:
242+
NONO_CI_HAS_WFP: true # windows-latest runners run as Administrator
243+
steps:
244+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
245+
246+
- name: Install Rust toolchain
247+
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
248+
with:
249+
toolchain: stable
250+
251+
- name: Cache cargo registry
252+
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
253+
with:
254+
path: |
255+
~\.cargo\registry
256+
~\.cargo\git
257+
target
258+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
259+
restore-keys: |
260+
${{ runner.os }}-cargo-
261+
262+
- name: Run Windows security harness
263+
shell: pwsh
264+
run: .\scripts\windows-test-harness.ps1 -Suite security -LogDir ci-logs
265+
266+
- name: Upload Windows security logs
267+
if: ${{ always() }}
268+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
269+
with:
270+
name: windows-security-logs
271+
path: ci-logs\windows-security.log
272+
if-no-files-found: warn
273+
274+
windows-regression:
275+
name: Windows Regression
276+
needs: changes
277+
if: ${{ !startsWith(github.head_ref, 'dependabot/github_actions/') && needs.changes.outputs.run_code_jobs == 'true' }}
278+
runs-on: windows-latest
279+
steps:
280+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
281+
282+
- name: Install Rust toolchain
283+
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
284+
with:
285+
toolchain: stable
286+
287+
- name: Cache cargo registry
288+
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
289+
with:
290+
path: |
291+
~\.cargo\registry
292+
~\.cargo\git
293+
target
294+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
295+
restore-keys: |
296+
${{ runner.os }}-cargo-
297+
298+
- name: Run Windows regression harness
299+
shell: pwsh
300+
run: .\scripts\windows-test-harness.ps1 -Suite regression -LogDir ci-logs
301+
302+
- name: Upload Windows regression logs
303+
if: ${{ always() }}
304+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
305+
with:
306+
name: windows-regression-logs
307+
path: ci-logs\windows-regression.log
308+
if-no-files-found: warn
309+
310+
windows-packaging:
311+
name: Windows Packaging
312+
needs: changes
313+
if: ${{ !startsWith(github.head_ref, 'dependabot/github_actions/') && needs.changes.outputs.run_code_jobs == 'true' }}
314+
runs-on: windows-latest
315+
steps:
316+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
317+
318+
- name: Install Rust toolchain
319+
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
320+
with:
321+
toolchain: stable
322+
323+
- name: Cache cargo registry
324+
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
325+
with:
326+
path: |
327+
~\.cargo\registry
328+
~\.cargo\git
329+
target
330+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
331+
restore-keys: |
332+
${{ runner.os }}-cargo-
333+
334+
- name: Build Windows release binaries
335+
shell: pwsh
336+
run: cargo build --release -p nono-cli
337+
338+
- name: Validate Windows MSI contract
339+
shell: pwsh
340+
run: |
341+
.\scripts\validate-windows-msi-contract.ps1 `
342+
-BinaryPath .\target\release\nono.exe `
343+
-ServiceBinaryPath .\target\release\nono-wfp-service.exe
344+
127345
fmt:
128346
name: Rustfmt
129347
needs: changes

0 commit comments

Comments
 (0)