@sebastienrousseau/dotfiles 0.2.501 → 0.2.503

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (420) hide show
  1. package/CHANGELOG.md +155 -4
  2. package/LICENSE +21 -1283
  3. package/README.md +40 -8
  4. package/docs/CONFIG_STRATEGY.md +124 -0
  5. package/docs/COPYRIGHT +1 -1
  6. package/docs/GOVERNANCE.md +98 -0
  7. package/docs/MAINTAINERS.md +41 -0
  8. package/docs/OPENCODE.md +127 -0
  9. package/docs/README.md +2 -0
  10. package/docs/STRUCTURE.md +102 -0
  11. package/docs/adr/ADR-011-nushell-tier3-keep.md +2 -2
  12. package/docs/architecture/AI_COST_OPTIMIZATION.md +143 -0
  13. package/docs/architecture/REPO_LAYOUT.md +8 -8
  14. package/docs/archive/MILESTONE_v0.2.493.md +1 -1
  15. package/docs/index.md +2 -2
  16. package/docs/interop/POWERSHELL.md +1 -1
  17. package/docs/manual/00-introduction.md +1 -1
  18. package/docs/manual/01-concepts/02-trust-model.md +1 -1
  19. package/docs/manual/03-reference/01-dot-cli.md +63 -45
  20. package/docs/manual/03-reference/02-config-files.md +2 -2
  21. package/docs/manual/03-reference/05-feature-flags.md +62 -3
  22. package/docs/manual/_toc.yml +1 -1
  23. package/docs/manual/command-index.md +72 -55
  24. package/docs/manual/index.md +66 -0
  25. package/docs/operations/CI_COMPOSITES.md +2 -2
  26. package/docs/operations/COMPLETIONS.md +2 -2
  27. package/docs/operations/COVERAGE.md +40 -6
  28. package/docs/operations/HARD_AUDIT_2026.md +631 -0
  29. package/docs/operations/MAINTENANCE.md +3 -3
  30. package/docs/operations/MANIFEST.md +127 -0
  31. package/docs/operations/REGISTRY.md +89 -0
  32. package/docs/operations/RELEASE_PIPELINE.md +130 -0
  33. package/docs/operations/RFC_v0_2_503_reorganization.md +280 -0
  34. package/docs/operations/ROADMAP_2026.md +665 -0
  35. package/docs/operations/ROADMAP_V0_2_503.md +134 -0
  36. package/docs/operations/TESTING.md +17 -0
  37. package/docs/operations/TRACEABILITY.md +9 -3
  38. package/docs/operations/VERSION_SYNC.md +4 -4
  39. package/docs/reference/POWERSHELL_PARITY.md +81 -0
  40. package/docs/registry.json +6 -0
  41. package/docs/schema/dot-env-v1.json +110 -0
  42. package/docs/security/CI_EGRESS_ALLOWLIST.md +1 -1
  43. package/docs/security/CI_PINNING.md +121 -0
  44. package/docs/security/COMMIT_SIGNING.md +138 -0
  45. package/docs/security/DEPS_DEV_EXCEPTIONS.md +2 -2
  46. package/docs/security/DISCLOSURE.md +130 -0
  47. package/docs/security/FUZZING.md +114 -0
  48. package/docs/security/INSTALL_VERIFICATION.md +2 -2
  49. package/docs/security/KEY_ROTATION.md +81 -1
  50. package/docs/security/POLICY_RELEASES.md +2 -2
  51. package/docs/security/SCORECARD.md +130 -15
  52. package/docs/security/SHELL_EXEMPTIONS.md +4 -4
  53. package/docs/security/VERIFY_RELEASE.md +201 -0
  54. package/docs/security/security-pubkey.asc +15 -0
  55. package/install.sh +67 -38
  56. package/package.json +1 -1
  57. package/scripts/README.md +123 -0
  58. package/scripts/ci/check-copyright-headers.sh +4 -93
  59. package/scripts/ci/check-shell-preamble.sh +4 -103
  60. package/scripts/ci/guard-gitleaks-checkout.sh +4 -54
  61. package/scripts/diagnostics/a2a-conformance.sh +4 -4
  62. package/scripts/diagnostics/alias-governance.sh +1 -1
  63. package/scripts/diagnostics/aliases-cheatsheet.sh +2 -2
  64. package/scripts/diagnostics/benchmark.sh +4 -4
  65. package/scripts/diagnostics/conflicts.sh +2 -2
  66. package/scripts/diagnostics/doctor-unified.sh +2 -2
  67. package/scripts/diagnostics/doctor.sh +45 -15
  68. package/scripts/diagnostics/drift-dashboard.sh +2 -2
  69. package/scripts/diagnostics/health.sh +4 -4
  70. package/scripts/diagnostics/history-analysis.sh +2 -2
  71. package/scripts/diagnostics/mcp-doctor.sh +10 -7
  72. package/scripts/diagnostics/perf.sh +4 -4
  73. package/scripts/diagnostics/scorecard.sh +4 -4
  74. package/scripts/diagnostics/security-score.sh +2 -2
  75. package/scripts/diagnostics/smoke-test.sh +2 -2
  76. package/scripts/diagnostics/snapshot.sh +2 -2
  77. package/scripts/diagnostics/verify.sh +4 -4
  78. package/scripts/diagnostics/version-locks.sh +2 -2
  79. package/scripts/diagnostics/workstation-attestation.sh +14 -14
  80. package/scripts/dot/commands/agent.sh +27 -22
  81. package/scripts/dot/commands/agents.sh +335 -0
  82. package/scripts/dot/commands/ai.sh +144 -25
  83. package/scripts/dot/commands/aliases.sh +10 -8
  84. package/scripts/dot/commands/appearance.sh +2 -2
  85. package/scripts/dot/commands/core.sh +12 -6
  86. package/scripts/dot/commands/diagnostics.sh +5 -5
  87. package/scripts/dot/commands/env-emit.sh +202 -0
  88. package/scripts/dot/commands/fleet.sh +290 -14
  89. package/scripts/dot/commands/init.sh +184 -0
  90. package/scripts/dot/commands/lint.sh +9 -4
  91. package/scripts/dot/commands/manual.sh +3 -3
  92. package/scripts/dot/commands/meta.sh +19 -10
  93. package/scripts/dot/commands/patterns.sh +2 -2
  94. package/scripts/dot/commands/registry.sh +263 -0
  95. package/scripts/dot/commands/restore.sh +4 -4
  96. package/scripts/dot/commands/secrets.sh +4 -3
  97. package/scripts/dot/commands/security.sh +2 -2
  98. package/scripts/dot/commands/tools.sh +62 -4
  99. package/scripts/dot/powershell/Dot.psm1 +199 -0
  100. package/scripts/fonts/install-nerd-fonts.sh +2 -2
  101. package/scripts/git-hooks/pre-commit-audit.sh +2 -2
  102. package/scripts/git-hooks/pre-push +13 -0
  103. package/scripts/lib/secrets_provider.sh +32 -6
  104. package/scripts/ops/ai-setup.sh +1 -1
  105. package/scripts/ops/bundle.sh +2 -2
  106. package/scripts/ops/chaos.sh +2 -2
  107. package/scripts/ops/chezmoi-apply.sh +4 -4
  108. package/scripts/ops/heal.sh +4 -4
  109. package/scripts/ops/post-apply-repair.sh +2 -2
  110. package/scripts/ops/prewarm.sh +2 -2
  111. package/scripts/ops/release.sh +4 -4
  112. package/scripts/ops/rollback.sh +18 -4
  113. package/scripts/ops/setup.sh +2 -2
  114. package/scripts/qa/check-version-consistency.sh +123 -0
  115. package/scripts/qa/coverage-baseline.sh +1 -1
  116. package/scripts/qa/docs-coverage.sh +2 -2
  117. package/scripts/qa/powershell-contract.ps1 +1 -1
  118. package/scripts/qa/scorecard-snapshot.sh +127 -0
  119. package/scripts/security/backup.sh +2 -2
  120. package/scripts/security/check-disclosure-key-expiry.sh +110 -0
  121. package/scripts/security/dns-doh.sh +4 -4
  122. package/scripts/security/encryption-check.sh +4 -4
  123. package/scripts/security/enforce-policies.sh +2 -2
  124. package/scripts/security/firewall.sh +4 -4
  125. package/scripts/security/lock-configs.sh +11 -2
  126. package/scripts/security/lock-screen.sh +4 -4
  127. package/scripts/security/manage-secrets.sh +2 -2
  128. package/scripts/security/ssh-cert.sh +2 -2
  129. package/scripts/security/telemetry-kill.sh +4 -4
  130. package/scripts/security/usb-safety.sh +4 -4
  131. package/scripts/theme/extract-heic-frames.sh +114 -0
  132. package/scripts/theme/rebuild-themes.sh +8 -1
  133. package/scripts/theme/switch.sh +13 -6
  134. package/scripts/theme/wallpaper-sync.sh +297 -93
  135. package/scripts/tuning/linux.sh +2 -2
  136. package/scripts/tuning/macos.sh +2 -2
  137. package/scripts/version-sync.sh +58 -7
  138. package/dot_config/.module-manifest.json +0 -69
  139. package/dot_config/ai/identity.md +0 -23
  140. package/dot_config/ai/patterns/architect.md +0 -16
  141. package/dot_config/ai/patterns/hardener.md +0 -15
  142. package/dot_config/ai/patterns/refactor.md +0 -15
  143. package/dot_config/aider/aider.conf.yml +0 -32
  144. package/dot_config/alacritty/alacritty.toml.tmpl +0 -55
  145. package/dot_config/ansible/ansible.cfg +0 -11
  146. package/dot_config/atuin/config.toml.tmpl +0 -47
  147. package/dot_config/bat/config +0 -23
  148. package/dot_config/brave-flags.conf.tmpl +0 -7
  149. package/dot_config/btop/btop.conf +0 -16
  150. package/dot_config/btop/themes/tokyonight.theme +0 -34
  151. package/dot_config/bun/bunfig.toml.tmpl +0 -33
  152. package/dot_config/claude/mcp_servers.json +0 -20
  153. package/dot_config/containers/containers.conf +0 -14
  154. package/dot_config/curl/dot_curlrc +0 -18
  155. package/dot_config/dlv/config.yml +0 -39
  156. package/dot_config/docker/config.json +0 -15
  157. package/dot_config/dotfiles/agent-card.json +0 -29
  158. package/dot_config/dotfiles/agent-profiles.json +0 -92
  159. package/dot_config/dotfiles/boot/README.md +0 -13
  160. package/dot_config/dotfiles/grub/README.md +0 -13
  161. package/dot_config/dotfiles/lock/README.md +0 -13
  162. package/dot_config/dotfiles/mcp-lock.json +0 -33
  163. package/dot_config/dotfiles/mcp-policy.json +0 -52
  164. package/dot_config/dotfiles/mcp-registry.json +0 -47
  165. package/dot_config/dotfiles/model-registry.json +0 -20
  166. package/dot_config/dotfiles/policy-bundles.json +0 -38
  167. package/dot_config/dotfiles/prompt-registry.json +0 -16
  168. package/dot_config/dotfiles/versions.env +0 -18
  169. package/dot_config/duf/duf.conf +0 -6
  170. package/dot_config/duti/defaults.duti +0 -5
  171. package/dot_config/emoji/emoji.txt +0 -34
  172. package/dot_config/environment.d/50-ssh-agent.conf +0 -2
  173. package/dot_config/environment.d/90-wayland.conf +0 -19
  174. package/dot_config/fastfetch/config.jsonc +0 -28
  175. package/dot_config/firefox/user.js.tmpl +0 -58
  176. package/dot_config/fish/completions/dot-theme-sync.fish.tmpl +0 -9
  177. package/dot_config/fish/completions/dot.fish.tmpl +0 -115
  178. package/dot_config/fish/conf.d/000-perf-cache.fish +0 -56
  179. package/dot_config/fish/conf.d/aliases.fish.tmpl +0 -77
  180. package/dot_config/fish/conf.d/env.fish.tmpl +0 -48
  181. package/dot_config/fish/conf.d/functions.fish.tmpl +0 -22
  182. package/dot_config/fish/conf.d/init.fish.tmpl +0 -172
  183. package/dot_config/fish/config.fish.tmpl +0 -44
  184. package/dot_config/fish/fish_plugins +0 -1
  185. package/dot_config/fish/functions/_.fish +0 -3
  186. package/dot_config/fish/functions/_cached_eval.fish +0 -131
  187. package/dot_config/fish/functions/_cached_eval_clear.fish +0 -17
  188. package/dot_config/fish/functions/als.fish +0 -46
  189. package/dot_config/fish/functions/bg-upgrade.fish +0 -7
  190. package/dot_config/fish/functions/c.fish +0 -3
  191. package/dot_config/fish/functions/cat.fish +0 -9
  192. package/dot_config/fish/functions/d.fish +0 -7
  193. package/dot_config/fish/functions/dot.fish +0 -34
  194. package/dot_config/fish/functions/h.fish +0 -3
  195. package/dot_config/fish/functions/l.fish +0 -7
  196. package/dot_config/fish/functions/la.fish +0 -7
  197. package/dot_config/fish/functions/ll.fish +0 -7
  198. package/dot_config/fish/functions/log_error.fish +0 -13
  199. package/dot_config/fish/functions/log_info.fish +0 -13
  200. package/dot_config/fish/functions/lr.fish +0 -7
  201. package/dot_config/fish/functions/lra.fish +0 -7
  202. package/dot_config/fish/functions/ls.fish +0 -7
  203. package/dot_config/fish/functions/lt.fish +0 -7
  204. package/dot_config/fish/functions/lta.fish +0 -7
  205. package/dot_config/fish/functions/notify-run.fish +0 -11
  206. package/dot_config/fish/functions/q.fish +0 -3
  207. package/dot_config/fish/functions/silent-run.fish +0 -7
  208. package/dot_config/fish/functions/yy.fish +0 -8
  209. package/dot_config/flatpak/flatpak.list +0 -4
  210. package/dot_config/fontconfig/fonts.conf.tmpl +0 -57
  211. package/dot_config/foot/foot.ini.tmpl +0 -33
  212. package/dot_config/fuzzel/fuzzel.ini.tmpl +0 -18
  213. package/dot_config/fzf/fzf.zsh +0 -48
  214. package/dot_config/gem/gemrc +0 -9
  215. package/dot_config/gh/config.yml +0 -12
  216. package/dot_config/ghostty/config.tmpl +0 -165
  217. package/dot_config/git/allowed_signers.tmpl +0 -18
  218. package/dot_config/git/attributes +0 -12
  219. package/dot_config/git/commit-template +0 -10
  220. package/dot_config/git/hooks/executable_commit-msg +0 -146
  221. package/dot_config/git/ignore +0 -27
  222. package/dot_config/gnupg/gpg-agent.conf +0 -11
  223. package/dot_config/go/golangci.yml +0 -118
  224. package/dot_config/go/gopls.json +0 -30
  225. package/dot_config/goose/config.yaml +0 -29
  226. package/dot_config/gtk-3.0/gtk.css.tmpl +0 -184
  227. package/dot_config/gtk-3.0/settings.ini.tmpl +0 -27
  228. package/dot_config/gtk-4.0/gtk.css.tmpl +0 -252
  229. package/dot_config/gtk-4.0/settings.ini.tmpl +0 -18
  230. package/dot_config/htop/htoprc +0 -20
  231. package/dot_config/inputrc +0 -2
  232. package/dot_config/ipython/profile_default/ipython_config.py +0 -19
  233. package/dot_config/just/justfile +0 -122
  234. package/dot_config/k9s/config.yaml +0 -65
  235. package/dot_config/k9s/skins/catppuccin-mocha.yaml +0 -116
  236. package/dot_config/kanshi/config.tmpl +0 -22
  237. package/dot_config/karabiner/karabiner.json +0 -14
  238. package/dot_config/kitty/kitty.conf.tmpl +0 -53
  239. package/dot_config/lazydocker/config.yml +0 -186
  240. package/dot_config/lazygit/config.yml +0 -35
  241. package/dot_config/mako/config +0 -47
  242. package/dot_config/mas/masapps.txt +0 -5
  243. package/dot_config/micro/settings.json +0 -3
  244. package/dot_config/mimeapps.list +0 -77
  245. package/dot_config/minikube/config.json +0 -13
  246. package/dot_config/mise/config.toml +0 -99
  247. package/dot_config/mongosh/mongoshrc.js +0 -68
  248. package/dot_config/mpv/input.conf +0 -47
  249. package/dot_config/mpv/mpv.conf +0 -47
  250. package/dot_config/mycli/myclirc +0 -67
  251. package/dot_config/nano/nanorc +0 -28
  252. package/dot_config/ncdu/config +0 -12
  253. package/dot_config/niri/config.kdl.tmpl +0 -327
  254. package/dot_config/nushell/aliases.nu +0 -18
  255. package/dot_config/nushell/cached_eval.nu +0 -80
  256. package/dot_config/nushell/completions.nu.tmpl +0 -52
  257. package/dot_config/nushell/config.nu.tmpl +0 -86
  258. package/dot_config/nushell/env.nu.tmpl +0 -102
  259. package/dot_config/nushell/functions.nu.tmpl +0 -17
  260. package/dot_config/nvim/init.lua +0 -18
  261. package/dot_config/nvim/lazy-lock.json +0 -58
  262. package/dot_config/nvim/lua/config/autocmds.lua +0 -107
  263. package/dot_config/nvim/lua/config/keymaps.lua +0 -92
  264. package/dot_config/nvim/lua/config/lazy.lua +0 -44
  265. package/dot_config/nvim/lua/config/options.lua +0 -49
  266. package/dot_config/nvim/lua/plugins/ai.lua +0 -75
  267. package/dot_config/nvim/lua/plugins/coding.lua +0 -216
  268. package/dot_config/nvim/lua/plugins/completion.lua +0 -60
  269. package/dot_config/nvim/lua/plugins/dap.lua +0 -412
  270. package/dot_config/nvim/lua/plugins/editor.lua +0 -55
  271. package/dot_config/nvim/lua/plugins/git.lua +0 -10
  272. package/dot_config/nvim/lua/plugins/lsp.lua +0 -156
  273. package/dot_config/nvim/lua/plugins/markdown.lua +0 -18
  274. package/dot_config/nvim/lua/plugins/rust.lua +0 -34
  275. package/dot_config/nvim/lua/plugins/sessions.lua +0 -33
  276. package/dot_config/nvim/lua/plugins/ui.lua +0 -509
  277. package/dot_config/paru/paru.conf +0 -10
  278. package/dot_config/pip/pip.conf.tmpl +0 -32
  279. package/dot_config/powershell/Microsoft.PowerShell_profile.ps1.tmpl +0 -81
  280. package/dot_config/pueue/pueue.yml +0 -34
  281. package/dot_config/pypoetry/config.toml +0 -6
  282. package/dot_config/pyrightconfig.json +0 -5
  283. package/dot_config/raycast/README.md +0 -13
  284. package/dot_config/redis/redisclirc +0 -41
  285. package/dot_config/ripgrep/ripgreprc +0 -21
  286. package/dot_config/shell/00-core-paths.sh.tmpl +0 -134
  287. package/dot_config/shell/05-core-safety.sh +0 -48
  288. package/dot_config/shell/10-secrets.sh +0 -41
  289. package/dot_config/shell/40-fzf-defaults.sh.tmpl +0 -17
  290. package/dot_config/shell/40-ls-colors.sh +0 -49
  291. package/dot_config/shell/50-logic-functions-core.sh.tmpl +0 -11
  292. package/dot_config/shell/50-logic-functions.sh.tmpl +0 -11
  293. package/dot_config/shell/51-logic-functions-extra.sh.tmpl +0 -65
  294. package/dot_config/shell/90-ux-aliases.sh.tmpl +0 -121
  295. package/dot_config/shell/91-ux-aliases-lazy.sh.tmpl +0 -55
  296. package/dot_config/shell/Brewfile +0 -207
  297. package/dot_config/shell/Brewfile.cask +0 -92
  298. package/dot_config/shell/Brewfile.cli +0 -127
  299. package/dot_config/shell/README.md +0 -284
  300. package/dot_config/shell/als_data.txt.tmpl +0 -65
  301. package/dot_config/shell/custom/auto_ls.zsh +0 -20
  302. package/dot_config/shell/custom/context_suggest.zsh +0 -68
  303. package/dot_config/shell/custom/error_analysis.zsh +0 -45
  304. package/dot_config/sops/dot_sops.yaml +0 -23
  305. package/dot_config/starship.toml.tmpl +0 -202
  306. package/dot_config/swaylock/config +0 -43
  307. package/dot_config/systemd/user/dotfiles-maintenance.service +0 -8
  308. package/dot_config/systemd/user/dotfiles-maintenance.timer +0 -11
  309. package/dot_config/systemd/user/pueued.service +0 -12
  310. package/dot_config/systemd/user/ssh-agent.service +0 -12
  311. package/dot_config/task/Taskfile.yml +0 -86
  312. package/dot_config/tflint/tflint.hcl +0 -9
  313. package/dot_config/tmux/tmux.conf.tmpl +0 -223
  314. package/dot_config/topgrade.toml.tmpl +0 -54
  315. package/dot_config/user-dirs.dirs +0 -10
  316. package/dot_config/vscode/extensions.txt +0 -11
  317. package/dot_config/vscode/settings.json.tmpl +0 -82
  318. package/dot_config/waybar/config.jsonc.tmpl +0 -90
  319. package/dot_config/waybar/style.css.tmpl +0 -211
  320. package/dot_config/wezterm/wezterm.lua.tmpl +0 -64
  321. package/dot_config/wget/wgetrc +0 -12
  322. package/dot_config/xdg-desktop-portal/niri-portals.conf +0 -5
  323. package/dot_config/yarn/yarnrc.yml +0 -36
  324. package/dot_config/yazi/keymap.toml +0 -67
  325. package/dot_config/yazi/theme.toml +0 -102
  326. package/dot_config/yazi/yazi.toml +0 -40
  327. package/dot_config/zathura/zathurarc +0 -52
  328. package/dot_config/zellij/config.kdl.tmpl +0 -79
  329. package/dot_config/zsh/dot_zprofile +0 -7
  330. package/dot_config/zsh/dot_zshenv +0 -5
  331. package/dot_config/zsh/dot_zshrc.tmpl +0 -635
  332. package/dot_config/zsh/rc.d/00-alias-shims.zsh +0 -99
  333. package/dot_config/zsh/rc.d/05-ssh-agent.zsh +0 -18
  334. package/dot_config/zsh/rc.d/10-env.zsh.tmpl +0 -28
  335. package/dot_config/zsh/rc.d/20-zinit.zsh +0 -65
  336. package/dot_config/zsh/rc.d/30-options.zsh.tmpl +0 -214
  337. package/dot_config/zsh/rc.d/40-bell.zsh +0 -20
  338. package/dot_config/zsh/rc.d/50-login-fortune.zsh +0 -9
  339. package/dot_config/zsh/rc.d/99-alias-wrapper.zsh +0 -32
  340. package/dot_local/bin/executable_ai-update +0 -195
  341. package/dot_local/bin/executable_ai_core +0 -152
  342. package/dot_local/bin/executable_antigravity +0 -11
  343. package/dot_local/bin/executable_b64 +0 -84
  344. package/dot_local/bin/executable_bm +0 -79
  345. package/dot_local/bin/executable_cb +0 -39
  346. package/dot_local/bin/executable_dot +0 -596
  347. package/dot_local/bin/executable_dot-ai +0 -36
  348. package/dot_local/bin/executable_dot-bootstrap +0 -77
  349. package/dot_local/bin/executable_dot-launch-or-focus +0 -52
  350. package/dot_local/bin/executable_dot-load-benchmark +0 -31
  351. package/dot_local/bin/executable_dot-load-benchmark-pty +0 -77
  352. package/dot_local/bin/executable_dot-theme-sync +0 -952
  353. package/dot_local/bin/executable_dot_completion +0 -57
  354. package/dot_local/bin/executable_dtags +0 -28
  355. package/dot_local/bin/executable_epoch +0 -67
  356. package/dot_local/bin/executable_extract +0 -41
  357. package/dot_local/bin/executable_gbd +0 -52
  358. package/dot_local/bin/executable_gd +0 -42
  359. package/dot_local/bin/executable_git-ai-commit +0 -175
  360. package/dot_local/bin/executable_git-ai-diff +0 -169
  361. package/dot_local/bin/executable_gl +0 -101
  362. package/dot_local/bin/executable_hash +0 -161
  363. package/dot_local/bin/executable_hashsum +0 -160
  364. package/dot_local/bin/executable_hex +0 -115
  365. package/dot_local/bin/executable_jsonv +0 -78
  366. package/dot_local/bin/executable_jwt +0 -94
  367. package/dot_local/bin/executable_kill-port +0 -75
  368. package/dot_local/bin/executable_lorem +0 -118
  369. package/dot_local/bin/executable_mkscript +0 -35
  370. package/dot_local/bin/executable_monitor +0 -56
  371. package/dot_local/bin/executable_myip +0 -51
  372. package/dot_local/bin/executable_notify +0 -24
  373. package/dot_local/bin/executable_open +0 -38
  374. package/dot_local/bin/executable_pw +0 -27
  375. package/dot_local/bin/executable_rec-start +0 -46
  376. package/dot_local/bin/executable_rec-stop +0 -35
  377. package/dot_local/bin/executable_regex +0 -132
  378. package/dot_local/bin/executable_start-niri +0 -8
  379. package/dot_local/bin/executable_tmux-sessionizer +0 -314
  380. package/dot_local/bin/executable_tour +0 -177
  381. package/dot_local/bin/executable_up +0 -23
  382. package/dot_local/bin/executable_update +0 -142
  383. package/dot_local/bin/executable_uuid +0 -87
  384. package/dot_local/bin/executable_win +0 -32
  385. package/dot_local/bin/executable_yamlv +0 -57
  386. package/dot_local/share/bash-completion/completions/dot +0 -72
  387. package/dot_local/share/icons/hicolor/128x128/apps/rousseau.png +0 -0
  388. package/dot_local/share/icons/hicolor/16x16/apps/rousseau.png +0 -0
  389. package/dot_local/share/icons/hicolor/24x24/apps/rousseau.png +0 -0
  390. package/dot_local/share/icons/hicolor/256x256/apps/rousseau.png +0 -0
  391. package/dot_local/share/icons/hicolor/32x32/apps/rousseau.png +0 -0
  392. package/dot_local/share/icons/hicolor/48x48/apps/rousseau.png +0 -0
  393. package/dot_local/share/icons/hicolor/512x512/apps/rousseau.png +0 -0
  394. package/dot_local/share/icons/hicolor/64x64/apps/rousseau.png +0 -0
  395. package/dot_local/share/icons/hicolor/96x96/apps/rousseau.png +0 -0
  396. package/dot_local/share/icons/hicolor/scalable/apps/rousseau.png +0 -0
  397. package/dot_local/share/man/man1/dot.1 +0 -149
  398. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_download +0 -64
  399. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_install +0 -18
  400. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_list-all +0 -13
  401. package/dot_local/share/wayland-sessions/niri.desktop.tmpl +0 -6
  402. package/dot_local/share/zsh/completions/.keep +0 -0
  403. package/dot_local/share/zsh/completions/_dot +0 -283
  404. package/scripts/ci/check-dangerous-chmod.sh +0 -19
  405. package/scripts/ci/check-deps-dev.sh +0 -236
  406. package/scripts/ci/check-insecure-tls.sh +0 -61
  407. package/scripts/ci/check-regression-traceability.sh +0 -67
  408. package/scripts/ci/install-chezmoi-verified.sh +0 -64
  409. package/scripts/ci/run-coverage.sh +0 -362
  410. package/scripts/ci/validate-chezmoidata.sh +0 -25
  411. package/scripts/ci/validate-ci-config.sh +0 -224
  412. package/scripts/docs/build-manual.sh +0 -883
  413. package/scripts/docs/check-manual.sh +0 -213
  414. package/scripts/dot/lib/bento.sh +0 -50
  415. package/scripts/dot/lib/log.sh +0 -200
  416. package/scripts/dot/lib/platform.sh +0 -99
  417. package/scripts/dot/lib/ui.sh +0 -518
  418. package/scripts/dot/lib/utils.sh +0 -377
  419. package/scripts/maintenance/check-updates.sh +0 -131
  420. package/scripts/release/package-policy-bundles.sh +0 -125
