@sebastienrousseau/dotfiles 0.2.519 → 0.2.520

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 (163) hide show
  1. package/CHANGELOG.md +182 -0
  2. package/README.md +1163 -163
  3. package/docs/ARCHITECTURE.md +117 -0
  4. package/docs/COPYRIGHT +1 -1
  5. package/docs/ECOSYSTEM.md +220 -0
  6. package/docs/GOLD-STANDARD-AUDIT.md +352 -0
  7. package/docs/GOVERNANCE.md +1 -1
  8. package/docs/MAINTAINERS.md +1 -1
  9. package/docs/MINIMUM-TOOLCHAIN.md +100 -0
  10. package/docs/README.md +1 -1
  11. package/docs/STRUCTURE.md +1 -1
  12. package/docs/architecture/ARCHITECTURE.md +11 -108
  13. package/docs/architecture/REPO_LAYOUT.md +3 -3
  14. package/docs/guides/MACOS_ICLOUD_SYMLINKS.md +121 -0
  15. package/docs/index.md +3 -3
  16. package/docs/manual/00-introduction.md +1 -1
  17. package/docs/manual/03-reference/01-dot-cli.md +28 -3
  18. package/docs/manual/command-index.md +24 -4
  19. package/docs/manual/concept-index.md +2 -0
  20. package/docs/migration/README.md +81 -0
  21. package/docs/migration/from-bare-git-repo.md +156 -0
  22. package/docs/migration/from-gnu-stow.md +165 -0
  23. package/docs/migration/from-plain-chezmoi.md +148 -0
  24. package/docs/migration/from-yadm.md +187 -0
  25. package/docs/operations/PERFORMANCE_BUDGETS.md +196 -0
  26. package/docs/operations/REGISTRY.md +1 -1
  27. package/docs/operations/RELEASE_PIPELINE.md +4 -4
  28. package/docs/operations/TESTING.md +3 -3
  29. package/docs/operations/TRACEABILITY.md +1 -0
  30. package/docs/packaging.md +222 -0
  31. package/docs/reference/FEATURE-MATRIX.md +646 -0
  32. package/docs/reference/TOOLS.md +1 -1
  33. package/docs/reference/UTILS.md +1 -0
  34. package/docs/security/COMPLIANCE.md +1 -1
  35. package/docs/security/DISCLOSURE.md +4 -4
  36. package/docs/security/FUZZING.md +113 -18
  37. package/docs/security/KEY_ROTATION.md +1 -1
  38. package/docs/security/SCORECARD.md +3 -3
  39. package/docs/security/VERIFY_RELEASE.md +2 -2
  40. package/install.sh +6 -6
  41. package/package.json +2 -2
  42. package/scripts/ci/check-copyright-headers.sh +1 -1
  43. package/scripts/ci/check-shell-preamble.sh +1 -1
  44. package/scripts/ci/guard-gitleaks-checkout.sh +1 -1
  45. package/scripts/demo/record.sh +1 -1
  46. package/scripts/diagnostics/a2a-conformance.sh +1 -1
  47. package/scripts/diagnostics/alias-governance.sh +30 -3
  48. package/scripts/diagnostics/aliases-cheatsheet.sh +1 -1
  49. package/scripts/diagnostics/aliases-manifest.sh +1 -1
  50. package/scripts/diagnostics/attest-verify.sh +147 -0
  51. package/scripts/diagnostics/benchmark.sh +1 -1
  52. package/scripts/diagnostics/conflicts.sh +1 -1
  53. package/scripts/diagnostics/doctor-unified.sh +6 -2
  54. package/scripts/diagnostics/doctor.sh +56 -10
  55. package/scripts/diagnostics/drift-dashboard.sh +3 -2
  56. package/scripts/diagnostics/health.sh +43 -10
  57. package/scripts/diagnostics/history-analysis.sh +1 -1
  58. package/scripts/diagnostics/mcp-doctor.sh +2 -2
  59. package/scripts/diagnostics/perf.sh +1 -1
  60. package/scripts/diagnostics/scorecard.sh +3 -2
  61. package/scripts/diagnostics/secret-governance.sh +1 -1
  62. package/scripts/diagnostics/security-score.sh +1 -1
  63. package/scripts/diagnostics/smoke-test.sh +1 -1
  64. package/scripts/diagnostics/snapshot.sh +1 -1
  65. package/scripts/diagnostics/verify.sh +1 -1
  66. package/scripts/diagnostics/verify_state.sh +1 -1
  67. package/scripts/diagnostics/version-locks.sh +1 -1
  68. package/scripts/diagnostics/workstation-attestation.sh +26 -1
  69. package/scripts/dot/commands/agent.sh +64 -14
  70. package/scripts/dot/commands/agents.sh +24 -8
  71. package/scripts/dot/commands/ai.sh +20 -7
  72. package/scripts/dot/commands/aliases.sh +1 -1
  73. package/scripts/dot/commands/appearance.sh +1 -1
  74. package/scripts/dot/commands/completion.sh +42 -5
  75. package/scripts/dot/commands/core.sh +1 -1
  76. package/scripts/dot/commands/diagnostics.sh +1 -1
  77. package/scripts/dot/commands/env-emit.sh +1 -1
  78. package/scripts/dot/commands/fleet.sh +41 -18
  79. package/scripts/dot/commands/init.sh +1 -1
  80. package/scripts/dot/commands/lint.sh +1 -1
  81. package/scripts/dot/commands/manual.sh +1 -1
  82. package/scripts/dot/commands/meta.sh +115 -10
  83. package/scripts/dot/commands/patterns.sh +1 -1
  84. package/scripts/dot/commands/registry.sh +43 -7
  85. package/scripts/dot/commands/restore.sh +1 -1
  86. package/scripts/dot/commands/secrets.sh +1 -1
  87. package/scripts/dot/commands/security.sh +1 -1
  88. package/scripts/dot/commands/tools.sh +21 -7
  89. package/scripts/fonts/install-nerd-fonts.sh +1 -1
  90. package/scripts/fonts/patch-fonts.sh +1 -1
  91. package/scripts/git-hooks/install.sh +1 -1
  92. package/scripts/git-hooks/pre-commit-audit.sh +2 -2
  93. package/scripts/lib/secrets_provider.sh +19 -4
  94. package/scripts/nvim/headless-upgrade.lua +81 -0
  95. package/scripts/ops/ai-setup.sh +1 -1
  96. package/scripts/ops/bundle.sh +1 -1
  97. package/scripts/ops/chaos.sh +1 -1
  98. package/scripts/ops/chezmoi-apply.sh +1 -1
  99. package/scripts/ops/chezmoi-diff.sh +1 -1
  100. package/scripts/ops/chezmoi-remove.sh +3 -3
  101. package/scripts/ops/chezmoi-update.sh +6 -2
  102. package/scripts/ops/heal-chezmoi.sh +1 -1
  103. package/scripts/ops/heal-system.sh +1 -1
  104. package/scripts/ops/heal-tools.sh +1 -1
  105. package/scripts/ops/heal.sh +1 -1
  106. package/scripts/ops/post-apply-repair.sh +1 -1
  107. package/scripts/ops/prewarm.sh +1 -1
  108. package/scripts/ops/release.sh +1 -1
  109. package/scripts/ops/rollback.sh +11 -2
  110. package/scripts/ops/setup.sh +1 -1
  111. package/scripts/ops/teleport.sh +1 -1
  112. package/scripts/qa/check-feature-matrix.sh +296 -0
  113. package/scripts/qa/check-version-consistency.sh +7 -119
  114. package/scripts/qa/coverage-baseline.sh +1 -1
  115. package/scripts/qa/docs-coverage.sh +9 -3
  116. package/scripts/qa/examples-coverage.sh +1 -1
  117. package/scripts/qa/reliability-audit.sh +1 -1
  118. package/scripts/qa/scorecard-snapshot.sh +1 -1
  119. package/scripts/qa/traceability-coverage.sh +9 -2
  120. package/scripts/qa/validate-examples.sh +66 -3
  121. package/scripts/qa/wsl-contract.sh +1 -1
  122. package/scripts/secrets/age-init.sh +1 -1
  123. package/scripts/secrets/create-secrets-file.sh +1 -1
  124. package/scripts/secrets/encrypt-ssh-key.sh +1 -1
  125. package/scripts/security/backup.sh +1 -1
  126. package/scripts/security/check-disclosure-key-expiry.sh +1 -1
  127. package/scripts/security/dns-doh.sh +1 -1
  128. package/scripts/security/encryption-check.sh +1 -1
  129. package/scripts/security/enforce-policies.sh +315 -98
  130. package/scripts/security/firewall.sh +1 -1
  131. package/scripts/security/lock-configs.sh +1 -1
  132. package/scripts/security/lock-screen.sh +1 -1
  133. package/scripts/security/manage-secrets.sh +1 -1
  134. package/scripts/security/ssh-cert.sh +1 -1
  135. package/scripts/security/telemetry-kill.sh +1 -1
  136. package/scripts/security/usb-safety.sh +1 -1
  137. package/scripts/theme/apply-gnome-theme.sh +1 -1
  138. package/scripts/theme/extract-heic-frames.sh +1 -1
  139. package/scripts/theme/extract-theme.py +284 -6
  140. package/scripts/theme/install-boot-logo.sh +1 -1
  141. package/scripts/theme/install-catppuccin-themes.sh +1 -1
  142. package/scripts/theme/install-cursors.sh +1 -1
  143. package/scripts/theme/install-file-icons.sh +1 -1
  144. package/scripts/theme/install-grub-theme.sh +1 -1
  145. package/scripts/theme/install-lock-icon.sh +1 -1
  146. package/scripts/theme/merge-wallpaper.sh +1 -1
  147. package/scripts/theme/rebuild-themes.sh +64 -5
  148. package/scripts/theme/switch.sh +46 -19
  149. package/scripts/theme/wallpaper-rotate.sh +1 -1
  150. package/scripts/theme/wallpaper-sync.sh +1 -1
  151. package/scripts/tools/cmatrix.sh +1 -1
  152. package/scripts/tools/detect-collisions.py +1 -1
  153. package/scripts/tools/emoji-picker.sh +1 -1
  154. package/scripts/tools/figlet-banner.sh +1 -1
  155. package/scripts/tools/log-rotate.sh +1 -1
  156. package/scripts/tools/lolcat-wrap.sh +1 -1
  157. package/scripts/tools/pipes.sh +1 -1
  158. package/scripts/tuning/linux.sh +1 -1
  159. package/scripts/tuning/macos.sh +1 -1
  160. package/scripts/uninstall.sh +1 -1
  161. package/scripts/verify-release-versions +156 -0
  162. package/scripts/version-sync.sh +63 -3
  163. package/LICENSE +0 -21
