@dk/hipp 0.1.19 → 0.1.21

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 (3) hide show
  1. package/README.md +24 -17
  2. package/hipp.js +31 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -109,32 +109,36 @@ The manifest contains:
109
109
  {
110
110
  "origin": "git@github.com:dk/your-package.git",
111
111
  "tag": "v1.0.0",
112
+ "revision": "<git-commit-hash>",
112
113
  "hash": "<sha256-of-tarball>",
113
114
  "signature": "<base64-ed25519-signature>",
114
115
  "name": "Jane Developer",
115
- "email": "jane@example.com"
116
+ "email": "jane@example.com",
117
+ "npm": "10.2.4",
118
+ "node": "v20.11.0"
116
119
  }
117
120
  ```
118
121
 
119
122
  **Step 2: Clone git and verify**
120
123
 
121
124
  3. Clone the repository at the tagged commit (using origin/tag from manifest)
122
- 4. Stage all tracked files
123
- 5. Run `npm pack` to create a tarball
124
- 6. Compute SHA256 hash of the clean tarball
125
- 7. Compare with the `hash` field from the npm manifest
125
+ 4. Verify the cloned commit hash matches the `revision` field in manifest
126
+ 5. Stage all tracked files
127
+ 6. Run `npm pack` to create a tarball
128
+ 7. Compute SHA256 hash of the clean tarball
129
+ 8. Compare with the `hash` field from the npm manifest
126
130
 
127
131
  **Step 3: Verify signature**
128
132
 
129
- 8. Read `hipp.pub` from the cloned repository
130
- 9. Verify the signature was created by signing:
131
- `hash + "\n" + origin + "\n" + tag + "\n" + name + "\n" + email`
133
+ 9. Read `hipp.pub` from the cloned repository
134
+ 10. Verify the signature was created by signing:
135
+ `hash + "\n" + origin + "\n" + tag + "\n" + revision + "\n" + name + "\n" + email`
132
136
 
133
137
  **Step 4: Rebuild verification**
134
138
 
135
- 10. Append the manifest to the staged README
136
- 11. Update the staged `package.json` version to match the tag
137
- 12. Run `npm pack` again and verify the hash matches the npm tarball
139
+ 11. Append the manifest to the staged README
140
+ 12. Update the staged `package.json` version to match the tag
141
+ 13. Run `npm pack` again and verify the hash matches the npm tarball
138
142
 
139
143
  ### Three Verification Checks
140
144
 
@@ -216,16 +220,19 @@ PERFORMANCE OF THIS SOFTWARE.
216
220
  Verify this package with [@dk/hipp](https://www.npmjs.com/package/@dk/hipp):
217
221
 
218
222
  ```bash
219
- npx @dk/hipp verify @dk/hipp@0.1.19
223
+ npx @dk/hipp verify @dk/hipp@0.1.21
220
224
  ```
221
225
 
222
226
  ```json
223
227
  {
224
- "origin": "git@github.com:dmytri/hipp.git",
225
- "tag": "v0.1.19",
226
- "hash": "adcdd07b563c5667d405b36ee1e391710e1baf4ee9434b1fd2f5a11c2acdecf0",
227
- "signature": "MdkA4AbDX4ofShqXKJxwWX+x+RWQJU16WpSkFvHU8LihgdIBJbsyNvzIfrjm+3cll2FdR5u3+/dwv+a0rHbUDw==",
228
+ "origin": "https://github.com/dmytri/hipp.git",
229
+ "tag": "v0.1.21",
230
+ "revision": "0a0be44db52e62d425959bda9f640049005c8809",
231
+ "hash": "50de72f67534fe6d9054c5b0cfab317aa1620d258cb291bd1dc65d60a43d77d8",
232
+ "signature": "m0+8tk8kM835KJcTeHPZPG20XLh4rEtyISoJB54aV8LknEmJVM5yRG6syq+Kg0AAP6VcJMmNrpMG9jOeDkyoBQ==",
228
233
  "name": "Dmytri Kleiner",
229
- "email": "dev@dmytri.to"
234
+ "email": "dev@dmytri.to",
235
+ "npm": "11.12.1",
236
+ "node": "v25.8.2"
230
237
  }
231
238
  ```
package/hipp.js CHANGED
@@ -33,6 +33,14 @@ function getGitUserInfo() {
33
33
  return { name, email };
34
34
  }
35
35
 
36
+ function sshToHttpsUrl(sshUrl) {
37
+ const match = sshUrl.match(/^git@([^:]+):(.+\.git)$/);
38
+ if (match) {
39
+ return `https://${match[1]}/${match[2]}`;
40
+ }
41
+ return sshUrl;
42
+ }
43
+
36
44
  function runCmd(cmd, args, options = {}) {
37
45
  const result = spawnSync(cmd, args, {
38
46
  encoding: 'utf8',
@@ -121,8 +129,8 @@ function verifySignature(data, signature, publicKey) {
121
129
  }, Buffer.from(signature, 'base64'));
122
130
  }
123
131
 
124
- function buildSignData(hash, origin, tag, name, email) {
125
- return `${hash}\n${origin}\n${tag}\n${name}\n${email}\n`;
132
+ function buildSignData(hash, origin, tag, revision, name, email) {
133
+ return `${hash}\n${origin}\n${tag}\n${revision}\n${name}\n${email}\n`;
126
134
  }
127
135
 
128
136
  function findLastJsonBlock(readmeContent) {
@@ -463,11 +471,11 @@ async function runVerify(packageSpec) {
463
471
 
464
472
  const npmReadme = fs.readFileSync(npmReadmePath, 'utf8');
465
473
  manifest = findLastJsonBlock(npmReadme);
466
- if (!manifest || !manifest.origin || !manifest.tag || !manifest.hash || !manifest.signature || !manifest.name || !manifest.email) {
474
+ if (!manifest || !manifest.origin || !manifest.tag || !manifest.revision || !manifest.hash || !manifest.signature || !manifest.name || !manifest.email) {
467
475
  fail(`❌ Manifest not found or invalid in README`);
468
476
  }
469
477
 
470
- const { origin: originUrl, tag, signature, name, email } = manifest;
478
+ const { origin: originUrl, tag, revision, signature, name, email, npm: npmVer, node: nodeVer } = manifest;
471
479
 
472
480
  log.info(`đŸŒŋ Cloning git origin at tag ${tag}...`);
473
481
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `hipp-verify-git-`));
@@ -476,6 +484,12 @@ async function runVerify(packageSpec) {
476
484
  try {
477
485
  git(['clone', '--branch', tag, '--depth', '1', originUrl, tmpDir], { stdio: 'pipe' });
478
486
 
487
+ const clonedRevision = git(['rev-parse', 'HEAD'], { cwd: tmpDir });
488
+ if (clonedRevision !== revision) {
489
+ fail(`❌ Revision mismatch: manifest claims ${revision.slice(0, 12)} but tag points to ${clonedRevision.slice(0, 12)}`);
490
+ }
491
+ log.success(`đŸˇī¸ Revision verified: ${revision.slice(0, 12)}...`);
492
+
479
493
  const publicKeyPath = path.join(tmpDir, 'hipp.pub');
480
494
  if (!fs.existsSync(publicKeyPath)) {
481
495
  fail(`❌ hipp.pub not found in git at tag ${tag}`);
@@ -498,7 +512,7 @@ async function runVerify(packageSpec) {
498
512
  log.success(`🔒 Manifest hash verified`);
499
513
 
500
514
  log.info(`🔍 Check 1: Verifying signature...`);
501
- const signData = buildSignData(manifest.hash, originUrl, tag, name, email);
515
+ const signData = buildSignData(manifest.hash, originUrl, tag, revision, name, email);
502
516
  const signatureValid = verifySignature(signData, signature, publicKey);
503
517
  if (!signatureValid) {
504
518
  fail(`❌ Signature verification failed`);
@@ -540,6 +554,9 @@ async function runVerify(packageSpec) {
540
554
  log.info(`📍 Publisher: ${name} <${email}>`);
541
555
  log.info(`📍 Origin: ${originUrl}`);
542
556
  log.info(`📍 Tag: ${tag}`);
557
+ if (npmVer && nodeVer) {
558
+ log.info(`â„šī¸ npm: ${npmVer} | node: ${nodeVer}`);
559
+ }
543
560
  } finally {
544
561
  fs.rmSync(tmpDir, { recursive: true, force: true });
545
562
  fs.rmSync(stageDir, { recursive: true, force: true });
@@ -638,16 +655,23 @@ async function run() {
638
655
  }
639
656
 
640
657
  const { name, email } = getGitUserInfo();
641
- const dataToSign = buildSignData(tarballHash, provenance.remoteUrl, rawTag, name, email);
658
+ const revision = refInfo.head;
659
+ const npmVersion = runCmd('npm', ['--version']).stdout.trim();
660
+ const nodeVersion = process.version;
661
+ const originUrl = sshToHttpsUrl(provenance.remoteUrl);
662
+ const dataToSign = buildSignData(tarballHash, originUrl, rawTag, revision, name, email);
642
663
  const signature = signContent(dataToSign, privateKey);
643
664
 
644
665
  const manifestJson = {
645
- origin: provenance.remoteUrl,
666
+ origin: originUrl,
646
667
  tag: rawTag,
668
+ revision: revision,
647
669
  hash: tarballHash,
648
670
  signature: signature,
649
671
  name: name,
650
672
  email: email,
673
+ npm: npmVersion,
674
+ node: nodeVersion,
651
675
  };
652
676
 
653
677
  stagedReadme = stagedReadme.trimEnd() + '\n\n## Verify\n\n' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dk/hipp",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "High Integrity Package Publisher",
5
5
  "main": "hipp.js",
6
6
  "bin": {