docs(installer): correct the Windows service decision, and the 1053 advice #98

Merged
whitlocktech merged 1 commits from docs/windows-service-1053 into main 2026-08-07 18:52:37 +00:00
Member

What & why

Docs half of link#29 (the sidecar fix) and installer#16 (the message fix).

PLAN.md §8 recorded, as resolved, that sc create against the plain console sidecar worked and needed no change to link. The first Windows install disproved it:

Service Control Manager: A timeout was reached (30000 milliseconds) while waiting
for the Runic Gateway uo-link sidecar service to connect.        [1053]

sc query RunicGatewayLink  ->  SERVICE_EXIT_CODE : 0

The premise was a false symmetry with systemd. systemd supervises any foreground process; the Windows SCM supervises only a process that calls StartServiceCtrlDispatcher within ~30 seconds and then reports its own state transitions. There is no third option where sc.exe adopts an arbitrary console executable.

I recorded the reversal in place, with the evidence, rather than quietly editing the old decision away — a decision record that silently changes its mind teaches nobody why.

What changed

PLAN.md §8 — the resolved decision now keeps what was right (virtual service account, failure actions, config pinned in binPath, no WinSW/NSSM shim) and adds a dated correction covering what was wrong, why, and the four consequences: one binary with no --service flag, the service log file, Running reported only after the listeners bind, and the v1.2.0 floor.

INSTALL.md

  • Troubleshooting gains a 1053 row naming the real cause and the two tell-tales that distinguish it from a crash: SERVICE_EXIT_CODE : 0, and a foreground run of the same binary working fine.
  • The existing "Service registered but stops immediately" row said the same wrong thing ("It cannot read its config"). It now covers only the genuine-crash case, and points at the service log file and journalctl.
  • §3 "Where everything lands" documents the log file, and notes the service needs a sidecar ≥ v1.2.0.
  • Appendix A4 gains the version floor as the first of the things easy to get wrong, plus where the log lands.

Drive-by fix: the backups row in §3 contained a literal 0x08 backspace byte where a backslash belonged, rendering as %ProgramData%\RunicGatewayackups\<timestamp>\. Now %ProgramData%\RunicGateway\backups\<timestamp>\, and there are no remaining 0x08 bytes in the file.

Note on the v1.2.0 floor

INSTALL.md names v1.2.0 as the oldest sidecar that can start as a service. That is the version link#29 is expected to release as. If it lands under a different number, this and MIN_SERVICE_SIDECAR in installer/src/service.rs both need updating.

Base branch

