@planu/cli 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -1
- package/dist/cli/commands/doctor.d.ts +22 -0
- package/dist/cli/commands/doctor.js +176 -2
- package/dist/cli/commands/spec.js +10 -1
- package/dist/core/spec-validator.js +32 -18
- package/dist/engine/autopilot/bootstrap.js +27 -0
- package/dist/engine/core-bridge.d.ts +28 -0
- package/dist/engine/core-bridge.js +67 -0
- package/dist/engine/drift-monitor.js +16 -18
- package/dist/engine/evidence-gates/artifact-reader.d.ts +2 -0
- package/dist/engine/evidence-gates/artifact-reader.js +59 -2
- package/dist/engine/evidence-gates/evidence-autofill.d.ts +10 -0
- package/dist/engine/evidence-gates/evidence-autofill.js +148 -0
- package/dist/engine/evidence-gates/evidence-skeletons.d.ts +19 -0
- package/dist/engine/evidence-gates/evidence-skeletons.js +69 -0
- package/dist/engine/execution/operation-journal.js +10 -4
- package/dist/engine/living-spec/hash-tracker.js +26 -28
- package/dist/engine/minimality/policy-loader.js +247 -6
- package/dist/engine/planu-core.darwin-arm64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-arm64.node.sbom.json +14 -14
- package/dist/engine/planu-core.darwin-x64.node.manifest.json +7 -7
- package/dist/engine/planu-core.darwin-x64.node.sbom.json +14 -14
- package/dist/engine/planu-core.linux-arm64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-gnu.node.sbom.json +14 -14
- package/dist/engine/planu-core.linux-arm64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-arm64-musl.node.sbom.json +14 -14
- package/dist/engine/planu-core.linux-x64-gnu.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-gnu.node.sbom.json +14 -14
- package/dist/engine/planu-core.linux-x64-musl.node.manifest.json +7 -7
- package/dist/engine/planu-core.linux-x64-musl.node.sbom.json +14 -14
- package/dist/engine/planu-core.win32-arm64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-arm64-msvc.node.sbom.json +14 -14
- package/dist/engine/planu-core.win32-x64-msvc.node.manifest.json +7 -7
- package/dist/engine/planu-core.win32-x64-msvc.node.sbom.json +14 -14
- package/dist/engine/reverse-engineer/api-detector.js +2 -13
- package/dist/engine/reverse-engineer/complexity-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/config-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/dependency-graph.js +2 -13
- package/dist/engine/reverse-engineer/test-analyzer.js +2 -13
- package/dist/engine/reverse-engineer/walk-ignore.d.ts +3 -0
- package/dist/engine/reverse-engineer/walk-ignore.js +26 -0
- package/dist/engine/spec-format/acceptance-criteria.js +13 -12
- package/dist/engine/spec-format/text-fences.js +20 -2
- package/dist/engine/spec-language/english-only.d.ts +14 -0
- package/dist/engine/spec-language/english-only.js +58 -0
- package/dist/engine/spec-migrator/criteria-scanner.js +11 -13
- package/dist/engine/spec-migrator/drift-detector.js +10 -12
- package/dist/engine/spec-state-syncer.js +1 -1
- package/dist/engine/timing/budget.js +5 -1
- package/dist/engine/vector-store/tfidf.d.ts +13 -9
- package/dist/engine/vector-store/tfidf.js +26 -0
- package/dist/engine/worker-config-loader.d.ts +1 -1
- package/dist/engine/worker-config-loader.js +1 -11
- package/dist/engine/workers/schema.d.ts +0 -8
- package/dist/engine/workers/schema.js +0 -1
- package/dist/i18n/index.d.ts +18 -0
- package/dist/i18n/index.js +40 -1
- package/dist/server/routes/specs.js +7 -5
- package/dist/storage/global-store.d.ts +9 -0
- package/dist/storage/global-store.js +23 -0
- package/dist/storage/semantic-index-store.d.ts +23 -0
- package/dist/storage/semantic-index-store.js +105 -0
- package/dist/storage/status-store/self-healing.js +15 -17
- package/dist/tools/challenge-spec/scenarios-utils.js +5 -1
- package/dist/tools/challenge-spec-helpers.d.ts +10 -1
- package/dist/tools/challenge-spec-helpers.js +63 -22
- package/dist/tools/challenge-spec.js +18 -3
- package/dist/tools/check-readiness.js +37 -13
- package/dist/tools/create-spec/spec-builder.d.ts +7 -0
- package/dist/tools/create-spec/spec-builder.js +19 -4
- package/dist/tools/create-spec.js +216 -101
- package/dist/tools/init-project/handler.js +78 -25
- package/dist/tools/learn.js +10 -8
- package/dist/tools/register-spec-tools/core-spec-tools.js +13 -12
- package/dist/tools/registry/auth.js +1 -11
- package/dist/tools/semantic-search-handler.js +5 -6
- package/dist/tools/status-handler.js +19 -6
- package/dist/tools/sync-spec-state-handler.js +49 -1
- package/dist/tools/update-status/batch.d.ts +6 -2
- package/dist/tools/update-status/batch.js +58 -1
- package/dist/tools/update-status/dod-gates.d.ts +16 -1
- package/dist/tools/update-status/dod-gates.js +191 -1
- package/dist/tools/update-status/done-receipt-verifier.d.ts +8 -0
- package/dist/tools/update-status/done-receipt-verifier.js +37 -2
- package/dist/tools/update-status/evidence-gate.d.ts +4 -0
- package/dist/tools/update-status/evidence-gate.js +67 -2
- package/dist/tools/update-status/file-sync.d.ts +2 -2
- package/dist/tools/update-status/index.d.ts +23 -1
- package/dist/tools/update-status/index.js +201 -24
- package/dist/tools/update-status/transition-guard.js +13 -1
- package/dist/tools/validation-loop-handler.js +16 -15
- package/dist/tools/workspace-dashboard-handler.js +38 -0
- package/dist/types/evidence-autofill.d.ts +34 -0
- package/dist/types/evidence-autofill.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/spec/core.d.ts +6 -0
- package/dist/types/spec/inputs.d.ts +7 -2
- package/dist/types/spec-format.d.ts +1 -1
- package/dist/types/spec-language-translation.d.ts +18 -0
- package/dist/types/spec-language-translation.js +5 -0
- package/dist/types/spec-registry.d.ts +0 -2
- package/dist/types/status.d.ts +2 -0
- package/dist/types/transition-log.d.ts +1 -1
- package/dist/types/validation.d.ts +8 -2
- package/dist/types/vector-store.d.ts +18 -0
- package/dist/types/workers.d.ts +0 -3
- package/package.json +11 -10
- package/planu-native.json +8 -29
- package/planu-plugin.json +1 -1
- package/dist/engine/security/cve-refresher.d.ts +0 -12
- package/dist/engine/security/cve-refresher.js +0 -128
|
@@ -21,6 +21,24 @@ export interface TFIDFConfig {
|
|
|
21
21
|
minDocFrequency: number;
|
|
22
22
|
stopWords: Set<string>;
|
|
23
23
|
}
|
|
24
|
+
/** Serializable TF-IDF engine state (SPEC-1345: persisted index). */
|
|
25
|
+
export interface TFIDFExportedState {
|
|
26
|
+
schemaVersion: number;
|
|
27
|
+
docFreq: [string, number][];
|
|
28
|
+
docCount: number;
|
|
29
|
+
}
|
|
30
|
+
/** A single corpus document as seen by the persisted semantic index (SPEC-1345). */
|
|
31
|
+
export interface SemanticIndexDoc {
|
|
32
|
+
id: string;
|
|
33
|
+
content: string;
|
|
34
|
+
}
|
|
35
|
+
/** On-disk shape of a persisted TF-IDF index + hash manifest (SPEC-1345). */
|
|
36
|
+
export interface PersistedSemanticIndex {
|
|
37
|
+
schemaVersion: number;
|
|
38
|
+
docHashes: Record<string, string>;
|
|
39
|
+
docTokens: Record<string, string[]>;
|
|
40
|
+
tfidfState: TFIDFExportedState;
|
|
41
|
+
}
|
|
24
42
|
/** Configuration for the HNSW index. */
|
|
25
43
|
export interface HNSWConfig {
|
|
26
44
|
M: number;
|
package/dist/types/workers.d.ts
CHANGED
|
@@ -8,7 +8,6 @@ export interface WorkerTrigger {
|
|
|
8
8
|
/** Interval in ms for schedule triggers */
|
|
9
9
|
intervalMs?: number;
|
|
10
10
|
}
|
|
11
|
-
export type WorkerTier = 'free' | 'pro';
|
|
12
11
|
export interface WorkerDefinition {
|
|
13
12
|
name: string;
|
|
14
13
|
description: string;
|
|
@@ -19,7 +18,6 @@ export interface WorkerDefinition {
|
|
|
19
18
|
/** Minimum ms between executions */
|
|
20
19
|
cooldownMs: number;
|
|
21
20
|
enabled: boolean;
|
|
22
|
-
tier: WorkerTier;
|
|
23
21
|
}
|
|
24
22
|
export type WorkerFindingSeverity = 'critical' | 'high' | 'medium' | 'low' | 'warning' | 'info';
|
|
25
23
|
export interface WorkerFinding {
|
|
@@ -66,7 +64,6 @@ export interface WorkerOverride {
|
|
|
66
64
|
enabled?: boolean;
|
|
67
65
|
cooldownMs?: number;
|
|
68
66
|
priority?: number;
|
|
69
|
-
tier?: WorkerTier;
|
|
70
67
|
}
|
|
71
68
|
export interface WorkerProjectConfig {
|
|
72
69
|
overrides: Record<string, WorkerConfigOverride>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planu/cli",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Planu — MCP Server for Spec Driven Development with native Rust acceleration for hot paths. Cross-platform (Linux/macOS/Windows, x64/arm64, glibc/musl).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"packageName": "@planu/core"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"@planu/core-darwin-arm64": "5.
|
|
39
|
-
"@planu/core-darwin-x64": "5.
|
|
40
|
-
"@planu/core-linux-arm64-gnu": "5.
|
|
41
|
-
"@planu/core-linux-arm64-musl": "5.
|
|
42
|
-
"@planu/core-linux-x64-gnu": "5.
|
|
43
|
-
"@planu/core-linux-x64-musl": "5.
|
|
44
|
-
"@planu/core-win32-arm64-msvc": "5.
|
|
45
|
-
"@planu/core-win32-x64-msvc": "5.
|
|
38
|
+
"@planu/core-darwin-arm64": "5.2.0",
|
|
39
|
+
"@planu/core-darwin-x64": "5.2.0",
|
|
40
|
+
"@planu/core-linux-arm64-gnu": "5.2.0",
|
|
41
|
+
"@planu/core-linux-arm64-musl": "5.2.0",
|
|
42
|
+
"@planu/core-linux-x64-gnu": "5.2.0",
|
|
43
|
+
"@planu/core-linux-x64-musl": "5.2.0",
|
|
44
|
+
"@planu/core-win32-arm64-msvc": "5.2.0",
|
|
45
|
+
"@planu/core-win32-x64-msvc": "5.2.0"
|
|
46
46
|
},
|
|
47
47
|
"engines": {
|
|
48
48
|
"node": ">=24.0.0"
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
"test": "vitest run",
|
|
78
78
|
"test:watch": "vitest",
|
|
79
79
|
"test:coverage": "vitest run --coverage --testTimeout=60000 --maxWorkers=4",
|
|
80
|
+
"test:release-gate": "vitest run --exclude 'tests/integration/**'",
|
|
80
81
|
"test:integration": "vitest run tests/integration",
|
|
81
82
|
"test:website:unit": "vitest run tests/website tests/scripts/generate-website-proof.test.ts tests/scripts/website-tool-counts.test.ts",
|
|
82
83
|
"test:website:browser": "playwright test --config playwright.website.config.ts",
|
|
@@ -117,7 +118,7 @@
|
|
|
117
118
|
"prepublishOnly": "bash scripts/prepublish-guard.sh",
|
|
118
119
|
"prepack": "pnpm build:ts && pnpm package:size",
|
|
119
120
|
"test:debug": "vitest run --inspect-brk --single-thread",
|
|
120
|
-
"validate": "pnpm build && pnpm typecheck && pnpm verify:typescript-migration && pnpm lint && pnpm format:check && pnpm test",
|
|
121
|
+
"validate": "pnpm build && pnpm typecheck && pnpm verify:typescript-migration && pnpm lint && pnpm format:check && pnpm test:release-gate",
|
|
121
122
|
"docker:build": "docker build -t planu .",
|
|
122
123
|
"docker:run": "docker compose up",
|
|
123
124
|
"publish:blog": "node scripts/publish-blog.mjs",
|
package/planu-native.json
CHANGED
|
@@ -1,26 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dev.planu.native",
|
|
3
3
|
"displayName": "Planu Native Lightweight Surface",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.2.0",
|
|
5
5
|
"packageName": "@planu/cli",
|
|
6
6
|
"modes": {
|
|
7
7
|
"lightweight": {
|
|
8
8
|
"requiresMcp": false,
|
|
9
9
|
"requiresDaemon": false,
|
|
10
|
-
"hosts": [
|
|
11
|
-
"codex",
|
|
12
|
-
"claude-code"
|
|
13
|
-
],
|
|
10
|
+
"hosts": ["codex", "claude-code"],
|
|
14
11
|
"commands": [
|
|
15
12
|
{
|
|
16
13
|
"id": "planu.status",
|
|
17
14
|
"title": "Project status",
|
|
18
15
|
"description": "Show the compact Planu project snapshot without loading the MCP tool graph.",
|
|
19
16
|
"invocation": "planu status",
|
|
20
|
-
"hosts": [
|
|
21
|
-
"codex",
|
|
22
|
-
"claude-code"
|
|
23
|
-
],
|
|
17
|
+
"hosts": ["codex", "claude-code"],
|
|
24
18
|
"requiresMcp": false,
|
|
25
19
|
"requiresDaemon": false,
|
|
26
20
|
"mapsTo": "handlePlanStatus"
|
|
@@ -30,10 +24,7 @@
|
|
|
30
24
|
"title": "Create spec",
|
|
31
25
|
"description": "Create a new spec through the CLI-backed SDD contract.",
|
|
32
26
|
"invocation": "planu spec create \"<title>\"",
|
|
33
|
-
"hosts": [
|
|
34
|
-
"codex",
|
|
35
|
-
"claude-code"
|
|
36
|
-
],
|
|
27
|
+
"hosts": ["codex", "claude-code"],
|
|
37
28
|
"requiresMcp": false,
|
|
38
29
|
"requiresDaemon": false,
|
|
39
30
|
"mapsTo": "handleCreateSpec"
|
|
@@ -43,10 +34,7 @@
|
|
|
43
34
|
"title": "List specs",
|
|
44
35
|
"description": "List specs in the current project with optional status/type filters.",
|
|
45
36
|
"invocation": "planu spec list",
|
|
46
|
-
"hosts": [
|
|
47
|
-
"codex",
|
|
48
|
-
"claude-code"
|
|
49
|
-
],
|
|
37
|
+
"hosts": ["codex", "claude-code"],
|
|
50
38
|
"requiresMcp": false,
|
|
51
39
|
"requiresDaemon": false,
|
|
52
40
|
"mapsTo": "handleListSpecs"
|
|
@@ -56,10 +44,7 @@
|
|
|
56
44
|
"title": "Validate spec",
|
|
57
45
|
"description": "Validate a spec against the current codebase from the native CLI surface.",
|
|
58
46
|
"invocation": "planu spec validate SPEC-001",
|
|
59
|
-
"hosts": [
|
|
60
|
-
"codex",
|
|
61
|
-
"claude-code"
|
|
62
|
-
],
|
|
47
|
+
"hosts": ["codex", "claude-code"],
|
|
63
48
|
"requiresMcp": false,
|
|
64
49
|
"requiresDaemon": false,
|
|
65
50
|
"mapsTo": "handleValidate"
|
|
@@ -69,10 +54,7 @@
|
|
|
69
54
|
"title": "Audit technical debt",
|
|
70
55
|
"description": "Run the read-only project audit path for lightweight debt checks.",
|
|
71
56
|
"invocation": "planu audit debt",
|
|
72
|
-
"hosts": [
|
|
73
|
-
"codex",
|
|
74
|
-
"claude-code"
|
|
75
|
-
],
|
|
57
|
+
"hosts": ["codex", "claude-code"],
|
|
76
58
|
"requiresMcp": false,
|
|
77
59
|
"requiresDaemon": false,
|
|
78
60
|
"mapsTo": "handleAudit"
|
|
@@ -82,10 +64,7 @@
|
|
|
82
64
|
"title": "Check release readiness",
|
|
83
65
|
"description": "Check local-first release readiness, branch cleanliness, and optional gitflow drift.",
|
|
84
66
|
"invocation": "planu release check",
|
|
85
|
-
"hosts": [
|
|
86
|
-
"codex",
|
|
87
|
-
"claude-code"
|
|
88
|
-
],
|
|
67
|
+
"hosts": ["codex", "claude-code"],
|
|
89
68
|
"requiresMcp": false,
|
|
90
69
|
"requiresDaemon": false,
|
|
91
70
|
"mapsTo": "releaseCommand"
|
package/planu-plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dev.planu.cli",
|
|
3
3
|
"displayName": "Planu — Spec Driven Development",
|
|
4
4
|
"description": "Manage software specs, estimations, and autonomous SDD workflows. Language-agnostic MCP server for Claude Code.",
|
|
5
|
-
"version": "5.
|
|
5
|
+
"version": "5.2.0",
|
|
6
6
|
"icon": "assets/plugin/icon.svg",
|
|
7
7
|
"command": ["npx", "@planu/cli@latest"],
|
|
8
8
|
"packageName": "@planu/cli",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { StalenessInfo } from '../../types/security/index.js';
|
|
2
|
-
export type { StalenessInfo };
|
|
3
|
-
export declare const CVE_DB_PATH: string;
|
|
4
|
-
/** Check if known-cves.json is older than 7 days. */
|
|
5
|
-
export declare function isCveDatabaseStale(): Promise<StalenessInfo>;
|
|
6
|
-
/**
|
|
7
|
-
* Refresh known-cves.json from OSV.dev for the given ecosystems.
|
|
8
|
-
* Queries each package already in the database to get up-to-date CVE data.
|
|
9
|
-
* Writes updated JSON via atomicWriteFile. Records refresh in cve-refresh-log.json.
|
|
10
|
-
*/
|
|
11
|
-
export declare function refreshCveDatabase(ecosystems: string[]): Promise<void>;
|
|
12
|
-
//# sourceMappingURL=cve-refresher.d.ts.map
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
// engine/security/cve-refresher.ts — SPEC-773
|
|
2
|
-
// Auto-refresh known-cves.json from OSV.dev public API.
|
|
3
|
-
import { stat, readFile, mkdir } from 'node:fs/promises';
|
|
4
|
-
import { resolve, dirname } from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import { atomicWriteFile } from '../safety/atomic-write-file.js';
|
|
7
|
-
import { globalDataDir } from '../../storage/base-store.js';
|
|
8
|
-
const MODULE_DIR = dirname(fileURLToPath(import.meta.url));
|
|
9
|
-
export const CVE_DB_PATH = resolve(MODULE_DIR, '../../config/known-cves.json');
|
|
10
|
-
const OSV_API = 'https://api.osv.dev/v1/query';
|
|
11
|
-
const STALE_THRESHOLD_MS = 7 * 24 * 60 * 60 * 1000;
|
|
12
|
-
/** Check if known-cves.json is older than 7 days. */
|
|
13
|
-
export async function isCveDatabaseStale() {
|
|
14
|
-
try {
|
|
15
|
-
const s = await stat(CVE_DB_PATH);
|
|
16
|
-
const ageMs = Date.now() - s.mtimeMs;
|
|
17
|
-
return { stale: ageMs > STALE_THRESHOLD_MS, ageDays: Math.floor(ageMs / 86400000) };
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return { stale: true, ageDays: 999 };
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function toEntry(vuln, pkgName, ecosystem) {
|
|
24
|
-
const cveId = vuln.aliases?.find((a) => a.startsWith('CVE-'));
|
|
25
|
-
if (!cveId) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
let fixVersion;
|
|
29
|
-
outer: for (const aff of vuln.affected ?? []) {
|
|
30
|
-
for (const range of aff.ranges ?? []) {
|
|
31
|
-
for (const ev of range.events ?? []) {
|
|
32
|
-
if (ev.fixed) {
|
|
33
|
-
fixVersion = ev.fixed;
|
|
34
|
-
break outer;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const score = parseFloat(vuln.affected?.[0]?.severity?.[0]?.score ?? '0');
|
|
40
|
-
const severity = score >= 7 ? 'critical' : 'warning';
|
|
41
|
-
return {
|
|
42
|
-
package: pkgName,
|
|
43
|
-
ecosystem,
|
|
44
|
-
affectedVersions: fixVersion ? `<${fixVersion}` : 'unknown',
|
|
45
|
-
cveId,
|
|
46
|
-
severity,
|
|
47
|
-
description: vuln.summary ?? '',
|
|
48
|
-
...(fixVersion ? { fixVersion } : {}),
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Refresh known-cves.json from OSV.dev for the given ecosystems.
|
|
53
|
-
* Queries each package already in the database to get up-to-date CVE data.
|
|
54
|
-
* Writes updated JSON via atomicWriteFile. Records refresh in cve-refresh-log.json.
|
|
55
|
-
*/
|
|
56
|
-
export async function refreshCveDatabase(ecosystems) {
|
|
57
|
-
let currentDb;
|
|
58
|
-
try {
|
|
59
|
-
const raw = await readFile(CVE_DB_PATH, 'utf-8');
|
|
60
|
-
currentDb = JSON.parse(raw);
|
|
61
|
-
}
|
|
62
|
-
catch {
|
|
63
|
-
currentDb = { lastUpdated: '', vulnerabilities: [] };
|
|
64
|
-
}
|
|
65
|
-
// Build package list per ecosystem for ecosystems being refreshed (AC-5: ecosystem-scoped)
|
|
66
|
-
const byEcosystem = new Map();
|
|
67
|
-
for (const vuln of currentDb.vulnerabilities) {
|
|
68
|
-
if (!ecosystems.includes(vuln.ecosystem)) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
const set = byEcosystem.get(vuln.ecosystem) ?? new Set();
|
|
72
|
-
set.add(vuln.package);
|
|
73
|
-
byEcosystem.set(vuln.ecosystem, set);
|
|
74
|
-
}
|
|
75
|
-
// Query OSV.dev per package with ecosystem filter (not a generic all-ecosystems fetch)
|
|
76
|
-
const freshVulns = [];
|
|
77
|
-
for (const [ecosystem, packages] of byEcosystem) {
|
|
78
|
-
for (const pkgName of packages) {
|
|
79
|
-
try {
|
|
80
|
-
const resp = await fetch(OSV_API, {
|
|
81
|
-
method: 'POST',
|
|
82
|
-
headers: { 'Content-Type': 'application/json' },
|
|
83
|
-
body: JSON.stringify({ package: { name: pkgName, ecosystem } }),
|
|
84
|
-
});
|
|
85
|
-
if (!resp.ok) {
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
const data = (await resp.json());
|
|
89
|
-
for (const vuln of data.vulns ?? []) {
|
|
90
|
-
const entry = toEntry(vuln, pkgName, ecosystem);
|
|
91
|
-
if (entry) {
|
|
92
|
-
freshVulns.push(entry);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch {
|
|
97
|
-
// per-package error — skip and continue
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// Preserve untouched ecosystems; replace refreshed ones with fresh data (or keep stale if
|
|
102
|
-
// OSV returned nothing new for that ecosystem)
|
|
103
|
-
const untouched = currentDb.vulnerabilities.filter((v) => !ecosystems.includes(v.ecosystem));
|
|
104
|
-
const refreshedEcos = new Set(freshVulns.map((v) => v.ecosystem));
|
|
105
|
-
const staleKept = currentDb.vulnerabilities.filter((v) => ecosystems.includes(v.ecosystem) && !refreshedEcos.has(v.ecosystem));
|
|
106
|
-
const merged = [...untouched, ...staleKept, ...freshVulns];
|
|
107
|
-
const updatedDb = {
|
|
108
|
-
lastUpdated: new Date().toISOString().slice(0, 10),
|
|
109
|
-
vulnerabilities: merged,
|
|
110
|
-
};
|
|
111
|
-
await atomicWriteFile(CVE_DB_PATH, JSON.stringify(updatedDb, null, 2));
|
|
112
|
-
// Write refresh log (best-effort — non-fatal)
|
|
113
|
-
try {
|
|
114
|
-
const dir = globalDataDir();
|
|
115
|
-
await mkdir(dir, { recursive: true });
|
|
116
|
-
const log = {
|
|
117
|
-
refreshedAt: new Date().toISOString(),
|
|
118
|
-
source: 'osv.dev',
|
|
119
|
-
ecosystems,
|
|
120
|
-
entryCount: merged.length,
|
|
121
|
-
};
|
|
122
|
-
await atomicWriteFile(`${dir}/cve-refresh-log.json`, JSON.stringify(log, null, 2));
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
// log write failure is non-fatal
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
//# sourceMappingURL=cve-refresher.js.map
|