@wrongstack/core 0.269.0 → 0.272.0

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 (76) hide show
  1. package/dist/{agent-bridge-PcHQl_UQ.d.ts → agent-bridge-jVSZiygR.d.ts} +1 -1
  2. package/dist/{agent-subagent-runner-SHJW7t8q.d.ts → agent-subagent-runner-DOLIwBRo.d.ts} +7 -7
  3. package/dist/{brain-BYcK__Ym.d.ts → brain-CdbbJWi3.d.ts} +71 -1
  4. package/dist/{compactor-C2RKEBtC.d.ts → compactor-72ug-ZRB.d.ts} +1 -1
  5. package/dist/{config-C_ae2k86.d.ts → config-D2DGoGSQ.d.ts} +29 -2
  6. package/dist/{context-Dp87Bcaq.d.ts → context-Dw55zZ_Q.d.ts} +110 -1
  7. package/dist/coordination/index.d.ts +121 -17
  8. package/dist/coordination/index.js +738 -74
  9. package/dist/coordination/index.js.map +1 -1
  10. package/dist/defaults/index.d.ts +25 -25
  11. package/dist/defaults/index.js +599 -86
  12. package/dist/defaults/index.js.map +1 -1
  13. package/dist/execution/index.d.ts +23 -18
  14. package/dist/execution/index.js +136 -41
  15. package/dist/execution/index.js.map +1 -1
  16. package/dist/execution/prompt-enhancer.d.ts +36 -6
  17. package/dist/execution/prompt-enhancer.js +35 -9
  18. package/dist/execution/prompt-enhancer.js.map +1 -1
  19. package/dist/extension/index.d.ts +6 -6
  20. package/dist/{global-mailbox-Bvrz1P3f.d.ts → global-mailbox-CQj_C9Dp.d.ts} +139 -3
  21. package/dist/{goal-preamble-CA_4yiGQ.d.ts → goal-preamble-ZXDjjR1y.d.ts} +9 -9
  22. package/dist/{goal-store-DhuJoUNG.d.ts → goal-store-CcJBd-g1.d.ts} +1 -1
  23. package/dist/hq/index.d.ts +93 -6
  24. package/dist/hq/index.js +619 -49
  25. package/dist/hq/index.js.map +1 -1
  26. package/dist/{index-whDfTANu.d.ts → index-2Lhk5v0o.d.ts} +2 -2
  27. package/dist/{index-CZQ6Pwbs.d.ts → index-BL7BAx0p.d.ts} +8 -8
  28. package/dist/{index-W4VJCzHa.d.ts → index-Qo4kTzgw.d.ts} +5 -5
  29. package/dist/index.d.ts +96 -56
  30. package/dist/index.js +1941 -352
  31. package/dist/index.js.map +1 -1
  32. package/dist/infrastructure/index.d.ts +6 -6
  33. package/dist/infrastructure/index.js +5 -3
  34. package/dist/infrastructure/index.js.map +1 -1
  35. package/dist/kernel/index.d.ts +9 -9
  36. package/dist/kernel/index.js.map +1 -1
  37. package/dist/{mcp-servers-DJdZiRcv.d.ts → mcp-servers-DS-YUXvF.d.ts} +3 -3
  38. package/dist/models/index.d.ts +5 -5
  39. package/dist/models/index.js +28 -5
  40. package/dist/models/index.js.map +1 -1
  41. package/dist/{models-registry-C3a-2-Yd.d.ts → models-registry-DP6pGHet.d.ts} +1 -1
  42. package/dist/{multi-agent-coordinator-CJSpTe5O.d.ts → multi-agent-coordinator-BvbdNQ14.d.ts} +1 -1
  43. package/dist/{null-fleet-bus-QVshIsDx.d.ts → null-fleet-bus-BxTfXBKo.d.ts} +6 -6
  44. package/dist/observability/index.d.ts +2 -2
  45. package/dist/{parallel-eternal-engine-D9y5Pkcc.d.ts → parallel-eternal-engine-Cf-GTegR.d.ts} +9 -9
  46. package/dist/{path-resolver-CnQ8SIfh.d.ts → path-resolver-DztfnFcv.d.ts} +3 -3
  47. package/dist/{permission-CvYQNUqZ.d.ts → permission-CC7XFYWG.d.ts} +1 -1
  48. package/dist/{permission-policy-D5Ss8j4B.d.ts → permission-policy-cYR4RJmw.d.ts} +2 -2
  49. package/dist/{pipeline-l_zzFRh3.d.ts → pipeline-sNIkhXeB.d.ts} +2 -2
  50. package/dist/{plan-templates-NtPgyeJA.d.ts → plan-templates-DYiKFmEb.d.ts} +11 -5
  51. package/dist/{provider-model-resolve-d5poT5y0.d.ts → provider-model-resolve-dYAbTs_i.d.ts} +3 -3
  52. package/dist/{provider-runner-gkctlQV_.d.ts → provider-runner-Dw8x0F7u.d.ts} +3 -3
  53. package/dist/{retry-policy-CtFhfwa8.d.ts → retry-policy-BV7nzeAd.d.ts} +1 -1
  54. package/dist/sdd/index.d.ts +8 -8
  55. package/dist/sdd/index.js +2 -0
  56. package/dist/sdd/index.js.map +1 -1
  57. package/dist/{secret-vault-BLsVmTIK.d.ts → secret-vault-eMBKfheR.d.ts} +9 -1
  58. package/dist/security/index.d.ts +5 -5
  59. package/dist/security/index.js +137 -10
  60. package/dist/security/index.js.map +1 -1
  61. package/dist/{selector-CXl2_y9W.d.ts → selector-C4ORTOid.d.ts} +1 -1
  62. package/dist/{session-event-bridge-Ccud20CC.d.ts → session-event-bridge-CeNpUL9w.d.ts} +1 -1
  63. package/dist/{session-reader-ZeXQmsmE.d.ts → session-reader-BepLSnGL.d.ts} +1 -1
  64. package/dist/storage/index.d.ts +45 -13
  65. package/dist/storage/index.js +374 -113
  66. package/dist/storage/index.js.map +1 -1
  67. package/dist/tools/index.d.ts +2 -2
  68. package/dist/tools/index.js +9 -2
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/types/index.d.ts +19 -19
  71. package/dist/types/index.js +202 -41
  72. package/dist/types/index.js.map +1 -1
  73. package/dist/utils/index.d.ts +17 -4
  74. package/dist/utils/index.js +48 -9
  75. package/dist/utils/index.js.map +1 -1
  76. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import { S as SecretScrubber } from './permission-CvYQNUqZ.js';
