@expressots/studio-agent 4.0.0-preview.1

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 (86) hide show
  1. package/README.md +143 -0
  2. package/dist/agent.d.ts +127 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +1031 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/discovery/index.d.ts +2 -0
  7. package/dist/discovery/index.d.ts.map +1 -0
  8. package/dist/discovery/index.js +2 -0
  9. package/dist/discovery/index.js.map +1 -0
  10. package/dist/discovery/route-scanner.d.ts +35 -0
  11. package/dist/discovery/route-scanner.d.ts.map +1 -0
  12. package/dist/discovery/route-scanner.js +385 -0
  13. package/dist/discovery/route-scanner.js.map +1 -0
  14. package/dist/index.d.ts +15 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +15 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/instrumentation/index.d.ts +2 -0
  19. package/dist/instrumentation/index.d.ts.map +1 -0
  20. package/dist/instrumentation/index.js +2 -0
  21. package/dist/instrumentation/index.js.map +1 -0
  22. package/dist/instrumentation/tracer.d.ts +40 -0
  23. package/dist/instrumentation/tracer.d.ts.map +1 -0
  24. package/dist/instrumentation/tracer.js +190 -0
  25. package/dist/instrumentation/tracer.js.map +1 -0
  26. package/dist/introspection/container-introspector.d.ts +81 -0
  27. package/dist/introspection/container-introspector.d.ts.map +1 -0
  28. package/dist/introspection/container-introspector.js +251 -0
  29. package/dist/introspection/container-introspector.js.map +1 -0
  30. package/dist/logging/log-capture.d.ts +58 -0
  31. package/dist/logging/log-capture.d.ts.map +1 -0
  32. package/dist/logging/log-capture.js +184 -0
  33. package/dist/logging/log-capture.js.map +1 -0
  34. package/dist/recording/index.d.ts +2 -0
  35. package/dist/recording/index.d.ts.map +1 -0
  36. package/dist/recording/index.js +2 -0
  37. package/dist/recording/index.js.map +1 -0
  38. package/dist/recording/request-recorder.d.ts +43 -0
  39. package/dist/recording/request-recorder.d.ts.map +1 -0
  40. package/dist/recording/request-recorder.js +373 -0
  41. package/dist/recording/request-recorder.js.map +1 -0
  42. package/dist/security/fix-resolver.d.ts +40 -0
  43. package/dist/security/fix-resolver.d.ts.map +1 -0
  44. package/dist/security/fix-resolver.js +283 -0
  45. package/dist/security/fix-resolver.js.map +1 -0
  46. package/dist/security/fix-runner.d.ts +60 -0
  47. package/dist/security/fix-runner.d.ts.map +1 -0
  48. package/dist/security/fix-runner.js +188 -0
  49. package/dist/security/fix-runner.js.map +1 -0
  50. package/dist/security/index.d.ts +140 -0
  51. package/dist/security/index.d.ts.map +1 -0
  52. package/dist/security/index.js +460 -0
  53. package/dist/security/index.js.map +1 -0
  54. package/dist/security/lockfile-graph.d.ts +69 -0
  55. package/dist/security/lockfile-graph.d.ts.map +1 -0
  56. package/dist/security/lockfile-graph.js +245 -0
  57. package/dist/security/lockfile-graph.js.map +1 -0
  58. package/dist/security/npm-audit.d.ts +67 -0
  59. package/dist/security/npm-audit.d.ts.map +1 -0
  60. package/dist/security/npm-audit.js +320 -0
  61. package/dist/security/npm-audit.js.map +1 -0
  62. package/dist/security/osv-cache.d.ts +51 -0
  63. package/dist/security/osv-cache.d.ts.map +1 -0
  64. package/dist/security/osv-cache.js +99 -0
  65. package/dist/security/osv-cache.js.map +1 -0
  66. package/dist/security/osv-client.d.ts +47 -0
  67. package/dist/security/osv-client.d.ts.map +1 -0
  68. package/dist/security/osv-client.js +247 -0
  69. package/dist/security/osv-client.js.map +1 -0
  70. package/dist/security/posture-analyzer.d.ts +44 -0
  71. package/dist/security/posture-analyzer.d.ts.map +1 -0
  72. package/dist/security/posture-analyzer.js +397 -0
  73. package/dist/security/posture-analyzer.js.map +1 -0
  74. package/dist/security/reachability.d.ts +59 -0
  75. package/dist/security/reachability.d.ts.map +1 -0
  76. package/dist/security/reachability.js +302 -0
  77. package/dist/security/reachability.js.map +1 -0
  78. package/dist/security/score.d.ts +36 -0
  79. package/dist/security/score.d.ts.map +1 -0
  80. package/dist/security/score.js +94 -0
  81. package/dist/security/score.js.map +1 -0
  82. package/dist/types/index.d.ts +587 -0
  83. package/dist/types/index.d.ts.map +1 -0
  84. package/dist/types/index.js +14 -0
  85. package/dist/types/index.js.map +1 -0
  86. package/package.json +75 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Compute concrete remediation steps for supply-chain findings.
