Skip to content

fix: unified remediation of consolidated audit findings (Phases 1-7)#2

Open
cryptoxdog wants to merge 4 commits into
mainfrom
fix/unified-remediation-phases-1-7
Open

fix: unified remediation of consolidated audit findings (Phases 1-7)#2
cryptoxdog wants to merge 4 commits into
mainfrom
fix/unified-remediation-phases-1-7

Conversation

@cryptoxdog

Copy link
Copy Markdown
Collaborator

Summary

Merges and remediates the overlapping findings from two independently-produced audit documents (consolidated-findings-plan.md: PRD-*/ICA-*, and consolidated-findings-remediation-plan.md: AUD-*/SEC-*/RAA-*/DWA-*), both audited against base_ref 87075d82. Cross-referencing them surfaced 25 raw finding IDs collapsing to 18 distinct defects, one confirmed false positive (AUD-003), and one critical release-blocking bug (ICA-002/ICA-003) that only one of the two documents caught.

  • Phase 1 — CI/test safety net (TEST-CI-GAP): add eslint.config.js + a real Vitest suite; wire npm test/npm run lint into ci.yml/publish.yml
  • Phase 2 — Critical bug fix (ICA-002/ICA-003): getDowngradedModel() now branches on provider/model-family; removes the unchecked as any cast that could send a GeneralModel string to the Perplexity API on any hard-throttled search task
  • Phase 3 — Pricing consolidation (PRICING-DRIFT): single canonical src/pricing.ts consumed by both openrouter.ts and general-matrix.ts
  • Phase 4 — Dead-wiring activation: disableSearch branch fixed, checkSurge()/resetGlobalMonthly() wrappers added, real CircuitBreaker implemented and wired into execute(), unused RoutingResult removed, swallowed fallback errors now accumulated (AUD-005)
  • Phase 5 — Security hardening: vision-URL SSRF allowlist (SEC-001), Zod runtime validation of TaskDescriptor/RouterConfig (SEC-002), error toJSON() redaction (SEC-003), npm audit --omit=dev CI gate (SEC-004)
  • Phase 6 — Contract docs (RAA-003): ARCHITECTURE.md + no-restricted-imports ESLint rule enforcing router-only-egress
  • Phase 7 — Re-baseline: ledger/baseline handoff doc closing out all 18 findings (WIP planning docs, not tracked in git)

Full defect-by-defect disposition lives in src/docs/WIP/LLM-Router audits/unified-remediation-ledger.md (gitignored WIP doc, not part of this diff).

Note: this branch intentionally excludes a set of unrelated untracked repo-scaffold files present in the working tree (CODEOWNERS, ISSUE_TEMPLATE/, dependabot.yml, several l9-*.yml workflows, CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, SUPPORT.md) — those were not produced by this remediation session and are out of scope for this PR.

Test plan

  • npm run build — clean
  • npm run verify:types — clean
  • npm run lint — 0 errors (2 pre-existing, out-of-scope any warnings in vision/general-config branches)
  • npm test — 82/82 passing across 10 test files
  • npm audit --audit-level=high --omit=dev — 0 vulnerabilities
  • CI green on this PR (ci.yml now runs audit/build/typecheck/lint/test)

Made with Cursor

Merges and remediates the overlapping findings from
consolidated-findings-plan.md (PRD-*/ICA-*) and
consolidated-findings-remediation-plan.md (AUD-*/SEC-*/RAA-*/DWA-*),
both audited against base_ref 87075d8. 18 distinct defects closed;
see src/docs/WIP/LLM-Router audits/unified-remediation-ledger.md for
full deduplication rationale and per-ID disposition (not tracked in
git — WIP planning doc).

Phase 1 — CI/test safety net (TEST-CI-GAP: PRD-002/AUD-001/RAA-001)
- Add eslint.config.js (flat config, ESLint v9) and a real Vitest suite
- Wire npm test + npm run lint into ci.yml and publish.yml

Phase 2 — Critical live-traffic bug (ICA-002/ICA-003)
- getDowngradedModel() now branches on provider/model-family instead of
  always returning a GeneralModel