@@ -11,6 +11,33 @@ narrative behind it.
11
11
 
12
12
  ## Live score
13
13
 
14
+ <!-- BEGIN scorecard-snapshot (auto-generated, do not edit by hand) -->
15
+ Aggregate score **7.6 / 10** at 2026-05-17T08:11:51Z.
16
+
17
+ | Check | Score | Reason |
18
+ |---|---:|---|
19
+ | Binary-Artifacts | 10 | no binaries found in the repo |
20
+ | Branch-Protection | -1 | internal error: error during branchesHandler.setup: internal error: some github tokens can't read cl |
21
+ | CI-Tests | 10 | 15 out of 15 merged PRs checked by a CI test -- score normalized to 10 |
22
+ | CII-Best-Practices | 2 | badge detected: InProgress |
23
+ | Code-Review | 0 | Found 0/30 approved changesets -- score normalized to 0 |
24
+ | Contributors | 0 | project has 0 contributing companies or organizations -- score normalized to 0 |
25
+ | Dangerous-Workflow | 10 | no dangerous workflow patterns detected |
26
+ | Dependency-Update-Tool | 10 | update tool detected |
27
+ | Fuzzing | 0 | project is not fuzzed |
28
+ | License | 9 | license file detected |
29
+ | Maintained | 10 | 30 commit(s) and 30 issue activity found in the last 90 days -- score normalized to 10 |
30
+ | Packaging | 10 | packaging workflow detected |
31
+ | Pinned-Dependencies | 9 | dependency not pinned by hash detected -- score normalized to 9 |
32
+ | SAST | 10 | SAST tool is run on all commits |
33
+ | Security-Policy | 10 | security policy file detected |
34
+ | Signed-Releases | 3 | 1 out of the last 3 releases have a total of 2 signed artifacts. |
35
+ | Token-Permissions | 10 | GitHub workflow tokens follow principle of least privilege |
36
+ | Vulnerabilities | 10 | 0 existing vulnerabilities detected |
37
+
38
+ *Refresh: `scripts/qa/scorecard-snapshot.sh` · CI check: `lint/scorecard-snapshot` (planned).*
39
+ <!-- END scorecard-snapshot -->
40
+
14
41
  [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/sebastienrousseau/dotfiles/badge)](https://scorecard.dev/viewer/?uri=github.com/sebastienrousseau/dotfiles)
15
42
 
16
43
  The badge above is regenerated every Monday at 06:00 UTC and on every
@@ -30,7 +57,7 @@ Regressions are triaged within one Monday cycle: identify the check
30
57
  that dropped, either remediate or file an exception entry below with
31
58
  a rationale and an expiry date.
32
59
 
33
- ## Per-check posture (snapshot)
60
+ ## Per-check posture (snapshot, master HEAD)
34
61
 
35
62
  The checks below come from OpenSSF Scorecard's published rubric. Tick
36
63
  marks reflect this repo's posture at the time of writing — the
@@ -38,30 +65,103 @@ marks reflect this repo's posture at the time of writing — the
38
65
 
39
66
  | Check | Status | Notes |
40
67
  |---|---|---|
41
- | Branch-Protection | | `master` requires signed commits, linear history, required checks. Codified at `.github/rulesets/master.json` and `.github/branch-protection-config.json`. |
42
- | Code-Review | | Every PR requires at least one approval; CODEOWNERS in place. |
68
+ | Branch-Protection | | `master` requires signed commits, linear history, required checks (`.github/rulesets/master.json`). Scorecard can't read classic protection rules without a fine-grained PAT, so this check reports as `-1` ("internal error"). |
69
+ | Code-Review | | Single-maintainer repo; PRs are self-merged after CI. Scorecard scores 0/30 here by design — see `Open findings` below. |
43
70
  | Signed-Commits | ✓ | Enforced by pre-push hook (`scripts/git-hooks/pre-push`) and at-push by branch protection (#853 + #857). |
44
71
  | Dependency-Update-Tool | ✓ | Dependabot configured for github-actions / npm / docker / devcontainers / uv. |
45
- | Fuzzing | ⚠ | `install.sh` fuzz harness lives under `tests/fuzz/` (closes #881). Coverage is the script's CLI surface plus chaos input fixtures not full corpus fuzzing yet. |
46
- | License | ✓ | Apache-2.0 at repo root. |
47
- | Maintained | ✓ | Active commit cadence; the [README](../../README.md) lists the current `dotfiles_version` (v0.2.501). |
48
- | Pinned-Dependencies | | Every workflow action is pinned to a 40-char commit SHA; the lint rule under `actionlint` enforces this on PR. |
72
+ | Fuzzing | ⚠ | `install.sh` fuzz harness lives under `tests/fuzz/` (closes #881), but it's shell-based and Scorecard's heuristic only recognizes OSS-Fuzz / ClusterFuzzLite / native Go fuzz / libFuzzer / Atheris. None support shell. Property tests under `tests/unit/functions/test_property_*.sh` cover the closest equivalent surface. |
73
+ | License | ✓ | MIT at repo root (`LICENSE`). |
74
+ | Maintained | ✓ | Active commit cadence; the [README](../../README.md) lists the current `dotfiles_version`. |
75
+ | Pinned-Dependencies | | Closed 8 of 14 findings this cycle (every Dockerfile base + every workflow action + 2 `curl \| sh` installers + the `npm install -g npm` upgrade step). 5 residual findings stay open by design — see `Open findings`. |
49
76
  | SAST | ✓ | CodeQL (`.github/workflows/codeql.yml`) + Checkov + Grype. |
50
77
  | SBOM | ✓ | Generated per PR by `sbom-diff.yml` and per release by `security-release.yml`. |
51
78
  | Security-Policy | ✓ | `.github/SECURITY.md` + this page + `docs/security/THREAT_MODEL.md`. |
52
- | Token-Permissions | ✓ | Workflows use least-privilege `permissions:` blocks. `harden-runner` adoption (#878) tightens this further. |
79
+ | Token-Permissions | ✓ | Top-level `permissions:` blocks restricted to `contents: read`. `write` scopes scoped to the jobs that need them (#886). |
53
80
  | Vulnerabilities | ✓ | Grype gate hard-fails on `high` / `critical` on `master` (#852). |
54
81
  | Webhooks | n/a | No external webhooks configured. |
55
- | CI-Tests | ✓ | Comprehensive CI matrix (Linux + macOS Intel + Apple Silicon, optional Windows). |
56
- | CII-Best-Practices | ☐ | Not applied yet — see "Open work" below. |
82
+ | CI-Tests | ✓ | Linux + macOS Intel + Apple Silicon matrix; optional Windows. |
83
+ | CII-Best-Practices | ☐ | Not applied yet — see `Open work` below. |
57
84
  | Dangerous-Workflow | ✓ | No `pull_request_target` with checkout-PR-code anti-pattern. |
58
85
  | Packaging | ✓ | `npm publish --provenance` via OIDC (`.github/workflows/npm-publish.yml`); `policy-bundle-release.yml` for the policy artifact. |
86
+ | Signed-Releases | ⚠ | SLSA provenance + minisig attached via `security-release.yml`; Cosign keyless signing tracked at #876. |
87
+
88
+ ## Open findings
89
+
90
+ The eight items below are surfaced as alerts at
91
+ <https://github.com/sebastienrousseau/dotfiles/security/code-scanning>.
92
+ Each row gives the dismissal **reason** and the exact **comment text**
93
+ to paste when triaging.
94
+
95
+ ### Bucket 1 — Dismiss in the UI (5 items)
96
+
97
+ Scorecard flags every `npm install`, `pip install`, `go install`, and
98
+ `curl | sh` invocation under the `Pinned-Dependencies` check. The five
99
+ below either belong to user-facing "update everything" aliases or are
100
+ false positives in Scorecard's regex.
101
+
102
+ | Path | Reason | Comment to paste |
103
+ |---|---|---|
104
+ | `.chezmoitemplates/aliases/legal/legal.aliases.sh:64` | **Won't fix** | User-facing convenience alias — `go install <fortune-style joke command>@latest`. Pinning by SHA would require users to update the alias manually on every upstream change. Intentional. |
105
+ | `.chezmoitemplates/aliases/update/update.aliases.sh:173` | **Won't fix** | User-facing convenience alias — bulk-update wrapper around `npm`. The alias's purpose is to update everything; pinning defeats it. Intentional. |
106
+ | `dot_local/bin/executable_update:99` | **Won't fix** | `dot_local/bin/executable_update` is the user-invoked "update everything" command. The literal point of `npm update -g` is to update to whatever's latest. Pinning defeats it. Intentional. |
107
+ | `scripts/dot/commands/tools.sh:121` | **False positive** | `npm install --package-lock-only --ignore-scripts --silent` generates a lockfile and does NOT fetch packages. Scorecard's regex matches `npm install` blindly; this invocation has no supply-chain surface. |
108
+ | `install/provision/run_onchange_10-linux-packages.sh.tmpl:369` | **Won't fix** | Already exact-version-pins `aider-chat==0.86.2`. Scorecard wants sha256-hash pinning, which would require a ~2,700-line lockfile covering all 108 transitive deps and re-generated on every aider release — disproportionate maintenance for a single optional provisioning install. |
109
+
110
+ ### Bucket 2 — Architectural (1 item)
111
+
112
+ | Alert | Why architectural |
113
+ |---|---|
114
+ | `CodeReviewID` (high) — score 0 | Scorecard requires every merged PR to record an approval review by a different GitHub user than the author. This repo is single-maintainer; PRs are self-merged after CI. The fix path is either (a) onboard a co-maintainer who reviews PRs before merge, or (b) accept the finding. Dismiss as **Won't fix** with comment: "Single-maintainer project — no second reviewer available. CI gates (47 required checks per PR) substitute for human review." |
115
+
116
+ ### Bucket 3 — External action (2 items)
117
+
118
+ | Alert | Action |
119
+ |---|---|
120
+ | `FuzzingID` (medium) | Dismiss as **Won't fix** with comment: "Repo is bash + Go-template + Lua. ClusterFuzzLite / OSS-Fuzz / native Go fuzz / libFuzzer / Atheris (the frameworks Scorecard recognises) all target compiled languages, none support shell. The `tests/fuzz/fuzz_install.sh` harness + property tests under `tests/unit/functions/test_property_*.sh` cover the equivalent surface." |
121
+ | `CIIBestPracticesID` (low) | Apply at <https://www.bestpractices.dev/projects/new>. ~67 self-attested questions, free, 1-2 hours. After silver-tier approval, paste the badge into `README.md` next to the existing Scorecard badge. Most criteria already met (signed commits, CI, security policy, license). |
122
+
123
+ ## Closed this cycle
124
+
125
+ | Date | Score | Alerts open | Change |
126
+ |---|---|---|---|
127
+ | 2026-05-14 | 6.5 | 28 | First clean publish after fixing the scorecard.yml `uses:`-only restriction (#885). Findings had been hidden by publish-step 400s until then. |
128
+ | 2026-05-14 | 6.5 | 11 | Closed 17 of 28: 10× TokenPermissions (#886), 6× Dockerfile bases (#886), 1× gitleaks fixture (#884). |
129
+ | 2026-05-14 | 6.5 | 9 | Closed 2× `curl \| sh` installers (#888). |
130
+ | 2026-05-14 | 6.5 | 8 | Closed 1× `npm install -g npm@…` via Node 24 bump (#889). |
131
+ | 2026-05-17 | 7.6 | 7 | v0.2.502 released; Cosign keyless signing live (#876 implementation landed in `security-release.yml` sbom job). |
132
+ | 2026-05-17 | 7.6 | 6 | SLSA Release Attestation pipeline unblocked (PR #894 — 6 prior releases had failed identically). v0.2.502 backfilled with `.intoto.jsonl` + `.sig` + `.pem` triplet. `Signed-Releases` should bump from 3 to ~10 on next Scorecard re-scrape. |
133
+ | 2026-05-17 | 7.6 | — | Added `MAINTAINERS.md` + `GOVERNANCE.md` at repo root. Provides the formal context for the `Code-Review` 0/30 score (solo maintainer) and unblocks the CII Best Practices badge application. |
59
134
 
60
135
  ## Open work
61
136
 
62
- - Apply for the [OpenSSF Best Practices badge (CII)](https://www.bestpractices.dev/) and embed it next to the Scorecard badge. (Maintainer action needs the project to register with the BestPractices.dev site.)
63
- - Once `harden-runner` is in `block` mode across all jobs (#878), the **Token-Permissions** check should hit its maximum.
64
- - Once Cosign keyless signing is wired into the release pipeline (#876), the **Signed-Releases** check should hit its maximum.
137
+ - **Apply for the OpenSSF Best Practices Badge** see Bucket 3 above. All passing-tier criteria are now met (signed commits, CI, security policy, MIT license, MAINTAINERS.md, GOVERNANCE.md, RFC process documented).
138
+ - **Re-trigger Scorecard after SLSA backfill propagates** expected `Signed-Releases` 3 10.
139
+ - **`harden-runner` block-mode adoption (#878)** should tighten the `Token-Permissions` check further.
140
+ - **Investigate `License` 9/10 false-positive** — repo is MIT (SPDX-compliant), Scorecard's penalty should not apply.
141
+ - **Investigate `Branch-Protection` `-1`** — scanner internal error; manually verify with `gh api repos/:owner/:repo/branches/master/protection` and document.
142
+
143
+ ### Enabling Branch-Protection + Webhooks checks (one-time PAT setup)
144
+
145
+ Scorecard's `Branch-Protection` and `Webhooks` checks require a
146
+ fine-grained Personal Access Token with `Administration: read`
147
+ scope. Without it both checks return `-1` ("internal error"). The
148
+ workflow already wires this up — only the secret needs to be created.
149
+
150
+ Steps (one-time, repo owner):
151
+
152
+ 1. Go to <https://github.com/settings/personal-access-tokens/new>
153
+ 2. **Resource owner**: `sebastienrousseau` · **Repository access**: only `sebastienrousseau/dotfiles`
154
+ 3. **Repository permissions** → `Administration: read-only` and `Metadata: read-only`
155
+ 4. **Expiration**: 1 year (set a calendar reminder to rotate; document the rotation in this file when done)
156
+ 5. Generate the token, copy it once
157
+ 6. Add as a secret named `SCORECARD_TOKEN` at <https://github.com/sebastienrousseau/dotfiles/settings/secrets/actions/new>
158
+ 7. Next Scorecard run (manual via `gh workflow run scorecard.yml` or weekly cron) picks it up automatically
159
+ 8. Expected effect: `Branch-Protection` `-1` → 10/10 if all rules are correctly configured; `Webhooks` `-1` → 10/10 (no webhooks present).
160
+
161
+ The PAT secret is **optional**. When absent, the workflow falls back
162
+ to `${{ github.token }}` and Scorecard continues to run, only with
163
+ those two checks at `-1`. Adding the PAT cannot reduce any other check's
164
+ score — it's a strict improvement.
65
165
 
66
166
  ## Exceptions
67
167
 
@@ -72,9 +172,24 @@ marks reflect this repo's posture at the time of writing — the
72
172
  If you add an exception, include the check name, an expiry date
73
173
  (don't allow indefinite), and the rationale. Re-evaluate every quarter.
74
174
 
175
+ ## Refreshing this document
176
+
177
+ ```bash
178
+ # Re-count open alerts:
179
+ gh api 'repos/sebastienrousseau/dotfiles/code-scanning/alerts?state=open&per_page=50' \
180
+ --jq '[.[].rule.id] | group_by(.) | map({rule: .[0], count: length})'
181
+
182
+ # Trigger Scorecard manually:
183
+ gh workflow run scorecard.yml --ref master
184
+ ```
185
+
186
+ If a new category appears, add a row to the matching bucket. If a
187
+ remediation closes one of the rows above, delete the row.
188
+
75
189
  ## References
76
190
 
77
- - `.github/workflows/scorecard.yml` — the scanner.
191
+ - `.github/workflows/scorecard.yml` — the scanner workflow (split into
192
+ `analysis` + `track-regression` jobs per #885).
78
193
  - [Scorecard project](https://github.com/ossf/scorecard).
79
194
  - [Scorecard checks reference](https://github.com/ossf/scorecard/blob/main/docs/checks.md).
80
- - Issue [#869](https://github.com/sebastienrousseau/dotfiles/issues/869).
195
+ - Tracking issue [#869](https://github.com/sebastienrousseau/dotfiles/issues/869).
@@ -7,7 +7,7 @@ render_with_liquid: false
7
7
  Every bash script in this repo must include `set -euo pipefail` (or
8
8
  `set -eu` for POSIX `sh`) within its first 50 lines. The rule is
9
9
  enforced by
10
- [`scripts/ci/check-shell-preamble.sh`](../../scripts/ci/check-shell-preamble.sh),
10
+ [`tools/ci/check-shell-preamble.sh`](../../tools/ci/check-shell-preamble.sh),
11
11
  wired into `pre-commit` and the `reusable-shell-lint.yml` CI job.
12
12
  Tests pin the contract under
13
13
  [`tests/unit/security/test_shell_preamble_lint.sh`](../../tests/unit/security/test_shell_preamble_lint.sh).
@@ -115,14 +115,14 @@ When you need to mark a new file:
115
115
  3. **Run the checker:**
116
116
 
117
117
  ```bash
118
- ./scripts/ci/check-shell-preamble.sh path/to/file.sh
118
+ ./tools/ci/check-shell-preamble.sh path/to/file.sh
119
119
  ```
120
120
 
121
121
  Exit 0 = lint passes.
122
122
 
123
123
  4. **If you're adding a new entire directory of fragments**
124
124
  (rare — alias buckets, plugin trees), edit the path-skip rule
125
- in `scripts/ci/check-shell-preamble.sh` and document it in this
125
+ in `tools/ci/check-shell-preamble.sh` and document it in this
126
126
  page's "Bulk-sourced fragments" table above.
127
127
 
128
128
  ## CI integration
@@ -138,7 +138,7 @@ this page in the same PR.
138
138
 
139
139
  ## References
140
140
 
141
- - `scripts/ci/check-shell-preamble.sh` — the lint.
141
+ - `tools/ci/check-shell-preamble.sh` — the lint.
142
142
  - `tests/unit/security/test_shell_preamble_lint.sh` — contract test.
143
143
  - `config/pre-commit-config.yaml` (`shell-preamble-check` hook).
144
144
  - `.github/workflows/reusable-shell-lint.yml` — CI invocation.
@@ -0,0 +1,201 @@
1
+ ---
2
+ title: "Verify a Release"
3
+ date: 2026-05-17
4
+ ---
5
+
6
+ # Verifying a Release
7
+
8
+ Every release of the framework ships four independent attestations.
9
+ Verify any of them, they're orthogonal and each rules out a
10
+ different class of attack.
11
+
12
+ | Artefact | Format | Tool | Threat covered |
13
+ |----------|--------|------|----------------|
14
+ | **SBOM** (`dotfiles-sbom.spdx.json`) | SPDX 2.3 JSON | any SBOM viewer | "what's in the release?", full component inventory |
15
+ | **Cosign signature** (`.sig` + `.pem`) | sigstore keyless | `cosign verify-blob` | "did our CI actually produce this SBOM?", short-lived Fulcio cert + Rekor transparency-log entry |
16
+ | **SLSA provenance** (`.intoto.jsonl`) | in-toto v1 / SLSA L3 | `slsa-verifier` | "what build process produced this?", workflow ID, source ref, builder identity |
17
+ | **Unified manifest** (`ALL_SHA256SUMS` + `.sig` + `.pem`) | text + sigstore keyless | `cosign verify-blob` then `sha256sum -c` | "is every other asset on this release the one our CI produced?", one signed line per asset |
18
+
19
+ All four are attached to every GitHub Release as assets, from v0.2.503 forward.
20
+ Releases v0.2.500 through v0.2.502 carry the SBOM bundle only: the unified
21
+ manifest landed in v0.2.503 and is forward-only (re-tagging earlier releases
22
+ would break consumer pins on existing SHAs).
23
+
24
+ ---
25
+
26
+ ## TL;DR — verify v0.2.503+ end-to-end
27
+
28
+ ```sh
29
+ # 0. Pick the release to verify
30
+ TAG=v0.2.503
31
+ REPO=sebastienrousseau/dotfiles
32
+
33
+ # 1. Download every attestation artefact
34
+ gh release download "$TAG" --repo "$REPO" \
35
+ --pattern dotfiles-sbom.spdx.json \
36
+ --pattern dotfiles-sbom.spdx.json.sig \
37
+ --pattern dotfiles-sbom.spdx.json.pem \
38
+ --pattern dotfiles-sbom.spdx.json.intoto.jsonl \
39
+ --pattern ALL_SHA256SUMS \
40
+ --pattern ALL_SHA256SUMS.sig \
41
+ --pattern ALL_SHA256SUMS.pem
42
+
43
+ # 2. Verify Cosign signature on the SBOM (binds SBOM to CI workflow identity)
44
+ cosign verify-blob \
45
+ --certificate dotfiles-sbom.spdx.json.pem \
46
+ --signature dotfiles-sbom.spdx.json.sig \
47
+ --certificate-identity-regexp "^https://github.com/$REPO/" \
48
+ --certificate-oidc-issuer https://token.actions.githubusercontent.com \
49
+ dotfiles-sbom.spdx.json
50
+
51
+ # 3. Verify SLSA provenance (binds SBOM to exact source tag + builder)
52
+ slsa-verifier verify-artifact dotfiles-sbom.spdx.json \
53
+ --provenance-path dotfiles-sbom.spdx.json.intoto.jsonl \
54
+ --source-uri "github.com/$REPO" \
55
+ --source-tag "$TAG"
56
+
57
+ # 4. Verify the unified manifest, then verify every other asset against it.
58
+ # One signed file covers all release artefacts in one shot.
59
+ cosign verify-blob \
60
+ --certificate ALL_SHA256SUMS.pem \
61
+ --signature ALL_SHA256SUMS.sig \
62
+ --certificate-identity-regexp "^https://github.com/$REPO/" \
63
+ --certificate-oidc-issuer https://token.actions.githubusercontent.com \
64
+ ALL_SHA256SUMS
65
+
66
+ gh release download "$TAG" --repo "$REPO" --dir . # pull every other asset
67
+ sha256sum -c ALL_SHA256SUMS # one line per asset
68
+ ```
69
+
70
+ All four commands should print "Verified" / "PASSED" / "OK" and
71
+ exit 0. If any fails, **the release was tampered with**: open
72
+ an issue at <https://github.com/sebastienrousseau/dotfiles/issues>
73
+ and do **not** install.
74
+
75
+ ---
76
+
77
+ ## Tool installation
78
+
79
+ | Tool | macOS | Linux | Windows |
80
+ |------|-------|-------|---------|
81
+ | `gh` (GitHub CLI) | `brew install gh` | `apt install gh` / [release page](https://github.com/cli/cli/releases) | `scoop install gh` |
82
+ | `cosign` | `brew install cosign` | `curl -sSfL https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 -o /usr/local/bin/cosign && chmod +x /usr/local/bin/cosign` | `scoop install cosign` |
83
+ | `slsa-verifier` | `brew install slsa-verifier` | `go install github.com/slsa-framework/slsa-verifier/v2/cli/slsa-verifier@latest` | `scoop install slsa-verifier` |
84
+
85
+ If you don't have Go installed, fetch the pre-built `slsa-verifier`
86
+ binary from <https://github.com/slsa-framework/slsa-verifier/releases>
87
+ (SHA256-verify per their release notes).
88
+
89
+ ---
90
+
91
+ ## What each verification actually proves
92
+
93
+ ### `cosign verify-blob` succeeds
94
+
95
+ - The SBOM was signed by a workflow run **on this repository** (the
96
+ `--certificate-identity-regexp` enforces it).
97
+ - The signing OIDC token was issued by **GitHub Actions** (the
98
+ `--certificate-oidc-issuer` enforces it).
99
+ - The signature is recorded in the **Rekor public transparency log**
100
+ (cosign queries this automatically) — anyone can audit it.
101
+ - The Cosign cert was issued by **Fulcio** (the sigstore CA) and
102
+ was valid at the time of signing.
103
+
104
+ This **does not** prove what the build process did — only that
105
+ "the file you have is the file CI produced." For "what did CI do",
106
+ see SLSA verification below.
107
+
108
+ ### `slsa-verifier verify-artifact` succeeds
109
+
110
+ - The SBOM digest matches a provenance statement.
111
+ - The provenance was generated by the **SLSA-Generator** running on
112
+ **GitHub-hosted runners** for **this exact repository**.
113
+ - The build was triggered by the named tag (`--source-tag $TAG`).
114
+ - The provenance is anchored in Rekor (immutable, third-party-auditable).
115
+
116
+ SLSA Level 3 is achieved because: (a) the provenance is generated
117
+ by a *trusted, isolated* builder (slsa-github-generator), not by
118
+ us; (b) the builder runs with hermetic, non-falsifiable inputs;
119
+ (c) the provenance is signed by the builder's own identity, not
120
+ ours.
121
+
122
+ ### What none of this proves
123
+
124
+ The framework's source code is **not formally verified**. SBOM +
125
+ SLSA + Cosign protect the *supply chain* (you got what we shipped)
126
+ — not the *correctness* (what we shipped does what we claim).
127
+
128
+ For correctness review:
129
+
130
+ - Code is open under MIT — read it. Start at `bin/dot`.
131
+ - CI runs ~75 checks per PR (shellcheck, shfmt, CodeQL, Semgrep, Codacy, etc.).
132
+ - Pre-commit hooks reject typos, unsigned commits, raw secrets.
133
+ - See `docs/security/SCORECARD.md` for the OpenSSF score posture.
134
+
135
+ ---
136
+
137
+ ## In-shell one-liner for ongoing verification
138
+
139
+ If you intend to install or update from a release tag, add this to
140
+ your shell startup (already in `dot_config/shell/*` for users who
141
+ run `chezmoi apply`):
142
+
143
+ ```sh
144
+ verify-dot-release() {
145
+ local tag="${1:-$(gh release view --json tagName --jq .tagName \
146
+ --repo sebastienrousseau/dotfiles)}"
147
+ local tmp
148
+ tmp="$(mktemp -d)"
149
+ ( cd "$tmp" \
150
+ && gh release download "$tag" --repo sebastienrousseau/dotfiles \
151
+ --pattern 'dotfiles-sbom.*' \
152
+ && cosign verify-blob \
153
+ --certificate dotfiles-sbom.spdx.json.pem \
154
+ --signature dotfiles-sbom.spdx.json.sig \
155
+ --certificate-identity-regexp '^https://github.com/sebastienrousseau/dotfiles/' \
156
+ --certificate-oidc-issuer https://token.actions.githubusercontent.com \
157
+ dotfiles-sbom.spdx.json \
158
+ && slsa-verifier verify-artifact dotfiles-sbom.spdx.json \
159
+ --provenance-path dotfiles-sbom.spdx.json.intoto.jsonl \
160
+ --source-uri github.com/sebastienrousseau/dotfiles \
161
+ --source-tag "$tag"
162
+ )
163
+ local rc=$?
164
+ rm -rf "$tmp"
165
+ return $rc
166
+ }
167
+ ```
168
+
169
+ Usage:
170
+
171
+ ```sh
172
+ verify-dot-release # verify latest
173
+ verify-dot-release v0.2.502 # verify specific tag
174
+ ```
175
+
176
+ ---
177
+
178
+ ## If verification fails
179
+
180
+ 1. **Don't install.** Stop the bootstrap script. `^C` any in-flight
181
+ `chezmoi apply`.
182
+ 2. **Compare assets**. The release page shows file sizes — if
183
+ yours don't match what's on
184
+ <https://github.com/sebastienrousseau/dotfiles/releases>, you
185
+ downloaded from a man-in-the-middle.
186
+ 3. **Report**: open an issue and email
187
+ `security@sebastienrousseau.com` (encrypted to the WKD-published
188
+ GPG key — fingerprint
189
+ `55AFAD364FD9DB3819E61F0C8D688FAFA9144693`). Acknowledgement
190
+ SLA: 72 hours per `.github/SECURITY.md`.
191
+
192
+ ---
193
+
194
+ ## See also
195
+
196
+ - `.github/SECURITY.md` — coordinated disclosure policy.
197
+ - `docs/security/KEY_ROTATION.md` — disclosure-key rotation procedure.
198
+ - `docs/security/SCORECARD.md` — OpenSSF Scorecard posture.
199
+ - `docs/operations/HARD_AUDIT_2026.md` Part 7 — the GPG key generation + WKD publication record.
200
+ - [Sigstore Cosign docs](https://docs.sigstore.dev/cosign/signing/overview/)
201
+ - [SLSA verifier docs](https://github.com/slsa-framework/slsa-verifier)
@@ -0,0 +1,15 @@
1
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
2
+
3
+ mDMEagg20hYJKwYBBAHaRw8BAQdAk2HMi5IFTHBGhCtSFzqwsyuVb7mO0iIhoUXR
4
+ mTv/PNK0R1NlYmFzdGllbiBSb3Vzc2VhdSAoRG90ZmlsZXMgU2VjdXJpdHkpIDxz
5
+ ZWN1cml0eUBzZWJhc3RpZW5yb3Vzc2VhdS5jb20+iLUEExYKAF0WIQRVr602T9nb
6
+ OBnmHwyNaI+vqRRGkwUCagg20hsUgAAAAAAEAA5tYW51MiwyLjUrMS4xMiwwLDMC
7
+ GwMFCQWjmoAFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQjWiPr6kURpOH
8
+ qQEA4gl4pfhkR9Y3IM6oMHydavrx3CE6mX4YRIkYJ7fYj4UA/iO/54bdjG+wmIrE
9
+ cQ077+ijTTCMnHrosn3E13oQ6NIJuDgEagg20hIKKwYBBAGXVQEFAQEHQKdKJLxe
10
+ xsXBXELbxGHUz2asoTuOnsKk8WEdOyESH3dnAwEIB4iUBBgWCgA8FiEEVa+tNk/Z
11
+ 2zgZ5h8MjWiPr6kURpMFAmoINtIbFIAAAAAABAAObWFudTIsMi41KzEuMTIsMCwz
12
+ AhsMAAoJEI1oj6+pFEaTUw0A/14oNMWsx1gcyx9wl/vy+OgEXoOksxSV+FetAI2Q
13
+ Q7qOAP9pohjVAi40dqfBXv3vet7CV0V4p2kQ+qpQTOPTVafkDA==
14
+ =UtsL
15
+ -----END PGP PUBLIC KEY BLOCK-----
package/install.sh CHANGED
@@ -6,6 +6,13 @@
6
6
 
7
7
  set -euo pipefail
8
8
 
9
+ # Restrict the permissions of any file/dir we create during bootstrap.
10
+ # The installer writes secret-adjacent artifacts (chezmoi config, age
11
+ # keys, ssh tooling, downloaded archives) under $HOME — 077 prevents
12
+ # other local accounts from reading them. Individual call sites can
13
+ # still relax with `chmod` when a file is meant to be world-readable.
14
+ umask 077
15
+
9
16
  # ANSI Colors
10
17
  RED='\033[0;31m'
11
18
  GREEN='\033[0;32m'
@@ -52,7 +59,7 @@ show_help() {
52
59
  Usage: install.sh [version] [options]
53
60
 
54
61
  Arguments:
55
- version The version (tag or branch) to install (default: v0.2.501)
62
+ version The version (tag or branch) to install (default: v0.2.503)
56
63
 
57
64
  Options:
58
65
  --help Show this help message
@@ -64,7 +71,7 @@ EOF
64
71
  }
65
72
 
66
73
  main() {
67
- local version="v0.2.501"
74
+ local version="v0.2.503"
68
75
  local version_set=0
69
76
  local minimal=0
70
77
  local _cleanup_files=()
@@ -92,7 +99,7 @@ main() {
92
99
  # like `foobar` doesn't trigger a 30s+ network download attempt.
93
100
  # Caught by the install.sh fuzz harness (#881).
94
101
  if [[ ! "$arg" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+([-+][a-zA-Z0-9.-]+)?$ ]]; then
95
- error "Unrecognized positional argument '$arg' — expected a semver version (e.g. v0.2.501)."
102
+ error "Unrecognized positional argument '$arg' — expected a semver version (e.g. v0.2.503)."
96
103
  fi
97
104
  version="$arg"
98
105
  version_set=1
@@ -135,10 +142,29 @@ main() {
135
142
  sudo mkdir -p /etc/apt/keyrings
136
143
  curl -fsSL https://repo.charm.sh/apt/gpg.key |
137
144
  sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/charm.gpg
138
- # Verify Charm GPG key fingerprint
139
- if ! gpg --no-default-keyring --keyring /etc/apt/keyrings/charm.gpg \
140
- --list-keys --with-colons 2>/dev/null | grep -q "fid:"; then
141
- echo "Warning: Could not verify Charm GPG key" >&2
145
+ # Pin the Charm GPG key fingerprint — a DNS attacker swapping
146
+ # repo.charm.sh/apt/gpg.key for a forged key with the same uid
147
+ # would otherwise pass the prior "any fid: present" check.
148
+ # Pinned value taken from https://repo.charm.sh/apt/gpg.key on
149
+ # 2026-05-16. If Charm rotates, update this and call it out in
150
+ # CHANGELOG.md.
151
+ CHARM_GPG_EXPECTED_FPR="C026D31B92F9BBE91D5DB75AB07AE17C9E0A6585"
152
+ charm_actual_fpr="$(gpg --no-default-keyring \
153
+ --keyring /etc/apt/keyrings/charm.gpg \
154
+ --with-colons --fingerprint 2>/dev/null |
155
+ awk -F: '/^fpr:/{print $10; exit}')"
156
+ if [[ -z "$charm_actual_fpr" ]]; then
157
+ echo "Error: Could not extract Charm GPG fingerprint — aborting" >&2
158
+ sudo rm -f /etc/apt/keyrings/charm.gpg
159
+ return 1
160
+ fi
161
+ if [[ "$charm_actual_fpr" != "$CHARM_GPG_EXPECTED_FPR" ]]; then
162
+ echo "Error: Charm GPG fingerprint mismatch" >&2
163
+ echo " expected: $CHARM_GPG_EXPECTED_FPR" >&2
164
+ echo " got: $charm_actual_fpr" >&2
165
+ echo " aborting (possible DNS / keyserver hijack)" >&2
166
+ sudo rm -f /etc/apt/keyrings/charm.gpg
167
+ return 1
142
168
  fi
143
169
  echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list
144
170
  sudo apt-get update && sudo apt-get install gum -y >/dev/null 2>&1
@@ -160,43 +186,31 @@ main() {
160
186
  mkdir -p "$bin_dir"
161
187
  echo " Installing chezmoi via binary download..."
162
188
 
163
- # Prefer verified installer with SHA256 checksum when available
189
+ # Prefer verified installer with SHA256 checksum when available.
190
+ # When verification fails or the verified installer isn't present
191
+ # we refuse to bootstrap rather than silently downloading and
192
+ # executing an unverified script (the previous fall-back to
193
+ # `get.chezmoi.io` was an unsigned bootstrap and a security hole).
164
194
  local verified_installer
165
- verified_installer="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/scripts/ci/install-chezmoi-verified.sh"
195
+ verified_installer="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/tools/ci/install-chezmoi-verified.sh"
166
196
  if [[ -x "$verified_installer" ]] || [[ -f "$verified_installer" ]]; then
167
197
  echo " Using checksum-verified installer..."
168
198
  if ! bash "$verified_installer" "${CHEZMOI_VERSION:-2.47.1}" "$bin_dir"; then
169
- echo " Verified installer failed, falling back to get.chezmoi.io" >&2
170
- else
171
- return 0
199
+ echo "" >&2
200
+ echo " The verified chezmoi installer failed." >&2
201
+ echo " Refusing to fall back to an unverified bootstrap path." >&2
202
+ echo " Install chezmoi manually from a trusted source, then re-run install.sh:" >&2
203
+ echo " macOS: brew install chezmoi" >&2
204
+ echo " Linux: see https://www.chezmoi.io/install/" >&2
205
+ return 1
172
206
  fi
207
+ return 0
173
208
  fi
174
-
175
- # Fallback: download installer with size/shebang validation
176
- local installer
177
- installer=$(umask 077 && mktemp)
178
- if ! curl -fsSL -o "$installer" https://get.chezmoi.io; then
179
- rm -f "$installer"
180
- echo " Failed to download chezmoi installer" >&2
181
- return 1
182
- fi
183
- # Validate: must be a shell script and not suspiciously large
184
- if [[ "$(wc -c <"$installer")" -gt 102400 ]]; then
185
- rm -f "$installer"
186
- echo " Chezmoi installer suspiciously large. Aborting." >&2
187
- return 1
188
- fi
189
- if ! head -1 "$installer" | grep -q '^#!/'; then
190
- rm -f "$installer"
191
- echo " Chezmoi installer doesn't look like a shell script. Aborting." >&2
192
- return 1
193
- fi
194
- if ! BINDIR="$bin_dir" sh "$installer"; then
195
- rm -f "$installer"
196
- echo " chezmoi binary installer failed" >&2
197
- return 1
198
- fi
199
- rm -f "$installer"
209
+ echo "" >&2
210
+ echo " tools/ci/install-chezmoi-verified.sh is missing; cannot verify chezmoi bootstrap." >&2
211
+ echo " Install chezmoi manually (brew install chezmoi / official binary)" >&2
212
+ echo " and re-run install.sh." >&2
213
+ return 1
200
214
  fi
201
215
  }
202
216
 
@@ -290,6 +304,21 @@ main() {
290
304
  # 6. Initialize & Apply
291
305
  step "Applying Configuration..."
292
306
 
307
+ # ── Auto-migration for v0.2.503 reorg ─────────────────────────────────
308
+ # If the user is upgrading from a pre-0.2.503 install, run the
309
+ # migration script BEFORE `chezmoi apply` so the reorg's source-
310
+ # path moves don't cause chezmoi to delete deployed files.
311
+ # The script is idempotent + silent-by-default; safe to run on
312
+ # every install (fresh installs detect "no prior state" and exit 0).
313
+ for migrate_src in "$SOURCE_DIR" "$LEGACY_SOURCE_DIR"; do
314
+ migrate_script="$migrate_src/install/migrate/migrate-v0_2-to-v0_2_503.sh"
315
+ if [[ -x "$migrate_script" ]]; then
316
+ echo " Running v0.2.503 migration (idempotent; safe on fresh installs)..."
317
+ "$migrate_script" || echo " migration exited non-zero — continuing apply"
318
+ break
319
+ fi
320
+ done
321
+
293
322
  # If we are running from a local source, just apply
294
323
  if [[ -d "$SOURCE_DIR/.git" ]]; then
295
324
  echo " Applying from local source: $SOURCE_DIR"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sebastienrousseau/dotfiles",
3
- "version": "0.2.501",
3
+ "version": "0.2.503",
4
4
  "description": "The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.",
5
5
  "main": "install.sh",
6
6
  "bin": {