@superblocksteam/sdk 2.0.123-next.0 → 2.0.124-next.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 (115) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/cli-replacement/automatic-upgrades.d.ts +37 -1
  3. package/dist/cli-replacement/automatic-upgrades.d.ts.map +1 -1
  4. package/dist/cli-replacement/automatic-upgrades.js +162 -10
  5. package/dist/cli-replacement/automatic-upgrades.js.map +1 -1
  6. package/dist/cli-replacement/automatic-upgrades.test.js +377 -8
  7. package/dist/cli-replacement/automatic-upgrades.test.js.map +1 -1
  8. package/dist/cli-replacement/dependency-install-classifier.d.mts +21 -0
  9. package/dist/cli-replacement/dependency-install-classifier.d.mts.map +1 -0
  10. package/dist/cli-replacement/dependency-install-classifier.mjs +83 -0
  11. package/dist/cli-replacement/dependency-install-classifier.mjs.map +1 -0
  12. package/dist/cli-replacement/dependency-install-classifier.test.d.mts +2 -0
  13. package/dist/cli-replacement/dependency-install-classifier.test.d.mts.map +1 -0
  14. package/dist/cli-replacement/dependency-install-classifier.test.mjs +51 -0
  15. package/dist/cli-replacement/dependency-install-classifier.test.mjs.map +1 -0
  16. package/dist/cli-replacement/dev-s3-restore.test.mjs +170 -14
  17. package/dist/cli-replacement/dev-s3-restore.test.mjs.map +1 -1
  18. package/dist/cli-replacement/dev-startup-git-before-dbfs-order.test.mjs +33 -2
  19. package/dist/cli-replacement/dev-startup-git-before-dbfs-order.test.mjs.map +1 -1
  20. package/dist/cli-replacement/dev-token-priming.test.d.mts +31 -0
  21. package/dist/cli-replacement/dev-token-priming.test.d.mts.map +1 -0
  22. package/dist/cli-replacement/dev-token-priming.test.mjs +87 -0
  23. package/dist/cli-replacement/dev-token-priming.test.mjs.map +1 -0
  24. package/dist/cli-replacement/dev.d.mts +36 -0
  25. package/dist/cli-replacement/dev.d.mts.map +1 -1
  26. package/dist/cli-replacement/dev.interception.test.d.mts +2 -0
  27. package/dist/cli-replacement/dev.interception.test.d.mts.map +1 -0
  28. package/dist/cli-replacement/dev.interception.test.mjs +68 -0
  29. package/dist/cli-replacement/dev.interception.test.mjs.map +1 -0
  30. package/dist/cli-replacement/dev.mjs +396 -62
  31. package/dist/cli-replacement/dev.mjs.map +1 -1
  32. package/dist/cli-replacement/home-npmrc.d.mts +180 -0
  33. package/dist/cli-replacement/home-npmrc.d.mts.map +1 -0
  34. package/dist/cli-replacement/home-npmrc.mjs +283 -0
  35. package/dist/cli-replacement/home-npmrc.mjs.map +1 -0
  36. package/dist/cli-replacement/home-npmrc.test.d.mts +10 -0
  37. package/dist/cli-replacement/home-npmrc.test.d.mts.map +1 -0
  38. package/dist/cli-replacement/home-npmrc.test.mjs +582 -0
  39. package/dist/cli-replacement/home-npmrc.test.mjs.map +1 -0
  40. package/dist/cli-replacement/install-packages.classify.test.d.mts +2 -0
  41. package/dist/cli-replacement/install-packages.classify.test.d.mts.map +1 -0
  42. package/dist/cli-replacement/install-packages.classify.test.mjs +125 -0
  43. package/dist/cli-replacement/install-packages.classify.test.mjs.map +1 -0
  44. package/dist/cli-replacement/install-packages.npm-registry.test.d.mts +2 -0
  45. package/dist/cli-replacement/install-packages.npm-registry.test.d.mts.map +1 -0
  46. package/dist/cli-replacement/install-packages.npm-registry.test.mjs +260 -0
  47. package/dist/cli-replacement/install-packages.npm-registry.test.mjs.map +1 -0
  48. package/dist/cli-replacement/post-upgrade-lockfile-strip.d.mts +58 -0
  49. package/dist/cli-replacement/post-upgrade-lockfile-strip.d.mts.map +1 -0
  50. package/dist/cli-replacement/post-upgrade-lockfile-strip.mjs +224 -0
  51. package/dist/cli-replacement/post-upgrade-lockfile-strip.mjs.map +1 -0
  52. package/dist/cli-replacement/post-upgrade-lockfile-strip.test.d.mts +11 -0
  53. package/dist/cli-replacement/post-upgrade-lockfile-strip.test.d.mts.map +1 -0
  54. package/dist/cli-replacement/post-upgrade-lockfile-strip.test.mjs +317 -0
  55. package/dist/cli-replacement/post-upgrade-lockfile-strip.test.mjs.map +1 -0
  56. package/dist/cli-replacement/userconfig-env.integration.test.d.mts +26 -0
  57. package/dist/cli-replacement/userconfig-env.integration.test.d.mts.map +1 -0
  58. package/dist/cli-replacement/userconfig-env.integration.test.mjs +148 -0
  59. package/dist/cli-replacement/userconfig-env.integration.test.mjs.map +1 -0
  60. package/dist/dev-utils/dev-server-metrics.d.mts +25 -0
  61. package/dist/dev-utils/dev-server-metrics.d.mts.map +1 -1
  62. package/dist/dev-utils/dev-server-metrics.mjs +84 -0
  63. package/dist/dev-utils/dev-server-metrics.mjs.map +1 -1
  64. package/dist/dev-utils/dev-server-metrics.test.d.mts +2 -0
  65. package/dist/dev-utils/dev-server-metrics.test.d.mts.map +1 -0
  66. package/dist/dev-utils/dev-server-metrics.test.mjs +26 -0
  67. package/dist/dev-utils/dev-server-metrics.test.mjs.map +1 -0
  68. package/dist/dev-utils/dev-server.d.mts +23 -1
  69. package/dist/dev-utils/dev-server.d.mts.map +1 -1
  70. package/dist/dev-utils/dev-server.mjs +21 -9
  71. package/dist/dev-utils/dev-server.mjs.map +1 -1
  72. package/dist/dev-utils/dev-server.status.test.d.mts +2 -0
  73. package/dist/dev-utils/dev-server.status.test.d.mts.map +1 -0
  74. package/dist/dev-utils/dev-server.status.test.mjs +41 -0
  75. package/dist/dev-utils/dev-server.status.test.mjs.map +1 -0
  76. package/dist/dev-utils/token-manager.d.ts +31 -0
  77. package/dist/dev-utils/token-manager.d.ts.map +1 -1
  78. package/dist/dev-utils/token-manager.js +34 -0
  79. package/dist/dev-utils/token-manager.js.map +1 -1
  80. package/dist/telemetry/local-obs.js +1 -1
  81. package/dist/telemetry/local-obs.js.map +1 -1
  82. package/dist/telemetry/util.js +1 -1
  83. package/dist/types/scoped-jwt-token-payload.d.ts +1 -0
  84. package/dist/types/scoped-jwt-token-payload.d.ts.map +1 -1
  85. package/dist/version-control.d.mts.map +1 -1
  86. package/dist/version-control.mjs +6 -7
  87. package/dist/version-control.mjs.map +1 -1
  88. package/package.json +12 -12
  89. package/src/cli-replacement/automatic-upgrades.test.ts +530 -8
  90. package/src/cli-replacement/automatic-upgrades.ts +179 -7
  91. package/src/cli-replacement/dependency-install-classifier.mts +118 -0
  92. package/src/cli-replacement/dependency-install-classifier.test.mts +72 -0
  93. package/src/cli-replacement/dev-s3-restore.test.mts +210 -14
  94. package/src/cli-replacement/dev-startup-git-before-dbfs-order.test.mts +35 -2
  95. package/src/cli-replacement/dev-token-priming.test.mts +103 -0
  96. package/src/cli-replacement/dev.interception.test.mts +80 -0
  97. package/src/cli-replacement/dev.mts +495 -92
  98. package/src/cli-replacement/home-npmrc.mts +409 -0
  99. package/src/cli-replacement/home-npmrc.test.mts +757 -0
  100. package/src/cli-replacement/install-packages.classify.test.mts +168 -0
  101. package/src/cli-replacement/install-packages.npm-registry.test.mts +345 -0
  102. package/src/cli-replacement/post-upgrade-lockfile-strip.mts +296 -0
  103. package/src/cli-replacement/post-upgrade-lockfile-strip.test.mts +482 -0
  104. package/src/cli-replacement/userconfig-env.integration.test.mts +189 -0
  105. package/src/dev-utils/dev-server-metrics.mts +96 -0
  106. package/src/dev-utils/dev-server-metrics.test.mts +38 -0
  107. package/src/dev-utils/dev-server.mts +48 -8
  108. package/src/dev-utils/dev-server.status.test.mts +58 -0
  109. package/src/dev-utils/token-manager.ts +36 -0
  110. package/src/telemetry/local-obs.ts +1 -1
  111. package/src/telemetry/util.ts +1 -1
  112. package/src/types/scoped-jwt-token-payload.ts +1 -0
  113. package/src/version-control.mts +8 -6
  114. package/tsconfig.tsbuildinfo +1 -1
  115. package/.turbo/turbo-publish-package.log +0 -0