Cut from main, deliberately not from docs/bundles-branch (docs#97), which also touches these two files. This is an independent fix and shouldn't have its merge coupled to that PR's. It applied cleanly against main; whichever lands second may need a trivial merge in PLAN.md.

How it was tested

Prose only — no build to run. The behaviour described was verified for real: 13/13 checks against a live Windows service, with the sidecar starting in 1s, serving /health, writing uo-link-sidecar.2026-08-07.log, and stopping cleanly. Every path, filename and error code in the new text was taken from that run rather than written from memory.

Checklist

  • I have read CONTRIBUTING.md.
  • The change builds and existing tests/checks pass locally.
  • I have added or updated tests/docs where it makes sense.
  • My commits are reasonably scoped with clear messages.

AI-assisted contributions (required)

  • AI tools were used. Tool(s): Claude Code (Opus 5). I have reviewed and understand
    every change, and take responsibility for it. AI-authored commits are
    marked with a Co-Authored-By trailer.

License

  • I agree that my contribution is licensed under this project's license
    (GNU GPL v3.0 or later), and I have the right to contribute it.
## What & why Docs half of `link#29` (the sidecar fix) and `installer#16` (the message fix). `PLAN.md` §8 recorded, as **resolved**, that `sc create` against the plain console sidecar worked and needed no change to `link`. The first Windows install disproved it: ``` Service Control Manager: A timeout was reached (30000 milliseconds) while waiting for the Runic Gateway uo-link sidecar service to connect. [1053] sc query RunicGatewayLink -> SERVICE_EXIT_CODE : 0 ``` The premise was a false symmetry with systemd. systemd supervises *any* foreground process; the Windows SCM supervises only a process that calls `StartServiceCtrlDispatcher` within ~30 seconds and then reports its own state transitions. There is no third option where `sc.exe` adopts an arbitrary console executable. I recorded the reversal in place, with the evidence, rather than quietly editing the old decision away — a decision record that silently changes its mind teaches nobody why. ## What changed **PLAN.md §8** — the resolved decision now keeps what was right (virtual service account, failure actions, config pinned in `binPath`, no WinSW/NSSM shim) and adds a dated correction covering what was wrong, why, and the four consequences: one binary with no `--service` flag, the service log file, `Running` reported only after the listeners bind, and the v1.2.0 floor. **INSTALL.md** - Troubleshooting gains a **1053 row** naming the real cause and the two tell-tales that distinguish it from a crash: `SERVICE_EXIT_CODE : 0`, and a foreground run of the same binary working fine. - The existing *"Service registered but stops immediately"* row said the same wrong thing ("It cannot read its config"). It now covers only the genuine-crash case, and points at the service log file and `journalctl`. - §3 "Where everything lands" documents the log file, and notes the service needs a sidecar ≥ v1.2.0. - Appendix A4 gains the version floor as the first of the things easy to get wrong, plus where the log lands. **Drive-by fix:** the backups row in §3 contained a literal `0x08` backspace byte where a backslash belonged, rendering as `%ProgramData%\RunicGatewayackups\<timestamp>\`. Now `%ProgramData%\RunicGateway\backups\<timestamp>\`, and there are no remaining `0x08` bytes in the file. ## Note on the v1.2.0 floor INSTALL.md names **v1.2.0** as the oldest sidecar that can start as a service. That is the version `link#29` is expected to release as. If it lands under a different number, this and `MIN_SERVICE_SIDECAR` in `installer/src/service.rs` both need updating. ## Base branch Cut from `main`, deliberately **not** from `docs/bundles-branch` (docs#97), which also touches these two files. This is an independent fix and shouldn't have its merge coupled to that PR's. It applied cleanly against `main`; whichever lands second may need a trivial merge in PLAN.md. ## How it was tested Prose only — no build to run. The behaviour described was verified for real: 13/13 checks against a live Windows service, with the sidecar starting in 1s, serving `/health`, writing `uo-link-sidecar.2026-08-07.log`, and stopping cleanly. Every path, filename and error code in the new text was taken from that run rather than written from memory. ## Checklist - [x] I have read [CONTRIBUTING.md](CONTRIBUTING.md). - [x] The change builds and existing tests/checks pass locally. - [x] I have added or updated tests/docs where it makes sense. - [x] My commits are reasonably scoped with clear messages. ## AI-assisted contributions (required) - [x] AI tools were used. Tool(s): `Claude Code (Opus 5)`. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with a `Co-Authored-By` trailer. ## License - [x] I agree that my contribution is licensed under this project's license (**GNU GPL v3.0 or later**), and I have the right to contribute it.
wtclaude added 1 commit 2026-08-07 18:52:09 +00:00
PLAN.md §8 recorded that `sc create` against the plain console sidecar worked
and needed no change to `link`. The first Windows install disproved it: 1053,
"a timeout was reached (30000 milliseconds) while waiting for the service to
connect", with SERVICE_EXIT_CODE 0.

The premise was a false symmetry with systemd. systemd supervises any
foreground process; the Windows SCM supervises only one that calls
StartServiceCtrlDispatcher within ~30 seconds. Record the reversal and what it
costs: link gains a Windows service entry point, kept at the edges so the whole
sidecar stays shared and Cargo builds neither Windows crate for Linux.

INSTALL.md:
- Troubleshooting gains a 1053 row naming the real cause (a sidecar older than
  v1.2.0) and the two tell-tales that distinguish it from a crash: exit code 0,
  and a foreground run of the same binary working fine.
- The existing "stops immediately" row said the same wrong thing; it now covers
  the genuine-crash case only, and points at the log file and journalctl.
- §3 and Appendix A4 document the service log, and A4 states the version floor.
- Fixes a literal 0x08 byte in the backups path row, which rendered as
  `%ProgramData%\RunicGatewayackups\` — the backslash had been eaten.

Co-Authored-By: Claude <noreply@anthropic.com>
whitlocktech merged commit 18dfceae73 into main 2026-08-07 18:52:37 +00:00
whitlocktech deleted branch docs/windows-service-1053 2026-08-07 18:52:38 +00:00
Sign in to join this conversation.
No description provided.