windows-development-sandbox 1.11.7 → 1.13.0
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/README.md +13 -6
- package/config.example.json +15 -4
- package/dist/app/features/access/access.def.d.ts +190 -0
- package/dist/app/features/access/access.def.js +273 -0
- package/dist/app/features/access/access.run.d.ts +79 -0
- package/dist/app/features/access/access.run.js +129 -0
- package/dist/app/features/access/index.d.ts +2 -0
- package/dist/app/features/access/index.js +3 -0
- package/dist/app/features/agents/agent-entry.js +5 -0
- package/dist/app/features/agents/agents.def.js +1 -0
- package/dist/app/features/apps/apps-rows.d.ts +4 -1
- package/dist/app/features/apps/apps-rows.js +7 -2
- package/dist/app/features/apps/apps.def.d.ts +19 -0
- package/dist/app/features/apps/apps.def.js +50 -12
- package/dist/app/features/apps/apps.run.d.ts +2 -0
- package/dist/app/features/apps/apps.run.js +1 -1
- package/dist/app/features/audit/audit.def.d.ts +350 -0
- package/dist/app/features/audit/audit.def.js +457 -0
- package/dist/app/features/audit/audit.run.d.ts +110 -0
- package/dist/app/features/audit/audit.run.js +133 -0
- package/dist/app/features/audit/index.d.ts +2 -0
- package/dist/app/features/audit/index.js +3 -0
- package/dist/app/features/defs.d.ts +349 -4
- package/dist/app/features/defs.js +16 -1
- package/dist/app/features/files/files.def.js +1 -0
- package/dist/app/features/health/health.def.js +1 -0
- package/dist/app/features/sandbox/sandbox.def.js +3 -0
- package/dist/app/features/sessions/sessions.def.d.ts +36 -0
- package/dist/app/features/sessions/sessions.def.js +77 -9
- package/dist/app/features/sessions/sessions.run.d.ts +25 -2
- package/dist/app/features/sessions/sessions.run.js +71 -3
- package/dist/app/features/settings/settings.def.d.ts +8 -0
- package/dist/app/features/settings/settings.def.js +17 -0
- package/dist/app/features/settings/settings.run.d.ts +3 -0
- package/dist/app/features/settings/settings.run.js +16 -2
- package/dist/app/features/web/web.def.d.ts +9 -0
- package/dist/app/features/web/web.def.js +26 -1
- package/dist/app/features/web/web.run.d.ts +3 -0
- package/dist/app/features/web/web.run.js +11 -3
- package/dist/app/kernel/access.d.ts +33 -0
- package/dist/app/kernel/access.js +44 -0
- package/dist/app/kernel/define.d.ts +26 -2
- package/dist/app/kernel/index.d.ts +1 -0
- package/dist/app/kernel/index.js +1 -0
- package/dist/app/kernel/rpc.d.ts +5 -2
- package/dist/app/registry.d.ts +4 -1
- package/dist/app/registry.js +26 -4
- package/dist/cli/args.d.ts +0 -3
- package/dist/cli/args.js +3 -4
- package/dist/cli/commands/index.d.ts +1 -1
- package/dist/cli/commands/index.js +1 -1
- package/dist/cli/commands/launch/prepare.js +1 -1
- package/dist/cli/commands/maintenance/index.d.ts +0 -1
- package/dist/cli/commands/maintenance/index.js +0 -1
- package/dist/cli/commands/registry.js +3 -2
- package/dist/cli/commands/remote.d.ts +2 -0
- package/dist/cli/commands/remote.js +49 -0
- package/dist/cli/commands/sessions/reopen.js +3 -0
- package/dist/cli/commands/web.js +66 -0
- package/dist/cli/manifest.d.ts +63 -45
- package/dist/cli/manifest.js +33 -18
- package/dist/cli/menu/io-menu.d.ts +5 -3
- package/dist/cli/menu/io-menu.js +12 -5
- package/dist/cli/menu/pages/apps-page.js +2 -15
- package/dist/cli/menu/pages/maintenance-page.d.ts +4 -0
- package/dist/cli/menu/pages/maintenance-page.js +51 -8
- package/dist/cli/menu/remote-menu.d.ts +19 -0
- package/dist/cli/menu/remote-menu.js +108 -0
- package/dist/cli/menu/views.js +4 -0
- package/dist/cli/operations/handler.js +15 -1
- package/dist/cli/services/remote-client.d.ts +16 -0
- package/dist/cli/services/remote-client.js +141 -0
- package/dist/cli/services/sessions-service.d.ts +5 -0
- package/dist/cli/services/sessions-service.js +17 -1
- package/dist/core/config/defaults.js +12 -2
- package/dist/core/local-config/file.js +16 -2
- package/dist/core/local-config/overrides.js +7 -0
- package/dist/core/run/versions.js +9 -8
- package/dist/core/schema/apps.d.ts +9 -0
- package/dist/core/schema/apps.js +9 -0
- package/dist/core/schema/config.d.ts +23 -3
- package/dist/core/schema/config.js +42 -5
- package/dist/core/schema/sandbox.d.ts +1 -0
- package/dist/core/schema/sandbox.js +11 -3
- package/dist/core/schema/web.d.ts +51 -0
- package/dist/core/schema/web.js +46 -1
- package/dist/core/util/fs.d.ts +5 -0
- package/dist/core/util/fs.js +23 -0
- package/dist/core/util/index.d.ts +1 -1
- package/dist/core/util/index.js +1 -1
- package/dist/guest/apps/app-installer.js +50 -4
- package/dist/guest/apps/index.d.ts +1 -1
- package/dist/guest/apps/index.js +1 -1
- package/dist/guest/apps/sources.js +1 -1
- package/dist/guest/audit/parse.d.ts +32 -2
- package/dist/guest/audit/parse.js +43 -5
- package/dist/guest/audit/process-audit.d.ts +3 -1
- package/dist/guest/audit/process-audit.js +9 -6
- package/dist/guest/boot/boot.js +12 -3
- package/dist/guest/boot/guide.d.ts +1 -1
- package/dist/guest/boot/guide.js +27 -3
- package/dist/guest/daemon/daemon.js +2 -0
- package/dist/guest/daemon/idle-shutdown.js +2 -1
- package/dist/guest/daemon/sessions.d.ts +23 -2
- package/dist/guest/daemon/sessions.js +151 -20
- package/dist/guest/entries/daemon.js +2 -1
- package/dist/guest/git/decision.js +7 -0
- package/dist/guest/sessions/cmdline.d.ts +14 -0
- package/dist/guest/sessions/cmdline.js +10 -0
- package/dist/guest/setup/addon-mcp.d.ts +2 -0
- package/dist/guest/setup/addon-mcp.js +49 -0
- package/dist/guest/setup/agent-addons.d.ts +9 -0
- package/dist/guest/setup/agent-addons.js +22 -0
- package/dist/guest/setup/headroom.d.ts +7 -0
- package/dist/guest/setup/headroom.js +60 -0
- package/dist/guest/setup/managed-policy.d.ts +2 -1
- package/dist/guest/setup/managed-policy.js +15 -6
- package/dist/guest/toolchains/plan.js +8 -3
- package/dist/guest/toolchains/setup.js +3 -0
- package/dist/host/audit/attribute.d.ts +46 -0
- package/dist/host/audit/attribute.js +76 -0
- package/dist/host/audit/collect.d.ts +29 -3
- package/dist/host/audit/collect.js +256 -61
- package/dist/host/audit/git-commits.d.ts +29 -0
- package/dist/host/audit/git-commits.js +157 -0
- package/dist/host/audit/index.d.ts +5 -0
- package/dist/host/audit/index.js +6 -0
- package/dist/host/audit/log.d.ts +45 -7
- package/dist/host/audit/log.js +148 -45
- package/dist/host/audit/redact.d.ts +2 -0
- package/dist/host/audit/redact.js +67 -0
- package/dist/host/channel/channel.d.ts +5 -1
- package/dist/host/channel/channel.js +12 -0
- package/dist/host/guard/agent-files.js +7 -1
- package/dist/host/guard/commands.js +13 -1
- package/dist/host/guard/git-config.js +27 -7
- package/dist/host/guard/git-dirs.js +78 -3
- package/dist/host/guard/mark-of-the-web.js +3 -1
- package/dist/host/guard/nested-repos.js +7 -2
- package/dist/host/guard/store.js +1 -0
- package/dist/host/guard/types.d.ts +2 -0
- package/dist/host/launch/mappings.js +11 -1
- package/dist/host/launch/project-scan.js +2 -21
- package/dist/host/launch/stage.js +4 -0
- package/dist/host/life/session-ledger.js +2 -1
- package/dist/host/remote/access-store.d.ts +156 -0
- package/dist/host/remote/access-store.js +308 -0
- package/dist/host/remote/cert.d.ts +20 -0
- package/dist/host/remote/cert.js +103 -0
- package/dist/host/remote/door-client.d.ts +13 -0
- package/dist/host/remote/door-client.js +54 -0
- package/dist/host/remote/firewall.d.ts +44 -0
- package/dist/host/remote/firewall.js +118 -0
- package/dist/host/remote/gate.d.ts +125 -0
- package/dist/host/remote/gate.js +391 -0
- package/dist/host/remote/index.d.ts +8 -0
- package/dist/host/remote/index.js +10 -0
- package/dist/host/remote/lan.d.ts +24 -0
- package/dist/host/remote/lan.js +88 -0
- package/dist/host/remote/tls-store.d.ts +22 -0
- package/dist/host/remote/tls-store.js +63 -0
- package/dist/host/remote/windows-helper.d.ts +67 -0
- package/dist/host/remote/windows-helper.js +129 -0
- package/dist/host/web/bridge.d.ts +5 -1
- package/dist/host/web/bridge.js +6 -2
- package/dist/host/web/browser.js +1 -1
- package/dist/host/web/control.d.ts +4 -1
- package/dist/host/web/control.js +28 -4
- package/dist/host/web/rpc.d.ts +16 -2
- package/dist/host/web/rpc.js +37 -4
- package/dist/host/web/runner.d.ts +4 -0
- package/dist/host/web/runner.js +12 -0
- package/dist/host/web/server.d.ts +18 -2
- package/dist/host/web/server.js +97 -24
- package/dist/host/web/state.d.ts +5 -0
- package/dist/host/web/state.js +8 -0
- package/dist/runtime/agent.js +184 -18
- package/dist/runtime/daemon.js +772 -338
- package/dist/runtime/db.js +184 -18
- package/dist/runtime/gitguard.js +6 -0
- package/dist/runtime/main.js +966 -553
- package/dist/runtime/netproxy.js +184 -18
- package/dist/runtime/view.js +186 -18
- package/dist/selftest/app.test.js +66 -7
- package/dist/selftest/audit.test.js +354 -47
- package/dist/selftest/channel.test.js +16 -0
- package/dist/selftest/cmdline.test.js +16 -0
- package/dist/selftest/git-access.test.js +8 -0
- package/dist/selftest/hcs.test.js +35 -0
- package/dist/selftest/hostile-input.test.js +12 -1
- package/dist/selftest/index.js +2 -0
- package/dist/selftest/live-daemon.test.js +25 -0
- package/dist/selftest/local-config.test.js +30 -0
- package/dist/selftest/menu-screens.js +1 -1
- package/dist/selftest/menu.test.js +3 -3
- package/dist/selftest/remote.test.d.ts +2 -0
- package/dist/selftest/remote.test.js +536 -0
- package/dist/selftest/repo-guard.test.js +56 -2
- package/dist/selftest/resume.test.js +2 -1
- package/dist/selftest/sharing.test.js +9 -2
- package/dist/selftest/support/engine-golden.js +9 -0
- package/dist/selftest/support/fixtures.d.ts +14 -0
- package/dist/selftest/support/web-preview.js +157 -0
- package/dist/selftest/toolchains.test.js +147 -2
- package/dist/selftest/web.test.js +2 -0
- package/dist/shared/apps/agent-addons.d.ts +64 -0
- package/dist/shared/apps/agent-addons.js +95 -0
- package/dist/shared/apps/catalogue.d.ts +33 -2
- package/dist/shared/apps/catalogue.js +102 -11
- package/dist/shared/apps/index.d.ts +3 -2
- package/dist/shared/apps/index.js +3 -2
- package/dist/shared/apps/selection.d.ts +2 -0
- package/dist/shared/apps/selection.js +7 -0
- package/dist/shared/channel/schema.d.ts +23 -0
- package/dist/shared/channel/schema.js +8 -0
- package/dist/shared/pty/protocol.d.ts +2 -0
- package/dist/shared/pty/protocol.js +2 -0
- package/dist/sync/watcher.js +9 -1
- package/dist/web/index.html +2 -2
- package/dist/web/{main-RQFN4WBY.css → main-UAQPI5XD.css} +1 -1
- package/dist/web/main-Z2WYAE2Z.js +221 -0
- package/native/csharp/HcsHost/AssemblyInfo.cs +5 -3
- package/native/csharp/HcsHost/Hcs.cs +9 -0
- package/native/csharp/HcsHost/Program.cs +26 -1
- package/native/csharp/HcsHost/Share.cs +173 -0
- package/native/csharp/HostTools/AssemblyInfo.cs +3 -3
- package/native/csharp/HostTools/Program.cs +17 -1
- package/native/csharp/HostTools/WebHelper.cs +499 -0
- package/native/scripts/get-network-profile.ps1 +19 -0
- package/native/scripts/set-folder-access.ps1 +11 -0
- package/native/scripts/set-web-firewall.ps1 +103 -0
- package/package.json +1 -1
- package/sandbox/addons/ccusage/package-lock.json +111 -0
- package/sandbox/addons/ccusage/package.json +7 -0
- package/sandbox/addons/context7/package-lock.json +1313 -0
- package/sandbox/addons/context7/package.json +7 -0
- package/sandbox/addons/headroom/requirements.in +1 -0
- package/sandbox/addons/headroom/requirements.txt +2922 -0
- package/sandbox/addons/playwright-mcp/package-lock.json +56 -0
- package/sandbox/addons/playwright-mcp/package.json +7 -0
- package/sandbox/csharp/PtyHost.cs +20 -0
- package/schemas/config.schema.json +78 -4
- package/schemas/sandbox-config.schema.json +2 -20
- package/dist/cli/commands/maintenance/audit.d.ts +0 -3
- package/dist/cli/commands/maintenance/audit.js +0 -58
- package/dist/web/main-K2JMCAZI.js +0 -219
|
@@ -10,6 +10,9 @@ export declare const webStatusRun: import("../../kernel/define.js").Implementati
|
|
|
10
10
|
running: import("zod").ZodBoolean;
|
|
11
11
|
port: import("zod").ZodNullable<import("zod").ZodNumber>;
|
|
12
12
|
address: import("zod").ZodNullable<import("zod").ZodString>;
|
|
13
|
+
lanAddress: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
14
|
+
lanFingerprint: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
15
|
+
lanProblem: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
13
16
|
}, import("zod/v4/core").$strip>, "web.status">, import("../../../cli/commands/context.js").Context>;
|
|
14
17
|
export declare const startWebRun: import("../../kernel/define.js").Implementation<import("../../kernel/define.js").OperationDef<import("zod").ZodObject<{}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
15
18
|
port: import("zod").ZodNumber;
|
|
@@ -60,7 +60,15 @@ export const webStatusRun = implement(webStatus, async (ctx) => {
|
|
|
60
60
|
requireOnPc('web');
|
|
61
61
|
const { running, state } = await controlOf(ctx).status();
|
|
62
62
|
const port = running && state ? state.port : null;
|
|
63
|
-
|
|
63
|
+
const lan = running ? (state?.lan ?? null) : null;
|
|
64
|
+
return {
|
|
65
|
+
running,
|
|
66
|
+
port,
|
|
67
|
+
address: port ? 'http://127.0.0.1:' + port + '/' : null,
|
|
68
|
+
lanAddress: lan?.url ?? null,
|
|
69
|
+
lanFingerprint: lan?.fingerprint ?? null,
|
|
70
|
+
lanProblem: lan?.problem ?? null,
|
|
71
|
+
};
|
|
64
72
|
});
|
|
65
73
|
export const startWebRun = implement(startWeb, async (ctx, _input, io) => {
|
|
66
74
|
requireOnPc('web');
|
|
@@ -73,8 +81,8 @@ export const openWebRun = implement(openWeb, async (ctx, _input, io) => {
|
|
|
73
81
|
const started = await startServer(ctx, io, control);
|
|
74
82
|
if (started.wasRunning)
|
|
75
83
|
io.log(started.message);
|
|
76
|
-
const { state } = await control.status();
|
|
77
|
-
if (!state)
|
|
84
|
+
const { running, state } = await control.status();
|
|
85
|
+
if (!running || !state)
|
|
78
86
|
return fail('The web UI stopped right away.', 'Run sandbox web start again.');
|
|
79
87
|
openBrowser(control.url(state));
|
|
80
88
|
return { message: 'Opened in your browser.' };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** What a definition needs. Default (fails closed): a query needs view, an operation owner. */
|
|
2
|
+
export type Access = 'view' | 'control' | 'owner';
|
|
3
|
+
/** A role the owner can give: view only, or full control (everything but the owner's own things). */
|
|
4
|
+
export type RemoteRole = 'view' | 'control';
|
|
5
|
+
/** Who runs a definition: the owner, or someone the owner let in. */
|
|
6
|
+
export type Caller = {
|
|
7
|
+
readonly kind: 'owner';
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: 'windows';
|
|
10
|
+
readonly user: string;
|
|
11
|
+
readonly role: RemoteRole;
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: 'device';
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly role: RemoteRole;
|
|
17
|
+
};
|
|
18
|
+
export declare const OWNER: Caller;
|
|
19
|
+
/** A definition's need, as written: fixed, or from its input (settings.set on a web.* key needs owner). */
|
|
20
|
+
export type AccessRule = Access | ((input: unknown) => Access);
|
|
21
|
+
/** The most a caller may do. */
|
|
22
|
+
export declare function callerAccess(caller: Caller): Access;
|
|
23
|
+
/** The caller may run something that needs `need`. */
|
|
24
|
+
export declare function allows(caller: Caller, need: Access): boolean;
|
|
25
|
+
/** What a definition needs for this input. A rule that throws on a strange input needs owner. */
|
|
26
|
+
export declare function accessNeeded(def: {
|
|
27
|
+
readonly kind: 'operation' | 'query';
|
|
28
|
+
readonly access?: AccessRule;
|
|
29
|
+
}, input: unknown): Access;
|
|
30
|
+
/** Who the caller is, in a few words (the audit log, the page's header). */
|
|
31
|
+
export declare function callerLabel(caller: Caller): string;
|
|
32
|
+
/** The refusal text for a caller that may not. */
|
|
33
|
+
export declare function refusalText(caller: Caller, need: Access): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Who may run what (docs/design/remote-access.md): every definition needs view, control or owner; the caller of a run
|
|
2
|
+
// has a role. The owner (at the PC, or through the token link) may do everything; another Windows user of this PC or a
|
|
3
|
+
// paired device has the role the owner gave them, never owner. Pure (the web bundle shows what the role allows).
|
|
4
|
+
export const OWNER = { kind: 'owner' };
|
|
5
|
+
const RANK = { view: 0, control: 1, owner: 2 };
|
|
6
|
+
/** The most a caller may do. */
|
|
7
|
+
export function callerAccess(caller) {
|
|
8
|
+
return caller.kind === 'owner' ? 'owner' : caller.role;
|
|
9
|
+
}
|
|
10
|
+
/** The caller may run something that needs `need`. */
|
|
11
|
+
export function allows(caller, need) {
|
|
12
|
+
return RANK[callerAccess(caller)] >= RANK[need];
|
|
13
|
+
}
|
|
14
|
+
/** What a definition needs for this input. A rule that throws on a strange input needs owner. */
|
|
15
|
+
export function accessNeeded(def, input) {
|
|
16
|
+
const rule = def.access;
|
|
17
|
+
if (rule === undefined)
|
|
18
|
+
return def.kind === 'query' ? 'view' : 'owner';
|
|
19
|
+
if (typeof rule === 'string')
|
|
20
|
+
return rule;
|
|
21
|
+
try {
|
|
22
|
+
return rule(input);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return 'owner';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Who the caller is, in a few words (the audit log, the page's header). */
|
|
29
|
+
export function callerLabel(caller) {
|
|
30
|
+
switch (caller.kind) {
|
|
31
|
+
case 'owner':
|
|
32
|
+
return 'you';
|
|
33
|
+
case 'windows':
|
|
34
|
+
return 'Windows user ' + caller.user;
|
|
35
|
+
case 'device':
|
|
36
|
+
return 'device ' + caller.name;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** The refusal text for a caller that may not. */
|
|
40
|
+
export function refusalText(caller, need) {
|
|
41
|
+
if (need === 'owner')
|
|
42
|
+
return 'Only the owner of this PC can do that, at the PC.';
|
|
43
|
+
return callerAccess(caller) === 'view' ? 'Your access is view only.' : 'You may not do that.';
|
|
44
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { z } from 'zod';
|
|
2
|
+
import type { AccessRule } from './access.js';
|
|
2
3
|
import type { OperationIO } from './io.js';
|
|
3
|
-
import type { Page } from './view.js';
|
|
4
|
+
import type { Page, Target } from './view.js';
|
|
4
5
|
export type SurfaceName = 'cli' | 'menu' | 'web';
|
|
5
6
|
export declare const SURFACE_NAMES: readonly SurfaceName[];
|
|
6
7
|
/** Where a definition is offered: everywhere, or everywhere but these surfaces (each with the reason). */
|
|
@@ -63,6 +64,11 @@ interface Definition<Id extends string, I extends z.ZodType, O extends z.ZodType
|
|
|
63
64
|
readonly output: O;
|
|
64
65
|
/** Default: every surface. */
|
|
65
66
|
readonly surfaces?: Surfaces;
|
|
67
|
+
/**
|
|
68
|
+
* What a caller other than the owner needs (docs/design/remote-access.md). Default (fails closed): view for a query,
|
|
69
|
+
* owner for an operation; an operation says 'control' to be open to someone the owner gave control.
|
|
70
|
+
*/
|
|
71
|
+
readonly access?: AccessRule;
|
|
66
72
|
readonly cli?: CliHint;
|
|
67
73
|
/** The output in one text: what an operation did, or a value a query read (CLI output, menu notice, web note). */
|
|
68
74
|
text?(output: z.output<O>): string;
|
|
@@ -77,6 +83,13 @@ export interface OperationDef<I extends z.ZodType = z.ZodType, O extends z.ZodTy
|
|
|
77
83
|
readonly kind: 'operation';
|
|
78
84
|
/** Shown as dangerous (red); it asks for its own confirmation through io.confirm. */
|
|
79
85
|
readonly danger?: boolean;
|
|
86
|
+
/** Its result must stay on screen until dismissed (a one-time code to type elsewhere): the web keeps it open. */
|
|
87
|
+
readonly keepResult?: boolean;
|
|
88
|
+
/**
|
|
89
|
+
* Where every surface goes once it succeeded: a new session's terminal is attached on the command line and in the
|
|
90
|
+
* menu, and opened in the web UI.
|
|
91
|
+
*/
|
|
92
|
+
opens?(output: z.output<O>): Target | undefined;
|
|
80
93
|
}
|
|
81
94
|
export interface QueryDef<I extends z.ZodType = z.ZodType, O extends z.ZodType = z.ZodType, Id extends string = string> extends Definition<Id, I, O> {
|
|
82
95
|
readonly kind: 'query';
|
|
@@ -103,6 +116,15 @@ export interface ViewTabs<P> {
|
|
|
103
116
|
readonly label: string;
|
|
104
117
|
}[];
|
|
105
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* A filter of a view: one parameter picked from fixed values (the audit's kind and period). The web shows a small
|
|
121
|
+
* choice per filter above the page (changing one keeps the view's other parameters); the command line has the query's
|
|
122
|
+
* flags for the same thing, and the menu shows the first value. The first value is the default.
|
|
123
|
+
*/
|
|
124
|
+
export interface ViewFilter<P> extends ViewTabs<P> {
|
|
125
|
+
/** What the choice is about ("Period"), for its label. */
|
|
126
|
+
readonly label: string;
|
|
127
|
+
}
|
|
106
128
|
export interface ViewDef<Q extends QueryMap = QueryMap, P = Record<string, never>, Id extends string = string> {
|
|
107
129
|
readonly kind: 'view';
|
|
108
130
|
readonly id: Id;
|
|
@@ -115,7 +137,9 @@ export interface ViewDef<Q extends QueryMap = QueryMap, P = Record<string, never
|
|
|
115
137
|
readonly pickers?: readonly QueryDef[];
|
|
116
138
|
/** A parameter switched with tabs above the page (Settings: all projects or this project), first choice default. */
|
|
117
139
|
readonly tabs?: ViewTabs<P>;
|
|
118
|
-
/** Parameters
|
|
140
|
+
/** Parameters picked from fixed values above the page (the audit's kind and period), first value default. */
|
|
141
|
+
readonly filters?: readonly ViewFilter<P>[];
|
|
142
|
+
/** Parameters taken from the address as they are (the log shown), besides the tabs' and filters' ones. */
|
|
119
143
|
readonly params?: readonly (keyof P & string)[];
|
|
120
144
|
/** The input of each query for these view parameters (default: each query's defaults). */
|
|
121
145
|
inputs?(params: P): ViewInputs<Q>;
|
package/dist/app/kernel/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// The kernel of the shared core: pure (zod and nothing of Node, the terminal or the DOM), so the CLI, the menu, the
|
|
2
2
|
// web server and the browser all import the same definitions, view model, form fields, questions and RPC messages.
|
|
3
|
+
export * from './access.js';
|
|
3
4
|
export * from './define.js';
|
|
4
5
|
export * from './errors.js';
|
|
5
6
|
export * from './fields.js';
|
package/dist/app/kernel/rpc.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import type { Access, Caller } from './access.js';
|
|
2
3
|
import { type OperationIO } from './io.js';
|
|
3
4
|
/** One call or subscription on the socket (chosen by the browser, unique while it runs). */
|
|
4
5
|
export declare const RpcIdSchema: z.ZodString;
|
|
@@ -168,6 +169,8 @@ export interface RpcHost {
|
|
|
168
169
|
kind(id: string): 'operation' | 'query' | undefined;
|
|
169
170
|
/** How often a query is read again while subscribed (undefined: once). */
|
|
170
171
|
liveMs(id: string): number | undefined;
|
|
171
|
-
/**
|
|
172
|
-
|
|
172
|
+
/** What a caller other than the owner needs to run it with this input (undefined: not here). */
|
|
173
|
+
need(id: string, input: unknown): Access | undefined;
|
|
174
|
+
/** Runs an allowed definition (input and output checked); refused when `caller` (default: the owner) may not. */
|
|
175
|
+
run(id: string, input: unknown, io: OperationIO, caller?: Caller): Promise<unknown>;
|
|
173
176
|
}
|
package/dist/app/registry.d.ts
CHANGED
|
@@ -6,5 +6,8 @@ export declare function implementationOf(id: string): Implementation<AnyDefiniti
|
|
|
6
6
|
export declare function runDefinition(id: string, ctx: AppContext, input: unknown, io: OperationIO): Promise<unknown>;
|
|
7
7
|
/** Reads a query in-process (the menu): typed output, and no questions. */
|
|
8
8
|
export declare function readQuery<D extends QueryDef>(def: D, ctx: AppContext, input?: unknown): Promise<OutputOf<D>>;
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* What the web server may run: the registered definitions whose surfaces include the web, each refused to a caller
|
|
11
|
+
* whose role does not reach what it needs (docs/design/remote-access.md).
|
|
12
|
+
*/
|
|
10
13
|
export declare function createRpcHost(ctx: AppContext): RpcHost;
|
package/dist/app/registry.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { fail } from '../core/util/errors.js';
|
|
2
|
+
import { accessNeeded, allows, invoke, OWNER, refusalText, NO_QUESTIONS, onSurface, } from './kernel/index.js';
|
|
2
3
|
import { addAgentRun, listAgentsRun, makeDefaultAgentRun, removeAgentRun, startAgentRun, } from './features/agents/index.js';
|
|
3
4
|
import { defaultAccountRun, listAccountsRun, removeAccountRun, renameAccountRun, saveAccountRun, useAccountRun, } from './features/accounts/index.js';
|
|
4
5
|
import { listAppsRun, requestAppRun, setCustomAppsRun, toggleAppRun } from './features/apps/index.js';
|
|
@@ -9,13 +10,15 @@ import { addProjectRun, allProjectsRun, chooseProjectsRun, excludeProjectRun, in
|
|
|
9
10
|
import { checkHealthRun, enableSandboxRun, lastHealthRun, repairHealthRun } from './features/health/index.js';
|
|
10
11
|
import { hideWindowRun, sandboxStatusRun, showWindowRun, stopSandboxRun } from './features/sandbox/index.js';
|
|
11
12
|
import { listLogsRun, tailLogRun } from './features/logs/index.js';
|
|
12
|
-
import {
|
|
13
|
+
import { listAuditRun } from './features/audit/index.js';
|
|
14
|
+
import { closeSessionRun, listSessionsRun, restartSessionsRun, startShellRun } from './features/sessions/index.js';
|
|
13
15
|
import { exportConfigRun, getSettingRun, importConfigRun, listSettingsRun, resetSettingRun, setSettingRun, } from './features/settings/index.js';
|
|
14
16
|
import { migrateSettingsRun, runUpdateRun, updatesStatusRun } from './features/updates/index.js';
|
|
15
17
|
import { checkEngineRun, cleanEngineRun, engineLeftoversRun, engineStatusRun } from './features/engine/index.js';
|
|
16
18
|
import { openWebRun, startWebRun, stopWebRun, webStatusRun } from './features/web/index.js';
|
|
17
19
|
import { vpnLoginRun, vpnLogoutRun, vpnStatusRun } from './features/vpn/index.js';
|
|
18
20
|
import { githubLoginRun, githubLogoutRun, githubStatusRun } from './features/github/index.js';
|
|
21
|
+
import { accessStatusRun, allowDeviceRun, lanOffRun, lanOnRun, revokeAccessRun, revokeAllAccessRun, } from './features/access/index.js';
|
|
19
22
|
export const IMPLEMENTATIONS = [
|
|
20
23
|
sandboxStatusRun,
|
|
21
24
|
showWindowRun,
|
|
@@ -23,6 +26,8 @@ export const IMPLEMENTATIONS = [
|
|
|
23
26
|
stopSandboxRun,
|
|
24
27
|
listSessionsRun,
|
|
25
28
|
restartSessionsRun,
|
|
29
|
+
startShellRun,
|
|
30
|
+
closeSessionRun,
|
|
26
31
|
startAgentRun,
|
|
27
32
|
addAgentRun,
|
|
28
33
|
makeDefaultAgentRun,
|
|
@@ -69,6 +74,7 @@ export const IMPLEMENTATIONS = [
|
|
|
69
74
|
containedOffRun,
|
|
70
75
|
listLogsRun,
|
|
71
76
|
tailLogRun,
|
|
77
|
+
listAuditRun,
|
|
72
78
|
runUpdateRun,
|
|
73
79
|
migrateSettingsRun,
|
|
74
80
|
updatesStatusRun,
|
|
@@ -86,6 +92,12 @@ export const IMPLEMENTATIONS = [
|
|
|
86
92
|
githubLoginRun,
|
|
87
93
|
githubLogoutRun,
|
|
88
94
|
webStatusRun,
|
|
95
|
+
accessStatusRun,
|
|
96
|
+
allowDeviceRun,
|
|
97
|
+
revokeAccessRun,
|
|
98
|
+
revokeAllAccessRun,
|
|
99
|
+
lanOnRun,
|
|
100
|
+
lanOffRun,
|
|
89
101
|
];
|
|
90
102
|
export function implementationOf(id) {
|
|
91
103
|
return IMPLEMENTATIONS.find((i) => i.def.id === id);
|
|
@@ -101,7 +113,10 @@ export function runDefinition(id, ctx, input, io) {
|
|
|
101
113
|
export async function readQuery(def, ctx, input = {}) {
|
|
102
114
|
return (await runDefinition(def.id, ctx, input, NO_QUESTIONS));
|
|
103
115
|
}
|
|
104
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* What the web server may run: the registered definitions whose surfaces include the web, each refused to a caller
|
|
118
|
+
* whose role does not reach what it needs (docs/design/remote-access.md).
|
|
119
|
+
*/
|
|
105
120
|
export function createRpcHost(ctx) {
|
|
106
121
|
const allowed = (id) => {
|
|
107
122
|
const impl = implementationOf(id);
|
|
@@ -113,10 +128,17 @@ export function createRpcHost(ctx) {
|
|
|
113
128
|
const def = allowed(id)?.def;
|
|
114
129
|
return def?.kind === 'query' ? def.live?.everyMs : undefined;
|
|
115
130
|
},
|
|
116
|
-
|
|
131
|
+
need: (id, input) => {
|
|
132
|
+
const impl = allowed(id);
|
|
133
|
+
return impl ? accessNeeded(impl.def, input) : undefined;
|
|
134
|
+
},
|
|
135
|
+
run: async (id, input, io, caller = OWNER) => {
|
|
117
136
|
const impl = allowed(id);
|
|
118
137
|
if (!impl)
|
|
119
138
|
throw new Error('Not allowed on the web: ' + id);
|
|
139
|
+
const need = accessNeeded(impl.def, input);
|
|
140
|
+
if (!allows(caller, need))
|
|
141
|
+
fail(refusalText(caller, need));
|
|
120
142
|
return invoke(impl, ctx, input, io);
|
|
121
143
|
},
|
|
122
144
|
};
|
package/dist/cli/args.d.ts
CHANGED
|
@@ -42,9 +42,6 @@ export interface CliOptions {
|
|
|
42
42
|
all: boolean;
|
|
43
43
|
/** launch --session <agent>@<folder> (repeatable): several sessions at once, folders made absolute. */
|
|
44
44
|
sessions: SessionWant[];
|
|
45
|
-
/** audit: only events of this kind, and containing this text. */
|
|
46
|
-
kind?: string;
|
|
47
|
-
grep?: string;
|
|
48
45
|
/** migrate --dry-run, and --restore <backup folder>. */
|
|
49
46
|
dryRun: boolean;
|
|
50
47
|
/** doctor --fix: repair what it finds without asking. */
|
package/dist/cli/args.js
CHANGED
|
@@ -217,11 +217,10 @@ export function parseCli(argv, wrapper = false) {
|
|
|
217
217
|
keepOld: Boolean(o.keepOld),
|
|
218
218
|
withPaths: Boolean(o.withPaths),
|
|
219
219
|
all: Boolean(o.all),
|
|
220
|
-
|
|
220
|
+
// launch --session is repeatable (a list); `audit --session <id>` is one id, which its definition reads.
|
|
221
|
+
sessions: (Array.isArray(o.session) ? o.session : []).map((s) => parseSessionWant(s)),
|
|
221
222
|
timeout: o.timeout ?? 600,
|
|
222
|
-
days: o.days ??
|
|
223
|
-
kind: o.kind,
|
|
224
|
-
grep: o.grep,
|
|
223
|
+
days: o.days ?? 7,
|
|
225
224
|
dryRun: Boolean(o.dryRun),
|
|
226
225
|
fix: Boolean(o.fix),
|
|
227
226
|
auto: o.auto === true,
|
|
@@ -6,6 +6,6 @@ export { repairCommand } from './repair/index.js';
|
|
|
6
6
|
export { contextOrDefaults } from './context.js';
|
|
7
7
|
export { attach, db, exec } from './sessions/index.js';
|
|
8
8
|
export { resume } from './resume.js';
|
|
9
|
-
export {
|
|
9
|
+
export { claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
|
|
10
10
|
export { agentCommandsCommand, syncAgentCommands } from './agent-commands.js';
|
|
11
11
|
export { HANDLERS, type Handler } from './registry.js';
|
|
@@ -6,6 +6,6 @@ export { repairCommand } from './repair/index.js';
|
|
|
6
6
|
export { contextOrDefaults } from './context.js';
|
|
7
7
|
export { attach, db, exec } from './sessions/index.js';
|
|
8
8
|
export { resume } from './resume.js';
|
|
9
|
-
export {
|
|
9
|
+
export { claudeHost, config, doctor, hostCommand, logs, migrateBeforeCommand, sync, updatesBeforeCommand, watcher, } from './maintenance/index.js';
|
|
10
10
|
export { agentCommandsCommand, syncAgentCommands } from './agent-commands.js';
|
|
11
11
|
export { HANDLERS } from './registry.js';
|
|
@@ -7,7 +7,7 @@ import { RepoGuardStore, readDataSize, saveMarkedProjects } from '../../../host/
|
|
|
7
7
|
import { ensureConpty, ensureTerminal } from '../../../host/tools/index.js';
|
|
8
8
|
import { planView, viewSkipped, saveActiveViews, WorkspaceView } from '../../../host/workspace-view/index.js';
|
|
9
9
|
import { saveForwards } from '../../../host/network/index.js';
|
|
10
|
-
import { saveAuditSettings } from '../../../host/audit/
|
|
10
|
+
import { saveAuditSettings } from '../../../host/audit/index.js';
|
|
11
11
|
import { humanBytes } from '../../../core/disk.js';
|
|
12
12
|
import { syncBeforeLaunch, watcherRunning } from '../../../sync/index.js';
|
|
13
13
|
import { errMsg } from '../../../core/util/index.js';
|
|
@@ -8,13 +8,14 @@ import { containedStatus, showStorage } from '../../app/features/storage/index.j
|
|
|
8
8
|
import { listProjects } from '../../app/features/projects/index.js';
|
|
9
9
|
import { definitionHandler } from '../operations/index.js';
|
|
10
10
|
import { fail } from '../../core/util/index.js';
|
|
11
|
-
import {
|
|
11
|
+
import { claudeHost, config, doctor, hostCommand, logs, sync, watcher } from './maintenance/index.js';
|
|
12
12
|
import { engine } from './engine.js';
|
|
13
13
|
import { resume } from './resume.js';
|
|
14
14
|
import { agentCommandsCommand } from './agent-commands.js';
|
|
15
15
|
import { vpn } from './vpn.js';
|
|
16
16
|
import { github } from './github.js';
|
|
17
17
|
import { web, webServer } from './web.js';
|
|
18
|
+
import { remote } from './remote.js';
|
|
18
19
|
export const HANDLERS = {
|
|
19
20
|
launch: (ctx) => launch(ctx),
|
|
20
21
|
generate: (ctx) => launch(ctx, true),
|
|
@@ -29,7 +30,6 @@ export const HANDLERS = {
|
|
|
29
30
|
projects: definitionHandler(listProjects),
|
|
30
31
|
sync: sync,
|
|
31
32
|
logs: logs,
|
|
32
|
-
audit: audit,
|
|
33
33
|
config: config,
|
|
34
34
|
doctor: doctor,
|
|
35
35
|
setup: setup,
|
|
@@ -55,5 +55,6 @@ export const HANDLERS = {
|
|
|
55
55
|
vpn: vpn,
|
|
56
56
|
github: github,
|
|
57
57
|
web: web,
|
|
58
|
+
remote: remote,
|
|
58
59
|
_web: webServer,
|
|
59
60
|
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// `sandbox remote [user] [--browser]`: another Windows user's program, used from here (docs/design/remote-access.md).
|
|
2
|
+
// Windows sign-in through the owner's pipe gives a one-time token; the menu then runs over the owner's web UI (every
|
|
3
|
+
// action checked against the role the owner gave, and written to their audit log), or --browser opens it signed in.
|
|
4
|
+
import { allows } from '../../app/kernel/index.js';
|
|
5
|
+
import { fail, safeText } from '../../core/util/index.js';
|
|
6
|
+
import { knockOnDoor } from '../../host/remote/index.js';
|
|
7
|
+
import { currentUserName, runningOwner } from '../../host/sharing/index.js';
|
|
8
|
+
import { openBrowser } from '../../host/web/index.js';
|
|
9
|
+
import { RemoteMenu } from '../menu/remote-menu.js';
|
|
10
|
+
import { remoteClient } from '../services/remote-client.js';
|
|
11
|
+
import { App } from '../tui/index.js';
|
|
12
|
+
import { requireOnPc } from './context.js';
|
|
13
|
+
/** Whose program: the user named, else the owner of the running sandbox when it is someone else's. */
|
|
14
|
+
function ownerOf(ctx) {
|
|
15
|
+
const named = ctx.options.positionals[0];
|
|
16
|
+
if (named)
|
|
17
|
+
return { name: named, id: named };
|
|
18
|
+
const owner = runningOwner();
|
|
19
|
+
if (owner.kind === 'other')
|
|
20
|
+
return { name: owner.user, id: owner.record.sid };
|
|
21
|
+
return fail('Whose web UI? No sandbox of another user is running.', 'Name them: sandbox remote <their Windows user name>');
|
|
22
|
+
}
|
|
23
|
+
export async function remote(ctx) {
|
|
24
|
+
requireOnPc('remote');
|
|
25
|
+
const owner = ownerOf(ctx);
|
|
26
|
+
const answer = await knockOnDoor(ctx.storageRoot, owner.id);
|
|
27
|
+
if (!answer.ok)
|
|
28
|
+
return fail(safeText(answer.reason), 'Ask ' +
|
|
29
|
+
safeText(owner.name) +
|
|
30
|
+
' to turn on web.remote.windowsSignIn, add you to web.remote.users and start the web UI.');
|
|
31
|
+
if (ctx.options.raw.browser === true) {
|
|
32
|
+
openBrowser('http://127.0.0.1:' + answer.port + '/#w=' + answer.token);
|
|
33
|
+
console.log('Opened ' + safeText(owner.name) + "'s web UI in your browser (" + answer.role + '). It runs as them, not you.');
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
const client = await remoteClient(answer.port, answer.token);
|
|
37
|
+
const caller = { kind: 'windows', user: currentUserName(), role: answer.role };
|
|
38
|
+
const app = new App();
|
|
39
|
+
try {
|
|
40
|
+
await new RemoteMenu(app, ctx, client, owner.name, caller).start();
|
|
41
|
+
}
|
|
42
|
+
finally {
|
|
43
|
+
app.close();
|
|
44
|
+
client.close();
|
|
45
|
+
}
|
|
46
|
+
if (!allows(caller, 'control'))
|
|
47
|
+
console.log('You had view access: nothing was changed.');
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
@@ -8,6 +8,9 @@ import { c } from '../../output/index.js';
|
|
|
8
8
|
/** Where each running session is on this PC, so it can be reopened after a restart. */
|
|
9
9
|
export function sessionsToReopen(registry, sessions) {
|
|
10
10
|
return sessions.flatMap((s) => {
|
|
11
|
+
// Shells are not reopened: a new one would not be the one that ended.
|
|
12
|
+
if (s.kind === 'shell')
|
|
13
|
+
return [];
|
|
11
14
|
const project = projectForGuestDir([...registry.projects, ...registry.roots.map((r) => ({ ...r }))], s.cwd);
|
|
12
15
|
return project
|
|
13
16
|
? [
|
package/dist/cli/commands/web.js
CHANGED
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
// running when no sandbox does. startWebOnLaunch is the sandbox start's hook.
|
|
4
4
|
import fs from 'node:fs';
|
|
5
5
|
import path from 'node:path';
|
|
6
|
+
import { accessStoreOf } from '../../app/features/access/index.js';
|
|
6
7
|
import { currentServer, START_WAIT_MS, webStatus } from '../../app/features/web/index.js';
|
|
7
8
|
import { createRpcHost } from '../../app/registry.js';
|
|
9
|
+
import { loadConfig } from '../../core/config/index.js';
|
|
8
10
|
import { packageVersion } from '../../core/package-info.js';
|
|
9
11
|
import { sleep, fail } from '../../core/util/index.js';
|
|
12
|
+
import { AuditLog } from '../../host/audit/index.js';
|
|
13
|
+
import { doorPipeName, HostToolsHelper, networkProfile, RemoteGate, TlsStore, } from '../../host/remote/index.js';
|
|
14
|
+
import { SecretStore } from '../../host/secrets/index.js';
|
|
15
|
+
import { currentUserSid } from '../../host/sharing/index.js';
|
|
10
16
|
import { IDLE_EXIT_MS, openBrowser, WebControl, WebRunner, WebStore } from '../../host/web/index.js';
|
|
11
17
|
import { spawnDetached } from '../../host/sandbox/index.js';
|
|
12
18
|
import { WebService } from '../services/index.js';
|
|
@@ -53,6 +59,65 @@ export async function startWebOnLaunch(ctx) {
|
|
|
53
59
|
export async function web(ctx) {
|
|
54
60
|
return (await definitionHandler(webStatus)(ctx)) ?? 0;
|
|
55
61
|
}
|
|
62
|
+
/** The remote settings as in the file now (read again at most every 3 seconds; a broken file keeps the last). */
|
|
63
|
+
function remoteSettings(ctx) {
|
|
64
|
+
let last = ctx.loaded.config.web.remote;
|
|
65
|
+
let readAt = Date.now();
|
|
66
|
+
return () => {
|
|
67
|
+
if (Date.now() - readAt < 3000)
|
|
68
|
+
return last;
|
|
69
|
+
readAt = Date.now();
|
|
70
|
+
try {
|
|
71
|
+
last = loadConfig(ctx.options.config).config.web.remote;
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// A settings file being edited or broken: keep what was read last.
|
|
75
|
+
}
|
|
76
|
+
return last;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Remote actions go to the audit log of this data set (k: remote), so the Activity page shows who did what. */
|
|
80
|
+
function remoteAudit(ctx) {
|
|
81
|
+
const { days, maxMb } = ctx.loaded.config.audit;
|
|
82
|
+
const log = new AuditLog(AuditLog.dirFor(ctx.storageRoot, ctx.dataPath), { days, maxMb });
|
|
83
|
+
return (entry) => {
|
|
84
|
+
try {
|
|
85
|
+
log.append([{ t: new Date().toISOString(), k: 'remote', p: entry.what, a: entry.outcome, au: entry.who }]);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// The audit log is a record, never a reason for a request to fail.
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The gate for other Windows users and devices (docs/design/remote-access.md). The Windows helper is started when it
|
|
94
|
+
* can be built here: then the owner's own cookie is bound to the owner's connections too, and the sign-in pipe is
|
|
95
|
+
* served (it refuses everyone while web.remote.windowsSignIn is off).
|
|
96
|
+
*/
|
|
97
|
+
function remoteGate(ctx) {
|
|
98
|
+
const secrets = SecretStore.standard();
|
|
99
|
+
let ownerSid = '';
|
|
100
|
+
try {
|
|
101
|
+
ownerSid = currentUserSid();
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Unknown: Windows sign-in stays off, the owner signs in with the token as before.
|
|
105
|
+
}
|
|
106
|
+
const helper = ownerSid ? HostToolsHelper.start(ctx.storageRoot, doorPipeName(ownerSid)) : null;
|
|
107
|
+
const audit = remoteAudit(ctx);
|
|
108
|
+
helper?.onProblem((text) => audit({ who: 'the web UI', what: 'Windows sign-in: ' + text, outcome: 'failed' }));
|
|
109
|
+
const store = new WebStore(ctx.storageRoot);
|
|
110
|
+
return new RemoteGate({
|
|
111
|
+
store: accessStoreOf(ctx),
|
|
112
|
+
settings: remoteSettings(ctx),
|
|
113
|
+
ownerSid,
|
|
114
|
+
helper,
|
|
115
|
+
audit,
|
|
116
|
+
tls: new TlsStore(store.dir, secrets),
|
|
117
|
+
profile: (address) => networkProfile(address),
|
|
118
|
+
port: () => ctx.loaded.config.web.port,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
56
121
|
/** Body of the background process (`sandbox _web`): runs until stopped. */
|
|
57
122
|
export async function webServer(ctx) {
|
|
58
123
|
const staticRoot = path.join(ctx.packageRoot, 'dist', 'web');
|
|
@@ -66,6 +131,7 @@ export async function webServer(ctx) {
|
|
|
66
131
|
staticRoot,
|
|
67
132
|
version: packageVersion(),
|
|
68
133
|
idleExitMs: IDLE_EXIT_MS,
|
|
134
|
+
gate: remoteGate(ctx),
|
|
69
135
|
}).run();
|
|
70
136
|
process.exit(0);
|
|
71
137
|
}
|