3
+ *
4
+ * For each finding we want to answer two questions:
5
+ *
6
+ * 1. **What's the root cause?** For transitive vulns the user can't
7
+ * `npm install <vulnerable-pkg>@<fixedVersion>` — they have to
8
+ * bump whichever direct dep brought the package in. We resolve
9
+ * this from the lockfile graph.
10
+ *
11
+ * 2. **What's the fix command?** Either a one-liner the user can
12
+ * paste (`npm install pkg@^X`), `npm audit fix` for the
13
+ * automatic case, or `--force` for semver-major upgrades. When
14
+ * no fix exists we return a `'none'` spec so the UI can render a
15
+ * consistent disabled button.
16
+ *
17
+ * Pure functions — no I/O, no spawning. The engine wires the spec into
18
+ * the fix-runner when the user clicks "Apply fix".
19
+ */
20
+ import type { DependencyFinding, FixGroup } from '../types/index.js';
21
+ import type { AuditFixAvailability } from './npm-audit.js';
22
+ import type { LockfileGraph } from './lockfile-graph.js';
23
+ /**
24
+ * Enrich every finding in-place with `fix` and `rootCause`. The
25
+ * lockfile graph is optional — when absent (no `package-lock.json`)
26
+ * we still produce a best-effort `FixSpec` based on the finding's
27
+ * own `fixedVersion`.
28
+ */
29
+ export declare function enrichFindings(findings: DependencyFinding[], fixAvailability: Map<string, AuditFixAvailability>, lockfile: LockfileGraph | null): DependencyFinding[];
30
+ /**
31
+ * Bucket findings that share a fix command together so the UI can show
32
+ * "Upgrade lodash — fixes 4 advisories" rather than four separate rows.
33
+ *
34
+ * Grouping key:
35
+ * - install commands → group by exact command string
36
+ * - audit-fix / audit-fix-force → one bucket each across the whole report
37
+ * - override / none → not grouped (each finding stays individual)
38
+ */
39
+ export declare function buildFixGroups(findings: DependencyFinding[]): FixGroup[];
40
+ //# sourceMappingURL=fix-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-resolver.d.ts","sourceRoot":"","sources":["../../src/security/fix-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,QAAQ,EAIT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAWzD;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,EAClD,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,iBAAiB,EAAE,CAYrB;AAkGD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,QAAQ,EAAE,CAsDxE"}
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Compute concrete remediation steps for supply-chain findings.
3
+ *
4
+ * For each finding we want to answer two questions:
5
+ *
6
+ * 1. **What's the root cause?** For transitive vulns the user can't
7
+ * `npm install <vulnerable-pkg>@<fixedVersion>` — they have to
8
+ * bump whichever direct dep brought the package in. We resolve
9
+ * this from the lockfile graph.
10
+ *
11
+ * 2. **What's the fix command?** Either a one-liner the user can
12
+ * paste (`npm install pkg@^X`), `npm audit fix` for the
13
+ * automatic case, or `--force` for semver-major upgrades. When
14
+ * no fix exists we return a `'none'` spec so the UI can render a
15
+ * consistent disabled button.
16
+ *
17
+ * Pure functions — no I/O, no spawning. The engine wires the spec into
18
+ * the fix-runner when the user clicks "Apply fix".
19
+ */
20
+ /** Severity ordering used to pick the "worst" severity per fix group. */
21
+ const SEVERITY_ORDER = {
22
+ CRITICAL: 4,
23
+ HIGH: 3,
24
+ MEDIUM: 2,
25
+ LOW: 1,
26
+ INFO: 0,
27
+ };
28
+ /**
29
+ * Enrich every finding in-place with `fix` and `rootCause`. The
30
+ * lockfile graph is optional — when absent (no `package-lock.json`)
31
+ * we still produce a best-effort `FixSpec` based on the finding's
32
+ * own `fixedVersion`.
33
+ */
34
+ export function enrichFindings(findings, fixAvailability, lockfile) {
35
+ return findings.map((finding) => {
36
+ const rootCause = lockfile
37
+ ? lockfile.findRootCause(finding.package) ?? undefined
38
+ : undefined;
39
+ const fix = resolveFix(finding, fixAvailability, rootCause, lockfile);
40
+ return {
41
+ ...finding,
42
+ fix,
43
+ rootCause,
44
+ };
45
+ });
46
+ }
47
+ /**
48
+ * Pick the right command for `finding`. Order of preference:
49
+ *
50
+ * 1. If the package is a direct dep and we know a `fixedVersion`,
51
+ * generate a precise `npm install <pkg>@<ver>` command.
52
+ * 2. If npm-audit says it can fix without going semver-major:
53
+ * `npm audit fix`.
54
+ * 3. If npm-audit can only fix with `--force`: `npm audit fix --force`,
55
+ * flagged as breaking.
56
+ * 4. Otherwise — no upstream fix yet. UI renders an advisory link
57
+ * and a disabled "Apply fix" button.
58
+ */
59
+ function resolveFix(finding, availability, rootCause, lockfile) {
60
+ const fa = availability.get(finding.package) ?? { kind: 'none' };
61
+ const isDirect = rootCause?.isDirect ?? lockfile?.isDirect(finding.package) ?? false;
62
+ // Direct dep with a known fix version → exact install command.
63
+ if (isDirect && finding.fixedVersion) {
64
+ const breaking = isSemVerMajor(finding.installedVersion, finding.fixedVersion);
65
+ return {
66
+ kind: 'install',
67
+ command: `npm install ${finding.package}@${quoteVersionRange(finding.fixedVersion)}`,
68
+ breaking,
69
+ label: `Upgrade ${finding.package} ${finding.installedVersion} → ${finding.fixedVersion}`,
70
+ note: breaking ? 'Semver-major upgrade — may include breaking changes.' : undefined,
71
+ };
72
+ }
73
+ // npm-audit reports a specific upgrade target (typically points at
74
+ // the root package the user owns, even for transitive vulns).
75
+ if (fa.kind === 'specific') {
76
+ if (!fa.isSemVerMajor) {
77
+ return {
78
+ kind: 'audit-fix',
79
+ command: 'npm audit fix',
80
+ breaking: false,
81
+ label: rootCause && !rootCause.isDirect
82
+ ? `Upgrade ${rootCause.rootPackage} via npm audit fix`
83
+ : `Auto-fix ${fa.name ?? finding.package}`,
84
+ };
85
+ }
86
+ return {
87
+ kind: 'audit-fix-force',
88
+ command: 'npm audit fix --force',
89
+ breaking: true,
90
+ label: rootCause && !rootCause.isDirect
91
+ ? `Force-upgrade ${rootCause.rootPackage} (semver-major)`
92
+ : `Force-fix ${fa.name ?? finding.package}`,
93
+ note: '`--force` may install semver-major upgrades that break your build.',
94
+ };
95
+ }
96
+ // npm-audit said it can auto-fix but didn't pin a version (the most
97
+ // common "fixAvailable: true" case). We still recommend running
98
+ // `npm audit fix` — npm will pick the right targets.
99
+ if (fa.kind === 'auto') {
100
+ return {
101
+ kind: 'audit-fix',
102
+ command: 'npm audit fix',
103
+ breaking: false,
104
+ label: rootCause && !rootCause.isDirect
105
+ ? `Upgrade ${rootCause.rootPackage} via npm audit fix`
106
+ : `Auto-fix ${finding.package} via npm audit fix`,
107
+ };
108
+ }
109
+ // No fixAvailable target. If the vulnerable package isn't a direct
110
+ // dep but we know a fixed version, the user can pin it via
111
+ // `package.json` overrides — surface that as a manual step.
112
+ if (!isDirect && rootCause && finding.fixedVersion) {
113
+ return {
114
+ kind: 'override',
115
+ command: '',
116
+ breaking: false,
117
+ label: `Add a ${finding.package} override`,
118
+ note: `Upstream (${rootCause.rootPackage}) hasn't shipped a fixed version. ` +
119
+ `Add an "overrides" entry to package.json pinning ${finding.package}@${finding.fixedVersion}.`,
120
+ };
121
+ }
122
+ return {
123
+ kind: 'none',
124
+ command: '',
125
+ breaking: false,
126
+ label: 'No upstream fix yet',
127
+ note: isDirect ? 'Watch the advisory link for a patched release.' : undefined,
128
+ };
129
+ }
130
+ /**
131
+ * Bucket findings that share a fix command together so the UI can show
132
+ * "Upgrade lodash — fixes 4 advisories" rather than four separate rows.
133
+ *
134
+ * Grouping key:
135
+ * - install commands → group by exact command string
136
+ * - audit-fix / audit-fix-force → one bucket each across the whole report
137
+ * - override / none → not grouped (each finding stays individual)
138
+ */
139
+ export function buildFixGroups(findings) {
140
+ const buckets = new Map();
141
+ for (const f of findings) {
142
+ if (!f.fix)
143
+ continue;
144
+ if (f.fix.kind === 'none' || f.fix.kind === 'override')
145
+ continue;
146
+ const key = `${f.fix.kind}::${f.fix.command}`;
147
+ const list = buckets.get(key) ?? [];
148
+ list.push(f);
149
+ buckets.set(key, list);
150
+ }
151
+ const out = [];
152
+ for (const [key, list] of buckets) {
153
+ if (list.length === 0)
154
+ continue;
155
+ const first = list[0];
156
+ const fix = first.fix;
157
+ const groupPkg = first.rootCause?.rootPackage ?? first.package;
158
+ const fromVersion = first.rootCause?.rootInstalledVersion ?? first.installedVersion;
159
+ const toVersion = inferTargetVersion(fix, first);
160
+ const severity = list.reduce((acc, f) => SEVERITY_ORDER[f.severity] > SEVERITY_ORDER[acc] ? f.severity : acc, 'INFO');
161
+ const reachability = pickStrongestReachability(list);
162
+ out.push({
163
+ id: `fg-${hashKey(key)}-${list.length}`,
164
+ package: groupPkg,
165
+ fromVersion,
166
+ toVersion,
167
+ breaking: fix.breaking,
168
+ severity,
169
+ findingIds: list.map((f) => f.id),
170
+ fix,
171
+ reachability,
172
+ });
173
+ }
174
+ // Sort highest-impact groups first: more findings, then higher severity,
175
+ // then reachability (confirmed > likely > unknown > unreachable).
176
+ out.sort((a, b) => {
177
+ if (b.findingIds.length !== a.findingIds.length) {
178
+ return b.findingIds.length - a.findingIds.length;
179
+ }
180
+ if (SEVERITY_ORDER[b.severity] !== SEVERITY_ORDER[a.severity]) {
181
+ return SEVERITY_ORDER[b.severity] - SEVERITY_ORDER[a.severity];
182
+ }
183
+ return reachabilityRank(b.reachability) - reachabilityRank(a.reachability);
184
+ });
185
+ return out;
186
+ }
187
+ // ────────────────────────────────────────────────────────────────────────
188
+ // Helpers
189
+ // ────────────────────────────────────────────────────────────────────────
190
+ /**
191
+ * Return the target version string we want to show on a fix-group card.
192
+ * For exact `install` commands we extract it from the command itself;
193
+ * for `audit-fix` we don't actually know the target until npm runs, so
194
+ * we fall back to the finding's `fixedVersion` (best signal we have).
195
+ */
196
+ function inferTargetVersion(fix, finding) {
197
+ if (fix.kind === 'install') {
198
+ const m = fix.command.match(/@([^@]+)$/);
199
+ if (m)
200
+ return m[1].replace(/^['"]/, '').replace(/['"]$/, '');
201
+ }
202
+ return finding.fixedVersion ?? 'latest';
203
+ }
204
+ function pickStrongestReachability(findings) {
205
+ let best = -1;
206
+ let label;
207
+ for (const f of findings) {
208
+ const lvl = f.reachability?.level;
209
+ if (!lvl)
210
+ continue;
211
+ const rank = reachabilityRank(lvl);
212
+ if (rank > best) {
213
+ best = rank;
214
+ label = lvl;
215
+ }
216
+ }
217
+ return label;
218
+ }
219
+ function reachabilityRank(r) {
220
+ switch (r) {
221
+ case 'confirmed':
222
+ return 3;
223
+ case 'likely':
224
+ return 2;
225
+ case 'unknown':
226
+ return 1;
227
+ case 'unreachable':
228
+ return 0;
229
+ default:
230
+ return -1;
231
+ }
232
+ }
233
+ /**
234
+ * Quote the version range for the shell when it contains characters
235
+ * that have special meaning in PowerShell / zsh. Caret (`^`) and tilde
236
+ * (`~`) are safe in bash but break in PowerShell — wrap in single
237
+ * quotes whenever we see them.
238
+ */
239
+ function quoteVersionRange(version) {
240
+ if (/[\s<>=^~|*"'\\]/.test(version)) {
241
+ // Use single quotes; npm install on every platform accepts the
242
+ // shell-quoted form. Escape any embedded single quotes too.
243
+ return `'${version.replace(/'/g, "\\'")}'`;
244
+ }
245
+ return version;
246
+ }
247
+ /**
248
+ * Cheap, non-cryptographic hash for fix-group ids. Stable across
249
+ * scans so the UI can keep its expanded/collapsed state across
250
+ * incoming reports.
251
+ */
252
+ function hashKey(input) {
253
+ let h = 2166136261;
254
+ for (let i = 0; i < input.length; i++) {
255
+ h ^= input.charCodeAt(i);
256
+ h = Math.imul(h, 16777619);
257
+ }
258
+ return (h >>> 0).toString(36);
259
+ }
260
+ /**
261
+ * Best-effort semver-major detection used when npm-audit doesn't tell
262
+ * us whether the upgrade is breaking. We strip non-digit prefixes and
263
+ * compare the leading number — good enough for the standard "X.Y.Z"
264
+ * shape; conservatively returns `false` on anything weirder so we
265
+ * don't scare users about benign patch bumps.
266
+ */
267
+ function isSemVerMajor(from, to) {
268
+ const fromMajor = leadingMajor(from);
269
+ const toMajor = leadingMajor(to);
270
+ if (fromMajor === null || toMajor === null)
271
+ return false;
272
+ return toMajor > fromMajor;
273
+ }
274
+ function leadingMajor(version) {
275
+ // npm-audit `range` strings can be like ">=1.2.3 <2.0.0" — take the
276
+ // first numeric component.
277
+ const m = version.match(/(?:^|[^\d])(\d+)/);
278
+ if (!m)
279
+ return null;
280
+ const n = parseInt(m[1], 10);
281
+ return Number.isFinite(n) ? n : null;
282
+ }
283
+ //# sourceMappingURL=fix-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-resolver.js","sourceRoot":"","sources":["../../src/security/fix-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAYH,yEAAyE;AACzE,MAAM,cAAc,GAA6B;IAC/C,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;CACR,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAC5B,QAA6B,EAC7B,eAAkD,EAClD,QAA8B;IAE9B,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,SAAS,GAAG,QAAQ;YACxB,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,SAAS;YACtD,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QACtE,OAAO;YACL,GAAG,OAAO;YACV,GAAG;YACH,SAAS;SACV,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,UAAU,CACjB,OAA0B,EAC1B,YAA+C,EAC/C,SAAgC,EAChC,QAA8B;IAE9B,MAAM,EAAE,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,MAAe,EAAE,CAAC;IAC1E,MAAM,QAAQ,GACZ,SAAS,EAAE,QAAQ,IAAI,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC;IAEtE,+DAA+D;IAC/D,IAAI,QAAQ,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;QAC/E,OAAO;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,eAAe,OAAO,CAAC,OAAO,IAAI,iBAAiB,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE;YACpF,QAAQ;YACR,KAAK,EAAE,WAAW,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,gBAAgB,MAAM,OAAO,CAAC,YAAY,EAAE;YACzF,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,sDAAsD,CAAC,CAAC,CAAC,SAAS;SACpF,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,8DAA8D;IAC9D,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;YACtB,OAAO;gBACL,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,eAAe;gBACxB,QAAQ,EAAE,KAAK;gBACf,KAAK,EAAE,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ;oBACrC,CAAC,CAAC,WAAW,SAAS,CAAC,WAAW,oBAAoB;oBACtD,CAAC,CAAC,YAAY,EAAE,CAAC,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE;aAC7C,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,uBAAuB;YAChC,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ;gBACrC,CAAC,CAAC,iBAAiB,SAAS,CAAC,WAAW,iBAAiB;gBACzD,CAAC,CAAC,aAAa,EAAE,CAAC,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE;YAC7C,IAAI,EAAE,oEAAoE;SAC3E,CAAC;IACJ,CAAC;IAED,oEAAoE;IACpE,gEAAgE;IAChE,qDAAqD;IACrD,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QACvB,OAAO;YACL,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,eAAe;YACxB,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,SAAS,IAAI,CAAC,SAAS,CAAC,QAAQ;gBACrC,CAAC,CAAC,WAAW,SAAS,CAAC,WAAW,oBAAoB;gBACtD,CAAC,CAAC,YAAY,OAAO,CAAC,OAAO,oBAAoB;SACpD,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,2DAA2D;IAC3D,4DAA4D;IAC5D,IAAI,CAAC,QAAQ,IAAI,SAAS,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACnD,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,SAAS,OAAO,CAAC,OAAO,WAAW;YAC1C,IAAI,EACF,aAAa,SAAS,CAAC,WAAW,oCAAoC;gBACtE,oDAAoD,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,YAAY,GAAG;SACjG,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,KAAK;QACf,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,SAAS;KAC9E,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,QAA6B;IAC1D,MAAM,OAAO,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEvD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,CAAC,CAAC,GAAG;YAAE,SAAS;QACrB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACjE,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC;QAClC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAI,CAAC;QACvB,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,EAAE,WAAW,IAAI,KAAK,CAAC,OAAO,CAAC;QAC/D,MAAM,WAAW,GACf,KAAK,CAAC,SAAS,EAAE,oBAAoB,IAAI,KAAK,CAAC,gBAAgB,CAAC;QAClE,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAC1B,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CACT,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,EACrE,MAAM,CACP,CAAC;QACF,MAAM,YAAY,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAErD,GAAG,CAAC,IAAI,CAAC;YACP,EAAE,EAAE,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE;YACvC,OAAO,EAAE,QAAQ;YACjB,WAAW;YACX,SAAS;YACT,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,QAAQ;YACR,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjC,GAAG;YACH,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,yEAAyE;IACzE,kEAAkE;IAClE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QAChB,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YAChD,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;QACnD,CAAC;QACD,IAAI,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,OAAO,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2EAA2E;AAC3E,UAAU;AACV,2EAA2E;AAE3E;;;;;GAKG;AACH,SAAS,kBAAkB,CAAC,GAAY,EAAE,OAA0B;IAClE,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QACzC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,OAAO,CAAC,YAAY,IAAI,QAAQ,CAAC;AAC1C,CAAC;AAED,SAAS,yBAAyB,CAChC,QAA6B;IAE7B,IAAI,IAAI,GAAW,CAAC,CAAC,CAAC;IACtB,IAAI,KAAqE,CAAC;IAC1E,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,CAAC,CAAC,YAAY,EAAE,KAAK,CAAC;QAClC,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC;YAChB,IAAI,GAAG,IAAI,CAAC;YACZ,KAAK,GAAG,GAAG,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,gBAAgB,CACvB,CAAiE;IAEjE,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,WAAW;YACd,OAAO,CAAC,CAAC;QACX,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC;QACX,KAAK,SAAS;YACZ,OAAO,CAAC,CAAC;QACX,KAAK,aAAa;YAChB,OAAO,CAAC,CAAC;QACX;YACE,OAAO,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,OAAe;IACxC,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,+DAA+D;QAC/D,4DAA4D;QAC5D,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,SAAS,OAAO,CAAC,KAAa;IAC5B,IAAI,CAAC,GAAG,UAAU,CAAC;IACnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,EAAU;IAC7C,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC;IACjC,IAAI,SAAS,KAAK,IAAI,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACzD,OAAO,OAAO,GAAG,SAAS,CAAC;AAC7B,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,oEAAoE;IACpE,2BAA2B;IAC3B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Spawn a fix command (`npm install pkg@ver`, `npm audit fix`, or
3
+ * `npm audit fix --force`) in the host project's cwd and stream its
4
+ * output back to the engine line-by-line.
5
+ *
6
+ * The runner is intentionally policy-free: it neither decides what
7
+ * command to run (that's the fix-resolver's job) nor what to do with
8
+ * the result (the engine triggers a rescan). It just owns spawning,
9
+ * timeouts, buffer caps, and line splitting.
10
+ *
11
+ * **Safety constraints**
12
+ * - Only commands matching a small allow-list of fix kinds run. The
13
+ * command string from the WS message is never forwarded to the
14
+ * shell verbatim; the runner re-builds the argv from a vetted
15
+ * `kind` enum + optional `pkg@version` tuple.
16
+ * - 10 min hard timeout. `npm install` over a slow network can easily
17
+ * take a few minutes; anything beyond that is a hung process.
18
+ * - 4 MB stdout / 256 KB stderr caps so a runaway can't OOM the agent.
19
+ */
20
+ /** Lifecycle states surfaced to the UI for the "fix in progress" banner. */
21
+ export type FixState = 'running' | 'success' | 'error';
22
+ /** Caller-supplied identifier echoed in progress/result frames. */
23
+ export type FixTargetId = string;
24
+ /** The discrete kinds of fix invocations the runner will accept. */
25
+ export type FixCommandKind = 'install' | 'audit-fix' | 'audit-fix-force';
26
+ export interface FixRunInput {
27
+ cwd: string;
28
+ kind: FixCommandKind;
29
+ /** Required for `kind: 'install'`. */
30
+ package?: string;
31
+ /** Required for `kind: 'install'`. */
32
+ version?: string;
33
+ /** Identifier echoed back via progress/result frames. */
34
+ targetId: FixTargetId;
35
+ }
36
+ export interface FixRunResult {
37
+ state: FixState;
38
+ exitCode: number | null;
39
+ command: string;
40
+ durationMs: number;
41
+ stdoutTail: string;
42
+ stderrTail: string;
43
+ }
44
+ export type FixProgressHandler = (line: string, stream: 'stdout' | 'stderr') => void;
45
+ /**
46
+ * Build the argv for `kind`. Returns `null` for an invalid input so
47
+ * callers can fail fast without spawning anything.
48
+ */
49
+ export declare function buildFixArgs(input: FixRunInput): {
50
+ cmd: string;
51
+ args: string[];
52
+ pretty: string;
53
+ } | null;
54
+ /**
55
+ * Spawn the fix command, stream line-by-line progress through
56
+ * `onProgress`, and resolve with the captured tails once the child
57
+ * exits or the timeout fires.
58
+ */
59
+ export declare function runFix(input: FixRunInput, onProgress: FixProgressHandler): Promise<FixRunResult>;
60
+ //# sourceMappingURL=fix-runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-runner.d.ts","sourceRoot":"","sources":["../../src/security/fix-runner.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEvD,mEAAmE;AACnE,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,oEAAoE;AACpE,MAAM,MAAM,cAAc,GACtB,SAAS,GACT,WAAW,GACX,iBAAiB,CAAC;AAEtB,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,cAAc,CAAC;IACrB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,QAAQ,EAAE,WAAW,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAG,QAAQ,KAAK,IAAI,CAAC;AAOrF;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,WAAW,GACjB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAwBxD;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CACpB,KAAK,EAAE,WAAW,EAClB,UAAU,EAAE,kBAAkB,GAC7B,OAAO,CAAC,YAAY,CAAC,CA8GvB"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Spawn a fix command (`npm install pkg@ver`, `npm audit fix`, or
3
+ * `npm audit fix --force`) in the host project's cwd and stream its
4
+ * output back to the engine line-by-line.
5
+ *
6
+ * The runner is intentionally policy-free: it neither decides what
7
+ * command to run (that's the fix-resolver's job) nor what to do with
8
+ * the result (the engine triggers a rescan). It just owns spawning,
9
+ * timeouts, buffer caps, and line splitting.
10
+ *
11
+ * **Safety constraints**
12
+ * - Only commands matching a small allow-list of fix kinds run. The
13
+ * command string from the WS message is never forwarded to the
14
+ * shell verbatim; the runner re-builds the argv from a vetted
15
+ * `kind` enum + optional `pkg@version` tuple.
16
+ * - 10 min hard timeout. `npm install` over a slow network can easily
17
+ * take a few minutes; anything beyond that is a hung process.
18
+ * - 4 MB stdout / 256 KB stderr caps so a runaway can't OOM the agent.
19
+ */
20
+ import { spawn } from 'node:child_process';
21
+ /** Hard cap for an in-flight fix command (10 min). */
22
+ const FIX_TIMEOUT_MS = 10 * 60 * 1000;
23
+ const MAX_STDOUT_BYTES = 4 * 1024 * 1024;
24
+ const MAX_STDERR_BYTES = 256 * 1024;
25
+ /**
26
+ * Build the argv for `kind`. Returns `null` for an invalid input so
27
+ * callers can fail fast without spawning anything.
28
+ */
29
+ export function buildFixArgs(input) {
30
+ switch (input.kind) {
31
+ case 'install': {
32
+ if (!input.package || !input.version)
33
+ return null;
34
+ // Keep the *exact* spec the resolver emitted — quoting is not
35
+ // needed for spawn() because we bypass the shell.
36
+ const spec = `${input.package}@${input.version}`;
37
+ return {
38
+ cmd: 'npm',
39
+ args: ['install', spec],
40
+ pretty: `npm install ${spec}`,
41
+ };
42
+ }
43
+ case 'audit-fix':
44
+ return { cmd: 'npm', args: ['audit', 'fix'], pretty: 'npm audit fix' };
45
+ case 'audit-fix-force':
46
+ return {
47
+ cmd: 'npm',
48
+ args: ['audit', 'fix', '--force'],
49
+ pretty: 'npm audit fix --force',
50
+ };
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+ /**
56
+ * Spawn the fix command, stream line-by-line progress through
57
+ * `onProgress`, and resolve with the captured tails once the child
58
+ * exits or the timeout fires.
59
+ */
60
+ export function runFix(input, onProgress) {
61
+ return new Promise((resolve) => {
62
+ const argv = buildFixArgs(input);
63
+ if (!argv) {
64
+ resolve({
65
+ state: 'error',
66
+ exitCode: null,
67
+ command: '',
68
+ durationMs: 0,
69
+ stdoutTail: '',
70
+ stderrTail: 'Invalid fix command (missing package/version for install).',
71
+ });
72
+ return;
73
+ }
74
+ const started = Date.now();
75
+ let child;
76
+ try {
77
+ child = spawn(argv.cmd, argv.args, {
78
+ cwd: input.cwd,
79
+ // npm on Windows is `npm.cmd`; the shell flag lets the OS resolve it.
80
+ shell: process.platform === 'win32',
81
+ env: process.env,
82
+ });
83
+ }
84
+ catch (err) {
85
+ resolve({
86
+ state: 'error',
87
+ exitCode: null,
88
+ command: argv.pretty,
89
+ durationMs: 0,
90
+ stdoutTail: '',
91
+ stderrTail: err.message || 'failed to spawn npm',
92
+ });
93
+ return;
94
+ }
95
+ let stdoutBytes = 0;
96
+ let stderrBytes = 0;
97
+ let stdoutTail = '';
98
+ let stderrTail = '';
99
+ // Line buffer: hold partial lines across chunk boundaries so the UI
100
+ // never sees a half-formed log entry. Flush on newline.
101
+ let pendingOut = '';
102
+ let pendingErr = '';
103
+ child.stdout?.on('data', (chunk) => {
104
+ stdoutBytes += chunk.length;
105
+ const text = chunk.toString('utf-8');
106
+ if (stdoutBytes <= MAX_STDOUT_BYTES) {
107
+ stdoutTail += text;
108
+ if (stdoutTail.length > MAX_STDOUT_BYTES) {
109
+ stdoutTail = stdoutTail.slice(-MAX_STDOUT_BYTES);
110
+ }
111
+ }
112
+ pendingOut += text;
113
+ pendingOut = flushLines(pendingOut, (line) => onProgress(line, 'stdout'));
114
+ });
115
+ child.stderr?.on('data', (chunk) => {
116
+ stderrBytes += chunk.length;
117
+ const text = chunk.toString('utf-8');
118
+ if (stderrBytes <= MAX_STDERR_BYTES) {
119
+ stderrTail += text;
120
+ if (stderrTail.length > MAX_STDERR_BYTES) {
121
+ stderrTail = stderrTail.slice(-MAX_STDERR_BYTES);
122
+ }
123
+ }
124
+ pendingErr += text;
125
+ pendingErr = flushLines(pendingErr, (line) => onProgress(line, 'stderr'));
126
+ });
127
+ let settled = false;
128
+ const settle = (state, code) => {
129
+ if (settled)
130
+ return;
131
+ settled = true;
132
+ clearTimeout(timer);
133
+ // Flush any trailing partial line.
134
+ if (pendingOut.trim().length > 0)
135
+ onProgress(pendingOut.trim(), 'stdout');
136
+ if (pendingErr.trim().length > 0)
137
+ onProgress(pendingErr.trim(), 'stderr');
138
+ resolve({
139
+ state,
140
+ exitCode: code,
141
+ command: argv.pretty,
142
+ durationMs: Date.now() - started,
143
+ stdoutTail,
144
+ stderrTail,
145
+ });
146
+ };
147
+ const timer = setTimeout(() => {
148
+ try {
149
+ child.kill('SIGTERM');
150
+ }
151
+ catch {
152
+ // Process already exited — ignore.
153
+ }
154
+ // Give it a beat to clean up before we resolve as an error.
155
+ setTimeout(() => settle('error', null), 250);
156
+ }, FIX_TIMEOUT_MS);
157
+ child.on('error', () => settle('error', null));
158
+ child.on('close', (code) => {
159
+ // npm install exits 0 on success. npm audit fix exits 0 on full
160
+ // remediation; non-zero when issues remain (which from the
161
+ // user's POV may still be progress). We treat any non-zero exit
162
+ // as `error` so the UI surfaces it, but the rescan that follows
163
+ // will accurately show the new state.
164
+ settle(code === 0 ? 'success' : 'error', code ?? null);
165
+ });
166
+ });
167
+ }
168
+ /**
169
+ * Split `buffer` on newlines, hand each complete line to `onLine`, and
170
+ * return whatever partial line remains for next time.
171
+ */
172
+ function flushLines(buffer, onLine) {
173
+ let start = 0;
174
+ for (let i = 0; i < buffer.length; i++) {
175
+ const ch = buffer.charCodeAt(i);
176
+ if (ch !== 10 && ch !== 13)
177
+ continue; // \n or \r
178
+ const line = buffer.slice(start, i);
179
+ if (line.length > 0)
180
+ onLine(line);
181
+ // Skip CRLF as a unit.
182
+ if (ch === 13 && buffer.charCodeAt(i + 1) === 10)
183
+ i++;
184
+ start = i + 1;
185
+ }
186
+ return buffer.slice(start);
187
+ }
188
+ //# sourceMappingURL=fix-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-runner.js","sourceRoot":"","sources":["../../src/security/fix-runner.ts"],"names":[],"mappings":"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"}