- Replace the unchecked `as any` cast in execute()'s Perplexity branch
  with a fail-closed isSonarModel() guard

Phase 3 — Pricing authority consolidation (PRICING-DRIFT: PRD-003/AUD-002/RAA-002)
- Extract canonical src/pricing.ts; openrouter.ts and general-matrix.ts
  both consume it instead of maintaining independent rate tables

Phase 4 — Dead-wiring activation & cleanup
- Implement the disableSearch branch (ICA-001/DWA-001): web_search_options
  is now omitted when search is disabled
- Add checkSurge()/resetGlobalMonthly() router wrappers (DWA-002/DWA-003)
- Implement a real CircuitBreaker, wired into execute() (DWA-005)
- Remove unused RoutingResult/ResolvedConfig types (DWA-004)
- Accumulate per-attempt fallback errors instead of discarding them (AUD-005)

Phase 5 — Security hardening
- validateImageUrl(): https-only + private/loopback/link-local hostname
  allowlist for vision image URLs (SEC-001, candidate CWE-918)
- src/schemas.ts: Zod validation of TaskDescriptor/RouterConfig at
  execute()/constructor entry (SEC-002)
- toJSON() redaction allowlists on PerplexityError/OpenRouterError/
  BudgetExhaustedError (SEC-003)
- npm audit --audit-level=high --omit=dev gate in ci.yml/publish.yml (SEC-004)

Phase 6 — Contract documentation (RAA-003)
- ARCHITECTURE.md documents module boundaries and router-only-egress
- no-restricted-imports ESLint rule enforces that only src/index.ts may
  import providers/* directly

Phase 7 — Re-baseline
- Ledger and prior-baseline handoff doc updated to close out all findings
  (WIP docs, not tracked in git)

82 tests across 10 files, 0 lint errors, 0 npm audit vulnerabilities
(prod deps), clean tsc build/typecheck.

Co-authored-by: Cursor <cursoragent@cursor.com>
@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

cryptoxdog and others added 3 commits July 20, 2026 03:04
Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	eslint.config.js
#	package.json
#	src/index.ts
#	src/types.ts
#	tests/budget.test.ts
#	tests/router.test.ts
Core commit 54a2f2fc (pinned via L9_CORE_REF) predates Core's own fix for a
provision-sdk bug where the cloned SDK's requirements.txt was never installed
before probing its CLI, causing `ModuleNotFoundError: No module named 'yaml'`.

Bump to Core main HEAD (d2c2cd7f), which fixed this the next day
(98f012f05b92, "provision: install SDK deps") and shipped two more
provisioning refinements since. Diffed the two commits via `gh api compare`
to confirm no breaking changes to the actions/inputs this workflow calls:
resolve-governance is untouched; provision-sdk, route-artifacts,
validate-bundle, and publish-analysis.yml changed only via backward-compatible
bug fixes. Bonus: also picks up a fix for route-artifacts' copy_exact()
raising SameFileError when the raw report is already at its routed
destination, matching this workflow's artifact layout.

Applied on this branch (not the original ci/l9-v2-setup) because PR #3 was
already merged into main by the time this landed, and the bug had propagated
to main and to this branch via that merge.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ublish

The first pin bump (d2c2cd7f) fixed Analyze (semgrep -> SDK) but surfaced a
second, deeper bug: at that Core commit, publish-analysis.yml's own nested
provision-sdk step is still pinned to an older, un-synced Core SHA
(4b6b7336...), which passes it the outer job's current sdk-revision
(6368ba17...) as an input. That older checkout's own
.l9/sdk-compatibility.yaml predates the SDK-pin bump, so it rejects
6368ba17... as an unlisted revision:

  provision-sdk: sdk-revision is not listed in .l9/sdk-compatibility.yaml

Core already fixed this in f8811650 ("fix(publish-analysis): bump internal
action refs to d2c2cd7 so publish provisions the current SDK pin (#33)").
Bump to Core main HEAD (89dcb36e) rather than the minimal fix commit --
diffed the two and confirmed only docs/template files changed in between, no
functional action code.

Co-authored-by: Cursor <cursoragent@cursor.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
C Security Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

💡 Need a hand with PR review? Try Gitar by Sonar!

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