@sebastienrousseau/dotfiles 0.2.519 → 0.2.521
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.
- package/CHANGELOG.md +200 -0
- package/LICENSE-APACHE +190 -0
- package/{LICENSE → LICENSE-MIT} +1 -1
- package/README.md +1172 -166
- package/install.sh +77 -11
- package/package.json +8 -8
- package/tools/README.md +49 -0
- package/tools/ci/install-chezmoi-verified.sh +68 -0
- package/docs/.vitepress/reports/localization-readability-audit.md +0 -73
- package/docs/AI.md +0 -179
- package/docs/CNAME +0 -1
- package/docs/CONFIG_STRATEGY.md +0 -124
- package/docs/COPYRIGHT +0 -7
- package/docs/GOVERNANCE.md +0 -98
- package/docs/MAINTAINERS.md +0 -41
- package/docs/NAMING_CONVENTIONS.md +0 -102
- package/docs/OPENCODE.md +0 -127
- package/docs/README.md +0 -84
- package/docs/STRUCTURE.md +0 -102
- package/docs/adr/ADR-001-ci-cd-pipeline.md +0 -118
- package/docs/adr/ADR-002-shell-performance.md +0 -130
- package/docs/adr/ADR-003-security-first.md +0 -158
- package/docs/adr/ADR-004-cli-architecture.md +0 -171
- package/docs/adr/ADR-005-chezmoi-choice.md +0 -99
- package/docs/adr/ADR-006-shell-selection.md +0 -124
- package/docs/adr/ADR-007-multi-shell-parity.md +0 -62
- package/docs/adr/ADR-008-alias-system-architecture.md +0 -95
- package/docs/adr/ADR-009-wallpaper-driven-theming.md +0 -131
- package/docs/adr/ADR-010-starship-transient-prompt.md +0 -144
- package/docs/adr/ADR-011-nushell-tier3-keep.md +0 -144
- package/docs/adr/ADR-012-ai-fleet-local-proxy.md +0 -79
- package/docs/adr/README.md +0 -40
- package/docs/architecture/AI_COST_OPTIMIZATION.md +0 -144
- package/docs/architecture/ARCHITECTURE.md +0 -117
- package/docs/architecture/INTEROP.md +0 -44
- package/docs/architecture/REPO_LAYOUT.md +0 -241
- package/docs/architecture/WALKTHROUGH.md +0 -86
- package/docs/architecture/fleet-deployment.md +0 -77
- package/docs/archive/EUXIS_2026_REVIEW.md +0 -127
- package/docs/archive/LEGACY_ROADMAP.md +0 -6
- package/docs/archive/MILESTONE_v0.2.493.md +0 -47
- package/docs/archive/PLAN.md +0 -199
- package/docs/archive/REPO_AUDIT.md +0 -31
- package/docs/articles/.pages +0 -6
- package/docs/articles/2026-07-05-custom-mkdocs-material-dark-theme.md +0 -216
- package/docs/articles/2026-07-05-fish-startup-abbr.md +0 -153
- package/docs/articles/2026-07-05-master-to-main-rename-runbook.md +0 -128
- package/docs/articles/index.md +0 -36
- package/docs/guides/INSTALL.md +0 -144
- package/docs/guides/NEOVIM_IDE_GUIDE.md +0 -61
- package/docs/guides/THEMING.md +0 -230
- package/docs/guides/TROUBLESHOOTING.md +0 -176
- package/docs/guides/WSL2_NIX_TROUBLESHOOTING.md +0 -792
- package/docs/index.md +0 -132
- package/docs/interop/A2A.md +0 -39
- package/docs/interop/POWERSHELL.md +0 -102
- package/docs/manual/00-introduction.md +0 -89
- package/docs/manual/01-concepts/01-architecture.md +0 -138
- package/docs/manual/01-concepts/02-trust-model.md +0 -183
- package/docs/manual/01-concepts/03-theme-engine.md +0 -186
- package/docs/manual/01-concepts/04-fleet.md +0 -148
- package/docs/manual/01-concepts/05-self-healing.md +0 -204
- package/docs/manual/02-tutorials/01-first-install.md +0 -197
- package/docs/manual/02-tutorials/02-add-wallpaper.md +0 -216
- package/docs/manual/02-tutorials/03-create-profile.md +0 -244
- package/docs/manual/02-tutorials/04-encrypt-secret.md +0 -281
- package/docs/manual/02-tutorials/05-deploy-fleet.md +0 -283
- package/docs/manual/03-reference/01-dot-cli.md +0 -450
- package/docs/manual/03-reference/02-config-files.md +0 -265
- package/docs/manual/03-reference/03-environment.md +0 -124
- package/docs/manual/03-reference/04-templates.md +0 -190
- package/docs/manual/03-reference/05-feature-flags.md +0 -187
- package/docs/manual/04-cookbook/01-recipes.md +0 -285
- package/docs/manual/04-cookbook/02-troubleshooting.md +0 -351
- package/docs/manual/04-cookbook/03-faq.md +0 -175
- package/docs/manual/05-appendices/A-platform-matrix.md +0 -101
- package/docs/manual/05-appendices/B-security-checklist.md +0 -85
- package/docs/manual/05-appendices/C-glossary.md +0 -40
- package/docs/manual/05-appendices/D-bibliography.md +0 -58
- package/docs/manual/05-appendices/E-license.md +0 -38
- package/docs/manual/_toc.yml +0 -58
- package/docs/manual/command-index.md +0 -155
- package/docs/manual/concept-index.md +0 -168
- package/docs/manual/index.md +0 -66
- package/docs/operations/ARCHITECTURE_ROADMAP.md +0 -7
- package/docs/operations/ATTESTATION.md +0 -44
- package/docs/operations/CI_CADENCE.md +0 -107
- package/docs/operations/CI_COMPOSITES.md +0 -156
- package/docs/operations/COMPLETIONS.md +0 -123
- package/docs/operations/COVERAGE.md +0 -204
- package/docs/operations/DRIFT.md +0 -107
- package/docs/operations/HARD_AUDIT_2026.md +0 -631
- package/docs/operations/MAINTENANCE.md +0 -63
- package/docs/operations/MANIFEST.md +0 -127
- package/docs/operations/MIGRATION.md +0 -109
- package/docs/operations/OPERATIONS.md +0 -188
- package/docs/operations/PERFORMANCE.md +0 -133
- package/docs/operations/REGISTRY.md +0 -90
- package/docs/operations/RELEASE_PIPELINE.md +0 -128
- package/docs/operations/RELIABILITY.md +0 -122
- package/docs/operations/RFC_v0_2_503_reorganization.md +0 -280
- package/docs/operations/ROADMAP.md +0 -10
- package/docs/operations/ROADMAP_2026.md +0 -7
- package/docs/operations/ROADMAP_V0_2_503.md +0 -10
- package/docs/operations/TESTING.md +0 -216
- package/docs/operations/TRACEABILITY.md +0 -43
- package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +0 -65
- package/docs/operations/VERSION_SYNC.md +0 -393
- package/docs/reference/ALIASES.md +0 -131
- package/docs/reference/ALIASES_CHEATSHEET.md +0 -32
- package/docs/reference/ALIASES_DEPRECATIONS.md +0 -13
- package/docs/reference/FEATURES.md +0 -66
- package/docs/reference/FONTS.md +0 -112
- package/docs/reference/POWERSHELL_PARITY.md +0 -82
- package/docs/reference/PROFILES.md +0 -69
- package/docs/reference/SCREENSHOTS.md +0 -121
- package/docs/reference/SCRIPTS.md +0 -71
- package/docs/reference/SUPPORT_MATRIX.md +0 -80
- package/docs/reference/THEMES.md +0 -117
- package/docs/reference/TOOLS.md +0 -110
- package/docs/reference/UTILS.md +0 -242
- package/docs/registry.json +0 -6
- package/docs/schema/dot-env-v1.json +0 -110
- package/docs/schema/dot-registry-v1.json +0 -33
- package/docs/security/AI_ACT_COMPLIANCE.md +0 -94
- package/docs/security/AUDIT_BYPASS.md +0 -103
- package/docs/security/AUTOMATION_SECRETS.md +0 -26
- package/docs/security/CI_EGRESS_ALLOWLIST.md +0 -127
- package/docs/security/CI_PINNING.md +0 -129
- package/docs/security/COMMIT_SIGNING.md +0 -138
- package/docs/security/COMPLIANCE.md +0 -458
- package/docs/security/DEPS_DEV_EXCEPTIONS.md +0 -86
- package/docs/security/DISCLOSURE.md +0 -130
- package/docs/security/ENCRYPTION.md +0 -57
- package/docs/security/FMEA.md +0 -159
- package/docs/security/FUZZING.md +0 -114
- package/docs/security/HISTORY_FILTERING.md +0 -132
- package/docs/security/INCIDENT_RESPONSE.md +0 -579
- package/docs/security/INSTALL_VERIFICATION.md +0 -122
- package/docs/security/KEYS.md +0 -49
- package/docs/security/KEY_ROTATION.md +0 -303
- package/docs/security/MCP_POLICY.md +0 -78
- package/docs/security/POLICY_RELEASES.md +0 -37
- package/docs/security/README.md +0 -28
- package/docs/security/SCORECARD.md +0 -195
- package/docs/security/SECRETS.md +0 -158
- package/docs/security/SECURITY.md +0 -45
- package/docs/security/SECURITY_CHECKLIST.md +0 -55
- package/docs/security/SHELL_EXEMPTIONS.md +0 -145
- package/docs/security/SOUP_REGISTER.md +0 -36
- package/docs/security/THREAT_MODEL.md +0 -130
- package/docs/security/VERIFICATION_VALIDATION.md +0 -228
- package/docs/security/VERIFY_RELEASE.md +0 -201
- package/docs/security/security-pubkey.asc +0 -15
- package/docs/stylesheets/extra.css +0 -444
- package/docs/themes/README.md +0 -10
- package/docs/themes/VISUAL_INTEGRITY_REPORT.md +0 -30
- package/docs/themes/hero-shot.svg +0 -78
- package/scripts/README.md +0 -123
- package/scripts/ci/check-copyright-headers.sh +0 -8
- package/scripts/ci/check-shell-preamble.sh +0 -8
- package/scripts/ci/guard-gitleaks-checkout.sh +0 -8
- package/scripts/demo/record.sh +0 -43
- package/scripts/diagnostics/a2a-conformance.sh +0 -163
- package/scripts/diagnostics/alias-governance.sh +0 -138
- package/scripts/diagnostics/aliases-cheatsheet.sh +0 -74
- package/scripts/diagnostics/aliases-manifest.sh +0 -77
- package/scripts/diagnostics/benchmark.sh +0 -408
- package/scripts/diagnostics/conflicts.sh +0 -73
- package/scripts/diagnostics/doctor-unified.sh +0 -39
- package/scripts/diagnostics/doctor.sh +0 -751
- package/scripts/diagnostics/drift-dashboard.sh +0 -202
- package/scripts/diagnostics/health.sh +0 -623
- package/scripts/diagnostics/history-analysis.sh +0 -86
- package/scripts/diagnostics/mcp-doctor.sh +0 -582
- package/scripts/diagnostics/perf.sh +0 -453
- package/scripts/diagnostics/scorecard.sh +0 -119
- package/scripts/diagnostics/secret-governance.sh +0 -65
- package/scripts/diagnostics/security-score.sh +0 -467
- package/scripts/diagnostics/smoke-test.sh +0 -88
- package/scripts/diagnostics/snapshot.sh +0 -90
- package/scripts/diagnostics/verify.sh +0 -108
- package/scripts/diagnostics/verify_state.sh +0 -73
- package/scripts/diagnostics/version-locks.sh +0 -94
- package/scripts/diagnostics/workstation-attestation.sh +0 -187
- package/scripts/dot/commands/agent.sh +0 -485
- package/scripts/dot/commands/agents.sh +0 -336
- package/scripts/dot/commands/ai.sh +0 -587
- package/scripts/dot/commands/aliases.sh +0 -277
- package/scripts/dot/commands/appearance.sh +0 -110
- package/scripts/dot/commands/completion.sh +0 -134
- package/scripts/dot/commands/core.sh +0 -217
- package/scripts/dot/commands/diagnostics.sh +0 -265
- package/scripts/dot/commands/env-emit.sh +0 -203
- package/scripts/dot/commands/fleet.sh +0 -688
- package/scripts/dot/commands/init.sh +0 -185
- package/scripts/dot/commands/lint.sh +0 -208
- package/scripts/dot/commands/manual.sh +0 -169
- package/scripts/dot/commands/meta.sh +0 -333
- package/scripts/dot/commands/patterns.sh +0 -55
- package/scripts/dot/commands/registry.sh +0 -419
- package/scripts/dot/commands/restore.sh +0 -232
- package/scripts/dot/commands/secrets.sh +0 -296
- package/scripts/dot/commands/security.sh +0 -102
- package/scripts/dot/commands/tools.sh +0 -556
- package/scripts/dot/data/alias-deprecations.tsv +0 -2
- package/scripts/dot/powershell/Dot.psm1 +0 -319
- package/scripts/fonts/install-nerd-fonts.sh +0 -75
- package/scripts/fonts/patch-fonts.sh +0 -36
- package/scripts/git-hooks/install.sh +0 -12
- package/scripts/git-hooks/pre-commit +0 -12
- package/scripts/git-hooks/pre-commit-audit.sh +0 -146
- package/scripts/git-hooks/pre-push +0 -105
- package/scripts/git-hooks/prepare-commit-msg +0 -29
- package/scripts/lib/secrets_provider.sh +0 -185
- package/scripts/ops/ai-setup.sh +0 -71
- package/scripts/ops/bundle.sh +0 -104
- package/scripts/ops/chaos.sh +0 -50
- package/scripts/ops/chezmoi-apply.sh +0 -333
- package/scripts/ops/chezmoi-diff.sh +0 -16
- package/scripts/ops/chezmoi-remove.sh +0 -46
- package/scripts/ops/chezmoi-update.sh +0 -63
- package/scripts/ops/heal-chezmoi.sh +0 -87
- package/scripts/ops/heal-system.sh +0 -129
- package/scripts/ops/heal-tools.sh +0 -297
- package/scripts/ops/heal.sh +0 -223
- package/scripts/ops/post-apply-repair.sh +0 -107
- package/scripts/ops/prewarm.sh +0 -128
- package/scripts/ops/release.sh +0 -262
- package/scripts/ops/rollback.sh +0 -604
- package/scripts/ops/setup.sh +0 -138
- package/scripts/ops/teleport.sh +0 -34
- package/scripts/qa/check-version-consistency.sh +0 -124
- package/scripts/qa/coverage-baseline.sh +0 -61
- package/scripts/qa/docs-coverage.sh +0 -112
- package/scripts/qa/examples-coverage.sh +0 -94
- package/scripts/qa/powershell-contract.ps1 +0 -95
- package/scripts/qa/reliability-audit.sh +0 -139
- package/scripts/qa/scorecard-snapshot.sh +0 -128
- package/scripts/qa/traceability-coverage.sh +0 -117
- package/scripts/qa/validate-examples.sh +0 -27
- package/scripts/qa/wsl-contract.sh +0 -12
- package/scripts/secrets/age-init.sh +0 -82
- package/scripts/secrets/create-secrets-file.sh +0 -46
- package/scripts/secrets/encrypt-ssh-key.sh +0 -44
- package/scripts/security/backup.sh +0 -58
- package/scripts/security/check-disclosure-key-expiry.sh +0 -111
- package/scripts/security/dns-doh.sh +0 -52
- package/scripts/security/encryption-check.sh +0 -55
- package/scripts/security/enforce-policies.sh +0 -335
- package/scripts/security/firewall.sh +0 -91
- package/scripts/security/lock-configs.sh +0 -67
- package/scripts/security/lock-screen.sh +0 -56
- package/scripts/security/manage-secrets.sh +0 -429
- package/scripts/security/ssh-cert.sh +0 -204
- package/scripts/security/telemetry-kill.sh +0 -51
- package/scripts/security/usb-safety.sh +0 -52
- package/scripts/theme/apply-gnome-theme.sh +0 -333
- package/scripts/theme/extract-heic-frames.sh +0 -115
- package/scripts/theme/extract-theme.py +0 -742
- package/scripts/theme/install-boot-logo.sh +0 -63
- package/scripts/theme/install-catppuccin-themes.sh +0 -371
- package/scripts/theme/install-cursors.sh +0 -26
- package/scripts/theme/install-file-icons.sh +0 -27
- package/scripts/theme/install-grub-theme.sh +0 -62
- package/scripts/theme/install-lock-icon.sh +0 -31
- package/scripts/theme/merge-wallpaper.sh +0 -146
- package/scripts/theme/rebuild-themes.sh +0 -544
- package/scripts/theme/switch.sh +0 -449
- package/scripts/theme/wallpaper-rotate.sh +0 -137
- package/scripts/theme/wallpaper-sync.sh +0 -690
- package/scripts/tools/cmatrix.sh +0 -22
- package/scripts/tools/detect-collisions.py +0 -103
- package/scripts/tools/emoji-picker.sh +0 -49
- package/scripts/tools/figlet-banner.sh +0 -19
- package/scripts/tools/log-rotate.sh +0 -31
- package/scripts/tools/lolcat-wrap.sh +0 -20
- package/scripts/tools/pipes.sh +0 -49
- package/scripts/tuning/linux.sh +0 -186
- package/scripts/tuning/macos.sh +0 -56
- package/scripts/uninstall.sh +0 -86
- package/scripts/version-sync.sh +0 -654
- package/templates/chezmoi-data/geekom-a9.toml.example +0 -21
- package/templates/chezmoi-data/mac-m1.toml.example +0 -16
- package/templates/chezmoi-data/mac-t2-linux.toml.example +0 -21
- package/templates/chezmoi-data/surface-pro-7p.toml.example +0 -21
- package/templates/projects/go/.github/workflows/ci.yml +0 -31
- package/templates/projects/go/README.md +0 -7
- package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +0 -8
- package/templates/projects/go/go.mod +0 -3
- package/templates/projects/go/go.sum +0 -0
- package/templates/projects/molecule/README.md +0 -7
- package/templates/projects/molecule/converge.yml +0 -7
- package/templates/projects/molecule/molecule.yml +0 -16
- package/templates/projects/node/.github/workflows/ci.yml +0 -30
- package/templates/projects/node/README.md +0 -7
- package/templates/projects/node/package-lock.json +0 -12
- package/templates/projects/node/package.json +0 -10
- package/templates/projects/node/src/index.js +0 -3
- package/templates/projects/packer/README.md +0 -15
- package/templates/projects/packer/main.pkr.hcl +0 -15
- package/templates/projects/python/.github/workflows/ci.yml +0 -34
- package/templates/projects/python/README.md +0 -7
- package/templates/projects/python/pyproject.toml +0 -25
- package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +0 -2
- package/templates/projects/python/tests/test_basic.py +0 -3
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
render_with_liquid: false
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Pre-Push Audit Bypass
|
|
6
|
-
|
|
7
|
-
This page documents when the pre-push reliability audit can be bypassed,
|
|
8
|
-
how to do it, and why the answer is "almost never on `main`."
|
|
9
|
-
|
|
10
|
-
## Background
|
|
11
|
-
|
|
12
|
-
`scripts/git-hooks/pre-push` runs two checks on every push:
|
|
13
|
-
|
|
14
|
-
1. **Signed-commit verification** — every commit being pushed must have
|
|
15
|
-
a valid GPG/SSH signature. No bypass is available; an unsigned
|
|
16
|
-
commit is refused unconditionally.
|
|
17
|
-
|
|
18
|
-
2. **Reliability audit** — `scripts/qa/reliability-audit.sh --quick`
|
|
19
|
-
runs a fast subset of the test suite + lint checks. This is the
|
|
20
|
-
step that can be bypassed.
|
|
21
|
-
|
|
22
|
-
Before issue #871 the audit was opt-out: `DOTFILES_SKIP_PRE_PUSH_AUDIT=1`
|
|
23
|
-
in your shell rc would silently skip every push's audit. Bypass was
|
|
24
|
-
invisible, persistent, and one keystroke away. That's the wrong default.
|
|
25
|
-
|
|
26
|
-
## The new policy
|
|
27
|
-
|
|
28
|
-
Effective with #871 and the corresponding commit on this branch:
|
|
29
|
-
|
|
30
|
-
- The audit **always runs by default**. Missing env var → audit runs.
|
|
31
|
-
- Bypass requires `DOTFILES_ALLOW_UNSKIPPED_PUSH=1` set inline for the
|
|
32
|
-
one push you want to bypass (not exported in your shell rc).
|
|
33
|
-
- The legacy `DOTFILES_SKIP_PRE_PUSH_AUDIT=1` is **rejected** with a
|
|
34
|
-
migration message; the hook exits non-zero if it sees the old var.
|
|
35
|
-
- Every bypass is appended to
|
|
36
|
-
`${XDG_STATE_HOME:-~/.local/state}/dotfiles/audit-bypass.log` with
|
|
37
|
-
timestamp, branch, remote, and reason.
|
|
38
|
-
- `dot doctor` reports the count of bypasses in the last 7 days.
|
|
39
|
-
|
|
40
|
-
The new variable name is deliberately awkward
|
|
41
|
-
(`DOTFILES_ALLOW_UNSKIPPED_PUSH`) — it should not feel like a routine
|
|
42
|
-
flag. Setting it should require a moment's thought.
|
|
43
|
-
|
|
44
|
-
## How to bypass for a single push
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
DOTFILES_ALLOW_UNSKIPPED_PUSH=1 \
|
|
48
|
-
DOTFILES_BYPASS_REASON='hotfix: CI is wedged on flake' \
|
|
49
|
-
git push origin hotfix/my-branch
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
The reason string is optional but encouraged. It lands in the audit log
|
|
53
|
-
so `dot doctor` and any future review can answer "why was this
|
|
54
|
-
bypassed?" without git archaeology.
|
|
55
|
-
|
|
56
|
-
## When bypass is legitimate
|
|
57
|
-
|
|
58
|
-
Short list — anything outside this is suspicious:
|
|
59
|
-
|
|
60
|
-
- **Hotfix push to a non-main branch** when CI infrastructure itself
|
|
61
|
-
is the audit blocker (e.g., the audit pre-flight depends on a remote
|
|
62
|
-
service that's down). The fix should land *before* the
|
|
63
|
-
infrastructure recovers; bypass is the bridge.
|
|
64
|
-
- **Force-push of a tag rewind** that doesn't introduce new commits
|
|
65
|
-
(rare).
|
|
66
|
-
|
|
67
|
-
When bypass is **not** legitimate:
|
|
68
|
-
|
|
69
|
-
- Routine `main` pushes. The whole point of the audit is to guard
|
|
70
|
-
the protected branch.
|
|
71
|
-
- Pushes whose audit failure is "annoying" — the right move is to fix
|
|
72
|
-
the failure, not skip the check.
|
|
73
|
-
- CI environments. CI should run the audit explicitly, never bypass
|
|
74
|
-
it; if a CI job pushes, the env var must remain unset there.
|
|
75
|
-
|
|
76
|
-
## Verifying current state
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
dot doctor # surfaces recent bypasses
|
|
80
|
-
cat ${XDG_STATE_HOME:-~/.local/state}/dotfiles/audit-bypass.log
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Each line of the log is tab-separated:
|
|
84
|
-
`ISO8601-timestamp \t branch=... \t remote=... \t reason=...`.
|
|
85
|
-
|
|
86
|
-
## Disabling bypass entirely
|
|
87
|
-
|
|
88
|
-
If your machine should *never* bypass (e.g., a release runner), unset
|
|
89
|
-
the env var in your shell rc and add a guard to your `.zshenv` or
|
|
90
|
-
equivalent:
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
unset DOTFILES_ALLOW_UNSKIPPED_PUSH
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
There's no way to permanently grant bypass — that's intentional.
|
|
97
|
-
|
|
98
|
-
## References
|
|
99
|
-
|
|
100
|
-
- `scripts/git-hooks/pre-push` — the hook itself
|
|
101
|
-
- `scripts/diagnostics/doctor.sh` — the "Pre-Push Audit Bypass" section
|
|
102
|
-
- `tests/unit/security/test_pre_push_bypass.sh` — regression test
|
|
103
|
-
- Issue #871
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
render_with_liquid: false
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Automation Secrets
|
|
6
|
-
|
|
7
|
-
## Required secrets
|
|
8
|
-
|
|
9
|
-
| Secret | Scope | Purpose |
|
|
10
|
-
| :--- | :--- | :--- |
|
|
11
|
-
| `ACTIONS_BOT_SIGNING_KEY` | GitHub Actions | SSH private key used for signed automation commits |
|
|
12
|
-
| `GITHUB_TOKEN` | GitHub Actions | GitHub API access for PRs, attestations, and scans |
|
|
13
|
-
|
|
14
|
-
## Required local variables
|
|
15
|
-
|
|
16
|
-
| Variable | Scope | Purpose |
|
|
17
|
-
| :--- | :--- | :--- |
|
|
18
|
-
| `HOMEBREW_INSTALLER_SHA256` | macOS bootstrap | Verifies the Homebrew installer before execution |
|
|
19
|
-
| `CHEZMOI_INSTALLER_SHA256` | Installer | Verifies the Chezmoi installer before execution |
|
|
20
|
-
|
|
21
|
-
## Provisioning notes
|
|
22
|
-
|
|
23
|
-
1. Store the SSH signing private key in GitHub Actions as `ACTIONS_BOT_SIGNING_KEY`.
|
|
24
|
-
2. Store the matching public key in [allowed_signers](https://github.com/sebastienrousseau/dotfiles/blob/main/defaults/dot_config/git/allowed_signers.tmpl).
|
|
25
|
-
3. Rotate the key on personnel or workstation change.
|
|
26
|
-
4. Fail closed when secrets are absent.
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
render_with_liquid: false
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# CI Egress Allowlist
|
|
6
|
-
|
|
7
|
-
This page documents the network endpoints CI jobs are allowed to
|
|
8
|
-
reach when `step-security/harden-runner` is operating in `block`
|
|
9
|
-
mode. Managed under
|
|
10
|
-
[#878](https://github.com/sebastienrousseau/dotfiles/issues/878).
|
|
11
|
-
|
|
12
|
-
## Status
|
|
13
|
-
|
|
14
|
-
All 76 jobs across the 28 workflow files in `.github/workflows/` are
|
|
15
|
-
currently in **`audit` mode** — harden-runner is the first step in
|
|
16
|
-
every job and records outbound network calls to the
|
|
17
|
-
[step-security telemetry dashboard](https://app.stepsecurity.io) but
|
|
18
|
-
does not block them.
|
|
19
|
-
|
|
20
|
-
The next iteration (tracked as a follow-up under #878) flips each
|
|
21
|
-
group to `block` once the audit-mode runs confirm the allowlist is
|
|
22
|
-
complete. Switching one job at a time keeps blast radius small:
|
|
23
|
-
a missing endpoint on a `block`-mode job fails the run loud and the
|
|
24
|
-
list below gets updated.
|
|
25
|
-
|
|
26
|
-
## Allowlist (by domain)
|
|
27
|
-
|
|
28
|
-
This is the union of endpoints the entire workflow surface needs.
|
|
29
|
-
When flipping a specific job to `block` mode, narrow this list to
|
|
30
|
-
the endpoints that particular job actually touches.
|
|
31
|
-
|
|
32
|
-
### GitHub itself (universally required)
|
|
33
|
-
|
|
34
|
-
| Endpoint | Used by | Why |
|
|
35
|
-
|---|---|---|
|
|
36
|
-
| `github.com:443` | every job | git clone, gh CLI |
|
|
37
|
-
| `api.github.com:443` | every job | gh CLI, issue/PR API |
|
|
38
|
-
| `objects.githubusercontent.com:443` | every job | release-asset downloads, LFS objects |
|
|
39
|
-
| `*.actions.githubusercontent.com:443` | every job | runner ↔ orchestrator |
|
|
40
|
-
| `pkg.actions.githubusercontent.com:443` | every job | action-cache CDN |
|
|
41
|
-
| `results-receiver.actions.githubusercontent.com:443` | every job | workflow telemetry |
|
|
42
|
-
| `codeload.github.com:443` | jobs that `git clone` tagged refs | tarball downloads for some actions |
|
|
43
|
-
| `uploads.github.com:443` | jobs that upload artifacts | `actions/upload-artifact` |
|
|
44
|
-
| `raw.githubusercontent.com:443` | the install-script jobs | curl-pull of unversioned content |
|
|
45
|
-
|
|
46
|
-
### Package managers (apt, brew, cargo, npm, luarocks)
|
|
47
|
-
|
|
48
|
-
| Endpoint | Used by | Why |
|
|
49
|
-
|---|---|---|
|
|
50
|
-
| `azure.archive.ubuntu.com:443` | ubuntu jobs running `apt-get` | apt mirror |
|
|
51
|
-
| `archive.ubuntu.com:80` | ubuntu jobs running `apt-get` | apt mirror |
|
|
52
|
-
| `security.ubuntu.com:80` | ubuntu jobs running `apt-get` | security updates |
|
|
53
|
-
| `keyserver.ubuntu.com:443` | jobs that add repo signing keys | GPG keyserver |
|
|
54
|
-
| `formulae.brew.sh:443` | macOS jobs running `brew` | Homebrew formula index |
|
|
55
|
-
| `ghcr.io:443` + `*.docker.io:443` | docker / container jobs | image pulls |
|
|
56
|
-
| `registry.npmjs.org:443` | npm-publish.yml + the pre-commit npm hook | npm metadata + publish |
|
|
57
|
-
| `registry-1.docker.io:443` | docker jobs | image manifests |
|
|
58
|
-
| `crates.io:443` + `static.crates.io:443` | cargo-install jobs | crate downloads |
|
|
59
|
-
| `index.crates.io:443` | cargo-install jobs | crate index |
|
|
60
|
-
| `luarocks.org:443` + `*.luarocks.org:443` | reusable-lua-lint.yml | luacheck install |
|
|
61
|
-
|
|
62
|
-
### Project-specific installers (chezmoi / mise / starship / stylua / typos / etc.)
|
|
63
|
-
|
|
64
|
-
| Endpoint | Used by | Why |
|
|
65
|
-
|---|---|---|
|
|
66
|
-
| `get.chezmoi.io:443` | `setup-chezmoi` composite (fallback path) | chezmoi installer |
|
|
67
|
-
| `mise.run:443` | `setup-mise` composite | mise installer |
|
|
68
|
-
| `releases.starship.rs:443` | mise-managed install of starship | starship binary |
|
|
69
|
-
|
|
70
|
-
### Security / SBOM / scanning
|
|
71
|
-
|
|
72
|
-
| Endpoint | Used by | Why |
|
|
73
|
-
|---|---|---|
|
|
74
|
-
| `api.osv.dev:443` | grype / scorecard | OSV vuln database |
|
|
75
|
-
| `vulners.com:443` | grype | vulnerability metadata |
|
|
76
|
-
| `toolbox-data.anchore.io:443` | anchore/sbom-action | SBOM tooling |
|
|
77
|
-
| `api.deps.dev:443` | future deps.dev integration (#877) | package metadata |
|
|
78
|
-
| `api.securityscorecards.dev:443` | scorecard.yml | publish_results upload |
|
|
79
|
-
| `*.codeql.github.com:443` | codeql.yml | CodeQL bundle download |
|
|
80
|
-
|
|
81
|
-
## Job-level egress notes (legitimate broad-egress jobs)
|
|
82
|
-
|
|
83
|
-
A few jobs need wider network access than the standard allowlist
|
|
84
|
-
covers. Each carries an inline comment near the harden-runner step
|
|
85
|
-
explaining the deviation so reviewers can audit at a glance.
|
|
86
|
-
|
|
87
|
-
### `update-deps.yml` — broad GitHub API egress
|
|
88
|
-
|
|
89
|
-
Polls multiple `github.com/<repo>/releases/latest` endpoints to find
|
|
90
|
-
new tool versions. Allowlist needs to include `api.github.com:443`
|
|
91
|
-
and the raw-content domain for sed-replacing version strings.
|
|
92
|
-
|
|
93
|
-
### `devcontainer-prebuild.yml` — registry push
|
|
94
|
-
|
|
95
|
-
Pushes to `ghcr.io:443` with the `packages: write` token. The egress
|
|
96
|
-
allowlist for that job is the standard set plus `ghcr.io` writes.
|
|
97
|
-
|
|
98
|
-
### `nightly.yml` — `Beta/Nightly Tools Test` job
|
|
99
|
-
|
|
100
|
-
This job deliberately runs `curl ... | tar -xJf -` against the
|
|
101
|
-
shellcheck release. Justified because the job is `continue-on-error: true`
|
|
102
|
-
and is opt-in (manual or scheduled). Future hardening: download the
|
|
103
|
-
release asset, verify a known hash, then exec — same shape as
|
|
104
|
-
`tools/ci/install-chezmoi-verified.sh`.
|
|
105
|
-
|
|
106
|
-
## Updating this page
|
|
107
|
-
|
|
108
|
-
Whenever a job is flipped to `block` mode:
|
|
109
|
-
|
|
110
|
-
1. Run the audit-mode workflow at least once after every recent
|
|
111
|
-
workflow change to make sure the harden-runner telemetry reflects
|
|
112
|
-
reality.
|
|
113
|
-
2. Visit the [step-security dashboard](https://app.stepsecurity.io/)
|
|
114
|
-
filtered to the repo + job + last 7 days.
|
|
115
|
-
3. Add any endpoints the dashboard reports that aren't already in
|
|
116
|
-
this page's tables.
|
|
117
|
-
4. Edit the job to set `egress-policy: block` and add the per-job
|
|
118
|
-
`allowed-endpoints:` block listing only what that specific job
|
|
119
|
-
needs (not the whole union).
|
|
120
|
-
5. Land the change, watch the first run; if anything fails the run
|
|
121
|
-
loud, add the missing endpoint and retry.
|
|
122
|
-
|
|
123
|
-
## References
|
|
124
|
-
|
|
125
|
-
- `step-security/harden-runner` — [https://github.com/step-security/harden-runner](https://github.com/step-security/harden-runner)
|
|
126
|
-
- `docs/security/SCORECARD.md` — Token-Permissions check ties to harden-runner adoption.
|
|
127
|
-
- Issue [#878](https://github.com/sebastienrousseau/dotfiles/issues/878).
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
render_with_liquid: false
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# CI Dependency Pinning Policy
|
|
6
|
-
|
|
7
|
-
Every external dependency the CI pipeline consumes must be pinned by
|
|
8
|
-
40-hex commit SHA. The policy applies to:
|
|
9
|
-
|
|
10
|
-
1. **Third-party actions** — `uses: owner/action@<sha>` (already enforced via Scorecard's `Pinned-Dependencies` check at score ≥ 9).
|
|
11
|
-
2. **Reusable workflows in this repo** — `uses: sebastienrousseau/dotfiles/.github/workflows/reusable-X.yml@<sha>` (added with [#855](https://github.com/sebastienrousseau/dotfiles/issues/855); enforced by `tools/ci/lint-reusable-pins.sh`).
|
|
12
|
-
3. **Container base images** — `FROM image:tag@sha256:<digest>` (closed by [#886](https://github.com/sebastienrousseau/dotfiles/pull/886)).
|
|
13
|
-
4. **Release binaries downloaded at build time** — `curl … && echo "<sha256> ..." | sha256sum -c` (closed by [#888](https://github.com/sebastienrousseau/dotfiles/pull/888)).
|
|
14
|
-
|
|
15
|
-
The sole exception is the SLSA generic reusable workflow. Its bootstrap
|
|
16
|
-
validates that the caller reference has the form `refs/tags/vX.Y.Z` and
|
|
17
|
-
fails when invoked through a bare commit SHA. Therefore
|
|
18
|
-
`generator_generic_slsa3.yml` is pinned to the exact release tag
|
|
19
|
-
`v2.1.0`; the corresponding commit SHA is recorded beside the call site
|
|
20
|
-
and must be verified before any tag bump. OpenSSF Scorecard explicitly
|
|
21
|
-
exempts the SLSA generator from its SHA-pinning check for this constraint.
|
|
22
|
-
|
|
23
|
-
## Why SHA-pin reusable workflows
|
|
24
|
-
|
|
25
|
-
When `ci.yml` calls a reusable via `./.github/workflows/reusable-X.yml`,
|
|
26
|
-
GitHub resolves the reusable from the **same ref as the calling
|
|
27
|
-
workflow at run time**. For an in-repo PR that's the PR's branch —
|
|
28
|
-
fine. The risk is the inverse: a malicious push to `main` (or any
|
|
29
|
-
ref the calling workflow might resolve from) can swap reusable
|
|
30
|
-
content under a CI run, with no audit trail in the PR diff.
|
|
31
|
-
|
|
32
|
-
Pinning to a 40-hex SHA freezes the reusable's content at the
|
|
33
|
-
pinned commit. To swap the reusable, you have to bump every call
|
|
34
|
-
site — visible in the PR diff, reviewable, revertible.
|
|
35
|
-
|
|
36
|
-
## Acceptable forms
|
|
37
|
-
|
|
38
|
-
```yaml
|
|
39
|
-
# Acceptable — full SHA pin.
|
|
40
|
-
uses: sebastienrousseau/dotfiles/.github/workflows/reusable-shell-lint.yml@b0615f8fb5c0f3826f58904a5567eff11b6c500e # main
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
The trailing comment is a human-readable hint at what the SHA
|
|
44
|
-
represented when it was pinned (typically `main`, sometimes a tag
|
|
45
|
-
like `v0.2.501`). The hint is documentation only — the SHA is what
|
|
46
|
-
GitHub uses.
|
|
47
|
-
|
|
48
|
-
## Rejected forms
|
|
49
|
-
|
|
50
|
-
```yaml
|
|
51
|
-
# Rejected — relative path is a mutable ref.
|
|
52
|
-
uses: ./.github/workflows/reusable-shell-lint.yml
|
|
53
|
-
|
|
54
|
-
# Rejected — branch ref is mutable.
|
|
55
|
-
uses: sebastienrousseau/dotfiles/.github/workflows/reusable-shell-lint.yml@main
|
|
56
|
-
|
|
57
|
-
# Rejected — tag ref is mutable (tags can be moved).
|
|
58
|
-
uses: sebastienrousseau/dotfiles/.github/workflows/reusable-shell-lint.yml@v0.2.501
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
The `lint-reusable-pins` job in `ci.yml` runs `tools/ci/lint-reusable-pins.sh`
|
|
62
|
-
on every workflow change. The lint fails the build on any of the
|
|
63
|
-
rejected forms above.
|
|
64
|
-
|
|
65
|
-
## Refreshing pinned SHAs
|
|
66
|
-
|
|
67
|
-
`bump-reusable-pins.yml` handles this automatically. On every push to
|
|
68
|
-
`main` that touches `.github/workflows/reusable-*.yml`, the bot scans
|
|
69
|
-
caller workflows for stale pins and opens a PR bumping them to the new
|
|
70
|
-
SHA. Signed with `ACTIONS_BOT_SIGNING_KEY` so the resulting commit
|
|
71
|
-
passes `Verify Commit Signatures`.
|
|
72
|
-
|
|
73
|
-
The manual recipe below stays here as a fallback — for example, if you
|
|
74
|
-
need to bump pins before a merge to main, or if the bot's run failed
|
|
75
|
-
and you want to short-circuit waiting for the next push trigger.
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
# 1. Land the change to the reusable on main via a PR.
|
|
79
|
-
# 2. After merge, capture the new main SHA:
|
|
80
|
-
git fetch origin main
|
|
81
|
-
PIN=$(git rev-parse origin/main)
|
|
82
|
-
echo "$PIN"
|
|
83
|
-
|
|
84
|
-
# 3. Bump every call site:
|
|
85
|
-
find .github/workflows -name '*.yml' -exec sed -i.bak -E \
|
|
86
|
-
"s|(/reusable-[a-z0-9-]+\.yml@)[0-9a-f]{40}|\\1${PIN}|g" {} +
|
|
87
|
-
rm -f .github/workflows/*.bak
|
|
88
|
-
|
|
89
|
-
# 4. Verify the lint still passes:
|
|
90
|
-
bash tools/ci/lint-reusable-pins.sh
|
|
91
|
-
|
|
92
|
-
# 5. Land the bump on a follow-up PR with a single-purpose commit:
|
|
93
|
-
git commit -am "chore(ci): bump reusable-workflow pins to ${PIN:0:10}"
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Whether bumped by the bot or by hand, the resulting PR runs the full
|
|
97
|
-
CI suite — a reviewer still confirms the new reusable content is
|
|
98
|
-
intentional before merge.
|
|
99
|
-
|
|
100
|
-
## Dependabot
|
|
101
|
-
|
|
102
|
-
Dependabot's `github-actions` ecosystem now updates full-SHA references to
|
|
103
|
-
same-repository reusable workflows. PR
|
|
104
|
-
[#992](https://github.com/sebastienrousseau/dotfiles/pull/992) verified this
|
|
105
|
-
behavior by moving the reusable workflow baseline from v0.2.511 to the
|
|
106
|
-
immutable v0.2.516 commit alongside the external minor/patch action group.
|
|
107
|
-
|
|
108
|
-
Keep `bump-reusable-pins.yml` enabled as the immediate post-merge path. It
|
|
109
|
-
updates callers as soon as a reusable workflow changes on `main`, while
|
|
110
|
-
Dependabot provides the scheduled dependency review and grouped update path.
|
|
111
|
-
Both mechanisms must preserve full 40-hex SHA references and pass
|
|
112
|
-
`lint-reusable-pins` plus the egress-policy contract tests.
|
|
113
|
-
|
|
114
|
-
## Negative test
|
|
115
|
-
|
|
116
|
-
`tests/unit/ci/test_reusable_pin_lint.sh` deliberately drops an
|
|
117
|
-
unpinned reusable reference into a sandboxed workflow tree and
|
|
118
|
-
asserts that `lint-reusable-pins.sh` exits non-zero with the
|
|
119
|
-
expected error message. The test runs as part of the standard
|
|
120
|
-
test suite — a regression in the lint catches at PR time, not at
|
|
121
|
-
merge time.
|
|
122
|
-
|
|
123
|
-
## See also
|
|
124
|
-
|
|
125
|
-
- [#855](https://github.com/sebastienrousseau/dotfiles/issues/855) — original tracking issue.
|
|
126
|
-
- `tools/ci/lint-reusable-pins.sh` — the enforcement script.
|
|
127
|
-
- `tests/unit/ci/test_reusable_pin_lint.sh` — the negative test.
|
|
128
|
-
- `.github/workflows/bump-reusable-pins.yml` — the auto-bump bot.
|
|
129
|
-
- [GitHub: pinning actions to a full-length commit SHA](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions).
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# Commit Signing — Policy & Setup
|
|
2
|
-
|
|
3
|
-
Every commit that reaches `main` in this repository must carry a
|
|
4
|
-
cryptographic signature that GitHub can verify. The policy is enforced
|
|
5
|
-
in three independent layers, so a single bypass does not break the
|
|
6
|
-
chain. This document explains the policy, walks through SSH and GPG
|
|
7
|
-
setup, and lists the verification commands you can run locally before
|
|
8
|
-
pushing.
|
|
9
|
-
|
|
10
|
-
## Why
|
|
11
|
-
|
|
12
|
-
Closes [#853](https://github.com/sebastienrousseau/dotfiles/issues/853).
|
|
13
|
-
Local hooks alone are bypassable — `git commit --no-verify`,
|
|
14
|
-
`git push --no-verify`, or unsetting `DOTFILES_ALLOW_UNSKIPPED_PUSH`
|
|
15
|
-
all let an unsigned commit reach a remote if GitHub-side enforcement
|
|
16
|
-
is missing. The chain below removes every escape hatch.
|
|
17
|
-
|
|
18
|
-
## Enforcement layers
|
|
19
|
-
|
|
20
|
-
1. **Local commit hook** — `dot_config/git/hooks/executable_commit-msg`
|
|
21
|
-
is deployed by chezmoi. It rejects an unsigned commit at the
|
|
22
|
-
`commit-msg` stage on the developer machine.
|
|
23
|
-
2. **Local pre-push hook** — `scripts/git-hooks/pre-push` runs
|
|
24
|
-
`git verify-commit` against every commit in the push range. A
|
|
25
|
-
single unverified commit aborts the push. `--no-verify` skips
|
|
26
|
-
this layer; the next two catch it.
|
|
27
|
-
3. **GitHub Rulesets** — `.github/rulesets/main.json` declares
|
|
28
|
-
`required_signatures` on `refs/heads/main`. The rule is part
|
|
29
|
-
of the repo so it's reproducible across forks. Apply with
|
|
30
|
-
`gh ruleset import .github/rulesets/main.json`.
|
|
31
|
-
4. **`compliance-guard.yml` workflow** — runs on every PR targeting
|
|
32
|
-
`main`. Walks the commit range with `git verify-commit` and
|
|
33
|
-
marks unsigned commits in the PR summary; fails the workflow
|
|
34
|
-
when `unsigned_count > 0`.
|
|
35
|
-
|
|
36
|
-
A merge to `main` therefore requires (Ruleset accepts the push) AND
|
|
37
|
-
(the workflow's signed-commit check passes) AND (the maintainer's
|
|
38
|
-
push key is allowed). The protection holds even if a contributor's
|
|
39
|
-
local hooks are missing or skipped.
|
|
40
|
-
|
|
41
|
-
## Setting up SSH signing (recommended)
|
|
42
|
-
|
|
43
|
-
SSH signing is the 2026 default. It reuses your existing SSH key —
|
|
44
|
-
no new key material, no GPG agent, no Kleopatra UI. GitHub has
|
|
45
|
-
recognised SSH signatures since [2022](https://github.blog/changelog/2022-08-23-ssh-commit-verification-now-supported/).
|
|
46
|
-
|
|
47
|
-
```sh
|
|
48
|
-
# 1. Tell git to sign with SSH.
|
|
49
|
-
git config --global gpg.format ssh
|
|
50
|
-
|
|
51
|
-
# 2. Point at the SSH key you want git to use.
|
|
52
|
-
git config --global user.signingkey "$HOME/.ssh/id_ed25519.pub"
|
|
53
|
-
|
|
54
|
-
# 3. Turn on auto-signing for every commit and tag.
|
|
55
|
-
git config --global commit.gpgsign true
|
|
56
|
-
git config --global tag.gpgsign true
|
|
57
|
-
|
|
58
|
-
# 4. Tell GitHub which SSH key signs your commits.
|
|
59
|
-
gh ssh-key add ~/.ssh/id_ed25519.pub --type signing --title "$(hostname) signing"
|
|
60
|
-
|
|
61
|
-
# 5. (Optional) Populate the allowed_signers file so
|
|
62
|
-
# `git log --show-signature` can verify locally.
|
|
63
|
-
mkdir -p "$HOME/.config/git"
|
|
64
|
-
echo "$(git config user.email) $(cat ~/.ssh/id_ed25519.pub)" \
|
|
65
|
-
> "$HOME/.config/git/allowed_signers"
|
|
66
|
-
git config --global gpg.ssh.allowedSignersFile \
|
|
67
|
-
"$HOME/.config/git/allowed_signers"
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
After this, `git log --show-signature` shows `Good "git" signature
|
|
71
|
-
for you@example.com with ED25519 key SHA256:…` on every new commit.
|
|
72
|
-
|
|
73
|
-
## Setting up GPG signing (legacy / for tag-signing mirrors that don't yet support SSH)
|
|
74
|
-
|
|
75
|
-
```sh
|
|
76
|
-
# 1. Generate or import a key. ED25519 is the modern recommendation;
|
|
77
|
-
# RSA-4096 is the conservative fallback.
|
|
78
|
-
gpg --quick-generate-key "Your Name <you@example.com>" ed25519 sign 2y
|
|
79
|
-
|
|
80
|
-
# 2. Find the long key ID.
|
|
81
|
-
gpg --list-secret-keys --keyid-format=long
|
|
82
|
-
|
|
83
|
-
# 3. Tell git which key.
|
|
84
|
-
git config --global user.signingkey <LONG_KEY_ID>
|
|
85
|
-
git config --global commit.gpgsign true
|
|
86
|
-
|
|
87
|
-
# 4. Export and upload the public key to GitHub.
|
|
88
|
-
gpg --armor --export <LONG_KEY_ID> | gh gpg-key add -
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Verifying locally before pushing
|
|
92
|
-
|
|
93
|
-
```sh
|
|
94
|
-
# Every commit in the push range.
|
|
95
|
-
git log "$(git merge-base @{u} HEAD)..HEAD" \
|
|
96
|
-
--pretty='%H %G? %s' \
|
|
97
|
-
| awk '$2 != "G" {print "UNSIGNED:", $0}'
|
|
98
|
-
|
|
99
|
-
# Or the canonical command the pre-push hook uses:
|
|
100
|
-
for c in $(git rev-list "$(git merge-base @{u} HEAD)..HEAD"); do
|
|
101
|
-
git verify-commit "$c" >/dev/null 2>&1 \
|
|
102
|
-
&& echo "✓ $c" \
|
|
103
|
-
|| echo "✗ $c — unsigned, will be rejected by main ruleset"
|
|
104
|
-
done
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## Troubleshooting
|
|
108
|
-
|
|
109
|
-
| Symptom | Likely cause | Fix |
|
|
110
|
-
|---|---|---|
|
|
111
|
-
| `error: gpg failed to sign the data` | gpg-agent isn't running, or `GPG_TTY` not exported | `export GPG_TTY=$(tty)` in your shell rc; restart agent with `gpgconf --kill gpg-agent` |
|
|
112
|
-
| `error: Load key "/.../id_ed25519": Permission denied` | SSH key permissions too open | `chmod 600 ~/.ssh/id_ed25519` |
|
|
113
|
-
| GitHub shows "Unverified" on a commit signed locally | Signing key not uploaded to GitHub | `gh ssh-key add … --type signing` (SSH) or `gh gpg-key add` (GPG) |
|
|
114
|
-
| Pre-push hook rejects a merge commit you didn't author | Upstream commit lacks a signature | Either pull the rebased branch, or fast-forward instead of merging |
|
|
115
|
-
| Ruleset import via `gh` complains "invalid JSON" | Rulesets API expects the `target` + `rules` envelope, not just the rules array | Use the file as-is — `gh ruleset import .github/rulesets/main.json` |
|
|
116
|
-
|
|
117
|
-
## Re-applying the ruleset after a manual edit
|
|
118
|
-
|
|
119
|
-
If someone edits the ruleset in the GitHub UI by mistake, the
|
|
120
|
-
file-of-truth wins. Re-apply:
|
|
121
|
-
|
|
122
|
-
```sh
|
|
123
|
-
gh api -X POST repos/{owner}/{repo}/rulesets \
|
|
124
|
-
--input .github/rulesets/main.json
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
(or `-X PUT` against the existing ruleset's ID if it already exists).
|
|
128
|
-
|
|
129
|
-
## References
|
|
130
|
-
|
|
131
|
-
- `.github/rulesets/main.json` — the enforced policy.
|
|
132
|
-
- `.github/workflows/compliance-guard.yml` — the workflow that
|
|
133
|
-
fails PRs containing unsigned commits.
|
|
134
|
-
- `scripts/git-hooks/pre-push` — the local pre-push gate.
|
|
135
|
-
- `dot_config/git/hooks/executable_commit-msg` — the local
|
|
136
|
-
commit-msg gate.
|
|
137
|
-
- [GitHub: About commit signature verification](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification)
|
|
138
|
-
- [GitHub: Telling Git about your SSH key](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key)
|