switchroom 0.7.11 → 0.7.15

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.
@@ -17,7 +17,7 @@ var __export = (target, all) => {
17
17
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
18
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
19
 
20
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/identity.js
20
+ // node_modules/yaml/dist/nodes/identity.js
21
21
  var require_identity = __commonJS((exports) => {
22
22
  var ALIAS = Symbol.for("yaml.alias");
23
23
  var DOC = Symbol.for("yaml.document");
@@ -71,7 +71,7 @@ var require_identity = __commonJS((exports) => {
71
71
  exports.isSeq = isSeq;
72
72
  });
73
73
 
74
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/visit.js
74
+ // node_modules/yaml/dist/visit.js
75
75
  var require_visit = __commonJS((exports) => {
76
76
  var identity = require_identity();
77
77
  var BREAK = Symbol("break visit");
@@ -226,7 +226,7 @@ var require_visit = __commonJS((exports) => {
226
226
  exports.visitAsync = visitAsync;
227
227
  });
228
228
 
229
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/directives.js
229
+ // node_modules/yaml/dist/doc/directives.js
230
230
  var require_directives = __commonJS((exports) => {
231
231
  var identity = require_identity();
232
232
  var visit = require_visit();
@@ -378,7 +378,7 @@ var require_directives = __commonJS((exports) => {
378
378
  exports.Directives = Directives;
379
379
  });
380
380
 
381
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/anchors.js
381
+ // node_modules/yaml/dist/doc/anchors.js
382
382
  var require_anchors = __commonJS((exports) => {
383
383
  var identity = require_identity();
384
384
  var visit = require_visit();
@@ -440,7 +440,7 @@ var require_anchors = __commonJS((exports) => {
440
440
  exports.findNewAnchor = findNewAnchor;
441
441
  });
442
442
 
443
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/applyReviver.js
443
+ // node_modules/yaml/dist/doc/applyReviver.js
444
444
  var require_applyReviver = __commonJS((exports) => {
445
445
  function applyReviver(reviver, obj, key, val) {
446
446
  if (val && typeof val === "object") {
@@ -487,7 +487,7 @@ var require_applyReviver = __commonJS((exports) => {
487
487
  exports.applyReviver = applyReviver;
488
488
  });
489
489
 
490
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/toJS.js
490
+ // node_modules/yaml/dist/nodes/toJS.js
491
491
  var require_toJS = __commonJS((exports) => {
492
492
  var identity = require_identity();
493
493
  function toJS(value, arg, ctx) {
@@ -514,7 +514,7 @@ var require_toJS = __commonJS((exports) => {
514
514
  exports.toJS = toJS;
515
515
  });
516
516
 
517
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Node.js
517
+ // node_modules/yaml/dist/nodes/Node.js
518
518
  var require_Node = __commonJS((exports) => {
519
519
  var applyReviver = require_applyReviver();
520
520
  var identity = require_identity();
@@ -551,7 +551,7 @@ var require_Node = __commonJS((exports) => {
551
551
  exports.NodeBase = NodeBase;
552
552
  });
553
553
 
554
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Alias.js
554
+ // node_modules/yaml/dist/nodes/Alias.js
555
555
  var require_Alias = __commonJS((exports) => {
556
556
  var anchors = require_anchors();
557
557
  var visit = require_visit();
@@ -659,7 +659,7 @@ var require_Alias = __commonJS((exports) => {
659
659
  exports.Alias = Alias;
660
660
  });
661
661
 
662
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Scalar.js
662
+ // node_modules/yaml/dist/nodes/Scalar.js
663
663
  var require_Scalar = __commonJS((exports) => {
664
664
  var identity = require_identity();
665
665
  var Node = require_Node();
@@ -687,7 +687,7 @@ var require_Scalar = __commonJS((exports) => {
687
687
  exports.isScalarValue = isScalarValue;
688
688
  });
689
689
 
690
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/createNode.js
690
+ // node_modules/yaml/dist/doc/createNode.js
691
691
  var require_createNode = __commonJS((exports) => {
692
692
  var Alias = require_Alias();
693
693
  var identity = require_identity();
@@ -759,7 +759,7 @@ var require_createNode = __commonJS((exports) => {
759
759
  exports.createNode = createNode;
760
760
  });
761
761
 
762
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Collection.js
762
+ // node_modules/yaml/dist/nodes/Collection.js
763
763
  var require_Collection = __commonJS((exports) => {
764
764
  var createNode = require_createNode();
765
765
  var identity = require_identity();
@@ -874,7 +874,7 @@ var require_Collection = __commonJS((exports) => {
874
874
  exports.isEmptyPath = isEmptyPath;
875
875
  });
876
876
 
877
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyComment.js
877
+ // node_modules/yaml/dist/stringify/stringifyComment.js
878
878
  var require_stringifyComment = __commonJS((exports) => {
879
879
  var stringifyComment = (str) => str.replace(/^(?!$)(?: $)?/gm, "#");
880
880
  function indentComment(comment, indent) {
@@ -891,7 +891,7 @@ var require_stringifyComment = __commonJS((exports) => {
891
891
  exports.stringifyComment = stringifyComment;
892
892
  });
893
893
 
894
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/foldFlowLines.js
894
+ // node_modules/yaml/dist/stringify/foldFlowLines.js
895
895
  var require_foldFlowLines = __commonJS((exports) => {
896
896
  var FOLD_FLOW = "flow";
897
897
  var FOLD_BLOCK = "block";
@@ -1028,7 +1028,7 @@ ${indent}${text.slice(fold + 1, end2)}`;
1028
1028
  exports.foldFlowLines = foldFlowLines;
1029
1029
  });
1030
1030
 
1031
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyString.js
1031
+ // node_modules/yaml/dist/stringify/stringifyString.js
1032
1032
  var require_stringifyString = __commonJS((exports) => {
1033
1033
  var Scalar = require_Scalar();
1034
1034
  var foldFlowLines = require_foldFlowLines();
@@ -1326,7 +1326,7 @@ ${indent}`);
1326
1326
  exports.stringifyString = stringifyString;
1327
1327
  });
1328
1328
 
1329
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringify.js
1329
+ // node_modules/yaml/dist/stringify/stringify.js
1330
1330
  var require_stringify = __commonJS((exports) => {
1331
1331
  var anchors = require_anchors();
1332
1332
  var identity = require_identity();
@@ -1447,7 +1447,7 @@ ${ctx.indent}${str}`;
1447
1447
  exports.stringify = stringify;
1448
1448
  });
1449
1449
 
1450
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyPair.js
1450
+ // node_modules/yaml/dist/stringify/stringifyPair.js
1451
1451
  var require_stringifyPair = __commonJS((exports) => {
1452
1452
  var identity = require_identity();
1453
1453
  var Scalar = require_Scalar();
@@ -1583,7 +1583,7 @@ ${ctx.indent}`;
1583
1583
  exports.stringifyPair = stringifyPair;
1584
1584
  });
1585
1585
 
1586
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/log.js
1586
+ // node_modules/yaml/dist/log.js
1587
1587
  var require_log = __commonJS((exports) => {
1588
1588
  var node_process = __require("process");
1589
1589
  function debug(logLevel, ...messages) {
@@ -1602,7 +1602,7 @@ var require_log = __commonJS((exports) => {
1602
1602
  exports.warn = warn;
1603
1603
  });
1604
1604
 
1605
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/merge.js
1605
+ // node_modules/yaml/dist/schema/yaml-1.1/merge.js
1606
1606
  var require_merge = __commonJS((exports) => {
1607
1607
  var identity = require_identity();
1608
1608
  var Scalar = require_Scalar();
@@ -1656,7 +1656,7 @@ var require_merge = __commonJS((exports) => {
1656
1656
  exports.merge = merge;
1657
1657
  });
1658
1658
 
1659
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/addPairToJSMap.js
1659
+ // node_modules/yaml/dist/nodes/addPairToJSMap.js
1660
1660
  var require_addPairToJSMap = __commonJS((exports) => {
1661
1661
  var log = require_log();
1662
1662
  var merge = require_merge();
@@ -1717,7 +1717,7 @@ var require_addPairToJSMap = __commonJS((exports) => {
1717
1717
  exports.addPairToJSMap = addPairToJSMap;
1718
1718
  });
1719
1719
 
1720
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/Pair.js
1720
+ // node_modules/yaml/dist/nodes/Pair.js
1721
1721
  var require_Pair = __commonJS((exports) => {
1722
1722
  var createNode = require_createNode();
1723
1723
  var stringifyPair = require_stringifyPair();
@@ -1755,7 +1755,7 @@ var require_Pair = __commonJS((exports) => {
1755
1755
  exports.createPair = createPair;
1756
1756
  });
1757
1757
 
1758
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyCollection.js
1758
+ // node_modules/yaml/dist/stringify/stringifyCollection.js
1759
1759
  var require_stringifyCollection = __commonJS((exports) => {
1760
1760
  var identity = require_identity();
1761
1761
  var stringify = require_stringify();
@@ -1907,7 +1907,7 @@ ${indent}${end}`;
1907
1907
  exports.stringifyCollection = stringifyCollection;
1908
1908
  });
1909
1909
 
1910
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/YAMLMap.js
1910
+ // node_modules/yaml/dist/nodes/YAMLMap.js
1911
1911
  var require_YAMLMap = __commonJS((exports) => {
1912
1912
  var stringifyCollection = require_stringifyCollection();
1913
1913
  var addPairToJSMap = require_addPairToJSMap();
@@ -2034,7 +2034,7 @@ var require_YAMLMap = __commonJS((exports) => {
2034
2034
  exports.findPair = findPair;
2035
2035
  });
2036
2036
 
2037
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/map.js
2037
+ // node_modules/yaml/dist/schema/common/map.js
2038
2038
  var require_map = __commonJS((exports) => {
2039
2039
  var identity = require_identity();
2040
2040
  var YAMLMap = require_YAMLMap();
@@ -2053,7 +2053,7 @@ var require_map = __commonJS((exports) => {
2053
2053
  exports.map = map;
2054
2054
  });
2055
2055
 
2056
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/YAMLSeq.js
2056
+ // node_modules/yaml/dist/nodes/YAMLSeq.js
2057
2057
  var require_YAMLSeq = __commonJS((exports) => {
2058
2058
  var createNode = require_createNode();
2059
2059
  var stringifyCollection = require_stringifyCollection();
@@ -2146,7 +2146,7 @@ var require_YAMLSeq = __commonJS((exports) => {
2146
2146
  exports.YAMLSeq = YAMLSeq;
2147
2147
  });
2148
2148
 
2149
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/seq.js
2149
+ // node_modules/yaml/dist/schema/common/seq.js
2150
2150
  var require_seq = __commonJS((exports) => {
2151
2151
  var identity = require_identity();
2152
2152
  var YAMLSeq = require_YAMLSeq();
@@ -2165,7 +2165,7 @@ var require_seq = __commonJS((exports) => {
2165
2165
  exports.seq = seq;
2166
2166
  });
2167
2167
 
2168
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/string.js
2168
+ // node_modules/yaml/dist/schema/common/string.js
2169
2169
  var require_string = __commonJS((exports) => {
2170
2170
  var stringifyString = require_stringifyString();
2171
2171
  var string = {
@@ -2181,7 +2181,7 @@ var require_string = __commonJS((exports) => {
2181
2181
  exports.string = string;
2182
2182
  });
2183
2183
 
2184
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/common/null.js
2184
+ // node_modules/yaml/dist/schema/common/null.js
2185
2185
  var require_null = __commonJS((exports) => {
2186
2186
  var Scalar = require_Scalar();
2187
2187
  var nullTag = {
@@ -2196,7 +2196,7 @@ var require_null = __commonJS((exports) => {
2196
2196
  exports.nullTag = nullTag;
2197
2197
  });
2198
2198
 
2199
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/bool.js
2199
+ // node_modules/yaml/dist/schema/core/bool.js
2200
2200
  var require_bool = __commonJS((exports) => {
2201
2201
  var Scalar = require_Scalar();
2202
2202
  var boolTag = {
@@ -2217,7 +2217,7 @@ var require_bool = __commonJS((exports) => {
2217
2217
  exports.boolTag = boolTag;
2218
2218
  });
2219
2219
 
2220
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyNumber.js
2220
+ // node_modules/yaml/dist/stringify/stringifyNumber.js
2221
2221
  var require_stringifyNumber = __commonJS((exports) => {
2222
2222
  function stringifyNumber({ format, minFractionDigits, tag, value }) {
2223
2223
  if (typeof value === "bigint")
@@ -2241,7 +2241,7 @@ var require_stringifyNumber = __commonJS((exports) => {
2241
2241
  exports.stringifyNumber = stringifyNumber;
2242
2242
  });
2243
2243
 
2244
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/float.js
2244
+ // node_modules/yaml/dist/schema/core/float.js
2245
2245
  var require_float = __commonJS((exports) => {
2246
2246
  var Scalar = require_Scalar();
2247
2247
  var stringifyNumber = require_stringifyNumber();
@@ -2284,7 +2284,7 @@ var require_float = __commonJS((exports) => {
2284
2284
  exports.floatNaN = floatNaN;
2285
2285
  });
2286
2286
 
2287
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/int.js
2287
+ // node_modules/yaml/dist/schema/core/int.js
2288
2288
  var require_int = __commonJS((exports) => {
2289
2289
  var stringifyNumber = require_stringifyNumber();
2290
2290
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -2326,7 +2326,7 @@ var require_int = __commonJS((exports) => {
2326
2326
  exports.intOct = intOct;
2327
2327
  });
2328
2328
 
2329
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/core/schema.js
2329
+ // node_modules/yaml/dist/schema/core/schema.js
2330
2330
  var require_schema = __commonJS((exports) => {
2331
2331
  var map = require_map();
2332
2332
  var _null = require_null();
@@ -2351,7 +2351,7 @@ var require_schema = __commonJS((exports) => {
2351
2351
  exports.schema = schema;
2352
2352
  });
2353
2353
 
2354
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/json/schema.js
2354
+ // node_modules/yaml/dist/schema/json/schema.js
2355
2355
  var require_schema2 = __commonJS((exports) => {
2356
2356
  var Scalar = require_Scalar();
2357
2357
  var map = require_map();
@@ -2415,7 +2415,7 @@ var require_schema2 = __commonJS((exports) => {
2415
2415
  exports.schema = schema;
2416
2416
  });
2417
2417
 
2418
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/binary.js
2418
+ // node_modules/yaml/dist/schema/yaml-1.1/binary.js
2419
2419
  var require_binary = __commonJS((exports) => {
2420
2420
  var node_buffer = __require("buffer");
2421
2421
  var Scalar = require_Scalar();
@@ -2470,7 +2470,7 @@ var require_binary = __commonJS((exports) => {
2470
2470
  exports.binary = binary;
2471
2471
  });
2472
2472
 
2473
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/pairs.js
2473
+ // node_modules/yaml/dist/schema/yaml-1.1/pairs.js
2474
2474
  var require_pairs = __commonJS((exports) => {
2475
2475
  var identity = require_identity();
2476
2476
  var Pair = require_Pair();
@@ -2545,7 +2545,7 @@ ${cn.comment}` : item.comment;
2545
2545
  exports.resolvePairs = resolvePairs;
2546
2546
  });
2547
2547
 
2548
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/omap.js
2548
+ // node_modules/yaml/dist/schema/yaml-1.1/omap.js
2549
2549
  var require_omap = __commonJS((exports) => {
2550
2550
  var identity = require_identity();
2551
2551
  var toJS = require_toJS();
@@ -2617,7 +2617,7 @@ var require_omap = __commonJS((exports) => {
2617
2617
  exports.omap = omap;
2618
2618
  });
2619
2619
 
2620
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/bool.js
2620
+ // node_modules/yaml/dist/schema/yaml-1.1/bool.js
2621
2621
  var require_bool2 = __commonJS((exports) => {
2622
2622
  var Scalar = require_Scalar();
2623
2623
  function boolStringify({ value, source }, ctx) {
@@ -2646,7 +2646,7 @@ var require_bool2 = __commonJS((exports) => {
2646
2646
  exports.trueTag = trueTag;
2647
2647
  });
2648
2648
 
2649
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/float.js
2649
+ // node_modules/yaml/dist/schema/yaml-1.1/float.js
2650
2650
  var require_float2 = __commonJS((exports) => {
2651
2651
  var Scalar = require_Scalar();
2652
2652
  var stringifyNumber = require_stringifyNumber();
@@ -2692,7 +2692,7 @@ var require_float2 = __commonJS((exports) => {
2692
2692
  exports.floatNaN = floatNaN;
2693
2693
  });
2694
2694
 
2695
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/int.js
2695
+ // node_modules/yaml/dist/schema/yaml-1.1/int.js
2696
2696
  var require_int2 = __commonJS((exports) => {
2697
2697
  var stringifyNumber = require_stringifyNumber();
2698
2698
  var intIdentify = (value) => typeof value === "bigint" || Number.isInteger(value);
@@ -2768,7 +2768,7 @@ var require_int2 = __commonJS((exports) => {
2768
2768
  exports.intOct = intOct;
2769
2769
  });
2770
2770
 
2771
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/set.js
2771
+ // node_modules/yaml/dist/schema/yaml-1.1/set.js
2772
2772
  var require_set = __commonJS((exports) => {
2773
2773
  var identity = require_identity();
2774
2774
  var Pair = require_Pair();
@@ -2851,7 +2851,7 @@ var require_set = __commonJS((exports) => {
2851
2851
  exports.set = set;
2852
2852
  });
2853
2853
 
2854
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
2854
+ // node_modules/yaml/dist/schema/yaml-1.1/timestamp.js
2855
2855
  var require_timestamp = __commonJS((exports) => {
2856
2856
  var stringifyNumber = require_stringifyNumber();
2857
2857
  function parseSexagesimal(str, asBigInt) {
@@ -2933,7 +2933,7 @@ var require_timestamp = __commonJS((exports) => {
2933
2933
  exports.timestamp = timestamp;
2934
2934
  });
2935
2935
 
2936
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/yaml-1.1/schema.js
2936
+ // node_modules/yaml/dist/schema/yaml-1.1/schema.js
2937
2937
  var require_schema3 = __commonJS((exports) => {
2938
2938
  var map = require_map();
2939
2939
  var _null = require_null();
@@ -2974,7 +2974,7 @@ var require_schema3 = __commonJS((exports) => {
2974
2974
  exports.schema = schema;
2975
2975
  });
2976
2976
 
2977
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/tags.js
2977
+ // node_modules/yaml/dist/schema/tags.js
2978
2978
  var require_tags = __commonJS((exports) => {
2979
2979
  var map = require_map();
2980
2980
  var _null = require_null();
@@ -3065,7 +3065,7 @@ var require_tags = __commonJS((exports) => {
3065
3065
  exports.getTags = getTags;
3066
3066
  });
3067
3067
 
3068
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/schema/Schema.js
3068
+ // node_modules/yaml/dist/schema/Schema.js
3069
3069
  var require_Schema = __commonJS((exports) => {
3070
3070
  var identity = require_identity();
3071
3071
  var map = require_map();
@@ -3095,7 +3095,7 @@ var require_Schema = __commonJS((exports) => {
3095
3095
  exports.Schema = Schema;
3096
3096
  });
3097
3097
 
3098
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/stringify/stringifyDocument.js
3098
+ // node_modules/yaml/dist/stringify/stringifyDocument.js
3099
3099
  var require_stringifyDocument = __commonJS((exports) => {
3100
3100
  var identity = require_identity();
3101
3101
  var stringify = require_stringify();
@@ -3175,7 +3175,7 @@ var require_stringifyDocument = __commonJS((exports) => {
3175
3175
  exports.stringifyDocument = stringifyDocument;
3176
3176
  });
3177
3177
 
3178
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/doc/Document.js
3178
+ // node_modules/yaml/dist/doc/Document.js
3179
3179
  var require_Document = __commonJS((exports) => {
3180
3180
  var Alias = require_Alias();
3181
3181
  var Collection = require_Collection();
@@ -3410,7 +3410,7 @@ var require_Document = __commonJS((exports) => {
3410
3410
  exports.Document = Document;
3411
3411
  });
3412
3412
 
3413
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/errors.js
3413
+ // node_modules/yaml/dist/errors.js
3414
3414
  var require_errors = __commonJS((exports) => {
3415
3415
  class YAMLError extends Error {
3416
3416
  constructor(name, pos, code, message) {
@@ -3475,7 +3475,7 @@ ${pointer}
3475
3475
  exports.prettifyError = prettifyError;
3476
3476
  });
3477
3477
 
3478
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-props.js
3478
+ // node_modules/yaml/dist/compose/resolve-props.js
3479
3479
  var require_resolve_props = __commonJS((exports) => {
3480
3480
  function resolveProps(tokens, { flow, indicator, next, offset, onError, parentIndent, startOnNewline }) {
3481
3481
  let spaceBefore = false;
@@ -3605,7 +3605,7 @@ var require_resolve_props = __commonJS((exports) => {
3605
3605
  exports.resolveProps = resolveProps;
3606
3606
  });
3607
3607
 
3608
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-contains-newline.js
3608
+ // node_modules/yaml/dist/compose/util-contains-newline.js
3609
3609
  var require_util_contains_newline = __commonJS((exports) => {
3610
3610
  function containsNewline(key) {
3611
3611
  if (!key)
@@ -3645,7 +3645,7 @@ var require_util_contains_newline = __commonJS((exports) => {
3645
3645
  exports.containsNewline = containsNewline;
3646
3646
  });
3647
3647
 
3648
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-flow-indent-check.js
3648
+ // node_modules/yaml/dist/compose/util-flow-indent-check.js
3649
3649
  var require_util_flow_indent_check = __commonJS((exports) => {
3650
3650
  var utilContainsNewline = require_util_contains_newline();
3651
3651
  function flowIndentCheck(indent, fc, onError) {
@@ -3660,7 +3660,7 @@ var require_util_flow_indent_check = __commonJS((exports) => {
3660
3660
  exports.flowIndentCheck = flowIndentCheck;
3661
3661
  });
3662
3662
 
3663
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-map-includes.js
3663
+ // node_modules/yaml/dist/compose/util-map-includes.js
3664
3664
  var require_util_map_includes = __commonJS((exports) => {
3665
3665
  var identity = require_identity();
3666
3666
  function mapIncludes(ctx, items, search) {
@@ -3673,7 +3673,7 @@ var require_util_map_includes = __commonJS((exports) => {
3673
3673
  exports.mapIncludes = mapIncludes;
3674
3674
  });
3675
3675
 
3676
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-block-map.js
3676
+ // node_modules/yaml/dist/compose/resolve-block-map.js
3677
3677
  var require_resolve_block_map = __commonJS((exports) => {
3678
3678
  var Pair = require_Pair();
3679
3679
  var YAMLMap = require_YAMLMap();
@@ -3780,7 +3780,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3780
3780
  exports.resolveBlockMap = resolveBlockMap;
3781
3781
  });
3782
3782
 
3783
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-block-seq.js
3783
+ // node_modules/yaml/dist/compose/resolve-block-seq.js
3784
3784
  var require_resolve_block_seq = __commonJS((exports) => {
3785
3785
  var YAMLSeq = require_YAMLSeq();
3786
3786
  var resolveProps = require_resolve_props();
@@ -3828,7 +3828,7 @@ var require_resolve_block_seq = __commonJS((exports) => {
3828
3828
  exports.resolveBlockSeq = resolveBlockSeq;
3829
3829
  });
3830
3830
 
3831
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-end.js
3831
+ // node_modules/yaml/dist/compose/resolve-end.js
3832
3832
  var require_resolve_end = __commonJS((exports) => {
3833
3833
  function resolveEnd(end, offset, reqSpace, onError) {
3834
3834
  let comment = "";
@@ -3868,7 +3868,7 @@ var require_resolve_end = __commonJS((exports) => {
3868
3868
  exports.resolveEnd = resolveEnd;
3869
3869
  });
3870
3870
 
3871
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-flow-collection.js
3871
+ // node_modules/yaml/dist/compose/resolve-flow-collection.js
3872
3872
  var require_resolve_flow_collection = __commonJS((exports) => {
3873
3873
  var identity = require_identity();
3874
3874
  var Pair = require_Pair();
@@ -4059,7 +4059,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
4059
4059
  exports.resolveFlowCollection = resolveFlowCollection;
4060
4060
  });
4061
4061
 
4062
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-collection.js
4062
+ // node_modules/yaml/dist/compose/compose-collection.js
4063
4063
  var require_compose_collection = __commonJS((exports) => {
4064
4064
  var identity = require_identity();
4065
4065
  var Scalar = require_Scalar();
@@ -4121,7 +4121,7 @@ var require_compose_collection = __commonJS((exports) => {
4121
4121
  exports.composeCollection = composeCollection;
4122
4122
  });
4123
4123
 
4124
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-block-scalar.js
4124
+ // node_modules/yaml/dist/compose/resolve-block-scalar.js
4125
4125
  var require_resolve_block_scalar = __commonJS((exports) => {
4126
4126
  var Scalar = require_Scalar();
4127
4127
  function resolveBlockScalar(ctx, scalar, onError) {
@@ -4314,7 +4314,7 @@ var require_resolve_block_scalar = __commonJS((exports) => {
4314
4314
  exports.resolveBlockScalar = resolveBlockScalar;
4315
4315
  });
4316
4316
 
4317
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/resolve-flow-scalar.js
4317
+ // node_modules/yaml/dist/compose/resolve-flow-scalar.js
4318
4318
  var require_resolve_flow_scalar = __commonJS((exports) => {
4319
4319
  var Scalar = require_Scalar();
4320
4320
  var resolveEnd = require_resolve_end();
@@ -4530,7 +4530,7 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
4530
4530
  exports.resolveFlowScalar = resolveFlowScalar;
4531
4531
  });
4532
4532
 
4533
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-scalar.js
4533
+ // node_modules/yaml/dist/compose/compose-scalar.js
4534
4534
  var require_compose_scalar = __commonJS((exports) => {
4535
4535
  var identity = require_identity();
4536
4536
  var Scalar = require_Scalar();
@@ -4608,7 +4608,7 @@ var require_compose_scalar = __commonJS((exports) => {
4608
4608
  exports.composeScalar = composeScalar;
4609
4609
  });
4610
4610
 
4611
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/util-empty-scalar-position.js
4611
+ // node_modules/yaml/dist/compose/util-empty-scalar-position.js
4612
4612
  var require_util_empty_scalar_position = __commonJS((exports) => {
4613
4613
  function emptyScalarPosition(offset, before, pos) {
4614
4614
  if (before) {
@@ -4635,7 +4635,7 @@ var require_util_empty_scalar_position = __commonJS((exports) => {
4635
4635
  exports.emptyScalarPosition = emptyScalarPosition;
4636
4636
  });
4637
4637
 
4638
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-node.js
4638
+ // node_modules/yaml/dist/compose/compose-node.js
4639
4639
  var require_compose_node = __commonJS((exports) => {
4640
4640
  var Alias = require_Alias();
4641
4641
  var identity = require_identity();
@@ -4738,7 +4738,7 @@ var require_compose_node = __commonJS((exports) => {
4738
4738
  exports.composeNode = composeNode;
4739
4739
  });
4740
4740
 
4741
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/compose-doc.js
4741
+ // node_modules/yaml/dist/compose/compose-doc.js
4742
4742
  var require_compose_doc = __commonJS((exports) => {
4743
4743
  var Document = require_Document();
4744
4744
  var composeNode = require_compose_node();
@@ -4778,7 +4778,7 @@ var require_compose_doc = __commonJS((exports) => {
4778
4778
  exports.composeDoc = composeDoc;
4779
4779
  });
4780
4780
 
4781
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/compose/composer.js
4781
+ // node_modules/yaml/dist/compose/composer.js
4782
4782
  var require_composer = __commonJS((exports) => {
4783
4783
  var node_process = __require("process");
4784
4784
  var directives = require_directives();
@@ -4967,7 +4967,7 @@ ${end.comment}` : end.comment;
4967
4967
  exports.Composer = Composer;
4968
4968
  });
4969
4969
 
4970
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst-scalar.js
4970
+ // node_modules/yaml/dist/parse/cst-scalar.js
4971
4971
  var require_cst_scalar = __commonJS((exports) => {
4972
4972
  var resolveBlockScalar = require_resolve_block_scalar();
4973
4973
  var resolveFlowScalar = require_resolve_flow_scalar();
@@ -5157,7 +5157,7 @@ var require_cst_scalar = __commonJS((exports) => {
5157
5157
  exports.setScalarValue = setScalarValue;
5158
5158
  });
5159
5159
 
5160
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst-stringify.js
5160
+ // node_modules/yaml/dist/parse/cst-stringify.js
5161
5161
  var require_cst_stringify = __commonJS((exports) => {
5162
5162
  var stringify = (cst) => ("type" in cst) ? stringifyToken(cst) : stringifyItem(cst);
5163
5163
  function stringifyToken(token) {
@@ -5215,7 +5215,7 @@ var require_cst_stringify = __commonJS((exports) => {
5215
5215
  exports.stringify = stringify;
5216
5216
  });
5217
5217
 
5218
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst-visit.js
5218
+ // node_modules/yaml/dist/parse/cst-visit.js
5219
5219
  var require_cst_visit = __commonJS((exports) => {
5220
5220
  var BREAK = Symbol("break visit");
5221
5221
  var SKIP = Symbol("skip children");
@@ -5274,7 +5274,7 @@ var require_cst_visit = __commonJS((exports) => {
5274
5274
  exports.visit = visit;
5275
5275
  });
5276
5276
 
5277
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/cst.js
5277
+ // node_modules/yaml/dist/parse/cst.js
5278
5278
  var require_cst = __commonJS((exports) => {
5279
5279
  var cstScalar = require_cst_scalar();
5280
5280
  var cstStringify = require_cst_stringify();
@@ -5375,7 +5375,7 @@ var require_cst = __commonJS((exports) => {
5375
5375
  exports.tokenType = tokenType;
5376
5376
  });
5377
5377
 
5378
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/lexer.js
5378
+ // node_modules/yaml/dist/parse/lexer.js
5379
5379
  var require_lexer = __commonJS((exports) => {
5380
5380
  var cst = require_cst();
5381
5381
  function isEmpty(ch) {
@@ -5961,7 +5961,7 @@ var require_lexer = __commonJS((exports) => {
5961
5961
  exports.Lexer = Lexer;
5962
5962
  });
5963
5963
 
5964
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/line-counter.js
5964
+ // node_modules/yaml/dist/parse/line-counter.js
5965
5965
  var require_line_counter = __commonJS((exports) => {
5966
5966
  class LineCounter {
5967
5967
  constructor() {
@@ -5989,7 +5989,7 @@ var require_line_counter = __commonJS((exports) => {
5989
5989
  exports.LineCounter = LineCounter;
5990
5990
  });
5991
5991
 
5992
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/parse/parser.js
5992
+ // node_modules/yaml/dist/parse/parser.js
5993
5993
  var require_parser = __commonJS((exports) => {
5994
5994
  var node_process = __require("process");
5995
5995
  var cst = require_cst();
@@ -6838,7 +6838,7 @@ var require_parser = __commonJS((exports) => {
6838
6838
  exports.Parser = Parser;
6839
6839
  });
6840
6840
 
6841
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/public-api.js
6841
+ // node_modules/yaml/dist/public-api.js
6842
6842
  var require_public_api = __commonJS((exports) => {
6843
6843
  var composer = require_composer();
6844
6844
  var Document = require_Document();
@@ -6932,7 +6932,7 @@ var require_public_api = __commonJS((exports) => {
6932
6932
  exports.stringify = stringify;
6933
6933
  });
6934
6934
 
6935
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/index.js
6935
+ // node_modules/yaml/dist/index.js
6936
6936
  var composer, Document, Schema, errors, Alias, identity, Pair, Scalar, YAMLMap, YAMLSeq, cst, lexer, lineCounter, parser, publicApi, visit, $Composer, $Document, $Schema, $YAMLError, $YAMLParseError, $YAMLWarning, $Alias, $isAlias, $isCollection, $isDocument, $isMap, $isNode, $isPair, $isScalar, $isSeq, $Pair, $Scalar, $YAMLMap, $YAMLSeq, $Lexer, $LineCounter, $Parser, $parse, $parseAllDocuments, $parseDocument, $stringify, $visit, $visitAsync;
6937
6937
  var init_dist = __esm(() => {
6938
6938
  composer = require_composer();
@@ -6981,7 +6981,7 @@ var init_dist = __esm(() => {
6981
6981
  $visitAsync = visit.visitAsync;
6982
6982
  });
6983
6983
 
6984
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/util.js
6984
+ // node_modules/zod/v3/helpers/util.js
6985
6985
  var util, objectUtil, ZodParsedType, getParsedType = (data) => {
6986
6986
  const t = typeof data;
6987
6987
  switch (t) {
@@ -7112,7 +7112,7 @@ var init_util = __esm(() => {
7112
7112
  ]);
7113
7113
  });
7114
7114
 
7115
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/ZodError.js
7115
+ // node_modules/zod/v3/ZodError.js
7116
7116
  var ZodIssueCode, quotelessJson = (obj) => {
7117
7117
  const json = JSON.stringify(obj, null, 2);
7118
7118
  return json.replace(/"([^"]+)":/g, "$1:");
@@ -7233,7 +7233,7 @@ var init_ZodError = __esm(() => {
7233
7233
  };
7234
7234
  });
7235
7235
 
7236
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/locales/en.js
7236
+ // node_modules/zod/v3/locales/en.js
7237
7237
  var errorMap = (issue, _ctx) => {
7238
7238
  let message;
7239
7239
  switch (issue.code) {
@@ -7340,7 +7340,7 @@ var init_en = __esm(() => {
7340
7340
  en_default = errorMap;
7341
7341
  });
7342
7342
 
7343
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/errors.js
7343
+ // node_modules/zod/v3/errors.js
7344
7344
  function setErrorMap(map) {
7345
7345
  overrideErrorMap = map;
7346
7346
  }
@@ -7353,7 +7353,7 @@ var init_errors = __esm(() => {
7353
7353
  overrideErrorMap = en_default;
7354
7354
  });
7355
7355
 
7356
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
7356
+ // node_modules/zod/v3/helpers/parseUtil.js
7357
7357
  function addIssueToContext(ctx, issueData) {
7358
7358
  const overrideMap = getErrorMap();
7359
7359
  const issue = makeIssue({
@@ -7458,10 +7458,10 @@ var init_parseUtil = __esm(() => {
7458
7458
  });
7459
7459
  });
7460
7460
 
7461
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/typeAliases.js
7461
+ // node_modules/zod/v3/helpers/typeAliases.js
7462
7462
  var init_typeAliases = () => {};
7463
7463
 
7464
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
7464
+ // node_modules/zod/v3/helpers/errorUtil.js
7465
7465
  var errorUtil;
7466
7466
  var init_errorUtil = __esm(() => {
7467
7467
  (function(errorUtil2) {
@@ -7470,7 +7470,7 @@ var init_errorUtil = __esm(() => {
7470
7470
  })(errorUtil || (errorUtil = {}));
7471
7471
  });
7472
7472
 
7473
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/types.js
7473
+ // node_modules/zod/v3/types.js
7474
7474
  class ParseInputLazyPath {
7475
7475
  constructor(parent, value, path, key) {
7476
7476
  this._cachedPath = [];
@@ -10821,7 +10821,7 @@ var init_types = __esm(() => {
10821
10821
  NEVER = INVALID;
10822
10822
  });
10823
10823
 
10824
- // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/external.js
10824
+ // node_modules/zod/v3/external.js
10825
10825
  var exports_external = {};
10826
10826
  __export(exports_external, {
10827
10827
  void: () => voidType,
@@ -10941,7 +10941,7 @@ var init_external = __esm(() => {
10941
10941
  init_ZodError();
10942
10942
  });
10943
10943
 
10944
- // node_modules/.bun/zod@3.25.76/node_modules/zod/index.js
10944
+ // node_modules/zod/index.js
10945
10945
  var init_zod = __esm(() => {
10946
10946
  init_external();
10947
10947
  init_external();
@@ -11224,7 +11224,7 @@ var init_schema = __esm(() => {
11224
11224
  }).optional()
11225
11225
  });
11226
11226
  VaultConfigSchema = exports_external.object({
11227
- path: exports_external.string().default("~/.switchroom/vault.enc").describe("Path to encrypted vault file"),
11227
+ path: exports_external.string().default("~/.switchroom/vault/vault.enc").describe("Path to encrypted vault file. v0.7.12+ canonical default is " + "`~/.switchroom/vault/vault.enc` (parent-dir bind-mount enables " + "atomic-rename writes from the broker container). Older installs " + "with `~/.switchroom/vault.enc` are auto-migrated on `switchroom " + "apply`; the legacy path becomes a symlink for v0.7.10/.11 CLI " + "compatibility (sunset in v0.7.14)."),
11228
11228
  broker: exports_external.object({
11229
11229
  socket: exports_external.string().default("~/.switchroom/vault-broker.sock").describe("Unix domain socket path for the vault-broker daemon"),
11230
11230
  enabled: exports_external.boolean().default(true).describe("Whether to start the vault-broker daemon on agent launch"),
@@ -11257,7 +11257,7 @@ var init_schema = __esm(() => {
11257
11257
  });
11258
11258
 
11259
11259
  // src/config/paths.ts
11260
- import { existsSync as existsSync2 } from "node:fs";
11260
+ import { existsSync as existsSync4 } from "node:fs";
11261
11261
  import { resolve as resolve2 } from "node:path";
11262
11262
  function home() {
11263
11263
  return process.env.HOME ?? "/root";
@@ -11269,9 +11269,9 @@ function resolveDualPath(pathStr) {
11269
11269
  const absolute = resolve2(h, rest);
11270
11270
  if (rest.startsWith(`${DEFAULT_STATE_DIR}/`)) {
11271
11271
  const frag = rest.slice(DEFAULT_STATE_DIR.length + 1);
11272
- if (!existsSync2(absolute)) {
11272
+ if (!existsSync4(absolute)) {
11273
11273
  const legacy = resolve2(h, LEGACY_STATE_DIR, frag);
11274
- if (existsSync2(legacy))
11274
+ if (existsSync4(legacy))
11275
11275
  return legacy;
11276
11276
  }
11277
11277
  }
@@ -11291,7 +11291,7 @@ __export(exports_loader, {
11291
11291
  findConfigFile: () => findConfigFile,
11292
11292
  ConfigError: () => ConfigError
11293
11293
  });
11294
- import { readFileSync as readFileSync2, existsSync as existsSync3 } from "node:fs";
11294
+ import { readFileSync as readFileSync4, existsSync as existsSync5 } from "node:fs";
11295
11295
  import { homedir } from "node:os";
11296
11296
  import { resolve as resolve3 } from "node:path";
11297
11297
  function formatZodErrors(error) {
@@ -11320,7 +11320,7 @@ function findConfigFile(startDir) {
11320
11320
  resolve3(userDir, "clerk.yml")
11321
11321
  ].filter(Boolean);
11322
11322
  for (const path of searchPaths) {
11323
- if (existsSync3(path)) {
11323
+ if (existsSync5(path)) {
11324
11324
  return path;
11325
11325
  }
11326
11326
  }
@@ -11328,12 +11328,12 @@ function findConfigFile(startDir) {
11328
11328
  }
11329
11329
  function loadConfig(configPath) {
11330
11330
  const filePath = configPath ?? findConfigFile();
11331
- if (!existsSync3(filePath)) {
11331
+ if (!existsSync5(filePath)) {
11332
11332
  throw new ConfigError(`Config file not found: ${filePath}`);
11333
11333
  }
11334
11334
  let raw;
11335
11335
  try {
11336
- raw = readFileSync2(filePath, "utf-8");
11336
+ raw = readFileSync4(filePath, "utf-8");
11337
11337
  } catch (err) {
11338
11338
  throw new ConfigError(`Failed to read config file: ${filePath}`, [
11339
11339
  ` ${err.message}`
@@ -11385,7 +11385,7 @@ var init_loader = __esm(() => {
11385
11385
 
11386
11386
  // src/vault/broker/server.ts
11387
11387
  import * as net from "node:net";
11388
- import { mkdirSync as mkdirSync4, chmodSync as chmodSync3, chownSync, existsSync as existsSync5, readFileSync as readFileSync5, readdirSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3, renameSync as renameSync2 } from "node:fs";
11388
+ import { mkdirSync as mkdirSync5, chmodSync as chmodSync4, chownSync, existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as readdirSync2, unlinkSync as unlinkSync4, writeFileSync as writeFileSync3, renameSync as renameSync3 } from "node:fs";
11389
11389
 
11390
11390
  // src/agents/compose.ts
11391
11391
  import { createHash } from "node:crypto";
@@ -11676,21 +11676,183 @@ function allocateAgentUid(name) {
11676
11676
  }
11677
11677
 
11678
11678
  // src/vault/broker/server.ts
11679
- import { dirname as dirname3, resolve as resolve4 } from "node:path";
11679
+ import { dirname as dirname4, resolve as resolve4, basename as basename3 } from "node:path";
11680
11680
  import * as os3 from "node:os";
11681
11681
  import * as path3 from "node:path";
11682
11682
 
11683
11683
  // src/vault/vault.ts
11684
11684
  import { randomBytes, scryptSync, createCipheriv, createDecipheriv } from "node:crypto";
11685
11685
  import {
11686
- readFileSync,
11686
+ readFileSync as readFileSync2,
11687
11687
  writeFileSync,
11688
- existsSync,
11688
+ existsSync as existsSync2,
11689
11689
  renameSync,
11690
11690
  mkdirSync,
11691
- unlinkSync
11691
+ unlinkSync as unlinkSync2
11692
11692
  } from "node:fs";
11693
11693
  import { dirname, basename, resolve } from "node:path";
11694
+
11695
+ // src/vault/flock.ts
11696
+ import {
11697
+ existsSync,
11698
+ openSync,
11699
+ closeSync,
11700
+ writeSync,
11701
+ fsyncSync,
11702
+ unlinkSync,
11703
+ readFileSync,
11704
+ readdirSync,
11705
+ rmdirSync,
11706
+ statSync,
11707
+ constants as fsConstants
11708
+ } from "node:fs";
11709
+ var DEFAULT_LOCK_RETRY_MS = 5000;
11710
+ function lockPathFor(vaultPath) {
11711
+ return `${vaultPath}.lock`;
11712
+ }
11713
+ function readLockHolder(lockPath) {
11714
+ try {
11715
+ const raw = readFileSync(lockPath, "utf8");
11716
+ const lines = raw.split(`
11717
+ `);
11718
+ const pid = Number.parseInt(lines[0] ?? "", 10);
11719
+ const acquiredAtMs = Number.parseInt(lines[1] ?? "", 10);
11720
+ if (!Number.isFinite(pid) || pid <= 0)
11721
+ return null;
11722
+ if (!Number.isFinite(acquiredAtMs) || acquiredAtMs <= 0)
11723
+ return null;
11724
+ return { pid, acquiredAtMs, argv0: lines[2] ?? "" };
11725
+ } catch {
11726
+ return null;
11727
+ }
11728
+ }
11729
+ function pidIsLive(pid) {
11730
+ if (process.platform === "linux") {
11731
+ return existsSync(`/proc/${pid}`);
11732
+ }
11733
+ try {
11734
+ process.kill(pid, 0);
11735
+ return true;
11736
+ } catch {
11737
+ return false;
11738
+ }
11739
+ }
11740
+ function clearStaleSentinelDir(lockPath) {
11741
+ try {
11742
+ if (!existsSync(lockPath))
11743
+ return true;
11744
+ const s = statSync(lockPath);
11745
+ if (!s.isDirectory())
11746
+ return true;
11747
+ for (const entry of readdirSync(lockPath)) {
11748
+ try {
11749
+ unlinkSync(`${lockPath}/${entry}`);
11750
+ } catch {}
11751
+ }
11752
+ rmdirSync(lockPath);
11753
+ return true;
11754
+ } catch {
11755
+ return false;
11756
+ }
11757
+ }
11758
+ function acquireLock(vaultPath, options = {}) {
11759
+ const budgetMs = options.budgetMs ?? DEFAULT_LOCK_RETRY_MS;
11760
+ const lockPath = lockPathFor(vaultPath);
11761
+ const deadline = Date.now() + budgetMs;
11762
+ const sleepBuf = new Int32Array(new SharedArrayBuffer(4));
11763
+ while (true) {
11764
+ let fd = null;
11765
+ try {
11766
+ fd = openSync(lockPath, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL, 384);
11767
+ } catch (err) {
11768
+ const code = err?.code ?? "";
11769
+ if (code === "EEXIST") {
11770
+ let isDir = false;
11771
+ try {
11772
+ isDir = statSync(lockPath).isDirectory();
11773
+ } catch {}
11774
+ if (isDir) {
11775
+ if (clearStaleSentinelDir(lockPath))
11776
+ continue;
11777
+ }
11778
+ const holder = readLockHolder(lockPath);
11779
+ if (holder && !pidIsLive(holder.pid)) {
11780
+ try {
11781
+ unlinkSync(lockPath);
11782
+ } catch {}
11783
+ continue;
11784
+ }
11785
+ if (Date.now() >= deadline) {
11786
+ throw makeBusyError(vaultPath, lockPath, holder, budgetMs);
11787
+ }
11788
+ Atomics.wait(sleepBuf, 0, 0, 100);
11789
+ continue;
11790
+ } else {
11791
+ throw err;
11792
+ }
11793
+ }
11794
+ try {
11795
+ const meta = `${process.pid}
11796
+ ${Date.now()}
11797
+ ${process.argv[1] ?? ""}
11798
+ `;
11799
+ writeSync(fd, meta);
11800
+ fsyncSync(fd);
11801
+ } catch {
11802
+ try {
11803
+ closeSync(fd);
11804
+ } catch {}
11805
+ try {
11806
+ unlinkSync(lockPath);
11807
+ } catch {}
11808
+ throw new Error(`vault flock: failed to write holder metadata to ${lockPath}`);
11809
+ }
11810
+ const ownedFd = fd;
11811
+ return {
11812
+ release: () => {
11813
+ try {
11814
+ closeSync(ownedFd);
11815
+ } catch {}
11816
+ try {
11817
+ unlinkSync(lockPath);
11818
+ } catch {}
11819
+ }
11820
+ };
11821
+ }
11822
+ }
11823
+
11824
+ class VaultBusyError extends Error {
11825
+ vaultPath;
11826
+ lockPath;
11827
+ holderPid;
11828
+ heldForMs;
11829
+ budgetMs;
11830
+ constructor(message, fields) {
11831
+ super(message);
11832
+ this.name = "VaultBusyError";
11833
+ this.vaultPath = fields.vaultPath;
11834
+ this.lockPath = fields.lockPath;
11835
+ this.holderPid = fields.holderPid;
11836
+ this.heldForMs = fields.heldForMs;
11837
+ this.budgetMs = fields.budgetMs;
11838
+ }
11839
+ }
11840
+ function makeBusyError(vaultPath, lockPath, holder, budgetMs) {
11841
+ const holderPid = holder?.pid ?? null;
11842
+ const heldForMs = holder ? Date.now() - holder.acquiredAtMs : null;
11843
+ const holderClause = holder ? `held by pid ${holder.pid} (acquired ${Math.round((heldForMs ?? 0) / 1000)}s ago)` : "held by another writer (holder PID unreadable — lock file empty or unparseable)";
11844
+ return new VaultBusyError(`vault busy: ${holderClause} at ${lockPath} (retried for ${budgetMs}ms). ` + `Try again in a moment. If the holder process is gone, the next acquirer ` + `will clear the stale lock automatically.`, { vaultPath, lockPath, holderPid, heldForMs, budgetMs });
11845
+ }
11846
+
11847
+ // src/vault/vault.ts
11848
+ var KNOWN_VAULT_ARTIFACT_NAMES = new Set([
11849
+ "vault.enc",
11850
+ "vault.enc.bak",
11851
+ "vault.enc.tmp",
11852
+ "vault.enc.lock",
11853
+ ".vault.enc.symlink-tmp"
11854
+ ]);
11855
+ var SAVE_VAULT_LOCK_RETRY_MS = DEFAULT_LOCK_RETRY_MS;
11694
11856
  var SCRYPT_N = 32768;
11695
11857
  var SCRYPT_R = 8;
11696
11858
  var SCRYPT_P = 1;
@@ -11703,17 +11865,20 @@ function atomicWriteFileSync(path, data, mode) {
11703
11865
  renameSync(tmp, path);
11704
11866
  } catch (err) {
11705
11867
  try {
11706
- if (existsSync(tmp))
11707
- unlinkSync(tmp);
11868
+ if (existsSync2(tmp))
11869
+ unlinkSync2(tmp);
11708
11870
  } catch {}
11709
11871
  throw err;
11710
11872
  }
11711
11873
  }
11712
11874
 
11713
11875
  class VaultError extends Error {
11714
- constructor(message) {
11876
+ cause;
11877
+ constructor(message, options) {
11715
11878
  super(message);
11716
11879
  this.name = "VaultError";
11880
+ if (options?.cause !== undefined)
11881
+ this.cause = options.cause;
11717
11882
  }
11718
11883
  }
11719
11884
  var LEGACY_SCRYPT_N = 16384;
@@ -11759,12 +11924,12 @@ function normalizeSecrets(raw) {
11759
11924
  return out;
11760
11925
  }
11761
11926
  function openVault(passphrase, vaultPath) {
11762
- if (!existsSync(vaultPath)) {
11927
+ if (!existsSync2(vaultPath)) {
11763
11928
  throw new VaultError(`Vault file not found: ${vaultPath}`);
11764
11929
  }
11765
11930
  let vaultFile;
11766
11931
  try {
11767
- vaultFile = JSON.parse(readFileSync(vaultPath, "utf8"));
11932
+ vaultFile = JSON.parse(readFileSync2(vaultPath, "utf8"));
11768
11933
  } catch {
11769
11934
  throw new VaultError(`Failed to read vault file: ${vaultPath}`);
11770
11935
  }
@@ -11786,24 +11951,181 @@ function openVault(passphrase, vaultPath) {
11786
11951
  return normalizeSecrets(vaultData.secrets ?? {});
11787
11952
  }
11788
11953
  function saveVault(passphrase, vaultPath, secrets) {
11789
- if (!existsSync(vaultPath)) {
11954
+ if (!existsSync2(vaultPath)) {
11790
11955
  throw new VaultError(`Vault file not found: ${vaultPath}`);
11791
11956
  }
11792
- let vaultFile;
11957
+ let releaseLock = null;
11958
+ try {
11959
+ releaseLock = acquireLock(vaultPath, { budgetMs: SAVE_VAULT_LOCK_RETRY_MS }).release;
11960
+ } catch (err) {
11961
+ if (err instanceof VaultBusyError) {
11962
+ throw new VaultError(err.message, { cause: err });
11963
+ }
11964
+ throw err;
11965
+ }
11793
11966
  try {
11794
- vaultFile = JSON.parse(readFileSync(vaultPath, "utf8"));
11967
+ let vaultFile;
11968
+ try {
11969
+ vaultFile = JSON.parse(readFileSync2(vaultPath, "utf8"));
11970
+ } catch {
11971
+ throw new VaultError(`Failed to read vault file: ${vaultPath}`);
11972
+ }
11973
+ const salt = Buffer.from(vaultFile.salt, "hex");
11974
+ const key = deriveKey(passphrase, salt, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P });
11975
+ vaultFile.kdf = { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P };
11976
+ const vaultData = { secrets };
11977
+ const { iv, data, tag } = encrypt(key, JSON.stringify(vaultData));
11978
+ vaultFile.iv = iv;
11979
+ vaultFile.data = data;
11980
+ vaultFile.tag = tag;
11981
+ atomicWriteFileSync(vaultPath, JSON.stringify(vaultFile, null, 2), 384);
11982
+ } finally {
11983
+ if (releaseLock !== null) {
11984
+ try {
11985
+ releaseLock();
11986
+ } catch {}
11987
+ }
11988
+ }
11989
+ }
11990
+ function acquireVaultLock(vaultPath) {
11991
+ try {
11992
+ return acquireLock(vaultPath, { budgetMs: SAVE_VAULT_LOCK_RETRY_MS }).release;
11993
+ } catch (err) {
11994
+ if (err instanceof VaultBusyError) {
11995
+ throw new VaultError(err.message, { cause: err });
11996
+ }
11997
+ throw err;
11998
+ }
11999
+ }
12000
+
12001
+ // src/vault/migrate-layout.ts
12002
+ import {
12003
+ copyFileSync,
12004
+ chmodSync,
12005
+ existsSync as existsSync3,
12006
+ fsyncSync as fsyncSync3,
12007
+ lstatSync,
12008
+ mkdirSync as mkdirSync2,
12009
+ openSync as openSync3,
12010
+ closeSync as closeSync3,
12011
+ readFileSync as readFileSync3,
12012
+ renameSync as renameSync2,
12013
+ statSync as statSync2,
12014
+ symlinkSync,
12015
+ unlinkSync as unlinkSync3
12016
+ } from "node:fs";
12017
+ import { createHash as createHash2 } from "node:crypto";
12018
+ import { basename as basename2, dirname as dirname2, join } from "node:path";
12019
+ function vaultLayoutPaths(home) {
12020
+ const switchroomRoot = join(home, ".switchroom");
12021
+ return {
12022
+ oldPath: join(switchroomRoot, "vault.enc"),
12023
+ newPath: join(switchroomRoot, "vault", "vault.enc"),
12024
+ parent: join(switchroomRoot, "vault"),
12025
+ switchroomRoot
12026
+ };
12027
+ }
12028
+ function inspectVaultLayout(home) {
12029
+ return runMigration(home, { dryRun: true });
12030
+ }
12031
+ function runMigration(home, opts) {
12032
+ const { oldPath, newPath, parent, switchroomRoot } = vaultLayoutPaths(home);
12033
+ const lockTarget = existsSync3(newPath) ? newPath : existsSync3(oldPath) ? oldPath : null;
12034
+ const release = !opts.dryRun && lockTarget !== null ? acquireVaultLock(lockTarget) : null;
12035
+ try {
12036
+ const oldStat = lstatSyncOrNull(oldPath);
12037
+ const newExists = existsSync3(newPath);
12038
+ if (oldStat === null && !newExists) {
12039
+ return { kind: "no-vault" };
12040
+ }
12041
+ if (oldStat?.isSymbolicLink() && newExists) {
12042
+ return { kind: "already-migrated" };
12043
+ }
12044
+ if (oldStat?.isFile() && newExists) {
12045
+ const oldHash = sha256File(oldPath);
12046
+ const newHash = sha256File(newPath);
12047
+ if (oldHash === newHash) {
12048
+ if (opts.dryRun)
12049
+ return { kind: "completed-partial" };
12050
+ atomicReplaceWithSymlink(oldPath, "vault/vault.enc");
12051
+ fsyncDir(switchroomRoot);
12052
+ return { kind: "completed-partial" };
12053
+ }
12054
+ const oldRealStat = statSync2(oldPath);
12055
+ const newRealStat = statSync2(newPath);
12056
+ return {
12057
+ kind: "divergent",
12058
+ details: {
12059
+ oldPath,
12060
+ newPath,
12061
+ oldHash,
12062
+ newHash,
12063
+ oldSize: oldRealStat.size,
12064
+ newSize: newRealStat.size,
12065
+ oldMtime: oldRealStat.mtime.toISOString(),
12066
+ newMtime: newRealStat.mtime.toISOString()
12067
+ }
12068
+ };
12069
+ }
12070
+ if (oldStat?.isFile() && !newExists) {
12071
+ if (opts.dryRun)
12072
+ return { kind: "migrated" };
12073
+ mkdirSync2(parent, { recursive: true, mode: 448 });
12074
+ const tempNew = `${newPath}.tmp`;
12075
+ copyFileSync(oldPath, tempNew);
12076
+ chmodSync(tempNew, 384);
12077
+ fsyncFile(tempNew);
12078
+ renameSync2(tempNew, newPath);
12079
+ fsyncDir(parent);
12080
+ atomicReplaceWithSymlink(oldPath, "vault/vault.enc");
12081
+ fsyncDir(switchroomRoot);
12082
+ return { kind: "migrated" };
12083
+ }
12084
+ return { kind: "no-vault" };
12085
+ } finally {
12086
+ if (release !== null) {
12087
+ try {
12088
+ release();
12089
+ } catch {}
12090
+ }
12091
+ }
12092
+ }
12093
+ function lstatSyncOrNull(path) {
12094
+ try {
12095
+ return lstatSync(path);
11795
12096
  } catch {
11796
- throw new VaultError(`Failed to read vault file: ${vaultPath}`);
12097
+ return null;
12098
+ }
12099
+ }
12100
+ function sha256File(path) {
12101
+ const data = readFileSync3(path);
12102
+ return createHash2("sha256").update(data).digest("hex");
12103
+ }
12104
+ function atomicReplaceWithSymlink(target, linkTarget) {
12105
+ const tmp = join(dirname2(target), `.${basename2(target)}.symlink-tmp`);
12106
+ if (existsSync3(tmp)) {
12107
+ try {
12108
+ unlinkSync3(tmp);
12109
+ } catch {}
12110
+ }
12111
+ symlinkSync(linkTarget, tmp);
12112
+ renameSync2(tmp, target);
12113
+ }
12114
+ function fsyncFile(path) {
12115
+ const fd = openSync3(path, "r+");
12116
+ try {
12117
+ fsyncSync3(fd);
12118
+ } finally {
12119
+ closeSync3(fd);
12120
+ }
12121
+ }
12122
+ function fsyncDir(path) {
12123
+ const fd = openSync3(path, "r");
12124
+ try {
12125
+ fsyncSync3(fd);
12126
+ } finally {
12127
+ closeSync3(fd);
11797
12128
  }
11798
- const salt = Buffer.from(vaultFile.salt, "hex");
11799
- const key = deriveKey(passphrase, salt, { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P });
11800
- vaultFile.kdf = { N: SCRYPT_N, r: SCRYPT_R, p: SCRYPT_P };
11801
- const vaultData = { secrets };
11802
- const { iv, data, tag } = encrypt(key, JSON.stringify(vaultData));
11803
- vaultFile.iv = iv;
11804
- vaultFile.data = data;
11805
- vaultFile.tag = tag;
11806
- atomicWriteFileSync(vaultPath, JSON.stringify(vaultFile, null, 2), 384);
11807
12129
  }
11808
12130
 
11809
12131
  // src/vault/broker/server.ts
@@ -11811,7 +12133,7 @@ init_loader();
11811
12133
 
11812
12134
  // src/vault/auto-unlock.ts
11813
12135
  import { createHmac, randomBytes as randomBytes2, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2 } from "node:crypto";
11814
- import { chmodSync, existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
12136
+ import { chmodSync as chmodSync2, existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "node:fs";
11815
12137
  var FORMAT_VERSION = 1;
11816
12138
  var SALT_LEN = 16;
11817
12139
  var NONCE_LEN = 12;
@@ -11839,7 +12161,7 @@ class AutoUnlockDecryptError extends Error {
11839
12161
  function readMachineId() {
11840
12162
  for (const path of [MACHINE_ID_PRIMARY, MACHINE_ID_FALLBACK]) {
11841
12163
  try {
11842
- const id = readFileSync3(path, "utf8").trim();
12164
+ const id = readFileSync5(path, "utf8").trim();
11843
12165
  if (id.length > 0)
11844
12166
  return id;
11845
12167
  } catch {}
@@ -11876,12 +12198,12 @@ function decryptAutoUnlock(blob, machineId) {
11876
12198
  }
11877
12199
  }
11878
12200
  function readAutoUnlockFile(filePath) {
11879
- if (!existsSync4(filePath)) {
12201
+ if (!existsSync6(filePath)) {
11880
12202
  throw new AutoUnlockDecryptError("io");
11881
12203
  }
11882
12204
  let blob;
11883
12205
  try {
11884
- blob = readFileSync3(filePath);
12206
+ blob = readFileSync5(filePath);
11885
12207
  } catch {
11886
12208
  throw new AutoUnlockDecryptError("io");
11887
12209
  }
@@ -11891,7 +12213,7 @@ var DEFAULT_AUTO_UNLOCK_PATH = "~/.switchroom/vault-auto-unlock";
11891
12213
 
11892
12214
  // src/vault/broker/peercred.ts
11893
12215
  import { execFileSync } from "node:child_process";
11894
- import { readFileSync as readFileSync4, readlinkSync, fstatSync } from "node:fs";
12216
+ import { readFileSync as readFileSync6, readlinkSync, fstatSync } from "node:fs";
11895
12217
 
11896
12218
  // src/vault/broker/peercred-ffi.ts
11897
12219
  function getPeerCred(fd) {
@@ -12017,7 +12339,7 @@ function findClientPidByServerInode(rows, socketPath, serverInode) {
12017
12339
  }
12018
12340
  function readUid(pid) {
12019
12341
  try {
12020
- const status = readFileSync4(`/proc/${pid}/status`, "utf8");
12342
+ const status = readFileSync6(`/proc/${pid}/status`, "utf8");
12021
12343
  const m = status.match(/^Uid:\s+(\d+)/m);
12022
12344
  if (!m)
12023
12345
  return null;
@@ -12035,7 +12357,7 @@ function readExe(pid) {
12035
12357
  }
12036
12358
  function readSystemdUnit(pid) {
12037
12359
  try {
12038
- const content = readFileSync4(`/proc/${pid}/cgroup`, "utf8");
12360
+ const content = readFileSync6(`/proc/${pid}/cgroup`, "utf8");
12039
12361
  const lines = content.split(`
12040
12362
  `);
12041
12363
  for (const line of lines) {
@@ -12298,7 +12620,8 @@ var PutRequestSchema = exports_external.object({
12298
12620
  exports_external.object({ kind: exports_external.literal("string"), value: exports_external.string() }),
12299
12621
  exports_external.object({ kind: exports_external.literal("binary"), value: exports_external.string() })
12300
12622
  ]),
12301
- token: exports_external.string().optional()
12623
+ token: exports_external.string().optional(),
12624
+ passphrase: exports_external.string().optional()
12302
12625
  });
12303
12626
  var ListRequestSchema = exports_external.object({
12304
12627
  v: exports_external.literal(1),
@@ -12309,9 +12632,10 @@ var MintGrantRequestSchema = exports_external.object({
12309
12632
  v: exports_external.literal(1),
12310
12633
  op: exports_external.literal("mint_grant"),
12311
12634
  agent: exports_external.string().min(1),
12312
- keys: exports_external.array(exports_external.string().min(1)).min(1),
12635
+ keys: exports_external.array(exports_external.string().min(1)),
12313
12636
  ttl_seconds: exports_external.number().int().positive().nullable(),
12314
- description: exports_external.string().optional()
12637
+ description: exports_external.string().optional(),
12638
+ write_keys: exports_external.array(exports_external.string().min(1)).optional()
12315
12639
  });
12316
12640
  var ListGrantsRequestSchema = exports_external.object({
12317
12641
  v: exports_external.literal(1),
@@ -12452,6 +12776,7 @@ var GrantMetaSchema = exports_external.object({
12452
12776
  id: exports_external.string(),
12453
12777
  agent_slug: exports_external.string(),
12454
12778
  key_allow: exports_external.array(exports_external.string()),
12779
+ write_allow: exports_external.array(exports_external.string()).default([]),
12455
12780
  expires_at: exports_external.number().nullable(),
12456
12781
  created_at: exports_external.number(),
12457
12782
  description: exports_external.string().nullable()
@@ -12622,7 +12947,7 @@ function createAuditLogger(opts = {}) {
12622
12947
  // src/vault/grants.ts
12623
12948
  import { randomBytes as randomBytes4 } from "node:crypto";
12624
12949
 
12625
- // node_modules/.bun/bcryptjs@3.0.3/node_modules/bcryptjs/index.js
12950
+ // node_modules/bcryptjs/index.js
12626
12951
  import nodeCrypto from "crypto";
12627
12952
  var randomFallback = null;
12628
12953
  function randomBytes3(len) {
@@ -14307,6 +14632,11 @@ function migrateGrantsSchema(db) {
14307
14632
  description TEXT
14308
14633
  )
14309
14634
  `);
14635
+ const cols = db.query(`PRAGMA table_info(vault_grants)`).all();
14636
+ const hasWriteAllow = cols.some((c) => c.name === "write_allow");
14637
+ if (!hasWriteAllow) {
14638
+ db.run(`ALTER TABLE vault_grants ADD COLUMN write_allow TEXT NOT NULL DEFAULT '[]'`);
14639
+ }
14310
14640
  }
14311
14641
  var BCRYPT_COST = 10;
14312
14642
  function generateId() {
@@ -14330,21 +14660,43 @@ function rowToGrant(row) {
14330
14660
  id: row.id,
14331
14661
  agent_slug: row.agent_slug,
14332
14662
  key_allow: parseKeyAllow(row.key_allow),
14663
+ write_allow: parseKeyAllow(row.write_allow ?? "[]"),
14333
14664
  expires_at: row.expires_at ?? null,
14334
14665
  revoked_at: row.revoked_at ?? null,
14335
14666
  created_at: row.created_at,
14336
14667
  description: row.description ?? null
14337
14668
  };
14338
14669
  }
14339
- async function mintGrant(db, agent_slug, key_allow, ttl_seconds, description) {
14670
+ function keyMatchesPatterns(patterns, key) {
14671
+ for (const pat of patterns) {
14672
+ if (pat.endsWith("*")) {
14673
+ const prefix = pat.slice(0, -1);
14674
+ if (key.startsWith(prefix))
14675
+ return true;
14676
+ } else if (pat === key) {
14677
+ return true;
14678
+ }
14679
+ }
14680
+ return false;
14681
+ }
14682
+ async function mintGrant(db, agent_slug, key_allow, ttl_seconds, description, write_allow = []) {
14340
14683
  const id = generateId();
14341
14684
  const secret = generateSecret();
14342
14685
  const token = `${id}.${secret}`;
14343
14686
  const secret_hash = await hash(secret, BCRYPT_COST);
14344
14687
  const now = Math.floor(Date.now() / 1000);
14345
14688
  const expires_at = ttl_seconds != null ? now + ttl_seconds : null;
14346
- db.run(`INSERT INTO vault_grants (id, secret_hash, agent_slug, key_allow, expires_at, revoked_at, created_at, description)
14347
- VALUES (?, ?, ?, ?, ?, NULL, ?, ?)`, [id, secret_hash, agent_slug, JSON.stringify(key_allow), expires_at, now, description ?? null]);
14689
+ db.run(`INSERT INTO vault_grants (id, secret_hash, agent_slug, key_allow, write_allow, expires_at, revoked_at, created_at, description)
14690
+ VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`, [
14691
+ id,
14692
+ secret_hash,
14693
+ agent_slug,
14694
+ JSON.stringify(key_allow),
14695
+ JSON.stringify(write_allow),
14696
+ expires_at,
14697
+ now,
14698
+ description ?? null
14699
+ ]);
14348
14700
  return { token, id, expires_at };
14349
14701
  }
14350
14702
  async function validateGrant(db, token, key) {
@@ -14385,6 +14737,41 @@ async function validateGrant(db, token, key) {
14385
14737
  }
14386
14738
  return { ok: true, grant };
14387
14739
  }
14740
+ async function validateGrantForWrite(db, token, key) {
14741
+ const dotIdx = token.indexOf(".");
14742
+ if (dotIdx === -1 || !token.startsWith("vg_")) {
14743
+ return { ok: false, reason: "grant-invalid" };
14744
+ }
14745
+ const id = token.slice(0, dotIdx);
14746
+ const secret = token.slice(dotIdx + 1);
14747
+ if (!id || !secret) {
14748
+ return { ok: false, reason: "grant-invalid" };
14749
+ }
14750
+ const row = db.query(`SELECT id, secret_hash, agent_slug, key_allow, write_allow, expires_at, revoked_at, created_at, description
14751
+ FROM vault_grants WHERE id = ?`).get(id);
14752
+ if (!row)
14753
+ return { ok: false, reason: "grant-invalid" };
14754
+ const secretHash = row.secret_hash;
14755
+ let hashMatches;
14756
+ try {
14757
+ hashMatches = await compare(secret, secretHash);
14758
+ } catch {
14759
+ hashMatches = false;
14760
+ }
14761
+ if (!hashMatches)
14762
+ return { ok: false, reason: "grant-invalid" };
14763
+ const grant = rowToGrant(row);
14764
+ const now = Math.floor(Date.now() / 1000);
14765
+ if (grant.revoked_at !== null)
14766
+ return { ok: false, reason: "grant-revoked" };
14767
+ if (grant.expires_at !== null && grant.expires_at < now) {
14768
+ return { ok: false, reason: "grant-expired" };
14769
+ }
14770
+ if (!keyMatchesPatterns(grant.write_allow, key)) {
14771
+ return { ok: false, reason: "grant-write-not-allowed" };
14772
+ }
14773
+ return { ok: true, grant };
14774
+ }
14388
14775
  function revokeGrant(db, id) {
14389
14776
  const now = Math.floor(Date.now() / 1000);
14390
14777
  const result = db.run(`UPDATE vault_grants SET revoked_at = ? WHERE id = ? AND revoked_at IS NULL`, [now, id]);
@@ -14393,11 +14780,11 @@ function revokeGrant(db, id) {
14393
14780
  function listGrants(db, agent_slug) {
14394
14781
  let rows;
14395
14782
  if (agent_slug !== undefined) {
14396
- rows = db.query(`SELECT id, agent_slug, key_allow, expires_at, revoked_at, created_at, description
14783
+ rows = db.query(`SELECT id, agent_slug, key_allow, write_allow, expires_at, revoked_at, created_at, description
14397
14784
  FROM vault_grants WHERE revoked_at IS NULL AND agent_slug = ?
14398
14785
  ORDER BY created_at DESC`).all(agent_slug);
14399
14786
  } else {
14400
- rows = db.query(`SELECT id, agent_slug, key_allow, expires_at, revoked_at, created_at, description
14787
+ rows = db.query(`SELECT id, agent_slug, key_allow, write_allow, expires_at, revoked_at, created_at, description
14401
14788
  FROM vault_grants WHERE revoked_at IS NULL
14402
14789
  ORDER BY created_at DESC`).all();
14403
14790
  }
@@ -14786,9 +15173,12 @@ class VaultBroker {
14786
15173
  grantsDb;
14787
15174
  constructor(testOpts = {}) {
14788
15175
  this.testOpts = testOpts;
14789
- const usingTestOpt = testOpts._testSecrets !== undefined || testOpts._testConfig !== undefined || testOpts._testIdentify !== undefined || testOpts._testAuditLogger !== undefined || testOpts._testGrantsDb !== undefined;
15176
+ const usingTestOpt = testOpts._testSecrets !== undefined || testOpts._testConfig !== undefined || testOpts._testIdentify !== undefined || testOpts._testAuditLogger !== undefined || testOpts._testGrantsDb !== undefined || testOpts._testVaultPath !== undefined;
14790
15177
  if (usingTestOpt && true) {
14791
- throw new Error("VaultBroker: BrokerTestOpts (_testSecrets/_testConfig/_testIdentify/_testAuditLogger/_testGrantsDb) " + "must not be set outside tests. Set NODE_ENV=test if you really mean it.");
15178
+ throw new Error("VaultBroker: BrokerTestOpts (_testSecrets/_testConfig/_testIdentify/_testAuditLogger/_testGrantsDb/_testVaultPath) " + "must not be set outside tests. Set NODE_ENV=test if you really mean it.");
15179
+ }
15180
+ if (testOpts._testVaultPath !== undefined) {
15181
+ this.vaultPath = testOpts._testVaultPath;
14792
15182
  }
14793
15183
  this.auditLogger = testOpts._testAuditLogger ?? createAuditLogger();
14794
15184
  if (testOpts._testGrantsDb !== undefined) {
@@ -14819,15 +15209,15 @@ class VaultBroker {
14819
15209
  this.secrets = { ...this.testOpts._testSecrets };
14820
15210
  }
14821
15211
  process.umask(63);
14822
- const parentDir = dirname3(this.socketPath);
14823
- mkdirSync4(parentDir, { recursive: true, mode: 448 });
15212
+ const parentDir = dirname4(this.socketPath);
15213
+ mkdirSync5(parentDir, { recursive: true, mode: 448 });
14824
15214
  try {
14825
- chmodSync3(parentDir, 448);
15215
+ chmodSync4(parentDir, 448);
14826
15216
  } catch {}
14827
15217
  for (const p of [this.socketPath, this.unlockSocketPath]) {
14828
- if (existsSync5(p)) {
15218
+ if (existsSync7(p)) {
14829
15219
  try {
14830
- unlinkSync2(p);
15220
+ unlinkSync4(p);
14831
15221
  } catch {}
14832
15222
  }
14833
15223
  }
@@ -14843,6 +15233,7 @@ class VaultBroker {
14843
15233
  }
14844
15234
  }
14845
15235
  unlockFromPassphrase(passphrase) {
15236
+ detectVaultLayoutDrift(this.vaultPath);
14846
15237
  const secrets = openVault(passphrase, this.vaultPath);
14847
15238
  this.secrets = secrets;
14848
15239
  this.passphrase = passphrase;
@@ -14874,24 +15265,24 @@ class VaultBroker {
14874
15265
  try {
14875
15266
  entry.server.close();
14876
15267
  } catch {}
14877
- if (existsSync5(sockPath)) {
15268
+ if (existsSync7(sockPath)) {
14878
15269
  try {
14879
- unlinkSync2(sockPath);
15270
+ unlinkSync4(sockPath);
14880
15271
  } catch {}
14881
15272
  }
14882
15273
  }
14883
15274
  this.agentServers.clear();
14884
15275
  for (const p of [this.socketPath, this.unlockSocketPath]) {
14885
- if (p && existsSync5(p)) {
15276
+ if (p && existsSync7(p)) {
14886
15277
  try {
14887
- unlinkSync2(p);
15278
+ unlinkSync4(p);
14888
15279
  } catch {}
14889
15280
  }
14890
15281
  }
14891
15282
  try {
14892
15283
  const pidPath = resolvePath(PID_FILE_DEFAULT);
14893
- if (existsSync5(pidPath))
14894
- unlinkSync2(pidPath);
15284
+ if (existsSync7(pidPath))
15285
+ unlinkSync4(pidPath);
14895
15286
  } catch {}
14896
15287
  }
14897
15288
  getStatus() {
@@ -14913,18 +15304,18 @@ class VaultBroker {
14913
15304
  return new Promise((resolveP, rejectP) => {
14914
15305
  if (abs.endsWith("/sock")) {
14915
15306
  const dir = abs.slice(0, -"/sock".length);
14916
- if (existsSync5(dir)) {
15307
+ if (existsSync7(dir)) {
14917
15308
  try {
14918
15309
  chownSync(dir, 0, 0);
14919
15310
  } catch {}
14920
15311
  try {
14921
- chmodSync3(dir, 448);
15312
+ chmodSync4(dir, 448);
14922
15313
  } catch {}
14923
15314
  }
14924
15315
  }
14925
- if (existsSync5(abs)) {
15316
+ if (existsSync7(abs)) {
14926
15317
  try {
14927
- unlinkSync2(abs);
15318
+ unlinkSync4(abs);
14928
15319
  } catch (err) {
14929
15320
  const msg = err instanceof Error ? err.message : String(err);
14930
15321
  process.stderr.write(`[vault-broker] could not unlink stale socket agent=${agentName} sock=${abs}: ${msg}
@@ -14937,7 +15328,7 @@ class VaultBroker {
14937
15328
  server.on("error", (err) => rejectP(err));
14938
15329
  server.listen(abs, () => {
14939
15330
  try {
14940
- chmodSync3(abs, 432);
15331
+ chmodSync4(abs, 432);
14941
15332
  } catch {}
14942
15333
  try {
14943
15334
  const uid = allocateAgentUid(agentName);
@@ -14966,7 +15357,7 @@ class VaultBroker {
14966
15357
  });
14967
15358
  server.listen(this.socketPath, () => {
14968
15359
  try {
14969
- chmodSync3(this.socketPath, 384);
15360
+ chmodSync4(this.socketPath, 384);
14970
15361
  } catch {}
14971
15362
  this.server = server;
14972
15363
  resolve5();
@@ -14983,7 +15374,7 @@ class VaultBroker {
14983
15374
  });
14984
15375
  server.listen(this.unlockSocketPath, () => {
14985
15376
  try {
14986
- chmodSync3(this.unlockSocketPath, 384);
15377
+ chmodSync4(this.unlockSocketPath, 384);
14987
15378
  } catch {}
14988
15379
  this.unlockServer = server;
14989
15380
  resolve5();
@@ -15277,30 +15668,71 @@ class VaultBroker {
15277
15668
  socket.write(encodeResponse(errorResponse("LOCKED", "Vault is locked")));
15278
15669
  return;
15279
15670
  }
15280
- if (agentName === null) {
15281
- socket.write(encodeResponse(errorResponse("DENIED", "put requires path-as-identity (token-based grants are read-only)")));
15671
+ let passphraseAttested = false;
15672
+ if (req.passphrase !== undefined && req.passphrase !== "") {
15673
+ if (req.passphrase === this.passphrase) {
15674
+ passphraseAttested = true;
15675
+ } else {
15676
+ this.auditLogger.write({
15677
+ ts: new Date().toISOString(),
15678
+ op: "put",
15679
+ key: req.key,
15680
+ caller: auditCaller,
15681
+ pid: auditPid,
15682
+ cgroup: auditCgroup,
15683
+ result: "denied:passphrase-mismatch",
15684
+ method: "passphrase"
15685
+ });
15686
+ socket.write(encodeResponse(errorResponse("DENIED", "supplied passphrase does not match the broker's unlocked passphrase")));
15687
+ return;
15688
+ }
15689
+ }
15690
+ let writeGrantId = null;
15691
+ if (req.token !== undefined && req.token !== "") {
15692
+ const v = await validateGrantForWrite(this.grantsDb, req.token, req.key);
15693
+ if (v.ok) {
15694
+ writeGrantId = v.grant.id;
15695
+ } else if (v.reason === "grant-expired" || v.reason === "grant-revoked") {
15696
+ this.auditLogger.write({
15697
+ ts: new Date().toISOString(),
15698
+ op: "put",
15699
+ key: req.key,
15700
+ caller: auditCaller,
15701
+ pid: auditPid,
15702
+ cgroup: auditCgroup,
15703
+ result: `denied:${v.reason}`,
15704
+ method: "grant"
15705
+ });
15706
+ socket.write(encodeResponse(errorResponse("DENIED", v.reason)));
15707
+ return;
15708
+ }
15709
+ }
15710
+ if (writeGrantId === null && !passphraseAttested && agentName === null) {
15711
+ socket.write(encodeResponse(errorResponse("DENIED", "put requires path-as-identity, a valid write-grant token, or operator-passphrase attestation")));
15282
15712
  return;
15283
15713
  }
15284
15714
  if (this.config === null) {
15285
15715
  socket.write(encodeResponse(errorResponse("INTERNAL", "Broker config not loaded")));
15286
15716
  return;
15287
15717
  }
15288
- const aclResult = checkAclByAgent(this.config, agentName, req.key);
15289
- if (!aclResult.allow) {
15290
- this.auditLogger.write({
15291
- ts: new Date().toISOString(),
15292
- op: "put",
15293
- key: req.key,
15294
- caller: auditCaller,
15295
- pid: auditPid,
15296
- cgroup: auditCgroup,
15297
- result: `denied:${aclResult.reason}`
15298
- });
15299
- socket.write(encodeResponse(errorResponse("DENIED", aclResult.reason)));
15300
- return;
15718
+ if (writeGrantId === null && !passphraseAttested) {
15719
+ const aclResult = checkAclByAgent(this.config, agentName, req.key);
15720
+ if (!aclResult.allow) {
15721
+ this.auditLogger.write({
15722
+ ts: new Date().toISOString(),
15723
+ op: "put",
15724
+ key: req.key,
15725
+ caller: auditCaller,
15726
+ pid: auditPid,
15727
+ cgroup: auditCgroup,
15728
+ result: `denied:${aclResult.reason}`
15729
+ });
15730
+ socket.write(encodeResponse(errorResponse("DENIED", aclResult.reason)));
15731
+ return;
15732
+ }
15301
15733
  }
15302
15734
  const existing = this.secrets[req.key];
15303
- if (existing === undefined) {
15735
+ if (existing === undefined && writeGrantId === null && !passphraseAttested) {
15304
15736
  this.auditLogger.write({
15305
15737
  ts: new Date().toISOString(),
15306
15738
  op: "put",
@@ -15310,10 +15742,10 @@ class VaultBroker {
15310
15742
  cgroup: auditCgroup,
15311
15743
  result: "denied:unknown_key"
15312
15744
  });
15313
- socket.write(encodeResponse(errorResponse("UNKNOWN_KEY", `Key not found: ${req.key} (broker put cannot introduce new keys; ask operator to set it once via 'switchroom vault set' from the host)`)));
15745
+ socket.write(encodeResponse(errorResponse("UNKNOWN_KEY", `Key not found: ${req.key} (broker put cannot introduce new keys without a write-grant; ask operator to 'switchroom vault grant <agent> --write ${req.key}' or set it once via 'switchroom vault set' from the host)`)));
15314
15746
  return;
15315
15747
  }
15316
- if (existing.kind !== req.entry.kind) {
15748
+ if (existing !== undefined && existing.kind !== req.entry.kind && !passphraseAttested) {
15317
15749
  this.auditLogger.write({
15318
15750
  ts: new Date().toISOString(),
15319
15751
  op: "put",
@@ -15331,7 +15763,11 @@ class VaultBroker {
15331
15763
  try {
15332
15764
  saveVault(this.passphrase, this.vaultPath, this.secrets);
15333
15765
  } catch (err) {
15334
- this.secrets[req.key] = previousEntry;
15766
+ if (previousEntry === undefined) {
15767
+ delete this.secrets[req.key];
15768
+ } else {
15769
+ this.secrets[req.key] = previousEntry;
15770
+ }
15335
15771
  this.auditLogger.write({
15336
15772
  ts: new Date().toISOString(),
15337
15773
  op: "put",
@@ -15339,7 +15775,8 @@ class VaultBroker {
15339
15775
  caller: auditCaller,
15340
15776
  pid: auditPid,
15341
15777
  cgroup: auditCgroup,
15342
- result: `error:${err?.message ?? "save failed"}`
15778
+ result: `error:${err?.message ?? "save failed"}`,
15779
+ ...passphraseAttested ? { method: "passphrase" } : writeGrantId !== null ? { method: "grant", grant_id: writeGrantId } : {}
15343
15780
  });
15344
15781
  socket.write(encodeResponse(errorResponse("INTERNAL", `Failed to persist: ${err?.message ?? "unknown"}`)));
15345
15782
  return;
@@ -15351,7 +15788,8 @@ class VaultBroker {
15351
15788
  caller: auditCaller,
15352
15789
  pid: auditPid,
15353
15790
  cgroup: auditCgroup,
15354
- result: "allowed"
15791
+ result: "allowed",
15792
+ ...passphraseAttested ? { method: "passphrase" } : writeGrantId !== null ? { method: "grant", grant_id: writeGrantId } : {}
15355
15793
  });
15356
15794
  socket.write(encodeResponse({ ok: true, put: true, key: req.key }));
15357
15795
  return;
@@ -15404,10 +15842,22 @@ class VaultBroker {
15404
15842
  }
15405
15843
  }
15406
15844
  if (req.op === "mint_grant") {
15407
- const { agent, keys, ttl_seconds, description } = req;
15845
+ const { agent, keys, ttl_seconds, description, write_keys } = req;
15846
+ if (keys.length === 0 && (write_keys?.length ?? 0) === 0) {
15847
+ this.auditLogger.write({
15848
+ ts: new Date().toISOString(),
15849
+ op: "mint_grant",
15850
+ caller: auditCaller,
15851
+ pid: auditPid,
15852
+ cgroup: auditCgroup,
15853
+ result: "denied:no-capabilities"
15854
+ });
15855
+ socket.write(encodeResponse(errorResponse("BAD_REQUEST", "mint_grant requires at least one of `keys` or `write_keys` to be non-empty")));
15856
+ return;
15857
+ }
15408
15858
  let mintResult;
15409
15859
  try {
15410
- mintResult = await mintGrant(this.grantsDb, agent, keys, ttl_seconds, description);
15860
+ mintResult = await mintGrant(this.grantsDb, agent, keys, ttl_seconds, description, write_keys ?? []);
15411
15861
  } catch (err) {
15412
15862
  const msg = err instanceof Error ? err.message : String(err);
15413
15863
  this.auditLogger.write({
@@ -15423,11 +15873,11 @@ class VaultBroker {
15423
15873
  }
15424
15874
  try {
15425
15875
  const tokenDir = path3.join(os3.homedir(), ".switchroom", "agents", agent);
15426
- mkdirSync4(tokenDir, { recursive: true });
15876
+ mkdirSync5(tokenDir, { recursive: true });
15427
15877
  const tokenPath = path3.join(tokenDir, ".vault-token");
15428
15878
  const tmpPath = `${tokenPath}.tmp.${process.pid}`;
15429
15879
  writeFileSync3(tmpPath, mintResult.token, { mode: 384 });
15430
- renameSync2(tmpPath, tokenPath);
15880
+ renameSync3(tmpPath, tokenPath);
15431
15881
  } catch (err) {
15432
15882
  process.stderr.write(`[vault-broker] mint_grant: failed to write token file for agent ${agent}: ${err.message}
15433
15883
  `);
@@ -15460,10 +15910,11 @@ class VaultBroker {
15460
15910
  cgroup: auditCgroup,
15461
15911
  result: `allowed:${grants.length}`
15462
15912
  });
15463
- const grantMetas = grants.map(({ id, agent_slug, key_allow, expires_at, created_at, description }) => ({
15913
+ const grantMetas = grants.map(({ id, agent_slug, key_allow, write_allow, expires_at, created_at, description }) => ({
15464
15914
  id,
15465
15915
  agent_slug,
15466
15916
  key_allow,
15917
+ write_allow,
15467
15918
  expires_at,
15468
15919
  created_at,
15469
15920
  description
@@ -15478,9 +15929,9 @@ class VaultBroker {
15478
15929
  const row = this.grantsDb.query("SELECT agent_slug FROM vault_grants WHERE id = ?").get(id);
15479
15930
  if (row) {
15480
15931
  const tokenPath = path3.join(os3.homedir(), ".switchroom", "agents", row.agent_slug, ".vault-token");
15481
- if (existsSync5(tokenPath)) {
15932
+ if (existsSync7(tokenPath)) {
15482
15933
  try {
15483
- unlinkSync2(tokenPath);
15934
+ unlinkSync4(tokenPath);
15484
15935
  } catch {}
15485
15936
  }
15486
15937
  }
@@ -15721,7 +16172,7 @@ class VaultBroker {
15721
16172
  const envPath = process.env.SWITCHROOM_VAULT_BROKER_AUTO_UNLOCK_PATH;
15722
16173
  const configuredPath = (envPath && envPath.length > 0 ? envPath : undefined) ?? this.config?.vault?.broker?.autoUnlockCredentialPath ?? DEFAULT_AUTO_UNLOCK_PATH;
15723
16174
  const filePath = resolvePath(configuredPath);
15724
- if (!existsSync5(filePath))
16175
+ if (!existsSync7(filePath))
15725
16176
  return false;
15726
16177
  let passphrase;
15727
16178
  try {
@@ -15758,7 +16209,7 @@ class VaultBroker {
15758
16209
  const credPath = `${dir}/vault-passphrase`;
15759
16210
  let passphrase;
15760
16211
  try {
15761
- passphrase = readFileSync5(credPath, "utf8").replace(/\n+$/, "");
16212
+ passphrase = readFileSync7(credPath, "utf8").replace(/\n+$/, "");
15762
16213
  } catch (err) {
15763
16214
  const code = err.code;
15764
16215
  if (code === "ENOENT") {
@@ -15795,6 +16246,21 @@ class VaultBroker {
15795
16246
  } catch {}
15796
16247
  }
15797
16248
  }
16249
+ function detectVaultLayoutDrift(vaultPath) {
16250
+ const dir = dirname4(vaultPath);
16251
+ if (basename3(dir) !== "vault")
16252
+ return;
16253
+ if (basename3(vaultPath) !== "vault.enc")
16254
+ return;
16255
+ const switchroomDir = dirname4(dir);
16256
+ if (basename3(switchroomDir) !== ".switchroom")
16257
+ return;
16258
+ const home2 = dirname4(switchroomDir);
16259
+ const result = inspectVaultLayout(home2);
16260
+ if (result.kind === "divergent") {
16261
+ throw new VaultError(`Vault layout divergence detected at boot: ${result.details.oldPath} and ${result.details.newPath} are both regular files with different content. An older switchroom CLI may have written to the legacy path after migration ran. Run \`switchroom apply\` from the host to surface the recovery recipe (state E refusal with literal \`mv\` commands). See docs/operators/state-e-recovery.md.`);
16262
+ }
16263
+ }
15798
16264
  var _globalBroker = null;
15799
16265
  function registerShutdownHandlers(broker) {
15800
16266
  _globalBroker = broker;
@@ -15815,8 +16281,8 @@ async function main() {
15815
16281
  const vaultPath = process.env.SWITCHROOM_VAULT_PATH;
15816
16282
  let perAgentTargets = [];
15817
16283
  try {
15818
- if (existsSync5(perAgentDir)) {
15819
- const entries = readdirSync(perAgentDir, { withFileTypes: true });
16284
+ if (existsSync7(perAgentDir)) {
16285
+ const entries = readdirSync2(perAgentDir, { withFileTypes: true });
15820
16286
  const flat = [];
15821
16287
  const subdirs = [];
15822
16288
  for (const e of entries) {