Skip to content

Probe list-targets, soft-seeder, and Pages publish pipeline#41

Draft
chrisns wants to merge 6 commits into
mainfrom
feat/probe-seeding-pipeline
Draft

Probe list-targets, soft-seeder, and Pages publish pipeline#41
chrisns wants to merge 6 commits into
mainfrom
feat/probe-seeding-pipeline

Conversation

@chrisns

@chrisns chrisns commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Tracks 1–3 from docs/reporting-site-plan.md — the data pipeline that makes the reporting site (#40) render real measured data instead of a fixture.

Track 1 — sandbox-probe list-targets

Emits the probe's own sensitive-path registry as JSON, each entry classified (kind, scope, seedable). Only home-scoped regular files are seedable. The probe is the single source of truth, so the seeder can't drift from what's actually probed. Registry gains an isDir flag; directories and system paths are never seedable.

Track 2 — scripts/seed-decoys.sh

Soft-plants decoys at seedable targets — writes only where nothing exists, so it never clobbers a real secret (safe on a laptop and a bare runner alike). Wired into scan-matrix before the probe runs, identically for the direct baseline and every harness — seed parity is what makes a baseline-vs-sandbox diff mean "the sandbox blocked it" rather than "the file was absent."

Track 3 — aggregate & publish job

One job (needs: [build, scan], if: always()): downloads every scan's report, appends one immutable commit to the gh-pages-data branch (data/<run-ts>/<os>-<harness>.json), rebuilds the concatenated all-reports.json from the whole history (scripts/build-site-data.mjs), and deploys Pages via the official deploy-pages flow. One commit → no 30-way push race.

Verified locally, end-to-end

Built the probe, ran list-targets, seeded a throwaway $HOME, then ran a real direct baseline and real Seatbelt-confined scans (sandbox-exec, the same mechanism Claude/Codex use on macOS). The probe measured a genuine boundary — Seatbelt cut sensitive reads 31→5 and blocked network — and the site rendered the real baseline-vs-sandbox diff. build-site-data.mjs verified against a data-branch layout; new Go tests cover the registry/seedable classification.

Tests exercised in CI on first run (the deploy + data-branch creation can't be fully driven locally).

Depends on #40

The publish job deploys site/ (added in #40). Merge #40 first, or together.

Note

Real data surfaced a correctness bug in the site's renderer (empty-array findings counted as leaks) — fixed on the #40 branch, not here.

https://claude.ai/code/session_01PtFjYK8MdnDMmFYVWPDRrn

chrisns added 3 commits July 13, 2026 16:36
Static GitHub Pages report over the probe's data: a baseline-normalized
three-state comparison matrix, an exposure-over-time chart with version-release
markers, a per-capability heatmap, and an attributed flip-log — all derived
client-side from one concatenated reports file (dev fixture: sample-data.json).

Design intentionally left plain; this is the functional pass for a design
system to build on. Records the domain glossary (CONTEXT.md), the pipeline
decision (ADR 0001), and the build checklist (docs/reporting-site-plan.md).

Claude-Session: https://claude.ai/code/session_01PtFjYK8MdnDMmFYVWPDRrn
Makes the reporting site's data real and non-hollow (see docs/reporting-site-plan.md):

- probe `list-targets`: emits the probe's own sensitive-path registry as JSON,
  classified so a seeder knows what is safe to plant (home-scoped regular files
  only). Single source of truth — seeding can't drift from what is probed.
- scripts/seed-decoys.sh: soft-plants decoys at seedable targets (writes only
  where absent, never clobbers a real secret). Wired into scan-matrix before the
  probe runs, identically for the direct baseline and every harness — parity is
  what makes a diff mean "blocked" not "absent".
- aggregate & publish job: one job collects every scan's report, appends one
  immutable commit to the data branch, rebuilds the concatenated all-reports.json
  from the whole history (scripts/build-site-data.mjs), and deploys Pages. One
  commit, no 30-way push race.

Verified locally end-to-end: seeded home + real Seatbelt (sandbox-exec) runs
produce a real measured baseline-vs-sandbox diff the site renders.

Claude-Session: https://claude.ai/code/session_01PtFjYK8MdnDMmFYVWPDRrn
A probe task can run and find nothing, emitting the finding type with an empty
value (e.g. DNS blocked -> external_host_dns_resolution: []). The renderer
counted a present finding as a leak regardless, so a blocked capability rendered
as leaked. Caught against real Seatbelt data, where strict confinement zeroes
the network findings rather than dropping them. Gate on a non-empty value.

Claude-Session: https://claude.ai/code/session_01PtFjYK8MdnDMmFYVWPDRrn
@chrisns
chrisns marked this pull request as draft July 13, 2026 16:15
The seeder planted its decoy string into ~/.gitconfig, so every later git
operation on the runner failed with "fatal: bad config line 1", breaking the
trae install's `git clone` (exit 128). ~/.gitconfig is a content-predicate
target — the probe only reports it when it contains a [credential] section — so
a generic decoy never satisfies the predicate anyway; seeding it was pointless
and corrupting. Exclude contains!="" targets from Seedable. Verified by
reproducing the exact git-clone failure and confirming it clears.

Claude-Session: https://claude.ai/code/session_01PtFjYK8MdnDMmFYVWPDRrn
Ports colors, fonts, and dark-first rules from the ControlPlane Design
System project (Claude Design) into style.css by hand, since ADR 0001
keeps the site framework-free — no React/Tailwind bundle pulled in.
Charts in app.js now read the same CSS custom properties so they never
drift from the page theme.

Claude-Session: https://claude.ai/code/session_01QUYzKwJan4snRrbM6h5z41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant