@reneturcios/tracewatch 0.0.0-stage → 0.1.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.
Files changed (49) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +138 -2
  3. package/dist/adapters.d.ts +31 -0
  4. package/dist/adapters.js +128 -0
  5. package/dist/adapters.js.map +1 -0
  6. package/dist/blame.d.ts +15 -0
  7. package/dist/blame.js +165 -0
  8. package/dist/blame.js.map +1 -0
  9. package/dist/cli.d.ts +2 -0
  10. package/dist/cli.js +236 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/core.d.ts +18 -0
  13. package/dist/core.js +19 -0
  14. package/dist/core.js.map +1 -0
  15. package/dist/diff.d.ts +21 -0
  16. package/dist/diff.js +131 -0
  17. package/dist/diff.js.map +1 -0
  18. package/dist/git.d.ts +16 -0
  19. package/dist/git.js +80 -0
  20. package/dist/git.js.map +1 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +3 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/ingest.d.ts +54 -0
  25. package/dist/ingest.js +182 -0
  26. package/dist/ingest.js.map +1 -0
  27. package/dist/mcp.d.ts +1 -0
  28. package/dist/mcp.js +80 -0
  29. package/dist/mcp.js.map +1 -0
  30. package/dist/render.d.ts +13 -0
  31. package/dist/render.js +151 -0
  32. package/dist/render.js.map +1 -0
  33. package/dist/report.d.ts +3 -0
  34. package/dist/report.js +61 -0
  35. package/dist/report.js.map +1 -0
  36. package/dist/store.d.ts +31 -0
  37. package/dist/store.js +163 -0
  38. package/dist/store.js.map +1 -0
  39. package/dist/types.d.ts +215 -0
  40. package/dist/types.js +13 -0
  41. package/dist/types.js.map +1 -0
  42. package/dist/util.d.ts +16 -0
  43. package/dist/util.js +65 -0
  44. package/dist/util.js.map +1 -0
  45. package/dist/watch.d.ts +62 -0
  46. package/dist/watch.js +401 -0
  47. package/dist/watch.js.map +1 -0
  48. package/package.json +1 -6
  49. package/server.json +1 -0
