diff --git a/.gitignore b/.gitignore
index 4f53639..ffc32a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,6 +71,8 @@ credentials.json
# Tests
# ===================
test-results/
+playwright-report/
+apps/docs/playwright-report/
# ===================
# Agents
diff --git a/AGENTS.md b/AGENTS.md
index 0366da7..04a30f9 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -266,7 +266,7 @@ See `.agents/README.md` for usage instructions.
## Version Information
-- **Repository**: https://github.com/miccy/dont-be-shy-hulud
+- **Repository**: https://github.com/miccy/worms-ctrl
- **License**: MIT
- **Maintainer**: @miccy
- **Status**: Active development (public release, seeking contributors)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 135edf2..e65136a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,10 +1,97 @@
# Changelog
+
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [Unreleased]
+
+### Added
+- **Path validation** — Added `validatePath()` utility to scanner to reject null bytes and empty/whitespace paths.
+- **Threat database** — Added `xz-utils-2024.json` threat profile to `packages/ioc/threats`.
+- **E2E Test Robustness** — Added escaping of regex special characters in E2E assertions for docs navigation.
+
+### Changed
+- **Scanner types** — `LockfileEntry.resolved` property made optional to accommodate bundlers/resolvers without integrity metadata.
+- **Documentation standardization** — Updated references in `bunfig-secure.toml`, `pnpm-workspace-secure.yaml`, and scripts to canonical `worms-ctrl` names.
+- **Scan Scripts** — Enhanced `comprehensive-scan.sh` output with clearer action instructions and `full-audit.sh` with the verified URL.
+- **Documentation**: Updated IOC database repository link to point to the new `worms-ctrl` repository in both English and Czech `ioc-database.md` reference pages.
+- **Dependencies**: Pinned `@types/bun` to `^1.3.13` in the `kb` package.
+
+### Security
+- **SSRF Hardening** — `isPrivateIp` now correctly parses IPv4-mapped IPv6 addresses, drops full `169.254.0.0/16` subnet, and `fetch` prevents arbitrary redirects (`redirect: 'manual'`).
+
+## [2.0.0] - 2026-05-04
+
+### ⚠️ Breaking Changes
+
+- **Stricter threat schema validation** — `sha256` fields in `file_artifacts` now require a valid 64-character hex hash or `null` (empty strings are rejected). IOC and remediation string arrays now reject empty strings.
+- **pnpm parser output** — `resolved` and `integrity` are now separate fields (previously `integrity` was conflated into `resolved`).
+
+### Added
+
+- **SSRF protection** — `ingest.ts` now blocks fetches to private/internal networks, adds fetch timeouts (15s), and enforces response size limits (2 MB).
+- **Alias descriptor parsing** — Bun and pnpm parsers now correctly handle npm alias descriptors (`alias@npm:real@1.2.3`) by extracting the alias name.
+- **Per-entry threat loading** — Both `packages/ioc/index.js` and `packages/scanner/src/threats.ts` now load threat files individually, so one malformed JSON file doesn't drop the entire catalog.
+- **Threat shape validation** — `readThreatObject()` in the scanner now validates the parsed JSON shape before indexing, preventing crashes on malformed threat files.
+- **Dynamic test discovery** — `threats.validate.test.ts` now validates all JSON files in the threats directory automatically instead of a hardcoded list.
+- **Path traversal security** — Added `validatePath()` utility to scanner with null byte and empty path rejection.
+
+### Fixed
+
+- **Bun lockfile deduplication** — Scanner now prefers `bun.lock` over `bun.lockb` when both exist, preventing duplicate findings.
+- **npm parser** — Skips workspace/link entries and root package (`""` key) in v3 lockfiles.
+- **Threat loader resilience** — `readdirSync` wrapped in try/catch to handle TOCTOU race after `existsSync`.
+- **`toFindingSeverity` switch** — Added default case to prevent `undefined` return for unexpected severity values.
+- **CLI output error handling** — `writeFileSync` failures now return a user-friendly error message instead of an unhandled exception.
+- **Empty hash indicators** — Replaced `sha256: ""` with `sha256: null` in `event-stream-2018`, `ctx-2022`, and `xz-utils-2024` threat profiles.
+- **Node ESM compatibility** — `packages/ioc/index.js` now uses `fs.readFileSync` for JSON loading instead of bare import assertions.
+- **Playwright config** — Added `stdout`/`stderr` pipe configuration for better CI debugging.
+- **Redundant wrapper** — Removed `parseNpmLock()` wrapper in `scan.ts` (calls `parseNpmLockfile()` directly).
+- **Top-level await** — Added documentation comment explaining intentional eager threat database initialization.
+
+### Changed
+
+- **Version bump** — `1.5.2` → `2.0.0`
+
+### Added
+
+- **Grant-ready threat catalog** — Added structured threat objects for `event-stream`, `node-ipc`, `ua-parser-js`, `ctx`, and `xz-utils` under `packages/ioc/threats/`.
+- **Threat catalog expansion** — Added `axios-2026`, `shai-hulud-2025`, and `teampcp-2026` threat objects plus fixture data for npm and PyPI compromise scenarios.
+- **AI ingestion skeleton** — Added `packages/engine/src/ingest.ts`, `prompt.ts`, and `validate.ts` for JSON-mode threat extraction with graceful OpenAI fallback behavior and Zod validation.
+- **Scanner validation flow** — Added scanner and engine validation plumbing for npm lock parsing, injection findings, and schema-based threat extraction support.
+- **Threat regression tests** — Added fixture-based `bun:test` coverage for malicious version matching, phantom dependency detection, threat schema validation, and clean baseline scans.
+- **Grant demo artifact** — Added a SARIF demo output for the axios compromise fixture under `examples/axios-compromise.sarif`.
+
+### Security
+
+- **Report Sanitization** — Implemented a centralized `redactSensitiveData` function in the Playwright HTML report to strip emails, tokens, secrets, and local paths from AI prompts.
+- **Payload Removal** — Removed the embedded base64 ZIP payload from the HTML report to prevent secret leakage and encourage CI artifact usage.
+
+### Fixed
+
+- **E2E Stability** — Corrected invalid Playwright assertions in `apps/docs` to use `toBeVisible()` and removed silent failures in table rendering tests.
+- **Git Hygiene** — Added `playwright-report/` to `.gitignore` to prevent committing generated test artifacts.
+
+### Changed
+
+- **Lockfile coverage** — Completed pnpm and Bun parser support and wired both into scanner dispatch.
+- **Threat-aware detection** — Scanner now cross-references `packages/ioc/threats/*.json` for known malicious versions and only emits injection findings for known phantom dependency IOCs.
+- **Python package coverage** — Added basic `requirements.txt` parsing so PyPI threat entries can be matched by the scanner.
+- **CLI flow** — Reworked the main CLI entry point to support `--format`, `--output`, and `--threats`, and to run through the scanner package end-to-end.
+- **Documentation** — Rewrote the root README and added `cs/README.md` with grant-focused positioning, AI architecture, quick start, and threat database coverage.
+- **Threat schema** — Upgraded `ThreatObject` to use structured IOC and reference objects, expanded ecosystem coverage for Linux/system incidents, and migrated the bundled threat catalog to the new format.
+- **CLI packaging** — Added a self-contained CLI bundle build with bundled threat catalog assets so published installs no longer depend on monorepo-only source paths.
+
+- **E2E Test Robustness** — Updated documentation tests to assert element visibility and existence unconditionally, preventing silent regressions in table rendering and page navigation.
+- **Threat Database Accuracy** — Added missing `oneday-test` malicious version and updated empty SHA256 fields to `null` with explanatory notes in `node-ipc-2022` and `ua-parser-js-2021` threat profiles.
+- **IOC helper consistency** — Made archived threat/profile helper lookups return synchronously instead of mixing plain objects with dynamic-import promises.
+- **Parser resilience** — Fixed scoped `pnpm` key parsing, restored `bun.lockb` fallback after text-lock read failures, and added safer `bun pm ls` timeout/error handling.
+- **Scanner output** — Fixed the `low` severity summary line formatting, removed duplicate verbose location output, and reject empty `--output=` CLI values with a clear error.
+- **Regression coverage** — Added tests for structured threat validation, publish-safe CLI argument parsing, pnpm/Bun parser edge cases, text formatter output, and synchronous IOC helper returns.
+
## [1.5.2] - 2026-04-21
### Changed
@@ -21,6 +108,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **Scanner Output** — Symmetrized naming of formatters (`formatJson`, `formatText`, `formatSarif`) and fixed broken exports in `@worms-ctrl/scanner`.
- **KB Engine** — Fixed asynchronous generator logic in `chunker.ts` and removed dead exports from `@worms-ctrl/kb`.
- **Process Suspension Safety** — Fixed remediation playbook phase mapping and type definitions for safe malware containment.
+- **`safe-suspend` Parameter Fix** — Removed unused `_dryRun` parameter and implemented its logic in `packages/remediation/src/scripts/safe-suspend.ts`.
### Added
diff --git a/README.md b/README.md
index 1dcb357..0fd00f0 100644
--- a/README.md
+++ b/README.md
@@ -1,70 +1,90 @@
-# 🪱 worms-ctrl
+# wormsCTRL

