code-auditor-mcp 3.9.6 → 3.9.11
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/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +220 -0
- package/README.md +18 -0
- package/dist/analyzers/reactAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/reactAnalyzer.js +4 -1
- package/dist/analyzers/reactAnalyzer.js.map +1 -1
- package/dist/analyzers/ruleRegistry.d.ts +8 -0
- package/dist/analyzers/ruleRegistry.d.ts.map +1 -1
- package/dist/analyzers/ruleRegistry.js +32 -10
- package/dist/analyzers/ruleRegistry.js.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js +23 -20
- package/dist/analyzers/universal/UniversalSOLIDAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts +1 -0
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.d.ts.map +1 -1
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.js +19 -5
- package/dist/analyzers/universal/UniversalSchemaAnalyzer.js.map +1 -1
- package/dist/analyzers/universal/schema/codeAnalysis.d.ts +44 -2
- package/dist/analyzers/universal/schema/codeAnalysis.d.ts.map +1 -1
- package/dist/analyzers/universal/schema/codeAnalysis.js +153 -8
- package/dist/analyzers/universal/schema/codeAnalysis.js.map +1 -1
- package/dist/analyzers/universal/schema/config.d.ts +8 -0
- package/dist/analyzers/universal/schema/config.d.ts.map +1 -1
- package/dist/analyzers/universal/schema/config.js +9 -0
- package/dist/analyzers/universal/schema/config.js.map +1 -1
- package/dist/analyzers/universal/schema/types.d.ts +5 -0
- package/dist/analyzers/universal/schema/types.d.ts.map +1 -1
- package/dist/auditRouter.d.ts.map +1 -1
- package/dist/auditRouter.js +6 -1
- package/dist/auditRouter.js.map +1 -1
- package/dist/auditRunner.d.ts.map +1 -1
- package/dist/auditRunner.js +62 -8
- package/dist/auditRunner.js.map +1 -1
- package/dist/cli.js +157 -13
- package/dist/cli.js.map +1 -1
- package/dist/codeIndexDB.d.ts.map +1 -1
- package/dist/codeIndexDB.js +29 -7
- package/dist/codeIndexDB.js.map +1 -1
- package/dist/config/defaults.d.ts +2 -0
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +15 -6
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/effectiveConfig.d.ts +22 -1
- package/dist/config/effectiveConfig.d.ts.map +1 -1
- package/dist/config/effectiveConfig.js +69 -2
- package/dist/config/effectiveConfig.js.map +1 -1
- package/dist/config/lintConfigReader.d.ts +56 -0
- package/dist/config/lintConfigReader.d.ts.map +1 -0
- package/dist/config/lintConfigReader.js +263 -0
- package/dist/config/lintConfigReader.js.map +1 -0
- package/dist/constants.d.ts +9 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -6
- package/dist/constants.js.map +1 -1
- package/dist/dataPaths.d.ts +8 -0
- package/dist/dataPaths.d.ts.map +1 -1
- package/dist/dataPaths.js +21 -0
- package/dist/dataPaths.js.map +1 -1
- package/dist/dismissals.d.ts +59 -0
- package/dist/dismissals.d.ts.map +1 -0
- package/dist/dismissals.js +128 -0
- package/dist/dismissals.js.map +1 -0
- package/dist/enforcement/gate.d.ts.map +1 -1
- package/dist/enforcement/gate.js +5 -0
- package/dist/enforcement/gate.js.map +1 -1
- package/dist/hooks/codex.d.ts.map +1 -1
- package/dist/hooks/codex.js +18 -6
- package/dist/hooks/codex.js.map +1 -1
- package/dist/hooks/core.d.ts +12 -0
- package/dist/hooks/core.d.ts.map +1 -1
- package/dist/hooks/core.js +12 -3
- package/dist/hooks/core.js.map +1 -1
- package/dist/hooks/cursor.d.ts.map +1 -1
- package/dist/hooks/cursor.js +17 -10
- package/dist/hooks/cursor.js.map +1 -1
- package/dist/installConfig.d.ts +40 -0
- package/dist/installConfig.d.ts.map +1 -0
- package/dist/installConfig.js +84 -0
- package/dist/installConfig.js.map +1 -0
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +2 -15
- package/dist/installer.js.map +1 -1
- package/dist/languages/go/analyzer +0 -0
- package/dist/languages/go/analyzer-src/solid.go +14 -6
- package/dist/mcp.js +54 -0
- package/dist/mcp.js.map +1 -1
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +12 -1
- package/dist/pipeline.js.map +1 -1
- package/dist/pipelineAdapters.d.ts.map +1 -1
- package/dist/pipelineAdapters.js +87 -7
- package/dist/pipelineAdapters.js.map +1 -1
- package/dist/reporting/csvReportGenerator.d.ts.map +1 -1
- package/dist/reporting/csvReportGenerator.js +1 -0
- package/dist/reporting/csvReportGenerator.js.map +1 -1
- package/dist/reporting/htmlReportGenerator.d.ts.map +1 -1
- package/dist/reporting/htmlReportGenerator.js +5 -0
- package/dist/reporting/htmlReportGenerator.js.map +1 -1
- package/dist/reporting/jsonReportGenerator.d.ts.map +1 -1
- package/dist/reporting/jsonReportGenerator.js +6 -0
- package/dist/reporting/jsonReportGenerator.js.map +1 -1
- package/dist/reporting/sarifReportGenerator.d.ts.map +1 -1
- package/dist/reporting/sarifReportGenerator.js +3 -0
- package/dist/reporting/sarifReportGenerator.js.map +1 -1
- package/dist/services/auditJobService.d.ts.map +1 -1
- package/dist/services/auditJobService.js +4 -7
- package/dist/services/auditJobService.js.map +1 -1
- package/dist/structuralSignature.d.ts +41 -0
- package/dist/structuralSignature.d.ts.map +1 -0
- package/dist/structuralSignature.js +93 -0
- package/dist/structuralSignature.js.map +1 -0
- package/dist/telemetry.d.ts +80 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +148 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types.d.ts +72 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/version.generated.d.ts +2 -0
- package/dist/version.generated.d.ts.map +1 -0
- package/dist/version.generated.js +7 -0
- package/dist/version.generated.js.map +1 -0
- package/package.json +3 -2
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/scripts/hook-common.sh +37 -9
- package/plugin/skills/code-auditor/SKILL.md +24 -2
- package/server.json +2 -2
|
@@ -10,14 +10,11 @@
|
|
|
10
10
|
* The database handle is passed in explicitly (matching `ledger.ts`); callers
|
|
11
11
|
* resolve the per-project DB via `CodeIndexDB.getInstance(undefined, projectRoot)`.
|
|
12
12
|
*/
|
|
13
|
-
import path from 'node:path';
|
|
14
|
-
import { readFileSync } from 'node:fs';
|
|
15
|
-
import { fileURLToPath } from 'node:url';
|
|
16
13
|
import { createLedgerRun, detectRunInput, getLedgerRun, patchLedgerRun, } from '../ledger.js';
|
|
17
|
-
// Package version —
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const TOOL_VERSION =
|
|
14
|
+
// Package version — stamped into the build (see constants.ts), not read from
|
|
15
|
+
// package.json at runtime, so a stale binary reports the version it was built as.
|
|
16
|
+
import { PACKAGE_VERSION } from '../constants.js';
|
|
17
|
+
const TOOL_VERSION = PACKAGE_VERSION;
|
|
21
18
|
function toAuditJobRecord(detail) {
|
|
22
19
|
let progress;
|
|
23
20
|
if (detail.progressJson) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auditJobService.js","sourceRoot":"","sources":["../../src/services/auditJobService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"auditJobService.js","sourceRoot":"","sources":["../../src/services/auditJobService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec 57 — structural AST signature.
|
|
3
|
+
*
|
|
4
|
+
* The telemetry payload describes *the shape* of the code a finding points at,
|
|
5
|
+
* so the service can cluster "these are all for-loops with a `.save()` inside"
|
|
6
|
+
* without ever receiving source text. The only thing this module reads off a
|
|
7
|
+
* node is `type` — the tree-sitter grammar kind (`for_statement`,
|
|
8
|
+
* `call_expression`, `identifier`, `string`, …) — a fixed, finite vocabulary.
|
|
9
|
+
* It never reads `getNodeText`/`getNodeName`/`raw`, so identifiers, string
|
|
10
|
+
* literals, table names, paths, and comments can never enter a signature.
|
|
11
|
+
*
|
|
12
|
+
* Acceptance 6 (the shipping gate) hinges on exactly this: a finding on code
|
|
13
|
+
* containing a secret + a table name + a distinctive identifier must produce a
|
|
14
|
+
* signature containing none of the three. The `structuralSignature.spec.ts`
|
|
15
|
+
* guard test asserts that directly.
|
|
16
|
+
*/
|
|
17
|
+
import type { AST, ASTNode } from './languages/types.js';
|
|
18
|
+
export interface SignatureOptions {
|
|
19
|
+
/** Stop descending past this depth (default 8). Keeps the shape coarse. */
|
|
20
|
+
maxDepth?: number;
|
|
21
|
+
/** Stop after this many node kinds (default 128). Bounds large subtrees. */
|
|
22
|
+
maxNodes?: number;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Canonical structural signature of a node's subtree: a parenthesized pre-order
|
|
26
|
+
* encoding of node kinds. Only `type` is read; content is never touched, so the
|
|
27
|
+
* output is safe to transmit.
|
|
28
|
+
*
|
|
29
|
+
* Example: `for_statement ( ) call_expression ( member_expression ( identifier property_identifier ) argument_list ( ) )`
|
|
30
|
+
*/
|
|
31
|
+
export declare function structuralSignature(node: ASTNode, opts?: SignatureOptions): string;
|
|
32
|
+
/**
|
|
33
|
+
* Produce the structural signature for a finding at a 1-based source location.
|
|
34
|
+
* The located node is walked up to its function/class boundary before signing.
|
|
35
|
+
* Returns null when no node contains the location.
|
|
36
|
+
*/
|
|
37
|
+
export declare function signatureForLocation(ast: AST, location: {
|
|
38
|
+
line: number;
|
|
39
|
+
column: number;
|
|
40
|
+
}, opts?: SignatureOptions): string | null;
|
|
41
|
+
//# sourceMappingURL=structuralSignature.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structuralSignature.d.ts","sourceRoot":"","sources":["../src/structuralSignature.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,WAAW,gBAAgB;IAC/B,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAE,gBAAqB,GAAG,MAAM,CAsBtF;AAuDD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC1C,IAAI,GAAE,gBAAqB,GAC1B,MAAM,GAAG,IAAI,CAIf"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { isFunctionType, isClassType } from './languages/tree-sitter/converter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Canonical structural signature of a node's subtree: a parenthesized pre-order
|
|
4
|
+
* encoding of node kinds. Only `type` is read; content is never touched, so the
|
|
5
|
+
* output is safe to transmit.
|
|
6
|
+
*
|
|
7
|
+
* Example: `for_statement ( ) call_expression ( member_expression ( identifier property_identifier ) argument_list ( ) )`
|
|
8
|
+
*/
|
|
9
|
+
export function structuralSignature(node, opts = {}) {
|
|
10
|
+
const maxDepth = opts.maxDepth ?? 8;
|
|
11
|
+
const maxNodes = opts.maxNodes ?? 128;
|
|
12
|
+
const parts = [];
|
|
13
|
+
let count = 0;
|
|
14
|
+
const walk = (n, depth) => {
|
|
15
|
+
if (count >= maxNodes)
|
|
16
|
+
return false;
|
|
17
|
+
count += 1;
|
|
18
|
+
parts.push(n.type);
|
|
19
|
+
const kids = n.children ?? [];
|
|
20
|
+
if (depth >= maxDepth || kids.length === 0)
|
|
21
|
+
return true;
|
|
22
|
+
parts.push('(');
|
|
23
|
+
for (const child of kids) {
|
|
24
|
+
if (!walk(child, depth + 1))
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
parts.push(')');
|
|
28
|
+
return true;
|
|
29
|
+
};
|
|
30
|
+
walk(node, 0);
|
|
31
|
+
return parts.join(' ');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The node whose shape represents the finding's code: the nearest enclosing
|
|
35
|
+
* function/class/method boundary, else the nearest top-level statement, else the
|
|
36
|
+
* located node itself. Climbing to the function boundary means the signature
|
|
37
|
+
* captures the finding's *context* (the whole for-loop, not just the `.save()`),
|
|
38
|
+
* while `maxNodes` keeps a giant function from producing a giant signature.
|
|
39
|
+
*/
|
|
40
|
+
function findSignatureRoot(located) {
|
|
41
|
+
let funcOrClass = null;
|
|
42
|
+
let topLevel = null;
|
|
43
|
+
let cur = located;
|
|
44
|
+
while (cur) {
|
|
45
|
+
if (!funcOrClass && (isFunctionType(cur.type) || isClassType(cur.type))) {
|
|
46
|
+
funcOrClass = cur;
|
|
47
|
+
}
|
|
48
|
+
const parent = cur.parent;
|
|
49
|
+
if (parent && !parent.parent) {
|
|
50
|
+
// `parent` is the root — `cur` is a top-level statement/declaration.
|
|
51
|
+
if (!topLevel)
|
|
52
|
+
topLevel = cur;
|
|
53
|
+
}
|
|
54
|
+
cur = parent;
|
|
55
|
+
}
|
|
56
|
+
return funcOrClass ?? topLevel ?? located;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Locate the deepest node containing the given 1-based line/column.
|
|
60
|
+
* Returns null when the location is outside the tree.
|
|
61
|
+
*/
|
|
62
|
+
function findDeepestNodeAt(root, location) {
|
|
63
|
+
let best = null;
|
|
64
|
+
let bestDepth = -1;
|
|
65
|
+
const walk = (node, depth) => {
|
|
66
|
+
const s = node.location.start;
|
|
67
|
+
const e = node.location.end;
|
|
68
|
+
const contains = (s.line < location.line || (s.line === location.line && s.column <= location.column)) &&
|
|
69
|
+
(e.line > location.line || (e.line === location.line && e.column >= location.column));
|
|
70
|
+
if (!contains)
|
|
71
|
+
return;
|
|
72
|
+
if (depth > bestDepth) {
|
|
73
|
+
best = node;
|
|
74
|
+
bestDepth = depth;
|
|
75
|
+
}
|
|
76
|
+
for (const child of node.children ?? [])
|
|
77
|
+
walk(child, depth + 1);
|
|
78
|
+
};
|
|
79
|
+
walk(root, 0);
|
|
80
|
+
return best;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Produce the structural signature for a finding at a 1-based source location.
|
|
84
|
+
* The located node is walked up to its function/class boundary before signing.
|
|
85
|
+
* Returns null when no node contains the location.
|
|
86
|
+
*/
|
|
87
|
+
export function signatureForLocation(ast, location, opts = {}) {
|
|
88
|
+
const located = findDeepestNodeAt(ast.root, location);
|
|
89
|
+
if (!located)
|
|
90
|
+
return null;
|
|
91
|
+
return structuralSignature(findSignatureRoot(located), opts);
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=structuralSignature.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structuralSignature.js","sourceRoot":"","sources":["../src/structuralSignature.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Severity } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The version of the telemetry *schema* — the payload shape itself — independent
|
|
4
|
+
* of the tool version. This is the cross-repo contract with the feedback service
|
|
5
|
+
* (`../services/src/index.ts`): both sides pin the same value, and a bump on one
|
|
6
|
+
* side without the other is caught by each repo's pinned-shape test. The `v`
|
|
7
|
+
* field below is the tool version, which changes every release while the schema
|
|
8
|
+
* stays put — it is *not* a schema version and must not be used as one.
|
|
9
|
+
*/
|
|
10
|
+
export declare const TELEMETRY_SCHEMA_VERSION = 2;
|
|
11
|
+
/** The exact, minimal set of fields sent. Adding a field here is a security review. */
|
|
12
|
+
export interface TelemetryPayload {
|
|
13
|
+
/** Payload schema version (the shape contract across repos), not the tool version. */
|
|
14
|
+
schema: number;
|
|
15
|
+
/** Anonymous install ID (random, generated locally) — groups submissions by source. */
|
|
16
|
+
install_id: string;
|
|
17
|
+
/** Tool version (package.json). */
|
|
18
|
+
v: string;
|
|
19
|
+
/** Canonical rule ID of the dismissed finding. */
|
|
20
|
+
rule: string;
|
|
21
|
+
/** Urgency level — critical | severe | high. */
|
|
22
|
+
level: Severity;
|
|
23
|
+
/** Dismissal reason, verbatim (the product — it is the human's words). */
|
|
24
|
+
reason: string;
|
|
25
|
+
/** Structural AST signature (grammar kinds only; no identifiers/literals). */
|
|
26
|
+
signature: string;
|
|
27
|
+
/** Coarse language/framework hint (e.g. `typescript`, `react`, `go`). */
|
|
28
|
+
lang: string;
|
|
29
|
+
/** ISO-8601 timestamp of the send. */
|
|
30
|
+
ts: string;
|
|
31
|
+
}
|
|
32
|
+
/** Coarse language/framework hint from a file path — never a path, just a class. */
|
|
33
|
+
export declare function languageHint(filePath: string): string;
|
|
34
|
+
export interface TelemetryPayloadInput {
|
|
35
|
+
install_id: string;
|
|
36
|
+
toolVersion: string;
|
|
37
|
+
rule: string;
|
|
38
|
+
level: Severity;
|
|
39
|
+
reason: string;
|
|
40
|
+
signature: string;
|
|
41
|
+
lang: string;
|
|
42
|
+
}
|
|
43
|
+
/** Assemble the payload. Timestamp is stamped at build time. */
|
|
44
|
+
export declare function buildTelemetryPayload(input: TelemetryPayloadInput): TelemetryPayload;
|
|
45
|
+
/** Human-readable preview, printed before any send so the user can review it. */
|
|
46
|
+
export declare function formatTelemetryPreview(payload: TelemetryPayload): string;
|
|
47
|
+
export interface TelemetryConfig {
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
/** Endpoint URL. Empty/absent → telemetry is a no-op (nothing to send to). */
|
|
50
|
+
endpoint: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolve opt-in from the user-level config (see `installConfig.ts`): OFF unless
|
|
54
|
+
* the user explicitly enabled it via the `telemetry` MCP tool. `opts.endpoint` is
|
|
55
|
+
* a caller override (e.g. the local-dev `--telemetry-endpoint` flag).
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveTelemetryConfig(opts?: {
|
|
58
|
+
endpoint?: string;
|
|
59
|
+
dir?: string;
|
|
60
|
+
}): TelemetryConfig;
|
|
61
|
+
export interface TelemetrySendResult {
|
|
62
|
+
sent: boolean;
|
|
63
|
+
error?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Send a payload to the feedback service. Best-effort: a missing endpoint, a
|
|
67
|
+
* network failure, a timeout, or a non-2xx response all resolve to
|
|
68
|
+
* `{ sent: false }` and never throw — telemetry can never block or fail a gate.
|
|
69
|
+
*/
|
|
70
|
+
export declare function sendTelemetry(payload: TelemetryPayload, endpoint: string, opts?: {
|
|
71
|
+
timeoutMs?: number;
|
|
72
|
+
}): Promise<TelemetrySendResult>;
|
|
73
|
+
/**
|
|
74
|
+
* Compute the structural signature for a finding at a file location. Reads the
|
|
75
|
+
* file, parses it, and signs the shape at that location. Returns null when the
|
|
76
|
+
* file can't be read/parsed or no node contains the location. Requires
|
|
77
|
+
* `initParsers()` to have been called by the caller.
|
|
78
|
+
*/
|
|
79
|
+
export declare function signatureForFinding(filePath: string, line: number, column: number): string | null;
|
|
80
|
+
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,uFAAuF;AACvF,MAAM,WAAW,gBAAgB;IAC/B,sFAAsF;IACtF,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,KAAK,EAAE,QAAQ,CAAC;IAChB,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,EAAE,EAAE,MAAM,CAAC;CACZ;AAID,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAgBrD;AAID,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gEAAgE;AAChE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,GAAG,gBAAgB,CAYpF;AAED,iFAAiF;AACjF,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAexE;AAID,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7C,eAAe,CAMjB;AAID,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAChC,OAAO,CAAC,mBAAmB,CAAC,CAuB9B;AAID;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,IAAI,CAYf"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec 57 — opt-in dismissals telemetry.
|
|
3
|
+
*
|
|
4
|
+
* When the user dismisses a finding and has opted in, a small anonymized payload
|
|
5
|
+
* is sent to the feedback service. The payload is *shape + decision*, never
|
|
6
|
+
* code. The only code-derived field is the structural signature (`structuralSignature`),
|
|
7
|
+
* which is built from grammar kinds alone — identifiers, string literals, table
|
|
8
|
+
* names, paths, and source text are structurally impossible to include.
|
|
9
|
+
*
|
|
10
|
+
* The rules that make this safe and invisible to the gate:
|
|
11
|
+
*
|
|
12
|
+
* - **opt-in** — nothing is sent unless the user opts in via the `telemetry` MCP
|
|
13
|
+
* tool, and the payload is *printed before sending* so the user can review it.
|
|
14
|
+
* - **offline never blocks** — `sendTelemetry` is best-effort: any network error
|
|
15
|
+
* resolves to `{ sent: false }`, never throws, never affects the exit code.
|
|
16
|
+
* - **no content** — the payload type has no field for a path, identifier,
|
|
17
|
+
* literal, or source snippet, so none can leak by accident (acceptance 4).
|
|
18
|
+
*/
|
|
19
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
20
|
+
import path from 'node:path';
|
|
21
|
+
import { parseFile } from './languages/adapterBridge.js';
|
|
22
|
+
import { signatureForLocation } from './structuralSignature.js';
|
|
23
|
+
import { getTelemetryOptIn } from './installConfig.js';
|
|
24
|
+
// ── Payload ──────────────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* The version of the telemetry *schema* — the payload shape itself — independent
|
|
27
|
+
* of the tool version. This is the cross-repo contract with the feedback service
|
|
28
|
+
* (`../services/src/index.ts`): both sides pin the same value, and a bump on one
|
|
29
|
+
* side without the other is caught by each repo's pinned-shape test. The `v`
|
|
30
|
+
* field below is the tool version, which changes every release while the schema
|
|
31
|
+
* stays put — it is *not* a schema version and must not be used as one.
|
|
32
|
+
*/
|
|
33
|
+
export const TELEMETRY_SCHEMA_VERSION = 2;
|
|
34
|
+
// ── Language hint ────────────────────────────────────────────────────────────
|
|
35
|
+
/** Coarse language/framework hint from a file path — never a path, just a class. */
|
|
36
|
+
export function languageHint(filePath) {
|
|
37
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
38
|
+
switch (ext) {
|
|
39
|
+
case '.tsx':
|
|
40
|
+
return 'typescript-react';
|
|
41
|
+
case '.jsx':
|
|
42
|
+
return 'javascript-react';
|
|
43
|
+
case '.ts':
|
|
44
|
+
return 'typescript';
|
|
45
|
+
case '.js':
|
|
46
|
+
return 'javascript';
|
|
47
|
+
case '.go':
|
|
48
|
+
return 'go';
|
|
49
|
+
default:
|
|
50
|
+
return 'other';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Assemble the payload. Timestamp is stamped at build time. */
|
|
54
|
+
export function buildTelemetryPayload(input) {
|
|
55
|
+
return {
|
|
56
|
+
schema: TELEMETRY_SCHEMA_VERSION,
|
|
57
|
+
install_id: input.install_id,
|
|
58
|
+
v: input.toolVersion,
|
|
59
|
+
rule: input.rule,
|
|
60
|
+
level: input.level,
|
|
61
|
+
reason: input.reason,
|
|
62
|
+
signature: input.signature,
|
|
63
|
+
lang: input.lang,
|
|
64
|
+
ts: new Date().toISOString(),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Human-readable preview, printed before any send so the user can review it. */
|
|
68
|
+
export function formatTelemetryPreview(payload) {
|
|
69
|
+
return [
|
|
70
|
+
'',
|
|
71
|
+
'── Telemetry payload (preview — review before sending) ──',
|
|
72
|
+
` schema: ${payload.schema}`,
|
|
73
|
+
` install ID: ${payload.install_id}`,
|
|
74
|
+
` tool version: ${payload.v}`,
|
|
75
|
+
` rule: ${payload.rule}`,
|
|
76
|
+
` urgency: ${payload.level}`,
|
|
77
|
+
` reason: ${payload.reason}`,
|
|
78
|
+
` signature: ${payload.signature}`,
|
|
79
|
+
` language: ${payload.lang}`,
|
|
80
|
+
' (no file paths, identifiers, literals, or source text are included)',
|
|
81
|
+
'',
|
|
82
|
+
].join('\n');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolve opt-in from the user-level config (see `installConfig.ts`): OFF unless
|
|
86
|
+
* the user explicitly enabled it via the `telemetry` MCP tool. `opts.endpoint` is
|
|
87
|
+
* a caller override (e.g. the local-dev `--telemetry-endpoint` flag).
|
|
88
|
+
*/
|
|
89
|
+
export function resolveTelemetryConfig(opts = {}) {
|
|
90
|
+
const optIn = getTelemetryOptIn(opts.dir);
|
|
91
|
+
return {
|
|
92
|
+
enabled: optIn.enabled,
|
|
93
|
+
endpoint: opts.endpoint ?? optIn.endpoint,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Send a payload to the feedback service. Best-effort: a missing endpoint, a
|
|
98
|
+
* network failure, a timeout, or a non-2xx response all resolve to
|
|
99
|
+
* `{ sent: false }` and never throw — telemetry can never block or fail a gate.
|
|
100
|
+
*/
|
|
101
|
+
export async function sendTelemetry(payload, endpoint, opts = {}) {
|
|
102
|
+
if (!endpoint)
|
|
103
|
+
return { sent: false };
|
|
104
|
+
const timeoutMs = opts.timeoutMs ?? 2000;
|
|
105
|
+
const controller = new AbortController();
|
|
106
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
107
|
+
try {
|
|
108
|
+
const response = await fetch(endpoint, {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: { 'content-type': 'application/json' },
|
|
111
|
+
body: JSON.stringify(payload),
|
|
112
|
+
signal: controller.signal,
|
|
113
|
+
});
|
|
114
|
+
clearTimeout(timer);
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
return { sent: false, error: `HTTP ${response.status}` };
|
|
117
|
+
}
|
|
118
|
+
return { sent: true };
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
return { sent: false, error: error instanceof Error ? error.message : String(error) };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ── Signature from a finding ─────────────────────────────────────────────────
|
|
126
|
+
/**
|
|
127
|
+
* Compute the structural signature for a finding at a file location. Reads the
|
|
128
|
+
* file, parses it, and signs the shape at that location. Returns null when the
|
|
129
|
+
* file can't be read/parsed or no node contains the location. Requires
|
|
130
|
+
* `initParsers()` to have been called by the caller.
|
|
131
|
+
*/
|
|
132
|
+
export function signatureForFinding(filePath, line, column) {
|
|
133
|
+
try {
|
|
134
|
+
if (!existsSync(filePath))
|
|
135
|
+
return null;
|
|
136
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
137
|
+
const ast = parseFile(filePath, content);
|
|
138
|
+
if (!ast)
|
|
139
|
+
return null;
|
|
140
|
+
const signature = signatureForLocation(ast, { line, column });
|
|
141
|
+
ast.dispose?.();
|
|
142
|
+
return signature;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -114,6 +114,13 @@ export interface Violation {
|
|
|
114
114
|
* `severityCap` soften-in-place mechanism.
|
|
115
115
|
*/
|
|
116
116
|
gateExcluded?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Spec 57 — true when a committed dismissal matches this finding's
|
|
119
|
+
* fingerprint. A dismissed finding never blocks the gate, but it is still
|
|
120
|
+
* counted in `summary.totalViolations` — dismissal never silently reduces the
|
|
121
|
+
* total; the reduced count is reported separately as `summary.dismissed`.
|
|
122
|
+
*/
|
|
123
|
+
dismissed?: boolean;
|
|
117
124
|
violationType?: string;
|
|
118
125
|
symbol?: string;
|
|
119
126
|
principle?: string;
|
|
@@ -148,6 +155,28 @@ export interface Violation {
|
|
|
148
155
|
*/
|
|
149
156
|
resolution?: Resolution;
|
|
150
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* A coverage diagnostic — a per-occurrence record that the analyzer could not
|
|
160
|
+
* *see* a region of the code, as distinct from a {@link Violation}, which says
|
|
161
|
+
* the code is wrong. Diagnostics are never blocking: the gate only ever reads
|
|
162
|
+
* violations. They are surfaced (counted, with file + line) in the report's
|
|
163
|
+
* coverage section and in the `metadata.diagnostics` channel alongside
|
|
164
|
+
* `zero-files` / `no-result` ("the tool couldn't do its job").
|
|
165
|
+
*/
|
|
166
|
+
export interface CoverageDiagnostic {
|
|
167
|
+
/** Owning analyzer (e.g. `schema`, `dependency-graph`). */
|
|
168
|
+
analyzerName: string;
|
|
169
|
+
/** The diagnostic kind — currently `unresolved-query` or `unresolved-dynamic-import`. */
|
|
170
|
+
kind: 'unresolved-query' | 'unresolved-dynamic-import';
|
|
171
|
+
/** Human-readable explanation of what could not be resolved. */
|
|
172
|
+
message: string;
|
|
173
|
+
/** File the unresolved construct is in. */
|
|
174
|
+
file: string;
|
|
175
|
+
/** 1-based line of the unresolved construct. */
|
|
176
|
+
line: number;
|
|
177
|
+
/** Kind-specific detail (e.g. `{ identifier }` or `{ expression }`). */
|
|
178
|
+
details?: Record<string, unknown>;
|
|
179
|
+
}
|
|
151
180
|
/**
|
|
152
181
|
* Per-rule coverage classification — emitted on every audit.
|
|
153
182
|
* @see buildCoverageReport() in pipeline.ts
|
|
@@ -209,6 +238,8 @@ export interface AnalyzerResult {
|
|
|
209
238
|
file: string;
|
|
210
239
|
error: string;
|
|
211
240
|
}>;
|
|
241
|
+
/** Per-occurrence coverage diagnostics (non-blocking). */
|
|
242
|
+
diagnostics?: CoverageDiagnostic[];
|
|
212
243
|
/** Number of files processed by the analyzer. */
|
|
213
244
|
filesProcessed?: number;
|
|
214
245
|
/** Arbitrary metrics bag — used by cross-domain, visualizations, etc. */
|
|
@@ -266,6 +297,9 @@ export interface VisitorResult {
|
|
|
266
297
|
violations: Violation[];
|
|
267
298
|
facts: Record<string, unknown>;
|
|
268
299
|
indexFacts?: IndexFactsEntry[];
|
|
300
|
+
/** Per-occurrence coverage diagnostics (non-blocking). Collected into
|
|
301
|
+
* `metadata.diagnostics` by the pipeline. */
|
|
302
|
+
diagnostics?: CoverageDiagnostic[];
|
|
269
303
|
}
|
|
270
304
|
/** Return type from stage-3/4 reducer reduce(). */
|
|
271
305
|
export interface ReducerResult {
|
|
@@ -283,6 +317,9 @@ export interface ReducerResult {
|
|
|
283
317
|
* `context.readSource` do not need to report here.
|
|
284
318
|
*/
|
|
285
319
|
consumedFiles?: string[];
|
|
320
|
+
/** Per-occurrence coverage diagnostics (non-blocking). Collected into
|
|
321
|
+
* `metadata.diagnostics` by the pipeline. */
|
|
322
|
+
diagnostics?: CoverageDiagnostic[];
|
|
286
323
|
}
|
|
287
324
|
/** Per-file visitor — runs on every AST in stage 2. */
|
|
288
325
|
export interface Stage2Visitor {
|
|
@@ -470,6 +507,9 @@ export interface PipelineResult {
|
|
|
470
507
|
analyzerName: string;
|
|
471
508
|
kind: string;
|
|
472
509
|
message: string;
|
|
510
|
+
file?: string;
|
|
511
|
+
line?: number;
|
|
512
|
+
details?: Record<string, unknown>;
|
|
473
513
|
}>;
|
|
474
514
|
coverage?: RuleCoverage[];
|
|
475
515
|
/** Spec 29: Per-table provenance catalog from schema reducer */
|
|
@@ -576,6 +616,12 @@ export interface AuditSummary {
|
|
|
576
616
|
type: string;
|
|
577
617
|
count: number;
|
|
578
618
|
}>;
|
|
619
|
+
/**
|
|
620
|
+
* Spec 57 — number of findings cleared by a committed dismissal. Reported
|
|
621
|
+
* alongside `totalViolations` ("43 findings, 3 dismissed"), never subtracted
|
|
622
|
+
* from it. Absent/0 when no dismissals apply.
|
|
623
|
+
*/
|
|
624
|
+
dismissed?: number;
|
|
579
625
|
}
|
|
580
626
|
export interface AuditResult {
|
|
581
627
|
timestamp: Date;
|
|
@@ -597,11 +643,15 @@ export interface AuditResult {
|
|
|
597
643
|
provenanceResolutionMs?: number;
|
|
598
644
|
/** Blast radius impact for changed functions (Spec 14 R6 — scoped audits only). */
|
|
599
645
|
blastRadius?: BlastRadiusImpact;
|
|
600
|
-
/** Zero-files
|
|
646
|
+
/** Zero-files / missing-result diagnostics plus per-occurrence coverage
|
|
647
|
+
* diagnostics (unresolved SQL/specifier). Non-blocking — see CoverageDiagnostic. */
|
|
601
648
|
diagnostics?: Array<{
|
|
602
649
|
analyzerName: string;
|
|
603
650
|
kind: string;
|
|
604
651
|
message: string;
|
|
652
|
+
file?: string;
|
|
653
|
+
line?: number;
|
|
654
|
+
details?: Record<string, unknown>;
|
|
605
655
|
}>;
|
|
606
656
|
baseline?: {
|
|
607
657
|
present: boolean;
|
|
@@ -647,6 +697,9 @@ export interface AuditResult {
|
|
|
647
697
|
inputPresence?: InputPresence;
|
|
648
698
|
/** Spec 44: per-file accounting (analyzed vs. dropped, with reasons). */
|
|
649
699
|
fileAccounting?: FileAccountingSummary;
|
|
700
|
+
/** Spec 50 R2 — which config layer supplied each size threshold (default,
|
|
701
|
+
* project-config, project-lint-config, preset:<id>). */
|
|
702
|
+
thresholdSources?: ThresholdSource[];
|
|
650
703
|
};
|
|
651
704
|
}
|
|
652
705
|
/** Thrown when an in-process audit is stopped via AbortSignal (parent cancel or soft budget). */
|
|
@@ -832,6 +885,24 @@ export interface AuditMetadata {
|
|
|
832
885
|
defaultValue: unknown;
|
|
833
886
|
effectiveValue: unknown;
|
|
834
887
|
}>;
|
|
888
|
+
/** Spec 50 R2 — which config layer supplied each size threshold. */
|
|
889
|
+
thresholdSources?: ThresholdSource[];
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Spec 50 R2 — a size threshold and the config layer that supplied its value.
|
|
893
|
+
* Surfaces in audit metadata and `print-config` so a threshold that came from
|
|
894
|
+
* the project's ESLint config (vs. a default or an explicit .codeauditor.json)
|
|
895
|
+
* is named, not archaeology.
|
|
896
|
+
*/
|
|
897
|
+
export interface ThresholdSource {
|
|
898
|
+
/** Dot-notation key within the analyzer namespace, e.g. `solid.maxLinesPerMethod`. */
|
|
899
|
+
key: string;
|
|
900
|
+
/** The effective value the run used. */
|
|
901
|
+
value: unknown;
|
|
902
|
+
/** Where the value came from: `default`, `project-config`, `project-lint-config`, `preset:<id>`, `path-profile:<name>`. */
|
|
903
|
+
source: string;
|
|
904
|
+
/** The analyzer's runtime default (for the `[differs from default]` display). */
|
|
905
|
+
defaultValue: unknown;
|
|
835
906
|
}
|
|
836
907
|
export interface BaseAnalyzerOptions {
|
|
837
908
|
verbose?: boolean;
|