Status: all owner decisions approved; implementation authorized
Prepared: 2026-08-30
Repository baseline: 1cc9282546224a263ff5885db12b583b8ad10aae
Published release source: v0.8.0 -> 119cbcc7f8d327482df8abfa50a4af0b69fcceee
External audit input:
web-app-security-skill-audit.zh-CN.md, SHA-256
4c81aefa04e1345f2f0b09d0618c363069dba52d6d2c750f3b2b00ad34e8ed38
This is the canonical execution plan for v0.8.1. Every completed phase must append an evidence log to section 21 before the next phase starts. The plan may be refined when a fixture disproves an assumption, but a finding may not be silently removed, downgraded or declared fixed.
v0.8.1 is a correctness and trust-boundary patch. It must make the existing product contract true in six places:
- the recorded source roots and exclusions constrain every scanner that claims to use them;
- intentional fixtures and reviewed benign matches have a narrow, expiring, visible disposition path without changing their evidence state;
- the repository can audit its production code without fixture noise hiding real findings;
- Node workspace export resolution and evidence redaction preserve the values their contracts say they preserve;
- a GitHub Release cannot be created by the release workflow before the immutable tag and trusted
signer are verified against policy sourced from protected
main; - CodeQL, Dependabot and historical workflow failures have explicit ownership and disposition instead of an unexplained green or red dashboard.
The release is not a detector-count release. No new vulnerability family is counted toward the stable capability total.
After v0.8.1:
- if a user says "scan only these folders", the tool scans only those folders or says which selected adapter cannot honor that boundary;
- if a known test fixture intentionally looks vulnerable, the report still records it but can keep it out of the blocking total through a reviewable, exact suppression;
- changing or expiring that suppression makes the finding active again;
- a numeric AI usage count such as
usage.tokens: 17remains17, while an actual access token remains redacted; - valid Node package export mappings with repeated right-hand-side
*placeholders resolve as Node documents them; - unsigned, wrongly signed or wrong-commit release tags stop before write-capable publication;
- moving
v1no longer creates a predictable generic-CI red window; - open platform alerts are fixed or explicitly classified, never merely ignored.
- the full external audit named above;
- current
mainsource, workflow, schemas, capability contract and v0.8.0 engineering record; - all public GitHub Issues, open and closed, numbers 1 through 7;
- all ten open CodeQL alerts visible on 2026-08-30;
- repository branch protection, rulesets, environments and security-analysis settings;
- recent failed GitHub Actions runs, with the two reported
v1failures reproduced from logs; - focused, read-only source-audit and redaction reproductions on the repository itself;
- official Node subpath-pattern language for repeated right-hand-side wildcard replacement;
- current TypeScript alias validation in the implementation.
confirmed: the repository source, platform API or a focused reproducer demonstrates the fact;suspected: a credible gap exists, but the causal path or supported input has not been proved;unknown: required platform/runtime evidence is unavailable;not_applicable: the condition is outside v0.8.1's accepted boundary.
A governance absence can be confirmed even when an exploit chain is only conditional. For example, the lack of branch protection is confirmed; compromise of a maintainer account is not.
The plan deliberately avoids repeating the complete matrix after every small edit:
- each implementation phase runs only the directly affected tests and syntax/schema checks;
- each silent-regression fix gets one planted-failure demonstration;
- the final frozen candidate runs
npm run checkonce; - if that candidate changes after a failure, the replacement candidate runs the full check once;
- the hosted four-job Node/macOS/Ubuntu matrix runs once on the pushed candidate;
- pinned real adapters run only in the existing Ubuntu/Node 22 hosted job unless a focused local adapter reproducer is necessary;
- live GitHub/npm/installer/Action verification runs only after immutable publication.
| ID | Priority | State | Finding | v0.8.1 disposition |
|---|---|---|---|---|
| C-01 | P0 conditional | confirmed governance gap | main has no branch protection, ruleset or release environment; v1 is movable |
Add minimum branch/tag rules and a release environment after D3. Do not claim account-compromise prevention. |
| C-02 | P0 | confirmed | tag-triggered release has write/attestation permissions and never calls cryptographic git verify-tag before publication |
Replace tag-triggered publication with trusted-main dispatch, trusted signer verification and split permissions. |
| C-03 | P0 | confirmed | sourceRoots and excludedDirectories are recorded and hashed but are not passed to built-in or external scans |
Implement one canonical scope predicate and adapter-specific fail-closed scope handling. |
| C-04 | P0 | confirmed | default self-scan reports 14 findings, including intentional fixtures and one benign rule-registry match, with no structured suppression | Ship narrow suppression/disposition and a production-only self-audit gate. |
| C-05 | P0 | confirmed | Node exports RHS replaces only the first *, contrary to Node's all-instance replacement rule |
Replace every RHS wildcard literally and add adversarial path tests. |
| C-06 | P1 | confirmed | ten CodeQL alerts are open and Dependabot alerts/security updates are disabled | Fix production alerts, disposition test alerts, accept an owner policy, then inventory dependency alerts. |
| C-07 | P1 | confirmed | numeric usage.tokens becomes [REDACTED] |
Make redaction type- and key-aware without weakening credential cleaning. |
| C-08 | P1 | confirmed failure; cause bounded | repeated v1 promotions trigger generic CI while the moving tag and recorded stable state temporarily disagree |
Separate local consistency from live promotion verification and stop generic CI from running on moving tags. Do not label this a race without further proof. |
| A-01 | P0 support | confirmed | scope boundary arrays are not structurally validated beyond their digest | Validate path grammar, duplicates, limits, roots, exclusions and symlink behavior before execution. |
| A-02 | P1 | confirmed | TypeScript path targets are limited to at most one wildcard, so CodeQL alert 9 is not the same bug as C-05 | Refactor to a one-wildcard literal helper or dismiss only after the invariant is machine-proved. Never apply Node replaceAll semantics mechanically. |
| A-03 | P1 review | suspected capability gap | Node conditional export traversal recognizes only import, default, require and types |
Plant node/custom-condition fixtures. If one exact source target can be retained, fix; otherwise fail closed and document the condition boundary. |
| A-04 | P1 | confirmed | secret scanning and push protection are already enabled, but Issue 7's title/body still describe pre-enable work | Correct the issue record; only Dependabot enablement and alert ownership remain undecided. |
| A-05 | P2 | confirmed | Issue 3 says the compatibility table claims WSL2 support, while the current table explicitly says unsupported | Keep the issue open as future verification work; do not invent a WSL2 pass for v0.8.1. |
Current orchestration sends the whole project root to both scanner families:
scripts/project-audit.mjs:223-230invokesauditSource(projectRoot, ...)andrunExternalAdapters(projectRoot, ...)without the recorded roots/exclusions;scripts/lib/source-audit.mjs:13-17owns a hard-codedIGNOREDset;scripts/lib/source-audit.mjs:383-385accepts a root and limits but no scope policy;scripts/lib/external-adapters.mjsindependently hard-codes roots and excludes for each adapter;scripts/lib/project-identity.mjs:180-213validates the digest but does not validate or apply the two boundary arrays.
The default arrays currently resemble the hard-coded values. That accidental agreement does not make the persisted contract operational and does not cover a modified, narrower scope.
The built-in source audit at the frozen baseline emits 14 findings:
- four
confirmed: two tracked.env.productionfixtures and two fixture manifests without a lockfile; - nine
suspected: intentional quickstart/insecure-demo/test patterns plus onecors-wildcard-with-credentialsmatch inscripts/lib/source-rule-registry.mjs:354; - one
unknown: incomplete route evidence caused by the mixed full-repository surface; - four HIGH, eight MEDIUM and two LOW severities.
This result is not evidence that the released tool has four confirmed vulnerabilities. It is evidence that the repository has no first-class way to separate production code, deliberate vulnerable examples and reviewed benign scanner matches.
scripts/lib/js-ts-module-graph.mjs:541-545 uses target.replace('*', wildcard) for Node package
exports. Official Node documentation states that every * on the right-hand side is replaced.
The TypeScript path branch at line 499 is different: config parsing at lines 186-197 rejects both patterns and targets with more than one wildcard. It needs an explicit one-wildcard implementation, not the Node multi-wildcard fix copied blindly.
The focused result is:
{"usage":{"tokens":"[REDACTED]","inputTokens":8},"accessToken":"[REDACTED]"}scripts/lib/evidence-writer.mjs:22-45 singularizes tokens to token, and lines 84-95 redact
non-string scalars under a secret-looking key. This protects credentials but corrupts a common
numeric usage counter.
.github/workflows/release.yml:2-9is triggered by a SemVer tag and grants write, ID-token and attestation permissions to the workflow;- lines 21-27 check version and files but do not cryptographically verify the tag;
gh release create --verify-tagat lines 48-57 verifies that the tag exists, not its SSH/GPG signer;- signer policy read from a tag checkout would be attacker-controlled if the attacker can also
select the tag commit, so the trusted policy must come from protected
mainor another immutable trust root; - generic CI currently uses
on: [push, pull_request], so a forcedv1tag update starts the full matrix; - failed runs
33265040656and32980990347both stopped onv1 differs from the recorded stable Action source commit; older promotions show the same class of failure.
The repeated failures prove an exposed intermediate-state invariant. They do not by themselves prove concurrent writers or a timing race.
- canonical scope compilation and validation;
- built-in, route, diff and external-adapter scope enforcement;
- visible, exact suppression/disposition;
- report/schema/renderer/gate/baseline integration for suppression;
- production-only repository self-audit;
- Node export replacement and bounded conditional-export review;
- type-aware redaction correction;
- release signer gate and least-privilege job split;
- explicit
v1promotion lifecycle and live-state verification; - CodeQL disposition, Dependabot decision and Issue 7 owner policy;
- checksum-pinned ShellCheck if D5 is approved;
- synchronized version, capability, limitation and release documentation.
- new secret, XSS, SQLi, authz or
security.txtdetector families; - MCP or a remote service;
- Strix or another scanner-as-a-service dependency;
- authenticated DAST or automatic exploitation;
- production precision/recall claims;
- a new ORM/framework/language family;
- arbitrary code-coverage percentages;
- claiming WSL2 support without a clean maintained runner;
- requiring a second reviewer when the repository still has one maintainer;
- rewriting all release infrastructure only to improve ceremony metrics.
Add one module that compiles the persisted boundary into an immutable policy object. Its public operations must be sufficient for all consumers:
compileAuditScope(projectRoot, auditBoundary)
-> roots
-> excludedDirectoryNames
-> includes(relativePath)
-> classify(relativePath)
-> governingInputs(manifests, lockfiles)
-> scopeDigest
No scanner may rebuild the policy from a separate hard-coded list.
Before reading target files:
sourceRootsis a non-empty bounded array of unique POSIX-relative paths;.is allowed; absolute paths, backslashes, NUL/control bytes, empty segments and..are rejected;- each root resolves lexically and physically inside
projectRoot; - a missing, unreadable or symlink root becomes an explicit scope error or unavailable coverage, never a clean scan;
- overlapping roots are de-duplicated without double-counting coverage;
excludedDirectoriesis a bounded unique array of directory basenames, not path globs;.gitand.webapp-securityremain mandatory engine-safety exclusions even if omitted by a hand-edited scope; the report distinguishes mandatory and user-recorded exclusions;- every normalized boundary used by execution is the same value used for
scopeDigest.
The recommended D1 decision is that scope is a file-read boundary, not merely an output filter. Under that decision:
- excluded files are not opened by the built-in analyzer;
- route/access analysis receives only parsed files admitted by the same policy;
- tracked-sensitive-env Git queries use pathspecs for admitted roots and post-validate every path;
- diff snapshots preserve repository-relative layout and then apply the same policy;
- coverage records excluded, missing and unavailable roots with reason codes;
- paths outside scope cannot appear in findings, patches, route artifacts or sampled coverage reasons;
- discovery may identify the repository layout, but it may not upgrade out-of-scope source to scanned evidence.
Root workspace metadata may govern a nested source root. Therefore a manifest/lockfile input is eligible only when it is:
- inside an admitted source root; or
- an ancestor-level recorded project/workspace input that governs at least one admitted root;
- not inside an excluded directory;
- contained by lexical and realpath checks.
The report must identify these as governing_input, rather than pretending they were ordinary
source files inside the root.
- a v0.8.0 scope with the exact generated default boundary remains comparable because its effective built-in exclusion behavior is unchanged;
- a pre-v0.8.1 baseline with a non-default boundary is
not_comparable / scope_enforcement_changed, because the previous run did not prove that boundary; - a changed root or exclusion still changes
scopeDigestand requires a new baseline; - scope migration never rewrites an old report or calls its excluded paths scanned.
| Adapter | v0.8.1 scope behavior | Failure boundary |
|---|---|---|
| Checkov | Build its exact Dockerfile/workflow input list through the canonical predicate; verify every returned path is in that list | No eligible input -> not_applicable; unexpected returned path -> unknown, not filtered success |
| OSV-Scanner | Pass only admitted/governing lockfiles after lexical and realpath containment | Excluded or escaping lockfile is not scanned; invalid recorded inputs make coverage unavailable |
| Opengrep | Scan a private, deterministic, path-preserving scoped snapshot or an equivalently exact supported target list | If exact file-read scoping cannot be proved, do not run broader and post-filter; return scope_not_supported unknown |
| Gitleaks working tree | Use an exact scoped snapshot with no Git history and map paths back to the project | Excluded content must not be read merely to discard its finding |
| Gitleaks history | Preserve current full-repository behavior only for the default full scope | A restricted custom scope is unknown / history_scope_not_supported until a pinned version can prove an exact history path boundary |
Every adapter result records scopeMode (full, scoped_snapshot, governing_inputs or
unsupported) in report scope metadata. A selected adapter that cannot honor a restricted scope
must contribute unknown evidence and exit 3 under the current precedence. Missing capability may
not become zero findings.
Suppression is a policy disposition, not a fifth evidence state. A suppressed suspected finding
remains suspected; a suppressed confirmed finding remains confirmed. Reports and baselines retain
the finding and its fingerprint.
Use a repository-root JSON file, proposed name webapp-security.suppressions.json:
{
"schemaVersion": 1,
"subjectId": "project-...",
"entries": [
{
"id": "suppression-...",
"adapterId": "builtin",
"ruleId": "cors-wildcard-with-credentials",
"path": "scripts/lib/source-rule-registry.mjs",
"fingerprint": "<64 lowercase hex>",
"reason": "Rule metadata contains the safe near-neighbour text used by the detector corpus.",
"owner": "@parousia8888",
"createdAt": "<RFC3339>",
"expiresAt": "<RFC3339>"
}
]
}- reject symlinks, paths outside the target, files over a small documented size and duplicate IDs;
- reject unknown fields, malformed timestamps, expiry before creation and control characters;
- require exact adapter, rule, relative path and fingerprint match;
- any path, rule revision or evidence fingerprint drift invalidates the entry;
- an expired entry is retained in diagnostics but does not suppress;
- a malformed file makes suppression coverage unavailable and cannot weaken the gate;
unknownandevidence_integrityfindings are never suppressible;- reasons are sanitized before rendering and never interpreted as code;
- suppression cannot change coverage status, baseline state or
fixedclassification; - a broad rule-only or directory-wide allowlist is not accepted in v0.8.1.
Recommended D2 decision:
reasonis always required;ownerandexpiresAtmay be omitted for a local evidence-only report;- both become mandatory when a suppression affects a CI/release gate;
- external-adapter suppressions always require owner and expiry, matching
docs/alert-policy.md.
Add an optional additive v3 finding disposition object and summary counts:
disposition.status:activeorsuppressed;- suppression ID, reason, owner and expiry only when valid and sanitized;
summary.activeTotal,summary.suppressedTotalandsummary.byDisposition;- existing
summary.totaland state/severity/domain counts continue to describe all retained findings; - Markdown/HTML place a visible
SUPPRESSEDlabel and expiry beside the finding; - SARIF uses the standard external suppression shape and keeps the result;
- JUnit represents a valid suppression as skipped, not passed;
- JSON is the source of truth for every renderer.
The gate evaluates active findings only. Incomplete/unknown evidence remains non-suppressible and keeps exit 3. Removing or expiring a suppression can make an unchanged finding block again.
- adding suppression does not make a baseline finding
fixed; - removing suppression does not make it
newif its evidence fingerprint is unchanged; - an absent finding becomes
fixedonly after completed comparable coverage; - moved-condition matching happens before disposition and keeps current v3 identity semantics;
- suppression-file changes are recorded in report scope/policy digest but do not rewrite the source evidence fingerprint.
Add one documented, deterministic repository self-audit with these surfaces:
- production source and runtime packaging files are in scope;
test, intentional vulnerableexamples, generated adoption material and release archives are explicitly excluded and counted;- root manifests/workflows remain governing inputs where applicable;
- the rule-registry benign match receives one exact suppression only if a focused review confirms the path/fingerprint on the final scope;
- no unknown/evidence-integrity result may be suppressed;
- CI fails on an active HIGH or above finding and on incomplete evidence;
- all suppressed findings remain in an uploaded report artifact;
- the gate runs without network and without external adapters.
The first clean self-audit is a regression fixture for scope and suppression. It is not a claim that the project has no vulnerabilities.
Use literal callback replacement or an equivalent slice-based helper so wildcard text containing
$&, $1, $$ or path separators is never interpreted as JavaScript replacement syntax.
Required cases:
- zero wildcard RHS;
- one wildcard RHS;
- two or more RHS wildcards all receiving the exact captured subpath;
- conditional export object and array fallback;
- captured value containing
/,$and dotted filenames; - null/private export targets;
- result escaping the workspace root;
- one exact resolution, multiple resolution ambiguity and missing target.
Keep the existing one-wildcard grammar. Replace through an exact helper whose precondition is proved
by config validation. Add a test that a second wildcard remains module_config_alias_invalid.
CodeQL alert 9 may be closed only when the code-level invariant is visible to the query or the live alert is dismissed with the fixture/test proof. It is not evidence of C-05 by itself.
Plant exact node, nested node -> import, custom condition and ambiguous-condition fixtures.
- if all supported branches resolve to one source, retain that source;
- if branches resolve to different sources and runtime conditions are unknown, return an explicit ambiguity reason;
- do not choose a convenient branch by object key name;
- if this cannot be implemented narrowly, add a known limitation and keep partial access coverage.
This review is bounded to workspace source resolution. It does not attempt the complete Node module resolver.
The allow rule is narrow:
- preserve a finite numeric scalar under exact usage-counter keys such as
tokens,tokenCount,inputTokens,outputTokens,promptTokens,completionTokensandtotalTokens; - do not preserve numeric
accessToken,refreshToken,idToken, credential, password, secret or API-key values; - do not treat arrays of numeric token IDs as usage counts;
- continue to redact strings under every secret key, even when the string contains digits;
- preserve normal booleans/nulls only where the existing evidence schema permits them;
- preserve nested authorization evidence exceptions already covered by the current model;
- render the same sanitized value in JSON, Markdown, HTML, SARIF and JUnit.
Required adversarial fixtures include numeric access tokens, stringified counts, arrays, nested
credentials, mixed-case/snake-case key variants and a normal usage.tokens counter.
Replace automatic tag-push publication with workflow_dispatch from main and explicit inputs for
version/tag. The workflow must reject execution unless github.ref is refs/heads/main.
Use two checkouts or equivalent immutable separation:
- trusted orchestration and
.github/release-signersfrom protectedmain; - candidate source from the input immutable tag.
The candidate is untrusted until the main-sourced verifier proves:
- the tag is an annotated tag object;
git verify-tagsucceeds against the trusted allowlist;- the peeled commit equals the declared source commit;
VERSION, package version, release evidence and manifest version agree;- the source commit is reachable from the approved candidate commit on
origin/main; - hosted CI and CodeQL succeeded on that exact source commit;
- the tag and release do not already exist in a conflicting state.
npm ci --ignore-scripts, artifact construction and all write-capable operations occur only after
this verification.
Use separate jobs:
verify-and-build:contents: read, no ID token, no attestations, no environment;publish: needs verified artifacts, hascontents: write,id-token: writeandattestations: write, and uses the protectedreleaseenvironment;post-publish-verify: read-only except for uploading workflow evidence, verifies public assets and provenance.
Workflow-level write permissions are forbidden. Release concurrency is one non-cancelling group so two versions cannot publish simultaneously.
A tag commit must not be able to replace its own trusted signer list or verifier. Tests must create a candidate commit with an attacker key and modified signer file, sign its tag with that key and prove the main-sourced verifier rejects it.
Generic CI becomes branch-scoped to main and pull requests to main; it does not run on arbitrary
tag updates. Live moving-tag consistency remains a dedicated promotion check.
Model promotion explicitly:
- record a pending candidate with prior
v1tag object and expected new source; - verify immutable GitHub/npm/installer/Action channels;
- create and locally verify the new signed annotated
v1tag; - update only the expected prior remote tag object under the recorded lease;
- run the
finalimmutable plusv1consumer workflow under promotion concurrency; - finalize
stableActionand clear pending state; - run
check-public-release-stateonly after the final state is coherent.
No ordering can make two independent Git refs transactional. The contract is an explicit pending state with dedicated verification, not a claim of atomic multi-ref mutation.
After D3, configure and re-read through the API:
- protect
mainfrom force-push and deletion; - require the selected CI and CodeQL checks before merge;
- keep administrator bypass behavior explicit;
- protect immutable
v0.*tags from update/deletion; - keep
v1movable only through the documented promotion authority; - create the
releaseenvironment used by the publish job; - do not require a second approving reviewer until a second maintainer exists.
Screenshots are supporting evidence only. API state is the recorded result.
| Alert | Path class | Planned action |
|---|---|---|
| 10 | production module graph | Fix C-05 and require the alert to close on the candidate. |
| 9 | production module graph | Prove the one-wildcard TypeScript invariant, refactor exact replacement, then close or evidence-based dismiss. |
| 11 | renderer test | Inspect escaping context; fix if output can execute, otherwise dismiss as test-only with ledger evidence. |
| 7, 6, 5 | deliberately vulnerable fixture | Dismiss as used in tests; link fixture purpose and regression. |
| 4, 3 | report contract test strings | Inspect generated output path, then dismiss only if values never become unescaped production output. |
| 2 | sitemap test | Preserve the XSS regression assertion; dismiss as test-only only after the production renderer remains escaped. |
| 1 | version consistency test | Prove fixed literal comparison and dismiss as test-only/false positive. |
Create docs/code-scanning-dispositions.md with alert ID, rule, path, classification, evidence,
owner, date and revisit condition. The release gate is:
- zero new undispositioned production-path HIGH alerts;
- zero open product-code alert known to represent a confirmed bug;
- test/fixture alerts may remain dismissed with the public ledger;
- a successful CodeQL workflow is not equivalent to zero alerts.
Current platform facts:
- secret scanning: enabled;
- secret-scanning push protection: enabled;
- Dependabot security updates: disabled;
- Dependabot vulnerability alerts endpoint: unavailable/disabled;
- no
.github/dependabot.ymlexists.
Under the approved D4 rollout and ownership policy:
- record signal owner, SLA, private escalation and gate authority;
- enable vulnerability alerts and Dependabot security updates;
- inventory and disposition the resulting alerts and generated security-update PRs;
- enable a blocking dependency-review gate after a planted disallowed-dependency fixture proves the evidence path;
- keep alert availability separate from merge-gate availability and evidence;
- treat unavailable plan/platform features as unavailable, not pass.
Issue 6 contains two separable requests:
- a checksum-pinned ShellCheck job is a bounded v0.8.1 supply-chain improvement if D5 approves it;
- Node coverage should be measured as research only. No arbitrary percentage becomes a patch release gate.
Issue 6 remains open unless both its own acceptance criteria are met. Partial work gets an exact issue comment, not a premature close.
| Issue | v0.8.1 action | Closure rule |
|---|---|---|
| 1 | Run the existing crawler malformed/empty/stale regression in the final suite only | Remains closed unless regression fails |
| 2 | Run the existing AWS permission-denied regression in the final suite only | Remains closed unless regression fails |
| 3 | Correct stale premise if needed; keep WSL2 unsupported | Keep open until a real clean WSL2 lifecycle exists |
| 4 | No implementation in a correctness patch | Keep open for a later feature release |
| 5 | Run existing sitemap entity/CDATA regression in the final suite only | Remains closed unless regression fails |
| 6 | Optionally ship pinned ShellCheck; measure coverage without a floor | Keep open if coverage/ownership acceptance is incomplete |
| 7 | Update current secret-scanning facts; accept owner policy; implement suppression and dependency-alert decision | Close only after D4 and live setting/fixture evidence |
Tasks:
- preserve the external audit hash, repository commit, release source and platform snapshots;
- record all finding states without copying the audit's severity labels uncritically;
- obtain D1-D5 decisions;
- freeze v0.8.1 included/excluded scope;
- create no version bump and no public release.
Gate:
- every external finding maps to a phase or explicit defer reason;
- every open Issue and CodeQL alert maps to a disposition;
- unresolved owner decisions remain visible and block their dependent phases only.
Tasks:
- add minimal tests for ignored custom source roots/exclusions;
- add built-in, tracked-env, route and diff scope fixtures;
- add one fake-adapter scope fixture per adapter family;
- add suppression expiry/fingerprint/unknown-state failures;
- add Node multi-RHS-wildcard and replacement-string adversarial fixtures;
- add numeric usage-token and numeric credential redaction fixtures;
- add trusted-main versus attacker-tag signer fixture;
- add a release-state fixture for pending
v1promotion.
Plant-the-failure gate:
- every test fails against v0.8.0 for the intended reason;
- test-only syntax errors or wrong fixture assumptions do not count;
- record test names and pre-fix failure messages in section 21.
Tasks:
- implement and validate the canonical scope object;
- remove the separate
IGNOREDsource of policy truth; - apply it to walking, reading, tracked env files, config/manifest inputs and route/access analysis;
- apply it to staged/since snapshots;
- add scope coverage and reason codes;
- preserve default-boundary baseline compatibility and reject unreliable custom legacy baselines.
Focused gate:
- only admitted files are opened and reported;
- excluded vulnerable fixture produces no finding and increments exclusion evidence;
- unreadable/missing root is unknown/non-zero;
- no outside path leaks into any renderer;
- reverting one scope-policy call makes a focused test fail.
Tasks:
- implement the matrix in section 8;
- make Checkov and OSV explicit-input scope exact;
- implement private scoped snapshots for Opengrep and working-tree Gitleaks;
- make restricted Gitleaks history fail closed if exact history scope is unavailable;
- record adapter scope mode and network behavior;
- preserve default full-scope deep-profile behavior.
Focused gate:
- fake adapters prove excluded marker content was not read;
- unexpected output paths become unknown;
- real pinned adapters run once on hosted Ubuntu/Node 22;
- missing/unsupported scope is not a pass;
- snapshot cleanup occurs on success, failure and timeout.
Tasks:
- implement the versioned suppression parser and exact matcher;
- extend v3 schemas and runtime validators additively;
- update summary, JSON, Markdown, HTML, SARIF and JUnit;
- update exit/gate logic without changing evidence states;
- preserve fixed/unretested/not-comparable baseline semantics;
- document and test local versus blocking owner/expiry rules.
Focused gate:
- valid exact suppression does not block but remains visible;
- stale, expired, malformed, broad or symlink suppression cannot weaken the gate;
- unknown/evidence-integrity remains non-suppressible and exit 3;
- all renderers agree on active/suppressed counts;
- plant removal of fingerprint or expiry validation is caught.
Tasks:
- define the production-only repository scope;
- classify the 14 baseline self-findings through scope or exact suppression, never deletion;
- add the no-network self-audit CI job and artifact;
- add the CodeQL disposition ledger;
- update false-positive and alert policies;
- confirm closed historical Issue regressions still exist.
Focused gate:
- intentional examples/tests are excluded with counts;
- the production rule-registry match is either fixed or exactly suppressed with review evidence;
- active HIGH and unknown results fail the self-gate;
- the report contains every suppression;
- no claim says self-audit proves repository safety.
Tasks:
- fix Node all-instance RHS wildcard replacement;
- refactor TypeScript one-wildcard replacement without semantic expansion;
- resolve or document bounded conditional-export fixtures;
- implement numeric usage-counter preservation;
- retain numeric credential and array redaction;
- update relevant known limitations.
Focused gate:
- CodeQL production alerts 9/10 have code-level outcomes;
- all replacement-string adversarial cases pass;
- access-chain partial/completed semantics do not silently widen;
- all renderer redaction outputs agree;
- reverting each correction is caught by its focused test.
Tasks:
- convert release to trusted-main manual dispatch;
- split verify/build and publish permissions;
- bind publish to release environment and concurrency;
- source verifier and signer policy from trusted main;
- branch-scope generic CI;
- add explicit pending/final promotion state;
- update release scripts/tests/runbook.
Focused gate:
- unsigned tag, wrong signer, tag-owned signer file and wrong peeled commit all stop before publish;
- read-only job cannot create a release or attestation;
- publish job cannot run without verified artifacts/environment;
v1pending state is not a generic CI failure;- final live-state mismatch still fails the dedicated verifier;
- no public tag/release/npm mutation occurs in local tests.
Tasks dependent on decisions:
- apply and re-read main/tag rules and release environment after D3;
- accept owner/SLA/escalation fields after D4;
- enable and inventory Dependabot alerts after D4;
- add checksum-pinned ShellCheck after D5;
- post evidence-based comments to Issues 3, 6 and 7;
- dismiss only classified CodeQL test/fixture alerts through the API.
Gate:
- live API JSON is retained in a sanitized evidence record;
- unavailable settings remain unavailable;
- no issue closes on documentation intent alone;
- no alert is dismissed without the public disposition ledger.
Tasks:
- update
SKILL.mdexecution instructions only where behavior changed; - update capability JSON/Markdown without increasing stable detector-family count;
- update README English/Chinese, tutorial, compatibility, false-positive policy, alert policy, known limitations, roadmap and changelog;
- document scope, suppression, report schema additions and release workflow;
- update npm/Skill/Action distribution allowlists for new runtime files;
- keep engineering/adoption evidence out of the runtime package unless required.
Gate:
- generated capability and public docs agree;
- every new claim points to a test or schema;
- WSL2 remains unsupported;
- no
0 FP, production precision or exploitability claim is added.
Tasks:
- bump VERSION/package/plugin/Action/release surfaces together;
- generate release evidence and candidate SBOM;
- run changed-script syntax and schema validation;
- run one final
npm run checkon the frozen candidate; - run Bash 3.2 smoke and package isolation/distribution checks;
- record exact pass/fail/skip/not-run inventory.
Gate:
- zero failed or not-run required tests;
- optional real adapters may be skipped locally only when recorded and are run hosted;
- no unexplained dirty file or generated drift;
- candidate commit is exact and no release tag exists.
Tasks:
- push the candidate commit to main without a release tag;
- wait for CI and CodeQL on the exact commit;
- run the pinned real-adapter job once;
- run the repository self-audit and upload its report;
- query live CodeQL/Dependabot/ruleset/environment state.
Gate:
- exact candidate CI and CodeQL conclude success;
- no undispositioned production HIGH alert;
- no active HIGH or unknown self-audit result;
- branch/rules/environment facts match the approved D3 state;
- any correction creates a new candidate and returns to P10.
Tasks:
- create the SSH-signed annotated
v0.8.1tag locally; - dispatch the trusted-main release workflow with exact version/tag;
- verify release assets, checksums, SBOM, attestation and signed tag;
- publish npm through trusted publishing and verify provenance/file identity;
- run exact-version npx and verified installer under a fresh isolated home;
- run the immutable full-SHA Action consumer;
- acquire the exact
v1lease, enter pending state, sign/movev1, run final consumers and finalize stable state; - append final evidence to this plan and
docs/releases/v0.8.1.md.
Gate:
- tag, manifest, GitHub assets, npm gitHead, immutable Action and
v1peel to one source commit; - repository-local signer verification and GitHub signature status both pass;
- npm package and source archive agree on every shipped path;
- required-attestation install passes;
- final public-state verifier passes only after pending promotion is cleared;
main, npm, GitHub Release, installer default and public docs all name v0.8.1.
| Case | Expected result |
|---|---|
default . plus default excludes |
Behavior compatible with v0.8.0 default scan |
| one nested root | Only nested source plus governing inputs |
| two overlapping roots | Files counted once |
| excluded directory inside root | Never opened; exclusion counted |
| missing root | unavailable/unknown, non-zero |
| symlink root or symlink child | refused or explicitly excluded, never followed |
| tracked env outside root | absent from finding; not read |
| staged/since outside root | excluded from diff artifact |
| route mount outside root | cannot supply hidden context; coverage explains absence |
| custom old baseline | not comparable when prior enforcement was unproved |
| Case | Expected result |
|---|---|
| exact active match | retained as suppressed; gate ignores only that finding |
| wrong path/rule/fingerprint | active finding plus unmatched-entry diagnostic |
| expired entry | active finding plus expiry diagnostic |
| malformed/symlink file | suppression unavailable; gate not weakened |
| unknown/evidence-integrity | suppression rejected |
| suppression added between baseline/current | unchanged evidence; disposition changes only |
| suppression removed | unchanged evidence becomes active |
| finding absent under completed coverage | fixed regardless of prior disposition |
| Case | Expected result |
|---|---|
| signed by allowed signer | verify job may build |
| unsigned tag | stop before dependency install/publication |
| signed by unlisted key | stop before publication |
| tag commit changes allowlist | still rejected by main-sourced allowlist |
| tag peels to wrong commit | rejected |
| CI status belongs to different commit | rejected |
| concurrent dispatch | serialized without cancelling active publication |
v1 moved while pending |
no generic CI red; dedicated state says pending |
stale prior v1 lease |
remote update refused |
Stop v0.8.1 publication if any condition holds:
- a selected scanner reads or reports a path outside its claimed restricted scope;
- an adapter silently post-filters broader reads while claiming scoped execution;
- malformed, expired or broad suppression weakens a gate;
- suppressed findings disappear from primary evidence;
- unknown evidence can be suppressed or rendered as pass;
- Node export correction increases completed access paths through an ambiguous target;
- redaction preserves a numeric credential or leaks a string token;
- release verification trusts signer policy from the candidate tag;
- a write-capable release job can start before verification;
- generic CI still predictably fails solely because
v1is in documented pending promotion; - an open production CodeQL HIGH representing a confirmed bug remains undispositioned;
- required GitHub control state cannot be read back after D3;
- final candidate tests, hosted checks, package identity, attestation or consumers disagree;
- documentation claims WSL2, precision/recall, exploitability or detector expansion not proved here.
v0.8.1 is complete only when:
- all confirmed C-02 through C-08 product/workflow defects assigned to the release are fixed and regression-tested;
- C-01 repository controls match the owner's D3 decision and residual bypass limits are documented;
- scope is operational across every selected scanner or explicitly unavailable per adapter;
- suppression is narrow, visible, expiring under gates and cannot hide incomplete evidence;
- the repository self-audit is useful and reviewable rather than fixture-noise-free by deletion;
- CodeQL alerts have live and documented dispositions;
- Dependabot state matches D4 and is not described as pass when disabled/unavailable;
- Issues 1-7 have accurate status/comments;
- the complete candidate/local/hosted/public evidence chain identifies one immutable source;
v0.8.1GitHub Release, npm package, installer default and signedv1are live and verified;- section 21 records every phase, deviation, failed gate and residual limitation.
Decision: approved on 2026-08-30. Scope is a file-read boundary, not an output-only filter.
Consequence: excluded source cannot be opened by a scanner that claims scoped execution. An adapter that cannot prove this boundary must return unknown instead of scanning broadly and filtering its results.
Blocks resolved: P2 and P3 may implement the contract in sections 7 and 8.
Decision: approved on 2026-08-30. Owner and expiry are optional for local evidence-only use and mandatory when a suppression changes a CI/release gate or external-adapter result.
Consequence: the local path remains usable by an individual, while a blocking suppression cannot be anonymous or permanent.
Blocks resolved: P4 may implement the contract in section 9.
Decision: minimum protection approved on 2026-08-30. Execution is authorized to:
- protect main from force-push/deletion;
- require CI and CodeQL checks;
- protect immutable SemVer tags;
- create release environment;
- retain a documented solo-maintainer bypass without requiring a nonexistent second reviewer.
Consequence: direct destructive ref changes are constrained, while the single maintainer is not blocked by a fabricated second-reviewer requirement. Live API readback remains required before C-01 can close.
Rollout decision: approved on 2026-08-30. Enable vulnerability alerts, Dependabot security updates and a blocking pull-request dependency-review gate after the planted gate fixture passes.
Approved ownership values:
- signal owner/update owner/gate authority:
@parousia8888; - private escalation: the private address/process already named by
SECURITY.md; - triage targets: one business day for a HIGH secret and three business days for a dependency finding.
Blocks resolved: live enablement, PR blocking and Issue 7 closure may proceed after their planted fixtures and live evidence gates pass.
Decision: approved on 2026-08-30. Include checksum-pinned ShellCheck and leave coverage-floor research open without a percentage gate.
Consequence: ShellCheck runs in CI through a reviewed fixed artifact path and is not downloaded or executed by normal CLI users.
Blocks resolved: the ShellCheck portion of P8 is included.
Append one entry after every phase. Do not pre-mark future work complete.
Required format:
### YYYY-MM-DD - Pn complete / blocked
- Start commit and end commit:
- Finding/Issue/alert IDs addressed:
- Files and behavior changed:
- Focused commands and exact outcomes:
- Plant-the-failure result:
- Platform/API evidence:
- Deviations from plan:
- Residual unknowns/limitations:
- Next phase:
- Start/end repository commit:
1cc9282546224a263ff5885db12b583b8ad10aae; no product source or release state changed during plan preparation. - External audit: all 401 lines read; SHA-256
4c81aefa04e1345f2f0b09d0618c363069dba52d6d2c750f3b2b00ad34e8ed38. - Confirmed product facts: scope disconnect, 14-finding noisy self-scan, Node RHS wildcard bug, numeric token-count redaction and missing pre-publication signature gate.
- Confirmed platform facts: no main protection, no rulesets, no environments, ten open CodeQL alerts, Dependabot alerts/security updates disabled, secret scanning and push protection enabled.
- Issue inventory: Issues 1/2/5 closed with regressions; 3/4/6/7 open. Issue 3's support premise and Issue 7's secret-scanning premise are stale relative to current repository facts.
- Workflow evidence: runs
33265040656and32980990347fail on the same public-state assertion; olderv1promotions show the same failure class. The audit's race explanation remains unproved. - Focused checks: in-memory source audit reproduced 14 findings; evidence sanitizer reproduced
numeric
usage.tokensloss; official Node documentation confirms all RHS wildcard instances are replacement sites. - Residual state: D1-D5 require owner decisions. No implementation phase has begun.
- Start/end repository commit:
1cc9282546224a263ff5885db12b583b8ad10aae; only this plan changed and no product or GitHub setting was mutated. - D1: restricted scope is a file-read boundary.
- D2: local evidence-only suppression may omit owner/expiry; a suppression affecting CI, release or an external adapter requires both.
- D3: minimum main/tag protection and a release environment are authorized, with no artificial second-reviewer requirement and an explicit solo-maintainer bypass.
- D4 rollout: vulnerability alerts, Dependabot security updates and a blocking pull-request dependency-review gate are authorized. Signal owner, gate authority, private escalation and SLA acceptance remain an explicit ownership sub-gate before live enablement.
- D5: checksum-pinned ShellCheck is included; no code-coverage percentage gate is authorized.
- P0 result: product semantics, ownership fields and rollout choices are frozen. P1-P8 may start in the required order.
- Next phase: P1 plants focused failing contracts without changing release or GitHub settings.
- Signal owner, update owner and gate authority:
@parousia8888. - Private escalation: the existing private process documented by
SECURITY.md. - Triage targets: one business day for a HIGH secret and three business days for a dependency finding.
- Authorized rollout: vulnerability alerts, Dependabot security updates and a blocking pull-request dependency-review gate after focused and live gates pass.
- Remaining owner decisions: none. Implementation is authorized through verified v0.8.1 public
release and signed
v1promotion.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; changes remain uncommitted until the bounded P2-P9 implementation stack is internally coherent. - Finding/Issue/alert IDs addressed: planted contracts for C-03, C-04, C-05, C-07, C-08 and the P3 adapter boundary; no defect was marked fixed in this phase.
- Files and behavior changed: added focused assertions in
evidence-writer,js-ts-module-graph,external-adapters,v081-scope-suppression-contractandv081-release-workflow-contract. - Focused pre-fix outcomes: evidence writer failed with actual
tokens: '[REDACTED]'; module graph failed with actual resolutionnull; scope failed becausesrc/private/excluded.jsremained in findings; Checkov restricted scope returnedadapter_internal_error; Release workflow failed at the missingworkflow_dispatchassertion; suppression run remained exit 1 with an active HIGH. - Plant-the-failure result: all five failure classes were caused by the intended v0.8.0 behavior, not syntax errors or unavailable fixtures. The external fixture printed the unexpected full-scope argument/evidence state, and the Release assertion printed the tag-push workflow.
- Platform/API evidence: none; no GitHub settings or refs changed.
- Deviations from plan: the trusted-attacker tag fixture and pending-promotion fixture remain paired with P7 because they require the verifier/state-machine interface P7 introduces. Their public workflow preconditions are already planted here.
- Residual unknowns/limitations: passing these assertions will not prove scanner precision or hosted GitHub policy enforcement.
- Next phase: P2 canonical scope implementation.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; implementation is still uncommitted and locally reviewable. - Finding/Issue/alert IDs addressed: C-03 built-in half and A-01; Issue mapping remains open until documentation and hosted evidence close.
- Files and behavior changed: added
scripts/lib/audit-scope.mjs; normalized and validated roots, basename exclusions, mandatory engine exclusions, physical containment, governing inputs and the execution digest; wired the policy into traversal, Git tracked-env pathspec/post-validation, route/access inputs and diff snapshots; expanded schema limits and scope traversal evidence. - Focused commands and exact outcomes:
audit-scope,source-coverage-ledger,js-ts-source-audit,incremental-source-auditandscope-target-validationall exited 0;git diff --checkexited 0. The combined v0.8.1 contract passes its source-root, exclusion, tracked-env, route and diff assertions and stops later at the still-unimplemented suppression. - Plant-the-failure result: the same combined contract failed before P2 because the excluded finding
remained present; after P2 it advances through every scope assertion. Omitting
scopeBoundaryretains the documented default full-scope behavior. - Platform/API evidence: none; this phase was network-free.
- Deviations from plan: a missing or invalid custom source root currently stops before report
creation with a non-zero scope error. It is fail-closed but does not yet emit an
unknownreport; that distinction is retained as a documented P9 limitation unless a narrow report path is added. - Residual unknowns/limitations: external adapters do not yet consume the policy; pre-v0.8.1 custom baseline compatibility needs its P9 contract wording and test.
- Next phase: P3 external adapter scoping.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; the bounded implementation remains uncommitted pending the coherent P5-P9 stack. - Finding/Issue/alert IDs addressed: C-03 external-adapter half. No adapter result was upgraded from unavailable to completed merely because a selected scope could not be represented.
- Files and behavior changed: Checkov now receives an exact eligible Dockerfile/workflow list;
OSV receives admitted or governing lockfiles only; working-tree Gitleaks and Opengrep use private
path-preserving scoped snapshots; restricted Gitleaks history returns
unknown / history_scope_not_supported; report adapter metadata recordsscopeMode. - Focused commands and exact outcomes:
node test/external-adapters.test.mjsexited 0 and covered all four adapter families, restricted inputs, unexpected paths, missing tools, failures and gate acknowledgement.node test/real-adapters.test.mjsrecorded the pinned binaries as unavailable locally rather than claiming a pass; the real pinned run remains a P11 hosted requirement. - Plant-the-failure result: the P1 restricted Checkov fixture failed before P3 with
adapter_internal_errorbecause the full-scope argument contract was still used. It now reaches completed/not-applicable coverage withscopeMode=governing_inputs; the snapshot fixtures fail if excluded marker files are copied. - Platform/API evidence: none; fake adapters were local and network-free.
- Deviations from plan: Gitleaks history is deliberately unavailable under restricted scope rather than post-filtered. This is the planned fail-closed outcome, not an implemented history filter.
- Residual unknowns/limitations: exact behavior of the pinned real binaries remains to be proved by the hosted Ubuntu/Node 22 job in P11.
- Next phase: P4 suppression, report and baseline integration.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; changes remain local and no public gate or release state changed. - Finding/Issue/alert IDs addressed: C-04 disposition half and the suppression contract required by Issue 7. Evidence states and finding fingerprints were not redefined.
- Files and behavior changed: added
scripts/lib/suppressions.mjs; accepted only a bounded, subject-bound, non-symlink JSON file with exact adapter/rule/path/fingerprint entries; added expiry and local-versus-gated governance; retained suppressed findings in v3 JSON, Markdown, HTML, SARIF and JUnit; added active/suppressed summaries; made the threshold gate ignore only valid suppressed findings while malformed suppression evidence returns exit 3. - Focused commands and exact outcomes:
node test/v081-scope-suppression-contract.test.mjs,node test/report-v3-contract.test.mjsandnode scripts/check-json-schema-contracts.mjsexited 0. The contract covered path/rule/fingerprint drift, expiry, malformed and symlink files, unknown/evidence-integrity findings, local owner/expiry omission, gated and external governance, renderer agreement and unchanged baseline identity when suppression is added or removed. - Plant-the-failure result: replacing the exact fingerprint predicate with
truefailed at the drift assertion (suppressedobserved,activeexpected). Disabling the expiry predicate made the expired run exit 0 instead of 1 and failed the gate assertion. Both mutations were restored, and the same focused test then exited 0. - Platform/API evidence: none; this phase was network-free.
- Deviations from plan:
node test/evidence-writer.test.mjsstill fails only at the already-planted P6 numericusage.tokensassertion. That defect is not marked as a P4 regression or pass. - Residual unknowns/limitations: a suppression remains an accepted policy disposition, not proof that the matched condition is safe. No broad directory/rule allowlist exists.
- Next phase: P5 production-only repository self-audit and public alert-disposition surface.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; work remains local and no GitHub alert was dismissed in this phase. - Finding/Issue/alert IDs addressed: C-04 self-audit half; C-06 public disposition surface; historical regression evidence for Issues 1, 2 and 5; ownership text for Issue 7.
- Files and behavior changed: added versioned
.github/self-audit-policy.json, exact governed.github/self-audit-suppressions.json, no-network.github/scripts/run-self-audit.mjs, a dedicated CI job with report artifact, clone-like self-audit regression anddocs/code-scanning-dispositions.md; updated alert and false-positive policy with the approved owner/SLA and exact suppression semantics. - Focused commands and exact outcomes:
node test/repository-self-audit.test.mjsexited 0; the actual repository report retained one suspected MEDIUM rule-registry finding as suppressed, reported zero active and zero unknown findings, scanned with network=false and recordedtest,examples,docs/adoptionanddocs/releasesexclusions. Crawler range, AWS permission and sitemap entity/CDATA regressions all exited 0. The P4 suppression contract andgit diff --checkalso exited 0 after the internal policy-path addition. - Plant-the-failure result: a clone-like fixture planted
rejectUnauthorized: falsein the production-scoped.githubtree and the self gate exited 1; an invalid-encoding JS file exited 3 with active unknown evidence. The intentionally vulnerable copies under excluded test/example and adoption/release directories did not enter findings and remained counted in coverage. - Platform/API evidence: the live CodeQL API returned alerts 1-7 and 9-11 open plus alert 8 fixed. Their rules, paths, current classification, evidence and revisit conditions are recorded in the public ledger. No dismissal API was called before that ledger existed.
- Deviations from plan: the published generated parser under
scripts/vendoris inside the scope, but the built-in JS detector records it asgenerated_or_minified_sourcerather than parsing it; its two paths remain visible in coverage. The repository self-audit uses an internal versioned suppression path so ordinary user audits keep the root-file convention and subject binding. - Residual unknowns/limitations: live CodeQL dismissals wait for P6 outcomes and P8 API mutation; the self-audit is a bounded built-in static check, not repository safety evidence.
- Next phase: P6 module graph and evidence-redaction corrections.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; the bounded implementation remains local and no tag, release or GitHub setting changed. - Finding/Issue/alert IDs addressed: C-05, C-07, A-02 and A-03; the corresponding CodeQL alert dispositions remain a P8 platform action after the trusted release workflow is locally proved.
- Files and behavior changed: Node package-export patterns now replace every right-hand-side
*literally, including captured paths containing$or/; TypeScript aliases retain their validated one-wildcard contract and literal replacement; conditional-export traversal considers all object branches but returns ambiguous evidence when supported conditions resolve to different files; finite scalar usage counters under an explicit key allowlist remain numeric, while token strings, arrays, credential keys and non-finite values remain redacted. - Focused commands and exact outcomes:
node test/js-ts-module-graph.test.mjs,node test/evidence-writer.test.mjs,node test/js-ts-access-path.test.mjs,node test/js-ts-route-authorization-audit.test.mjsandnode test/route-access-path-coverage.test.mjsall exited 0. The repository self-audit also exited 0 with its exact suppression still valid, zero active findings and zero unknown findings. - Plant-the-failure result: temporarily restoring first-only Node wildcard replacement made the
repeated-RHS fixture fail with resolution
null; temporarily removing the scalar usage-counter allowlist madeusage.tokensbecome[REDACTED]and failed its exact assertion. Both mutations were restored and both focused tests returned to exit 0. - Platform/API evidence: none; this phase was network-free.
- Deviations from plan: the first redaction run exposed an additional credential boundary:
tokens: [101, 202]was recursively retained. The array branch now redacts secret-key arrays as a whole, and the focused test proves that the usage exception applies only to finite scalars. - Residual unknowns/limitations: conditional export identity remains unavailable when conditions select different existing files; runtime reachability is not inferred. Numeric usage preservation is intentionally key-allowlisted rather than a general exemption for token-like fields.
- Next phase: P7 trusted-main release workflow, signer verification and pending
v1lifecycle.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; all work remains local, and no public ref, Release, package, environment or repository rule changed in this phase. - Finding/Issue/alert IDs addressed: C-02 and C-08; C-01's live environment/ruleset half remains P8. The release workflow now has the local contract required before those settings are enabled.
- Files and behavior changed: release publication is a
main-only manual dispatch with explicit version/tag; a read-only job sources its verifier and signer allowlist from trustedmain, checks an annotated signature, exact commit, candidate metadata and six exact hosted checks beforenpm ci; arelease-environment job alone has publication/attestation permissions; a read-only job re-downloads and verifies public assets. Generic CI is branch/PR scoped tomain. - Files and behavior changed for
v1:docs/release-state.jsonnow distinguishespendingandfinal; an exact transition CLI records the expected source and prior tag object; pending and final public-state verification are separate; the Action consumer hasimmutable-only,promotionandfinalphases under one non-cancelling concurrency group, and finalization reuses the exact successful promotion-run artifact instead of rerunning consumers. - Focused commands and exact outcomes: release candidate verifier, Action promotion state,
release-state, release-promotion, release-trust-boundary and v0.8.1 workflow-contract tests all
exited 0;
check-release-contract,check-document-contract, YAML parsing,git diff --checkand the repository self-audit exited 0. - Plant-the-failure result: temporarily bypassing
git verify-tagmade the wrong-signer fixture be accepted and failed the verifier test; allowing pending state through final verification failed the release-state test; givingverify-and-buildcontents write and changing CI away frommainfailed the workflow contract. All four mutations were restored and the focused suite returned to exit 0. - Platform/API evidence: a read-only GitHub query confirmed the actual required check names on the
baseline commit:
repository-self-auditis new for the candidate, alongside four matrix jobs andanalyze; no mutation API was called. - Deviations from plan: final
v1evidence uses two serialized workflow dispatches. The promotion run executes the Action consumers while state is pending; the final run downloads that exact successful artifact and publishes the durable record after state finalization, avoiding duplicate consumer execution. - Residual unknowns/limitations: local YAML parsing and contract tests do not prove GitHub accepts or enforces the workflow/environment permissions; that becomes hosted P11 evidence. Two Git refs remain non-transactional, and the prior-object lease is the control for the movable alias.
- Next phase: P8 live GitHub governance, alert dispositions, dependency gate and pinned ShellCheck.
- Start/end repository commit: start
1cc9282546224a263ff5885db12b583b8ad10aae; implementation remains local. GitHub settings changed, but no source ref, release, package or release tag changed. - Live platform changes and readback: Dependabot vulnerability alerts and security updates are
enabled;
mainrejects force-push/deletion and requires strict CodeQL, four Node/OS CI matrix, repository-self-audit, ShellCheck and pull-request dependency-review checks; administrator bypass is explicit for the solo maintainer. Active tag rulesets block update/deletion ofv0.*andv1unless the administrator bypass is used. Thereleaseenvironment accepts protected branches and has no fabricated second reviewer. - Local gate evidence: dependency review is pinned to Action commit
3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261and blocks moderate or higher changes. Changing its threshold to critical failedtest/v081-platform-governance-contract.test.mjs. A checksum-pinned ShellCheck v0.11.0 install verified the macOS arm64 archive; a planted unused variable produced SC2034 and exit 1, and the restored warning-level run exited 0. The platform contract andgit diff --checkexited 0. - First Dependabot inventory: 32 open alerts, all at
examples/quickstart/before/package.json(2 critical, 10 high, 16 medium, 4 low), plus generated PR 8. The old Next 15.0.0 pin is not a required vulnerable condition. The candidate aligns both quickstart manifests at 16.3.3, retains the intentional missing before lockfile, creates a real after lockfile and returned zero point-in-timenpm audit --omit=devfindings. A planted mismatch between before/after versions failed the platform contract and was restored. - Public records: sanitized readback is in
docs/releases/v0.8.1-platform-governance.json; Issues 3, 6 and 7 received evidence comments. Issues 3 and 6 remain open for real WSL2 and coverage research. Issue 7 remains open until hosted dependency review and post-push alert/PR readback complete. - Ordering deviation: CodeQL alerts 1-7 and 11 are not dismissed while their public ledger exists only locally. Alerts 9/10 remain open production alerts and are never dismissed as fixtures. P9 and P10 may prepare the exact candidate; after P11 publishes the ledger, P8 closeout performs the approved test/fixture dismissals, closes superseded dependency state, re-reads all API facts and only then marks P8 complete. This preserves the plan's no-dismissal-before-public-evidence gate.
- Residual unknowns/limitations: new required checks have not yet run on the candidate; dependency alerts cannot close before the manifest reaches main; an npm registry audit is point-in-time evidence, not a permanent no-vulnerability claim.
- Next phase: P9 public documentation and distribution synchronization, with P8 remaining in progress until the P11 closeout described above.
- Start/end repository commit: start and end base
1cc9282546224a263ff5885db12b583b8ad10aae; the coherent P2-P9 implementation remains local and uncommitted. No public ref, package, release or GitHub setting changed in this phase. - Finding/Issue/alert IDs addressed: public contracts for C-02 through C-08, A-01 through A-05 and the approved D1-D5 boundaries. No detector family or evidence state was added.
- Files and behavior documented: English/Chinese README and tutorial now explain the canonical file-read scope, exact visible suppression, adapter scope modes and restricted-history unknown; compatibility, limitations and adapter protocol expose abort/partial boundaries; capability, alert/false-positive, roadmap, changelog, AI/Skill maps and public contract describe production self-audit, module/redaction corrections and trusted-main/pending-final release behavior.
- Distribution changes:
docs/false-positive-policy.mdis included in npm and installed Skill payload allowlists. Engineering/adoption plans and platform-governance evidence remain outside the runtime payload. - Focused commands and exact outcomes: capability matrix check exited 0 and reported 29 total
capabilities, 11 stable detection categories and zero planned detection; document, product,
public-surface, release and distribution contracts each exited 0; relevant JSON parsing and
git diff --checkexited 0. - Plant-the-failure result: not separately required for prose-only P9 claims; existing public, capability, release and distribution contract checks machine-bind headings, categories, evidence paths, release language and payload membership. Silent product regressions remain covered by the planted P1-P8 tests recorded above.
- Platform/API evidence: none added. Documentation retains hosted checks, public package, attestation and v0.8.1 consumer state as pending; current v0.8.0 public facts remain separate.
- Deviations from plan:
docs/public-contract.jsonrecords v0.8.1 asnextSourceCandidatewhileVERSIONandcurrentSourceReleaseremain v0.8.0 until the atomic P10 version freeze. This keeps P9 contract checks green without presenting an unpublished candidate as the current release. - Residual unknowns/limitations: WSL2 remains unsupported; invalid custom roots can abort before a report artifact; restricted Gitleaks history remains unknown; self-audit is bounded evidence; the solo-maintainer administrator bypass is not independent review.
- Next phase: P10 atomic v0.8.1 version/evidence freeze and the single full local candidate gate.
- Start/end repository commits: version and implementation surfaces froze in
142c7ac7a7f42fcf0ad9d17bbd31735943542ab8; the fixed-project evidence refresh and single full local gate ran onb55e8a170f72378e742cfbe34adcb9ac00e06c2e. Nov0.8.1tag, GitHub Release, npm publication orv1movement occurred. - Version and candidate surfaces:
VERSION, npm/package lock, Claude plugin/marketplace, Action, capability/public contracts, changelog and release evidence name v0.8.1 together. Published v0.8.0 source facts remain unchanged until each public v0.8.1 object is observed. - Full local gate:
npm run checkexited 0. It recorded 88 passing test files, zero failures and one optional real-adapter skip; prerequisite surfaces recorded three passed, zero failed and one skipped. Bash 3.2 smoke, lint, schema, generated-file, public, release and distribution contracts passed. No required check was failed or marked not-run. - Skill validation: the first system-Python invocation was unavailable because PyYAML was absent
and was not called a pass.
uv run --no-project --with pyyaml python /Users/kenn/.codex/skills/.system/skill-creator/scripts/quick_validate.py .then returnedSkill is valid!from an isolated dependency environment without changing project dependencies. - Package/SBOM evidence:
npm pack --dry-run --jsonrecorded 221 files, 672,551 packed bytes, 2,821,340 unpacked bytes, SHA-12c9e06be7bd555a05fd8a8d8d908d3f54506f1d8and integritysha512-SUonYq1kXt8/Noz0yR3qubR7rhI+ob70heTf5xJPJNMFNdC5eUP4c3GvQ42IsTPozNHCyO3/O8Z2J2sRlffu3w==. The candidate SPDX 2.3 SBOM at/tmp/wass-v0.8.1-candidate.spdx.jsonhas SHA-256fb1b1762efc849f77310fbbb8bc5aed795eb87210dc1def36851bd3b02aeda46and remains outside the tree. - Fixed-project refresh: Linkwarden returned 278 findings and exit 3/incomplete; Healthchecks 149
and exit 0/complete; Open WebUI 162 and exit 3/incomplete; Uptime Kuma 122 and exit 3/incomplete;
Mealie 37 and exit 0/complete. All pinned checkouts remained clean. Gitleaks 8.30.1 used digest
ba52fb1b...e84f; OSV-Scanner 2.5.0 used digestfff5a2e3...da2. The shortened digests are journey log labels, not release checksum claims; exact adapter provenance remains in generated evidence. - Evidence-only closeout: this P10 record is the only post-gate source delta. Only document/release contracts and whitespace are rerun locally; P11 executes the complete matrix, CodeQL, repository self-audit and pinned real adapters on the exact pushed evidence commit.
- Residual unknowns/limitations: local optional real-adapter evidence remains skipped rather than passed; the candidate SBOM is not yet the signed public asset; no hosted branch/rules/environment, npm provenance, installer, Action consumer or public-object claim is made.
- Next phase: push the evidence-only candidate to
mainwithout a tag and complete P11 exact-commit hosted verification, then close the deferred P8 live alert/Issue work.
- Hosted governance identity: the public ledger reached
mainin candidate commit66a549c1248cbf68d7f470443c3f072f5b75374cbefore any CodeQL dismissal. The post-candidate sanitized readback was added todocs/releases/v0.8.1-platform-governance.jsonwithout replacing the original 32-alert snapshot. - CodeQL disposition: candidate analysis closed production alerts 9 and 10 as fixed; neither was
dismissed. Alerts 1-7 and 11 were re-read at their documented test/fixture paths, then dismissed
as
used in testswith the public revisit conditions retained. A second API read returned zero open CodeQL alerts. - Dependency state: the 32 open Dependabot alerts under the quickstart before fixture fell to zero
after its manifest reached
main; generated PR 8 closed without merge. This is point-in-time platform evidence, not a permanent dependency-safety claim. - Hosted PR gate: old PR 8 predated the new dependency-review job and could not prove its supported
event path. Temporary PR 9 therefore used an empty commit and zero file diff. The full-SHA-pinned
Action passed in run
33319628174, job99279204655; duplicate matrix/CodeQL work was cancelled, the PR closed without merge and the temporary local/remote branch was deleted. - Repository controls: strict required checks, no main force-push/deletion, active immutable-v0 and movable-v1 tag rulesets, and protected-branches-only release environment were re-read. The administrator bypass is retained for the approved solo-maintainer minimum and does not create independent review.
- Issue state: Issue 7 received the exact hosted evidence and closed as completed. Issues 3 and 6 remain open because WSL2 and an evidence-based coverage threshold remain unproved; neither was converted into a v0.8.1 pass.
- Residual limitations: dependency review was proved on a no-diff PR; the planted local contract, not the hosted probe, proves the moderate threshold text. GitHub settings do not protect against maintainer account compromise.
- Next phase: complete and record P11 exact-commit hosted candidate evidence.
- Candidate identity:
66a549c1248cbf68d7f470443c3f072f5b75374cwas pushed tomainwithout creatingv0.8.1, publishing npm or movingv1. - CI evidence: run
33319363473concluded success. All macOS/Ubuntu Node 22/24 jobs passed lint, tests and shell smoke; Ubuntu/Node 22 also installed checksum-pinned Gitleaks 8.30.1 and OSV-Scanner 2.5.0 and passed the real-adapter fixtures. ShellCheck and repository self-audit passed; dependency-review was correctly skipped on the unsupported push event. - CodeQL evidence: run
33319363476concluded success on the same commit and produced the P8 alert outcomes above. No failed hosted check was rerun or hidden. - Self-audit artifact: its checksum manifest verified. JSON recorded zero active, zero unknown and
one visible suppressed MEDIUM finding;
report.jsonSHA-256 isb3028306b46edb2ba2e26d584f68d9b5bd925e55d75752bd9d3d83e774e74f46. The suppression is a policy disposition and the report is not repository-safety evidence. - Governance/alert evidence: main, tag rules, release environment, Dependabot, CodeQL, Issues 3/6/7 and PRs 8/9 were re-read as recorded in P8. No unavailable setting was marked passed.
- Evidence-closeout boundary: this P8/P11 documentation commit is a bounded, evidence-only delta.
It must receive its own exact hosted checks before tagging. The trusted-main release workflow
independently requires the tag source, dispatch SHA,
mainSHA and six required successful check SHAs to agree, so the earlier run cannot authorize a changed release source. - Residual limitations: immutable signature, public assets/attestations, npm provenance, verified
install, full-SHA Action consumption and signed
v1promotion remain pending P12. - Next phase: after exact hosted checks pass on this evidence commit, sign and publish the immutable
v0.8.1 release, verify npm/install/Action, then perform the pending/final
v1promotion.
- Final immutable source:
6e581adcac7a0433ec6428d8080d20761dfc3a93; exact-source CI33319821767and CodeQL33319821731passed before publication. - Signed/public release: annotated tag object
69ed5f3dac996e44df62dbd7b5137eb97ef19e6bpeels to the exact source and verifies against.github/release-signers. Release workflow33320019069published release ID379322728; all four public asset digests, the 569-entry manifest and GitHub attestation verified. - npm: trusted-publishing workflow
33320091098publishedweb-app-security-skill@0.8.1with SLSA provenance andgitHeadequal to the release source. All 221 package files matched the signed source archive byte for byte; fresh-cachenpx ... versionreturned 0.8.1. - Installer trust: commit
4471a347156ed319a4d4f1262d5db5b508ee8d0dadded only the observed v0.8.1 asset identities and changed the verifier default. Its CodeQL run33320234387passed; CI33320234456correctly failed because the still-v0.8.0 public state disagreed with the new verifier. The state contract blocked a partial transition rather than silently accepting it. - Current boundary:
stableActionand signedv1still identify v0.8.0. No v0.8.1 Action or verified-installation claim is made until bootstrap and consumer gates pass. - Next step: synchronize observed Release/npm/installer facts, obtain a green exact commit, pin bootstrap to that verifier blob, then run clean-room installation and the pending/final Action promotion lifecycle.
- Public-state synchronization commit
0e53aaeb962d51f245b909de803e3fbd12c06b1dpassed CI33320577554and CodeQL33320577552; the four platform/Node jobs, real adapters, ShellCheck and production-scope self-audit all completed successfully. - The verifier blob at that exact green commit has SHA-256
d5e9f4ce50d9c38ef3502d512af1f342e80edd96844351d6134594de75b2edb8. The bootstrap, release contract and bilingual verification guide now pin the same commit and digest. - The v0.8.1 release-state migration test now models immutable publication preceding signed
v1promotion, using a verified annotated tag object in its pending-state fixture instead of assuming the published version and stable alias always advance atomically. - Current boundary: the updated bootstrap has not yet passed its own hosted checks or an isolated
attestation-required all-target installation.
v1remains unchanged at v0.8.0. - Next step: pass focused bootstrap/release tests and exact hosted checks, then execute the isolated public installer before Action promotion.
- Bootstrap identity: commit
0d488226ac55036b8871ff12b5572e697ec37bb7pins verifier commit0e53aaeb962d51f245b909de803e3fbd12c06b1dat SHA-256d5e9f4ce50d9c38ef3502d512af1f342e80edd96844351d6134594de75b2edb8; the bootstrap blob itself has SHA-2560b9c43d22c886f1f5394613800701eeeb1919a858168c5ca678f227ba0306c95. Exact-source CI33320776213and CodeQL33320776165both succeeded. - Isolated public install: a fresh temporary HOME ran the pinned public bootstrap with explicit
--version 0.8.1 --attestation required --target all. GitHub attestation verification passed; Claude, Codex and CLI surfaces installed as v0.8.1; the installed CLI returnedWeb App Security Skill 0.8.1. An earlier attempt without authenticatedghevidence failed as required and was not counted as a pass. No credential value was written to the log. - Public entrypoint correction: the bilingual README and verified-installation guides now pin the
bootstrap commit/digest above and use v0.8.1 asset names. Immutable Action examples and the
immutable-onlyconsumer now pin release source6e581adcac7a0433ec6428d8080d20761dfc3a93; v0.8.0 remains named only as the current movingv1target until promotion completes. - Regression gate:
test/v081-release-workflow-contract.test.mjsnow requires the exact v0.8.1 immutable source and rejects the prior v0.8.0 source. The focused workflow, release-contract, release-state, bootstrap and document checks exited 0; Ruby parsed the changed workflow andgit diff --checkexited 0. A first attempt to call nonexistentscripts/check-yaml.mjsfailed withMODULE_NOT_FOUND; it was a mistaken validation command, not a product result, and was replaced by the repository-available Ruby YAML parse. - Current boundary: this public-entrypoint delta is local until its exact commit passes hosted CI
and CodeQL.
v1still peels to v0.8.0 and no promotion state has begun. - Next step: commit and push this bounded delta, wait for exact-source hosted checks, rerun the published README bootstrap once, then dispatch the immutable-only Action consumer.
- Public-entrypoint commit
1e23b1bce3c59d481734c30785bd7085498ace02passed CI33321240947and CodeQL33321240956. The CI result includes four Node/OS jobs, production self-audit, ShellCheck and the Ubuntu/Node 22 pinned real-adapter fixtures; dependency review was correctly skipped for a push event. - The exact published README bootstrap was downloaded from commit
0d488226ac55036b8871ff12b5572e697ec37bb7, matched SHA-2560b9c43d22c886f1f5394613800701eeeb1919a858168c5ca678f227ba0306c95, then installed explicit v0.8.1 into a fresh HOME with--attestation required --target all. Attestation passed; all three surfaces installed; the CLI returnedWeb App Security Skill 0.8.1. - Immutable consumer run
33321407515succeeded. It consumed Action source6e581adcac7a0433ec6428d8080d20761dfc3a93by full SHA and verified the bounded route/access artifact. The movingv1consumer and final-state jobs were skipped by theimmutable-onlyphase. - Promotion lease: remote signed tag object
3e44c123d45f5fc06fa437fe1fbd58a71c5aaaa8still peeled to v0.8.0 source119cbcc7f8d327482df8abfa50a4af0b69fcceeeand verified against the signer policy. The state transition CLI recorded pending v0.8.1 source6e581adcac7a0433ec6428d8080d20761dfc3a93plus that exact prior object.v1has not moved. - Pending-gate correction: the first focused run showed
test/release-state.test.mjsstill required the live file to be final even though the production validator accepted the designed pending state. The test now accepts only the two exact v0.8.1 lifecycle records: old stable source plus exact pending version/source/prior object, or new stable source plus cleared final state. Its isolated repository exercise covers old signed alias, pending alias, new signed alias, final and stale-alias rejection. Release-state and transition tests then exited 0. - Local-execution deviation: one public-install command was rejected before process start because its cleanup trap used a locally prohibited deletion form. The same verification was rerun without cleanup; its temporary evidence paths were retained. This is not an installer failure.
- Next step: publish and host-verify the pending state commit, then create and locally verify a new
signed annotated
v1object and push it only with the exact prior-object lease.
- Pending source: commit
33884e8b6b12f9ad572fe69a348e9879016ca524passed CI33321543906and CodeQL33321543856, including all four matrix jobs, real adapters, production self-audit and ShellCheck. No tag moved before these checks succeeded. - Exact alias mutation: signed annotated tag object
c7482458f0ba9a86c1531651af9b64be61286e70peels to release source6e581adcac7a0433ec6428d8080d20761dfc3a93. Local signer-policy verification passed; GitHub returnedverified=trueand reasonvalid. The push used force-with-lease against exact prior object3e44c123d45f5fc06fa437fe1fbd58a71c5aaaa8; the approved administrator bypass was recorded. - Consumer evidence: promotion run
33321731609succeeded. It consumed the immutable source and signedv1, verified passive success, explicit authorization rejection, no active-probe request, Release/npm identities, pending public state and an attestation-required all-target install. Its 90-day artifact records the pending commit and both consumer outcomes. - Final transition:
action-promotion-state.mjs finalizeaccepted only the same expected source, changedstableAction.sourceCommitto the release source and cleared pending-only fields. The durable final live-verification record is not yet claimed. - Final-fixture correction: after the real local
v1ref moved, the release-state test could no longer obtain the historical old object by resolving currentv1. Its isolated old-state model now uses the signed immutablev0.8.0tag object and asserts that it peels to the exact prior stable source; the live pending-state branch still requires the actual historicalv1object. - Next step: push and host-verify the final state, dispatch
phase=finalwith promotion run33321731609, verify its Release asset and then record P12 completion.
- Final tracked state: commit
16c05ac009dc374e9729f3c608e5779546d91e8arecordsstableAction.sourceCommit=6e581adcac7a0433ec6428d8080d20761dfc3a93with promotion statefinaland no pending-only fields. CI33321898478and CodeQL33321898475both succeeded on that exact commit. - Durable verification: final workflow
33322069144accepted only retained promotion run33321731609, re-bound it to the finalized tracked state and completed successfully. Itsweb-app-security-skill-0.8.1.live-verification.jsonworkflow artifact and GitHub Release asset are byte-identical. - Release asset: the downloaded JSON has SHA-256
0fae8eaa68bafe35b52e8ed2c3b22b92e49c7b91fc58f9d83e6ed99210f2c6fa, equal to GitHub's recordedsha256:digest. It recordsstate=live_verified, version0.8.1, release source6e581adcac7a0433ec6428d8080d20761dfc3a93and eightverifiedgates covering assets, tag, GitHub/npm provenance, installer, immutable consumer,v1consumer and alias state. - Final ref check: remote
v0.8.1object69ed5f3dac996e44df62dbd7b5137eb97ef19e6band signed remotev1objectc7482458f0ba9a86c1531651af9b64be61286e70both peel to the release source. GitHub reports thev1signature verified with reasonvalid; npmgitHeadremains the same source. - P12 boundary: v0.8.1 publication is complete. The moving alias and solo-maintainer administrator bypass retain the documented limitations; no precision/recall, repository-safety, WSL2 or independent-review claim was added.
| Phase | Status | Exit artifact |
|---|---|---|
| P0 evidence/decisions | complete | approved plan and decision record |
| P1 failing contracts | complete | pre-fix failure ledger |
| P2 built-in scope | complete | canonical scope implementation and tests |
| P3 adapter scope | complete | adapter scope matrix evidence |
| P4 suppression | complete | schema/render/gate/baseline evidence |
| P5 self-audit | complete | production-scope self-report and alert ledger |
| P6 module/redaction | complete | focused regression evidence |
| P7 release workflow | complete | local trust-boundary fixtures |
| P8 platform governance | complete | live API evidence and Issue comments |
| P9 documentation | complete | synchronized public contracts |
| P10 local candidate | complete | exact candidate and test inventory |
| P11 hosted candidate | complete | exact-commit CI/CodeQL/self-audit evidence |
| P12 public release | complete | immutable release/npm/install, signed v1 and durable live verification |
The release may still state all of the following openly:
- built-in detectors remain bounded static rules, not whole-program taint analysis;
- a suppression records accepted policy, not proof that a condition is safe;
- restricted Gitleaks history may remain unavailable if exact path-bounded history scanning is not demonstrated;
- conditional Node exports may remain partial when runtime conditions select different files;
- moving
v1is convenient, not immutable; full-SHA consumers remain the strongest pin; - a single-maintainer repository cannot provide independent code review by configuration alone;
- branch/ruleset controls reduce accidental or unauthorized ref mutation but do not prove GitHub account security;
- WSL2 remains unsupported until Issue 3 obtains a maintained clean environment;
- CodeQL/test disposition and a clean self-audit do not establish production vulnerability precision or repository safety.