@dzhechkov/harness-cli 0.7.0 → 0.7.2
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/.dz-manifest.json +18 -18
- package/README.md +14 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +75 -17
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/sbom.json +17 -17
- package/src/cli.ts +72 -10
package/.dz-manifest.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "README.md",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "ca0d42d114330fe7a2d0833abbf2fe90f3a60221e6cffeb3dc3b7edc7f818ec6"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "dist/bin.d.ts",
|
|
@@ -29,51 +29,51 @@
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"path": "dist/cli.d.ts",
|
|
32
|
-
"sha256": "
|
|
32
|
+
"sha256": "5aeeec8ab84e3922ce0c7b7ea711fd1cdff67b68e1ded0b66e920a907e6ac267"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "dist/cli.d.ts.map",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "f1cc2dc4a5de433a2d3cbd1e0567bf9c7bb5f3d04e90f72d10c54a9ccc5b00ae"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"path": "dist/cli.js",
|
|
40
|
-
"sha256": "
|
|
40
|
+
"sha256": "a1154eea12c861e092af90e33b5074d1219401f2194e2205f29ae9deb742834e"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"path": "dist/cli.js.map",
|
|
44
|
-
"sha256": "
|
|
44
|
+
"sha256": "a1fcb5f0f1524e7564bdec11bcf3b1c8d9d41ddb08ea5502dc72bbb3de439baa"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
"path": "dist/core-compat.d.ts",
|
|
48
|
-
"sha256": "
|
|
48
|
+
"sha256": "4ab523bc0a5f777fd66b8ed44c07a8b240a4cf2ce32da779a3916e6ddc53fa33"
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"path": "dist/core-compat.d.ts.map",
|
|
52
|
-
"sha256": "
|
|
52
|
+
"sha256": "e378022dd85db141f1d5b4d06d4791072b4caf6900b992dde5781d09b0559c35"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"path": "dist/core-compat.js",
|
|
56
|
-
"sha256": "
|
|
56
|
+
"sha256": "0c33ad728e7b3b25211d0b16d2803b9ca35d0aae6d3a570b57aa9b8377fcde1f"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"path": "dist/core-compat.js.map",
|
|
60
|
-
"sha256": "
|
|
60
|
+
"sha256": "342b0c716f6ac9f853e6fb9e10d2d3ae4c643f047becd200d6f8576a84674fb2"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
"path": "dist/index.d.ts",
|
|
64
|
-
"sha256": "
|
|
64
|
+
"sha256": "936596fd99f3767ca0119a02f07dfabf22b5b1c30e7007c63c3ff21cfced3836"
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
"path": "dist/index.d.ts.map",
|
|
68
|
-
"sha256": "
|
|
68
|
+
"sha256": "9096b181a0164cd59061bddcf9f4bee59123c1ab776e7a12da8b9808bd5b7936"
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
"path": "dist/index.js",
|
|
72
|
-
"sha256": "
|
|
72
|
+
"sha256": "8225f1de31f005c0d883fa9cf9b3a106f5e244ebbe5b4b3d2375c8127ba821f8"
|
|
73
73
|
},
|
|
74
74
|
{
|
|
75
75
|
"path": "dist/index.js.map",
|
|
76
|
-
"sha256": "
|
|
76
|
+
"sha256": "02b6b6f1b17a53d652a75555d185a20ea5d3e3110aa915ab228bf5521b0ce5fb"
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
"path": "keys/README.md",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
"path": "package.json",
|
|
88
|
-
"sha256": "
|
|
88
|
+
"sha256": "ec93467aada7c720f48874e6f24a5fb57bb77e8f5e01a450a29bc363b81f7b9a"
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
91
|
"path": "src/bin.ts",
|
|
@@ -93,17 +93,17 @@
|
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"path": "src/cli.ts",
|
|
96
|
-
"sha256": "
|
|
96
|
+
"sha256": "a31c2567ee0817e7a01eb034ac4ae8e9c44e18edea85ef722af2d32b4a2dabc4"
|
|
97
97
|
},
|
|
98
98
|
{
|
|
99
99
|
"path": "src/core-compat.ts",
|
|
100
|
-
"sha256": "
|
|
100
|
+
"sha256": "b6e2b8d73bb492afec8717f39ecfe3638c62b2f1d2479a9be43c493adebf89d6"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
"path": "src/index.ts",
|
|
104
|
-
"sha256": "
|
|
104
|
+
"sha256": "d4258f3b183d03047aa07399ae96bdb2b3af83f0005127a24a39f8932982bf78"
|
|
105
105
|
}
|
|
106
106
|
]
|
|
107
107
|
},
|
|
108
|
-
"signature": "
|
|
108
|
+
"signature": "VkraAQ/N624hP58XICkV/5LZKWo+DyLBBOFC5Yf7ySORtJ/y/+8RL6XKoyhQhngq6xm/KJgxMtnNwnQ9kvzCDw=="
|
|
109
109
|
}
|
package/README.md
CHANGED
|
@@ -1223,7 +1223,12 @@ release STOPPED, exit 1, best-effort `gh issue create` (no `gh`/network ⇒ loud
|
|
|
1223
1223
|
note: the issue body embeds first lines of failing output — pass `--no-issue` on public repos when
|
|
1224
1224
|
test/audit output may carry paths or environment details) → on
|
|
1225
1225
|
green: re-sign reminder (`dz sign …` — the publish signature gate is refuse-unsigned), then the ready
|
|
1226
|
-
`dz publish` command printed **without** `--yes`: live publish stays your explicit act.
|
|
1226
|
+
`dz publish` command printed **without** `--yes`: live publish stays your explicit act. The signature
|
|
1227
|
+
gate verifies the **artifact** — it packs each package and checks the tarball, not the working tree,
|
|
1228
|
+
because the two differ by construction (npm synthesises a `LICENSE`, the packer rewrites
|
|
1229
|
+
`package.json`). If the artifact cannot be packed at all, the gate **blocks and says so** rather than
|
|
1230
|
+
falling back to the tree: with no artifact, nothing was compared, and a pass would be a claim about
|
|
1231
|
+
an object that was never built. **When to use:**
|
|
1227
1232
|
before a multi-package npm release, or whenever a broken dist/bin must be impossible to ship; keep plain
|
|
1228
1233
|
`dz publish` for routine pushes. `dz publish` itself is byte-identical whether or not release exists.
|
|
1229
1234
|
|
|
@@ -4051,6 +4056,14 @@ npx @dzhechkov/p-replicator init
|
|
|
4051
4056
|
|
|
4052
4057
|
## Status
|
|
4053
4058
|
|
|
4059
|
+
`v0.7.2` — **a signature-only republish.** `0.7.0` shipped through `pnpm publish` rather than
|
|
4060
|
+
`dz publish`, so the re-signing step was skipped and 17 of 497 files in the published core did not
|
|
4061
|
+
match their signed hashes — the content was correct, the manifest was ten hours stale. Nothing in
|
|
4062
|
+
the shipped behaviour changes between `0.7.0` and `0.7.2`; the integrity check stops reporting these
|
|
4063
|
+
packages as tampered. The one code change is a TEST: the compat case that asserted the workspace
|
|
4064
|
+
core sits exactly on `MIN_CORE` is split into an integration half and a boundary half, so a patch
|
|
4065
|
+
bump of core no longer reddens it and `MIN_CORE` need not claim a version the CLI does not require.
|
|
4066
|
+
|
|
4054
4067
|
`v0.7.0` — `dz recall` and `dz vector status` now say what the RUN did rather than what the config
|
|
4055
4068
|
allows. **One breaking change for scripts:** `dz recall --semantic` exits **1** when no vector could
|
|
4056
4069
|
serve it — the code the README already documented for the sibling "no engine" case, now applied on
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAA0B,KAAK,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKtF,OAAO,EA4CL,iBAAiB,EAmBjB,KAAK,oBAAoB,EA8SzB,KAAK,YAAY,EAsClB,MAAM,yBAAyB,CAAC;AAyIjC,2EAA2E;AAC3E,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAC3C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED,yFAAyF;AACzF,MAAM,MAAM,iBAAiB,GAAG,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KACvD;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAk8E9E;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CA0BnF;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -4692,23 +4692,43 @@ function cmdPublish(options, flags, cwd, write) {
|
|
|
4692
4692
|
const manifestPath = join(pk.dir, MANIFEST_NAME);
|
|
4693
4693
|
const manifestPresent = existsSync(manifestPath);
|
|
4694
4694
|
let verifyOk = false;
|
|
4695
|
+
let artifactUnavailable = false;
|
|
4695
4696
|
if (trustRootPresent && manifestPresent) {
|
|
4697
|
+
// Verify the ARTIFACT, through the SAME extraction `dz sign` uses. This used to walk the
|
|
4698
|
+
// source TREE narrowed to a shipped-path list — a different object by construction, because
|
|
4699
|
+
// npm synthesises a LICENSE into the pack of a package whose tree has none and pnpm rewrites
|
|
4700
|
+
// package.json at pack time. So the gate named two failures that were both true about the
|
|
4701
|
+
// tree and both wrong about what ships, for EVERY package, and a fail-closed gate no input
|
|
4702
|
+
// can satisfy is a gate that gets routed around — it was: the 0.7.0 release went out through
|
|
4703
|
+
// `pnpm publish` and skipped re-signing (ADR-001, features/publish-gate-verifies-the-tarball).
|
|
4704
|
+
let cleanupGate = null;
|
|
4696
4705
|
try {
|
|
4697
4706
|
const signed = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
4698
|
-
let
|
|
4707
|
+
let extracted;
|
|
4699
4708
|
try {
|
|
4700
|
-
|
|
4709
|
+
extracted = extractPublishTarball(pk.dir);
|
|
4710
|
+
cleanupGate = extracted.cleanup;
|
|
4701
4711
|
}
|
|
4702
|
-
catch {
|
|
4703
|
-
|
|
4712
|
+
catch (err) {
|
|
4713
|
+
// Cross-family review (codex `gpt-5.6-sol`, 2026-08-22): falling back to the working
|
|
4714
|
+
// TREE here fails the gate OPEN. The gate's whole claim is "what ships matches the
|
|
4715
|
+
// signature"; with no artifact, nothing was compared, and reporting a pass would be a
|
|
4716
|
+
// claim about an object that was never built. Say why, and block.
|
|
4717
|
+
write(`dz publish: could not pack ${pk.name} (${err.message.split('\n')[0]}) — the artifact was never built, so its signature was not checked`);
|
|
4718
|
+
artifactUnavailable = true;
|
|
4704
4719
|
}
|
|
4705
|
-
verifyOk =
|
|
4720
|
+
verifyOk =
|
|
4721
|
+
extracted !== undefined &&
|
|
4722
|
+
verifyManifest(extracted.dir, signed, readFileSync(trustRoot, 'utf8')).ok;
|
|
4706
4723
|
}
|
|
4707
4724
|
catch {
|
|
4708
4725
|
verifyOk = false;
|
|
4709
4726
|
}
|
|
4727
|
+
finally {
|
|
4728
|
+
cleanupGate?.();
|
|
4729
|
+
}
|
|
4710
4730
|
}
|
|
4711
|
-
const decision = decidePublishGate({ trustRootPresent, manifestPresent, verifyOk, requireSigning });
|
|
4731
|
+
const decision = decidePublishGate({ trustRootPresent, manifestPresent, verifyOk, requireSigning, artifactUnavailable });
|
|
4712
4732
|
if (decision.action === 'block') {
|
|
4713
4733
|
write(`dz publish: BLOCKED ${pk.name} — ${decision.reason}`);
|
|
4714
4734
|
blocked++;
|
|
@@ -4738,23 +4758,34 @@ function cmdPublish(options, flags, cwd, write) {
|
|
|
4738
4758
|
// Verify the OUTCOME against the trust root a CONSUMER would use — an existing key may be the
|
|
4739
4759
|
// WRONG key, and enumerating that state is a losing game (round-1 review). The pack NAME travels
|
|
4740
4760
|
// with the verdict so a pass about a different artifact cannot be mistaken for this one.
|
|
4761
|
+
// The identity must be the one the PUBLISHER uses — the npm package name — or the check
|
|
4762
|
+
// compares two vocabularies and can never agree. It did: `basename(packDir)` is `memory`
|
|
4763
|
+
// where the publisher says `@dzhechkov/memory`, so every scoped package (all of them here)
|
|
4764
|
+
// was refused as "a pass about another artifact", and the release routed around the gate
|
|
4765
|
+
// instead. MEASURED 2026-08-22 by running `dz publish --filter memory --yes`.
|
|
4741
4766
|
const trustRoot = resolve(cwd, TRUST_ROOT_REL);
|
|
4767
|
+
const identity = packNpmName(packDir);
|
|
4768
|
+
const id = identity === undefined ? {} : { pack: identity };
|
|
4742
4769
|
if (!existsSync(trustRoot))
|
|
4743
|
-
return { ok: false, trustRootPresent: false,
|
|
4770
|
+
return { ok: false, trustRootPresent: false, ...id };
|
|
4771
|
+
// Verify the SAME OBJECT `reSign` hashed: the extracted tarball. Walking the source tree here
|
|
4772
|
+
// compares a manifest built from the artifact against files npm rewrites at pack time, so it
|
|
4773
|
+
// reported "does not verify — most likely the WRONG signing key" about a correctly signed pack
|
|
4774
|
+
// (MEASURED 2026-08-22, `dz publish --filter memory --yes`). That message sends the operator
|
|
4775
|
+
// hunting for a key problem that does not exist; the object was simply the wrong one.
|
|
4776
|
+
let cleanup = null;
|
|
4744
4777
|
try {
|
|
4745
4778
|
const signed = JSON.parse(readFileSync(join(packDir, MANIFEST_NAME), 'utf8'));
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
}
|
|
4750
|
-
catch {
|
|
4751
|
-
shipped = undefined;
|
|
4752
|
-
}
|
|
4753
|
-
const res = verifyManifest(packDir, signed, readFileSync(trustRoot, 'utf8'), shipped);
|
|
4754
|
-
return { ok: res.ok, trustRootPresent: true, pack: basename(packDir) };
|
|
4779
|
+
const extracted = extractPublishTarball(packDir);
|
|
4780
|
+
cleanup = extracted.cleanup;
|
|
4781
|
+
const res = verifyManifest(extracted.dir, signed, readFileSync(trustRoot, 'utf8'));
|
|
4782
|
+
return { ok: res.ok, trustRootPresent: true, ...id };
|
|
4755
4783
|
}
|
|
4756
4784
|
catch {
|
|
4757
|
-
return { ok: false, trustRootPresent: true,
|
|
4785
|
+
return { ok: false, trustRootPresent: true, ...id };
|
|
4786
|
+
}
|
|
4787
|
+
finally {
|
|
4788
|
+
cleanup?.();
|
|
4758
4789
|
}
|
|
4759
4790
|
},
|
|
4760
4791
|
reSign: (packDir, keyPath) => {
|
|
@@ -9053,6 +9084,19 @@ function scanOneReqeRoot(featuresDir, keyMatchesDir, out, addMalformed) {
|
|
|
9053
9084
|
* authority on what `files[]` ships; reimplementing its globbing would put a second, divergent answer
|
|
9054
9085
|
* next to the real one — which is the class of defect this whole change exists to remove.
|
|
9055
9086
|
*/
|
|
9087
|
+
/**
|
|
9088
|
+
* The npm name of a pack on disk — the identity a publisher, a registry and a consumer all use.
|
|
9089
|
+
* `undefined` when it cannot be read, so an unestablished identity is never asserted as a match.
|
|
9090
|
+
*/
|
|
9091
|
+
function packNpmName(packDir) {
|
|
9092
|
+
try {
|
|
9093
|
+
const name = JSON.parse(readFileSync(join(packDir, 'package.json'), 'utf8')).name;
|
|
9094
|
+
return typeof name === 'string' && name !== '' ? name : undefined;
|
|
9095
|
+
}
|
|
9096
|
+
catch {
|
|
9097
|
+
return undefined;
|
|
9098
|
+
}
|
|
9099
|
+
}
|
|
9056
9100
|
function npmPackedPaths(packDir) {
|
|
9057
9101
|
// `pnpm`, not `npm`: the PUBLISHER is `pnpm publish` (see `publishArgv`), and the two packers do not
|
|
9058
9102
|
// agree. MEASURED 2026-08-21 on `skills-news`: `npm pack` emits a 1051-byte package.json identical
|
|
@@ -9077,6 +9121,20 @@ function npmPackedPaths(packDir) {
|
|
|
9077
9121
|
*/
|
|
9078
9122
|
function extractPublishTarball(packDir) {
|
|
9079
9123
|
const tmp = mkdtempSync(join(tmpdir(), 'dz-sign-pack-'));
|
|
9124
|
+
try {
|
|
9125
|
+
return extractIntoTempDir(packDir, tmp);
|
|
9126
|
+
}
|
|
9127
|
+
catch (err) {
|
|
9128
|
+
// The caller never receives a cleanup for a throw, so the directory this function created must
|
|
9129
|
+
// be removed HERE or it leaks once per failed pack (cross-family review, 2026-08-22).
|
|
9130
|
+
try {
|
|
9131
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
9132
|
+
}
|
|
9133
|
+
catch { /* best-effort */ }
|
|
9134
|
+
throw err;
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
function extractIntoTempDir(packDir, tmp) {
|
|
9080
9138
|
const out = execFileSync('pnpm', ['pack', '--pack-destination', tmp, '--json'], {
|
|
9081
9139
|
cwd: packDir,
|
|
9082
9140
|
encoding: 'utf-8',
|