@superblocksteam/sdk 2.0.149 → 2.0.150-next.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 (49) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/cli-replacement/dependency-install-classifier.d.mts +3 -1
  3. package/dist/cli-replacement/dependency-install-classifier.d.mts.map +1 -1
  4. package/dist/cli-replacement/dependency-install-classifier.mjs +16 -5
  5. package/dist/cli-replacement/dependency-install-classifier.mjs.map +1 -1
  6. package/dist/cli-replacement/dev-s3-restore.test.mjs +73 -14
  7. package/dist/cli-replacement/dev-s3-restore.test.mjs.map +1 -1
  8. package/dist/cli-replacement/dev-startup-git-before-dbfs-order.test.mjs +4 -0
  9. package/dist/cli-replacement/dev-startup-git-before-dbfs-order.test.mjs.map +1 -1
  10. package/dist/cli-replacement/dev.d.mts.map +1 -1
  11. package/dist/cli-replacement/dev.mjs +130 -12
  12. package/dist/cli-replacement/dev.mjs.map +1 -1
  13. package/dist/cli-replacement/install-packages.npm-registry.test.mjs +153 -0
  14. package/dist/cli-replacement/install-packages.npm-registry.test.mjs.map +1 -1
  15. package/dist/cli-replacement/npm-install-summary.d.mts +30 -0
  16. package/dist/cli-replacement/npm-install-summary.d.mts.map +1 -0
  17. package/dist/cli-replacement/npm-install-summary.mjs +67 -0
  18. package/dist/cli-replacement/npm-install-summary.mjs.map +1 -0
  19. package/dist/cli-replacement/npm-install-summary.test.d.mts +2 -0
  20. package/dist/cli-replacement/npm-install-summary.test.d.mts.map +1 -0
  21. package/dist/cli-replacement/npm-install-summary.test.mjs +70 -0
  22. package/dist/cli-replacement/npm-install-summary.test.mjs.map +1 -0
  23. package/dist/cli-replacement/npm-install-timing.d.mts +16 -0
  24. package/dist/cli-replacement/npm-install-timing.d.mts.map +1 -0
  25. package/dist/cli-replacement/npm-install-timing.mjs +104 -0
  26. package/dist/cli-replacement/npm-install-timing.mjs.map +1 -0
  27. package/dist/cli-replacement/npm-install-timing.test.d.mts +2 -0
  28. package/dist/cli-replacement/npm-install-timing.test.d.mts.map +1 -0
  29. package/dist/cli-replacement/npm-install-timing.test.mjs +151 -0
  30. package/dist/cli-replacement/npm-install-timing.test.mjs.map +1 -0
  31. package/dist/telemetry/logging.d.ts +7 -0
  32. package/dist/telemetry/logging.d.ts.map +1 -1
  33. package/dist/telemetry/logging.js +13 -0
  34. package/dist/telemetry/logging.js.map +1 -1
  35. package/dist/telemetry/logging.test.js +40 -0
  36. package/dist/telemetry/logging.test.js.map +1 -1
  37. package/package.json +6 -6
  38. package/src/cli-replacement/dependency-install-classifier.mts +38 -6
  39. package/src/cli-replacement/dev-s3-restore.test.mts +98 -14
  40. package/src/cli-replacement/dev-startup-git-before-dbfs-order.test.mts +4 -0
  41. package/src/cli-replacement/dev.mts +155 -11
  42. package/src/cli-replacement/install-packages.npm-registry.test.mts +235 -0
  43. package/src/cli-replacement/npm-install-summary.mts +82 -0
  44. package/src/cli-replacement/npm-install-summary.test.mts +94 -0
  45. package/src/cli-replacement/npm-install-timing.mts +121 -0
  46. package/src/cli-replacement/npm-install-timing.test.mts +199 -0
  47. package/src/telemetry/logging.test.ts +55 -0
  48. package/src/telemetry/logging.ts +21 -0
  49. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,151 @@
