Skip to content

spec: Windows native runtime#106

Open
passcod wants to merge 21 commits into
mainfrom
claude/pr-105-spec-tracey-config-70jsvh
Open

spec: Windows native runtime#106
passcod wants to merge 21 commits into
mainfrom
claude/pr-105-spec-tracey-config-70jsvh

Conversation

@passcod

@passcod passcod commented Jul 10, 2026

Copy link
Copy Markdown
Member

Supersedes #105, carrying its commits forward unchanged and hooking the new spec up to tracey.

  • docs/spec/runtime-windows.md: draft spec for a second Seedling runtime targeting Windows Server hosts with native-process primitives, using the w[...] rule namespace (from the 2026-07 design sessions).
  • docs/plans/windows-runtime.md: companion plan — workstreams, open questions, spikes, rollout.
  • docs/plans/windows-runtime-rationale.md: non-normative design rationale — rejected alternatives, fallback positions, governance ledger.
  • Registered the runtime-windows spec in .config/tracey/config.styx (same impl globs as the other runtime specs) and dropped the now-done "add a spec entry when this lands" notes from the docs.
  • Fixed both docs' references to the rationale document, which landed as windows-runtime-rationale.md rather than windows-design-rationale.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs


Generated by Claude Code

@github-code-quality

github-code-quality Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript, Rust

TypeScript / code-coverage/vitest

The overall coverage in the branch remains at 65%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File e14aa26 c2e39b2 +/-
src/routes/Apps.tsx 74% 78% +4%

Rust / code-coverage/rust

The overall coverage remains at 55%, unchanged from the branch.


Updated July 11, 2026 13:18 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

claude added 16 commits July 10, 2026 12:53
The web spec already owns the w prefix; win avoids future rule-name
collisions between the two specs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
- cite l[job.type] instead of the nonexistent l[job]
- stop claiming Executed.exit_code() holds verbatim; note the pending
  l[rt.executed.exit-code] restatement instead
- rename runtime.capability() to rt.capability() to match BSL naming
- select artifacts by config media type alone, dropping the
  tamanu-namespaced annotation (only Windows on x64 is supported)
- point backup.v1's open question at plan Q3 instead of a nonexistent
  plan section
- drop implementation details (extended TCP table, CreateProcessAsUser)
  from rule text

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
- renumber open questions to start at Q1 and update references
- schedule the l[rt.executed.exit-code] restatement alongside
  i[shell.exit], noting it is a semantic change on Linux
- rename runtime.capability() to rt.capability()
- clarify spec restructuring is a prerequisite for merging the
  implementation
- mark windows-backend-research.md as superseded by the new design docs
- fix list formatting in the plan and rationale

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
Profiles are properties of the software, not the deployment: declared
in the artifact config blob (following Docker's StopSignal precedent),
overridable per-deployment from BSL, with built-in profiles for adopted
native services that have no artifact. Link the three rules that used
the term undefined, and add the BSL override surface to the plan's
spec-restructuring workstream.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
… profile-based reload

- ingress (Caddy) and the resolver (CoreDNS) become special services:
  runtime-installed native SCM services with built-in profiles, bound
  directly rather than through the workload relay model, exempt from
  the identity GC sweep, replacing the Linux proxy and resolver
  infrastructure container rules
- v1 drops blue/green: deploys and health-driven replacement are
  stop-then-start of the single instance, with the supervisor-held
  listener bounding disruption; recorded in non-goals and rationale
- reload is a process-profile property, not a node capability:
  SIGHUP maps to the profile's declared reload event, and
  signal:reload leaves the capability vocabulary
- enumerate WFP allows for ingress route targets and resolver access

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
…ent, profile-based reload

- ingress (Caddy) and the resolver (CoreDNS) become special services:
  runtime-installed native SCM services with built-in profiles, holding
  their own binds, exempt from the identity GC sweep, replacing the
  Linux proxy and resolver infrastructure container rules
- special services hold their own binds so no Seedling process sits in
  their data path; the recorded trade is stop-then-start binary
  upgrades, with config changes applying via graceful reload
- workload deploys keep zero-downtime replacement, mediated by the
  supervisor relay: new generation alongside old, relay target switch,
  service-address bind never dropped
- reload is a process-profile property, not a node capability: SIGHUP
  maps to the profile's declared reload event, and signal:reload
  leaves the capability vocabulary
- enumerate WFP allows for ingress route targets and resolver access

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
…text parity

- extend the WFP default-deny to the bind/listen layers so Seedling
  prefix addresses cannot be squatted, and enumerate the bind allows
  per principal (supervisor, workload, special service)
- authenticate the daemon-supervisor pipe: creation ACL on the
  supervisor's SID, and the daemon verifies the pipe server against
  the supervisor record's PID and start time before trusting it
- rt.exec commands run under the workload's stripped token with the
  full rendered instance environment, matching Linux exec-inherits-
  container semantics

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
…nal-ladder questions

seedlingd runs under its own virtual service account with its SID on
the standard volume ACLs, which also resolves the backup engine's
volume access; it ships as a single self-contained binary with no
installer or package-manager distribution; and the ladder-only
rt.signal mapping moves from open question to settled.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
Companion to threat-model.md covering what changes when workloads are
native processes: the discretionary identity-based containment model,
the defended boundaries (mount-graph WFP, address squatting, file
ACLs, privilege creep, pipe impersonation, attach verification,
identity residue), the accepted exposures (administrators, ambient
read surface, Defender exclusions, shared workload/supervisor SID),
and the governance ledger for deployment security reviews.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
One file per spike (A-E) with the spec rules and open questions at
stake, concrete experiments, exit criteria, and retreat positions; the
main plan's spike section now links them instead of duplicating.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
One binary per spike (A-E) in a new Windows-only crate:
- spike-a-stop: Job Object + CTRL_BREAK delivery, exit-code synthesis,
  sc.exe dispatch-latency loop
- spike-b-conpty: pseudoconsole spawn, output pump, resize; QUIC bridge
  and empty-stderr contract stubbed as the follow-up
- spike-c-net: loopback aliases/skipassource, NRPT, extended-TCP-table
  bind probe; WFP install left as a named FWPM follow-up
- spike-d-vhdx: read-only attach with before/after digest to prove the
  image is untouched
- spike-e-identity: restricted-token spawn with privilege-count check,
  sc.exe virtual-account and ghost checks, icacls inheritance break

Each binary is cfg-gated to a stub main off Windows so the workspace
stays green on Linux; heavy control-plane steps shell out to
sc.exe/netsh/PowerShell/icacls, and sequences too large to draft
without a Windows target are marked as explicit follow-ups. Added a
Windows CI job scoped to the crate (fmt/clippy/test) since the
daemon crates are Linux-only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
Fixes surfaced by the Windows CI job: BOOL lives in windows::core, not
Foundation; SetConsoleCtrlHandler/GetExtendedTcpTable take plain bool;
CreateProcessW/CreateProcessAsUserW lpcommandline is Option<PWSTR>;
GetVirtualDiskPhysicalPath takes PWSTR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
- InitializeProcThreadAttributeList takes Option-wrapped list and flags
- CreateProcessW/CreateProcessAsUserW binherithandles is plain bool
- pass the ConPTY output handle across the pump thread as isize (HANDLE
  is not Send)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nJ3scWucs71FH2T7y5oBs
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