@vzn/vx 0.0.599 → 0.0.600

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vzn/vx",
3
- "version": "0.0.599",
3
+ "version": "0.0.600",
4
4
  "description": "The fastest task runner and build cache for JavaScript monorepos.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -21,10 +21,10 @@
21
21
  "node": ">=18"
22
22
  },
23
23
  "optionalDependencies": {
24
- "@vzn/vx-linux-x64": "0.0.599",
25
- "@vzn/vx-linux-arm64": "0.0.599",
26
- "@vzn/vx-darwin-x64": "0.0.599",
27
- "@vzn/vx-darwin-arm64": "0.0.599"
24
+ "@vzn/vx-linux-x64": "0.0.600",
25
+ "@vzn/vx-linux-arm64": "0.0.600",
26
+ "@vzn/vx-darwin-x64": "0.0.600",
27
+ "@vzn/vx-darwin-arm64": "0.0.600"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -1554,6 +1554,12 @@ function literalReadPaths(
1554
1554
  * `/**` is stripped before the compile). A task's read grant whose only
1555
1555
  * brackets are escaped names one path too, and Linux binds it whole, so
1556
1556
  * it gets the same subtree: `out/\[id\]` read `out/[id]` and none of it.
1557
+ *
1558
+ * A `*` or `?` meant as itself (escaped in a grant, or in a baseline's
1559
+ * name) has no spelling: SRT's rewrite of each runs inside a class too,
1560
+ * and a backslash compiles as a literal one, so `a\*.txt` granted
1561
+ * `a\bc.txt` and never `a*.txt`. Left out and said once, as on Linux
1562
+ * (`bindableReads`).
1557
1563
  */
1558
1564
  export function seatbeltBrackets(
1559
1565
  config: Parameters<SrtModule['SandboxManager']['wrapWithSandbox']>[2],
@@ -1563,7 +1569,9 @@ export function seatbeltBrackets(
1563
1569
  if (fs === undefined) return config
1564
1570
  const literal = (p: string): string => p.replaceAll('\\[', '[[]').replaceAll('\\]', ']')
1565
1571
  const bracketed = new Set(names.filter((n) => /[[\]]/.test(n)))
1572
+ const baseline = new Set(names)
1566
1573
  const read = (p: string): string[] => {
1574
+ if (!seatbeltSpells(p, 'read', baseline.has(p))) return []
1567
1575
  const name = bracketed.has(p) ? p : /\\[[\]]/.test(p) ? namedPath(p) : undefined
1568
1576
  if (name === undefined) return [literal(p)]
1569
1577
  const at = name.replaceAll('[', '[[]')
@@ -1574,7 +1582,7 @@ export function seatbeltBrackets(
1574
1582
  filesystem: {
1575
1583
  ...fs,
1576
1584
  denyRead: fs.denyRead.map((p) => p.replaceAll('[', '[[]')),
1577
- allowWrite: fs.allowWrite.map(literal),
1585
+ allowWrite: fs.allowWrite.filter((p) => seatbeltSpells(p, 'write', false)).map(literal),
1578
1586
  ...(fs.allowRead !== undefined
1579
1587
  ? { allowRead: [...new Set(fs.allowRead.flatMap(read))] }
1580
1588
  : {}),
@@ -1582,6 +1590,28 @@ export function seatbeltBrackets(
1582
1590
  }
1583
1591
  }
1584
1592
 
1593
+ /** A `*` or `?` behind an odd run of backslashes: the grant means the character. */
1594
+ const ESCAPED_WILDCARD = /(?:^|[^\\])(?:\\\\)*\\[*?]/
1595
+
1596
+ const warnedUnspellable = new Set<string>()
1597
+
1598
+ /** Whether seatbelt's SRT can take `grant` as written; said once when not. */
1599
+ function seatbeltSpells(grant: string, kind: 'read' | 'write', name: boolean): boolean {
1600
+ const m = name ? /[*?]/.exec(grant) : ESCAPED_WILDCARD.exec(grant)
1601
+ if (m === null) return true
1602
+ const at = name ? m.index : m.index + m[0].length - 2
1603
+ if (!warnedUnspellable.has(`${kind} ${grant}`)) {
1604
+ warnedUnspellable.add(`${kind} ${grant}`)
1605
+ process.stderr.write(
1606
+ `[vx] sandbox: the ${kind} grant ${grant} names a literal ${grant[at + (name ? 0 : 1)]}, ` +
1607
+ `which the macOS sandbox reads as a pattern and cannot spell as a name, so it is not ` +
1608
+ `granted. Rename it, or grant the directory above it: ` +
1609
+ `${grant.slice(0, grant.lastIndexOf(path.sep, at) + 1)}\n`,
1610
+ )
1611
+ }
1612
+ return false
1613
+ }
1614
+
1585
1615
  /** SRT's wrap, with the socket lift and the git-config grant this task asked for, or none (L-6, B-41). */
1586
1616
  function wrapForTask(
1587
1617
  SandboxManager: SrtModule['SandboxManager'],