From 2233f2ed8330c7ed94f9e82ad5f617b31dcec0bf Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 01:48:40 +0000 Subject: [PATCH 1/5] Capture trim-safe publish as a follow-up TODO PublishTrimmed is disabled in the App csproj to unblock the first release (see PR #18). Document the proper fix so it doesn't get lost: source-gen JsonSerializerContext to remove IL2026, audit the third-party IL2104 warnings, then turn PublishTrimmed back on. Payoff is a meaningfully smaller self-contained Velopack package. Co-Authored-By: Claude Opus 4.7 --- TODO.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/TODO.md b/TODO.md index cf5f66f..587573c 100644 --- a/TODO.md +++ b/TODO.md @@ -323,3 +323,20 @@ load-bearing for the v1 demo, but they're the obvious next-pulls. - **Trash UI.** Soft-deleted Snips currently just vanish from the views. Need a "Trash" entry in the pane footer that lists trashed Snips with a restore action and a hard-delete option. +- **Re-enable `PublishTrimmed` once JSON serialisation is trim-safe.** + Disabled in `Snipdeck.App.csproj` to unblock the first release. To + turn it back on: + 1. Move `JsonSnipStore` / `JsonSettingsStore` onto + `JsonSerializerContext` source generation + (`[JsonSerializable(typeof(SnipStoreDocument))]` etc.) so the + untyped `Serialize/Deserialize` calls disappear. Removes IL2026. + 2. Audit Jdenticon-net, Microsoft.Windows.SDK.NET and WinRT.Runtime + trim warnings (IL2104); either suppress per-assembly with + `` entries / `[DynamicallyAccessedMembers]` + attributes, or accept them via targeted + `false` carve-outs. + 3. Flip `PublishTrimmed` back to `True` for Release. + + Payoff is a meaningfully smaller self-contained Velopack package + (probably ~80 MB instead of ~150–200 MB). Not urgent for alpha but + worth doing before a stable cut. From 0444b474964a3269c6c844f206dd4ac1982cb00c Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 03:59:44 +0000 Subject: [PATCH 2/5] Add TODO entries for code signing and iteration-loop improvements Two loose threads from the v0.1.0-alpha.1 release session worth capturing before they're lost: - Code-sign the installer. The unsigned alpha trips SmartScreen's "not commonly downloaded" warning. Documents the three options (Azure Trusted Signing recommended, OV cert, EV cert), the recipe for the Azure Trusted Signing path, and the open cost / Velopack- signing questions. - Tighten the iteration loop. The build/run/debug cycle used PRs as the feedback loop because the App project can't be fully built on Linux. Three independent improvements: EnableWindowsTargeting for local builds (catches analyser rules before push), branch protection for required status checks (prevents the merged-red failure mode), and the draft-PR-plus-force-push-fixup convention for keeping merged history clean. Co-Authored-By: Claude Opus 4.7 --- TODO.md | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/TODO.md b/TODO.md index 587573c..fb52deb 100644 --- a/TODO.md +++ b/TODO.md @@ -297,6 +297,107 @@ Reasons: --- +## Code-sign the installer (SmartScreen / Authenticode) + +**Problem.** The v0.1.0-alpha.1 installer is unsigned. Downloading it in +Edge / Chrome trips SmartScreen's "this file isn't commonly downloaded — +make sure you trust it" warning, and running it shows the blue "Windows +protected your PC" dialog. Every user has to click through "More info → +Run anyway", which is a terrible first impression and a real deterrent. + +**Cause.** SmartScreen reputation is built from a combination of valid +Authenticode signatures plus aggregate download counts. An unsigned +binary with zero downloads is automatic prompt-territory. Signing solves +the warning immediately for EV certs and over time (as downloads +accumulate) for OV certs. + +**Options.** + +- **Azure Trusted Signing** (recommended). Microsoft's new managed + signing service, ~$10/month, gives you a cloud-hosted signing identity + with no HSM to manage. Velopack supports it natively via + `--azureTrustedSigningAccount` / `--azureTrustedSigningCertProfile` + flags on `vpk pack`. Wants an Azure subscription and an OIDC trust + relationship from the GitHub Actions runner — five-step setup, no + long-lived secrets in the repo. +- **Standard OV code-signing certificate.** From DigiCert / Sectigo / + GlobalSign, ~$200–400/year. Comes as a cert + key the runner imports. + SmartScreen reputation builds gradually rather than instantly. Easier + if you already have an account with a CA. +- **EV code-signing certificate.** ~$400–600/year, requires an HSM / + USB token (hard to use from CI without a paid signing service in front + of it) but gets immediate SmartScreen reputation. Probably overkill + for an alpha; revisit pre-1.0 stable. + +**Sketch — Azure Trusted Signing path.** + +1. Create the Azure resources (Trusted Signing account, certificate + profile, OIDC trust to the GitHub repo) per + . +2. Add the federated-identity secrets / variables to the repo: tenant + id, client id, account / profile names. +3. In `release.yml`, extend the `vpk pack` step with + `--azureTrustedSigningAccount`, `--azureTrustedSigningCertProfile`, + `--azureTrustedSigningEndpoint` (region URL) and an `azure/login@v2` + step ahead of it for federated auth. +4. Verify with `signtool verify /pa /v Snipdeck-*-Setup.exe` locally + after a download, and re-do the manual install smoke test. + +**Open questions.** + +- Whether the cost ($10/month indefinitely) is acceptable for a hobby / + side project. If not, the OV cert path is a single annual payment. +- Whether the Velopack-generated update packages (the `.nupkg` deltas + used by self-update) also need signing for self-update to keep working + smoothly under SmartScreen. Worth reading the Velopack signing docs + carefully before flipping the switch. + +Not urgent — alpha users can click through the prompt — but blocking +for any kind of broader distribution. + +--- + +## Tighten the iteration loop (build/CI feedback) + +**Problem.** During the phase build-out and post-release fixes, the +build-and-debug cycle relied heavily on PRs as the feedback loop: +local Linux can't build the `Snipdeck.App` project (the WinUI XAML +compiler is Windows-only), so analyser errors / build breaks only +surface in CI. Each round-trip is a PR, which generates churn and +sometimes ends with master broken (PR #13 was merged with red CI). + +**Idea.** Three independent improvements; each is small, all three +together would make the iteration loop tight. + +**Sketch.** + +- **`EnableWindowsTargeting=true` for local builds.** Adding this to + `Snipdeck.App.csproj` (or passing as `-p:EnableWindowsTargeting=true` + on Linux) lets the restore + compile step run on non-Windows hosts. + The WinUI XAML pass still requires Windows, but most analyser / + C# compiler rules fire under plain `dotnet build` and would catch + editorconfig violations (IDE0058, IDE0330, IDE0370, IDE0005 — all + hit in this session) before the push. +- **Branch protection: require status checks to pass.** Add a rule to + the existing branch ruleset on `master` that requires the + `App build (windows)` and `Core build + tests (ubuntu)` checks to be + green before the Merge button activates. Mechanical guardrail + against the merged-red scenario. +- **Draft PRs with force-push fixups during iteration.** Convention, + not config: open PRs as **Draft** while iterating, and amend + + force-push fixup commits into the original commit instead of stacking + "fix lint" follow-ups. The final merged history shows one clean + commit per change, which is what the project's commit log wants. + Auto-mode currently blocks `git push --force-with-lease` — would + need an explicit settings.json permission or a one-off approval + to enable. Force-push to `master` itself stays blocked. + +**Sequencing.** Do `EnableWindowsTargeting` first (cheapest, biggest +quality-of-life win for me); then branch protection (one-off setup, +done forever); then adopt the draft-PR convention. + +--- + ## Carried over from the phase stack These were trimmed out of Phase 4–6 to keep the PRs reviewable. None are From 3d61fd5263c04496b61f6f4f301fa4d19dca4359 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 07:12:24 +0000 Subject: [PATCH 3/5] Add final UI-polish pass TODO (copy button width, danger-style Delete CLI) Co-Authored-By: Claude Opus 4.8 --- TODO.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/TODO.md b/TODO.md index fb52deb..1c49b21 100644 --- a/TODO.md +++ b/TODO.md @@ -398,6 +398,26 @@ done forever); then adopt the draft-PR convention. --- +## Final UI polish pass + +A deliberate sweep of visual / interaction rough edges, done **at the end** +once the feature surface has settled — batching the nitpicks avoids +re-polishing the same screens after every feature lands. Known items so far: + +- **Snip card Copy button is too wide.** It currently stretches further than + it should; size it to its content (or a sensible fixed width) so the card + action row reads cleanly. +- **"Delete CLI" button should be styled as a danger action.** It's a + destructive, hard-to-reverse operation — give it the red/danger accent + (e.g. a danger `Button` style / `Foreground` from the theme palette) + rather than the neutral default, so it visually distinguishes itself from + benign actions. + +Add to this list as other cosmetic / interaction snags turn up during +feature work, then knock them out in one pass before a stable cut. + +--- + ## Carried over from the phase stack These were trimmed out of Phase 4–6 to keep the PRs reviewable. None are From a3b6edc3605dae5b25926877dba3cc00d0b1c80f Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 07:15:29 +0000 Subject: [PATCH 4/5] Add UI-polish TODOs: consistent button corner radii, whole-card copy target Co-Authored-By: Claude Opus 4.8 --- TODO.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/TODO.md b/TODO.md index 1c49b21..c3c256b 100644 --- a/TODO.md +++ b/TODO.md @@ -412,6 +412,17 @@ re-polishing the same screens after every feature lands. Known items so far: (e.g. a danger `Button` style / `Foreground` from the theme palette) rather than the neutral default, so it visually distinguishes itself from benign actions. +- **Inconsistent button corner radii.** Cancel buttons render with square + corners while Save / Copy buttons are rounded. Standardise on rounded + corners for *all* buttons (the dialog `CloseButton` is the likely culprit — + align it with the themed `CornerRadius` the primary buttons pick up). +- **Consider making the whole Snip card the Copy target.** Rather than a + dedicated Copy button on the card, let a click anywhere on the card trigger + the copy / parameter-fill flow. Weigh the trade-offs before committing: + discoverability and a cleaner card vs. losing an explicit affordance and + the risk of accidental copies / conflicts with the overflow menu and + favourite star hit-targets. Decide, then either remove the button or keep + it. Add to this list as other cosmetic / interaction snags turn up during feature work, then knock them out in one pass before a stable cut. From feb042ece43e7bc7411e32969b42b5584a465574 Mon Sep 17 00:00:00 2001 From: Stuart Meeks Date: Sat, 30 May 2026 08:33:28 +0000 Subject: [PATCH 5/5] Remove shipped items from TODO Drop the five carried-over items that have since shipped: backup retention, CLI delete, Trash UI, Nerdbank.GitVersioning, and Markdown rendering. The remaining carried-over items (hotkey rebinding, storage-path move/adopt/warn, re-enable PublishTrimmed) and every other section are untouched. Co-Authored-By: Claude Opus 4.8 --- TODO.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/TODO.md b/TODO.md index c3c256b..40f789a 100644 --- a/TODO.md +++ b/TODO.md @@ -442,19 +442,6 @@ load-bearing for the v1 demo, but they're the obvious next-pulls. the user changes the storage path we need three flows: move the existing store to the new path; adopt a store already at the new path; warn when both exist. UI: a "Change…" button next to the read-only path display. -- **Backup retention configurable.** Plumbing: `BackupService` takes - retention at construction time today; either re-create it on the relevant - config change or have it read from `AppConfig` lazily. -- **CLI delete.** Settle cascade semantics — must-be-empty vs trash-all-child-snips — - before wiring the UI. -- **Nerdbank.GitVersioning.** Right now `InformationalVersion` falls back to - the assembly's compile-time version. NBGV would give us a real git-tag-derived - string at build time (`v1.2.3+gabcdef0`). -- **Markdown rendering for Snip descriptions.** Stored as plain text right - now; render via a markdown control on the parameter-fill / detail view. -- **Trash UI.** Soft-deleted Snips currently just vanish from the views. - Need a "Trash" entry in the pane footer that lists trashed Snips with a - restore action and a hard-delete option. - **Re-enable `PublishTrimmed` once JSON serialisation is trim-safe.** Disabled in `Snipdeck.App.csproj` to unblock the first release. To turn it back on: