chore(ci): doc-link integrity + secret/host-leak guards in the test gate (#130)#131
Merged
Conversation
… gate (#130) The #129 doc cleanup surfaced two defect classes CI never caught: a real host name (nas-5sgf) committed in tests/README.md, and no verification that the .md hierarchy's internal links/anchors resolve. Both are cheap to catch mechanically. - tests/lib/md_link_check.py + test-doc-links.sh: offline resolver for every internal Markdown link + #anchor across all tracked .md (GitHub-slug compatible; honors <a name>/id=). Fails on any broken path or dead anchor. - tests/lib/secret_scan.py + test-secrets.sh + secrets-allowlist.txt: offline scan that fails on a tracked .env/private-key, a concrete RFC1918 private IP, a private-TLD host (.local/.lan/...), or a bare single-label URL host (the nas-5sgf class). Public dotted domains, loopback, and $/{}/<> placeholders pass; reviewed exceptions live in the allowlist (a ratchet — new leaks still fail). - Both auto-discovered by run-all.sh's test-*.sh glob (gate locally + in CI) and run as a fail-fast CI step BEFORE the Playwright browser install. - Proven by negative tests: catches nas-5sgf, a private IP, an .internal FQDN, a tracked .env, and a .pem; passes github.com/localhost/redis/placeholders. - Docs: tests/AGENTS.md (+ allowlist gotcha), tests/README.md, decisions.md entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review of #131 caught that the new files re-committed the very host name #129 scrubbed (in secret_scan.py's docstring incl. the full URL form, test-secrets.sh, and the decisions.md entry) — and the scanner couldn't self-catch it (own files SKIP_EXACT'd; the prose mention had no scheme). Removed all four; git grep clean. Hardening from the same review's non-blocking findings (all zero-FP on the tree, negative-tested): - secret_scan: URL_HOST_RE now covers DB/queue/socket schemes (redis/postgres/mongodb/amqp/mysql/mqtt/ws(s)) — a real host in a connection string is the same leak class; bracketed IPv6 literals survive capture and a private ULA (fc00::/fd00::) in a URL host is flagged (public IPv6 passes). - secret_scan: prefixed *.env files (production.env) now caught, matching the docstring; example/sample/template/dist env files stay exempt. - secret_scan: high-signal inline content secrets — private-key bodies and AWS access-key ids — in any tracked text file. - md_link_check: reference-style links `[text][label]` (defined labels only, so incidental `[x][y]` prose is ignored), internal `<a href>`, and `?query` stripping so `real.md?v=1#frag` resolves. Both guards remain 0-FP across 63 .md files; decisions.md stays a pure prepend. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bidOnly (#132) The escattr-sweep catalog test intermittently failed CI (run 29987925904: .catalog-card not found in 10s) though it passes on dev and #131 touches no UI/spec code — a genuine flake from the SPA's async render timing (root cause tracked in #132: loadCatalog fires once per route with no retry on a transient no-op). Add `retries: process.env.CI ? 2 : 0` so a real regression still fails every attempt while a transient flake self-heals, and `forbidOnly` so a stray `.only` can't silently green-light a partial CI run. This is resilience, not a mask — #132 tracks the product-side fix. Config validated (387 tests list, exit 0). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #130.
Why
The #129 doc-hierarchy cleanup exposed two defect classes current CI never caught:
nas-5sgf) sat committed intests/README.mdand passed every run — a Prime-Directive-1 miss on a public repo..mdhierarchy's internal links/anchors actually resolve — the docs: map + interconnect the .md hierarchy, AGENTS.md per folder, readability #129 review had to hand-build a resolver.Both are cheap to catch mechanically and expensive to catch by eye. This adds them to the gate and hardens the CI process.
What
Two offline
test-*.shvalidators, auto-discovered byrun-all.sh'stest-*.shglob (so they gate locally and in CI), plus a fast-fail CI step:tests/lib/md_link_check.py+test-doc-links.sh— resolves every internal Markdown link and#anchoracross all tracked.md(GitHub-slug compatible; strips fenced/inline code; honors<a name>/id=). Fails on any broken path or dead anchor. External URL liveness stays intest-urls.sh.tests/lib/secret_scan.py+test-secrets.sh+secrets-allowlist.txt— fails on: a tracked.env/private-key file; a concrete RFC1918 private IP; a private-TLD host (.local/.lan/.internal/…); or a bare single-label URL host (thenas-5sgfclass). Public dotted domains, loopback, and$/{}/<>placeholders pass automatically. Reviewed exceptions live in the allowlist — a ratchet: any new leak still fails..github/workflows/ci.yml— runs both guards as a fail-fast step (python3-only, preinstalled) before the multi-minute Playwright browser install, so a leak/broken-link fails in seconds.Proof it works (not a checker that never fails)
#anchor, and a broken image; passes valid links; slug matches GitHub (Community & Comms→community--comms, emphasis stripped, U+2011 dropped). It also caught my own wrong anchor in the newdecisions.mdentry.http://nas-5sgf:3000,192.168.4.73(both paths),ssh://buildbox.internal, a tracked.env, and a.pem; passesgithub.com/localhost/redis/your-ark-host..mdfiles); every allowlist entry is a reviewed doc example, protocol constant, or test fixture.Docs
tests/AGENTS.md(+ an allowlist gotcha: fix the leak, not the test),tests/README.md, and adocs/knowledge/decisions.mdentry (prepend; body unchanged).🤖 Generated with Claude Code