Development record
abcd Routes The Invisible Risks An Amateur Cannot See To A Real, Fail-Closed Gate That Wraps A Trusted Scanner
Press Release
abcd gains a pluggable validation-gate framework: a new kind of discipline that wraps an unmodified external scanner, fails closed, and emits the same four-verdict result as the fidelity reviewer — shipped with security/dependency/secret scanning as its first instance, validating the downstream app the product thinker builds, not abcd's own pipeline. The amateur-coder thesis says the risks a non-expert cannot see — most acutely security — must be routed to a gate whose own reliability is validated. abcd has built the intent→verdict spine but left this safety pillar as an extension point. This intent fills it without violating abcd's core rule: it does not fork or reimplement a scanner, it configures and wraps a trusted one. The wrapping machinery is generic; a11y, privacy, and architecture become later instances of the same pluggable pattern. It runs as a standalone CLI across CI, pre-commit, and runtime hooks — no Claude Code dependency — so it works on a local machine.
"I can judge whether the app does what I asked. I cannot judge whether it just shipped an XSS hole or a leaking dependency — that's exactly the part I'm blind to," said Iris, a product thinker building a real app on abcd. "I don't want abcd to describe a safety gate. I want it to actually run a scanner on what I built and refuse to call it safe when it can't tell. And I want that to keep working when I'm not in Claude Code."
Why This Matters
The amateur-coder thesis is explicit: keep the human's sense of "good" as the limiting constraint, and route what lies beyond it — security above all — to automated gates whose reliability is itself validated. An external assessment (2026-06-26) found this is abcd's single largest gap against its own thesis: the process-protecting gates (gitleaks, PII, push-block) are real and fail-closed, but they protect abcd's own dev process. The "invisible risks" of the downstream app the amateur builds — security, dependency, secret exposure, later a11y/privacy/architecture — are documented as a pattern, not delivered as a gate. The empirical case is stark: a large fraction of AI-generated code ships at least one OWASP vulnerability. A framework targeting amateurs that does not route this to a gate is, by its own logic, incomplete.
Two abcd governing rules shape how this gets built. First, abcd never touches its dependencies — it wraps and configures unmodified trusted tools, it does not fork, patch, or reimplement them. A safety gate must wrap an existing scanner, not become one. Second, abcd must eventually run locally, independent of Claude Code. The gate is therefore a standalone CLI exposed across the three tiers abcd already uses (CI, pre-commit, runtime hooks), reusing the fidelity reviewer's fail-closed, four-verdict posture so it composes with the machinery already trusted rather than inventing a parallel one. Building it as a pluggable framework (security first) rather than a one-off scanner means the remaining invisible risks plug into the same validated mechanism.
What's In Scope
- A pluggable validation-gate framework: a new kind of discipline — framework-provided "validation disciplines" that wrap an external tool and fail closed — distinct from the existing app-authored disciplines. (Introducing this distinction is a brief change; per [[itd-60-doc-fidelity-anti-drift]] / [[itd-61-brief-change-derivation]] that brief change is itself governed by the doc-fidelity loop.)
- A first instance: security / dependency / secret scanning, wrapping an unmodified, trusted external scanner (never forked, never reimplemented), targeting the downstream app the product thinker builds.
- Standalone CLI as the primary entrypoint, invocable from CI, pre-commit, and runtime hooks — the same three-tier model abcd uses elsewhere — with no Claude Code dependency, so the gate runs on a local machine.
- Fail-closed, four-verdict wiring: the gate emits MET / MET_WITH_CONCERNS / NOT_MET / INCONCLUSIVE per check, refuses (never passes silently) when the scanner is unavailable or a trustworthy scan cannot complete, and feeds the existing receipt/roll-up shape — mirroring the native ship gate and the fidelity reviewer.
- Per-project configuration of which validation disciplines apply, consistent with abcd's "downstream apps configure" model.
- The first capability seam a repository fills for its own product (proposed 2026-11-01, to confirm at planning): the external checker is declared in data and pinned by checksum and signer, the way abcd pins the tools it downloads (adr-2610241057124151), and
build,drain,lintandlaunch shiphonour its verdict unchanged, so a project extends abcd's gates without forking abcd. The person admits a project's checker once before it runs on their machine (the product thinker's ruling of 2026-11-01): the yes is kept in their home, bound to the repository's root commit, the checker's checksum and signer, and the exact invocation and configuration the project declares, asked again when any of them changes, and refused from an agent as a person-act, since a program a repository names runs as the person and a repository cannot grant that capability itself. abcd never runs a foreign executable under its own name; the next seams of the same shape (oracle, history, runner host) follow only when a consumer needs them (adr-22).
What's Out of Scope
- a11y / privacy / architecture gates themselves. They are explicitly the later instances that motivate the pluggable design, but this intent ships only the framework + the security/dep/secret instance.
- Forking, patching, or reimplementing any scanner. Hard constraint. The gate wraps an unmodified upstream tool and configures it; if a wrap needs upstream behavior it lacks, that is a wrap/config problem, not a fork.
- A Claude-Code-only delivery. A CC skill frontend may exist as convenience later, but the local standalone CLI is the in-scope primary; shipping CC-only would violate the local-first requirement.
- Re-hardening abcd's own pipeline. abcd's process-protecting gates already exist; this intent targets the downstream app, not abcd's CI.
- Sequencing relative to itd-60/61 —
/abcd:intent plan's job, though note the brief-change dependency below.
Acceptance Criteria
Given-When-Then per the itd-1 discipline.
- Given a downstream app built with abcd, when the security validation gate runs, then it executes a wrapped, unmodified trusted scanner against the app and emits a per-check four-verdict result (MET / MET_WITH_CONCERNS / NOT_MET / INCONCLUSIVE).
- Given the configured scanner is unavailable or a trustworthy scan cannot complete, when the gate runs, then it refuses (fails closed) and never reports a silent pass.
- Given abcd's "never touch deps" rule, when the gate is implemented, then it wraps and configures the scanner without forking, patching, or reimplementing it.
- Given abcd's local-first requirement, when the gate is invoked outside Claude Code (CI / pre-commit / runtime hook via the standalone CLI), then it runs to a verdict with no Claude Code dependency.
- Given the pluggable framework, when a second risk type (e.g. a11y or privacy) is later added, then it plugs in as another validation discipline of the same kind without re-architecting the gate.
SOTA
Surveyed on 2026-10-23; sources, evidence tiers and the local fit risks are in the security-isolation SOTA note.
- The motivating figure is real, vendor-run and task-skewed: Veracode's 2025 report found OWASP Top 10 flaws in 45% of test cases (80 curated tasks run across more than 100 models), scored by the vendor's own analyser; Java over 70%, XSS 86%, log injection 88% (Veracode press release).
- Secret scanners are high-recall, low-precision, measured: Gitleaks precision 46%, recall 88%; TruffleHog recall 52%; GitHub's scanner precision 75%; false positives from "generic regular expressions and ineffective entropy calculation" (Basak et al., ESEM 2023, arXiv 2307.00714).
- Gitleaks: MIT,
git/dir/stdinmodes, SARIF output, exit 0/1, and "Gitleaks is feature complete. I'm not merging new features", security patches only, the maintainer "shifting my focus to Betterleaks" (same maintainers, MIT; its SARIF support not confirmed in this pass), so the swappable seam is load-bearing from day one and the first-scanner choice is revisited at plan time (gitleaks README). - TruffleHog: AGPL-3, and "it can also log in to confirm if that secret is live", calling the provider with the found credential; outside a local-first default (trufflehog README).
- OSV-Scanner for dependencies: Go, Apache-2.0, "19+ lockfile types", container images, and an offline mode after one database download (osv-scanner README).
- SARIF 2.1.0 (OASIS Standard) is the one interchange shape with
result,fingerprintsandsuppressionobjects; the candidate scanners all emit it (SARIF 2.1.0). - Gates get ignored for presentation as much as precision: twenty developers named "false positives and the way in which the warnings are presented" as the barriers (Johnson et al., ICSE 2013).
- The local seam exists:
adapter/scannerfails closed and treats external scanners as "config-selected plug-ins behind the same seam" (internal/README.md).
Path 1: adopt gitleaks and OSV-Scanner as the first wrapped scanners, executed on PATH and never imported, with SARIF 2.1.0 the only shape the gate parses; a scanner missing or unparsable is INCONCLUSIVE. No Go dependency. The confirm-and-record flow of itd-2610071545369520 is what keeps a 46%-precision gate from being ignored. The independent fit-challenge runs at plan time.
Open Questions
- Which scanner(s) to wrap first for the security/dep/secret instance, and how to keep the choice swappable (the wrap must not bind abcd to one vendor)?
- Does a framework-provided validation discipline become a baseline every abcd project inherits (opt-out) or a configured opt-in? The brief currently says downstream apps author their own disciplines; the chosen answer is "two kinds" (framework-provided vs app-authored), and the opt-in/opt-out default is still open.
- How does the gate identify "the downstream app" to scan — by abcd project structure, an explicit target path, or configuration?
- Where does the four-verdict output feed — a new receipt type, the existing review-artifact pipeline, or acceptance evidence the fidelity reviewer consumes?
- Provenance/dependency: introducing the "validation discipline" kind edits the brief, which [[itd-61-brief-change-derivation]] would govern — does this intent wait on the doc-fidelity pair, or proceed and let them reconcile? (A
/abcd:intent plansequencing question.)
Audit Notes
Empty. Populated by intent-fidelity-reviewer when intent moves to shipped/.
References
- [[itd-63-setup-wizard-explains-installs]] names this gate's missing-scanner refusal as its consumer (criterion 4): the refusal calls
tools.Missingfor the explanation andtools.Installon an explicit yes, never a bare install command. - Originating assessment: an internal comparative assessment (2026-06-26, recorded in the sources ledger) — names the safety pillar as abcd's largest gap against the amateur-coder thesis, and identifies the transplantable mechanisms in the companion harness.
- Governing constraints: abcd never forks/patches/reimplements a dependency (wrap + configure only); abcd must run locally, independent of Claude Code.
- Reuses the fail-closed, four-verdict posture of the fidelity reviewer of spc-12 (predecessor store) and the native ship gate (scanner-unavailable → refuse, never silent pass).
- Brief-change dependency: introducing framework-provided "validation disciplines" alongside the existing app-authored disciplines is a brief edit governed by [[itd-60-doc-fidelity-anti-drift]] / [[itd-61-brief-change-derivation]].
- Existing disciplines for contrast:
intents/disciplines/(itd-1-acceptance-gates, itd-5-prompt-quality, itd-37-modification-grammar) — all app-process disciplines, none a validation gate.
Frontmatter
| id | itd-62 |
|---|---|
| type | intent |
| lifecycle | drafts |
| severity | major |
.abcd/development/intents/drafts/itd-62-pluggable-safety-gate.md
open on GitHub ↗ · commit history ↗
References2
Referenced by5
- adr-2611011813195749abcd never runs a foreign executable under its own name, and no code that writes records is loaded at run timerelated
- iss-84Managed pre-commit gates: the interim prepare-this-repo skill offers the secrets and absolute-path pre-commit config from a private template directory outside the repo. The gate belongs to the configuration layer itself: a core-owned surface should install and maintain commit gates in managed repos, replacing the template copy. Seeded from the scaffold-repo retirement analysis; relates to the pluggable safety gate draft (itd-62).related
- iss-2610262033027180itd-62 calls CI, pre-commit and runtime hooks 'the same three-tier model abcd uses elsewhere'; on the ahoy page, the three tiers are the .abcd/ record layout.related
- itd-63The Amateur Coder Is Told What Is Being Installed And Why, Not Just Asked To Run A Commandbuilt on by
- itd-2609291923559186The consistency pass runs where records are written and names each finding the same way every timerelated
mentions16
- adr-22Bundled dependencies become pluggable adapters over a native default
- adr-2610241057124151abcd installs the tools it needs from downloads pinned in its own release
- dcn-26092900000000112026-09-29 — The product thinker answered the twenty-six Group J rulings (plan or close), J1 to J26 (recorded by lane recGroupJ of autonomous run A, for orchestrator abcd-fc). The answers are kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29.md`, section "Group J", dated 2026-09-29, and are restated here because that file is not committed. PLAN: the installer script becomes a minimal starter with an ownership-checked hand-over, planned as a new intent with its planning interview owed (J2, iss-377, draft itd-2609292106557115); token metering and size classes are planned as one intent (J3, iss-2608301744251874 and iss-2608301856299268), and session token accounting in the history store joins that metering intent (J4, iss-2608220150157508; all three in draft itd-2609292107351737); the sources tooling moves into abcd's core with ingest and consult as abcd verbs (J5, iss-27, whose corpus half itd-76 already delivered), and the backfill of the placeholder source entries is part of that intent (J6, iss-55; both in draft itd-2609292108089653); the grill hands off to an installed external interview skill and falls back to its own (J11, iss-165, draft itd-2609292108373494); an opt-in local-model prompt sanitiser is planned (J14, iss-2608261543489261, draft itd-2609292109005937); decision-to-transcript links are planned, with the anchor kind and the link's home settled in the planning interview owed for draft itd-171 (J16, iss-2608290819228175); the dredge synthesis, its write-ups as their own memory source class, is planned together with draft itd-25, whose planning interview is owed (J19, iss-2609211905340006); one provenance register across ingest and vendoring is planned together with draft itd-26, whose planning interview is owed (J20, iss-2609211905346507); release retention, keeping the newest release per version line, is automated by planning draft itd-70 (J21, iss-282); a rules-backend seam with an opt-in CARL adapter is planned, the native loader staying the default (J22, iss-64, draft itd-2609292109214516); core-owned managed pre-commit gates are planned with draft itd-62 (J23, iss-84); a behavioural end-to-end scenario suite per verb family is planned (J24, iss-48, draft itd-2609292109475690). Every draft stays in drafts/ until a person plans it, and each source issue links its draft and names that planning interview in its deferral. BUILD: the teaching plane, the rules-loader safety domain generated from the hazard registry, is built as a lane, the registry being the single source (J10, iss-151 and itd-103; a code lane owns it). RULED DETAILS: `source_kind` carries both, as two separate labels, one for the tool and one for the route (J13, iss-2608230752354928); the prompt router's removal signal is the full list of active domains every time, a domain's absence meaning it has stopped (J15, iss-2608261550580260); setup offers an outside AI service (for example OpenRouter) at install, skippable, once the API adapter ships (J18, iss-2609081951416843, which waits on the API adapter); the salvage-hook timeout is 120 seconds, the wait must show a counter or a message while it runs and never stall silently, and every per-event timeout is pinned in a test (J25, iss-323). J13, J15 and J25 are carried by code lanes. CLOSE: the quick-tunnel preview protocol is closed unless the need recurs (J26, iss-2608230617385431, wontfix with that reason). PARKED ON A TRIGGER: agent payment protocols are kept under watch, not now, revisited as the protocols mature (J8, iss-138); the findings-only skill waits for the skill format to be versioned and stewarded (J9, iss-139); the disposition worksheet as an intent and a site page waits until after the first study (J17, iss-2609021815529020). DECIDE LATER: the Homebrew tap stays parked (J1, iss-380); pluggable search back ends (J7, iss-26); forge-backed record numbering (J12, iss-2608210737264758).
- dcn-26092900000000202026-09-29 — The product thinker answered the twenty-six Group J rulings (plan or close), J1 to J26 (recorded by lane recGroupJ of autonomous run A, for orchestrator abcd-fc). The answers are kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29.md`, section "Group J", dated 2026-09-29, and are restated here because that file is not committed. PLAN: the installer script becomes a minimal starter with an ownership-checked hand-over, planned as a new intent with its planning interview owed (J2, iss-377, draft itd-2609292106557115); token metering and size classes are planned as one intent (J3, iss-2608301744251874 and iss-2608301856299268), and session token accounting in the history store joins that metering intent (J4, iss-2608220150157508; all three in draft itd-2609292107351737); the sources tooling moves into abcd's core with ingest and consult as abcd verbs (J5, iss-27, whose corpus half itd-76 already delivered), and the backfill of the placeholder source entries is part of that intent (J6, iss-55; both in draft itd-2609292108089653); the grill hands off to an installed external interview skill and falls back to its own (J11, iss-165, draft itd-2609292108373494); an opt-in local-model prompt sanitiser is planned (J14, iss-2608261543489261, draft itd-2609292109005937); decision-to-transcript links are planned, with the anchor kind and the link's home settled in the planning interview owed for draft itd-171 (J16, iss-2608290819228175); the dredge synthesis, its write-ups as their own memory source class, is planned together with draft itd-25, whose planning interview is owed (J19, iss-2609211905340006); one provenance register across ingest and vendoring is planned together with draft itd-26, whose planning interview is owed (J20, iss-2609211905346507); release retention, keeping the newest release per version line, is automated by planning draft itd-70 (J21, iss-282); a rules-backend seam with an opt-in CARL adapter is planned, the native loader staying the default (J22, iss-64, draft itd-2609292109214516); core-owned managed pre-commit gates are planned with draft itd-62 (J23, iss-84); a behavioural end-to-end scenario suite per verb family is planned (J24, iss-48, draft itd-2609292109475690). Every draft stays in drafts/ until a person plans it, and each source issue links its draft and names that planning interview in its deferral. BUILD: the teaching plane, the rules-loader safety domain generated from the hazard registry, is built as a lane, the registry being the single source (J10, iss-151 and itd-103; a code lane owns it). RULED DETAILS: `source_kind` carries both, as two separate labels, one for the tool and one for the route (J13, iss-2608230752354928); the prompt router's removal signal is the full list of active domains every time, a domain's absence meaning it has stopped (J15, iss-2608261550580260); setup offers an outside AI service (for example OpenRouter) at install, skippable, once the API adapter ships (J18, iss-2609081951416843, which waits on the API adapter); the salvage-hook timeout is 120 seconds, the wait must show a counter or a message while it runs and never stall silently, and every per-event timeout is pinned in a test (J25, iss-323). J13, J15 and J25 are carried by code lanes. CLOSE: the quick-tunnel preview protocol is closed unless the need recurs (J26, iss-2608230617385431, wontfix with that reason). PARKED ON A TRIGGER: agent payment protocols are kept under watch, not now, revisited as the protocols mature (J8, iss-138); the findings-only skill waits for the skill format to be versioned and stewarded (J9, iss-139); the disposition worksheet as an intent and a site page waits until after the first study (J17, iss-2609021815529020). DECIDE LATER: the Homebrew tap stays parked (J1, iss-380); pluggable search back ends (J7, iss-26); forge-backed record numbering (J12, iss-2608210737264758).
- dcn-26100200000000022026-10-02 — The consistency pass follow-ups are planned as one intent (itd-2609291923559186, spc-2610021456200324, impact additive) after two adversarial reviews and a planning interview with the product thinker and technical facilitator, asked one at a time. Rulings: A3 stays in this intent, though iss-2609260926323349's body had routed it to the shipped itd-34; A4 stays and builds its own overflow signal; the pre-commit gate runs the rule checks on every commit and the model pass only where the owner's personal settings provide a route, marking it owed otherwise, and never refuses a commit on a judgement it could not obtain; what the gate does on a finding (warn, stop, or automatic: fix the obvious and file the rest) is asked at setup; the rule checks cover the whole corpus and the model pass covers the staged records and their links; the gate waits for the core-owned managed pre-commit gates (iss-84 with itd-62, ruling J23); G1 lands first; the new A1 codes are warnings, and the 136 one-way `builds_on` edges that exist when the rule lands are baselined, so only new ones are flagged. The 10 acceptance criteria are the product thinker's. Grounds: "pursued: contradictions get into the records unnoticed and are answered twice, and unattended runs write records with no one checking them for contradictions; wrong if, after it ships, the same contradiction is still filed twice, a rule-catchable one still gets in, or an unattended run still lands a contradiction the check covers."
- iss-2609281911015826itd-63 criterion 4 (the safety gate's missing-scanner case routes through the explain-then-install mode) is NOT_MET at ceb4b6dbb: no safety gate exists on main, itd-62 (pluggable-safety-gate) is still in intents/drafts/, so nothing surfaces the prerequisite the criterion names. The spec's close note substitutes the history store's armed-gitleaks refusal (internal/core/history/history.go calls tools.Missing), which is transcript capture, not the gate. The shipped record names a first consumer that does not exist; when itd-62 is planned its missing-scanner path must call tools.Missing/tools.Install rather than print a bare command, and itd-63's References/Why should stop asserting that the safety gate already blocks on a missing scanner.
- iss-2610262030559592The mental model calls the itd-60 doc-fidelity loop planned and not yet exercised; the docs chapter describes the itd-60 doc-fidelity gate as a working gate in the present tense.
- itd-1Every Intent Has Acceptance Criteria; Every Audit Verifies Them
- itd-5Every Agent Prompt Carries Its Version, Earns Its Lock, And Survives Injection
- itd-37Every Spec Externalises How It Should And Shouldn't Be Modified
- itd-64abcd Learns From Its Own Runs Which Configurations Work Best, And Tunes Its Configuration Layer Accordingly
- itd-65abcd Refuses To Publish A Payload Until The Full Ship-Time Pre-Flight Gate Suite Passes, Not Just The Secret Scan
- itd-2610071545369520A person confirms the assistant's verdict on each warned banned-name line instead of judging it alone
- spc-12disembark-grounds-a-lifeboat-s-open-questions-on-a-repo-s-to
- spc-2609211955339422setup-wizard-explains-installs
- spc-2610021456200324The consistency pass at commit time: a stable finding key, cross-document lint codes, chunked review, and a pre-commit gate