Skip to content

docs: directive for pre-publication guards against capture-derived data - #302

Open
vsits-proxy-builder[bot] wants to merge 2 commits into
mainfrom
docs/pre-publication-guards
Open

docs: directive for pre-publication guards against capture-derived data#302
vsits-proxy-builder[bot] wants to merge 2 commits into
mainfrom
docs/pre-publication-guards

Conversation

@vsits-proxy-builder

Copy link
Copy Markdown
Contributor

Directive only — no implementation here. Filing the reasoning so the layering argument exists in public before someone relies on the wrong half of it.

The correction this exists to make

"CI will catch it" is the assumption I was operating on, and it is wrong about prevention:

layer prevents publication? sees fork PRs?
contributor pre-push yes yes — the only layer that does
maintainer pre-push our own commits only no
CI on pull_request no yes

A fork PR's diff is public on github.com the instant it opens; CI starts afterward. The objects also land in this repo as refs/pull/N/head and persist even if the PR is closed or the fork deleted — verified, #294 and #296 are resolvable on origin right now.

CI is still worth having. It is detection and containment: keeps data off main, off tags, off npm, and bounds the window so remediation knows what to treat as burned. It is not a gate.

Why the tension is permanent

Testing this proxy well requires real Claude Code traffic. The fixtures that make the tests meaningful are the same artifacts that carry session UUIDs, thinking signatures, filesystem paths, and other people's words. We are not going to stop testing against real data, so the guard has to be structural rather than a habit.

Three instances have already reached public history:

The first one is ours. This is not a contributor-hygiene problem.

Deliberately not writing a scanner

@Gunther-Schulz already has tools/absence-scan.mjs — class-based, importable, and already running as his own pre-push guard against real captures. Per the anti-bloat lens, a second implementation needs justification and there is none. This directive depends on that scanner landing; asked on #292 whether it can split out of the #272 stack.

If he would rather own the whole thing including the hooks, close this in favour of his.

Two constraints worth reading

Scan the diff, not history. The untracked pre-push on the maintainer host scans all reachable history and produced 77 false positives on one rebase. A noisy guard gets --no-verify'd and then protects nothing.

Report classes and counts, never values. A guard that echoes what it found into a terminal, a CI log, or a PR comment has published it a second time. #292 was reported that way and it is the right pattern.

And an honest ceiling: mechanical classes are catchable (UUIDs, PEM blocks, high-entropy strings, home paths, IP literals). The 2,305 characters of someone else's GitHub comment that #292 actually carried is a judgment call — a heuristic flagging long verbatim strings under test/fixtures/ would surface it for review, which is as far as this can honestly claim to go.

Non-Functional Requirements

  • Size/complexity budget — ~150-250 LOC excluding the scanner: a pre-push wrapper, an installer, one CI step, one docs section. Materially larger means the scanner boundary was violated.
  • Threat model — the guard reads diffs containing the data it hunts. It must never write matched values to stdout, stderr, a log, or a CI annotation; counts and class names only. Runs on contributor machines: no phoning home, no reads outside the repo, no writes but its exit code.
  • Maintainability constraints — one scanner, three call sites. No second copy, no vendored fork.
  • Performance/reliability — runs on every push; diff-scoped keeps it sub-second. A scanner failure must fail the push, not silently pass.
  • Load-bearing?yes. It gates what becomes public and its failure mode is irreversible.

Open questions in the directive

  1. Does the scanner land standalone, or does @Gunther-Schulz own the whole thing?
  2. Should the CI step block merge or annotate? Leaning blocking, since the failure it prevents is unrecoverable — but fork PRs get no CI here until approved, so a false positive is slow for a contributor to iterate on.
  3. Is core.hooksPath acceptable? It replaces .git/hooks wholesale; the maintainer host has a post-merge/post-checkout pair that must survive, so the installer likely has to chain.

Refs #292, #272

— Proxy Builder

Testing this proxy well requires real CC traffic, so the fixtures that
make tests meaningful are the same artifacts that carry session UUIDs,
signatures, paths, and other people's words. Three instances have already
reached public history (#292, #272, meter#19).

Corrects the assumption that CI is the gate. A fork PR's diff is public
the moment it opens and the objects persist in this repo as
refs/pull/N/head; CI runs after. Only a contributor-side pre-push hook
prevents publication — CI is detection and containment, keeping data off
main, tags, and npm.

Depends on @Gunther-Schulz's tools/absence-scan.mjs rather than writing a
second scanner; asked on #292 whether it can land standalone.
@vsits-proxy-builder vsits-proxy-builder Bot added the directive-stage PR is in directive/spec review stage; remove when implementation begins label Aug 3, 2026
Ran @Gunther-Schulz's scanner against the #292 file. It already has every
interface the directive asked for — shebang, main-module guard, 0/2/1 exit
codes, --git-range for a pre-push caller — and reports class, path, and
length without ever echoing a value. Scope narrows accordingly: nothing
here asks for new capability.

Two settings are correct for his fork and wrong upstream, and would
otherwise survive the move by inertia. The #292 fixture is allowlisted by
name, so the range that introduced it scans clean; that entry has to come
out once the fixture is synthesized. And the semantic classes are scoped
to test/fixtures/harvested/, which does not exist here — upstream must
choose an equivalent or accept byte-level-only, deliberately rather than
by discovering three classes never ran.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

directive-stage PR is in directive/spec review stage; remove when implementation begins

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants