@keepgoingdev/cli 1.3.2 → 1.3.3

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 (2) hide show
  1. package/dist/index.js +43 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -616,6 +616,7 @@ import os from "os";
616
616
  import path3 from "path";
617
617
  var LICENSE_FILE = "license.json";
618
618
  var DEVICE_ID_FILE = "device-id";
619
+ var SIGNING_KEY_FILE = "signing-key";
619
620
  function getGlobalLicenseDir() {
620
621
  return path3.join(os.homedir(), ".keepgoing");
621
622
  }
@@ -637,6 +638,37 @@ function getDeviceId() {
637
638
  fs.writeFileSync(filePath, id, "utf-8");
638
639
  return id;
639
640
  }
641
+ function getSigningKey() {
642
+ const dir = getGlobalLicenseDir();
643
+ const keyPath = path3.join(dir, SIGNING_KEY_FILE);
644
+ try {
645
+ const existing = fs.readFileSync(keyPath, "utf-8").trim();
646
+ if (existing) return existing;
647
+ } catch {
648
+ }
649
+ const key = crypto.randomBytes(32).toString("hex");
650
+ if (!fs.existsSync(dir)) {
651
+ fs.mkdirSync(dir, { recursive: true });
652
+ }
653
+ fs.writeFileSync(keyPath, key, "utf-8");
654
+ return key;
655
+ }
656
+ function computeSignature(licenses) {
657
+ const sorted = [...licenses].sort((a, b) => a.licenseKey.localeCompare(b.licenseKey));
658
+ const payload = JSON.stringify(sorted);
659
+ return crypto.createHmac("sha256", getSigningKey()).update(payload).digest("hex");
660
+ }
661
+ function verifySignature(store) {
662
+ if (!store.signature) return false;
663
+ try {
664
+ const expected = Buffer.from(computeSignature(store.licenses), "hex");
665
+ const actual = Buffer.from(store.signature, "hex");
666
+ if (actual.length !== expected.length) return false;
667
+ return crypto.timingSafeEqual(actual, expected);
668
+ } catch {
669
+ return false;
670
+ }
671
+ }
640
672
  var DECISION_DETECTION_VARIANT_ID = 1361527;
641
673
  var SESSION_AWARENESS_VARIANT_ID = 1366510;
642
674
  var TEST_DECISION_DETECTION_VARIANT_ID = 1345647;
@@ -675,6 +707,13 @@ function readLicenseStore() {
675
707
  const data = JSON.parse(raw);
676
708
  if (data?.version === 2 && Array.isArray(data.licenses)) {
677
709
  store = data;
710
+ if (store.signature && !verifySignature(store)) {
711
+ store = {
712
+ version: 2,
713
+ licenses: store.licenses.map((l) => ({ ...l, status: "inactive" }))
714
+ // Omit signature so the next writeLicenseStore() re-signs cleanly
715
+ };
716
+ }
678
717
  } else {
679
718
  store = { version: 2, licenses: [] };
680
719
  }
@@ -691,6 +730,7 @@ function writeLicenseStore(store) {
691
730
  if (!fs.existsSync(dirPath)) {
692
731
  fs.mkdirSync(dirPath, { recursive: true });
693
732
  }
733
+ store.signature = computeSignature(store.licenses);
694
734
  const licensePath = path3.join(dirPath, LICENSE_FILE);
695
735
  fs.writeFileSync(licensePath, JSON.stringify(store, null, 2), "utf-8");
696
736
  _cachedStore = store;
@@ -724,7 +764,7 @@ function getLicenseForFeature(feature) {
724
764
  function getAllLicensesNeedingRevalidation() {
725
765
  return getActiveLicenses().filter((l) => needsRevalidation(l));
726
766
  }
727
- var REVALIDATION_THRESHOLD_MS = 24 * 60 * 60 * 1e3;
767
+ var REVALIDATION_THRESHOLD_MS = 6 * 60 * 60 * 1e3;
728
768
  function needsRevalidation(entry) {
729
769
  const lastValidated = new Date(entry.lastValidatedAt).getTime();
730
770
  return Date.now() - lastValidated > REVALIDATION_THRESHOLD_MS;
@@ -2398,7 +2438,7 @@ import { spawn } from "child_process";
2398
2438
  import { readFileSync, existsSync } from "fs";
2399
2439
  import path10 from "path";
2400
2440
  import os4 from "os";
2401
- var CLI_VERSION = "1.3.2";
2441
+ var CLI_VERSION = "1.3.3";
2402
2442
  var NPM_REGISTRY_URL = "https://registry.npmjs.org/@keepgoingdev/cli/latest";
2403
2443
  var FETCH_TIMEOUT_MS = 5e3;
2404
2444
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
@@ -3939,7 +3979,7 @@ async function main() {
3939
3979
  }
3940
3980
  break;
3941
3981
  case "version":
3942
- console.log(`keepgoing v${"1.3.2"}`);
3982
+ console.log(`keepgoing v${"1.3.3"}`);
3943
3983
  break;
3944
3984
  case "activate":
3945
3985
  await activateCommand({ licenseKey: subcommand });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keepgoingdev/cli",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Terminal CLI for KeepGoing. Resume side projects without the mental friction.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",