Bumps package.json, .claude-plugin/plugin.json and the README badge to 7.8.2; adds the release entry to CHANGELOG.md, docs/version-history.md, the README recent-versions table and the CLAUDE.md highlights block. Also fixes test pollution introduced with the ide-extension regression suite: its temp roots used an `llmsec-jb-plugin-` prefix, and jetbrains-parser.test.mjs asserts globally that no `llmsec-jb-*` directory survives anywhere in tmpdir. The shared prefix made that assertion fail depending on test order — it passed on the first full run and failed on the next. Prefix is now `llmsec-nullmanifest-`. npm test: 1901/1901 green, three consecutive runs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
255 lines
26 KiB
Markdown
255 lines
26 KiB
Markdown
# LLM Security — Version history
|
||
|
||
Per-release notes for v7.0.0 onward. Imported from `CLAUDE.md` via `@docs/version-history.md`.
|
||
|
||
## v7.8.2 — Silent-failure fixes from the completion review (HIGH)
|
||
|
||
Security patch covering five defects found in the v7.8.1 completion review. No
|
||
feature changes; full suite green at 1901/0 (1865 + 36 new regression tests).
|
||
|
||
The common thread in four of the five is **silent failure**: the scanner or
|
||
hook reported success while the check it is named for did not run. That is the
|
||
worst failure mode for a security tool, because a clean report is
|
||
indistinguishable from a clean target.
|
||
|
||
- **`hooks/scripts/pre-bash-destructive.mjs`** — the rule named "Filesystem
|
||
root destruction (rm -rf /)" did not block `rm -rf /`. Its target
|
||
alternation `(?:\/|~|\$HOME)\b` ended in a word-boundary assertion, which
|
||
cannot hold after `/` or `~` at end-of-command. Measured: `rm -rf /`,
|
||
`rm -rf ~`, `rm -rf /*`, `rm -fr /` and `sudo rm -rf /` all fell through to
|
||
WARN — advisory only, exit 0, command executed. `rm -rf $HOME` and
|
||
`rm -rf /usr` were blocked, which is why the gap survived: the rule looked
|
||
functional from either end. The `\b` now sits on the `$HOME` alternative
|
||
alone, so `$HOMEDIR` is still not swallowed. The prior test file had encoded
|
||
the defect as expected behaviour, with a NOTE attributing it to merged `-rf`
|
||
flags — a misdiagnosis, since `rm -rf /etc` blocks fine with merged flags.
|
||
|
||
- **`scanners/entropy-scanner.mjs`** — the "test fixtures intentionally contain
|
||
example secrets" suppression matched against the **absolute** path. Any
|
||
ancestor directory name containing `test`, `spec`, `fixture` or `mock`
|
||
therefore suppressed every entropy finding in the whole target: a repository
|
||
cloned into a CI workspace, or checked out beneath a folder named `testing`,
|
||
reported zero secrets with status `ok`. The rule now keys off the path
|
||
relative to the scan root, which was already computed and passed alongside
|
||
it. Genuine fixture suppression (a `*.test.mjs` file, a relative `tests/`
|
||
directory) is unchanged.
|
||
|
||
- **`scanners/ide-extension-scanner.mjs`** — `parseVSCodeExtension` signals
|
||
failure as bare `null`; `parseIntelliJPlugin` signals it as a **truthy**
|
||
`{ manifest: null, warnings }`. Only the former was guarded, so all five
|
||
JetBrains failure paths (no `lib/`, `lib/` not a directory, `lib/`
|
||
unreadable, no jars, no extractable jar) reached `manifest.hasSignature` and
|
||
threw. `mapConcurrent` awaited without a per-item catch, so `Promise.all`
|
||
rejected and the entire ide-scan aborted — one malformed plugin directory
|
||
took down the scan of every other installed extension, including, in an
|
||
audit context, a plugin that is malformed precisely because it is hostile.
|
||
|
||
- **`scanners/content-extractor.mjs`** — this is the remote-scan indirection
|
||
layer: agents are supposed to see a sanitized evidence package, never raw
|
||
hostile content. `stripInjection` scanned the raw text *and* its decoded
|
||
form, but removed matches with `sanitized.replace(match[0], …)` against the
|
||
raw text only. A decoded-only `match[0]` does not occur in the raw text by
|
||
construction, so the replace silently did nothing: the payload was handed to
|
||
the agent verbatim through `sanitized_content` while the report announced a
|
||
critical injection. Removal now redacts the offending source line, since
|
||
decoding is not length-preserving and decoded offsets cannot be mapped back.
|
||
A payload split across several lines still cannot be attributed; those
|
||
findings carry `unstripped: true` instead of failing quietly. Whole-file
|
||
redaction was rejected — `normalizeForScan` base64-decodes any long blob, so
|
||
a benign asset could blank a file's entire evidence.
|
||
|
||
- **`scanners/lib/ide-extension-parser.mjs`** — `decodeEntities` guarded
|
||
`parseInt` with `Number.isFinite`, which bounds nothing, so a character
|
||
reference above `0x10FFFF` raised `RangeError` in `String.fromCodePoint`.
|
||
Contrary to how this was filed, the documented no-throw contract held: the
|
||
per-field `safe()` wrapper catches it. The real effect was quieter — the
|
||
field was replaced with `''`, so a `<name>` carrying one such reference
|
||
parsed as an empty name and name-based checks (JetBrains typosquat
|
||
detection) ran against nothing. Severity is below HIGH: a document with a
|
||
code point above `0x10FFFF` is not well-formed XML, so IntelliJ would reject
|
||
the plugin as well. Undecodable references are now left literal.
|
||
|
||
## v7.8.1 — Auto-cleaner command-injection fix (CRITICAL)
|
||
|
||
Security patch for a CRITICAL defect introduced with the v7.8.0 auto-cleaner
|
||
hardening pass. No feature changes; full suite green at 1865/0.
|
||
|
||
`scanners/auto-cleaner.mjs` validated candidate `.mjs`/`.js`/`.cjs` content by
|
||
shelling out to ``node --check "${tmpPath}"`` via `execSync`. `tmpPath` is
|
||
derived from the finding's `file` field — an untrusted scanned-repo filename.
|
||
The F-2 containment guard that landed in v7.8.0 verifies the resolved path
|
||
stays inside the scanned tree, but performs no shell-metacharacter handling, so
|
||
a filename whose `"` terminates the interpolated quote injects a second
|
||
command. Because `/security clean` runs in live mode by default, scanning a
|
||
hostile repository was sufficient to execute attacker-chosen commands locally.
|
||
The defect was reproduced with a live proof-of-concept before being fixed.
|
||
|
||
Both subprocess sites now use `spawnSync` with an argv array — the syntax check
|
||
and the CLI's inline scan-orchestrator fallback — so no shell interprets a path.
|
||
As defense-in-depth, `applyFixes()` additionally refuses any finding whose
|
||
`file` carries shell or control metacharacters, surfacing it as `skipped`.
|
||
|
||
Regression coverage is deliberately split across both layers
|
||
(`tests/scanners/auto-cleaner-rce.test.mjs`): one test drives `validateContent`
|
||
directly to prove the shell is gone, because the metacharacter guard would
|
||
otherwise stop the hostile input before it reached the sink and the test would
|
||
pass without testing the fix.
|
||
|
||
## v7.8.0 — Trigger, signature, and AST-taint scanners
|
||
|
||
Three new deterministic deep-scan scanners (TRG/SIG/AST), each with its own
|
||
finding prefix, OWASP/AST mapping, policy block, fixtures, and graceful-skip
|
||
behaviour. They target the skills/agents activation and code surface that the
|
||
permission and shape-based scanners do not cover. Built behind a security-fix
|
||
gate — the F-1/F-2/F-3 shell-injection and path-traversal fixes landed first.
|
||
No existing scanner, hook, or command behaviour changes; full suite green
|
||
(1863 tests, 0 fail).
|
||
|
||
- **TRG — trigger/activation-abuse** (`scanners/trigger-scanner.mjs`).
|
||
Inspects command/agent/skill `name` + `description` frontmatter for three
|
||
activation-surface abuses: `TRG-shadow` (name collides with a built-in
|
||
command/tool and intercepts it), `TRG-baiting` (description uses
|
||
maximally-activating phrases — "anything", "always", "all files" — to bait
|
||
indiscriminate invocation), and `TRG-broad` (a generic name plus a
|
||
universal-applicability claim, so the unit auto-activates beyond its stated
|
||
purpose). Skills/agents auto-activate on their description, so this is a
|
||
skill-native surface not covered by the permission or taint scanners.
|
||
Descriptions pass through the decode pipeline (zero-width strip → homoglyph
|
||
fold → `normalizeForScan`) first, so obfuscated baiting still trips.
|
||
Thresholds and the phrase/built-in lists are overridable via
|
||
`.llm-security/policy.json` (`trg`). OWASP LLM06 (excessive agency); AST04.
|
||
|
||
- **SIG — known-bad-identity signatures** (`scanners/signature-scanner.mjs`).
|
||
A pure-Node signature engine for known-malware *identity* — webshells,
|
||
reverse shells, cryptominers, hacktools — complementary to the shape-based
|
||
entropy/taint scanners. Unlike a raw byte-matcher (e.g. YARA), every
|
||
signature is tested against both the raw bytes and the project decode
|
||
pipeline (base64/hex/url/entity/unicode decode, homoglyph fold, rot13), so
|
||
obfuscated known-malware a byte-matcher misses is still caught. Rules ship
|
||
in `knowledge/signatures.json`; families are policy-selectable. OWASP LLM03
|
||
(supply chain) primary; LLM02.
|
||
|
||
- **AST — Python taint analysis** (`scanners/ast-taint-scanner.mjs`). Shells
|
||
out to a PARSE-ONLY `python3` helper (`scanners/lib/py-ast-taint.py`) for
|
||
variable-level, scope-aware taint analysis of Python skill code — higher
|
||
recall/precision than the ~70%-recall regex `taint-tracer.mjs`. The helper
|
||
only `ast.parse`s the target and never executes it, so analysing hostile
|
||
code is side-effect-free. Falls back to the regex tracer whenever `python3`
|
||
is unavailable, so the scan never hard-fails. OWASP LLM01, LLM02; AST02.
|
||
|
||
Packaging/wiring: `TRG`/`SIG`/`AST` registered as valid finding prefixes
|
||
(`scanners/lib/output.mjs`); all three wired into the scan orchestrator and
|
||
policy loader; `knowledge/` added to the `package.json` `files` whitelist.
|
||
|
||
## v7.7.2 — Language consistency pass
|
||
|
||
Norwegian had crept into surface text across v7.5–v7.7. Per the
|
||
`~/.claude/CLAUDE.md` convention (English for code and documentation,
|
||
Norwegian for dialog only), this release translates: the HTML Report-step in
|
||
all 18 skill commands, the canonical CLI renderer
|
||
`scripts/lib/report-renderers.mjs` (display strings + JS comments), the
|
||
playground UI strings, the `skill-scanner-agent` and `mcp-scanner-agent`
|
||
system prompts, the playground architecture prose + Recent versions table in
|
||
the plugin `README.md`, the v7.7.x highlights in the plugin `CLAUDE.md`, the
|
||
llm-security entries in the marketplace root `README.md` + `CLAUDE.md`, and
|
||
six table cells in `docs/scanner-reference.md`. Demo-state fixture content
|
||
for the `dft-komplett-demo` project (intentional Norwegian persona) and
|
||
regex alternations that match Norwegian-language report markdown
|
||
(`/^high|^høy/`, `/resolution|løsning/`) were preserved. CHANGELOG and this
|
||
version-history file were deferred per operator decision — they remain in
|
||
the language they were written in. No scanner, hook, or behavior changes —
|
||
purely surface text.
|
||
|
||
## v7.0.0 — Severity-dominated risk scoring (v2 model, BREAKING)
|
||
|
||
Three changes target the false-positive cascade on real codebases (hyperframes.com gave `BLOCK / Extreme / 100`, ~70% noise):
|
||
|
||
1. **Risk-score v2 formula** (`scanners/lib/severity.mjs`) — severity-dominated, log-scaled within tier. Replaces v1 sum-and-cap that collapsed every non-trivial scan to 100/Extreme. Tiers: critical → 70–95, high only → 40–65, medium only → 15–35, low only → 1–11. Verdict cutoffs realigned to new bands (BLOCK ≥65, WARNING ≥15). `info` findings are observability-only — counted in OWASP aggregates but contribute zero to risk_score, verdict, and riskBand (B3, v7.2.0 — was undocumented pre-7.2.0). See `severity.mjs` JSDoc for full contract.
|
||
2. **Rule-based entropy scanner with file-extension skip, 8 line-level suppression rules, and configurable policy** — extensions skipped (`.glsl/.frag/.vert/.shader/.wgsl/.css/.scss/.sass/.less/.svg/.min.*/.map`); line-suppression rules (GLSL keywords, CSS-in-JS, inline SVG, ffmpeg `filter_complex`, User-Agent strings, SQL DDL, `throw new Error(\`...\`)`, markdown image URLs). Configurable via `.llm-security/policy.json` `entropy` section (thresholds, `suppress_extensions`, `suppress_line_patterns`, `suppress_paths`). Envelope `calibration` block reports skip counters + effective thresholds + policy source.
|
||
3. **DEP typosquat allowlist expansion** — 22 npm + 5 PyPI entries for short-name tools that tripped Levenshtein detection on every modern codebase (`knip`, `oxlint`, `tsx`, `nx`, `rimraf`, `uv`, `ruff`, etc.).
|
||
|
||
See `docs/security-hardening-guide.md` §6 for the calibration story.
|
||
|
||
## v7.1.1 — Scan-rapport narrative coherence (patch)
|
||
|
||
Three coordinated edits address the whiplash symptom that survived v7.0.0 (numbers fixed, narrative still walked findings back as "false positive" in prose):
|
||
(a) `agents/skill-scanner-agent.md` Step 2.5 mandates context-first severity assignment — every signal has exactly one disposition (suppressed OR reported), no per-finding walk-back; (b) `templates/unified-report.md` gains a `### Narrative Audit` block in Executive Summary surfacing `summary.narrative_audit.suppressed_findings.{count, by_category}` from the agent's trailing JSON; (c) both files updated from stale v1 risk-formula constants to the v2 model that has been authoritative in `severity.mjs` since v7.0.0. Counter is distinct from the existing top-level `output.suppressed` (`.llm-security-ignore` rule integer). Out-of-scope but flagged: `commands/scan.md:113-114` retains the v1 formula; resolution deferred to Batch B.
|
||
|
||
## v7.3.0 — MCP cumulative-drift baseline (Wave C of Batch C)
|
||
|
||
Closes E14 from `docs/critical-review-2026-04-20.md`. The `mcp-description-cache.mjs` schema gains a sticky `baseline` slot per tool plus a 10-event rolling `history` array (FIFO). Cumulative drift = `levenshtein(current, baseline) / max(|current|, |baseline|)`; when the ratio crosses `mcp.cumulative_drift_threshold` (default 0.25), `post-mcp-verify.mjs` emits a separate MEDIUM `mcp-cumulative-drift` advisory. The existing per-update >10% drift signal is unchanged — both fire independently. Slow-burn rug-pulls that keep each update under the per-update threshold but cumulatively diverge from baseline are now caught. Baseline survives the 7-day TTL purge so detection persists across the full window. New `/security mcp-baseline-reset` slash command (plus `scanners/mcp-baseline-reset.mjs` CLI: `--list`, `--target <tool>`, or no-args clear-all) lets the user acknowledge a legitimate MCP server upgrade — clearing the baseline causes the next call to seed a fresh one from the incoming description; description, firstSeen, lastSeen, and history are preserved for audit. `LLM_SECURITY_MCP_CACHE_FILE` env var overrides the cache path for end-to-end testing without polluting the user's real `~/.cache/llm-security/mcp-descriptions.json`.
|
||
|
||
## v7.3.0 — Env-var deprecation warnings (D3 of Batch C, Wave D)
|
||
|
||
Closes 8.7 from `.claude/projects/2026-04-29-batch-c-scope-finalize/plan.md`. `scanners/lib/policy-loader.mjs` exports a new helper `getPolicyValueWithEnvWarn(section, key, envVarName, defaultValue)` — env still wins per Preferences (existing behaviour), but when both the env-var AND the `policy.json` key are explicitly set, the helper emits a single per-process stderr line: `[llm-security] Deprecation: env-var ${ENVVAR} will be removed in v8.0.0; policy.json key ${section}.${key} also set — env wins for now. Suppress with LLM_SECURITY_DEPRECATION_QUIET=1.` Module-scoped `Set` dedupes per env-var name across call-sites. Four overlapping vars are wired through the helper: `LLM_SECURITY_INJECTION_MODE` ↔ `injection.mode` (in `pre-prompt-inject-scan.mjs`), `LLM_SECURITY_TRIFECTA_MODE` ↔ `trifecta.mode` and `LLM_SECURITY_ESCALATION_WINDOW` ↔ `trifecta.escalation_window` (in `post-session-guard.mjs`), `LLM_SECURITY_AUDIT_LOG` ↔ `audit.log_path` (in `scanners/lib/audit-trail.mjs`). `DEFAULT_POLICY` gains `trifecta.escalation_window: 5` to close the gap noted in the plan revisions table (M10). Env-only vars without policy.json equivalents (`LLM_SECURITY_UPDATE_CHECK`, `LLM_SECURITY_PRECOMPACT_MODE`, `LLM_SECURITY_PRECOMPACT_MAX_BYTES`, `LLM_SECURITY_IDE_ROOTS`, `LLM_SECURITY_MCP_CACHE_FILE`) are unchanged — they emit no deprecation signal because there is nothing to deprecate yet.
|
||
|
||
## v7.5.0 — Playground (additive surface, no scanner/hook behavior changes)
|
||
|
||
Single-file SPA at `playground/llm-security-playground.html` (~10 200 lines) for onboarding, demo og workshop-bruk uten Claude Code-installasjon. Parser + renderer for alle 18 `produces_report=true`-kommandoer i `CATALOG`. State i IndexedDB primær (`llm-security-playground-v1`) med localStorage-fallback, sirkelfri Proxy + EventTarget store, microtask-batchet render. Theme-bootstrap med FOUC-prevention. 4 overflater: onboarding (5 grupper) → home (3 tracks) → catalog (20 kommandoer) ⇄ project (rapporter / oversikt / kontekst / eksport). Demo-state har tre prosjekter inline; `dft-komplett-demo` har alle 18 rapporter ferdig parsed for klikk-gjennom. Vendor-synket design-system under `playground/vendor/playground-design-system/` (sjekksum-låst via `MANIFEST.json`, redigeres aldri direkte). Test-fixtures under `playground/test-fixtures/` (én markdown-fil per kommando) er kontrakt-anker for parser-utvikling. Skjermdumper i `playground/screenshots/v7.5.0/`. Eksponerte vinduer-globaler for testing/automasjon: `__store`, `__navigate`, `__loadDemoState`, `__scheduleRender`, `__PARSERS`, `__RENDERERS`, `__CATALOG`, `__inferVerdict`, `__inferKeyStats`, `__renderPageShell`, `__handlePasteImport`. Inkluderer fix av `normalizeVerdictText` regex-rekkefølge: GO-WITH-CONDITIONS sjekkes før GO så betinget verdict ikke kollapser til ALLOW.
|
||
|
||
## v7.6.0 — Playground Tier 3-referanse-case (additive surface, no scanner/hook behavior changes)
|
||
|
||
Playgroundet er nå en visuelt og strukturelt fullført referanse-implementasjon for `shared/playground-design-system/` Tier 3-supplementet. 8 nye Tier 3-komponenter integrert i de 18 rapport-rendererne: `tfa-flow` + `tfa-leg` + `tfa-arrow` (lethal trifecta-kjede med `<button>`-elementer + ARIA-group/aria-label) i `renderScan` + `renderDeepScan`; `mat-ladder` + `mat-step` (5-trinns modenhets-stige med terskler 0/25/50/75/95% PASS) i `renderPosture`; `suppressed-group` (narrative-audit fra `summary.narrative_audit.suppressed_findings`) i `renderScan` + `renderDeepScan`; `codepoint-reveal` + `cp-tag`/`cp-zw`/`cp-bidi` (Unicode-steganografi side-ved-side reveal med U+200B-D|FEFF|2060|180E → `cp-zw`, U+202A-E|2066-9 → `cp-bidi`-detection) i `renderMcpInspect`; `top-risks` + `top-risk[data-severity]` (rangert top-funn-listing, semantisk `<ol>`, ekskluderer info-funn) i `renderScan`/`renderDeepScan`/`renderPluginAudit`/`renderPosture`/`renderAudit`; utvidet `recommendation-card[data-severity]` (severity-tinted advisory) på alle inline-bruk + nye per-bucket advisory-cards i `renderClean` + intro snapshot + diff-rows i `renderHarden` (action-mapping CREATE→positive / APPEND→medium / MERGE→low / SKIP→low); `risk-meter` (band-visualisering 0-100 med Low/Medium/High/Critical/Extreme bands) på 5 archetypes (scan, deep-scan, plugin-audit, audit, red-team); `card--severity-{level}` modifier på `findings__item`-cards. Wave 1 (Sesjon 2) la til `badge--scope-security` (identitets-chip), `verdict-pill-lg` med `__verdict`+`__sub` (erstatter custom verdict-pill på alle 18 rapport-typer), og DS Tier 3 `form-progress` + `fp-step` i onboarding-wizard. Wave 0 (Sesjon 1) slettet ~30 duplikat-CSS-deklarasjoner fra `<style>`-blokken (DS vinner cascade) og harmoniserte page-shell på alle 4 overflater. 5 nye DS-helpers: `renderToxicFlow`, `renderMatLadder`, `renderSuppressedGroup`, `renderCodepointReveal`, `renderTopRisks`. 2 nye normaliserings-helpers: `mapSeverityToCardLevel(input)` (severity + action-types til DS-konvensjoner) og `parseNarrativeAudit(md)`. 12 skjermdumper planlagt i `playground/screenshots/v7.6.0/`. A11Y-rapport oppdatert (`playground/A11Y-RAPPORT.md`) — WCAG 2.1 AA bekreftet, severity-soft fargepar verifisert, semantiske elementer (`<ol>`, `<button>`, `<section>`) erstatter generic `<div>`. Filendring totalt over 5 sesjoner: 10209 → 10677 linjer. Kjent begrensning: `parsed.findings` er tom for `deep-scan`/`audit` demo-fixturer (parser-begrensning, ikke fikset i v7.6.0 — sporet for v7.6.x patch).
|
||
|
||
## v7.6.1 — Playground visuell-patch (no scanner/hook behavior changes)
|
||
|
||
Seks bugs fanget av maintainer ved manuell verifisering i nettleser etter v7.6.0-release. Alle skyldtes mismatch mellom DS-klasser og hvordan playground-rendrere brukte dem (eller manglende DS-implementasjoner av klasser playground-rendrere antok eksisterte).
|
||
|
||
(1) `renderFindingsBlock` brukte `.findings` outer-class som DS har som 2-kolonners grid (`grid-template-columns: 360px 1fr`) for list+detail-panel-layout — playground brukte den uten detail-panel, headeren havnet i venstre 360px-kolonne, items i 1fr. Erstattet med `<section class="report-meta">` + `<h4>` + korrekt `findings__list > findings__group > findings__group-header + findings__items`-mønster.
|
||
(2) `.report-table` manglet helt i DS men brukes i 7+ rendrere (OWASP-kategorier, Supply chain, Scanner Risk Matrix, Plugin-meta, Permission-matrise, Live-meter, Siste runs, Godkjenninger, Mitigation roadmap) — lagt lokal CSS-implementasjon i playground-HTML `<style>`-blokk (border-collapse, zebra-hover, header-styling).
|
||
(3) `renderPreDeploy` traffic-lights brukte `.sm-card__grade` som er fast 28×28 px (designet for én A-F-bokstav) — kuttet "PASS" til "AS" og "PASS-WITH-NOTES" til "PASS-WITH-..." i alle traffic-light-cards. Erstattet med bredde-tilpasset status-pill via inline styling (severity-soft + on tokens).
|
||
(4) Threat-model matrix-bobler ikke klikkbare — `<span>` uten event-handler. Erstattet med `<button type="button" data-threat-id>` + `aria-label`. Click-handler scroller til tilsvarende rad i Trusler-tabellen og fremhever den i 1.6 sek.
|
||
(5) Radar-labels overlappet ved 6+ akser — alle brukte `text-anchor="middle"` med samme offset. Økt SVG-størrelse fra 280×280 til 380×380, radius fra 105 til 125, bytter `text-anchor` fra `middle` til `start`/`end` basert på horisontal-posisjon (`Math.cos(ang)` > 0.2 / < -0.2 / mellom).
|
||
(6) `recommendation-card__body` tekstoverflyt på lange single-line tekster (vilkår, owner-tags, dato) — lagt `overflow-wrap: anywhere; word-break: break-word` i lokal `<style>`-blokk.
|
||
|
||
4/4 fix-spesifikke smoke-tester passerer + 18/18 renderere produserer fortsatt komplett HTML mot `dft-komplett-demo` (regresjons-test). Filendring 10677 → 10753 linjer (+76 netto).
|
||
|
||
## v7.7.0 — HTML-rapport for alle 18 skill-kommandoer
|
||
|
||
Alle 18 `/security`-kommandoer som produserer rapport får nå en klikkbar `file://`-lenke til en self-contained HTML-versjon. Levert over 5 sesjoner (UX-arbeid + extract + CLI + wiring). Ingen scanner- eller hook-atferdsendringer — purely additive.
|
||
|
||
**Sesjon 1 (`0dc7ff4`) — Playground katalog list-view + builder-pane.** Katalog-overflaten fikk list-view (grid-toggle) + builder-pane med copy-knapp på alle 18 rapporter, så onboarding-flytene blir bredere/dypere uten å forlate playground-modusen.
|
||
|
||
**Sesjon 2 (`86d6ecd`) — Playground prosjekt-surface opprydding.** Stub-screen-håndtering (rapport ikke ferdig parsed → tydelig placeholder i stedet for tom panel), topbar-splitt (navigasjons-trinn vs. eksport-handlinger), generell DS-justering for projekt-overflate.
|
||
|
||
**Sesjon 3 (`fa5fb48`) — `scripts/lib/report-renderers.mjs` extract.** De 18 inline parserne + 18 inline rendererne i playground-HTML-fila flyttet til canonical ESM-modul (`scripts/lib/report-renderers.mjs`) med ren `import { PARSERS, RENDERERS } from './...'`-overflate. Playground beholder en inline-kopi (bit-identisk) fordi ESM `import` ikke fungerer fra `file://` uten Chrome/Firefox-flags. Canonical kilden + playground inline = to overflater, samme atferd.
|
||
|
||
**Sesjon 4 (`db80854`) — `scripts/render-report.mjs` CLI + 4 skills wired.** Ny zero-dep Node-CLI tar `commandId` + `--in`/`--out` (stdin/file/stdout-modus), bruker kebab→camel-konvertering så alle 18 commandIds fungerer automatisk. Output er self-contained HTML (~140 KB): inlines 6 DS-stylesheets (`tokens`, `base`, `components`, `tier2`, `tier3`, `tier3-supplement`) + lokal `.report-table`-implementasjon. Fonter ikke inlined (ville blåst opp HTML 7x til ~1 MB) — `tokens.css` har `-apple-system, BlinkMacSystemFont, system-ui` som fallback. Absolutte `file://`-paths i stdout for Ghostty cmd-click. Default output `reports/<command>-<YYYYMMDD-HHmmss>.html` relativt til CWD. 4 skills wired: `scan`, `audit`, `posture`, `deep-scan`.
|
||
|
||
**Sesjon 5 — 14 resterende skills wired + release.** `plugin-audit`, `mcp-audit`, `mcp-inspect`, `ide-scan`, `supply-check`, `dashboard`, `pre-deploy`, `diff`, `watch`, `registry`, `clean`, `harden`, `threat-model`, `red-team` — alle har nå en avsluttende "HTML Report"-step i sin skill-fil som instruerer Claude å (1) compute temp md-path, (2) Write hele markdown-rapporten verbatim, (3) kjøre CLI, (4) appende `> **HTML-rapport:** [Åpne i nettleser](file:///abs/sti.html)` til respons. v7.7.0 release (versjonsbump på tvers av `package.json`, `.claude-plugin/plugin.json`, README badge + state, CLAUDE.md header + state-seksjon, marketplace-rot-README).
|
||
|
||
Pre-existing `pre-compact-scan`-perf-flake (1000ms terskel under last) gjenstår — defer til v7.7.x patch.
|
||
|
||
## v7.7.1 — Playground UX-strip (no scanner/hook behavior changes)
|
||
|
||
Operatør-feedback umiddelbart etter v7.7.0-release: hjem-overflaten viste
|
||
fortsatt tre prosjekt-tracks (Re-onboard / Nytt prosjekt / Command-katalog)
|
||
selv om katalog-funksjonen var det operatøren ønsket å fremheve. Minimum-
|
||
strip levert som tre atomic commits (`b732eee` + `2a6f73f` + `81b7beb`):
|
||
|
||
(1) `renderActive()`-router tvinger alltid `activeSurface` til `'catalog'`.
|
||
Onboarding/home/project-render-funksjonene + state-strukturen er bevart
|
||
i kildekoden, men ikke rutbare før funksjonalitet legges til igjen.
|
||
Init-default endret fra `'home'` til `'catalog'`. Konsekvens: playgrounden
|
||
lander direkte i Command-katalog (alle 20 kommandoer i list-view med
|
||
builder-pane + copy-knapp fra sesjon 1).
|
||
|
||
(2) Topbar `Hjem` og `Re-onboard`-knapper fjernet fra primær navigasjon.
|
||
`Katalog`-knappen + Eksporter/Importer/tema-toggle beholdt. Project-state
|
||
forblir i IndexedDB men ingen UI-vei dit.
|
||
|
||
(3) Topbar breadcrumb erstattet `shared.organization.name` (demo-state-
|
||
orgnavn) med statisk `llm-security` som nøytralt scope-anker. Crumb-
|
||
parameter (f.eks. `Katalog`) beholdt som suffix.
|
||
|
||
Fix: hardkodet versjons-streng `'Plugin v7.6.1'` på linje 6933 i
|
||
`renderHome` (template-string-litteral som v7.7.0-grep-en ikke fanget)
|
||
synket til v7.7.1.
|
||
|
||
Versjonsbump i 9 filer (`package.json`, `.claude-plugin/plugin.json`,
|
||
plugin `README.md` badge + Recent versions-tabell, plugin `CLAUDE.md`
|
||
header + state-seksjon, `docs/version-history.md`,
|
||
`playground/llm-security-playground.html`, rot `README.md` plugin-entry,
|
||
rot `CLAUDE.md` plugin-katalog, `CHANGELOG.md` `[7.7.1]`-seksjon).
|
||
Onboarding-konseptet dokumentert som v7.8.0-kandidat (per-kommando
|
||
kontekst-injeksjon) i `ROADMAP.md`.
|