1
+ import { S as SecretScrubber } from './permission-CC7XFYWG.js';
2
2
  import { L as Logger } from './logger-B63L5bTg.js';
3
3
  import { R as RotatableSecretVault, S as SecretVault } from './secret-vault-BAKpgFw_.js';
4
4
 
@@ -51,6 +51,14 @@ declare class DefaultSecretVault implements RotatableSecretVault {
51
51
  oldVersion: number;
52
52
  newVersion: number;
53
53
  };
54
+ /**
55
+ * If WRONGSTACK_VAULT_PASSPHRASE is set but the key on disk is still stored
56
+ * unwrapped (legacy v1 / versioned v2), re-write it in passphrase-wrapped (v3)
57
+ * form. The data key is preserved, so all existing ciphertext keeps
58
+ * decrypting. Best-effort: a write failure leaves the working unwrapped file
59
+ * in place and is not fatal to load.
60
+ */
61
+ private migrateToWrappedIfPassphrase;
54
62
  private loadOrCreateKey;
55
63
  }
56
64
  /**
@@ -1,8 +1,8 @@
1
- export { a as DefaultSecretScrubber, D as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, b as rotateConfigKeys } from '../secret-vault-BLsVmTIK.js';
2
- export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-D5Ss8j4B.js';
3
- export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-whDfTANu.js';
4
- import '../permission-CvYQNUqZ.js';
5
- import '../context-Dp87Bcaq.js';
1
+ export { a as DefaultSecretScrubber, D as DefaultSecretVault, S as SecretVaultOptions, d as decryptConfigSecrets, e as encryptConfigSecrets, i as isSecretField, m as migratePlaintextSecrets, r as rewriteConfigEncrypted, b as rotateConfigKeys } from '../secret-vault-eMBKfheR.js';
2
+ export { A as AutoApprovePermissionPolicy, D as DefaultPermissionPolicy, P as PermissionPolicyOptions } from '../permission-policy-cYR4RJmw.js';
3
+ export { D as DANGEROUS_FOR_SUBAGENTS, T as ToolCapabilities, a as ToolCapability, g as getDangerousCapabilities, h as hasCapability, b as hasDangerousCapabilityForSubagents } from '../index-2Lhk5v0o.js';
4
+ import '../permission-CC7XFYWG.js';
5
+ import '../context-Dw55zZ_Q.js';
6
6
  import '../logger-B63L5bTg.js';
7
7
  import '../secret-vault-BAKpgFw_.js';
8
8
  import '../input-reader-E-ffP2ee.js';
@@ -1,4 +1,4 @@
1
- import { randomBytes, createCipheriv, createDecipheriv } from 'crypto';
1
+ import { randomBytes, createCipheriv, createDecipheriv, scryptSync } from 'crypto';
2
2
  import * as fs2 from 'fs';
3
3
  import * as fs from 'fs/promises';
4
4
  import * as path3 from 'path';
@@ -310,6 +310,7 @@ function escapeRegex(s) {
310
310
  }
311
311
  var COMPILED_GLOB_CACHE = /* @__PURE__ */ new Map();
