ci: refactoring some things and removing others

Lots of source additions here from long-standing notes over the past few
months. Squashed to make it neater than 219 commits.

- bump version to v1.2.4, Jun 2026
- expand Tor section with new "Traffic analysis and the limits of Tor" subsection
  guard node persistence, website fingerprinting, and a practical breakdown of
  when Tor is and is not sufficient
- expand hardware/firmware threat section with new subsections on firmware
  implants, USB attack hardware (O.MG Cable, Rubber Ducky), Evil Maid attacks,
  supply chain compromise, and a physical inspection checklist
- rename "Removing Metadata from Files/Documents/Pictures" section to "Metadata
  auditing"; add reference table of tools by file type; expand EXIF/XMP coverage,
  PDF metadata (font fingerprinting), and DOCX revision history with real-world
  source identification cases; restructure subsections
- add introductory paragraph to "Your Metadata" section
- add new appendix B8: operational security failure case studies with common
  threads
- add new appendix B9: post-quantum cryptography covering HNDL threat, NIST PQC
  standards, Signal's PQXDH, browser hybrid KEM, PGP limitations, VPN guidance,
  and Monero note
- add new appendix C1: stylometric analysis and writing style covering features
  measured, deployed tools, real cases (J.K. Rowling), effective and ineffective
  countermeasures including AI rewriting
- fix Dangerzone GitHub URL (firstlook -> freedomofpress)
- Remove duplicate footnote [^500]; minor wording fixes ("users" -> "people",
  passive voice tweaks, cross-reference updates)

- docs/index.md: both MSK and RSK GPG fingerprints in a collapsible tip admonition
  instead of bare text
- docs/about/index.md: convert Note admonitions to tip; reformat social media
  links into collapsible tip block
- docs/mirrors/index.md: simplify PDF download instructions to point to Releases;
- README.md: add star history chart
- mkdocs.yml: rename site to "The Hitchhiker's Guide"; update site description
  with hashtags

- sign.yml: remove commented-out workflow_run trigger and if: condition; add
  verify job that runs after sign, downloads artifacts, runs verify_pdf.py, and
  writes a full job summary with hashes; update artifact upload description; minor
  comment and whitespace cleanup
- release.yml, changelog.yml: replace decorative banner comments with single-line
  comments; fix trailing-space style in permissions block
- publish.yml: remove stale comment about nomaterial theme
- verify_pdf.py: full rewrite: replace single-hash-file lookup with flexible
  resolver that checks both bare hash files (.sha256, .b2sum) and two-column
  sumfiles (sha256sums.txt, b2sums.txt); add BLAKE2b verification alongside
  SHA-256; fix signature extension (.asc not .sig); improve CLI (--file,
  --export-dir flags; remove --all; default runs all checks); improve VirusTotal
  output with direct link; cleaner output formatting with ruled separators
This commit is contained in:
nopeitsnothing committed 2026-05-30 09:32:16 -04:00
1 parent d1817e9049
commit c5e5ae48e1
13 files changed
+815 -410

No files matched your search

