@f5-sales-demo/xcsh 19.102.4 → 19.102.5
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@f5-sales-demo/xcsh",
|
|
4
|
-
"version": "19.102.
|
|
4
|
+
"version": "19.102.5",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/f5-sales-demo/xcsh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -57,13 +57,13 @@
|
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
59
59
|
"@mozilla/readability": "^0.6",
|
|
60
|
-
"@f5-sales-demo/xcsh-stats": "19.102.
|
|
61
|
-
"@f5-sales-demo/pi-agent-core": "19.102.
|
|
62
|
-
"@f5-sales-demo/pi-ai": "19.102.
|
|
63
|
-
"@f5-sales-demo/pi-natives": "19.102.
|
|
64
|
-
"@f5-sales-demo/pi-resource-management": "19.102.
|
|
65
|
-
"@f5-sales-demo/pi-tui": "19.102.
|
|
66
|
-
"@f5-sales-demo/pi-utils": "19.102.
|
|
60
|
+
"@f5-sales-demo/xcsh-stats": "19.102.5",
|
|
61
|
+
"@f5-sales-demo/pi-agent-core": "19.102.5",
|
|
62
|
+
"@f5-sales-demo/pi-ai": "19.102.5",
|
|
63
|
+
"@f5-sales-demo/pi-natives": "19.102.5",
|
|
64
|
+
"@f5-sales-demo/pi-resource-management": "19.102.5",
|
|
65
|
+
"@f5-sales-demo/pi-tui": "19.102.5",
|
|
66
|
+
"@f5-sales-demo/pi-utils": "19.102.5",
|
|
67
67
|
"@sinclair/typebox": "^0.34",
|
|
68
68
|
"@xterm/headless": "^6.0",
|
|
69
69
|
"ajv": "^8.20",
|
|
@@ -17,17 +17,17 @@ export interface BuildInfo {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const BUILD_INFO: BuildInfo = {
|
|
20
|
-
"version": "19.102.
|
|
21
|
-
"commit": "
|
|
22
|
-
"shortCommit": "
|
|
20
|
+
"version": "19.102.5",
|
|
21
|
+
"commit": "8a63bfb03a98e424c010b4176b65ed5583587dad",
|
|
22
|
+
"shortCommit": "8a63bfb",
|
|
23
23
|
"branch": "main",
|
|
24
|
-
"tag": "v19.102.
|
|
25
|
-
"commitDate": "2026-07-
|
|
26
|
-
"buildDate": "2026-07-
|
|
24
|
+
"tag": "v19.102.5",
|
|
25
|
+
"commitDate": "2026-07-30T22:33:51Z",
|
|
26
|
+
"buildDate": "2026-07-30T23:00:45.450Z",
|
|
27
27
|
"dirty": true,
|
|
28
28
|
"prNumber": "",
|
|
29
29
|
"repoUrl": "https://github.com/f5-sales-demo/xcsh",
|
|
30
30
|
"repoSlug": "f5-sales-demo/xcsh",
|
|
31
|
-
"commitUrl": "https://github.com/f5-sales-demo/xcsh/commit/
|
|
32
|
-
"releaseUrl": "https://github.com/f5-sales-demo/xcsh/releases/tag/v19.102.
|
|
31
|
+
"commitUrl": "https://github.com/f5-sales-demo/xcsh/commit/8a63bfb03a98e424c010b4176b65ed5583587dad",
|
|
32
|
+
"releaseUrl": "https://github.com/f5-sales-demo/xcsh/releases/tag/v19.102.5"
|
|
33
33
|
};
|
|
@@ -203,6 +203,12 @@ const COMMAND_BEARING_CONFIG = [
|
|
|
203
203
|
// was measured working with its config.yml read-only.
|
|
204
204
|
path.join(".config", "glab-cli", "aliases.yml"),
|
|
205
205
|
path.join("Library", "Application Support", "glab-cli", "aliases.yml"),
|
|
206
|
+
// Build configuration that redirects a later build. Protected by *omission* while home was denied —
|
|
207
|
+
// the cache carve-outs grant `.cargo/registry` rather than `.cargo` — so #2637 had to name them. A
|
|
208
|
+
// write here is persistence, not theft: the operator's next build runs what it says. Reads are fine.
|
|
209
|
+
path.join(".cargo", "config.toml"),
|
|
210
|
+
path.join(".gradle", "init.gradle"),
|
|
211
|
+
path.join(".gradle", "init.d"),
|
|
206
212
|
];
|
|
207
213
|
|
|
208
214
|
/** Read-only inside home: configuration a tool needs to behave correctly, but must not rewrite. */
|
|
@@ -268,9 +274,10 @@ const AGENT_PROFILE_FILES = ["user-profile.json", "computer-profile.json", "sett
|
|
|
268
274
|
* unforeseen — `/data`, `/scratch`, a bespoke mount.
|
|
269
275
|
*/
|
|
270
276
|
const DATA_ROOTS = [
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
277
|
+
// `/Users` and `/home` are deliberately absent: denying the home container denies this operator's own
|
|
278
|
+
// home with it, which is the whole of #2637. Other accounts are 0700, so the filesystem already refuses
|
|
279
|
+
// them; the fence is not here to re-implement file permissions.
|
|
280
|
+
"/root", // Linux superuser home: not this operator's account
|
|
274
281
|
"/Volumes", // macOS mounts. Per-container, not per-child: /Volumes/Macintosh HD resolves to /,
|
|
275
282
|
"/mnt", // which `tooBroadToDeny` then rejects, and the kernel resolves such a path before any
|
|
276
283
|
"/media", // rule matches it — so denying the container cannot deny the boot volume.
|
|
@@ -528,8 +535,22 @@ export function buildContainmentFence(options: ContainmentOptions): ContainmentF
|
|
|
528
535
|
// rejects, so `/`, `/usr`, `/tmp` and `$TMPDIR` are never denied and operational paths stay
|
|
529
536
|
// reachable. And it costs nothing below: the workspace is allowed at greater depth, and
|
|
530
537
|
// `fenceVerdict` takes the deepest match.
|
|
531
|
-
|
|
538
|
+
// Home is never denied, and the walk stops there (#2637).
|
|
539
|
+
//
|
|
540
|
+
// This is a professional courtesy, not a prison: an effort to stop *inadvertent* filesystem wandering
|
|
541
|
+
// between customers, for an operator with senior technical skills and the same rights on this machine
|
|
542
|
+
// as the agent acting for them. Denying home outright refused `~/git/STYLE_GUIDE.md` and then needed
|
|
543
|
+
// ~30 carve-outs to make ordinary tooling work again — every one of them evidence the posture was wrong.
|
|
544
|
+
//
|
|
545
|
+
// What the walk still covers is the part that matters: every level between the workspace and home. With
|
|
546
|
+
// the workspace at `~/MEDDPICC/EQUIFAX`, `~/MEDDPICC` is denied so the `ACME` sibling is unreachable,
|
|
547
|
+
// and with `<container>/<tenant>/repo` every level up to home is denied, so the v19.100.1 cross-tenant
|
|
548
|
+
// regression does not return.
|
|
549
|
+
//
|
|
550
|
+
// A session whose folder IS home, or a direct child of it, therefore fences nothing above itself. That
|
|
551
|
+
// is deliberate: if the operator chooses to work in home, that is their filesystem to lay out.
|
|
532
552
|
for (let ancestor = path.dirname(workspace); ; ancestor = path.dirname(ancestor)) {
|
|
553
|
+
if (ancestor === home) break; // the operator's own account is theirs
|
|
533
554
|
if (tooBroadToDeny(ancestor, fsRoot)) break;
|
|
534
555
|
deny.add(ancestor);
|
|
535
556
|
const next = path.dirname(ancestor);
|
|
@@ -629,6 +650,11 @@ export function buildContainmentFence(options: ContainmentOptions): ContainmentF
|
|
|
629
650
|
// e.g. /Volumes/Macintosh HD -> /. Skipped for the whole-root list, per the note above.
|
|
630
651
|
if (!rootScoped.has(resolved) && tooBroadToDeny(resolved, fsRoot)) continue;
|
|
631
652
|
if (resolved === fsRoot) continue; // never the root the workspace lives on
|
|
653
|
+
// Never a directory that CONTAINS home, because denying it denies home (#2637). Removing `/Users`
|
|
654
|
+
// and `/home` from the static list was not enough: the root enumeration re-adds them, since
|
|
655
|
+
// `Users` is not an operational name. That is what still refused `~/git/STYLE_GUIDE.md` at the
|
|
656
|
+
// kernel while `fenceVerdict` said allow — the unit tests use synthetic roots and could not see it.
|
|
657
|
+
if (home !== undefined && pathIsWithin(resolved, home)) continue;
|
|
632
658
|
// A deny beats an allow at EQUAL depth, so denying a root that IS the workspace or IS something
|
|
633
659
|
// the operator granted would not be redundant — it would silently revoke the grant. Deeper is
|
|
634
660
|
// fine and intended: an ancestor deny with the workspace allowed inside it is the normal shape.
|