312
312
  var CACHE_MAX_SIZE = 2e3;
313
+ var NEVER_MATCH = /[^\s\S]/;
313
314
  function getCachedGlob(pattern) {
314
315
  const cached = COMPILED_GLOB_CACHE.get(pattern);
315
316
  if (cached) return cached;
@@ -319,7 +320,12 @@ function getCachedGlob(pattern) {
319
320
  COMPILED_GLOB_CACHE.delete(expectDefined(keys[i]));
320
321
  }
321
322
  }
322
- const re = compileGlob(pattern);
323
+ let re;
324
+ try {
325
+ re = compileGlob(pattern);
326
+ } catch {
327
+ re = NEVER_MATCH;
328
+ }
323
329
  COMPILED_GLOB_CACHE.set(pattern, re);
324
330
  return re;
325
331
  }
@@ -543,6 +549,83 @@ var ALGO = "aes-256-gcm";
543
549
  var KEY_FILE_MODE = 384;
544
550
  var KEY_FILE_MAGIC = Buffer.from("WSKV", "ascii");
545
551
  var VERSIONED_KEY_FILE_SIZE = KEY_FILE_MAGIC.length + 1 + KEY_BYTES;
552
+ var KEK_MAGIC = Buffer.from("WSKW", "ascii");
553
+ var KEK_SALT_BYTES = 16;
554
+ var WRAPPED_KEY_FILE_SIZE = KEK_MAGIC.length + 1 + KEK_SALT_BYTES + IV_BYTES + TAG_BYTES + KEY_BYTES;
555
+ var SCRYPT_N = 1 << 15;
556
+ var SCRYPT_R = 8;
557
+ var SCRYPT_P = 1;
558
+ var SCRYPT_MAXMEM = 64 * 1024 * 1024;
559
+ function getVaultPassphrase() {
560
+ const v = process.env["WRONGSTACK_VAULT_PASSPHRASE"];
561
+ return v && v.length > 0 ? v : void 0;
562
+ }
563
+ function isWrappedKeyFile(buf) {
564
+ return buf.length === WRAPPED_KEY_FILE_SIZE && buf.subarray(0, KEK_MAGIC.length).equals(KEK_MAGIC);
565
+ }
566
+ function deriveKEK(passphrase, salt) {
567
+ return scryptSync(passphrase, salt, KEY_BYTES, {
568
+ N: SCRYPT_N,
569
+ r: SCRYPT_R,
570
+ p: SCRYPT_P,
571
+ maxmem: SCRYPT_MAXMEM
572
+ });
573
+ }
574
+ function wrapDataKey(dataKey, keyVersion, passphrase) {
575
+ const salt = randomBytes(KEK_SALT_BYTES);
576
+ const iv = randomBytes(IV_BYTES);
577
+ const kek = deriveKEK(passphrase, salt);
578
+ const cipher = createCipheriv(ALGO, kek, iv);
579
+ const ct = Buffer.concat([cipher.update(dataKey), cipher.final()]);
580
+ const tag = cipher.getAuthTag();
581
+ const out = Buffer.alloc(WRAPPED_KEY_FILE_SIZE);
582
+ let off = 0;
583
+ KEK_MAGIC.copy(out, off);
584
+ off += KEK_MAGIC.length;
585
+ out[off] = keyVersion & 255;
586
+ off += 1;
587
+ salt.copy(out, off);
588
+ off += KEK_SALT_BYTES;
589
+ iv.copy(out, off);
590
+ off += IV_BYTES;
591
+ tag.copy(out, off);
592
+ off += TAG_BYTES;
593
+ ct.copy(out, off);
594
+ return out;
595
+ }
596
+ function unwrapDataKey(buf, keyFile) {
597
+ const passphrase = getVaultPassphrase();
598
+ if (!passphrase) {
599
+ throw new ConfigError({
600
+ message: `SecretVault: key file ${keyFile} is passphrase-protected \u2014 set the WRONGSTACK_VAULT_PASSPHRASE environment variable to unlock it.`,
601
+ code: ERROR_CODES.CONFIG_INVALID,
602
+ context: { keyFile }
603
+ });
604
+ }
605
+ let off = KEK_MAGIC.length;
606
+ const version = buf[off];
607
+ off += 1;
608
+ const salt = buf.subarray(off, off + KEK_SALT_BYTES);
609
+ off += KEK_SALT_BYTES;
610
+ const iv = buf.subarray(off, off + IV_BYTES);
611
+ off += IV_BYTES;
612
+ const tag = buf.subarray(off, off + TAG_BYTES);
613
+ off += TAG_BYTES;
614
+ const ct = buf.subarray(off, off + KEY_BYTES);
615
+ const kek = deriveKEK(passphrase, salt);
616
+ const decipher = createDecipheriv(ALGO, kek, iv);
617
+ decipher.setAuthTag(tag);
618
+ try {
619
+ const key = Buffer.concat([decipher.update(ct), decipher.final()]);
620
+ return { key: Buffer.from(key), version };
621
+ } catch {
622
+ throw new ConfigError({
623
+ message: `SecretVault: failed to unlock key file ${keyFile} \u2014 wrong WRONGSTACK_VAULT_PASSPHRASE (key unwrap authentication failed).`,
624
+ code: ERROR_CODES.CONFIG_INVALID,
625
+ context: { keyFile }
626
+ });
627
+ }
628
+ }
546
629
  function checkKeyFilePermissions(keyFile) {
547
630
  if (process.platform === "win32") return;
548
631
  try {
@@ -635,25 +718,56 @@ var DefaultSecretVault = class {
635
718
  const oldVersion = this._keyVersion;
636
719
  const newKey = randomBytes(KEY_BYTES);
637
720
  const newVersion = oldVersion + 1;
638
- const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
639
- KEY_FILE_MAGIC.copy(keyFileBuf, 0);
640
- keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
641
- newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
642
721
  fs2.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
643
- fs2.writeFileSync(this.keyFile, keyFileBuf, { mode: 384 });
722
+ const passphrase = getVaultPassphrase();
723
+ if (passphrase) {
724
+ fs2.writeFileSync(this.keyFile, wrapDataKey(newKey, newVersion, passphrase), { mode: 384 });
725
+ } else {
726
+ const keyFileBuf = Buffer.alloc(VERSIONED_KEY_FILE_SIZE);
727
+ KEY_FILE_MAGIC.copy(keyFileBuf, 0);
728
+ keyFileBuf[KEY_FILE_MAGIC.length] = newVersion;
729
+ newKey.copy(keyFileBuf, KEY_FILE_MAGIC.length + 1);
730
+ fs2.writeFileSync(this.keyFile, keyFileBuf, { mode: 384 });
731
+ }
644
732
  checkKeyFilePermissions(this.keyFile);
645
733
  this.key = newKey;
646
734
  this._keyVersion = newVersion;
647
735
  return { oldVersion, newVersion };
648
736
  }
737
+ /**
738
+ * If WRONGSTACK_VAULT_PASSPHRASE is set but the key on disk is still stored
739
+ * unwrapped (legacy v1 / versioned v2), re-write it in passphrase-wrapped (v3)
740
+ * form. The data key is preserved, so all existing ciphertext keeps
741
+ * decrypting. Best-effort: a write failure leaves the working unwrapped file
742
+ * in place and is not fatal to load.
743
+ */
744
+ migrateToWrappedIfPassphrase() {
745
+ const passphrase = getVaultPassphrase();
746
+ if (!passphrase || !this.key) return;
747
+ try {
748
+ fs2.writeFileSync(this.keyFile, wrapDataKey(this.key, this._keyVersion, passphrase), {
749
+ mode: 384
750
+ });
751
+ checkKeyFilePermissions(this.keyFile);
752
+ } catch {
753
+ }
754
+ }
649
755
  loadOrCreateKey() {
650
756
  if (this.key) return this.key;
651
757
  try {
652
758
  const buf = fs2.readFileSync(this.keyFile);
759
+ if (isWrappedKeyFile(buf)) {
760
+ const { key: key2, version } = unwrapDataKey(buf, this.keyFile);
761
+ this.key = key2;
762
+ this._keyVersion = version;
763
+ checkKeyFilePermissions(this.keyFile);
764
+ return this.key;
765
+ }
653
766
  if (buf.length === KEY_BYTES) {
654
767
  this.key = buf;
655
768
  this._keyVersion = 1;
656
769
  checkKeyFilePermissions(this.keyFile);
770
+ this.migrateToWrappedIfPassphrase();
657
771
  return this.key;
658
772
  }
659
773
  if (buf.length === VERSIONED_KEY_FILE_SIZE) {
@@ -677,6 +791,7 @@ var DefaultSecretVault = class {
677
791
  this.key = Buffer.from(key2);
678
792
  this._keyVersion = version;
679
793
  checkKeyFilePermissions(this.keyFile);
794
+ this.migrateToWrappedIfPassphrase();
680
795
  return this.key;
681
796
  }
682
797
  throw new ConfigError({
@@ -689,11 +804,20 @@ var DefaultSecretVault = class {
689
804
  }
690
805
  fs2.mkdirSync(path3.dirname(this.keyFile), { recursive: true });
691
806
  const key = randomBytes(KEY_BYTES);
807
+ const passphrase = getVaultPassphrase();
808
+ const initialBytes = passphrase ? wrapDataKey(key, 1, passphrase) : key;
692
809
  try {
693
- fs2.writeFileSync(this.keyFile, key, { mode: 384, flag: "wx" });
810
+ fs2.writeFileSync(this.keyFile, initialBytes, { mode: 384, flag: "wx" });
694
811
  } catch (err) {
695
812
  if (err.code !== "EEXIST") throw err;
696
813
  const buf = fs2.readFileSync(this.keyFile);
814
+ if (isWrappedKeyFile(buf)) {
815
+ const { key: winnerKey, version } = unwrapDataKey(buf, this.keyFile);
816
+ this.key = winnerKey;
817
+ this._keyVersion = version;
818
+ checkKeyFilePermissions(this.keyFile);
819
+ return this.key;
820
+ }
697
821
  if (buf.length === KEY_BYTES) {
698
822
  this.key = buf;
699
823
  this._keyVersion = 1;
@@ -1086,6 +1210,9 @@ function isClearlyDestructiveBashCommand(command, projectRoot) {
1086
1210
  }
1087
1211
 
1088
1212
  // src/security/permission-policy.ts
1213
+ function matchesTrust(patterns, subject) {
1214
+ return patterns.includes(subject) || matchAny(patterns, subject);
1215
+ }
1089
1216
  var DefaultPermissionPolicy = class {
1090
1217
  policy = {};
1091
1218
  loaded = false;
@@ -1222,7 +1349,7 @@ var DefaultPermissionPolicy = class {
1222
1349
  this._evalCache.set(cacheKey, decision);
1223
1350
  return decision;
1224
1351
  }
1225
- if (entry?.deny && subject && matchAny(entry.deny, subject)) {
1352
+ if (entry?.deny && subject && matchesTrust(entry.deny, subject)) {
1226
1353
  const decision = { permission: "deny", source: "deny", reason: "matched deny pattern" };
1227
1354
  this._evalCache.set(cacheKey, decision);
1228
1355
  return decision;
@@ -1232,7 +1359,7 @@ var DefaultPermissionPolicy = class {
1232
1359
  this._evalCache.set(cacheKey, decision);
1233
1360
  return decision;
1234
1361
  }
1235
- if (entry?.allow && subject && matchAny(entry.allow, subject)) {
1362
+ if (entry?.allow && subject && matchesTrust(entry.allow, subject)) {
1236
1363
  const decision = { permission: "auto", source: "trust", reason: "matched allow pattern" };
1237
1364
  this._evalCache.set(cacheKey, decision);
1238
1365
  return decision;