@@ -27,7 +27,7 @@ dot registry url # show active registry URL
27
27
  dot registry set-url <url> # point at a different registry
28
28
  ```
29
29
 
30
- The registry index is cached locally at `${XDG_CACHE_HOME:-~/.cache}/dotfiles/registry/index.json` with a 6 hour TTL. Override the URL one-off via `DOTFILES_REGISTRY_URL=<url> dot registry list`.
30
+ The registry index is cached locally under `${XDG_CACHE_HOME:-~/.cache}/dotfiles/registry/` with a 6 hour TTL, in a file named for the URL it was fetched from (`index-<digest>.json`) so changing the registry URL never serves the previous registry's index. Override the URL one-off via `DOTFILES_REGISTRY_URL=<url> dot registry list`.
31
31
 
32
32
  ## JSON contract
33
33
 
@@ -52,9 +52,9 @@ dependencies allow.
52
52
  | `security-release.yml` (sbom job) | `release.published`, dispatch | Generate SPDX SBOM via anchore/sbom-action. Cosign keyless sign the SBOM. | `dotfiles-sbom.spdx.json` + `.sig` + `.pem`. |
53
53
  | `security-release.yml` (provenance job) | needs sbom | SLSA L3 provenance via slsa-framework/slsa-github-generator. | `dotfiles-sbom.spdx.json.intoto.jsonl`. |
54
54
  | `security-release.yml` (manifest job) | needs provenance + complete asset set | Build `ALL_SHA256SUMS` over every release asset, Cosign-sign it, and verify its signature and digests. | `ALL_SHA256SUMS` + `.sig` + `.pem`. |
55
- | `release-distribute-homebrew.yml` | `release.published`, dispatch | Hash `dot-VERSION.tar.gz`, regenerate `install/homebrew/dot.rb`, push branch + PR to `sebastienrousseau/homebrew-tap`. | One PR on the tap repo. |
56
- | `release-distribute-scoop.yml` | `release.published`, dispatch | Hash `dot-VERSION.zip`, rewrite `install/scoop/dot.json` via jq (both 64bit + arm64 point at same zip), PR to `sebastienrousseau/scoop-bucket`. | One PR on the bucket repo. |
57
- | `release-distribute-aur.yml` | `release.published`, dispatch | Hash `dot-VERSION.tar.gz`, rewrite `pkgver` + `sha256sums` in `install/aur/PKGBUILD`, regenerate `.SRCINFO` via dockerised `makepkg`, push to `ssh://aur@aur.archlinux.org/dot-cli-git.git`. | One commit on AUR. |
55
+ | `release-distribute-homebrew.yml` | `release.published`, dispatch | Hash `dot-VERSION.tar.gz`, regenerate `pkg/brew/dot.rb`, push branch + PR to `sebastienrousseau/homebrew-tap`. | One PR on the tap repo. |
56
+ | `release-distribute-scoop.yml` | `release.published`, dispatch | Hash `dot-VERSION.zip`, rewrite `pkg/scoop/dot.json` via jq (both 64bit + arm64 point at same zip), PR to `sebastienrousseau/scoop-bucket`. | One PR on the bucket repo. |
57
+ | `release-distribute-aur.yml` | `release.published`, dispatch | Hash `dot-VERSION.tar.gz`, rewrite `pkgver` + `sha256sums` in `pkg/aur/PKGBUILD`, regenerate `.SRCINFO` via dockerised `makepkg`, push to `ssh://aur@aur.archlinux.org/dot-cli-git.git`. | One commit on AUR. |
58
58
  | `release-attestation-check.yml` | weekly cron + dispatch | Verify the latest release carries the full attestation bundle (SBOM + sig + cert + intoto + manifest + sig + cert). | Opens or comments on a tracking issue. |