+38 -38
View File
@@ -15,12 +15,12 @@ Install these before anything else.
python3 --version
# poppler (pdftoppm) and qpdf
sudo apt install poppler-utils qpdf # Debian / Ubuntu
brew install poppler qpdf # macOS
sudo apt install poppler-utils qpdf # Debian/Ubuntu
brew install poppler qpdf # macOS
# GPG
sudo apt install gnupg # Debian / Ubuntu
brew install gnupg # macOS
sudo apt install gnupg # Debian/Ubuntu
brew install gnupg # macOS
# Python dependencies
pip install "mkdocs-material[imaging]" pillow numpy
@@ -31,13 +31,13 @@ Install these before anything else.
```powershell
# Python 3.11+ from https://python.org
# poppler — download from https://github.com/oschwartz10612/poppler-windows/releases
# poppler: download from https://github.com/oschwartz10612/poppler-windows/releases
# Extract and add the bin\ folder to PATH
# qpdf — download from https://github.com/qpdf/qpdf/releases
# qpdf: download from https://github.com/qpdf/qpdf/releases
# Extract and add the bin\ folder to PATH
# GPG — download Gpg4win from https://gpg4win.org
# GPG: download Gpg4win from https://gpg4win.org
# Python dependencies
pip install "mkdocs-material[imaging]" pillow numpy
@@ -52,26 +52,26 @@ You also need **Google Chrome** or **Microsoft Edge** installed for the light-mo
```
.github/
workflows/
build.yml ← builds PDFs, uploads artifact
sign.yml ← hashes + GPG signs, uploads signatures artifact
release.yml ← publishes GitHub Release with all assets
changelog.yml ← prepends a new entry to docs/changelog/index.md
publish.yml ← deploys MkDocs site to GitHub Pages
build-sign-release.yml← DEPRECATED — fails on trigger, kept for reference
build.yml # builds PDFs, uploads artifact
sign.yml # hashes + GPG signs, uploads signatures artifact
release.yml # publishes GitHub Release with all assets
changelog.yml # prepends a new entry to docs/changelog/index.md
publish.yml # deploys MkDocs site to GitHub Pages
build-sign-release.yml # DEPRECATED - fails on trigger, kept for reference
docs/
guide/index.md ← the guide (single Markdown file)
changelog/ ← release notes
code/ ← this page
export/ ← PDF output (PDFs gitignored; .sha256, .b2sum, .asc tracked)
pgp/ ← public signing keys
guide/index.md # the guide (single Markdown file)
changelog/ # release notes
code/ # this page
export/ # PDF output (PDFs gitignored; .sha256, .b2sum, .asc tracked)
pgp/ # public signing keys
scripts/
build_guide_pdf.py ← MkDocs + Chromium PDF builder
convert.py ← pixel-based dark mode PDF converter
update_changelog.py ← auto-generates changelog entries from git log
setup_workflow.py ← GitHub Secrets setup assistant
verify_pdf.py ← signature verification helper
build_guide_pdf.py # MkDocs + Chromium PDF builder
convert.py # pixel-based dark mode PDF converter
update_changelog.py # auto-generates changelog entries from git log
setup_workflow.py # GitHub Secrets setup assistant
verify_pdf.py # signature verification helper
archived/
tag_release.py ← ARCHIVED — GPG tag helper (not used in current flow)
tag_release.py # ARCHIVED - GPG tag helper (not used in current flow)
```
---
@@ -120,7 +120,7 @@ Opens at `http://127.0.0.1:8000`.
## CI/CD pipeline overview
The pipeline is fully manual after the initial build — no step automatically triggers the next. This prevents version mismatches between what was built, what was signed, and what gets released.
The pipeline is fully manual after the initial build - no step automatically triggers the next. This prevents version mismatches between what was built, what was signed, and what gets released.
```
push to main (or manual trigger)
@@ -131,7 +131,7 @@ push to main (or manual trigger)
Uploads artifact: pdfs
Note the run ID.
│
│ ← manually trigger sign.yml with the build run ID
│ # manually trigger sign.yml with the build run ID
▼
sign.yml
Downloads pdfs artifact. Hashes (SHA-256 + BLAKE2b) and GPG-signs
@@ -139,20 +139,20 @@ push to main (or manual trigger)
signatures, pdfs-signed
Note the run ID.
│
│ ← manually trigger release.yml with the sign run ID
│ # manually trigger release.yml with the sign run ID
▼
release.yml
Downloads signatures + pdfs-signed artifacts. Runs VirusTotal.
Creates GitHub Release tagged release-YYYYMMDD-<short-sha>.
│
│ ← manually trigger changelog.yml with the version string
│ # manually trigger changelog.yml with the version string
▼
changelog.yml
Runs update_changelog.py, prepends a new ## [vX.Y.Z] entry,
commits back to main.
```
Each stage is independent. If signing fails (e.g. an expired key), re-run only `sign.yml` pointing at the existing build artifact — no need to rebuild the PDFs.
Each stage is independent. If signing fails (e.g. an expired key), re-run only `sign.yml` pointing at the existing build artifact - no need to rebuild the PDFs.
!!! warning "Before you push"
@@ -166,7 +166,7 @@ Each stage is independent. If signing fails (e.g. an expired key), re-run only `
### 1. Trigger a build
Push to `main` — `build.yml` runs automatically when `docs/`, `mkdocs.yml`, or `scripts/` change. You can also trigger it manually from **Actions → Build PDFs → Run workflow**.
Push to `main` - `build.yml` runs automatically when `docs/`, `mkdocs.yml`, or `scripts/` change. You can also trigger it manually from **Actions → Build PDFs → Run workflow**.
Once it completes successfully, **note the run ID** from the URL or the Actions list.
@@ -208,7 +208,7 @@ Go to **Actions → Release → Run workflow**.
- Auto-generate a release tag in the format `release-YYYYMMDD-<short-sha>` (e.g. `release-20260527-abc1234`)
- Create a GitHub Release with all PDFs, hash files, and signatures attached, and the VirusTotal report URLs in the body
No version number needs to be chosen at this step — the tag is derived from the date and commit SHA, so it is always unique and always traceable.
No version number needs to be chosen at this step - the tag is derived from the date and commit SHA, so it is always unique and always traceable.
---
@@ -228,7 +228,7 @@ Go to **Actions → Update Changelog → Run workflow**.
- Prepends a new `## [version]` admonition block to `docs/changelog/index.md`
- Commits the result back to `main`
The version string is the only human decision in the release process. It goes into the changelog only — it does not affect the release tag.
The version string is the only human decision in the release process. It goes into the changelog only - it does not affect the release tag.
!!! tip "Previewing the changelog entry"
Run with `dry_run: true` first to review the generated entry before it is committed.
@@ -293,7 +293,7 @@ Copy the entire output (including `-----BEGIN PGP PRIVATE KEY BLOCK-----` and th
### `GPG_PASSPHRASE`
The passphrase protecting the private key above. Must match exactly — no trailing newline.
The passphrase protecting the private key above. Must match exactly - no trailing newline.
### `ACTIONS_SSH_SIGNING_KEY`
@@ -311,7 +311,7 @@ A [VirusTotal](https://www.virustotal.com) API key with file upload permissions.
### `CHANGELOG_PAT`
A GitHub Personal Access Token with `contents: write` scope on this repository. Needed because `changelog.yml` commits back to `main` — commits made with the default `GITHUB_TOKEN` do not trigger further workflow runs (GitHub loop-prevention). A PAT bypasses this. If absent, falls back to `GITHUB_TOKEN` — the commit still happens, it just won't trigger downstream workflows.
A GitHub Personal Access Token with `contents: write` scope on this repository. Needed because `changelog.yml` commits back to `main` - commits made with the default `GITHUB_TOKEN` do not trigger further workflow runs (GitHub loop-prevention). A PAT bypasses this. If absent, falls back to `GITHUB_TOKEN` - the commit still happens, it just won't trigger downstream workflows.
**Creating one:** GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens → set Contents to Read and write for this repo only.
@@ -319,11 +319,11 @@ A GitHub Personal Access Token with `contents: write` scope on this repository.
| Secret | Required by | What happens if missing |
|--------|------------|------------------------|
| `GPG_PRIVATE_KEY` | `sign.yml` | Signing step fails — no `.asc` files produced |
| `GPG_PRIVATE_KEY` | `sign.yml` | Signing step fails - no `.asc` files produced |
| `GPG_PASSPHRASE` | `sign.yml` | GPG import succeeds but signing fails |
| `ACTIONS_SSH_SIGNING_KEY` | `sign.yml` | Export commit is unsigned (may fail if branch protection requires signed commits) |
| `VT_API_KEY` | `release.yml` | VirusTotal step fails — release is not published |
| `CHANGELOG_PAT` | `changelog.yml` | Falls back to `GITHUB_TOKEN` — changelog updates but commit won't trigger downstream workflows |
| `VT_API_KEY` | `release.yml` | VirusTotal step fails - release is not published |
| `CHANGELOG_PAT` | `changelog.yml` | Falls back to `GITHUB_TOKEN` - changelog updates but commit won't trigger downstream workflows |
---
@@ -366,7 +366,7 @@ Install the imaging extras: `pip install "mkdocs-material[imaging]"`. Required b
Pillow needs libjpeg. Reinstall after installing the system lib: `sudo apt install libjpeg-dev && pip install --force-reinstall pillow`.
**`qpdf: can't find PDF header`**
Ensure you are on the current version of `convert.py` — qpdf only accepts PDF inputs, not PNG.
Ensure you are on the current version of `convert.py` - qpdf only accepts PDF inputs, not PNG.
**GPG signing fails on CI with `No secret key`**
The `GPG_PRIVATE_KEY` secret is missing or malformed. Re-export with `gpg --armor --export-secret-keys <fingerprint>` and paste the full block including header and footer lines.