@dk/hipp 0.1.35 → 0.1.37
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/README.md +10 -10
- package/hipp.js +45 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,10 +140,10 @@ npx @dk/hipp -- --access public --tag beta
|
|
|
140
140
|
HIPP provides out-of-band verification to prove package integrity:
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
|
-
npx @dk/hipp verify # auto-detect: local hipp repo → published version, else @dk/hipp
|
|
144
|
-
npx @dk/hipp verify --self # always verifies @dk/hipp itself
|
|
145
|
-
npx @dk/hipp verify @scope/package # verifies latest of a package
|
|
146
|
-
npx @dk/hipp verify @scope/package@1.0.0 # verifies specific version
|
|
143
|
+
npx @dk/hipp --verify # auto-detect: local hipp repo → published version, else @dk/hipp
|
|
144
|
+
npx @dk/hipp --verify --self # always verifies @dk/hipp itself
|
|
145
|
+
npx @dk/hipp --verify @scope/package # verifies latest of a package
|
|
146
|
+
npx @dk/hipp --verify @scope/package@1.0.0 # verifies specific version
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
### How Verification Works
|
|
@@ -273,21 +273,21 @@ PERFORMANCE OF THIS SOFTWARE.
|
|
|
273
273
|
Verify this package with [@dk/hipp](https://www.npmjs.com/package/@dk/hipp):
|
|
274
274
|
|
|
275
275
|
```bash
|
|
276
|
-
npx @dk/hipp verify @dk/hipp@0.1.
|
|
276
|
+
npx @dk/hipp --verify @dk/hipp@0.1.37
|
|
277
277
|
```
|
|
278
278
|
|
|
279
279
|
```json
|
|
280
280
|
{
|
|
281
281
|
"origin": "git@github.com:dmytri/hipp.git",
|
|
282
|
-
"tag": "v0.1.
|
|
283
|
-
"revision": "
|
|
284
|
-
"hash": "
|
|
285
|
-
"signature": "
|
|
282
|
+
"tag": "v0.1.37",
|
|
283
|
+
"revision": "3efc2c67bcb1e75b9fb3c44a2e572dba1aa1703d",
|
|
284
|
+
"hash": "f3cae0034df0aaa5382c0d047fff684ab30354eab2a3b7f280438a95a7ef9488",
|
|
285
|
+
"signature": "c7ck6ex7mu5OqR2JiRnlnU0nnBHoYPqQkSvKDnvhfyBGUKnOUyT/uEyxifj+UW+s3GB4m651zDauhjWsqVMIDw==",
|
|
286
286
|
"name": "Dmytri Kleiner",
|
|
287
287
|
"email": "dev@dmytri.to",
|
|
288
288
|
"npm": "11.12.1",
|
|
289
289
|
"node": "v25.8.2",
|
|
290
290
|
"git": "git version 2.47.3",
|
|
291
|
-
"hipp": "0.1.
|
|
291
|
+
"hipp": "0.1.37"
|
|
292
292
|
}
|
|
293
293
|
```
|
package/hipp.js
CHANGED
|
@@ -178,24 +178,25 @@ function findLastJsonBlock(readmeContent) {
|
|
|
178
178
|
return lastValid;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
function
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
181
|
+
function hashFiles(dir) {
|
|
182
|
+
const entries = [];
|
|
183
|
+
const walk = (d, prefix = '') => {
|
|
184
|
+
const items = fs.readdirSync(d);
|
|
185
|
+
for (const item of items.sort()) {
|
|
186
|
+
if (item === 'node_modules' || item === '.git' || item === 'hipp.priv') continue;
|
|
187
|
+
const full = path.join(d, item);
|
|
188
|
+
const rel = prefix ? prefix + '/' + item : item;
|
|
189
|
+
const stat = fs.statSync(full);
|
|
190
|
+
if (stat.isDirectory()) {
|
|
191
|
+
walk(full, rel);
|
|
192
|
+
} else {
|
|
193
|
+
const content = fs.readFileSync(full);
|
|
194
|
+
entries.push(rel + ':' + sha256(content));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
walk(dir);
|
|
199
|
+
return sha256(entries.join('\n'));
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
function safeStageName(name) {
|
|
@@ -455,10 +456,6 @@ async function runVerify(packageSpec) {
|
|
|
455
456
|
fail(`❌ Failed to download tarball`);
|
|
456
457
|
}
|
|
457
458
|
|
|
458
|
-
const npmTarballContent = fs.readFileSync(tarballPath);
|
|
459
|
-
const npmHash = sha256(npmTarballContent);
|
|
460
|
-
log.success(`📦 NPM tarball hash: ${npmHash.slice(0, 12)}...`);
|
|
461
|
-
|
|
462
459
|
if (fs.existsSync(extractDir)) {
|
|
463
460
|
fs.rmSync(extractDir, { recursive: true });
|
|
464
461
|
}
|
|
@@ -531,8 +528,8 @@ async function runVerify(packageSpec) {
|
|
|
531
528
|
const trackedFiles = getTrackedFilesFromDir(tmpDir);
|
|
532
529
|
copyTrackedFilesFromDir(stageDir, tmpDir, trackedFiles);
|
|
533
530
|
|
|
534
|
-
log.info(`📦
|
|
535
|
-
const
|
|
531
|
+
log.info(`📦 Computing logical hash of git files...`);
|
|
532
|
+
const cleanHash = hashFiles(stageDir);
|
|
536
533
|
log.success(`📦 Clean hash: ${cleanHash.slice(0, 12)}...`);
|
|
537
534
|
|
|
538
535
|
log.info(`🔍 Check 2: Verifying manifest hash...`);
|
|
@@ -564,21 +561,29 @@ async function runVerify(packageSpec) {
|
|
|
564
561
|
stagedReadme = stagedReadme.trimEnd() + '\n\n## Verify\n\n' +
|
|
565
562
|
'Verify this package with [@dk/hipp](https://www.npmjs.com/package/@dk/hipp):\n\n' +
|
|
566
563
|
'```bash\n' +
|
|
567
|
-
`npx @dk/hipp verify ${pkgName}@${tagVersion}\n` +
|
|
564
|
+
`npx @dk/hipp --verify ${pkgName}@${tagVersion}\n` +
|
|
568
565
|
'```\n\n' +
|
|
569
566
|
'```json\n' + JSON.stringify(manifest, null, 2) + '\n```\n';
|
|
570
567
|
fs.writeFileSync(stagedReadmePath, stagedReadme);
|
|
571
568
|
|
|
572
569
|
const stagedPkgPath = path.join(stageDir, 'package.json');
|
|
573
570
|
const stagedPkg = JSON.parse(fs.readFileSync(stagedPkgPath, 'utf8'));
|
|
574
|
-
stagedPkg.version = tagVersion;
|
|
575
571
|
fs.writeFileSync(stagedPkgPath, JSON.stringify(stagedPkg, null, 2) + '\n');
|
|
576
572
|
|
|
577
|
-
const
|
|
578
|
-
|
|
573
|
+
const npmExtractPkgPath = path.join(packageDir, 'package.json');
|
|
574
|
+
const npmExtractPkg = JSON.parse(fs.readFileSync(npmExtractPkgPath, 'utf8'));
|
|
575
|
+
if (stagedPkg.version === '0.0.0') {
|
|
576
|
+
npmExtractPkg.version = '0.0.0';
|
|
577
|
+
fs.writeFileSync(npmExtractPkgPath, JSON.stringify(npmExtractPkg, null, 2) + '\n');
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
const npmExtractHash = hashFiles(packageDir);
|
|
581
|
+
const rebuildHash = hashFiles(stageDir);
|
|
582
|
+
log.success(`📦 NPM-extract hash: ${npmExtractHash.slice(0, 12)}...`);
|
|
583
|
+
log.success(`📦 Git-rebuild hash: ${rebuildHash.slice(0, 12)}...`);
|
|
579
584
|
|
|
580
|
-
if (rebuildHash !==
|
|
581
|
-
log.error(`❌ Rebuild mismatch:
|
|
585
|
+
if (rebuildHash !== npmExtractHash) {
|
|
586
|
+
log.error(`❌ Rebuild mismatch: git ${rebuildHash.slice(0, 12)} != npm ${npmExtractHash.slice(0, 12)}`);
|
|
582
587
|
} else {
|
|
583
588
|
log.success(`🔄 Rebuild verified`);
|
|
584
589
|
results.rebuild = true;
|
|
@@ -707,9 +712,9 @@ async function run() {
|
|
|
707
712
|
|
|
708
713
|
const { privateKey } = loadOrGenerateKeys();
|
|
709
714
|
|
|
710
|
-
log.info(`📦
|
|
711
|
-
const
|
|
712
|
-
log.success(`🔒 Content hash: ${
|
|
715
|
+
log.info(`📦 Computing logical hash...`);
|
|
716
|
+
const logicalHash = hashFiles(stageDir);
|
|
717
|
+
log.success(`🔒 Content hash: ${logicalHash.slice(0, 12)}...`);
|
|
713
718
|
|
|
714
719
|
const stagedReadmePath = path.join(stageDir, 'README.md');
|
|
715
720
|
let stagedReadme = '';
|
|
@@ -726,14 +731,14 @@ async function run() {
|
|
|
726
731
|
const hippPkg = JSON.parse(fs.readFileSync(hippPkgPath, 'utf8'));
|
|
727
732
|
const hippVersion = hippPkg.version === '0.0.0' ? version : hippPkg.version;
|
|
728
733
|
const originUrl = provenance.remoteUrl;
|
|
729
|
-
const dataToSign = buildSignData(
|
|
734
|
+
const dataToSign = buildSignData(logicalHash, originUrl, rawTag, revision, name, email);
|
|
730
735
|
const signature = signContent(dataToSign, privateKey);
|
|
731
736
|
|
|
732
737
|
const manifestJson = {
|
|
733
738
|
origin: originUrl,
|
|
734
739
|
tag: rawTag,
|
|
735
740
|
revision: revision,
|
|
736
|
-
hash:
|
|
741
|
+
hash: logicalHash,
|
|
737
742
|
signature: signature,
|
|
738
743
|
name: name,
|
|
739
744
|
email: email,
|
|
@@ -746,7 +751,7 @@ async function run() {
|
|
|
746
751
|
stagedReadme = stagedReadme.trimEnd() + '\n\n## Verify\n\n' +
|
|
747
752
|
'Verify this package with [@dk/hipp](https://www.npmjs.com/package/@dk/hipp):\n\n' +
|
|
748
753
|
'```bash\n' +
|
|
749
|
-
`npx @dk/hipp verify ${pkg.name}@${version}\n` +
|
|
754
|
+
`npx @dk/hipp --verify ${pkg.name}@${version}\n` +
|
|
750
755
|
'```\n\n' +
|
|
751
756
|
'```json\n' + JSON.stringify(manifestJson, null, 2) + '\n```\n';
|
|
752
757
|
fs.writeFileSync(stagedReadmePath, stagedReadme);
|
|
@@ -787,8 +792,8 @@ async function run() {
|
|
|
787
792
|
}
|
|
788
793
|
}
|
|
789
794
|
|
|
790
|
-
const isVerify = process.argv.includes('verify');
|
|
791
|
-
const verifyIndex = process.argv.indexOf('verify');
|
|
795
|
+
const isVerify = process.argv.includes('--verify');
|
|
796
|
+
const verifyIndex = process.argv.indexOf('--verify');
|
|
792
797
|
const packageSpec = verifyIndex !== -1 ? process.argv[verifyIndex + 1] : null;
|
|
793
798
|
|
|
794
799
|
if (isVerify) {
|
|
@@ -817,8 +822,8 @@ if (isVerify) {
|
|
|
817
822
|
|
|
818
823
|
Usage:
|
|
819
824
|
npx hipp [options] [-- npm-options]
|
|
820
|
-
npx hipp verify [@package[@version]]
|
|
821
|
-
npx hipp verify --self
|
|
825
|
+
npx hipp --verify [@package[@version]]
|
|
826
|
+
npx hipp --verify --self
|
|
822
827
|
|
|
823
828
|
Without arguments: in a hipp repo (package.json version 0.0.0 or matching
|
|
824
829
|
a semver tag on HEAD), verifies the published package at that version.
|