package/dist/watch.js ADDED
@@ -0,0 +1,401 @@
1
+ /**
2
+ * Watch mode: poll a target and scan new content on arrival, recording
3
+ * time-to-detect for every detection.
4
+ *
5
+ * Local mode watches a directory: new or changed text files are scanned
6
+ * with injectcheck the poll they appear in, and a git HEAD move triggers
7
+ * a full ingest plus diff, with alerts for new/changed findings and ref
8
+ * events. GitHub mode watches an owner/repo slug through the ghapi
9
+ * helper: new issues and PRs are scanned on arrival, and a HEAD move is
10
+ * recorded (and scanned too, when a local clone path is supplied).
11
+ *
12
+ * State checkpoints to watch-state.json after every cycle, so a restart
13
+ * resumes from the last poll instead of re-alerting history. Polling is
14
+ * conservative (default 60 s, two API calls per GitHub cycle) and every
15
+ * detection records TTD = detected-at minus the content's own creation
16
+ * timestamp. Nothing here guesses: an API answer that cannot be parsed
17
+ * is logged as a watch note and retried next cycle, never faked.
18
+ */
19
+ import { createHash } from "node:crypto";
20
+ import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
21
+ import { basename, extname, join, relative, resolve } from "node:path";
22
+ import { tmpdir } from "node:os";
23
+ import { diffScans } from "./diff.js";
24
+ import { commitTime, headSha } from "./git.js";
25
+ import { GHAPI, } from "./blame.js";
26
+ import { ingestPath, recordScan, runCapture, runInjectcheckFile, toolVersion } from "./ingest.js";
27
+ import { makeFindingId, makeIdentity } from "./util.js";
28
+ const SKIP_DIRS = new Set([".git", "node_modules", "dist", ".tracewatch", "coverage", ".next", "target"]);
29
+ const TEXT_EXTS = new Set([".md", ".markdown", ".txt", ".rst", ".mdx", ".adoc"]);
30
+ export function snapshotTree(root) {
31
+ const out = {};
32
+ const walk = (dir) => {
33
+ let entries;
34
+ try {
35
+ entries = readdirSync(dir, { withFileTypes: true });
36
+ }
37
+ catch {
38
+ return;
39
+ }
40
+ for (const e of entries) {
41
+ const full = join(dir, e.name);
42
+ if (e.isDirectory()) {
43
+ if (!SKIP_DIRS.has(e.name))
44
+ walk(full);
45
+ }
46
+ else if (e.isFile()) {
47
+ try {
48
+ const st = statSync(full);
49
+ const mark = { mtimeMs: st.mtimeMs, size: st.size, birthtimeMs: st.birthtimeMs };
50
+ if (st.size <= 2 * 1024 * 1024) {
51
+ mark.hash = createHash("sha1").update(readFileSync(full)).digest("hex");
52
+ }
53
+ out[relative(root, full).split("\\").join("/")] = mark;
54
+ }
55
+ catch {
56
+ // Vanished mid-walk: next poll sees the settled state.
57
+ }
58
+ }
59
+ }
60
+ };
61
+ walk(root);
62
+ return out;
63
+ }
64
+ export const defaultDeps = {
65
+ scanFile: (p) => runInjectcheckFile(p),
66
+ ingest: (store, path, opts) => ingestPath(store, path, { name: opts.name, source: "watch" }),
67
+ ghGet: async (path) => {
68
+ if (!existsSync(GHAPI))
69
+ return null;
70
+ const res = await runCapture("python3", [GHAPI, "GET", path], 30000);
71
+ return res.code === 0 && res.stdout.includes("HTTP 200") ? res.stdout : null;
72
+ },
73
+ now: () => new Date(),
74
+ };
75
+ function loadState(store) {
76
+ return store.readWatchState() ?? { repos: {} };
77
+ }
78
+ function saveState(store, state) {
79
+ store.writeWatchState(state);
80
+ }
81
+ async function recordTextScan(ctx, repo, adapted, extra) {
82
+ const version = ctx.deps.version ? await ctx.deps.version("injectcheck") : await toolVersion("injectcheck");
83
+ const result = recordScan(ctx.store, repo, "watch", [adapted], {
84
+ injectcheck: { version, verdict: adapted.verdict, counts: adapted.counts, status: "ok" },
85
+ }, extra);
86
+ return { scanId: result.record.scanId, observations: result.observations };
87
+ }
88
+ async function diffAlerts(ctx, repo, at) {
89
+ const alerts = [];
90
+ try {
91
+ const diff = diffScans(ctx.store, repo);
92
+ for (const f of diff.added) {
93
+ alerts.push({ at, repo, kind: "new-finding", findingId: f.findingId, message: `NEW ${f.tool} ${f.rule} (${f.severity}) in ${f.file}: ${f.detail}` });
94
+ }
95
+ for (const c of diff.changed) {
96
+ alerts.push({ at, repo, kind: "changed-finding", findingId: c.after.findingId, message: `CHANGED ${c.after.tool} ${c.after.rule} in ${c.after.file}: ${c.changes.join("; ")}` });
97
+ }
98
+ for (const ev of diff.refEvents) {
99
+ alerts.push({
100
+ at,
101
+ repo,
102
+ kind: "ref-event",
103
+ findingId: diff.changed.find((c) => c.identity === ev.identity)?.after.findingId,
104
+ message: `${ev.kind.toUpperCase()} ${ev.action} in ${ev.file}: ref ${ev.oldRef} -> ${ev.newRef} (${ev.oldClassification} -> ${ev.newClassification})`,
105
+ });
106
+ }
107
+ }
108
+ catch {
109
+ // Fewer than two scans: nothing to diff yet.
110
+ }
111
+ return alerts;
112
+ }
113
+ /** One local poll cycle. Returns the alerts emitted this cycle. */
114
+ export async function pollLocalOnce(ctx, repo, targetPath) {
115
+ const { store, deps } = ctx;
116
+ const abs = resolve(targetPath);
117
+ const state = loadState(store);
118
+ const entry = state.repos[repo] ?? { target: abs };
119
+ const alerts = [];
120
+ const now = deps.now();
121
+ const at = now.toISOString();
122
+ const snap = snapshotTree(abs);
123
+ const head = await headSha(abs);
124
+ if (!entry.snapshot) {
125
+ // Baseline: record state, and take a baseline scan if none exists.
126
+ entry.snapshot = snap;
127
+ entry.lastHead = head;
128
+ state.repos[repo] = entry;
129
+ saveState(store, state);
130
+ if (store.scans(repo).length === 0) {
131
+ await deps.ingest(store, abs, { name: repo, source: "watch" });
132
+ }
133
+ return alerts;
134
+ }
135
+ const prev = entry.snapshot;
136
+ const changedFiles = [];
137
+ for (const [rel, mark] of Object.entries(snap)) {
138
+ const before = prev[rel];
139
+ if (!before)
140
+ changedFiles.push({ rel, mark, added: true });
141
+ else if (before.hash !== mark.hash || (before.hash === undefined && (before.mtimeMs !== mark.mtimeMs || before.size !== mark.size))) {
142
+ changedFiles.push({ rel, mark, added: false });
143
+ }
144
+ }
145
+ for (const { rel, mark, added } of changedFiles) {
146
+ if (!TEXT_EXTS.has(extname(rel).toLowerCase()))
147
+ continue;
148
+ const adapted = await deps.scanFile(join(abs, rel));
149
+ if (!adapted || adapted.findings.length === 0)
150
+ continue;
151
+ const { scanId, observations } = await recordTextScan(ctx, repo, adapted, { path: abs });
152
+ const createdMs = added && mark.birthtimeMs > 0 ? mark.birthtimeMs : mark.mtimeMs;
153
+ const detection = {
154
+ at,
155
+ repo,
156
+ kind: "file",
157
+ sourceRef: rel,
158
+ createdAt: new Date(createdMs).toISOString(),
159
+ timeToDetectMs: Math.max(0, now.getTime() - createdMs),
160
+ scanId,
161
+ findingIds: observations.map((o) => o.findingId),
162
+ };
163
+ store.appendDetection(detection);
164
+ const alert = {
165
+ at,
166
+ repo,
167
+ kind: "detection",
168
+ message: `DETECTION file ${rel}: ${observations.length} injectcheck finding(s), time-to-detect ${detection.timeToDetectMs} ms`,
169
+ detection,
170
+ };
171
+ alerts.push(alert);
172
+ ctx.emit(alert);
173
+ }
174
+ if (head && entry.lastHead && head !== entry.lastHead) {
175
+ const result = await deps.ingest(store, abs, { name: repo, source: "watch" });
176
+ const createdAt = (await commitTime(abs, "HEAD")) ?? at;
177
+ const diffAlertsList = await diffAlerts(ctx, repo, at);
178
+ const detection = {
179
+ at,
180
+ repo,
181
+ kind: "tree",
182
+ sourceRef: head,
183
+ createdAt,
184
+ timeToDetectMs: Math.max(0, now.getTime() - Date.parse(createdAt)),
185
+ scanId: result.record.scanId,
186
+ findingIds: diffAlertsList.map((a) => a.findingId).filter((x) => Boolean(x)),
187
+ };
188
+ store.appendDetection(detection);
189
+ for (const a of diffAlertsList) {
190
+ alerts.push(a);
191
+ ctx.emit(a);
192
+ }
193
+ const detAlert = {
194
+ at,
195
+ repo,
196
+ kind: "detection",
197
+ message: `DETECTION tree ${head.slice(0, 12)}: re-scanned, ${diffAlertsList.length} change alert(s), time-to-detect ${detection.timeToDetectMs} ms`,
198
+ detection,
199
+ };
200
+ alerts.push(detAlert);
201
+ ctx.emit(detAlert);
202
+ }
203
+ entry.snapshot = snap;
204
+ entry.lastHead = head;
205
+ state.repos[repo] = entry;
206
+ saveState(store, state);
207
+ return alerts;
208
+ }
209
+ /** One GitHub poll cycle (issues/PRs + HEAD). Returns alerts emitted. */
210
+ export async function pollGithubOnce(ctx, slug, opts = {}) {
211
+ const { store, deps } = ctx;
212
+ const alerts = [];
213
+ const now = deps.now();
214
+ const at = now.toISOString();
215
+ const state = loadState(store);
216
+ const entry = state.repos[slug] ?? { target: slug, issuesSeen: {} };
217
+ entry.issuesSeen ??= {};
218
+ const firstContact = Object.keys(entry.issuesSeen).length === 0 && !entry.lastHead;
219
+ // HEAD move.
220
+ const commitsOut = await deps.ghGet(`/repos/${slug}/commits?per_page=1`);
221
+ const headShaRemote = commitsOut?.match(/"sha":\s*"([0-9a-f]{40})"/)?.[1] ?? null;
222
+ const headDate = commitsOut?.match(/"date":\s*"([^"]+)"/)?.[1] ?? null;
223
+ if (headShaRemote && entry.lastHead && headShaRemote !== entry.lastHead) {
224
+ const detection = {
225
+ at,
226
+ repo: slug,
227
+ kind: "tree",
228
+ sourceRef: headShaRemote,
229
+ createdAt: headDate ?? at,
230
+ timeToDetectMs: Math.max(0, now.getTime() - Date.parse(headDate ?? at)),
231
+ findingIds: [],
232
+ };
233
+ if (opts.path) {
234
+ const result = await deps.ingest(store, opts.path, { name: slug, source: "watch" });
235
+ detection.scanId = result.record.scanId;
236
+ const list = await diffAlerts(ctx, slug, at);
237
+ detection.findingIds = list.map((a) => a.findingId).filter((x) => Boolean(x));
238
+ for (const a of list) {
239
+ alerts.push(a);
240
+ ctx.emit(a);
241
+ }
242
+ }
243
+ store.appendDetection(detection);
244
+ const alert = {
245
+ at,
246
+ repo: slug,
247
+ kind: "detection",
248
+ message: `DETECTION tree ${headShaRemote.slice(0, 12)} on ${slug}: time-to-detect ${detection.timeToDetectMs} ms${opts.path ? "" : " (no local clone supplied, tree recorded but not scanned)"}`,
249
+ detection,
250
+ };
251
+ alerts.push(alert);
252
+ ctx.emit(alert);
253
+ }
254
+ if (headShaRemote)
255
+ entry.lastHead = headShaRemote;
256
+ // Issues and PRs.
257
+ const issuesOut = await deps.ghGet(`/repos/${slug}/issues?state=all&per_page=10&sort=created&direction=desc`);
258
+ let issues = null;
259
+ if (issuesOut) {
260
+ const body = issuesOut.slice(issuesOut.indexOf("\n") + 1);
261
+ try {
262
+ const arr = JSON.parse(body);
263
+ if (Array.isArray(arr)) {
264
+ issues = arr.map((i) => ({
265
+ number: Number(i.number),
266
+ title: String(i.title ?? ""),
267
+ body: String(i.body ?? ""),
268
+ created_at: String(i.created_at ?? ""),
269
+ html_url: String(i.html_url ?? ""),
270
+ isPr: "pull_request" in i,
271
+ }));
272
+ }
273
+ }
274
+ catch {
275
+ issues = null;
276
+ }
277
+ }
278
+ if (issues === null) {
279
+ if (!entry.issueNoteAt || Date.parse(at) - Date.parse(entry.issueNoteAt) > 3600000) {
280
+ const note = {
281
+ at,
282
+ repo: slug,
283
+ kind: "watch-note",
284
+ message: "issue poll skipped this cycle: the API helper response could not be parsed in full (long responses are truncated by the helper); will retry next cycle. The CI event-driven pattern in the README is the recommended production path for issue scanning.",
285
+ };
286
+ alerts.push(note);
287
+ ctx.emit(note);
288
+ entry.issueNoteAt = at;
289
+ }
290
+ }
291
+ else {
292
+ const fresh = issues
293
+ .filter((i) => i.number > 0 && !(String(i.number) in (entry.issuesSeen ?? {})))
294
+ .sort((a, b) => a.number - b.number);
295
+ const baseline = firstContact;
296
+ for (const issue of fresh) {
297
+ entry.issuesSeen[String(issue.number)] = issue.created_at;
298
+ if (baseline)
299
+ continue; // First contact: record history silently, do not scan the backlog.
300
+ const tmpDir = join(tmpdir(), `tracewatch-issue-${slug.replace("/", "-")}-${issue.number}`);
301
+ mkdirSync(tmpDir, { recursive: true });
302
+ const tmpFile = join(tmpDir, "body.md");
303
+ writeFileSync(tmpFile, issue.body, "utf8");
304
+ const adaptedRaw = await deps.scanFile(tmpFile);
305
+ if (!adaptedRaw || adaptedRaw.findings.length === 0)
306
+ continue;
307
+ const label = `${issue.isPr ? "pr" : "issue"} #${issue.number}`;
308
+ const adapted = {
309
+ ...adaptedRaw,
310
+ findings: adaptedRaw.findings.map((f) => {
311
+ const location = label;
312
+ const identity = makeIdentity("injectcheck", location, f.rule);
313
+ return {
314
+ ...f,
315
+ file: label,
316
+ identity,
317
+ findingId: makeFindingId("injectcheck", f.rule, location, f.signature),
318
+ data: { ...f.data, source: { kind: issue.isPr ? "pr" : "issue", ref: String(issue.number), url: issue.html_url } },
319
+ };
320
+ }),
321
+ };
322
+ const { scanId, observations } = await recordTextScan(ctx, slug, adapted, { github: slug });
323
+ const detection = {
324
+ at,
325
+ repo: slug,
326
+ kind: issue.isPr ? "pr" : "issue",
327
+ sourceRef: label,
328
+ createdAt: issue.created_at || at,
329
+ timeToDetectMs: Math.max(0, now.getTime() - Date.parse(issue.created_at || at)),
330
+ scanId,
331
+ findingIds: observations.map((o) => o.findingId),
332
+ };
333
+ store.appendDetection(detection);
334
+ const alert = {
335
+ at,
336
+ repo: slug,
337
+ kind: "detection",
338
+ message: `DETECTION ${label} on ${slug}: ${observations.length} injectcheck finding(s), time-to-detect ${detection.timeToDetectMs} ms`,
339
+ detection,
340
+ };
341
+ alerts.push(alert);
342
+ ctx.emit(alert);
343
+ }
344
+ }
345
+ state.repos[slug] = entry;
346
+ saveState(store, state);
347
+ return alerts;
348
+ }
349
+ /** Run watch until stopped (SIGINT/SIGTERM), --once, or --max-minutes. */
350
+ export async function watch(opts) {
351
+ const deps = opts.deps ?? defaultDeps;
352
+ const intervalSec = Math.max(1, opts.intervalSec ?? 60);
353
+ const isLocal = existsSync(opts.target) && statSync(opts.target).isDirectory();
354
+ const repo = opts.name ?? (isLocal ? basename(resolve(opts.target)) : opts.target);
355
+ const log = opts.stderr ?? ((l) => process.stderr.write(`${l}\n`));
356
+ let alertCount = 0;
357
+ const emit = (alert) => {
358
+ alertCount++;
359
+ opts.store.appendAlert(alert);
360
+ const line = JSON.stringify(alert);
361
+ process.stdout.write(`${line}\n`);
362
+ if (opts.alertsFile)
363
+ appendFileSync(opts.alertsFile, `${line}\n`, "utf8");
364
+ };
365
+ const ctx = { store: opts.store, deps, emit };
366
+ let stopped = false;
367
+ const onSignal = () => {
368
+ stopped = true;
369
+ };
370
+ process.on("SIGINT", onSignal);
371
+ process.on("SIGTERM", onSignal);
372
+ const deadline = opts.maxMinutes ? Date.now() + opts.maxMinutes * 60000 : null;
373
+ log(`tracewatch watch: ${isLocal ? "local" : "github"} target ${opts.target}, interval ${intervalSec}s${opts.once ? ", single cycle" : ""}`);
374
+ let cycles = 0;
375
+ try {
376
+ for (;;) {
377
+ if (isLocal)
378
+ await pollLocalOnce(ctx, repo, resolve(opts.target));
379
+ else
380
+ await pollGithubOnce(ctx, opts.target, { path: opts.path });
381
+ cycles++;
382
+ if (opts.once || stopped)
383
+ break;
384
+ if (deadline && Date.now() >= deadline)
385
+ break;
386
+ const until = Date.now() + intervalSec * 1000;
387
+ while (!stopped && Date.now() < until && (!deadline || Date.now() < deadline)) {
388
+ await new Promise((r) => setTimeout(r, Math.min(250, Math.max(1, until - Date.now()))));
389
+ }
390
+ if (stopped || (deadline && Date.now() >= deadline))
391
+ break;
392
+ }
393
+ }
394
+ finally {
395
+ process.off("SIGINT", onSignal);
396
+ process.off("SIGTERM", onSignal);
397
+ }
398
+ log(`tracewatch watch: stopped after ${cycles} cycle(s), ${alertCount} alert(s)`);
399
+ return { cycles, alerts: alertCount };
400
+ }
401
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../src/watch.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1 @@
1
- {
2
- "name": "@reneturcios/tracewatch",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
1
+ {"bin":{"tracewatch":"dist/cli.js"},"dependencies":{"@modelcontextprotocol/sdk":"^1","zod":"^3"},"description":"Security Wave observability and root-cause tracker: scan history, diffs, provenance, and time-to-detect for hookcheck, actionpin, and injectcheck.","devDependencies":{"@types/node":"^20","tsx":"^4","typescript":"^5"},"engines":{"node":">=20"},"files":["dist","server.json"],"homepage":"https://github.com/CloudCorpRecords/tracewatch#readme","license":"MIT","mcpName":"io.github.CloudCorpRecords/tracewatch","name":"@reneturcios/tracewatch","private":false,"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/CloudCorpRecords/tracewatch.git"},"scripts":{"build":"tsc","dev":"tsx src/cli.ts","test":"tsx --test test/*.test.ts"},"type":"module","version":"0.1.0"}
package/server.json ADDED
@@ -0,0 +1 @@
1
+ {"$schema":"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json","description":"Observability, tracking, and root-cause for Security Wave scans and findings.","name":"io.github.CloudCorpRecords/tracewatch","packages":[{"identifier":"@reneturcios/tracewatch","packageArguments":[{"type":"positional","value":"mcp"}],"registryBaseUrl":"https://registry.npmjs.org","registryType":"npm","runtimeHint":"npx","transport":{"type":"stdio"},"version":"0.1.0"},{"identifier":"ghcr.io/cloudcorprecords/tracewatch:0.1.0","packageArguments":[{"type":"positional","value":"mcp"}],"registryType":"oci","runtimeArguments":[{"name":"--rm","type":"named"},{"name":"-i","type":"named"}],"runtimeHint":"docker","transport":{"type":"stdio"}}],"repository":{"source":"github","url":"https://github.com/CloudCorpRecords/tracewatch"},"version":"0.1.0"}