Terminal file viewer/editor + per-window app-command lockdown (#60)
Build App / compute-version (push) Successful in 7s
Secret Scan / scan (push) Successful in 8s
Build App / build-macos (push) Successful in 2m53s
Build App / build-linux (push) Successful in 5m12s
Build App / build-windows (push) Successful in 5m15s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 1m5s

Clicking a file path in Claude's terminal output now opens the file in its own window with a CodeMirror 6 editor. The editor highlights the target line, live-reloads while the file changes, and saves explicitly with hash-based conflict detection. The viewer commands are gated by window label.

Every app command is now ACL-gated per window through a Tauri AppManifest. build.rs checks the handler list against the capability files and fails the build on any mismatch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit was merged in pull request #60.
This commit is contained in:
2026-09-23 17:05:50 +00:00
co-authored by Claude Opus 5.5
parent 3537b234d8
commit 8305c96e20
65 changed files with 15043 additions and 108 deletions
@@ -3,6 +3,7 @@ import {
IMAGE_PREVIEW_LIMIT,
TEXT_PREVIEW_LIMIT,
decodeBase64,
encodeBase64,
extensionOf,
imageMimeFor,
looksBinary,
@@ -76,3 +77,22 @@ describe("decodeBase64 / looksBinary", () => {
expect(looksBinary(bytes)).toBe(false);
});
});
describe("encodeBase64", () => {
it("matches btoa on a small input", () => {
expect(encodeBase64(new Uint8Array([0xff, 0xd8, 0x00, 0x41]))).toBe(btoa("\xff\xd8\x00\x41"));
});
it("round-trips 1 MiB without overflowing the call stack", () => {
// Spreading a 1 MiB array into String.fromCharCode throws RangeError in V8.
const bytes = new Uint8Array(TEXT_PREVIEW_LIMIT);
for (let i = 0; i < bytes.length; i++) bytes[i] = (i * 31 + 7) & 0xff;
const back = decodeBase64(encodeBase64(bytes));
expect(back.length).toBe(bytes.length);
expect(back.every((b, i) => b === bytes[i])).toBe(true);
});
it("encodes an empty input as the empty string", () => {
expect(encodeBase64(new Uint8Array(0))).toBe("");
});
});