@kairosinternational/watchman 0.1.1 → 0.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/dist/engine.d.ts CHANGED
@@ -1,9 +1,14 @@
1
1
  import type { WatchmanConfig, Scanner, WatchmanReport } from './types/index.js';
2
+ import type { TelemetryReporter } from './telemetry.js';
3
+ export interface ScanOptions {
4
+ telemetry?: TelemetryReporter;
5
+ sessionId?: string;
6
+ }
2
7
  export declare class WatchmanEngine {
3
8
  private scanners;
4
9
  private config;
5
10
  constructor(config: WatchmanConfig);
6
11
  register(scanner: Scanner): void;
7
- scan(): Promise<WatchmanReport>;
12
+ scan(options?: ScanOptions): Promise<WatchmanReport>;
8
13
  }
9
14
  //# sourceMappingURL=engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EAEd,OAAO,EAIP,cAAc,EAEf,MAAM,kBAAkB,CAAC;AAkD1B,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI1B,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC;CAsDtC"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,cAAc,EAEd,OAAO,EAIP,cAAc,EAEf,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAExD,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkDD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAsC;IACtD,OAAO,CAAC,MAAM,CAAiB;gBAEnB,MAAM,EAAE,cAAc;IAIlC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAI1B,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC;CA0E3D"}