-> **Universal Supply Chain Audit Tool & Threat Knowledge Base**
-> Defending against registry-native worms, malicious packages, and CI/CD compromises.
+> Universal Supply Chain Audit Tool & Threat Knowledge Base for npm and adjacent open-source ecosystems.
-[](https://www.npmjs.com/package/@worms-ctrl/core)
[](LICENSE)
-[](CONTRIBUTING.md)
+[](https://github.com/miccy/worms-ctrl)
+[](https://bun.sh)
-## 🛡️ The Future of Supply Chain Defense
+Supply-chain attacks are growing because modern applications inherit trust from thousands of transitive packages, maintainer accounts, CI runners, and release pipelines they do not directly control. A single compromised publisher, malicious install script, or poisoned upstream artifact can now reach thousands of downstream builds in hours, which leaves solo developers and small teams with enterprise-grade risk but without enterprise-grade detection coverage. `wormsCTRL` exists to close that gap with auditable lockfile scanning, structured threat intelligence, and an AI-assisted ingestion pipeline that turns public advisories into machine-readable defensive knowledge.
-The evolution of software supply chain attacks has reached a critical point. Incidents like the [Shai-Hulud 2.0 npm worm](packages/ioc/archived/shai-hulud/) or the TeamPCP CI/CD compromise demonstrate the rise of self-propagating malware that leverages the trust of package registries to exfiltrate sensitive data.
+## Architecture
-**worms-ctrl** is an automated auditing tool and comprehensive Knowledge Base designed to:
-1. **Act as an Incident Response Tool:** Providing immediate audit capabilities and remediation steps when under attack.
-2. **Serve as a Threat Database:** Documenting historical threats (like Shai-Hulud) with exact Indicators of Compromise (IoCs).
-3. **Be AI-Agent Ready:** Exposing machine-readable Threat Models (JSON/YAML) that Autonomous Security Agents can consume to update defense mechanisms in real-time.
+```mermaid
+flowchart LR
+ A["Scanner
packages/scanner"] --> B["Engine
packages/engine"]
+ B --> C["Threat KB
packages/ioc + packages/kb"]
+ C --> D["CLI
apps/cli"]
+```
----
+- `Scanner` parses lockfiles from npm, Yarn, pnpm, and Bun to surface suspicious packages.
+- `Engine` converts advisories and blog posts into structured threat objects.
+- `Threat KB` stores documented incidents as JSON and exposes them for automation and RAG.
+- `CLI` makes the workflow usable in local dev, CI, and incident-response contexts.
-## ⚡ Quick Start
+## Quick Start
```bash
-# Install the universal scanner globally
-npm install -g @worms-ctrl/cli
+bun install
+npx worms-ctrl scan .
+```
-# Run an audit against your current project using all known threat definitions
-npx worms-ctrl scan
+Optional formats:
-# View the Knowledge Base of tracked threats
-npx worms-ctrl threats
+```bash
+npx worms-ctrl scan . --format json
+npx worms-ctrl scan . --format sarif --output wormsctrl.sarif
+npx worms-ctrl scan . --threats
```
-## 🧠 Threat Knowledge Base Architecture
+## AI Integration
-worms-ctrl treats threats as structured data. Inside `packages/ioc/`, you will find JSON representations of known supply chain attacks.
+`wormsCTRL` treats AI as a defensive extraction layer, not as an opaque security oracle.
-### Example: The Shai-Hulud Threat Object
-When a new threat is detected via our intelligence feeds (e.g., Socket.dev, OSV, Phylum), an AI Agent can automatically generate a Threat Profile:
+- `packages/engine/src/ingest.ts` accepts either raw advisory text or a blog/advisory URL.
+- The engine sends the material to the OpenAI API using a constrained JSON-mode extraction prompt.
+- The extracted payload is validated with Zod in `packages/engine/src/validate.ts`.
+- Only schema-valid threat objects are returned for downstream storage or review.
+- If `OPENAI_API_KEY` is not set, ingestion fails safely and returns `null` instead of throwing.
-```json
-{
- "id": "shai-hulud-2.0",
- "name": "Shai-Hulud 2.0",
- "ecosystem": "npm",
- "severity": "CRITICAL",
- "status": "ARCHIVED",
- "description": "A destructive npm supply-chain worm targeting developers and CI/CD pipelines."
-}
+Example environment:
+
+```bash
+export OPENAI_API_KEY=your_key_here
+export OPENAI_MODEL=gpt-4o-mini
```
-## 🗺️ Roadmap & Integration
-- [x] Refactor core architecture from static scripts to dynamic JSON Threat Object ingestion.
-- [x] Archive Shai-Hulud 2.0 as the first documented threat.
-- [ ] Integrate real-time webhook ingestion from Socket.dev & Phylum APIs.
-- [ ] Launch the `wormsCTRL` public Knowledge Base web portal.
-- [ ] Implement AI Agent workflow for automatic Threat Object generation from Twitter/Mastodon threat intel.
+## Threat Database
+
+Current documented entries include:
+
+| Threat ID | Ecosystem | Severity | Attack Vector | Summary |
+| --- | --- | --- | --- | --- |
+| `event-stream-2018` | npm |  | maintainer compromise | Introduced `flatmap-stream` to target Copay wallet builds. |
+| `node-ipc-2022` | npm |  | protestware | Overwrote files and dropped `WITH-LOVE-FROM-AMERICA.txt`. |
+| `ua-parser-js-2021` | npm |  | maintainer account hijack | Delivered credential theft and crypto-mining payloads. |
+| `ctx-2022` | pypi |  | account takeover | Exfiltrated environment variables to a Heroku endpoint. |
+| `xz-utils-2024` | linux |  | upstream release compromise | Backdoored `liblzma` via malicious upstream tarballs. |
+| `shai-hulud-2025` | npm |  | self-replicating registry worm | Injected `bundle.js`, scanned for credentials, and republished infected packages. |
+| `axios-2026` | npm |  | maintainer account compromise + phantom dependency | Published malicious axios releases plus `plain-crypto-js` RAT delivery. |
+| `teampcp-2026` | pypi |  | stolen OIDC Trusted Publisher token + direct registry push | Pushed malicious `litellm` and `telnyx` releases via compromised publishing identity. |
+
+Threat records live in [`packages/ioc/threats`](packages/ioc/threats) and are designed to be both human-readable and automation-friendly.
+
+## What Ships Today
----
+- Lockfile parsing for `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `bun.lock`, `bun.lockb`, and basic `requirements.txt` pins.
+- Injection detection with text, JSON, and SARIF output modes.
+- Structured incident entries for major real-world supply-chain attacks.
+- AI ingestion skeleton for converting advisories into reusable threat objects.
+- Implemented parser logic, injection finding generation, and schema validation for threat objects.
-## 🤝 Contributing
-We welcome contributions from security researchers! If you've analyzed a new malicious package campaign, please submit a PR adding a new Threat Object to our `packages/ioc` directory.
+## Grant Context
-See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
+Built as part of an OpenAI Cybersecurity Grant Program submission. Goal: democratize supply chain defense for solo developers and small teams.
----
+## License
-*Formerly known as dont-be-shy-hulud.*
+MIT. This repository is intentionally kept permissive and public for defensive reuse, research, and community contribution.
diff --git a/SECURITY.md b/SECURITY.md
index f633eee..429f2bc 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -17,7 +17,7 @@ Instead, please report them via one of the following methods:
### Private Security Advisory (Preferred)
-1. Go to the [Security Advisories page](https://github.com/miccy/dont-be-shy-hulud/security/advisories)
+1. Go to the [Security Advisories page](https://github.com/miccy/worms-ctrl/security/advisories)
2. Click "New draft security advisory"
3. Fill in the details
diff --git a/apps/cli/bin/cli.js b/apps/cli/bin/cli.js
index 0366310..d629c69 100755
--- a/apps/cli/bin/cli.js
+++ b/apps/cli/bin/cli.js
@@ -1,95 +1,32 @@
#!/usr/bin/env node
-/**
- * 🪱 worms-ctrl CLI
- * Supply Chain Attack Detection & Knowledge Base Toolkit
- */
-
-import { existsSync, readdirSync, readFileSync } from 'node:fs'
-import { dirname, join } from 'node:path'
-import { fileURLToPath } from 'node:url'
-import chalk from 'chalk'
+import { existsSync } from 'node:fs'
+import { dirname, resolve } from 'node:path'
+import { fileURLToPath, pathToFileURL } from 'node:url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
-const ROOT = join(__dirname, '..')
-
-const c = (color, text) => {
- const colorMap = {
- red: chalk.red,
- green: chalk.green,
- yellow: chalk.yellow,
- blue: chalk.blue,
- magenta: chalk.magenta,
- cyan: chalk.cyan,
- bright: chalk.bold,
- }
- return (colorMap[color] || chalk.white)(text)
-}
+const bundledCliPath = resolve(__dirname, '../dist/cli.js')
+const sourceCliPath = resolve(__dirname, '../../../packages/scanner/src/cli.ts')
-const banner = `
-${c('magenta', ' ╭─────────────────────────────────────────────────╮')}
-${c('magenta', ' │')} ${c('cyan', '🪱 worms-ctrl')} ${c('magenta', '│')}
-${c('magenta', ' │')} ${c('yellow', 'Supply chain attack detection & audit tool')} ${c('magenta', '│')}
-${c('magenta', ' ╰─────────────────────────────────────────────────╯')}
-`
+let entrypointPath = bundledCliPath
-function _getVersion() {
- try {
- const pkg = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf-8'))
- return pkg.version || '0.0.0'
- } catch {
- return '0.0.0'
+if (!existsSync(entrypointPath)) {
+ if (!existsSync(sourceCliPath)) {
+ console.error('[worms-ctrl] CLI bundle is missing. Run the build step before publishing.')
+ process.exit(1)
}
-}
-
-function loadThreats() {
- const threatsPath = join(ROOT, '..', '..', 'packages', 'ioc', 'archived')
- if (!existsSync(threatsPath)) return []
- const threats = []
- const dirs = readdirSync(threatsPath, { withFileTypes: true })
- .filter((dirent) => dirent.isDirectory())
- .map((dirent) => dirent.name)
-
- for (const dir of dirs) {
- try {
- const model = JSON.parse(readFileSync(join(threatsPath, dir, 'threat-model.json'), 'utf-8'))
- threats.push(model)
- } catch (_e) {
- // Skip
- }
+ if (!process.versions.bun) {
+ console.error(
+ '[worms-ctrl] Source fallback requires Bun. Run `bun ./apps/cli/bin/cli.js` or build the CLI first.'
+ )
+ process.exit(1)
}
- return threats
-}
-
-function main() {
- const args = process.argv.slice(2)
- const command = args[0] || 'help'
- console.log(banner)
-
- if (command === 'scan') {
- console.log(c('cyan', '🔍 Initializing worms-ctrl universal scanner...'))
- console.log(c('yellow', 'Loading threat definitions...'))
- const threats = loadThreats()
- console.log(`Loaded ${threats.length} threat models.`)
- console.log(c('green', 'Ready for universal supply chain audit. (Logic to be implemented)'))
- } else if (command === 'threats') {
- console.log(c('bright', '📊 KNOWN THREATS KNOWLEDGE BASE'))
- const threats = loadThreats()
- threats.forEach((t) => {
- console.log(`${c('red', t.name)} [${t.status}] - ${t.severity}`)
- console.log(` ${t.description}`)
- })
- } else {
- console.log(`
-${c('bright', 'COMMANDS:')}
- ${c('cyan', 'scan')} Scan directory using all loaded threat definitions
- ${c('cyan', 'threats')} List all tracked and archived threats
- ${c('cyan', 'help')} Show this help message
-`)
- }
+ entrypointPath = sourceCliPath
}
-main()
+const { runCli } = await import(pathToFileURL(entrypointPath).href)
+const exitCode = await runCli(process.argv.slice(2))
+process.exit(exitCode)
diff --git a/apps/cli/build.mjs b/apps/cli/build.mjs
new file mode 100644
index 0000000..456442b
--- /dev/null
+++ b/apps/cli/build.mjs
@@ -0,0 +1,43 @@
+import { spawnSync } from 'node:child_process'
+import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs'
+import { dirname, resolve } from 'node:path'
+import { fileURLToPath } from 'node:url'
+
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = dirname(__filename)
+const rootDir = resolve(__dirname, '../..')
+const scannerCliEntry = resolve(rootDir, 'packages/scanner/src/cli.ts')
+const threatSourceDir = resolve(rootDir, 'packages/ioc/threats')
+const distDir = resolve(__dirname, 'dist')
+const bundledCliPath = resolve(distDir, 'cli.js')
+const bundledThreatsPath = resolve(distDir, 'threats')
+
+if (!existsSync(scannerCliEntry)) {
+ throw new Error(`Scanner CLI entrypoint not found: ${scannerCliEntry}`)
+}
+
+if (!existsSync(threatSourceDir)) {
+ throw new Error(`Threat catalog directory not found: ${threatSourceDir}`)
+}
+
+rmSync(distDir, { recursive: true, force: true })
+mkdirSync(distDir, { recursive: true })
+
+const buildResult = spawnSync(
+ 'bun',
+ ['build', scannerCliEntry, '--target=node', '--format=esm', '--outfile', bundledCliPath],
+ {
+ cwd: rootDir,
+ stdio: 'inherit',
+ }
+)
+
+if (buildResult.error) {
+ throw buildResult.error
+}
+
+if ((buildResult.status ?? 1) !== 0) {
+ process.exit(buildResult.status ?? 1)
+}
+
+cpSync(threatSourceDir, bundledThreatsPath, { recursive: true })
diff --git a/apps/cli/package.json b/apps/cli/package.json
index a3feb23..bf224a0 100644
--- a/apps/cli/package.json
+++ b/apps/cli/package.json
@@ -6,9 +6,14 @@
"bin": {
"worms-ctrl": "./bin/cli.js"
},
+ "files": [
+ "bin",
+ "dist"
+ ],
"scripts": {
- "dev": "node bin/cli.js",
- "build": "echo 'No build step needed'",
+ "dev": "bun ./bin/cli.js",
+ "build": "node ./build.mjs",
+ "prepack": "npm run build",
"lint": "biome check .",
"typecheck": "tsc --noEmit"
},
@@ -16,7 +21,7 @@
"chalk": "latest",
"cli-progress": "latest",
"commander": "latest",
- "ora": "latest"
+ "ora": "^9.4.0"
},
"devDependencies": {
"@types/cli-progress": "latest",
diff --git a/apps/cli/tsconfig.json b/apps/cli/tsconfig.json
index c6a1c8e..9d57d6f 100644
--- a/apps/cli/tsconfig.json
+++ b/apps/cli/tsconfig.json
@@ -3,6 +3,7 @@
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
+ "types": ["node"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 88942d9..d171aa4 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -16,15 +16,15 @@
"test:ui": "playwright test --ui"
},
"dependencies": {
- "@astrojs/check": "^0.9.8",
- "@astrojs/starlight": "^0.38.3",
+ "@astrojs/check": "^0.9.9",
+ "@astrojs/starlight": "^0.38.4",
"@astrojs/starlight-tailwind": "^5.0.0",
"@pagefind/default-ui": "^1.5.2",
"@tailwindcss/vite": "^4.2.4",
- "astro": "^6.1.8",
+ "astro": "^6.2.1",
"astro-embed": "^0.13.0",
"astro-font": "^1.1.0",
- "marked": "^18.0.2",
+ "marked": "^18.0.3",
"sharp": "^0.34.4",
"vite": "^8.0.9"
},
diff --git a/apps/docs/playwright-report/index.html b/apps/docs/playwright-report/index.html
deleted file mode 100644
index 0d749eb..0000000
--- a/apps/docs/playwright-report/index.html
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-