@dzhechkov/harness-core 0.3.124 → 0.3.125

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.
package/src/sign.ts CHANGED
@@ -118,10 +118,18 @@ export function listPackFiles(root: string): string[] {
118
118
  const out: string[] = [];
119
119
  const walk = (dir: string, rel: string): void => {
120
120
  for (const e of readdirSync(dir, { withFileTypes: true })) {
121
+ // node_modules/.git are unsigned territory BY DESIGN (installed deps / VCS metadata — not pack
122
+ // content; npm tarballs ship neither). The SIGN and VERIFY walks MUST share these exclusions:
123
+ // an asymmetry here false-TAMPERs every pnpm workspace pack whose node_modules holds symlinks
124
+ // (found live arming task #36 — 10 of 23 skill packs flagged right after signing).
125
+ if (e.name === 'node_modules' || e.name === '.git') continue;
121
126
  if (e.name === MANIFEST_NAME || e.name === SBOM_NAME) continue;
122
127
  const abs = join(dir, e.name);
123
128
  const r = rel ? rel + '/' + e.name : e.name;
124
129
  if (e.isDirectory()) walk(abs, r);
130
+ // NOT else-isFile: a symlink (or other non-file) OUTSIDE the excluded dirs must stay VISIBLE to the
131
+ // verify sweep — it fails as "present but not signed" / "is a symlink" (R3-4: a smuggled symlink is a
132
+ // finding, not something to silently ignore). Only node_modules/.git are exempt territory.
125
133
  else out.push(r);
126
134
  }
127
135
  };
@@ -129,6 +137,27 @@ export function listPackFiles(root: string): string[] {
129
137
  return out.sort();
130
138
  }
131
139
 
140
+ /**
141
+ * The SIGN-side file list: same exclusions as {@link listPackFiles}, but REGULAR FILES ONLY — `dz sign`
142
+ * never signs a symlink (hashing one would follow it outside the pack). The verify sweep intentionally
143
+ * sees MORE than this (symlinks/specials outside node_modules), so a smuggled entry fails verification.
144
+ */
145
+ export function listSignablePackFiles(root: string): string[] {
146
+ const out: string[] = [];
147
+ const walk = (dir: string, rel: string): void => {
148
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
149
+ if (e.name === 'node_modules' || e.name === '.git') continue;
150
+ if (e.name === MANIFEST_NAME || e.name === SBOM_NAME) continue;
151
+ const abs = join(dir, e.name);
152
+ const r = rel ? rel + '/' + e.name : e.name;
153
+ if (e.isDirectory()) walk(abs, r);
154
+ else if (e.isFile()) out.push(r);
155
+ }
156
+ };
157
+ walk(root, '');
158
+ return out.sort();
159
+ }
160
+
132
161
  /**
133
162
  * The bytes that get signed (FR-7). Sorted by path, LF endings, no trailing whitespace, and no
134
163
  * dependence on JSON key order — a signature must not depend on how a serialiser felt that day.