1
+ import nodeFs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
5
+ import { consumeNpmInstallTimingAttributes } from "./npm-install-timing.mjs";
6
+ let logsDir;
7
+ beforeEach(async () => {
8
+ logsDir = await nodeFs.mkdtemp(path.join(os.tmpdir(), "npm-timing-"));
9
+ });
10
+ afterEach(async () => {
11
+ await nodeFs.rm(logsDir, { force: true, recursive: true });
12
+ });
13
+ /** Write a timing file using npm's own naming (`<log id>-timing.json`). */
14
+ async function writeTimingFile(logId, contents) {
15
+ const file = path.join(logsDir, `${logId}-timing.json`);
16
+ await nodeFs.writeFile(file, typeof contents === "string" ? contents : JSON.stringify(contents));
17
+ return file;
18
+ }
19
+ async function listTimingFiles() {
20
+ const entries = await nodeFs.readdir(logsDir);
21
+ return entries.filter((name) => name.endsWith("-timing.json"));
22
+ }
23
+ describe("consumeNpmInstallTimingAttributes", () => {
24
+ it("converts the whitelisted timers from milliseconds to seconds", async () => {
25
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
26
+ metadata: { version: "11.16.0" },
27
+ timers: {
28
+ idealTree: 230,
29
+ reify: 24500,
30
+ "reify:build": 90,
31
+ "reify:loadTrees": 400,
32
+ "reify:unpack": 23200,
33
+ },
34
+ unfinishedTimers: {},
35
+ });
36
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toEqual({
37
+ "superblocks.npm.install.build_seconds": 0.09,
38
+ "superblocks.npm.install.ideal_tree_seconds": 0.23,
39
+ "superblocks.npm.install.load_trees_seconds": 0.4,
40
+ "superblocks.npm.install.reify_seconds": 24.5,
41
+ "superblocks.npm.install.unpack_seconds": 23.2,
42
+ });
43
+ });
44
+ // npm records one `reifyNode:node_modules/<package>` timer per package it
45
+ // touched. Emitting those would be unbounded attribute cardinality and would
46
+ // put dependency names into telemetry, so only the fixed whitelist is ever
47
+ // emitted.
48
+ it("never emits a per-package reifyNode timer", async () => {
49
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
50
+ timers: {
51
+ idealTree: 100,
52
+ "reifyNode:node_modules/@dnd-kit/core": 12,
53
+ "reifyNode:node_modules/lodash": 34,
54
+ "reifyNode:node_modules/react": 56,
55
+ },
56
+ });
57
+ const attributes = await consumeNpmInstallTimingAttributes(logsDir);
58
+ expect(attributes).toEqual({
59
+ "superblocks.npm.install.ideal_tree_seconds": 0.1,
60
+ });
61
+ expect(Object.keys(attributes ?? {}).some((key) => key.includes("reifyNode"))).toBe(false);
62
+ });
63
+ // Which phases npm records depends on what the install did, so a missing
64
+ // timer is normal rather than an error.
65
+ it("omits timers npm did not record", async () => {
66
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
67
+ timers: { reify: 500 },
68
+ });
69
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toEqual({
70
+ "superblocks.npm.install.reify_seconds": 0.5,
71
+ });
72
+ });
73
+ // "npm unpacked nothing" is the signal that separates a metadata-only
74
+ // install from one that wrote tens of thousands of files, so a recorded zero
75
+ // is real data and must not be dropped as if it were missing.
76
+ it("emits a recorded zero rather than dropping it", async () => {
77
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
78
+ timers: { "reify:unpack": 0 },
79
+ });
80
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toEqual({
81
+ "superblocks.npm.install.unpack_seconds": 0,
82
+ });
83
+ });
84
+ // npm's log ids are fixed-width ISO timestamps, so the newest file is the
85
+ // last one alphabetically.
86
+ it("reads the newest file when older installs left files behind", async () => {
87
+ await writeTimingFile("2026-08-07T11_00_00_000Z", {
88
+ timers: { reify: 1000 },
89
+ });
90
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
91
+ timers: { reify: 2000 },
92
+ });
93
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toEqual({
94
+ "superblocks.npm.install.reify_seconds": 2,
95
+ });
96
+ });
97
+ // npm's `logs-max` pruning only covers its debug logs, so timing files would
98
+ // pile up on the app volume forever if nothing removed them.
99
+ it("removes the timing files it read so they cannot accumulate", async () => {
100
+ await writeTimingFile("2026-08-07T11_00_00_000Z", {
101
+ timers: { reify: 1000 },
102
+ });
103
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
104
+ timers: { reify: 2000 },
105
+ });
106
+ const debugLog = path.join(logsDir, "2026-08-07T12_00_00_000Z-debug-0.log");
107
+ await nodeFs.writeFile(debugLog, "npm debug output");
108
+ await consumeNpmInstallTimingAttributes(logsDir);
109
+ expect(await listTimingFiles()).toEqual([]);
110
+ // npm's debug log is a separate diagnostic that must survive.
111
+ await expect(nodeFs.readFile(debugLog, "utf8")).resolves.toBe("npm debug output");
112
+ });
113
+ it("returns null when the logs dir has no timing file", async () => {
114
+ await nodeFs.writeFile(path.join(logsDir, "2026-08-07T12_00_00_000Z-debug-0.log"), "npm debug output");
115
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toBeNull();
116
+ });
117
+ it("returns null when the logs dir does not exist", async () => {
118
+ expect(await consumeNpmInstallTimingAttributes(path.join(logsDir, "missing"))).toBeNull();
119
+ });
120
+ it("returns null for a file that is not JSON rather than throwing", async () => {
121
+ await writeTimingFile("2026-08-07T12_00_00_000Z", "not json at all");
122
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toBeNull();
123
+ });
124
+ it("returns null when the file carries no timers object", async () => {
125
+ await writeTimingFile("2026-08-07T12_00_00_000Z", { metadata: {} });
126
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toBeNull();
127
+ });
128
+ it("returns null when none of the whitelisted timers are present", async () => {
129
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
130
+ timers: { "npm:load": 12, "reifyNode:node_modules/lodash": 34 },
131
+ });
132
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toBeNull();
133
+ });
134
+ it("ignores timer values that are not finite numbers", async () => {
135
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
136
+ timers: { idealTree: "230", reify: null, "reify:unpack": 23200 },
137
+ });
138
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toEqual({
139
+ "superblocks.npm.install.unpack_seconds": 23.2,
140
+ });
141
+ });
142
+ it("clamps a negative duration so dashboards cannot be skewed", async () => {
143
+ await writeTimingFile("2026-08-07T12_00_00_000Z", {
144
+ timers: { reify: -500 },
145
+ });
146
+ expect(await consumeNpmInstallTimingAttributes(logsDir)).toEqual({
147
+ "superblocks.npm.install.reify_seconds": 0,
148
+ });
149
+ });
150
+ });
151
+ //# sourceMappingURL=npm-install-timing.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"npm-install-timing.test.mjs","sourceRoot":"","sources":["../../src/cli-replacement/npm-install-timing.test.mts"],"names":[],"mappings":"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"}
@@ -15,6 +15,13 @@ export interface Logger {
15
15
  debug: (...messages: unknown[]) => void;
16
16
  info: (...messages: unknown[]) => void;
17
17
  warn: (...messages: unknown[]) => void;
18
+ /**
19
+ * Emit an INFO-level log whose structured attributes are exported as OTel
20
+ * log attributes (Datadog facets) instead of being flattened into the
21
+ * message body. Plain `info()` joins every argument into one body string, so
22
+ * attributes passed to it are never queryable.
23
+ */
24
+ infoStructured?: (message: string, attributes: LogAttributes) => void;
18
25
  /**
19
26
  * Emit a WARN-level log whose structured attributes are exported as OTel log
20
27
  * attributes (Datadog facets) instead of being flattened into the message
@@ -1 +1 @@
1
- {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;;GAIG;AACH,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAE/D,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC;IACtE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;CACpD;AAyED,wBAAgB,SAAS,CACvB,cAAc,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,GAChD,MAAM,CAiBR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAgBtD"}
1
+ {"version":3,"file":"logging.d.ts","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"AA8DA,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED;;;;GAIG;AACH,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAE/D,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACxC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACvC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC;IACtE;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC;IACtE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,KAAK,IAAI,CAAC;CACpD;AAqFD,wBAAgB,SAAS,CACvB,cAAc,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,IAAI,GAChD,MAAM,CAmBR;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAgBtD"}
@@ -70,6 +70,18 @@ const logger = Object.freeze({
70
70
  });
71
71
  winstonLogger.warn(body);
72
72
  },
73
+ infoStructured: (message, attributes) => {
74
+ const body = sanitizeLogMessage(message);
75
+ // Same sanitize-then-emit contract as warnStructured below.
76
+ const safeAttributes = sanitizeLogObject(attributes);
77
+ getTracedLogger().emit({
78
+ severityNumber: SeverityNumber.INFO,
79
+ severityText: "INFO",
80
+ body,
81
+ attributes: safeAttributes,
82
+ });
83
+ winstonLogger.info(body);
84
+ },
73
85
  warnStructured: (message, attributes) => {
74
86
  const body = sanitizeLogMessage(message);
75
87
  // sanitizeLogObject strips secret-named keys and redacts secret values,
@@ -119,6 +131,7 @@ export function getLogger(loggerOverride) {
119
131
  // above, it forwards raw args to the supplied function and does NOT
120
132
  // sanitize or emit OTel attributes. Production callers use the default
121
133
  // logger (and the vite-plugin wrapLogger) which sanitize before emitting.
134
+ infoStructured: (message, attributes) => loggerOverride(message, attributes),
122
135
  warnStructured: (message, attributes) => loggerOverride(message, attributes),
123
136
  error: loggerOverride,
124
137
  };
@@ -1 +1 @@
1
- {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logging.js","sourceRoot":"","sources":["../../src/telemetry/logging.ts"],"names":[],"mappings":"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"}
@@ -115,6 +115,46 @@ describe("telemetry logger error sanitization", () => {
115
115
  expect(winstonErrorMock).toHaveBeenCalledWith("sanitized-message:plain failure");
116
116
  });
117
117
  });
118
+ describe("telemetry logger infoStructured", () => {
119
+ beforeEach(() => {
120
+ vi.clearAllMocks();
121
+ });
122
+ it("emits an INFO record carrying structured attributes (not flattened into the body)", () => {
123
+ const logger = getLogger();
124
+ logger.infoStructured?.("Package installation completed successfully", {
125
+ "superblocks.npm.install.added": 8,
126
+ "superblocks.npm.install.duration_seconds": 32.5,
127
+ "superblocks.npm.install.outcome": "success",
128
+ });
129
+ expect(emitMock).toHaveBeenCalledWith(expect.objectContaining({
130
+ severityText: "INFO",
131
+ body: "sanitized-message:Package installation completed successfully",
132
+ attributes: {
133
+ "superblocks.npm.install.added": 8,
134
+ "superblocks.npm.install.duration_seconds": 32.5,
135
+ "superblocks.npm.install.outcome": "sanitized-object:success",
136
+ },
137
+ }));
138
+ // Winston gets the body only (structured attributes go to OTel, not also
139
+ // to stdout log shippers as a duplicate).
140
+ expect(winstonLoggerMock.info).toHaveBeenCalledWith("sanitized-message:Package installation completed successfully");
141
+ });
142
+ it("strips secret-named attribute keys before emitting", () => {
143
+ const logger = getLogger();
144
+ logger.infoStructured?.("install done", {
145
+ registry: "https://npm.example.com",
146
+ token: "[REDACTED:token]",
147
+ });
148
+ expect(emitMock).toHaveBeenCalledWith(expect.objectContaining({
149
+ attributes: expect.objectContaining({
150
+ registry: "sanitized-object:https://npm.example.com",
151
+ }),
152
+ }));
153
+ expect(emitMock).not.toHaveBeenCalledWith(expect.objectContaining({
154
+ attributes: expect.objectContaining({ token: expect.anything() }),
155
+ }));
156
+ });
157
+ });
118
158
  describe("telemetry logger warnStructured", () => {
119
159
  beforeEach(() => {
120
160
  vi.clearAllMocks();
@@ -1 +1 @@
1
- {"version":3,"file":"logging.test.js","sourceRoot":"","sources":["../../src/telemetry/logging.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"logging.test.js","sourceRoot":"","sources":["../../src/telemetry/logging.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superblocksteam/sdk",
3
- "version": "2.0.149",
3
+ "version": "2.0.150-next.1",
4
4
  "description": "Superblocks JS SDK",
5
5
  "homepage": "https://www.superblocks.com",
6
6
  "license": "Superblocks Community Software License",
@@ -57,11 +57,11 @@
57
57
  "vite-tsconfig-paths": "^6.0.4",
58
58
  "winston": "^3.17.0",
59
59
  "yaml": "^2.7.1",
60
- "@superblocksteam/library-shared": "2.0.149",
61
- "@superblocksteam/shared": "0.9603.3",
62
- "@superblocksteam/telemetry": "2.0.149",
63
- "@superblocksteam/vite-plugin-file-sync": "2.0.149",
64
- "@superblocksteam/util": "2.0.149"
60
+ "@superblocksteam/library-shared": "2.0.150-next.1",
61
+ "@superblocksteam/shared": "0.9604.1",
62
+ "@superblocksteam/telemetry": "2.0.150-next.1",
63
+ "@superblocksteam/util": "2.0.150-next.1",
64
+ "@superblocksteam/vite-plugin-file-sync": "2.0.150-next.1"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@eslint/js": "^9.39.2",
@@ -45,8 +45,21 @@ interface ExecFailure {
45
45
  message?: string;
46
46
  }
47
47
 
48
- const REASON_TO_CATEGORY: Record<
48
+ /**
49
+ * `vulnerable_package` is produced only by Clark's install-time vulnerability
50
+ * gate, which runs in the ai-service AppShell — never by the parsers here,
51
+ * which read npm's own JSON/stderr. It is excluded rather than mapped so the
52
+ * registry/network reasons stay exhaustively checked, and folded to `unknown`
53
+ * at the boundary: the CLI has no distinct remediation for an index-blocked
54
+ * install, so a dedicated category would render the same generic guidance.
55
+ */
56
+ type ParsedBlockedReason = Exclude<
49
57
  NpmInstallBlockedReason,
58
+ "vulnerable_package"
59
+ >;
60
+
61
+ const REASON_TO_CATEGORY: Record<
62
+ ParsedBlockedReason,
50
63
  DependencyInstallError["category"]
51
64
  > = {
52
65
  not_in_registry: "not_in_registry",
@@ -55,6 +68,12 @@ const REASON_TO_CATEGORY: Record<
55
68
  tls_failed: "tls_failed",
56
69
  };
57
70
 
71
+ function isParsedBlockedReason(
72
+ reason: NpmInstallBlockedReason,
73
+ ): reason is ParsedBlockedReason {
74
+ return reason !== "vulnerable_package";
75
+ }
76
+
58
77
  const DEP_CONFLICT_CODES = /\b(ERESOLVE|ETARGET|EPEERINVALID)\b/;
59
78
 
60
79
  /** Best-effort: pull package specs out of an ERESOLVE/ETARGET `--json` detail. */
@@ -91,7 +110,9 @@ function fromBlocked(
91
110
  return {
92
111
  type: "dev-server/dependency-install",
93
112
  timestamp: new Date().toISOString(),
94
- category: REASON_TO_CATEGORY[b.reason],
113
+ category: isParsedBlockedReason(b.reason)
114
+ ? REASON_TO_CATEGORY[b.reason]
115
+ : "unknown",
95
116
  subreason: b.subreason,
96
117
  packages: b.packages.map((name) => ({ name })),
97
118
  registryHost: b.registryHost,
@@ -101,6 +122,15 @@ function fromBlocked(
101
122
  };
102
123
  }
103
124
 
125
+ /** Map a gate/registry `NpmInstallBlocked` into the startup degrade marker. */
126
+ export function initialInstallFailedFromBlocked(
127
+ blocked: NpmInstallBlocked,
128
+ ): InitialInstallFailed {
129
+ return new InitialInstallFailed(
130
+ fromBlocked(blocked, scrubSecrets(blocked.message)),
131
+ );
132
+ }
133
+
104
134
  /** Always returns a DependencyInstallError (never null). */
105
135
  export function classifyInitialInstallError(
106
136
  failure: ExecFailure,
@@ -196,10 +226,12 @@ export function classifyUpgradeError(
196
226
  if (blocked) {
197
227
  return {
198
228
  ...base,
199
- // `NpmInstallBlockedReason` is exactly the four registry/network reasons,
200
- // each of which is also a `DependencyUpgradeError` category, so the reason
201
- // doubles as the category directly (REASON_TO_CATEGORY is identity here).
202
- category: blocked.reason,
229
+ // Each parsed registry/network reason is also a `DependencyUpgradeError`
230
+ // category, so the reason doubles as the category directly
231
+ // (REASON_TO_CATEGORY is identity here).
232
+ category: isParsedBlockedReason(blocked.reason)
233
+ ? blocked.reason
234
+ : "unknown",
203
235
  npmErrorCode: blocked.npmErrorCode,
204
236
  hasAnyRegistryConfigured: blocked.hasAnyRegistryConfigured,
205
237
  };
@@ -5,6 +5,8 @@ import * as path from "node:path";
5
5
 
6
6
  import { beforeEach, describe, expect, it, vi, type Mock } from "vitest";
7
7
 
8
+ import type * as npmRegistry from "@superblocksteam/vite-plugin-file-sync/npm-registry";
9
+
8
10
  import { packageJsonSnapshot } from "./package-json-snapshot.mjs";
9
11
 
10
12
  const execMock = vi.fn();
@@ -62,6 +64,7 @@ const mockAiServiceState = vi.hoisted(() => ({
62
64
  npmRegistryClient: undefined as
63
65
  | { getConfig: () => Promise<Record<string, unknown>> }
64
66
  | undefined,
67
+ remediateDeclaredDependencies: vi.fn(async () => undefined),
65
68
  }));
66
69
 
67
70
  vi.mock("../telemetry/logging.js", () => ({
@@ -81,6 +84,8 @@ vi.mock("../telemetry/index.js", () => ({
81
84
  ) => fn({ end: vi.fn(), setStatus: vi.fn() }),
82
85
  ),
83
86
  }),
87
+ isCloudPrem: false,
88
+ shutdownTelemetry: vi.fn(async () => true),
84
89
  }));
85
90
 
86
91
  vi.mock("@opentelemetry/api", () => ({
@@ -117,6 +122,8 @@ vi.mock("@superblocksteam/vite-plugin-file-sync/ai-service", () => ({
117
122
  initialize = vi.fn(async () => undefined);
118
123
  notifyMigrationAppArtifactsReady = vi.fn();
119
124
  removeIntegrationCache = vi.fn(async () => undefined);
125
+ remediateDeclaredDependencies =
126
+ mockAiServiceState.remediateDeclaredDependencies;
120
127
  chatSessionStore = { invalidateCache: vi.fn() };
121
128
  // `dev.mts` reads this at startup for two paths: `syncHomeNpmrc`
122
129
  // (APPS-4231 home `~/.npmrc` writer) and the startup `installPackages`
@@ -131,24 +138,34 @@ vi.mock("@superblocksteam/vite-plugin-file-sync/ai-service", () => ({
131
138
  SnapshotManager: class {
132
139
  executePendingRestore = vi.fn(async () => false);
133
140
  },
141
+ hasEditLifecycleCapability: vi.fn(() => false),
134
142
  isSdkApiTemplate: vi.fn(() => false),
135
143
  stripResolvedFromLockfile: vi.fn(async () => undefined),
136
144
  }));
137
145
 
138
- vi.mock("@superblocksteam/vite-plugin-file-sync/npm-registry", () => ({
139
- shouldIgnoreInstallScripts: vi.fn(() => false),
140
- // Used by the dependency-install-classifier reachable from installPackages'
141
- // catch path (APPS-4450). Previously the only test that hit this codepath
142
- // (`logs a structured error when the background install fails`) didn't
143
- // assert classification, so the missing exports surfaced silently as a
144
- // ReferenceError instead of an InitialInstallFailed. The new
145
- // restart-vs-degrade test depends on installPackages re-throwing an actual
146
- // InitialInstallFailed marker, so stub all classifier-required exports.
147
- scrubSecrets: vi.fn((value: string) => value),
148
- parseNpmJsonDiagnostic: vi.fn(() => ""),
149
- parseNpmJsonError: vi.fn(() => null),
150
- classifyNpmExecStderr: vi.fn(() => null),
151
- }));
146
+ vi.mock("@superblocksteam/vite-plugin-file-sync/npm-registry", async () => {
147
+ // `NpmInstallBlocked` stays real: the startup remediation gate rejects with
148
+ // it and `dev.mts` routes it by `instanceof`, which only holds if the test
149
+ // and the module under test share one class.
150
+ const { NpmInstallBlocked } = await vi.importActual<typeof npmRegistry>(
151
+ "@superblocksteam/vite-plugin-file-sync/npm-registry",
152
+ );
153
+ return {
154
+ NpmInstallBlocked,
155
+ shouldIgnoreInstallScripts: vi.fn(() => false),
156
+ // Used by the dependency-install-classifier reachable from installPackages'
157
+ // catch path (APPS-4450). Previously the only test that hit this codepath
158
+ // (`logs a structured error when the background install fails`) didn't
159
+ // assert classification, so the missing exports surfaced silently as a
160
+ // ReferenceError instead of an InitialInstallFailed. The new
161
+ // restart-vs-degrade test depends on installPackages re-throwing an actual
162
+ // InitialInstallFailed marker, so stub all classifier-required exports.
163
+ scrubSecrets: vi.fn((value: string) => value),
164
+ parseNpmJsonDiagnostic: vi.fn(() => ""),
165
+ parseNpmJsonError: vi.fn(() => null),
166
+ classifyNpmExecStderr: vi.fn(() => null),
167
+ };
168
+ });
152
169
 
153
170
  vi.mock("@superblocksteam/vite-plugin-file-sync/git-service", () => ({
154
171
  createGitService: vi.fn(async () => undefined),
@@ -339,6 +356,10 @@ describe("dev startup after S3 workspace restore", () => {
339
356
  beforeEach(async () => {
340
357
  vi.clearAllMocks();
341
358
  mockAiServiceState.npmRegistryClient = undefined;
359
+ mockAiServiceState.remediateDeclaredDependencies.mockReset();
360
+ mockAiServiceState.remediateDeclaredDependencies.mockResolvedValue(
361
+ undefined,
362
+ );
342
363
  setupExecMock();
343
364
  mockCheckVersions.mockResolvedValue({
344
365
  cliUpdated: false,
@@ -346,6 +367,7 @@ describe("dev startup after S3 workspace restore", () => {
346
367
  });
347
368
 
348
369
  const { readPackage } = await import("read-pkg");
370
+ (readPackage as Mock).mockReset();
349
371
  (readPackage as Mock).mockResolvedValue({
350
372
  name: "test-app",
351
373
  dependencies: { "@superblocksteam/library": "1.0.0" },
@@ -357,6 +379,9 @@ describe("dev startup after S3 workspace restore", () => {
357
379
 
358
380
  await dev(buildDevOptions() as any);
359
381
 
382
+ expect(
383
+ mockAiServiceState.remediateDeclaredDependencies,
384
+ ).toHaveBeenCalledOnce();
360
385
  expect(execMock).not.toHaveBeenCalled();
361
386
  expect(mockLogger.info).toHaveBeenCalledWith(
362
387
  "Package install decision",
@@ -368,6 +393,65 @@ describe("dev startup after S3 workspace restore", () => {
368
393
  );
369
394
  });
370
395
 
396
+ it("installs packages when startup remediation changes package.json", async () => {
397
+ const { readPackage } = await import("read-pkg");
398
+ let packageJson = {
399
+ name: "test-app",
400
+ dependencies: { react: "18.2.0" },
401
+ };
402
+ (readPackage as Mock).mockImplementation(async () => packageJson);
403
+ mockAiServiceState.remediateDeclaredDependencies.mockImplementationOnce(
404
+ async () => {
405
+ packageJson = {
406
+ name: "test-app",
407
+ dependencies: { react: "18.3.1" },
408
+ };
409
+ },
410
+ );
411
+ const { dev } = await import("./dev.mjs");
412
+
413
+ await dev(buildDevOptions() as any);
414
+
415
+ expectInstallToHaveRun();
416
+ });
417
+
418
+ it("does not run the ungated install when startup remediation hard-blocks", async () => {
419
+ const { NpmInstallBlocked } =
420
+ await import("@superblocksteam/vite-plugin-file-sync/npm-registry");
421
+ mockAiServiceState.remediateDeclaredDependencies.mockRejectedValueOnce(
422
+ new NpmInstallBlocked({
423
+ findings: [
424
+ {
425
+ advisoryId: "MAL-2024-test",
426
+ kind: "malware",
427
+ package: "evil@1.0.0",
428
+ },
429
+ ],
430
+ packages: ["evil@1.0.0"],
431
+ reason: "vulnerable_package",
432
+ }),
433
+ );
434
+ const { readPackage } = await import("read-pkg");
435
+ (readPackage as Mock).mockResolvedValue({
436
+ name: "test-app",
437
+ dependencies: { evil: "1.0.0" },
438
+ });
439
+ const { dev } = await import("./dev.mjs");
440
+
441
+ await dev(
442
+ buildDevOptions({
443
+ forcePackageInstall: true,
444
+ }) as any,
445
+ );
446
+
447
+ expect(execMock).not.toHaveBeenCalled();
448
+ expect(mockCreateDevServer).toHaveBeenCalled();
449
+ expect(mockLogger.error).toHaveBeenCalledWith(
450
+ "[dev-server] initial dependency install failed; keeping dev server up",
451
+ expect.anything(),
452
+ );
453
+ });
454
+
371
455
  it("runs npm install when auto-upgrade only rewrites @superblocksteam/library", async () => {
372
456
  const { readPackage } = await import("read-pkg");
373
457
  (readPackage as Mock)
@@ -81,6 +81,8 @@ vi.mock("../telemetry/index.js", () => ({
81
81
  ) => fn({ end: vi.fn(), setStatus: vi.fn() }),
82
82
  ),
83
83
  }),
84
+ isCloudPrem: false,
85
+ shutdownTelemetry: vi.fn(async () => true),
84
86
  }));
85
87
 
86
88
  vi.mock("@opentelemetry/api", () => ({
@@ -117,6 +119,7 @@ vi.mock("@superblocksteam/vite-plugin-file-sync/ai-service", () => ({
117
119
  initialize = vi.fn(async () => undefined);
118
120
  notifyMigrationAppArtifactsReady = vi.fn();
119
121
  removeIntegrationCache = vi.fn(async () => undefined);
122
+ remediateDeclaredDependencies = vi.fn(async () => undefined);
120
123
  chatSessionStore = { invalidateCache: vi.fn() };
121
124
  getNpmRegistryClient = vi.fn(() => undefined);
122
125
  },
@@ -126,6 +129,7 @@ vi.mock("@superblocksteam/vite-plugin-file-sync/ai-service", () => ({
126
129
  SnapshotManager: class {
127
130
  executePendingRestore = vi.fn(async () => false);
128
131
  },
132
+ hasEditLifecycleCapability: vi.fn(() => false),
129
133
  isSdkApiTemplate: vi.fn(() => false),
130
134
  stripResolvedFromLockfile: vi.fn(async () => undefined),
131
135
  }));