Skip to content

QA hardening: 16 bug fixes + measured coverage/mutation/fuzz gates#13

Merged
code-with-rashid merged 2 commits into
mainfrom
qa/adversarial-cycle-2
Jun 23, 2026
Merged

QA hardening: 16 bug fixes + measured coverage/mutation/fuzz gates#13
code-with-rashid merged 2 commits into
mainfrom
qa/adversarial-cycle-2

Conversation

@code-with-rashid

Copy link
Copy Markdown
Owner

Summary

A QA hardening pass that (1) fixes 16 root-caused bugs found by adversarial testing, and (2) makes the test suite measurably strong and resumable. Two commits, separated by intent.

1. Bug fixes (A–P) — 4dd1b06

Each fix has a regression test that fails before and passes after. Full per-bug repro/evidence in QA_LOG.md.

  • Validator (validate-response.ts): linear termination on recursive $ref/cyclic values; conjunctive composition keywords; array/union types (BUG-1/3/4/5/C)
  • Mock: adjacent-param ReDoS → linear; status clamped to 200–599 (writeHead crash + 1xx hang); guarded handler (BUG-B/H/K)
  • Runner: query before #fragment; redirect: manual so 3xx is observable (BUG-A/L)
  • Scaffold/importers/schema: slug dedup + non-empty names; .strict() nested objects (BUG-E/F/G/J)
  • Discovery: per-file error isolation (BUG-I)
  • Web server: CSRF defense (Origin == Host) + X-Frame-Options/CSP — blocks cross-site and cross-port loopback (BUG-M/N)
  • UI a11y: document-level editor shortcuts; aria-labels + sr-only h1 (BUG-O/P)
  • CLI: run exits non-zero on zero requests found (BUG-D)

2. Measured QA + CI gates — 7d1c791

  • Coverage: 86.93% → 95.18% lines, 79.06% → 86.52% branches (+69 tests). Notably the VS Code extension went 0% → 90%+ via a vscode module mock.
  • Mutation: Stryker on the contract validator → 85.4% (300 killed).
  • Fuzz: committed seeded, deterministic property-fuzz (5 invariant targets) + qa/corpus/ crash regressions.
  • Persistent state under qa/ so re-runs are cumulative (INVENTORY, COVERAGE, TRIED, SEEDS, corpus).
  • CI gates: coverage thresholds enforced (lines ≥90 / branches ≥85), gen:schema no-diff check, weekly Stryker job (break ≥80).

Behavior changes (flagged for review)

  • BUG-D: truspec run now exits non-zero when zero requests are found (was 0). Matches jest/pytest "no tests found" convention.
  • BUG-L: the runner no longer auto-follows redirects (redirect: manual), so a 3xx is observable and contract-validatable.

Verification

312 tests pass, typecheck 7/7, build 5/5, coverage gate green, JSON Schema in sync. The README's documented blog flow runs exactly as advertised in the built binary.

…s (A–P)

Root-cause fixes from a 10-cycle adversarial QA pass; each has a regression
test that fails before the fix and passes after. See QA_LOG.md for per-bug
repro/evidence/root-cause.

Core engine & spec:
- validator: linear termination on recursive $ref + cyclic values; conjunctive
  composition keywords (allOf/anyOf/oneOf no longer skip sibling constraints);
  array/union types honored (BUG-1/3/4/5/C)
- mock: collapse adjacent path params (O(n^k) ReDoS -> linear); clamp response
  status to a valid final range 200–599 (writeHead crash + 1xx client hang);
  guard the request handler so a bad request can't crash the server (BUG-B/H/K)
- scaffold: dedup colliding filename slugs; non-empty name fallback (BUG-F/J)
- runner: insert query params before any #fragment; redirect: manual so a 3xx
  is observable/contract-validatable (BUG-A/L)
- importers/schema: empty-name fallback on import; .strict() on nested schema
  objects so typo'd keys surface (BUG-E/G)
- discovery: per-file error isolation so one malformed file doesn't abort the
  whole listing (BUG-I)

Web server & UI:
- CSRF/clickjacking: require Origin to match Host + X-Frame-Options/CSP; blocks
  cross-site AND cross-port loopback requests (BUG-M/N)
- a11y: document-level editor keyboard shortcuts; aria-labels + sr-only h1 +
  landmark (BUG-O/P)
- XSS: confirmed React-escaped end to end (invariant test)

CLI:
- run: exit non-zero when zero requests are found, so a misconfigured CI path
  fails loudly instead of going green (BUG-D)
Drive the suite to objective thresholds and persist the state under qa/ so
re-runs are cumulative instead of redundant (INVENTORY, COVERAGE, TRIED, SEEDS,
corpus). No new product bugs — this exercises surfaces the suite left untested.

Coverage 86.93%->95.18% lines, 79.06%->86.52% branch (+69 tests):
- VS Code extension 0->90%+ via a `vscode` module mock (activate, all commands,
  CodeLens) — previously an entirely untested public surface
- cli/serve.ts and web/src/api.ts 0->covered
- CLI command error/--json/--live/--min branches; output formatters; Postman
  importer variants; mock generateExample/pickResponse
- exclude pure-type format/types.ts (no runtime code)

Mutation (Stryker 9.6.1) on the contract validator -> 85.4% (300 killed): added
exact-message/path/edge tests to kill survivors (no-coverage 37->1).

Fuzz: committed seeded, deterministic property-fuzz (5 invariant targets) +
qa/corpus crash regressions, replacing the campaigns' scratch harnesses.

CI gates:
- coverage thresholds enforced in vitest.config (lines>=90, branches>=85)
- pnpm gen:schema no-diff check (catches runtime/contract drift)
- weekly Stryker mutation job (break threshold 80)
@code-with-rashid code-with-rashid merged commit 900966d into main Jun 23, 2026
2 checks passed
@code-with-rashid code-with-rashid deleted the qa/adversarial-cycle-2 branch June 23, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant