pi-landstrip 0.16.24 → 0.16.26
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/index.ts +31 -2
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -416,6 +416,36 @@ export function sessionScopeFor(filePath: string, baseDirectory: string): string
|
|
|
416
416
|
return dir;
|
|
417
417
|
}
|
|
418
418
|
|
|
419
|
+
// Length of the longest entry in `patterns` that matches `path`, or -1 for no
|
|
420
|
+
// match. Canonicalized so the value reflects how specific the rule is.
|
|
421
|
+
function longestPrefixMatch(path: string, patterns: string[], cwd: string): number {
|
|
422
|
+
let best = -1;
|
|
423
|
+
for (const pattern of patterns) {
|
|
424
|
+
if (!matchesPattern(path, [pattern], cwd)) continue;
|
|
425
|
+
const canonical = pattern.includes('*')
|
|
426
|
+
? expandPath(pattern, cwd)
|
|
427
|
+
: canonicalizePath(pattern, cwd);
|
|
428
|
+
if (canonical.length > best) best = canonical.length;
|
|
429
|
+
}
|
|
430
|
+
return best;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Most-specific-match wins: a read is allowed when its longest matching
|
|
434
|
+
// allowRead entry is at least as specific as its longest matching denyRead
|
|
435
|
+
// entry. So an explicit allow (e.g. a granted `~/.cache`) overrides the broad
|
|
436
|
+
// `denyRead` gate (`/home`), while a narrow denyRead carve-out still beats a
|
|
437
|
+
// broad allow. Ties favor allow. denyWrite stays an absolute block elsewhere.
|
|
438
|
+
export function readAllowed(
|
|
439
|
+
path: string,
|
|
440
|
+
allowRead: string[],
|
|
441
|
+
denyRead: string[],
|
|
442
|
+
cwd: string,
|
|
443
|
+
): boolean {
|
|
444
|
+
const allow = longestPrefixMatch(path, allowRead, cwd);
|
|
445
|
+
if (allow < 0) return false;
|
|
446
|
+
return allow >= longestPrefixMatch(path, denyRead, cwd);
|
|
447
|
+
}
|
|
448
|
+
|
|
419
449
|
function isPathLike(value: string): boolean {
|
|
420
450
|
const trimmed = value.trim();
|
|
421
451
|
return (
|
|
@@ -1343,8 +1373,7 @@ export function createLandstripIntegration(
|
|
|
1343
1373
|
const config = loadConfig(cwd);
|
|
1344
1374
|
const isAllowed = (cfg: SandboxConfig): boolean =>
|
|
1345
1375
|
operation === 'read'
|
|
1346
|
-
?
|
|
1347
|
-
matchesPattern(path, getEffectiveAllowRead(cfg), cwd)
|
|
1376
|
+
? readAllowed(path, getEffectiveAllowRead(cfg), cfg.filesystem.denyRead, cwd)
|
|
1348
1377
|
: !matchesPattern(path, cfg.filesystem.denyWrite, cwd) &&
|
|
1349
1378
|
!shouldPromptForWrite(path, getEffectiveAllowWrite(cfg), cwd);
|
|
1350
1379
|
|