feat: bug-report collector pseudonymises identities in two stages, opt-in via --pseudonymise (#158)
CI / verify (push) Successful in 2m5s
Release / release (push) Successful in 39s

Files changed:
- .gitea/workflows/ci.yml
- CHANGES.md
- INSTALL.md
- VERSION
- instructions/bug-report.md
- reports/CONTRACT.md
- tools/README.md
- tools/bugreport.py
- tools/chemenu/tests/test_bugreport.py
This commit is contained in:
torben committed 2026-09-30 19:03:59 +02:00
1 parent 0899c670fe
commit 76d67e45ba
9 files changed
+850 -15

No files matched your search

+33 -1
View File
@@ -59,7 +59,7 @@ concern - readable here, never shipped as something to parse.
---
## 8.0.0-beta.7 - 2026-09-30 - reports/CONTRACT.md: only the collector's two counting calls take the bugreport session id
## 8.0.0-beta.8 - 2026-09-30 - Bug-report collector can pseudonymise identities, in two stages
**Author:** Torben Nehmer
@@ -81,6 +81,7 @@ concern - readable here, never shipped as something to parse.
- Super Productivity API path: unwrap the {ok, data} envelope, exclude the inbox project, ready-aware health (#162)
- Live tracker suite: WIKITOOL_TASKS_CONFIG override, real-tracker tests for Super Productivity and CalDAV, nightly workflow and test image
- Bug-report collector: tools/bugreport.py and instructions/bug-report.md
- Bug-report collector can pseudonymise identities, in two stages
**Low impact**
- version bump no longer points at version release in its output
@@ -114,6 +115,37 @@ concern - readable here, never shipped as something to parse.
- reports/CONTRACT.md: only the collector's two counting calls take the bugreport session id
<!-- /wikitool:bumps -->
### Bug-report collector can pseudonymise identities, in two stages (Gitea #158)
A bundle carries machine, user and path names, and an installation failure usually turns on the
*shape* of those names, not on the names. `tools/bugreport.py --pseudonymise` therefore replaces
each identity by a placeholder of the same shape and leaves the structure alone. It is opt-in,
costs one more step, and the instruction recommends it for every channel except a direct handover
to the maintainer over a secure channel.
- **Stage 1 is mechanical.** The script reads user, `USERDOMAIN`/`COMPUTERNAME`, hostname, home and
repository path, `git config user.name`/`user.email` and the remote URLs, and replaces each word
of them in every text file, in raw and JSON-escaped form. A placeholder is an HMAC-SHA256 of the
lowercased word under a per-bundle random salt, so it keeps length, digit/ASCII/non-ASCII class
and per-occurrence case, is injective through a counter, and differs between two bundles. Words of
the stack's own vocabulary, top-level domains and the public origin stay readable. Matching is
whole-identity, longest first, on word boundaries.
- **Stage 2 is a model's judgement, applied by the script.** The agent reads the review list plus
`CHRONOLOGY.md` and `MANIFEST.md` in full, and trace and transcripts in full only under 100 KB
per file, and names further people, companies, customers, internal hosts and projects in a
candidate file. `--bundle DIR --candidates FILE` applies them with the same machinery and packs
the zip again; the model replaces nothing itself. It refuses with exit 1 and an unchanged bundle
when the mapping is gone, and can be repeated.
- **Three local files** - the mapping with its salt, the review list and the candidate file - sit
beside the bundle directory, never inside it and never in the zip. All three hold originals.
- **`MANIFEST.md` names three privacy states** (none, stage 1, stage 1 and 2) and lists the
placeholders, never an original. The closing output and the instruction name the residual
uncertainty: stage 2 can miss a name in free text it did not read in full.
- `instructions/bug-report.md`, `reports/CONTRACT.md`, `tools/README.md` and `INSTALL.md` describe
both stages and the three files; CI runs the collector with `--pseudonymise` from the exported
distribution and checks that the mapping is beside, not in, the bundle and that the host name is
gone.
### reports/CONTRACT.md: only the collector's two counting calls take the bugreport session id
The contract said all of the collector's `wikitool` calls run under `bugreport-<stamp>`. Only