From 9e89e93f9ae49ccd2137065947ba97e28faecad7 Mon Sep 17 00:00:00 2001 From: Behnam RK Date: Sun, 13 Sep 2026 17:55:44 +0330 Subject: [PATCH] docs(diag): say that a unix group name is deliberately kept, and pin it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A redacted bundle ships `control.group` verbatim in config.json and in doctor's control-check summary, and the question of whether that is a leak has now been raised once and answered: it is not. A unix group is a property of the machine rather than of the person or the provider — the default is `admin` — and the control check exists to tell you which group to join, which "you are not in the `profile-1` group" cannot do. Redacting it would replace the answer and hide no identity. Written into docs/usage/cli.md beside the kinds list, because the page already enumerates what IS replaced and a reader would otherwise reasonably assume this was covered. The same paragraph names the other deliberate keep, dezhban's own file paths, since both are the same reasoning and both have now been questioned. Pinned by TestAUnixGroupNameIsKeptInEveryEntryThatCarriesIt, which asserts BOTH entries keep it. One of the two would be worse than either answer: the same value reading as a token in one file and a name in the other is the "one identifier, two tokens" confusion the package already works to avoid. No CHANGELOG entry: nothing about the behaviour changed, only what is written down about it. Closes #69 Co-Authored-By: Claude Opus 5 (1M context) --- docs/usage/cli.md | 9 +++++++++ internal/redact/json_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/docs/usage/cli.md b/docs/usage/cli.md index ce8ca47..e62a232 100644 --- a/docs/usage/cli.md +++ b/docs/usage/cli.md @@ -501,6 +501,15 @@ were replaced: imported is redacted too, because a `.conf` or `.ovpn` is named after the VPN it configures. +Two things are deliberately **kept**, because redacting them would replace the +answer rather than an identity. The **unix group** in `control.group` is a +property of the machine, not of you or your provider — the default is `admin` — +and the control check exists to tell you which group to join, which +"you are not in the `profile-1` group" cannot do. And the **paths of dezhban's +own files**: the control check names the socket it probed, so a path reading as +`…/host-N` would be a diagnosis with its subject removed. A socket you renamed +yourself is redacted, because that name is yours. + The README's legend reports counts and the tokens they cover — a range ("23 distinct IP addresses → ip-1 … ip-23") when a kind's tokens run consecutively, and a list ("2 distinct profile names → profile-1, profile-3") diff --git a/internal/redact/json_test.go b/internal/redact/json_test.go index 5ff8dcd..b394d0f 100644 --- a/internal/redact/json_test.go +++ b/internal/redact/json_test.go @@ -589,3 +589,34 @@ func TestANameSpelledLikeAnExistingTokenKeepsItsSpelling(t *testing.T) { t.Errorf("legend = %v, want the single profile and no interface kind", legend) } } + +// A unix group is a property of the machine, not of the person or the provider: +// the macOS default is `admin`, and the control check exists to tell you which +// group to join — which "you are not in the profile-1 group" cannot do. Kept +// deliberately, in both entries that carry it, and pinned here because the +// question has been raised once and closed (#69): a bundle that hides the +// diagnosis has thrown away the answer and hidden no identity. +// +// Keeping it in only ONE of the two would be worse than either choice: the same +// value would read as a token in one entry and a name in the other. +func TestAUnixGroupNameIsKeptInEveryEntryThatCarriesIt(t *testing.T) { + r := New(true) + const group = "vpnadmins" + + cfg := r.JSON(`{"control":{"enabled":true,"group":"` + group + `"}}`) + if !strings.Contains(cfg, group) { + t.Errorf("config.json redacted the group: %q", cfg) + } + + doc := r.JSON(`{"checks":[{"name":"control","summary":"reachable (/var/db/dezhban/control.sock, group \"` + group + `\") — routine ops need no password."}]}`) + if !strings.Contains(doc, group) { + t.Errorf("doctor.json redacted the group: %q", doc) + } + // And the socket path beside it, for the same reason. + if !strings.Contains(doc, "/var/db/dezhban/control.sock") { + t.Errorf("doctor.json redacted the socket path: %q", doc) + } + if legend := r.Legend(); len(legend) != 0 { + t.Errorf("legend = %v, want nothing minted for a group name or a path", legend) + } +}