Files
nucleic-windows/spikes/WslcApiDump/FacadeAssumptions.cs
T

117 lines
7.8 KiB
C#
Raw Normal View History

namespace WslcApiDump;
/// <summary>
/// The <c>Microsoft.WSL.Containers</c> surface `NucleicBroker/Wslc/WslcFacade.cs` depends on.
///
/// **This list changed meaning on 2026-07-29.** It began as a list of *guesses* — the facade was
/// transcribed from documentation on machines with no WSL — and this tool existed to find out how
/// many were wrong. That question is answered (docs/WINDOWS_PORT.md §13.1: many of them, including
/// three that were missing capability rather than a wrong name). The entries below are now the
/// surface **actually observed in package 2.9.3**, so this tool's job has changed from discovery
/// to **drift detection**: run it after bumping the pin and it says what the new version moved.
///
/// Still strings rather than typed references, for the same reason as before — a typed check fails
/// to compile on the first rename and reports one problem; this reports all of them.
///
/// Keep in lockstep with WslcFacade.cs.
/// </summary>
internal static class FacadeAssumptions
{
internal sealed record Assumption(string Type, string Member, Kind MemberKind, string Why);
internal enum Kind { Method, Property, Event, Constructor, EnumValue, Type }
internal static readonly Assumption[] All =
[
// ---- Service entry point: onboarding (§8 step 2) ----
new("WslcService", "GetVersion", Kind.Method,
"hello capabilities — hostd degrades across preview→GA churn on this"),
new("WslcService", "GetMissingComponents", Kind.Method,
"components.missing RPC; returns IReadOnlyList<Component>, NOT a flags enum"),
new("WslcService", "InstallWithDependencies", Kind.Method, "components.install RPC"),
new("Component", "WslPackage", Kind.EnumValue,
"one of the three components onboarding can report missing"),
new("ServiceVersion", "Major", Kind.Property, "the version triple reported in hello"),
// ---- Session: one per channel, hosts every container (§3.2) ----
new("SessionSettings", ".ctor", Kind.Constructor, "SessionSettings(name, storagePath)"),
new("SessionSettings", "CpuCount", Kind.Property, "session.ensure cpu"),
new("SessionSettings", "MemorySizeInMB", Kind.Property,
"session.ensure memoryMB — NOT MemoryMB; a resize needs a sandbox restart (§3.2)"),
new("SessionSettings", "Timeout", Kind.Property, "idle timeout for the whole session VM"),
new("Session", ".ctor", Kind.Constructor,
"there is NO CreateOrOpen — construction is the only entry point, and whether a second "
+ "construction with an existing name attaches or throws Error.SessionReserved is the "
+ "open question broker reattach (§2.3) hangs on"),
new("Session", "Start", Kind.Method, "brings the session VM up after construction"),
new("Session", "Terminate", Kind.Method, "session.terminate RPC"),
new("Session", "Terminated", Kind.Event,
"session.down notification (SessionTerminationReason) → hostd's reconcile sweep"),
new("SessionTerminationReason", "Crashed", Kind.EnumValue,
"distinguishes a crash from an orderly shutdown in the session.down reason"),
// ---- Images ----
new("Session", "PullImage", Kind.Method, "image.pull RPC (naros-agent from GHCR), sync form"),
new("Session", "PullImageAsync", Kind.Method,
"the async form, which is where pull PROGRESS comes from (ImageProgress)"),
new("PullImageOptions", ".ctor", Kind.Constructor, "PullImageOptions(uri)"),
new("PullImageOptions", "RegistryAuth", Kind.Property,
"GHCR auth — a STRING, not a credentials object"),
new("ImageProgress", "CurrentBytes", Kind.Property,
"→ image.pullProgress → the existing controlDownloadProgress UI surface"),
new("ImageProgressStatus", "Downloading", Kind.EnumValue, "pull progress phase"),
new("Session", "GetImages", Kind.Method, "image.list / image.inspect"),
new("ImageInfo", "Name", Kind.Property, "image ref — NOT .Reference"),
new("ImageInfo", "Sha256", Kind.Property, "image digest — NOT .Digest"),
new("Session", "DeleteImage", Kind.Method, "image.delete"),
// ---- Containers ----
new("Session", "CreateContainer", Kind.Method, "container.create"),
new("ContainerSettings", ".ctor", Kind.Constructor, "ContainerSettings(imageName)"),
new("ContainerSettings", "Name", Kind.Property, "channel-suffixed container naming"),
new("ContainerSettings", "HostName", Kind.Property, "container.create hostname — capital N"),
new("ContainerSettings", "NetworkingMode", Kind.Property,
"None | Bridged — NOT the NAT/mirrored pair §5 assumed"),
new("ContainerSettings", "Volumes", Kind.Property, "the NTFS worktree bind mount (D8)"),
new("ContainerSettings", "InitProcess", Kind.Property, "naros-init as PID 1 (docs/NAROS.md)"),
new("ContainerVolume", ".ctor", Kind.Constructor,
"ContainerVolume(windowsPath, containerPath, readOnly)"),
new("ContainerNetworkingMode", "Bridged", Kind.EnumValue,
"the mode a container needs to reach the host at all (§5)"),
new("Container", "Start", Kind.Method, "container.start"),
new("Container", "Stop", Kind.Method, "container.stop(Signal, TimeSpan)"),
new("Container", "Delete", Kind.Method, "container.delete(DeleteContainerOption)"),
new("Container", "State", Kind.Property, "container.state → running/stopped/absent"),
new("Container", "Inspect", Kind.Method,
"the ONLY per-container introspection there is — there is no GetStatistics(), so "
+ "container.stats has to exec cgroup reads instead (§13.1 finding 2)"),
new("Container", "CreateProcess", Kind.Method,
"proc.exec — NOT RunProcess, and it does not start the process"),
new("ContainerState", "Running", Kind.EnumValue, "the one state the facade tests by name"),
new("DeleteContainerOption", "Force", Kind.EnumValue, "container.delete force"),
new("Error", "ContainerNotFound", Kind.EnumValue,
"structured failure codes — a better source for the RPC's data.kind than string matching"),
// ---- Processes: the agent stdio path (§3.2 WslcProcessHandle) ----
new("ProcessSettings", "CommandLine", Kind.Property, "argv — NOT CmdLine"),
new("ProcessSettings", "EnvironmentVariables", Kind.Property, "env — NOT Environment"),
new("ProcessSettings", "WorkingDirectory", Kind.Property, "cwd"),
new("ProcessSettings", "OutputMode", Kind.Property, "event-mode stdio, not polling"),
new("ProcessOutputMode", "Event", Kind.EnumValue,
"the mode that makes stdio push-based; polling would change the broker design"),
new("Process", "Start", Kind.Method,
"the second half of exec — handlers are attached between CreateProcess and this, which "
+ "is precisely why the API is split in two"),
new("Process", "OutputReceived", Kind.Event, "→ proc.stdout notifications"),
new("Process", "ErrorReceived", Kind.Event,
"→ proc.stderr — a SEPARATE event, not a stderr flag on one handler"),
new("Process", "Exited", Kind.Event, "→ proc.exit; must never overtake output (OutboundWriter)"),
new("Process", "GetInputStream", Kind.Method,
"proc.stdin — a WinRT stream, not a WriteStdin call; closing it is proc.closeStdin"),
new("Process", "Signal", Kind.Method, "proc.signal — the agent's real POSIX Stop path"),
new("Signal", "SIGKILL", Kind.EnumValue,
"signals are a NAMED enum; the RPC carries POSIX ints, so the broker maps them, and "
+ "anything outside None/HUP/INT/QUIT/KILL/TERM is unavailable"),
];
}