Skip to content

Windows services tab + security CI + wiki + UI tabs - #1

Merged
carterscode merged 14 commits into
mainfrom
feature/disable-services
May 7, 2026
Merged

Windows services tab + security CI + wiki + UI tabs#1
carterscode merged 14 commits into
mainfrom
feature/disable-services

Conversation

@carterscode

Copy link
Copy Markdown
Owner

Summary

This branch bundles four threads of work into one PR: the Windows services feature you asked for, a Settings UI restructure into tabs, a trust/security CI overhaul, and the new docs/wiki layout.

Features

  • Windows services — new Settings tab with 18 curated services, tri-state Want column (Default / Manual / Disabled), one-click "Gaming optimized" preset that flips the recommended subset, per-service Monitor and Auto-apply opt-in, drift detection routed through the standard MonitorService loop.
  • Tabbed Settings UI — General / Global gaming / Windows services / Display. Each tab has its own scroll; the Cancel/Apply/Save row stays docked across tabs.

Trust & security

  • CodeQL SAST on push, PRs, and a weekly schedule (csharp + actions).
  • Dependabot weekly watch for NuGet + GitHub Actions deps.
  • OpenSSF Scorecard workflow with public score badge.
  • SECURITY.md with private-channel disclosure policy.
  • PRIVACY.md documenting the zero-data-collection posture (also satisfies SignPath OSS application requirement).
  • All GitHub Actions pinned to commit SHAs (with # vX.Y.Z comments so versions are still readable). Dependabot keeps them updated.
  • release.yml gains: a dotnet list package --vulnerable gate before publish, SHA-256 checksums attached to every Release as SHA256SUMS.txt, and an optional VirusTotal scan step gated on the ENABLE_VIRUSTOTAL repo variable.
  • Deterministic=true + ContinuousIntegrationBuild in the csproj so CI builds at the same commit are byte-identical run-to-run.

Docs

  • New docs/wiki/ markdown (8 pages: Home, Installation, Build-from-source, File-locations, Logging, Verification, Source-file-reference, Architecture-rationale, Security) as the wiki source-of-truth.
  • tools/sync-wiki.ps1 mirrors docs/wiki/ into the GitHub Wiki repo on demand.
  • README trimmed from ~360 → ~120 lines; long-form detail moves to wiki.

Internal

  • New dev-build.yml workflow producing installer + portable EXE as workflow artifacts on every non-main push. Stamped {nextStable}-dev.{sha7} so a dev install never tries to "upgrade" itself to stable mid-test.
  • Periodic [trim ] memory-snapshot lines no longer written to changes.log (function preserved for ad-hoc debugging).

Test plan

  • Local Release build passes (no warnings, no errors)
  • Every dev-build run on this branch went green
  • Manually tested dev artifacts: 4 tabs render, services apply via UAC, badge layout fits at default window width, tri-state radios bind correctly, Gaming/Default preset flips the right subset
  • CodeQL pass on this PR
  • Scorecard run publishes initial score
  • First Release on merge cuts v0.1.30 with SHA256SUMS + VirusTotal scan

🤖 Generated with Claude Code

carterscode added 13 commits May 7, 2026 08:29
Builds installer + portable EXE on every push to a non-main branch and
on workflow_dispatch. Uploads as workflow artifacts only (no GitHub
Release) so the auto-updater never sees them. Version stamped as
{nextStable}-dev.{sha7} so the parsed semver sits above latest stable,
preventing the dev build from offering itself a downgrade to stable
during testing.
Adds a curated catalog of 10 Windows services that are commonly disabled
for gaming setups (DiagTrack, MapsBroker, WMPNetworkSvc, Fax, RetailDemo,
WerSvc, lfsvc, plus opt-ins for WSearch, SysMain, TabletInputService).

For each service the Settings UI shows display name + service ID, what
it does, the Windows default start type, the current start type+status,
and reboot/recommended/not-installed badges. Per-service the user
chooses Want=Disabled or Default, can toggle Monitor, and can enable
Auto-apply (re-applies via UAC if Windows or another app re-enables a
disabled service).

A 'Gaming optimized' / 'Default' radio at the top of the section is a
one-click preset that flips Want across the recommended subset.

WindowsServiceController wraps sc.exe via Verb=runas; DisableElevated
chains stop + config disabled into a single UAC prompt. Reads use
ServiceController + the registry (no elevation).

WindowsServiceMonitor implements IMonitoredSetting, one instance per
ServiceDefinition, registered in App.xaml.cs from ServiceCatalog.All.
Drift is only reported when the user opted into Want=Disabled (current
!= Disabled) or Want=Default-and-currently-Disabled — Manual->Auto
trigger transitions don't churn the monitor.

ServicePref ('Monitor', 'DesiredDisabled', 'AutoApply') is keyed by
service name in AppConfig.Services so adding services to the catalog
doesn't migrate existing configs.
…Display tabs

Single-window scroll was getting unwieldy with the services section added.
Each tab now has its own ScrollViewer; the Cancel/Apply/Save row stays
docked at the bottom across all tabs. Bumped default width 780 -> 820 so
tab headers fit comfortably; reduced default height 760 -> 720 since
each tab needs less vertical space than the combined view. All x:Names,
bindings, and event handlers preserved unchanged — code-behind didn't
need to change.
…rvices

The Want column on each service card is now three radios — Default,
Manual, Disabled — instead of two. This was driven by IP Helper, where
'Manual + stop' is a much safer target than full Disabled (some IPv6
tunneling on home networks still relies on it being available on demand).

Services added:
  Recommended (none — added without preset membership):
  * Spooler              Print Spooler — break printing if disabled
  * RemoteRegistry       Remote Registry — already Disabled by default on Win11
  * DoSvc                Delivery Optimization
  * iphlpsvc             IP Helper — Manual is safer than Disabled
  * XboxGipSvc           Xbox Accessory Management
  * XblAuthManager       Xbox Live Auth Manager
  * XblGameSave          Xbox Live Game Save
  * XboxNetApiSvc        Xbox Live Networking

None of the new services are in the Gaming-optimized preset; the user
opts into them individually. Existing 7 'recommended' services keep
their preset membership unchanged.

Model changes:
  * ServiceDefinition.RecommendedDisable (bool)
      -> RecommendedTarget (ServiceTargetState?)
  * ServicePref.DesiredDisabled (bool)
      -> Desired (ServiceTargetState; serialized as a string via
        JsonStringEnumConverter so configs are diffable)
  * WindowsServiceController.SetManualElevated wraps 'sc stop' +
    'sc config start= demand' in one UAC prompt.
  * WindowsServiceMonitor maps Desired -> ServiceStartType, dispatches
    to the matching elevated call. The Default-state drift heuristic
    is widened: it now also undoes a prior Manual change when the
    service's default is Auto/AutoDelayed.

Note: a dev tester who installed the previous build with DesiredDisabled
in their config will see services revert to Want=Default after this
upgrade (the old field is ignored). No existing public release wrote
DesiredDisabled, so stable users are unaffected.
The two callers (MonitorService periodic trim, settings-closed cleanup)
are removed. Psapi.TrimSelf and the GC compaction calls still happen on
the same cadence — only the changes.log line is gone.

LogMemorySnapshot itself is intentionally kept; opt back in at a
specific call site if you're tracking a regression.
TabItem defaults HorizontalContentAlignment + VerticalContentAlignment
to Center, which made the General tab's single Card float in the
vertical middle of the tab area with a wall of empty space above it.
Setting both to Stretch on the TabControl propagates to every TabItem
so each tab's ScrollViewer fills the available area and content sits
naturally at the top.
The display name + 4 badges + service-name pill on a single horizontal
line was getting truncated for long entries (Connected User Experiences
and Telemetry, Xbox Live Networking Service, etc.). Moves all badges to
a WrapPanel directly under the title so the name always has the full
card width, and badges flow to a third line if a card collects all four
of them.
Wiki content
  Lifts Installation, Build-from-source, File-locations, Logging,
  Verification, and Source-file-reference out of README into
  docs/wiki/ markdown files. Adds Home + _Sidebar nav and a Security
  page covering trust signals + spot-check guidance.
  tools/sync-wiki.ps1 mirrors docs/wiki/ -> github.com/<repo>.wiki.git
  on demand; first run requires the user to initialize the wiki by
  creating any first page in the GitHub UI.

Security CI
  * .github/workflows/codeql.yml — CodeQL SAST on push, PR, and weekly
    schedule. Both csharp and actions languages.
  * .github/dependabot.yml — weekly NuGet + GitHub Actions watch with
    auto-PRs.
  * .github/workflows/scorecard.yml — OpenSSF Scorecard public score
    with SARIF upload to code-scanning.
  * release.yml gains a 'dotnet list package --vulnerable' gate before
    publish, plus a SHA-256 checksum step that emits SHA256SUMS.txt
    alongside the installer + portable EXE on every Release.
  * SECURITY.md — disclosure policy, supported-version statement,
    private-channel reporting (Security Advisories preferred).

README
  Trims to overview + screenshot + feature table + verification +
  security summary. Detail moves to wiki. Adds CodeQL + Scorecard
  badges next to the existing build/release/license set.
Action pinning
  Every step in build/dev-build/release/codeql/scorecard now references
  a 40-char commit SHA with the matching version as a trailing comment.
  Dependabot updates these in place. Improves OpenSSF Scorecard's
  Pinned-Dependencies score and removes the 'mutable tag' supply-chain
  exposure where a compromised maintainer could repoint @v4 mid-flight.

Deterministic CI builds
  csproj sets Deterministic=true (always) and ContinuousIntegrationBuild=
  true under GITHUB_ACTIONS. Combined with portable PDBs, this makes
  CI-built binaries byte-identical across runs at the same source commit
  — a prerequisite for any future reproducibility claim.

Optional VirusTotal scan on Release
  release.yml gains an opt-in step that uploads installer + portable EXE
  to VirusTotal and appends per-engine result URLs to the auto-generated
  release notes. Gated on the repo variable ENABLE_VIRUSTOTAL=true *and*
  a VIRUSTOTAL_API_KEY secret — skips silently otherwise. release-notes-
  extra.md is initialized empty so body_path: append still works when VT
  is disabled.

Architecture rationale wiki page
  New page covering why GamerGuardian is user-mode P/Invoke and not a
  kernel driver, why polling instead of event subscriptions, why a
  single-file ~77 MB self-contained publish, why per-user install, why
  one IMonitoredSetting per setting, why HKLM writes go through reg.exe
  / sc.exe rather than Verb=runas of the app itself, and why no
  telemetry. Linked from the home page and sidebar.
signpath.io is the commercial product; the free OSS program lives at
signpath.org. Updates both wiki references to signpath.org and adds
the direct apply link in the Security page.
Required by SignPath Foundation for OSS code-signing eligibility, and
useful as a public statement of what the app does/doesn't do with user
data. Linked from README + the Security wiki page.
…lobal cards

Tab anchoring
  Setting HorizontalContentAlignment=Stretch / VerticalContentAlignment=
  Stretch on the TabControl wasn't enough — WPF-UI's TabItem style sets
  these explicitly, overriding the inherited TabControl values. Setting
  them inline on each TabItem wins via XAML attribute precedence over
  Style setters. The General tab's single Card no longer floats in the
  middle of empty space.

Global card layout
  'Hardware-accelerated GPU Scheduling (HAGS)' was being clipped on
  narrower window widths because the reboot badge sat on the same line.
  Moved the badge to its own line directly under the title (matching
  the service-card layout), with HorizontalAlignment=Left so it doesn't
  stretch across the card.
A bare <ui:Card> as the immediate child of a ScrollViewer ends up
vertically centered (WPF-UI's Card style appears to set
VerticalAlignment=Center). The other tabs already work because they
have a StackPanel between the ScrollViewer and the cards — StackPanel
naturally top-anchors children. Adding the same wrapper to the General
tab brings its layout in line.
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

_ = sc.Status;
return true;
}
catch { return false; }
_ => ServiceStartType.Unknown,
};
}
catch { return ServiceStartType.Unknown; }
using var sc = new ServiceController(serviceName);
return sc.Status;
}
catch { return null; }
Comment on lines +147 to +160
foreach (var row in ServiceRows)
{
if (!row.IsInstalled) continue;
if (useRecommended)
{
// Only flip rows with a RecommendedTarget. Leave others alone.
if (row.Definition.RecommendedTarget is { } target)
row.SetDesiredFromPreset(target);
}
else
{
row.SetDesiredFromPreset(ServiceTargetState.Default);
}
}
row.SetDesiredFromPreset(ServiceTargetState.Default);
}
}
try { _store.Save(_config); } catch { }
row.SetDesiredFromPreset(ServiceTargetState.Default);
}
}
try { _store.Save(_config); } catch { }
Removes from index and adds to .gitignore. File remains on disk so
Claude Code keeps reading it; new edits no longer enter git.

History intentionally not rewritten — the previous content is generic
developer context (architecture notes, machine paths) with nothing
sensitive. Rewriting history would orphan the v0.1.0..v0.1.29 tag
chain and force a re-clone for everyone, which isn't worth it for the
content this file contains.
@carterscode
carterscode merged commit a8310f9 into main May 7, 2026
4 checks passed
@carterscode
carterscode deleted the feature/disable-services branch May 7, 2026 17:26
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