59
59
 
60
60
  ## Event ownership and readiness
@@ -106,7 +106,7 @@ independently.
106
106
  - **AUR `pkgname=dot-cli-git`**: AUR's `-git` convention means
107
107
  "tracks git HEAD", but the workflow publishes tagged stable
108
108
  releases. Either rename to plain `dotfiles` in
109
- `install/aur/PKGBUILD` and register that package, or accept the
109
+ `pkg/aur/PKGBUILD` and register that package, or accept the
110
110
  misnomer. Documented in the v0.2.503 PR (#895).
111
111
  - **Signed-Releases retroactive**: the unified manifest landed in
112
112
  v0.2.503. Releases v0.2.500-502 carry the SBOM bundle only.
@@ -21,7 +21,7 @@ The repo uses a multi-layer testing approach: unit tests for individual function
21
21
  RUN_INTEGRATION=1 ./tests/framework/test_runner.sh
22
22
 
23
23
  # Run performance benchmarks
24
- ./tests/performance/benchmark_runner.sh
24
+ ./benches/benchmark_runner.sh
25
25
 
26
26
  # Run unit tests in parallel (parsed per-file output, deterministic order)
27
27
  ./tests/framework/test_runner.sh --jobs auto
@@ -120,7 +120,7 @@ Test individual functions in isolation. Each file follows the `test_*.sh` naming
120
120
 
121
121
  Test complete workflows like the installation script and end-to-end apply behavior.
122
122
 
123
- ### Performance tests (`tests/performance/`)
123
+ ### Performance tests (`benches/`)
124
124
 
125
125
  Measure resource efficiency with shell startup benchmarks and load tests.
126
126
 
@@ -171,7 +171,7 @@ Tests run automatically on every push to main, every pull request, and weekly sc
171
171
 
172
172
  - name: Run Performance Benchmarks
173
173
  run: |
174
- ./tests/performance/benchmark_runner.sh
174
+ ./benches/benchmark_runner.sh
175
175
  ```
176
176
 
177
177
  ## Environment variables
@@ -41,3 +41,4 @@ It is enforced by `bash ./scripts/qa/traceability-coverage.sh`.
41
41
  | BT-29 | OpenSSF Scorecard nightly snapshot artefact | `scripts/qa/scorecard-snapshot.sh` | `tests/unit/qa/test_scorecard_snapshot.sh` | `docs/security/SCORECARD.md` |
42
42
  | BT-30 | Shell completion generator (`dot completion <shell>`) | `scripts/dot/commands/completion.sh` | `tests/unit/dot-cli/test_dot_completion.sh` | `docs/reference/UTILS.md` |
43
43
  | BT-31 | Examples coverage contract (feature/command → example) | `scripts/qa/examples-coverage.sh` | `tests/unit/misc/test_qa_examples_coverage.sh` | `docs/reference/UTILS.md` |
44
+ | BT-32 | Feature matrix drift gate (command → test, benchmark, example) | `scripts/qa/check-feature-matrix.sh` | `tests/unit/misc/test_qa_check_feature_matrix.sh` | `docs/reference/FEATURE-MATRIX.md`, `docs/operations/TESTING.md` |
@@ -0,0 +1,222 @@
1
+ ---
2
+ render_with_liquid: false
3
+ ---
4
+
5
+ <!-- SPDX-License-Identifier: Apache-2.0 OR MIT -->
6
+ <!-- Copyright (c) 2015-2026 Sebastien Rousseau -->
7
+
8
+ # Packaging guide
9
+
10
+ **Audience: distribution maintainers.** If you are packaging `dot` for
11
+ Debian, Fedora, Arch, Homebrew, nixpkgs, Scoop, or anything else, this
12
+ page is written for you. Everything a packager normally has to
13
+ reverse-engineer — the licence grant, the toolchain floor, how the
14
+ dependencies are pinned, how to build and test offline, and how to
15
+ verify what you downloaded — is here.
16
+
17
+ Existing packaging inputs live in [`pkg/`](https://github.com/sebastienrousseau/dotfiles/tree/main/pkg),
18
+ one directory per format.
19
+
20
+ ## What this software is
21
+
22
+ A shell framework, not a compiled program. The shipped artefact is:
23
+
24
+ - `bin/dot` — the CLI dispatcher (bash)
25
+ - `lib/dot/`, `scripts/` — sourced bash libraries and subcommands
26
+ - `share/man/man1/dot.1` — the man page, **generated** from the CLI's
27
+ command registry at build time
28
+ - `share/{bash-completion,zsh,fish}/…` — completions, also generated
29
+ - `defaults/` — the chezmoi source tree the CLI applies to `$HOME`
30
+
31
+ There is nothing to compile and no architecture-specific output. The
32
+ release archive is `noarch`/`any`.
33
+
34
+ ## Licence grant
35
+
36
+ **`Apache-2.0 OR MIT`** — the SPDX expression declared in
37
+ `package.json` and in `REUSE.toml`. Both full texts ship in the
38
+ repository and in the release archive as `LICENSE-APACHE` and
39
+ `LICENSE-MIT`, and `make install` places both under
40
+ `$(PREFIX)/share/doc/dotfiles/`.
41
+
42
+ This is a dual grant, not a conjunction: a downstream recipient may
43
+ comply with **either** licence, at their option. For distributions
44
+ that require a single choice, MIT is the permissive default; choose
45
+ Apache-2.0 if you want the explicit patent grant.
46
+
47
+ Per-file licensing is machine-readable via [REUSE](https://reuse.software/):
48
+ `REUSE.toml` at the repository root annotates the tree, and
49
+ `reuse lint` runs in CI. Vendored third-party material, where present,
50
+ is annotated separately and keeps its own licence.
51
+
52
+ ## Minimum toolchain
53
+
54
+ Full policy, per-distro mapping, and the rules for when a floor may
55
+ rise: [`MINIMUM-TOOLCHAIN.md`](MINIMUM-TOOLCHAIN.md). The short form
56
+ for a packaging recipe:
57
+
58
+ | Dependency | Minimum | Kind |
59
+ |---|---|---|
60
+ | `bash` | 3.2 | **required at runtime** |
61
+ | `git` | 2.34 | required at runtime |
62
+ | `curl` | any | required by the bootstrap path only |
63
+ | `chezmoi` | 2.47.1 | **required at runtime** — the CLI is a control plane over chezmoi |
64
+ | `zsh` / `fish` / `nushell` | 5.8 / 4.0 / 0.98 | optional; only if the user wants that shell's integration |
65
+ | `jq`, `gum`, `starship`, `fzf` | any | optional; enable JSON output, rich prompts, and interactive pickers |
66
+ | `go` | 1.23 | **build/test only** — fuzz harnesses and the two Go TUIs. Not needed to build or run the package. |
67
+
68
+ Suggested dependency split for a distro package: `Depends: bash (>= 3.2),
69
+ git (>= 2.34), chezmoi (>= 2.47.1)`; `Recommends: jq, zsh`;
70
+ `Suggests: fish, nushell, gum, starship, fzf`.
71
+
72
+ ## Dependency pin model
73
+
74
+ Every dependency this project *builds and tests against* is pinned,
75
+ and every pin is committed:
76
+
77
+ | Surface | Pinned by | Notes |
78
+ |---|---|---|
79
+ | Development toolchain (node, go, rust, and ~20 CLI tools) | `mise.toml` + `mise.lock` + `mise-versions.lock.json` | mise is the package manager; the lock carries checksums |
80
+ | Documentation build (Python) | `requirements-docs.txt` | Hash-pinned (`--require-hashes`-compatible), compiled from `requirements-docs.in` |
81
+ | Node tooling | `package.json` | Dev-only |
82
+ | Nix | `flake.lock`, `nix/flake.lock` | Root flake provides the dev shell; `nix/flake.nix` provides `packages.default` |
83
+ | GitHub Actions | 40-hex commit SHA on every `uses:` | Enforced by `tools/ci/lint-reusable-pins.sh` and OpenSSF Scorecard |
84
+ | Container bases | `FROM image:tag@sha256:<digest>` | Policy in [`security/CI_PINNING.md`](security/CI_PINNING.md) |
85
+ | Binaries fetched during CI | `sha256sum -c` against a committed manifest | `security/remote-installers.sha256` |
86
+
87
+ None of these are needed to *build the package*: the release archive
88
+ is self-contained and its build has no network step. They exist so
89
+ that the tests you may want to run are reproducible.
90
+
91
+ Full provenance policy: [`supply-chain/README.md`](https://github.com/sebastienrousseau/dotfiles/blob/main/supply-chain/README.md).
92
+
93
+ ## Building the package
94
+
95
+ From a release tarball (recommended — it is the attested artefact):
96
+
97
+ ```sh
98
+ tar -xzf dot-0.2.520.tar.gz
99
+ cd dot-0.2.520
100
+ make install PREFIX=/usr DESTDIR="$pkgdir"
101
+ ```
102
+
103
+ From a git checkout:
104
+
105
+ ```sh
106
+ make # generates man page + completions into build/
107
+ make install PREFIX=/usr DESTDIR="$pkgdir"
108
+ ```
109
+
110
+ Both honour `PREFIX` (default `/usr/local`) and `DESTDIR`, and install
111
+ to FHS paths:
112
+
113
+ ```
114
+ $(DESTDIR)$(PREFIX)/bin/dot -> symlink into libexec
115
+ $(DESTDIR)$(PREFIX)/lib/dotfiles/ program tree
116
+ $(DESTDIR)$(PREFIX)/share/man/man1/dot.1
117
+ $(DESTDIR)$(PREFIX)/share/bash-completion/completions/dot
118
+ $(DESTDIR)$(PREFIX)/share/zsh/site-functions/_dot
119
+ $(DESTDIR)$(PREFIX)/share/fish/vendor_completions.d/dot.fish
120
+ $(DESTDIR)$(PREFIX)/share/doc/dotfiles/{LICENSE-APACHE,LICENSE-MIT,README.md,CHANGELOG.md}
121
+ ```
122
+
123
+ Every directory is individually overridable — `BINDIR`, `MANDIR`,
124
+ `DOCDIR`, `LIBEXECDIR`, `BASHCOMPDIR`, `ZSHCOMPDIR`, `FISHCOMPDIR` —
125
+ for distributions whose layout differs. If your `BINDIR` and
126
+ `LIBEXECDIR` are not siblings under `PREFIX`, also set `DOT_LINK` to
127
+ the correct relative or absolute symlink target; `make install` fails
128
+ loudly rather than leaving a dangling link.
129
+
130
+ `make uninstall` removes exactly what `make install` placed.
131
+
132
+ ## Testing offline
133
+
134
+ There are no vendored build dependencies to unbundle, and the checks a
135
+ packager cares about need no network:
136
+
137
+ ```sh
138
+ make installcheck DESTDIR="$pkgdir" # asserts the installed tree is complete and runs
139
+ make -C "$pkgdir" smoke # from a release tarball: run the CLI in place
140
+ ```
141
+
142
+ `installcheck` verifies the `bin` symlink resolves, the man page and
143
+ all three completions are present, the licences are installed, and the
144
+ installed binary reports the expected version and renders help — from
145
+ a sandboxed `HOME`, with no source checkout and no network.
146
+
147
+ The full suite also runs offline:
148
+
149
+ ```sh
150
+ make test # unit + regression; no network
151
+ make examples # every example under examples/ executed
152
+ ```
153
+
154
+ `make test-integration` and anything under `install/provision/` **do**
155
+ touch the network and modify `$HOME`; do not run them in a build
156
+ chroot.
157
+
158
+ ## Verifying what you downloaded
159
+
160
+ Do not package an unverified tarball. Every release carries four
161
+ independent attestations, and the consumer-side recipe with copy-paste
162
+ commands is in
163
+ [`pkg/VERIFY.md`](https://github.com/sebastienrousseau/dotfiles/blob/main/pkg/VERIFY.md)
164
+ and [`security/VERIFY_RELEASE.md`](security/VERIFY_RELEASE.md).
165
+
166
+ Minimum a packager should do:
167
+
168
+ ```sh
169
+ TAG=v0.2.520
170
+ REPO=sebastienrousseau/dotfiles
171
+
172
+ # SLSA build provenance on the tarball itself
173
+ gh attestation verify "dot-${TAG#v}.tar.gz" --repo "$REPO"
174
+
175
+ # Or, without the gh CLI: the signed manifest covering every asset
176
+ gh release download "$TAG" --repo "$REPO" \
177
+ --pattern ALL_SHA256SUMS --pattern 'ALL_SHA256SUMS.*'
178
+ cosign verify-blob \
179
+ --certificate ALL_SHA256SUMS.pem --signature ALL_SHA256SUMS.sig \
180
+ --certificate-identity-regexp "^https://github.com/$REPO/" \
181
+ --certificate-oidc-issuer https://token.actions.githubusercontent.com \
182
+ ALL_SHA256SUMS
183
+ sha256sum -c ALL_SHA256SUMS
184
+ ```
185
+
186
+ Tags are signed with an SSH ed25519 key published in
187
+ [`KEYS.asc`](https://github.com/sebastienrousseau/dotfiles/blob/main/KEYS.asc),
188
+ which is itself a `git allowed_signers` file:
189
+
190
+ ```sh
191
+ git -c gpg.ssh.allowedSignersFile=KEYS.asc tag -v v0.2.520
192
+ ```
193
+
194
+ An SBOM ships with every release in both CycloneDX and SPDX JSON.
195
+
196
+ ## Reproducibility
197
+
198
+ The release archives are built deterministically — `tar --sort=name
199
+ --mtime='1970-01-01' --owner=0 --group=0 --numeric-owner`, and
200
+ `zip -X -D` over a normalised tree — so two builds of the same tag
201
+ produce identical bytes.
202
+
203
+ This is a statement about the *archive build*, which is exercised by
204
+ CI on every release. It is **not** a verified end-to-end
205
+ reproducible-builds claim: no diffoscope comparison of two independent
206
+ rebuilds runs in CI today. Treat it as "deterministic archiving",
207
+ not as a reproducible-builds certification.
208
+
209
+ ## Channel notes
210
+
211
+ | Channel | File | How it is produced |
212
+ |---|---|---|
213
+ | Homebrew | `pkg/brew/dot.rb` | `release-distribute-homebrew.yml` rewrites `url` + `sha256`, opens a PR on `sebastienrousseau/homebrew-tap` |
214
+ | Scoop | `pkg/scoop/dot.json` | `release-distribute-scoop.yml` rewrites version + hashes via `jq`, opens a PR on `sebastienrousseau/scoop-bucket` |
215
+ | AUR | `pkg/aur/PKGBUILD` | `release-distribute-aur.yml` rewrites `pkgver` + `sha256sums`, regenerates `.SRCINFO`, pushes to the AUR |
216
+ | Nix | `pkg/nix/` → `nix/flake.nix` | `packages.default` in `nix/flake.nix` |
217
+ | deb / rpm | *not yet provided* | Contributions welcome; `make install` already produces a correct `DESTDIR` tree, so a recipe is thin |
218
+
219
+ If you are packaging for a distribution not listed here, please open
220
+ an issue — a link to your package will be added, and the `pkg/`
221
+ directory is the right place for the recipe to live so it stays in
222
+ lockstep with the release build.