@@ -0,0 +1,283 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import * as os from "node:os";
3
+ import * as path from "node:path";
4
+ import { PRESERVE_NPMRC_SCOPES, restoreInitialNpmrc, snapshotInitialNpmrc, writeNpmrc, } from "@superblocksteam/vite-plugin-file-sync/npm-registry";
5
+ import { getErrorMeta } from "../telemetry/logging.js";
6
+ /**
7
+ * File mode applied to the userconfig after every write. `0o400` (owner
8
+ * read, no write) strips the owner write bit so any `npm config set` or
9
+ * stray write that opens the file `O_WRONLY` fails loudly instead of
10
+ * silently retargeting the configured registry. The atomic rename inside
11
+ * `writeNpmrc` is governed by parent-dir perms — not the target's mode —
12
+ * so this writer can still re-sync the file on subsequent config changes.
13
+ * The stricter mode is a speed bump, not a security boundary: the CLI
14
+ * user can always `chmod +w` first.
15
+ */
16
+ export const HOME_NPMRC_MODE = 0o400;
17
+ const LOG_PREFIX = "[home-npmrc]";
18
+ /**
19
+ * Most recent `snapshotInitialNpmrc` outcome, keyed by userconfig target
20
+ * path. `syncHomeNpmrc` runs once per `NpmRegistryClient` cache refresh,
21
+ * so the snapshot (taken on a `configured`/`stale` resolve) and the
22
+ * destructive restore (on a later `not-configured` resolve) happen on
23
+ * SEPARATE invocations within one pod's lifetime. We remember the outcome
24
+ * across invocations so the not-configured branch can refuse to unlink the
25
+ * userconfig when the snapshot is known to have FAILED — a silent EXDEV
26
+ * (target and backup on different filesystems) leaves a real baked-in file
27
+ * with no backup, and unlinking it would fail the customer's install open
28
+ * to public npm (APPS-4428).
29
+ *
30
+ * Keyed by path so the test suite's per-test tmpdir `homeDir`s stay
31
+ * isolated. Absent (never snapshotted this process — e.g. not-configured
32
+ * from boot, or the policy-only path that deliberately skips the snapshot)
33
+ * preserves the original APPS-4328 behaviour: a missing backup is "nothing
34
+ * to preserve", so the unlink is allowed.
35
+ */
36
+ const lastSnapshotOutcomeByPath = new Map();
37
+ /**
38
+ * Resolves the Superblocks-owned npm userconfig path. Centralised so the
39
+ * image-build and CLI auto-upgrade `--userconfig=` plumbing and the
40
+ * runtime writer all agree on the same location. The file lives inside a
41
+ * hidden directory, so it is named `npmrc` (without a leading dot) by
42
+ * convention; the directory itself carries the visibility bit. `homeDir`
43
+ * defaults to `os.homedir()`; tests override it.
44
+ */
45
+ export function superblocksNpmrcPath(homeDir) {
46
+ return path.join(homeDir ?? os.homedir(), ".superblocks", "npmrc");
47
+ }
48
+ /**
49
+ * Resolves the directory npm should write its per-run debug logs to during
50
+ * Superblocks-spawned installs in the live-edit pod. Unlike
51
+ * `superblocksNpmrcPath` (home-based), this is rooted at the application
52
+ * working directory — `<app>/.superblocks/logs` — so each app's install
53
+ * logs are co-located with the app and collectable from a predictable
54
+ * place. Wired into the subprocess env as `NPM_CONFIG_LOGS_DIR` via
55
+ * `buildInstallEnv`; npm creates the directory if it does not exist.
56
+ */
57
+ export function superblocksLogsPath(appDir) {
58
+ return path.join(appDir, ".superblocks", "logs");
59
+ }
60
+ /**
61
+ * Resolves the on-disk backup path for the Superblocks-owned npm
62
+ * userconfig. Symmetric with `superblocksNpmrcPath`: lives next to the
63
+ * userconfig under `~/.superblocks/`. `syncHomeNpmrc` hardlinks the
64
+ * image-baked userconfig to this path on the first `configured` resolve
65
+ * so a later transition to `not-configured` has a baseline to restore
66
+ * from (APPS-4328) — mirroring the project-`.npmrc` capture/restore added
67
+ * in APPS-4320.
68
+ *
69
+ * The leading-dot filename mirrors the project-side `NPMRC_DEFAULT_FILENAME`
70
+ * convention even though the live userconfig is `npmrc` (no dot). The dot
71
+ * here is a convention-only marker that this file is the backup, not the
72
+ * active userconfig.
73
+ */
74
+ export function superblocksNpmrcBackupPath(homeDir) {
75
+ return path.join(homeDir ?? os.homedir(), ".superblocks", "npmrc.default");
76
+ }
77
+ /**
78
+ * Materialises `~/.superblocks/npmrc` from the server-fetched per-org
79
+ * npm registry config. Designed to run at dev-server CLI startup, after
80
+ * the `NpmRegistryClient` is wired but BEFORE the global Superblocks CLI
81
+ * auto-upgrade: with the file in place and the auto-upgrade invoking
82
+ * npm with `NPM_CONFIG_USERCONFIG=~/.superblocks/npmrc`, the
83
+ * `npm install -g @superblocksteam/cli@…` invocation resolves through
84
+ * the customer's private registry rather than `registry.npmjs.org`.
85
+ *
86
+ * Behaviour:
87
+ *
88
+ * - `client.getConfig()` resolves `configured` (or `stale`): snapshot
89
+ * the image-default userconfig to `~/.superblocks/npmrc.default`
90
+ * (once per pod boot via `link(2)`), then write
91
+ * `~/.superblocks/npmrc` atomically with mode `0o400`. The snapshot
92
+ * captures whatever the image baked (EE GHPR scope + token, or a
93
+ * no-file baseline on a fresh developer laptop) so the
94
+ * `not-configured` branch below has a baseline to restore from. The
95
+ * parent dir is `mkdir -p`'d first so a fresh `$HOME` on a
96
+ * developer's laptop is handled the same as a pod where the image
97
+ * already pre-creates `/home/node/.superblocks/`. If the snapshot
98
+ * attempt FAILS against a real baked file (e.g. EXDEV), we fail
99
+ * closed and SKIP the rewrite: see `skipped-snapshot-failed` in
100
+ * `SyncHomeNpmrcOutcome` for why (APPS-4428).
101
+ *
102
+ * - `client.getConfig()` resolves `not-configured`: restore the
103
+ * image-default userconfig from the `~/.superblocks/npmrc.default`
104
+ * backup captured on a prior `configured` boot. When no backup
105
+ * exists (cold boot where the org was deconfigured before the first
106
+ * `configured` resolve), the userconfig is unlinked entirely so a
107
+ * long-lived Superblocks-spawned npm/pnpm process cannot silently
108
+ * inherit a previously-configured org's registry/token. Closes the
109
+ * stale-userconfig hole flagged on PR #19621 (APPS-4328). One
110
+ * exception: if this process already SAW a snapshot attempt FAIL for
111
+ * this path, the configured branch above will have left the baked
112
+ * userconfig in place (no managed rewrite happened), so unlinking
113
+ * here would delete the baked baseline. Withhold the unlink (APPS-4428).
114
+ *
115
+ * - `client.getConfig()` resolves `unreachable`: cold cache + the
116
+ * registry server is down (or JWT refresh failed). Leave the file
117
+ * alone — the fail-closed gate in the CLI auto-upgrade is the
118
+ * backstop if the upgrade reaches a public registry.
119
+ *
120
+ * - Any throw (fs error, etc.): log + return `outcome: "error"`. We
121
+ * must not crash dev-server startup on a best-effort step.
122
+ *
123
+ * Idempotent for a given resolved config — safe to invoke on every
124
+ * `NpmRegistryClient` cache refresh as well as on startup.
125
+ */
126
+ export async function syncHomeNpmrc(deps) {
127
+ const targetPath = superblocksNpmrcPath(deps.homeDir);
128
+ const backupPath = superblocksNpmrcBackupPath(deps.homeDir);
129
+ let result;
130
+ try {
131
+ result = await deps.npmRegistryClient.getConfig();
132
+ }
133
+ catch (error) {
134
+ // `NpmRegistryClient` only throws for the deliberate-denial branches
135
+ // (RBAC 403, malformed request 400, double-401). All three signal a
136
+ // structurally broken session — surface the warn but keep the
137
+ // userconfig as-is rather than forging a "default" file that masks
138
+ // the real failure.
139
+ deps.logger.warn(`${LOG_PREFIX} client.getConfig() failed; ~/.superblocks/npmrc left unchanged`, { path: targetPath, ...getErrorMeta(error) });
140
+ return { outcome: "error", path: targetPath };
141
+ }
142
+ if (result.source === "unreachable") {
143
+ deps.logger.warn(`${LOG_PREFIX} registry server unreachable with no cached config; ~/.superblocks/npmrc left unchanged`, { path: targetPath });
144
+ return { outcome: "skipped-unreachable", path: targetPath };
145
+ }
146
+ if (!result.config.configured) {
147
+ if (result.config.allowInstallScripts === false) {
148
+ // Org policy disallows install scripts even without registry rows.
149
+ // Write a policy-only userconfig with `ignore-scripts=true`.
150
+ //
151
+ // IMPORTANT: we deliberately skip `snapshotInitialNpmrc` here.
152
+ // On a repeated sync the target already contains our own policy
153
+ // file; snapshotting it would poison the backup with policy content
154
+ // instead of the image-baked baseline, so a later flip to
155
+ // allowInstallScripts=true could never restore the original.
156
+ try {
157
+ await mkdir(path.dirname(targetPath), { recursive: true });
158
+ await writeNpmrc(targetPath, result.config, {
159
+ preserveScopeLines: PRESERVE_NPMRC_SCOPES,
160
+ mode: HOME_NPMRC_MODE,
161
+ });
162
+ deps.logger.info(`${LOG_PREFIX} wrote policy-only userconfig (ignore-scripts)`, { path: targetPath });
163
+ return { outcome: "written", path: targetPath };
164
+ }
165
+ catch (error) {
166
+ deps.logger.warn(`${LOG_PREFIX} policy-only write failed`, {
167
+ path: targetPath,
168
+ ...getErrorMeta(error),
169
+ });
170
+ return { outcome: "error", path: targetPath };
171
+ }
172
+ }
173
+ else {
174
+ // Restore the image-default userconfig from the backup captured on a
175
+ // prior configured boot. When the backup is absent (the org was never
176
+ // configured on this pod, OR the pod was rewritten before this
177
+ // commit landed) the userconfig is unlinked instead — leaving a
178
+ // stale Superblocks-owned userconfig in place would silently pin
179
+ // npm/pnpm at a previous org's registry/token, the exact hole
180
+ // gpoulios-sb flagged on PR #19621.
181
+ //
182
+ // EXCEPT when this process's most recent snapshot attempt FAILED:
183
+ // the snapshot ran against a real baked-in userconfig but `link(2)`
184
+ // failed silently (e.g. EXDEV across filesystems), so no backup
185
+ // exists for an unrelated reason. Unlinking here would delete a file
186
+ // that SHOULD have been preserved and restored. We can't distinguish
187
+ // that from "no backup" inside `restoreInitialNpmrc`, so we withhold
188
+ // the unlink option and leave the userconfig in place (APPS-4428).
189
+ // Absent state (never snapshotted: not-configured from boot, or the
190
+ // policy-only path) keeps the original APPS-4328 unlink behaviour.
191
+ const snapshotFailed = lastSnapshotOutcomeByPath.get(targetPath) === "failed";
192
+ if (snapshotFailed) {
193
+ deps.logger.warn(`${LOG_PREFIX} registry not configured but the userconfig snapshot failed earlier; leaving the userconfig in place rather than risk deleting an un-backed-up baseline`, { path: targetPath });
194
+ }
195
+ // Best-effort: `restoreInitialNpmrc` swallows fs errors as
196
+ // warn-and-no-op so dev-server startup never crashes on cleanup.
197
+ try {
198
+ await restoreInitialNpmrc(targetPath, backupPath, {
199
+ unlinkTargetWhenBackupMissing: !snapshotFailed,
200
+ });
201
+ // On the `snapshotFailed` branch we passed
202
+ // `unlinkTargetWhenBackupMissing: false`, so `restoreInitialNpmrc`
203
+ // intentionally no-ops (leaves the userconfig in place). Return
204
+ // the dedicated `skipped-snapshot-failed` outcome rather than
205
+ // `restored-not-configured` — nothing was restored or removed,
206
+ // and conflating the two would mislead telemetry/dashboards into
207
+ // thinking the baseline rollback ran when it didn't. The warn
208
+ // above already describes the decision; an info log here would
209
+ // contradict it during incident investigation.
210
+ if (snapshotFailed) {
211
+ return { outcome: "skipped-snapshot-failed", path: targetPath };
212
+ }
213
+ deps.logger.info(`${LOG_PREFIX} registry not configured; restored image-default userconfig (or removed Superblocks-owned file when no backup exists)`, { path: targetPath });
214
+ return { outcome: "restored-not-configured", path: targetPath };
215
+ }
216
+ catch (error) {
217
+ deps.logger.warn(`${LOG_PREFIX} restore failed`, {
218
+ path: targetPath,
219
+ ...getErrorMeta(error),
220
+ });
221
+ return { outcome: "error", path: targetPath };
222
+ }
223
+ }
224
+ }
225
+ try {
226
+ // `mkdir -p` so a fresh `$HOME` (developer laptop, unprovisioned
227
+ // sandbox) doesn't ENOENT inside `writeNpmrc`'s atomic-rename. Pod
228
+ // images already create `/home/node/.superblocks/` at build time, so
229
+ // this is a no-op there.
230
+ await mkdir(path.dirname(targetPath), { recursive: true });
231
+ // Snapshot the image-default userconfig BEFORE the first rewrite so
232
+ // the not-configured branch above has a restore baseline. Hardlink
233
+ // is atomic + idempotent: only one of N concurrent callers wins
234
+ // (kernel-serialised), and a subsequent `writeNpmrc` tmp+rename
235
+ // gives the userconfig a fresh inode while the backup inode (the
236
+ // baked content) stays alive. EEXIST after the first capture is
237
+ // expected and not a warning.
238
+ //
239
+ // Remember the outcome so a later `not-configured` resolve (a
240
+ // separate `syncHomeNpmrc` invocation) can tell whether a usable
241
+ // backup actually exists before it asks `restoreInitialNpmrc` to
242
+ // unlink the userconfig. A silent `failed` here (e.g. EXDEV) must
243
+ // NOT lead the not-configured branch to delete a real baked file
244
+ // that has no backup (APPS-4428).
245
+ const snapshotOutcome = await snapshotInitialNpmrc(targetPath, backupPath);
246
+ lastSnapshotOutcomeByPath.set(targetPath, snapshotOutcome);
247
+ // FAIL CLOSED on snapshot failure (APPS-4428, gpoulios-sb review of
248
+ // PR #19690). When a real baked file existed but the hardlink to
249
+ // `backupPath` failed (only `"failed"` reports this — `"no-source"`
250
+ // means there was nothing to snapshot in the first place), we have
251
+ // no way to undo a managed rewrite later: a `not-configured`
252
+ // transition could not restore the baseline (no backup) and could
253
+ // not safely unlink the file (it would delete the baseline). The
254
+ // earlier guard only addressed the unlink side and let the rewrite
255
+ // happen anyway, which still left stale private-registry config and
256
+ // auth on disk after deconfigure. The only safe choice is to leave
257
+ // the baked userconfig alone here — the install path falls back to
258
+ // whatever the image baked (typically EE GHPR), which is the
259
+ // pre-private-registry default behaviour.
260
+ if (snapshotOutcome === "failed") {
261
+ deps.logger.warn(`${LOG_PREFIX} userconfig snapshot failed; refusing to overwrite the baked userconfig with managed private-registry content (no restore baseline exists)`, { path: targetPath, source: result.source });
262
+ return { outcome: "skipped-snapshot-failed", path: targetPath };
263
+ }
264
+ await writeNpmrc(targetPath, result.config, {
265
+ preserveScopeLines: PRESERVE_NPMRC_SCOPES,
266
+ mode: HOME_NPMRC_MODE,
267
+ });
268
+ deps.logger.info(`${LOG_PREFIX} wrote ~/.superblocks/npmrc`, {
269
+ path: targetPath,
270
+ source: result.source,
271
+ mode: HOME_NPMRC_MODE.toString(8).padStart(4, "0"),
272
+ });
273
+ return { outcome: "written", path: targetPath, source: result.source };
274
+ }
275
+ catch (error) {
276
+ deps.logger.warn(`${LOG_PREFIX} write failed`, {
277
+ path: targetPath,
278
+ ...getErrorMeta(error),
279
+ });
280
+ return { outcome: "error", path: targetPath };
281
+ }
282
+ }
283
+ //# sourceMappingURL=home-npmrc.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home-npmrc.mjs","sourceRoot":"","sources":["../../src/cli-replacement/home-npmrc.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Tests for the CLI-startup `~/.superblocks/npmrc` writer.
3
+ *
4
+ * Strategy: stand up a tmpdir as a fake `$HOME` and a fake
5
+ * `NpmRegistryClient` whose `getConfig()` returns the canned response
6
+ * under test. Asserts cover the four state transitions plus the 0o400
7
+ * mode bit.
8
+ */
9
+ export {};
10
+ //# sourceMappingURL=home-npmrc.test.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home-npmrc.test.d.mts","sourceRoot":"","sources":["../../src/cli-replacement/home-npmrc.test.mts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}