javi-forge 1.34.0 → 1.34.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.
@@ -27,6 +27,11 @@ export interface FakeFaults {
27
27
  writeRefuse?: (name: string, callIndex: number) => boolean;
28
28
  /** Refuse renameInDir when the destination base name matches. */
29
29
  renameRefuse?: (to: string) => boolean;
30
+ /**
31
+ * Refuse applyExactMode for a target (chmod fault). Lets a test drive the
32
+ * rollback's prior-mode restore into failure without touching the bytes.
33
+ */
34
+ applyModeRefuse?: (target: string) => boolean;
30
35
  /**
31
36
  * Refuse proveManagedContainer for a path on its Nth call (a foreign
32
37
  * add/delete-child ACE on a managed container we own — the win32 CREATE_PARENT_DIR
@@ -152,6 +152,8 @@ export function makeFakeSecureFs() {
152
152
  return ok();
153
153
  },
154
154
  async applyExactMode(target, mode) {
155
+ if (fake.faults.applyModeRefuse?.(target))
156
+ return unsafe(`applyMode ${target}`);
155
157
  const file = files.get(target);
156
158
  if (!file)
157
159
  return unsafe(`applyMode enoent ${target}`);
@@ -191,10 +191,12 @@ function settingsSignals(value, classification, currentAssetSha) {
191
191
  };
192
192
  }
193
193
  const REMEDIATION = {
194
- absent: "install the managed $ (Slice 3)",
195
- "released-outdated": "upgrade the managed $ (Slice 3)",
196
- "exact-legacy": "migrate the legacy $ (Slice 3)",
197
- "edited-managed": "repair the managed $ with --force (Slice 3)",
194
+ // User-facing remediation: name the exact command to run, never an internal
195
+ // SDD slice number (which means nothing outside this repo's planning docs).
196
+ absent: "install the managed $ with: javi-forge hooks install claude",
197
+ "released-outdated": "upgrade the managed $ with: javi-forge hooks install claude",
198
+ "exact-legacy": "migrate the legacy $ with: javi-forge hooks install claude",
199
+ "edited-managed": "repair the managed $ with: javi-forge hooks repair claude --force",
198
200
  foreign: "manually review the $",
199
201
  symlink: "manually review the $",
200
202
  "non-regular": "manually review the $",
@@ -286,7 +286,16 @@ export async function runTransaction(input) {
286
286
  errors.push(`STOP: cannot stage rollback for ${entry.path}`);
287
287
  return;
288
288
  }
289
- await secureFs.applyExactMode(path.join(entry.dir.path, rName), entry.prior.mode);
289
+ // Prior-mode restore is BEST-EFFORT (JD-B-003): a chmod miss fails
290
+ // toward MORE restrictive perms (the 0600 staging mode), so it is not
291
+ // a security regression and must not halt the rollback — restoring the
292
+ // prior BYTES matters more than the prior mode. Record an
293
+ // INFORMATIONAL note (never `STOP:`, which signals a halted rollback)
294
+ // and continue to the rename.
295
+ const remoded = await secureFs.applyExactMode(path.join(entry.dir.path, rName), entry.prior.mode);
296
+ if (!remoded.ok) {
297
+ errors.push(`note: restored ${entry.path}; prior-mode restore failed, verify permissions (${remoded.detail ?? remoded.refusal ?? "unknown"})`);
298
+ }
290
299
  const restored = await secureFs.renameInDir(entry.dir, rName, base);
291
300
  if (!restored.ok) {
292
301
  errors.push(`STOP: cannot restore ${entry.path}; prior payload staged at ${path.join(entry.dir.path, rName)} for manual recovery`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "javi-forge",
3
- "version": "1.34.0",
3
+ "version": "1.34.1",
4
4
  "description": "Project scaffolding and AI-ready CI bootstrap",
5
5
  "type": "module",
6
6
  "bin": {