feat(project): add project trust and restricted execution mode (#517)

Projects now open with a user-owned trust decision. The prompt offers Preview in Restricted Mode, Don't Open and Trust Project, with an optional trusted parent folder; preview is the default focus so Enter never grants trust.

Restricted projects keep browsing, editing, saving, search and highlighting. Project-controlled execution is denied by default in the backend: run, debug, build, tools, language servers, plugins and Git commands that could honour repository configuration. Trusting a project enables those paths without reopening it, and decisions can be revoked in Settings.

Terminals stay available when the user opens one, without project shell settings, environment or virtualenv activation. A shell prompt that runs git in the folder can still honour the repository's core.fsmonitor.

Fixes #462
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-31 20:58:45 +08:00
1 джерело cf51b57924
коміт 2c9a6470ff
103 files changed
+1996 -168

No files matched your search

+2 -2
Переглянути файл
@@ -27,7 +27,7 @@ describe("server status", () => {
afterEach(() => dispose());
it("keeps a status that arrived after the snapshot was requested", async () => {
useProject.setState({ project: { name: "p", root: "/p", isGit: false, settings: {} } as never });
useProject.setState({ project: { name: "p", root: "/p", trusted: true, isGit: false, settings: {} } as never });
dispose = installServerEvents();
const id = 1 as ServerId;
const info: ServerInfo = { id, name: "jdtls", languages: [], root: "/p", status: "starting", pid: null };
@@ -47,7 +47,7 @@ describe("server status", () => {
});
it("drops a server the backend removed, even if an older snapshot still lists it", async () => {
useProject.setState({ project: { name: "p", root: "/p", isGit: false, settings: {} } as never });
useProject.setState({ project: { name: "p", root: "/p", trusted: true, isGit: false, settings: {} } as never });
dispose = installServerEvents();
const info = (id: number, name: string): ServerInfo => ({
id: id as ServerId,