package/dist/engine.js CHANGED
@@ -49,10 +49,13 @@ class WatchmanEngine {
49
49
  register(scanner) {
50
50
  this.scanners.set(scanner.id, scanner);
51
51
  }
52
- async scan() {
52
+ async scan(options) {
53
53
  const start = performance.now();
54
54
  const files = await collectFiles(this.config.projectRoot, this.config.exclude ?? []);
55
55
  const results = [];
56
+ const telemetry = options?.telemetry;
57
+ const sessionId = options?.sessionId;
58
+ const canReport = telemetry && sessionId;
56
59
  for (const [id, scanner] of this.scanners) {
57
60
  const scannerConfig = this.config.scanners[id];
58
61
  if (!scannerConfig?.enabled)
@@ -73,6 +76,19 @@ class WatchmanEngine {
73
76
  },
74
77
  };
75
78
  await scanner.scan(ctx);
79
+ // Fire-and-forget telemetry for each finding
80
+ if (canReport) {
81
+ for (const f of findings) {
82
+ telemetry.reportFinding({
83
+ scanner: f.scanner,
84
+ rule: f.rule,
85
+ severity: f.severity,
86
+ target: f.location?.file,
87
+ message: f.message,
88
+ evidence: f.evidence,
89
+ }, sessionId);
90
+ }
91
+ }
76
92
  results.push({
77
93
  scanner: id,
78
94
  findings,
@@ -1 +1 @@
1
- {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  export { WatchmanEngine } from './engine.js';
2
+ export type { ScanOptions } from './engine.js';
3
+ export { createTelemetryReporter } from './telemetry.js';
4
+ export type { TelemetryConfig, TelemetryFinding, TelemetryReporter, StartSessionOptions, } from './telemetry.js';
2
5
  export type { Severity, ScannerId, RuleConfig, ScannerConfig, WatchmanConfig, SourceLocation, Finding, ScanResult, WatchmanReport, ScanContext, Rule, Scanner, } from './types/index.js';
3
6
  export { DEFAULT_CONFIG } from './types/index.js';
4
7
  export { aiToolIntegrityScanner } from './scanners/ai-tool-integrity/index.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,YAAY,EACV,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACd,OAAO,EACP,UAAU,EACV,cAAc,EACd,WAAW,EACX,IAAI,EACJ,OAAO,GACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,YAAY,EAAE,kBAAkB,EAAE,MAAM,+DAA+D,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,2DAA2D,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACd,OAAO,EACP,UAAU,EACV,cAAc,EACd,WAAW,EACX,IAAI,EACJ,OAAO,GACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,EAAE,0BAA0B,EAAE,MAAM,0CAA0C,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,YAAY,EAAE,kBAAkB,EAAE,MAAM,+DAA+D,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,2DAA2D,CAAC"}
package/dist/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SECRET_SIGNATURES = exports.INJECTION_SIGNATURES = exports.runtimeMonitorScanner = exports.dependencyIntegrityScanner = exports.secretsExposureScanner = exports.aiToolIntegrityScanner = exports.DEFAULT_CONFIG = exports.WatchmanEngine = void 0;
3
+ exports.SECRET_SIGNATURES = exports.INJECTION_SIGNATURES = exports.runtimeMonitorScanner = exports.dependencyIntegrityScanner = exports.secretsExposureScanner = exports.aiToolIntegrityScanner = exports.DEFAULT_CONFIG = exports.createTelemetryReporter = exports.WatchmanEngine = void 0;
4
4
  var engine_js_1 = require("./engine.js");
5
5
  Object.defineProperty(exports, "WatchmanEngine", { enumerable: true, get: function () { return engine_js_1.WatchmanEngine; } });
6
+ var telemetry_js_1 = require("./telemetry.js");
7
+ Object.defineProperty(exports, "createTelemetryReporter", { enumerable: true, get: function () { return telemetry_js_1.createTelemetryReporter; } });
6
8
  var index_js_1 = require("./types/index.js");
7
9
  Object.defineProperty(exports, "DEFAULT_CONFIG", { enumerable: true, get: function () { return index_js_1.DEFAULT_CONFIG; } });
8
10
  var index_js_2 = require("./scanners/ai-tool-integrity/index.js");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA6C;AAApC,2GAAA,cAAc,OAAA;AAgBvB,6CAAkD;AAAzC,0GAAA,cAAc,OAAA;AAEvB,kEAA+E;AAAtE,kHAAA,sBAAsB,OAAA;AAC/B,iEAA8E;AAArE,kHAAA,sBAAsB,OAAA;AAC/B,qEAAsF;AAA7E,sHAAA,0BAA0B,OAAA;AACnC,gEAA4E;AAAnE,iHAAA,qBAAqB,OAAA;AAE9B,4DAA4D;AAC5D,yGAAqG;AAA5F,+HAAA,oBAAoB,OAAA;AAE7B,kGAA8F;AAArF,yHAAA,iBAAiB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,yCAA6C;AAApC,2GAAA,cAAc,OAAA;AAEvB,+CAAyD;AAAhD,uHAAA,uBAAuB,OAAA;AAsBhC,6CAAkD;AAAzC,0GAAA,cAAc,OAAA;AAEvB,kEAA+E;AAAtE,kHAAA,sBAAsB,OAAA;AAC/B,iEAA8E;AAArE,kHAAA,sBAAsB,OAAA;AAC/B,qEAAsF;AAA7E,sHAAA,0BAA0B,OAAA;AACnC,gEAA4E;AAAnE,iHAAA,qBAAqB,OAAA;AAE9B,4DAA4D;AAC5D,yGAAqG;AAA5F,+HAAA,oBAAoB,OAAA;AAE7B,kGAA8F;AAArF,yHAAA,iBAAiB,OAAA"}
@@ -0,0 +1,6 @@
1
+ export { INJECTION_SIGNATURES } from './scanners/ai-tool-integrity/patterns/injection-signatures.js';
2
+ export type { InjectionSignature } from './scanners/ai-tool-integrity/patterns/injection-signatures.js';
3
+ export { SECRET_SIGNATURES } from './scanners/secrets-exposure/patterns/secret-signatures.js';
4
+ export type { SecretSignature } from './scanners/secrets-exposure/patterns/secret-signatures.js';
5
+ export type { Severity, ScannerId, Finding, ScanResult, WatchmanReport, } from './types/index.js';
6
+ //# sourceMappingURL=patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../src/patterns.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,+DAA+D,CAAC;AACrG,YAAY,EAAE,kBAAkB,EAAE,MAAM,+DAA+D,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAC;AAC9F,YAAY,EAAE,eAAe,EAAE,MAAM,2DAA2D,CAAC;AAEjG,YAAY,EACV,QAAQ,EACR,SAAS,EACT,OAAO,EACP,UAAU,EACV,cAAc,GACf,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SECRET_SIGNATURES = exports.INJECTION_SIGNATURES = void 0;
4
+ // Edge-safe exports: pattern arrays + types only, no Node.js APIs
5
+ var injection_signatures_js_1 = require("./scanners/ai-tool-integrity/patterns/injection-signatures.js");
6
+ Object.defineProperty(exports, "INJECTION_SIGNATURES", { enumerable: true, get: function () { return injection_signatures_js_1.INJECTION_SIGNATURES; } });
7
+ var secret_signatures_js_1 = require("./scanners/secrets-exposure/patterns/secret-signatures.js");
8
+ Object.defineProperty(exports, "SECRET_SIGNATURES", { enumerable: true, get: function () { return secret_signatures_js_1.SECRET_SIGNATURES; } });
9
+ //# sourceMappingURL=patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.js","sourceRoot":"","sources":["../src/patterns.ts"],"names":[],"mappings":";;;AAAA,kEAAkE;AAClE,yGAAqG;AAA5F,+HAAA,oBAAoB,OAAA;AAE7B,kGAA8F;AAArF,yHAAA,iBAAiB,OAAA"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Telemetry reporter — fire-and-forget finding/session reporting.
3
+ *
4
+ * Edge Runtime compatible: uses only global fetch + AbortSignal.
5
+ * A failed telemetry call never delays or breaks the host app request.
6
+ */
7
+ import type { Severity } from './types/config.types.js';
8
+ export interface TelemetryConfig {
9
+ /** Watchman API base URL, e.g. "https://watchman.guide" */
10
+ endpoint: string;
11
+ /** Tenant API key (raw, not hashed) */
12
+ apiKey: string;
13
+ }
14
+ /** Shape accepted by reportFinding — adapters map their finding type to this. */
15
+ export interface TelemetryFinding {
16
+ scanner: string;
17
+ rule: string;
18
+ severity: Severity;
19
+ target?: string;
20
+ label?: string;
21
+ message: string;
22
+ evidence?: string;
23
+ }
24
+ export interface StartSessionOptions {
25
+ commitSha?: string;
26
+ branch?: string;
27
+ environment?: string;
28
+ }
29
+ export interface TelemetryReporter {
30
+ /** Report a single finding to the Watchman API. Fire-and-forget. */
31
+ reportFinding: (finding: TelemetryFinding, sessionId: string) => void;
32
+ /** Open a scan session. Returns the session ID (or null on failure). */
33
+ startSession: (projectSlug: string, options?: StartSessionOptions) => Promise<string | null>;
34
+ /** Close a scan session. Fire-and-forget. */
35
+ endSession: (sessionId: string) => void;
36
+ }
37
+ export declare function createTelemetryReporter(config: TelemetryConfig): TelemetryReporter;
38
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAIxD,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iFAAiF;AACjF,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,aAAa,EAAE,CAAC,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACtE,wEAAwE;IACxE,YAAY,EAAE,CACZ,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,mBAAmB,KAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC5B,6CAA6C;IAC7C,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAQD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,eAAe,GACtB,iBAAiB,CAoEnB"}
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * Telemetry reporter — fire-and-forget finding/session reporting.
4
+ *
5
+ * Edge Runtime compatible: uses only global fetch + AbortSignal.
6
+ * A failed telemetry call never delays or breaks the host app request.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createTelemetryReporter = createTelemetryReporter;
10
+ // ── Constants ───────────────────────────────────────────────────────
11
+ const TIMEOUT_MS = 5_000;
12
+ // ── Factory ─────────────────────────────────────────────────────────
13
+ function createTelemetryReporter(config) {
14
+ const { endpoint, apiKey } = config;
15
+ // Normalise base URL (strip trailing slash)
16
+ const base = endpoint.replace(/\/+$/, '');
17
+ /** POST helper — swallows all errors. */
18
+ async function post(path, body) {
19
+ try {
20
+ const res = await fetch(`${base}${path}`, {
21
+ method: 'POST',
22
+ headers: {
23
+ 'Content-Type': 'application/json',
24
+ Authorization: `Bearer ${apiKey}`,
25
+ },
26
+ body: JSON.stringify(body),
27
+ signal: AbortSignal.timeout(TIMEOUT_MS),
28
+ });
29
+ if (!res.ok)
30
+ return null;
31
+ return (await res.json());
32
+ }
33
+ catch {
34
+ // Network failure, timeout, JSON parse error — all swallowed.
35
+ return null;
36
+ }
37
+ }
38
+ // ── Public API ──────────────────────────────────────────────────
39
+ function reportFinding(finding, sessionId) {
40
+ // Fire-and-forget — caller does not await.
41
+ void post('/api/findings', {
42
+ session_id: sessionId,
43
+ scanner: finding.scanner,
44
+ rule: finding.rule,
45
+ severity: finding.severity,
46
+ target: finding.target ?? null,
47
+ label: finding.label ?? null,
48
+ details: {
49
+ message: finding.message,
50
+ evidence: finding.evidence ?? null,
51
+ },
52
+ });
53
+ }
54
+ async function startSession(projectSlug, options) {
55
+ const result = await post('/api/sessions/start', {
56
+ project_slug: projectSlug,
57
+ commit_sha: options?.commitSha ?? null,
58
+ branch: options?.branch ?? null,
59
+ environment: options?.environment ?? null,
60
+ });
61
+ return result?.id ?? null;
62
+ }
63
+ function endSession(sessionId) {
64
+ void post('/api/sessions/end', {
65
+ session_id: sessionId,
66
+ });
67
+ }
68
+ return { reportFinding, startSession, endSession };
69
+ }
70
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../src/telemetry.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAgDH,0DAsEC;AA5ED,uEAAuE;AAEvE,MAAM,UAAU,GAAG,KAAK,CAAC;AAEzB,uEAAuE;AAEvE,SAAgB,uBAAuB,CACrC,MAAuB;IAEvB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAEpC,4CAA4C;IAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1C,yCAAyC;IACzC,KAAK,UAAU,IAAI,CACjB,IAAY,EACZ,IAA6B;QAE7B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE;gBACxC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;iBAClC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;gBAC1B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC;aACxC,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,OAAO,IAAI,CAAC;YACzB,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;YAC9D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,mEAAmE;IAEnE,SAAS,aAAa,CAAC,OAAyB,EAAE,SAAiB;QACjE,2CAA2C;QAC3C,KAAK,IAAI,CAAC,eAAe,EAAE;YACzB,UAAU,EAAE,SAAS;YACrB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,IAAI;YAC9B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI;YAC5B,OAAO,EAAE;gBACP,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;aACnC;SACF,CAAC,CAAC;IACL,CAAC;IAED,KAAK,UAAU,YAAY,CACzB,WAAmB,EACnB,OAA6B;QAE7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAiB,qBAAqB,EAAE;YAC/D,YAAY,EAAE,WAAW;YACzB,UAAU,EAAE,OAAO,EAAE,SAAS,IAAI,IAAI;YACtC,MAAM,EAAE,OAAO,EAAE,MAAM,IAAI,IAAI;YAC/B,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,IAAI;SAC1C,CAAC,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,IAAI,IAAI,CAAC;IAC5B,CAAC;IAED,SAAS,UAAU,CAAC,SAAiB;QACnC,KAAK,IAAI,CAAC,mBAAmB,EAAE;YAC7B,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AACrD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kairosinternational/watchman",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Developer security engine — silent threat detection",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -9,6 +9,16 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "import": "./dist/index.js",
11
11
  "default": "./dist/index.js"
12
+ },
13
+ "./patterns": {
14
+ "types": "./dist/patterns.d.ts",
15
+ "import": "./dist/patterns.js",
16
+ "default": "./dist/patterns.js"
17
+ },
18
+ "./telemetry": {
19
+ "types": "./dist/telemetry.d.ts",
20
+ "import": "./dist/telemetry.js",
21
+ "default": "./dist/telemetry.js"
12
22
  }
13
23
  },
14
24
  "scripts": {
package/src/engine.ts CHANGED
@@ -11,6 +11,12 @@ import type {
11
11
  WatchmanReport,
12
12
  Severity,
13
13
  } from './types/index.js';
14
+ import type { TelemetryReporter } from './telemetry.js';
15
+
16
+ export interface ScanOptions {
17
+ telemetry?: TelemetryReporter;
18
+ sessionId?: string;
19
+ }
14
20
 
15
21
  const SEVERITY_ORDER: Record<Severity, number> = {
16
22
  critical: 4,
@@ -72,13 +78,16 @@ export class WatchmanEngine {
72
78
  this.scanners.set(scanner.id, scanner);
73
79
  }
74
80
 
75
- async scan(): Promise<WatchmanReport> {
81
+ async scan(options?: ScanOptions): Promise<WatchmanReport> {
76
82
  const start = performance.now();
77
83
  const files = await collectFiles(
78
84
  this.config.projectRoot,
79
85
  this.config.exclude ?? [],
80
86
  );
81
87
  const results: ScanResult[] = [];
88
+ const telemetry = options?.telemetry;
89
+ const sessionId = options?.sessionId;
90
+ const canReport = telemetry && sessionId;
82
91
 
83
92
  for (const [id, scanner] of this.scanners) {
84
93
  const scannerConfig = this.config.scanners[id];
@@ -103,6 +112,23 @@ export class WatchmanEngine {
103
112
 
104
113
  await scanner.scan(ctx);
105
114
 
115
+ // Fire-and-forget telemetry for each finding
116
+ if (canReport) {
117
+ for (const f of findings) {
118
+ telemetry.reportFinding(
119
+ {
120
+ scanner: f.scanner,
121
+ rule: f.rule,
122
+ severity: f.severity,
123
+ target: f.location?.file,
124
+ message: f.message,
125
+ evidence: f.evidence,
126
+ },
127
+ sessionId,
128
+ );
129
+ }
130
+ }
131
+
106
132
  results.push({
107
133
  scanner: id,
108
134
  findings,
package/src/index.ts CHANGED
@@ -1,4 +1,12 @@
1
1
  export { WatchmanEngine } from './engine.js';
2
+ export type { ScanOptions } from './engine.js';
3
+ export { createTelemetryReporter } from './telemetry.js';
4
+ export type {
5
+ TelemetryConfig,
6
+ TelemetryFinding,
7
+ TelemetryReporter,
8
+ StartSessionOptions,
9
+ } from './telemetry.js';
2
10
 
3
11
  export type {
4
12
  Severity,
@@ -0,0 +1,13 @@
1
+ // Edge-safe exports: pattern arrays + types only, no Node.js APIs
2
+ export { INJECTION_SIGNATURES } from './scanners/ai-tool-integrity/patterns/injection-signatures.js';
3
+ export type { InjectionSignature } from './scanners/ai-tool-integrity/patterns/injection-signatures.js';
4
+ export { SECRET_SIGNATURES } from './scanners/secrets-exposure/patterns/secret-signatures.js';
5
+ export type { SecretSignature } from './scanners/secrets-exposure/patterns/secret-signatures.js';
6
+
7
+ export type {
8
+ Severity,
9
+ ScannerId,
10
+ Finding,
11
+ ScanResult,
12
+ WatchmanReport,
13
+ } from './types/index.js';
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Telemetry reporter — fire-and-forget finding/session reporting.
3
+ *
4
+ * Edge Runtime compatible: uses only global fetch + AbortSignal.
5
+ * A failed telemetry call never delays or breaks the host app request.
6
+ */
7
+
8
+ import type { Severity } from './types/config.types.js';
9
+
10
+ // ── Types ───────────────────────────────────────────────────────────
11
+
12
+ export interface TelemetryConfig {
13
+ /** Watchman API base URL, e.g. "https://watchman.guide" */
14
+ endpoint: string;
15
+ /** Tenant API key (raw, not hashed) */
16
+ apiKey: string;
17
+ }
18
+
19
+ /** Shape accepted by reportFinding — adapters map their finding type to this. */
20
+ export interface TelemetryFinding {
21
+ scanner: string;
22
+ rule: string;
23
+ severity: Severity;
24
+ target?: string;
25
+ label?: string;
26
+ message: string;
27
+ evidence?: string;
28
+ }
29
+
30
+ export interface StartSessionOptions {
31
+ commitSha?: string;
32
+ branch?: string;
33
+ environment?: string;
34
+ }
35
+
36
+ export interface TelemetryReporter {
37
+ /** Report a single finding to the Watchman API. Fire-and-forget. */
38
+ reportFinding: (finding: TelemetryFinding, sessionId: string) => void;
39
+ /** Open a scan session. Returns the session ID (or null on failure). */
40
+ startSession: (
41
+ projectSlug: string,
42
+ options?: StartSessionOptions,
43
+ ) => Promise<string | null>;
44
+ /** Close a scan session. Fire-and-forget. */
45
+ endSession: (sessionId: string) => void;
46
+ }
47
+
48
+ // ── Constants ───────────────────────────────────────────────────────
49
+
50
+ const TIMEOUT_MS = 5_000;
51
+
52
+ // ── Factory ─────────────────────────────────────────────────────────
53
+
54
+ export function createTelemetryReporter(
55
+ config: TelemetryConfig,
56
+ ): TelemetryReporter {
57
+ const { endpoint, apiKey } = config;
58
+
59
+ // Normalise base URL (strip trailing slash)
60
+ const base = endpoint.replace(/\/+$/, '');
61
+
62
+ /** POST helper — swallows all errors. */
63
+ async function post<T = unknown>(
64
+ path: string,
65
+ body: Record<string, unknown>,
66
+ ): Promise<T | null> {
67
+ try {
68
+ const res = await fetch(`${base}${path}`, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ Authorization: `Bearer ${apiKey}`,
73
+ },
74
+ body: JSON.stringify(body),
75
+ signal: AbortSignal.timeout(TIMEOUT_MS),
76
+ });
77
+
78
+ if (!res.ok) return null;
79
+ return (await res.json()) as T;
80
+ } catch {
81
+ // Network failure, timeout, JSON parse error — all swallowed.
82
+ return null;
83
+ }
84
+ }
85
+
86
+ // ── Public API ──────────────────────────────────────────────────
87
+
88
+ function reportFinding(finding: TelemetryFinding, sessionId: string): void {
89
+ // Fire-and-forget — caller does not await.
90
+ void post('/api/findings', {
91
+ session_id: sessionId,
92
+ scanner: finding.scanner,
93
+ rule: finding.rule,
94
+ severity: finding.severity,
95
+ target: finding.target ?? null,
96
+ label: finding.label ?? null,
97
+ details: {
98
+ message: finding.message,
99
+ evidence: finding.evidence ?? null,
100
+ },
101
+ });
102
+ }
103
+
104
+ async function startSession(
105
+ projectSlug: string,
106
+ options?: StartSessionOptions,
107
+ ): Promise<string | null> {
108
+ const result = await post<{ id: string }>('/api/sessions/start', {
109
+ project_slug: projectSlug,
110
+ commit_sha: options?.commitSha ?? null,
111
+ branch: options?.branch ?? null,
112
+ environment: options?.environment ?? null,
113
+ });
114
+ return result?.id ?? null;
115
+ }
116
+
117
+ function endSession(sessionId: string): void {
118
+ void post('/api/sessions/end', {
119
+ session_id: sessionId,
120
+ });
121
+ }
122
+
123
+ return { reportFinding, startSession, endSession };
124
+ }