dsh-permission-rules 0.4.2 → 0.5.2
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/CHANGELOG.md +34 -0
- package/README.es.md +160 -117
- package/README.hi.md +162 -119
- package/README.md +133 -90
- package/README.pt.md +161 -118
- package/README.zh.md +162 -119
- package/docs/rule-test-vectors/README.md +28 -0
- package/docs/rule-test-vectors/corpus.json +109 -0
- package/lib/client.js +4693 -0
- package/lib/client.js.map +1 -0
- package/lib/index.js +1530 -179
- package/lib/typert.host.js +4305 -0
- package/lib/types/client/index.d.ts +28 -0
- package/lib/types/client/index.d.ts.map +1 -0
- package/lib/types/client/locales.d.ts +9 -0
- package/lib/types/client/locales.d.ts.map +1 -0
- package/lib/types/client/remote.d.ts +181 -0
- package/lib/types/client/remote.d.ts.map +1 -0
- package/lib/types/client/section.d.ts +35 -0
- package/lib/types/client/section.d.ts.map +1 -0
- package/lib/types/config.d.ts +54 -2
- package/lib/types/config.d.ts.map +1 -1
- package/lib/types/events.d.ts +45 -0
- package/lib/types/events.d.ts.map +1 -1
- package/lib/types/index.d.ts +8 -6
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/network.d.ts +90 -0
- package/lib/types/network.d.ts.map +1 -0
- package/lib/types/prose.d.ts +15 -0
- package/lib/types/prose.d.ts.map +1 -1
- package/lib/types/proxy.d.ts +128 -0
- package/lib/types/proxy.d.ts.map +1 -0
- package/lib/types/remote-service.d.ts +45 -0
- package/lib/types/remote-service.d.ts.map +1 -0
- package/lib/types/rules.d.ts +131 -0
- package/lib/types/rules.d.ts.map +1 -1
- package/lib/types/runtime.d.ts +153 -21
- package/lib/types/runtime.d.ts.map +1 -1
- package/lib/types/settings.d.ts +28 -0
- package/lib/types/settings.d.ts.map +1 -0
- package/lib/types/typert.host.d.ts +166 -0
- package/lib/types/typert.host.d.ts.map +1 -0
- package/lib/types/wire.d.ts +421 -0
- package/lib/types/wire.d.ts.map +1 -0
- package/package.json +182 -144
- package/scripts/repair-session-logs.mjs +7 -2
- package/src/client/index.ts +111 -0
- package/src/client/locales.ts +94 -0
- package/src/client/remote.ts +41 -0
- package/src/client/section.ts +201 -0
- package/src/config.ts +111 -0
- package/src/events.ts +46 -0
- package/src/index.ts +2 -0
- package/src/network.ts +177 -0
- package/src/prose.ts +85 -10
- package/src/proxy.ts +327 -0
- package/src/remote-service.ts +109 -0
- package/src/rules.ts +424 -5
- package/src/runtime.ts +464 -53
- package/src/settings.ts +74 -0
- package/src/typert.host.ts +25 -0
- package/src/wire.ts +239 -0
- package/lib/types/config.js +0 -99
- package/lib/types/config.js.map +0 -1
- package/lib/types/events.js +0 -44
- package/lib/types/events.js.map +0 -1
- package/lib/types/glob.js +0 -307
- package/lib/types/glob.js.map +0 -1
- package/lib/types/index.js +0 -27
- package/lib/types/index.js.map +0 -1
- package/lib/types/prose.js +0 -173
- package/lib/types/prose.js.map +0 -1
- package/lib/types/rules.js +0 -610
- package/lib/types/rules.js.map +0 -1
- package/lib/types/runtime.js +0 -818
- package/lib/types/runtime.js.map +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plugin's built-in local HTTP/CONNECT proxy: the process-level
|
|
3
|
+
* network gate for shell subprocess traffic. Bash/pwsh children inherit
|
|
4
|
+
* `HTTP(S)_PROXY`/`ALL_PROXY` environment variables pointing here, and the
|
|
5
|
+
* proxy adjudicates EVERY connection target against the loaded network
|
|
6
|
+
* rules and the active policy mode — the domain decision lives in the
|
|
7
|
+
* proxy layer, not in per-command wrappers.
|
|
8
|
+
*
|
|
9
|
+
* Boundaries (documented in the README): DSH's official `ctx.sandbox`
|
|
10
|
+
* enforces FILE effects only, so network interception is entirely this
|
|
11
|
+
* plugin's job; the proxy has no session context, so an `ask` decision at
|
|
12
|
+
* the proxy layer cannot ride the interactive approval seam — it blocks
|
|
13
|
+
* the connection with a structured message and is audit-logged instead
|
|
14
|
+
* (web tools get the real approval seam at `tools/pre-execute`).
|
|
15
|
+
* @module dsh-permission-rules/proxy
|
|
16
|
+
*/
|
|
17
|
+
import type { CallId } from '@deepseek-ai/dsh-llm';
|
|
18
|
+
import type { NetworkDecision, NetworkMode } from './network.js';
|
|
19
|
+
import type { NetworkTarget, SchemeName } from './rules.js';
|
|
20
|
+
/** Proxy environment variable names the injector sets/restores (uppercase + lowercase for mixed-ecosystem CLIs). */
|
|
21
|
+
export declare const PROXY_ENV_NAMES: readonly string[];
|
|
22
|
+
/** NO_PROXY names cleared (or preserved) by the injector. */
|
|
23
|
+
export declare const NO_PROXY_ENV_NAMES: readonly string[];
|
|
24
|
+
/** One recorded proxy-layer block (settings-page list + session audit + logger). */
|
|
25
|
+
export interface NetworkBlockRecord {
|
|
26
|
+
readonly time: number;
|
|
27
|
+
readonly tool: string;
|
|
28
|
+
readonly attributed: boolean;
|
|
29
|
+
readonly callId?: CallId;
|
|
30
|
+
readonly domain: string;
|
|
31
|
+
readonly scheme?: SchemeName;
|
|
32
|
+
readonly port?: number;
|
|
33
|
+
readonly action: 'deny' | 'ask';
|
|
34
|
+
readonly mode: NetworkMode;
|
|
35
|
+
readonly matched: boolean;
|
|
36
|
+
readonly source: string;
|
|
37
|
+
readonly ruleIndex?: number;
|
|
38
|
+
readonly reason?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Cumulative proxy-layer block counters. */
|
|
41
|
+
export interface NetworkStats {
|
|
42
|
+
denied: number;
|
|
43
|
+
askBlocked: number;
|
|
44
|
+
}
|
|
45
|
+
/** The attribution the runtime supplies for one connection (the newest in-flight shell execution). */
|
|
46
|
+
export interface ProxyAttribution {
|
|
47
|
+
readonly tool: string;
|
|
48
|
+
readonly callId?: CallId;
|
|
49
|
+
readonly agent?: {
|
|
50
|
+
readonly session: {
|
|
51
|
+
append(type: 'permissionRules/network', data: unknown, options?: {
|
|
52
|
+
ignorable?: true;
|
|
53
|
+
}): unknown;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** Construction options for {@link NetworkProxy}. */
|
|
58
|
+
export interface NetworkProxyOptions {
|
|
59
|
+
/** Bind address (loopback by config). */
|
|
60
|
+
readonly bind: string;
|
|
61
|
+
/** Requested port; `0` binds an ephemeral port. */
|
|
62
|
+
readonly port: number;
|
|
63
|
+
/** Cap on recent-block records kept in memory. */
|
|
64
|
+
readonly maxRecent: number;
|
|
65
|
+
/** Decision function supplied by the runtime (rules + mode). */
|
|
66
|
+
readonly decide: (target: NetworkTarget) => NetworkDecision;
|
|
67
|
+
/** Current attribution (newest in-flight shell execution), or undefined. */
|
|
68
|
+
readonly attribution?: () => ProxyAttribution | undefined;
|
|
69
|
+
/** Called for every blocked connection, after the response is sent. */
|
|
70
|
+
readonly onBlock?: (record: NetworkBlockRecord, attribution: ProxyAttribution | undefined) => void;
|
|
71
|
+
/** Logger sink (proxy failures must never crash the host). */
|
|
72
|
+
readonly logger: {
|
|
73
|
+
warn(message: string): void;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* The local HTTP/CONNECT policy proxy. Binds on demand (the plugin calls
|
|
78
|
+
* {@link start} inside an effect and {@link close} from its disposer);
|
|
79
|
+
* every live tunnel socket is tracked and destroyed on close so updates
|
|
80
|
+
* and uninstalls leave no orphaned connections.
|
|
81
|
+
*/
|
|
82
|
+
export declare class NetworkProxy {
|
|
83
|
+
private readonly options;
|
|
84
|
+
private server;
|
|
85
|
+
private readonly sockets;
|
|
86
|
+
private readonly recent;
|
|
87
|
+
private readonly stats;
|
|
88
|
+
private actualPort;
|
|
89
|
+
constructor(options: NetworkProxyOptions);
|
|
90
|
+
/** The bound port (valid after {@link start} resolves). */
|
|
91
|
+
get port(): number;
|
|
92
|
+
/** Deny/ask blocks recorded since mount, newest first (settings-page list). */
|
|
93
|
+
recentBlocks(): readonly NetworkBlockRecord[];
|
|
94
|
+
/** Cumulative block counters. */
|
|
95
|
+
blockStats(): NetworkStats;
|
|
96
|
+
/** Bind the server and return the actual port. */
|
|
97
|
+
start(): Promise<number>;
|
|
98
|
+
/** Stop the server and destroy every tunnel; resolves when sockets are closed. */
|
|
99
|
+
close(): Promise<void>;
|
|
100
|
+
/** Plain-HTTP proxying: absolute-form requests are adjudicated and forwarded (or blocked with a structured 403). */
|
|
101
|
+
private handleRequest;
|
|
102
|
+
/** CONNECT tunneling (HTTPS and friends): adjudicate, then either 403 or an established TCP tunnel. */
|
|
103
|
+
private handleConnect;
|
|
104
|
+
/** Adjudicate one plain-HTTP request; deny/ask blocks with a structured 403 before any forwarding. */
|
|
105
|
+
private forwardOrBlock;
|
|
106
|
+
/** Resolve a hostname once so `ips`-scoped rules see the real addresses, then decide. */
|
|
107
|
+
private decideWithResolution;
|
|
108
|
+
/** Record a block: counters, recent ring, and the runtime hook (logger + session audit). */
|
|
109
|
+
private recordBlock;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Inject the proxy environment variables for subprocesses and return a
|
|
113
|
+
* disposer restoring every previous value exactly (so updates and
|
|
114
|
+
* uninstalls leave the host environment untouched). `noProxy: 'clear'`
|
|
115
|
+
* empties NO_PROXY so the policy cannot be bypassed through ambient
|
|
116
|
+
* exclusions; `preserve` keeps ambient values.
|
|
117
|
+
*
|
|
118
|
+
* The snapshot pass covers EVERY name BEFORE any write: on Windows
|
|
119
|
+
* `process.env` is case-insensitive, so the uppercase/lowercase spellings
|
|
120
|
+
* share one variable — writing `HTTP_PROXY` mid-loop would otherwise
|
|
121
|
+
* poison the later snapshot of `http_proxy` and make the restore write
|
|
122
|
+
* the proxy address back over the original.
|
|
123
|
+
* @param port - the bound proxy port.
|
|
124
|
+
* @param noProxy - the configured NO_PROXY handling.
|
|
125
|
+
* @returns the restore disposer.
|
|
126
|
+
*/
|
|
127
|
+
export declare function injectProxyEnv(port: number, noProxy: 'clear' | 'preserve'): () => void;
|
|
128
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The settings-page Remote service: exposes the `permissionRules` Typert
|
|
3
|
+
* namespace (network snapshot + rule-file read/save/reload) to the
|
|
4
|
+
* browser half. All state lives in the {@link PermissionRulesRuntime}
|
|
5
|
+
* this service delegates to; the service itself only bridges the wire
|
|
6
|
+
* vocabulary. The rule editor only ever touches KNOWN rule sources —
|
|
7
|
+
* arbitrary paths are refused by the runtime.
|
|
8
|
+
* @module dsh-permission-rules/remote-service
|
|
9
|
+
*/
|
|
10
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
11
|
+
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
12
|
+
import type { PermissionRulesRuntime } from './runtime.js';
|
|
13
|
+
import type { PermissionRulesSnapshot, RulesReadResult, RulesReloadResult, RulesSaveResult } from './wire.js';
|
|
14
|
+
declare module '@deepseek-ai/cordis' {
|
|
15
|
+
interface Context {
|
|
16
|
+
/** Settings-page snapshot + rule-editor bridge (this package). */
|
|
17
|
+
permissionRules: PermissionRulesRemoteService;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Service config: the runtime instance whose state the wire exposes. */
|
|
21
|
+
export interface PermissionRulesRemoteServiceConfig {
|
|
22
|
+
/** The runtime holding the loaded rules, proxy state, and block records. */
|
|
23
|
+
runtime: PermissionRulesRuntime;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The Typert Remote service behind the settings page. Registered through
|
|
27
|
+
* `ctx.plugin(PermissionRulesRemoteService, { runtime })` in
|
|
28
|
+
* {@link apply}; the typert gateway binds its public methods to the
|
|
29
|
+
* invocation descriptors in `./wire.ts`.
|
|
30
|
+
*/
|
|
31
|
+
export declare class PermissionRulesRemoteService extends TypertRemoteService {
|
|
32
|
+
private readonly config;
|
|
33
|
+
static inject: string[];
|
|
34
|
+
constructor(ctx: Context, config: PermissionRulesRemoteServiceConfig);
|
|
35
|
+
/** The settings-page snapshot: mode mapping, proxy liveness, counters, recent blocks, editable rule sources. */
|
|
36
|
+
networkStatus(): PermissionRulesSnapshot;
|
|
37
|
+
/** Read one known rule file for the editor. */
|
|
38
|
+
rulesRead(path: string): RulesReadResult;
|
|
39
|
+
/** Validate and write one known rule file; invalid edits are rejected before anything touches disk. */
|
|
40
|
+
rulesSave(path: string, text: string): RulesSaveResult;
|
|
41
|
+
/** Re-read every cached workspace chain (after an external edit). */
|
|
42
|
+
reload(): RulesReloadResult;
|
|
43
|
+
}
|
|
44
|
+
export default PermissionRulesRemoteService;
|
|
45
|
+
//# sourceMappingURL=remote-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote-service.d.ts","sourceRoot":"","sources":["../../src/remote-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAA;AACtE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAC1D,OAAO,KAAK,EAAE,uBAAuB,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE7G,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,kEAAkE;QAClE,eAAe,EAAE,4BAA4B,CAAA;KAC9C;CACF;AAED,yEAAyE;AACzE,MAAM,WAAW,kCAAkC;IACjD,4EAA4E;IAC5E,OAAO,EAAE,sBAAsB,CAAA;CAChC;AAED;;;;;GAKG;AACH,qBAAa,4BAA6B,SAAQ,mBAAmB;IAGzC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFjD,MAAM,CAAC,MAAM,EAAS,MAAM,EAAE,CAAA;gBAElB,GAAG,EAAE,OAAO,EAAmB,MAAM,EAAE,kCAAkC;IAIrF,gHAAgH;IAChH,aAAa,IAAI,uBAAuB;IAiCxC,+CAA+C;IAC/C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAUxC,uGAAuG;IACvG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe;IAStD,qEAAqE;IACrE,MAAM,IAAI,iBAAiB;CAQ5B;AAED,eAAe,4BAA4B,CAAA"}
|
package/lib/types/rules.d.ts
CHANGED
|
@@ -12,6 +12,12 @@ export type RuleAction = 'allow' | 'deny' | 'ask';
|
|
|
12
12
|
export type PatternMode = 'glob' | 'regex';
|
|
13
13
|
/** Closed action list for runtime normalization of untrusted values. */
|
|
14
14
|
export declare const RULE_ACTIONS: readonly RuleAction[];
|
|
15
|
+
/** URL schemes a network rule may name (the proxy classifies CONNECT tunnels as `https`). */
|
|
16
|
+
export type SchemeName = 'http' | 'https';
|
|
17
|
+
/** Closed scheme list for runtime normalization of untrusted values. */
|
|
18
|
+
export declare const SCHEMES: readonly SchemeName[];
|
|
19
|
+
/** Hostname characters that make a URL candidate parseable as a network target. */
|
|
20
|
+
export declare const URL_CANDIDATE_KEYS: readonly string[];
|
|
15
21
|
/** Platform names a `when.platform` entry may name (Node `process.platform` values). */
|
|
16
22
|
export declare const PLATFORMS: readonly string[];
|
|
17
23
|
/**
|
|
@@ -58,6 +64,11 @@ export interface RuleMatchDoc {
|
|
|
58
64
|
agents: string[];
|
|
59
65
|
/** Environment/platform conditions; every listed env key must be present and match. */
|
|
60
66
|
when: WhenDoc;
|
|
67
|
+
/**
|
|
68
|
+
* Network scope, when this rule is a network rule; absent means the rule
|
|
69
|
+
* never evaluates URL/connection targets.
|
|
70
|
+
*/
|
|
71
|
+
network?: NetworkDoc;
|
|
61
72
|
}
|
|
62
73
|
/** The parsed `when` conditions. */
|
|
63
74
|
export interface WhenDoc {
|
|
@@ -66,6 +77,40 @@ export interface WhenDoc {
|
|
|
66
77
|
/** Platform names; ANY match satisfies the dimension. */
|
|
67
78
|
platform: string[];
|
|
68
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* The parsed network match dimensions; a rule WITHOUT this block has no
|
|
82
|
+
* network scope (it stays a file/command rule exactly as before). A rule
|
|
83
|
+
* WITH this block is a network rule: it matches a tool call only when the
|
|
84
|
+
* call carries a URL candidate satisfying every listed dimension (AND),
|
|
85
|
+
* and it matches proxy-layer connections (shell subprocess traffic)
|
|
86
|
+
* against the connection target.
|
|
87
|
+
*/
|
|
88
|
+
export interface NetworkDoc {
|
|
89
|
+
/**
|
|
90
|
+
* Domain patterns (lowercased; a trailing `.` is stripped). A pattern
|
|
91
|
+
* WITHOUT wildcards is subdomain-inclusive — `example.com` also matches
|
|
92
|
+
* `api.example.com` — while `*.example.com` matches subdomains only and
|
|
93
|
+
* `*`/`**` compile as ordinary globs. ANY pattern matching the target
|
|
94
|
+
* host satisfies the dimension.
|
|
95
|
+
*/
|
|
96
|
+
domains: string[];
|
|
97
|
+
/**
|
|
98
|
+
* IP patterns: an exact IPv4/IPv6 literal, a glob (e.g. `10.0.*.*`), or
|
|
99
|
+
* an IPv4 CIDR (`10.0.0.0/8`). A literal IP in the URL is always a
|
|
100
|
+
* candidate; the proxy additionally resolves hostnames and tests their
|
|
101
|
+
* addresses, while `tools/pre-execute` matches literal IPs only (no DNS
|
|
102
|
+
* in the hot path). ANY match satisfies the dimension.
|
|
103
|
+
*/
|
|
104
|
+
ips: string[];
|
|
105
|
+
/**
|
|
106
|
+
* Port patterns: `*`, one port (`443`), or an inclusive range
|
|
107
|
+
* (`8000-9000`). Evaluated against the effective port (URL port, else
|
|
108
|
+
* 80/443 by scheme). ANY match satisfies the dimension.
|
|
109
|
+
*/
|
|
110
|
+
ports: string[];
|
|
111
|
+
/** Schemes; the target scheme must be one of them (ANY). */
|
|
112
|
+
schemes: SchemeName[];
|
|
113
|
+
}
|
|
69
114
|
/** One compiled rule, ready for the `tools/pre-execute` hot path. */
|
|
70
115
|
export interface CompiledRule {
|
|
71
116
|
/** 0-based position in the merged rule chain. */
|
|
@@ -91,9 +136,33 @@ export interface CompiledRule {
|
|
|
91
136
|
readonly env: ReadonlyMap<string, readonly RegExp[]>;
|
|
92
137
|
readonly platform: readonly string[];
|
|
93
138
|
};
|
|
139
|
+
/** Compiled network dimensions, when this rule has network scope. */
|
|
140
|
+
readonly network?: CompiledNetwork;
|
|
94
141
|
/** The original source strings, kept for the `/rules` display. */
|
|
95
142
|
readonly source: RuleDocEntry;
|
|
96
143
|
}
|
|
144
|
+
/** One compiled port pattern: an inclusive range; `max: Infinity` is the `*` catch-all. */
|
|
145
|
+
export interface CompiledPortRange {
|
|
146
|
+
readonly min: number;
|
|
147
|
+
readonly max: number;
|
|
148
|
+
}
|
|
149
|
+
/** One compiled IP pattern: a glob RegExp, an IPv4 CIDR block, or an exact literal (IPv6/odd shapes). */
|
|
150
|
+
export interface CompiledIpPattern {
|
|
151
|
+
readonly regex?: RegExp;
|
|
152
|
+
readonly cidr?: {
|
|
153
|
+
readonly network: number;
|
|
154
|
+
readonly prefix: number;
|
|
155
|
+
};
|
|
156
|
+
readonly literal?: string;
|
|
157
|
+
}
|
|
158
|
+
/** The compiled network dimensions of one rule (absent block = no network scope). */
|
|
159
|
+
export interface CompiledNetwork {
|
|
160
|
+
/** Subdomain-inclusive exact domains and glob domains, all anchored + case-insensitive. */
|
|
161
|
+
readonly domains: readonly RegExp[];
|
|
162
|
+
readonly ips: readonly CompiledIpPattern[];
|
|
163
|
+
readonly ports: readonly CompiledPortRange[];
|
|
164
|
+
readonly schemes: readonly SchemeName[];
|
|
165
|
+
}
|
|
97
166
|
/** A compiled, size-capped ruleset. */
|
|
98
167
|
export interface CompiledRuleset {
|
|
99
168
|
readonly rules: readonly CompiledRule[];
|
|
@@ -213,11 +282,20 @@ export interface DescribeTokens {
|
|
|
213
282
|
readonly absent: string;
|
|
214
283
|
readonly when: string;
|
|
215
284
|
readonly platform: string;
|
|
285
|
+
readonly network: string;
|
|
286
|
+
readonly domains: string;
|
|
287
|
+
readonly ips: string;
|
|
288
|
+
readonly ports: string;
|
|
289
|
+
readonly schemes: string;
|
|
216
290
|
readonly disabled: string;
|
|
217
291
|
readonly tags: string;
|
|
218
292
|
/** Prefix of the per-rule source-file attribution. */
|
|
219
293
|
readonly src: string;
|
|
220
294
|
}
|
|
295
|
+
/** Whether a rule's tools dimension selects the tool. */
|
|
296
|
+
export declare function matchTools(rule: CompiledRule, toolName: string): boolean;
|
|
297
|
+
/** Whether a rule's when dimension holds for the host facts. */
|
|
298
|
+
export declare function matchWhen(rule: CompiledRule, context: MatchContext): boolean;
|
|
221
299
|
/** Top-level argument keys whose string values are path candidates. */
|
|
222
300
|
export declare const PATH_CANDIDATE_KEYS: readonly string[];
|
|
223
301
|
/**
|
|
@@ -231,6 +309,59 @@ export declare const PATH_CANDIDATE_KEYS: readonly string[];
|
|
|
231
309
|
* @returns candidate strings in argument key order (duplicates kept).
|
|
232
310
|
*/
|
|
233
311
|
export declare function extractPathCandidates(args: Record<string, unknown>): string[];
|
|
312
|
+
/** One parsed network target (a URL candidate or a proxy connection target). */
|
|
313
|
+
export interface NetworkTarget {
|
|
314
|
+
/** `http` or `https`, or undefined for scheme-less host candidates. */
|
|
315
|
+
readonly scheme: SchemeName | undefined;
|
|
316
|
+
/** Lowercased hostname (brackets stripped for IPv6) or literal IP, trailing dot stripped. */
|
|
317
|
+
readonly host: string;
|
|
318
|
+
/** Effective port: URL port, else 80/443 by scheme; undefined for bare hostnames. */
|
|
319
|
+
readonly port: number | undefined;
|
|
320
|
+
/** Literal IP when `host` is one; the proxy appends resolved addresses here. */
|
|
321
|
+
readonly ips: readonly string[];
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Whether the tool is a shell tool: its `command` argument is scanned for
|
|
325
|
+
* embedded URLs. Every other tool contributes URL candidates only through
|
|
326
|
+
* {@link URL_CANDIDATE_KEYS}.
|
|
327
|
+
*/
|
|
328
|
+
export declare function isShellTool(toolName: string): boolean;
|
|
329
|
+
/**
|
|
330
|
+
* Collect URL-candidate strings from tool arguments: values under the
|
|
331
|
+
* {@link URL_CANDIDATE_KEYS} at ANY nesting depth (capped like path
|
|
332
|
+
* extraction), plus embedded `http(s)://` substrings of command-shaped
|
|
333
|
+
* arguments (shell command text). Deterministic: own key order, duplicates
|
|
334
|
+
* kept.
|
|
335
|
+
* @param args - the parsed tool arguments.
|
|
336
|
+
* @returns raw candidate strings, each already an http(s) URL or a bare host.
|
|
337
|
+
*/
|
|
338
|
+
export declare function extractUrlCandidates(args: Record<string, unknown>): string[];
|
|
339
|
+
/**
|
|
340
|
+
* Parse one raw candidate into a {@link NetworkTarget}. Full `http(s)://`
|
|
341
|
+
* URLs parse through WHATWG URL semantics; a bare `host[:port]` candidate
|
|
342
|
+
* (no spaces, no slashes) becomes a scheme-less target (the `scheme` key
|
|
343
|
+
* is present with value `undefined`). Anything else yields `undefined` —
|
|
344
|
+
* a rule simply cannot match a non-target candidate.
|
|
345
|
+
* @param raw - the candidate string.
|
|
346
|
+
* @returns the parsed target, or undefined.
|
|
347
|
+
*/
|
|
348
|
+
export declare function parseUrlTarget(raw: string): NetworkTarget | undefined;
|
|
349
|
+
/** Whether a host string is an IP literal (IPv4 or IPv6). */
|
|
350
|
+
export declare function isIpLiteral(host: string): boolean;
|
|
351
|
+
/**
|
|
352
|
+
* Evaluate one target against one compiled network block (pure; shared by
|
|
353
|
+
* the pre-execute path and the proxy layer). Domain patterns are tested
|
|
354
|
+
* against the host string as-is — including literal-IP hosts, so a
|
|
355
|
+
* catch-all glob like `*` matches `127.0.0.1` too (Codex parity keeps
|
|
356
|
+
* loopback reachable only via the `loopback` short-circuit, never by
|
|
357
|
+
* name matching). Literal-IP hosts are tested against `ips` patterns
|
|
358
|
+
* directly; `target.ips` may carry additional resolved addresses
|
|
359
|
+
* supplied by the proxy.
|
|
360
|
+
* @param target - the parsed target.
|
|
361
|
+
* @param network - the compiled network dimensions.
|
|
362
|
+
* @returns true when EVERY listed dimension holds.
|
|
363
|
+
*/
|
|
364
|
+
export declare function targetMatchesNetwork(target: NetworkTarget, network: CompiledNetwork): boolean;
|
|
234
365
|
/**
|
|
235
366
|
* Normalize one candidate path against the workspace root: separators
|
|
236
367
|
* become `/`, `./` prefixes drop, and in-root paths become workspace
|
package/lib/types/rules.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,yDAAyD;AACzD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAA;AAEjD,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1C,wEAAwE;AACxE,eAAO,MAAM,YAAY,EAAE,SAAS,UAAU,EAA6B,CAAA;AAE3E,wFAAwF;AACxF,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EAAkF,CAAA;AAQzH;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,KAAK;gBACtB,OAAO,EAAE,MAAM;CAI5B;AAED,2EAA2E;AAC3E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB;AAED,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,UAAU,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAA;IAChB,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAED,mFAAmF;AACnF,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,uGAAuG;IACvG,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IAChC,gGAAgG;IAChG,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,2EAA2E;IAC3E,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,uFAAuF;IACvF,IAAI,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../src/rules.ts"],"names":[],"mappings":"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"}
|
package/lib/types/runtime.d.ts
CHANGED
|
@@ -13,9 +13,11 @@
|
|
|
13
13
|
import type { Context } from '@deepseek-ai/cordis';
|
|
14
14
|
import type { CommandInvocation, CommandResult } from '@deepseek-ai/dsh-commands';
|
|
15
15
|
import type { PreToolDecision, ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
16
|
-
import type { Config, ResolvedConfig } from './config.
|
|
17
|
-
import type { CompiledRuleset, RuleHit } from './rules.
|
|
18
|
-
import type {
|
|
16
|
+
import type { Config, ResolvedConfig } from './config.js';
|
|
17
|
+
import type { CompiledRuleset, RuleHit } from './rules.js';
|
|
18
|
+
import type { NetworkMode } from './network.js';
|
|
19
|
+
import type { NetworkBlockRecord } from './proxy.js';
|
|
20
|
+
import type { DecisionOutcome } from './events.js';
|
|
19
21
|
export declare const name = "permission-rules";
|
|
20
22
|
/** Services required before the plugin mounts. */
|
|
21
23
|
export declare const inject: string[];
|
|
@@ -33,11 +35,10 @@ interface LoadedRules {
|
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
35
37
|
* State and behavior. One instance per plugin mount; disposals are owned by
|
|
36
|
-
* the watcher/timer effects registered in {@link apply}.
|
|
38
|
+
* the watcher/timer/proxy effects registered in {@link apply}.
|
|
37
39
|
*/
|
|
38
40
|
export declare class PermissionRulesRuntime {
|
|
39
41
|
private readonly ctx;
|
|
40
|
-
readonly config: ResolvedConfig;
|
|
41
42
|
/** Loaded (or failed) rules per workspace cwd, least-recently-used first for eviction. */
|
|
42
43
|
private readonly byCwd;
|
|
43
44
|
/** Live watchers per watched path (rule file or candidate ancestor directory), with the cwds each serves. */
|
|
@@ -46,7 +47,19 @@ export declare class PermissionRulesRuntime {
|
|
|
46
47
|
private readonly timers;
|
|
47
48
|
/** Whether the host honors the audit envelope's `ignorable` marker: unknown until the first decision (or peer-version check). */
|
|
48
49
|
private auditSupport;
|
|
50
|
+
/** In-flight bash/pwsh executions (insertion order = start order), for proxy-block attribution. */
|
|
51
|
+
private readonly inFlight;
|
|
52
|
+
/** The network proxy, when the policy is enabled and mounted. */
|
|
53
|
+
private networkProxy;
|
|
54
|
+
/** Restores the injected proxy environment (set after a successful bind). */
|
|
55
|
+
private envRestore;
|
|
56
|
+
/** The authoritative config source: the composition entry, replaced by the settings scope while attached. */
|
|
57
|
+
private configSource;
|
|
49
58
|
constructor(ctx: Context, config: ResolvedConfig);
|
|
59
|
+
/** The currently authoritative config (settings scope or composition entry). */
|
|
60
|
+
get config(): ResolvedConfig;
|
|
61
|
+
/** Rebind the config source (the settings section hooks call this on attach/detach/change). */
|
|
62
|
+
setConfigSource(source: () => ResolvedConfig): void;
|
|
50
63
|
/** The shared compile options derived from config. */
|
|
51
64
|
private compileOptions;
|
|
52
65
|
/**
|
|
@@ -109,16 +122,28 @@ export declare class PermissionRulesRuntime {
|
|
|
109
122
|
* The `tools/pre-execute` listener. A deny/ask hit returns the decision
|
|
110
123
|
* (first match wins, short-circuiting downstream listeners); an allow hit
|
|
111
124
|
* and a passthrough MUST delegate via `next()` so later listeners keep
|
|
112
|
-
* their say.
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
125
|
+
* their say. Network-scoped rule hits on tool calls carry the structured
|
|
126
|
+
* `[network: …]` marker; when NO rule matches a web tool
|
|
127
|
+
* (`web_fetch`/`web_search`) the network mode default applies (deny-all
|
|
128
|
+
* denies, whitelist asks/denies, allow-all passes) — shell tools are
|
|
129
|
+
* NOT gated here, the proxy enforces their traffic per connection.
|
|
130
|
+
* Under `enforce: false` (dry-run) a deny/ask hit also delegates — the
|
|
131
|
+
* record keeps the would-be action with `dryRun: true` and the actual
|
|
132
|
+
* downstream outcome. Audit is appended once the final outcome is
|
|
133
|
+
* known, so the recorded `outcome` matches what the waterfall settled
|
|
134
|
+
* on.
|
|
117
135
|
* @param exec - the pending call (name, parsed arguments, caller agent).
|
|
118
136
|
* @param next - the downstream chain.
|
|
119
137
|
* @returns the pre-execute decision.
|
|
120
138
|
*/
|
|
121
139
|
preExecute(exec: ToolExecution, next: () => Promise<PreToolDecision>): Promise<PreToolDecision>;
|
|
140
|
+
/**
|
|
141
|
+
* The mode-default decision for an unlisted web-tool call, or undefined
|
|
142
|
+
* when the policy is disabled, the tool is not a web tool, or the mode
|
|
143
|
+
* allows. Shell tools always yield undefined here (the proxy decides
|
|
144
|
+
* their traffic per connection).
|
|
145
|
+
*/
|
|
146
|
+
private webToolFallback;
|
|
122
147
|
/**
|
|
123
148
|
* Append the log-only `permissionRules/decision` audit event for every
|
|
124
149
|
* decision (passthrough included unless `audit: 'hits'`), requesting the
|
|
@@ -131,18 +156,120 @@ export declare class PermissionRulesRuntime {
|
|
|
131
156
|
* `allowUnmarkedAudit: true` opts back in. `source` names the matched
|
|
132
157
|
* rule's file, or the nearest effective file on a passthrough; `cwd`
|
|
133
158
|
* names the workspace the rules were resolved for; `dryRun` marks
|
|
134
|
-
* would-be deny/ask hits under `enforce: false
|
|
135
|
-
*
|
|
136
|
-
*
|
|
159
|
+
* would-be deny/ask hits under `enforce: false`; `modeDefault` records a
|
|
160
|
+
* network mode-default decision on a web tool (no rule fired).
|
|
161
|
+
* Agentless calls have no session to audit; append failures are
|
|
162
|
+
* contained so an audit hiccup can never change a permission decision.
|
|
137
163
|
* @param exec - the pending call.
|
|
138
164
|
* @param loaded - the rules in effect.
|
|
139
165
|
* @param hit - the first matching rule, or undefined for passthrough.
|
|
140
166
|
* @param outcome - the final pre-execute decision.
|
|
141
167
|
* @param dryRun - mark the record as a would-be decision (dry-run mode).
|
|
168
|
+
* @param modeDefault - the network mode-default action when no rule fired.
|
|
142
169
|
*/
|
|
143
|
-
audit(exec: ToolExecution, loaded: LoadedRules, hit: RuleHit | undefined, outcome: DecisionOutcome, dryRun?: boolean): void;
|
|
170
|
+
audit(exec: ToolExecution, loaded: LoadedRules, hit: RuleHit | undefined, outcome: DecisionOutcome, dryRun?: boolean, modeDefault?: 'deny' | 'ask'): void;
|
|
171
|
+
/** After the first append, probe the returned envelope for the ignorable marker (host capability detection). */
|
|
172
|
+
private probeAuditResult;
|
|
144
173
|
/** Append one audit event through the session surface; the probe seam for host-capability detection. */
|
|
145
174
|
private appendAudit;
|
|
175
|
+
/**
|
|
176
|
+
* Resolve the network policy mode. An explicit config mode wins; `auto`
|
|
177
|
+
* maps the official sandbox preset (`read-only` → deny-all,
|
|
178
|
+
* `workspace-write` → whitelist, `danger-full-access` → allow-all) with
|
|
179
|
+
* `network.autoFallback` covering hosts without the sandbox-policy
|
|
180
|
+
* service (rc.6 and friends stay permissive until configured). For web
|
|
181
|
+
* tools the SESSION's resolved mode is used; the proxy resolves without
|
|
182
|
+
* a session (its connections carry no session context).
|
|
183
|
+
* @param session - optional session whose override outranks the default.
|
|
184
|
+
* @returns the resolved mode plus the sandbox preset it came from.
|
|
185
|
+
*/
|
|
186
|
+
resolveNetworkMode(session?: {
|
|
187
|
+
events?: unknown;
|
|
188
|
+
}): {
|
|
189
|
+
mode: NetworkMode;
|
|
190
|
+
sandboxMode: string | undefined;
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* The proxy-layer decision for one connection target: first-match
|
|
194
|
+
* network rules across every loaded workspace chain (insertion order),
|
|
195
|
+
* then the mode default. Shell subprocess traffic counts as `bash`/
|
|
196
|
+
* `pwsh` tool candidates; loopback handling follows config.
|
|
197
|
+
*/
|
|
198
|
+
private decideProxyTarget;
|
|
199
|
+
/** The loaded rule chains in cache order, nearest workspace first. */
|
|
200
|
+
private proxyChains;
|
|
201
|
+
/** Mark one delegated shell execution as in-flight (newest attribution wins). */
|
|
202
|
+
private markShell;
|
|
203
|
+
/** Drop one shell execution when it settles. */
|
|
204
|
+
unmarkShell(exec: ToolExecution): void;
|
|
205
|
+
/** The newest in-flight shell execution within the TTL, or undefined (best-effort attribution). */
|
|
206
|
+
private proxyAttribution;
|
|
207
|
+
/**
|
|
208
|
+
* Audit one proxy-layer block: the in-memory record is always kept
|
|
209
|
+
* (settings page), the logger always warns, and when the block can be
|
|
210
|
+
* attributed to an agent the `permissionRules/network` event is appended
|
|
211
|
+
* with the same ignorable-marker discipline as the decision audit.
|
|
212
|
+
*/
|
|
213
|
+
private auditNetworkBlock;
|
|
214
|
+
/**
|
|
215
|
+
* Mount the network proxy and the subprocess environment injection.
|
|
216
|
+
* Called from {@link apply}; the proxy binds an ephemeral (or
|
|
217
|
+
* configured) loopback port, the env injection only happens after a
|
|
218
|
+
* successful bind, and every side effect is owned by an effect
|
|
219
|
+
* disposer. A bind failure degrades loudly (file rules stay active,
|
|
220
|
+
* the settings page and `/rules network` show the inactive proxy)
|
|
221
|
+
* instead of taking the permission plugin down.
|
|
222
|
+
*/
|
|
223
|
+
attachNetworkProxy(): Promise<void>;
|
|
224
|
+
/**
|
|
225
|
+
* Apply a live settings change to the network policy: rebind the proxy
|
|
226
|
+
* when a bind/env-relevant knob changed (old proxy closed, old env
|
|
227
|
+
* restored, new proxy + env installed). Web-tool gating and the decision
|
|
228
|
+
* path read the config per call, so they need no rebind.
|
|
229
|
+
*/
|
|
230
|
+
onNetworkConfigChanged(): Promise<void>;
|
|
231
|
+
/** The network snapshot the settings page and `/rules network` render. */
|
|
232
|
+
networkSnapshot(): {
|
|
233
|
+
readonly enabled: boolean;
|
|
234
|
+
readonly mode: NetworkMode;
|
|
235
|
+
readonly configuredMode: 'auto' | NetworkMode;
|
|
236
|
+
readonly sandboxMode: string | undefined;
|
|
237
|
+
readonly proxyPort: number;
|
|
238
|
+
readonly proxyActive: boolean;
|
|
239
|
+
readonly denied: number;
|
|
240
|
+
readonly askBlocked: number;
|
|
241
|
+
readonly recent: readonly NetworkBlockRecord[];
|
|
242
|
+
};
|
|
243
|
+
/**
|
|
244
|
+
* The rule-file paths the settings-page editor may read or write: every
|
|
245
|
+
* currently loaded source plus the per-workspace project files and the
|
|
246
|
+
* configured fallback (so a not-yet-existing project file can be
|
|
247
|
+
* created). The editor never touches arbitrary paths.
|
|
248
|
+
*/
|
|
249
|
+
knownRuleSources(): readonly string[];
|
|
250
|
+
/** Read one known rule file for the editor: `{ exists, text, error }`. */
|
|
251
|
+
readRuleFile(path: string): {
|
|
252
|
+
path: string;
|
|
253
|
+
exists: boolean;
|
|
254
|
+
text: string;
|
|
255
|
+
error?: string;
|
|
256
|
+
};
|
|
257
|
+
/** The workspace a rule source belongs to (for the editor's file list), or undefined for the fallback. */
|
|
258
|
+
sourceOwner(path: string): string | undefined;
|
|
259
|
+
/** Re-read every cached workspace chain (the settings-page reload action). */
|
|
260
|
+
reloadAll(): void;
|
|
261
|
+
/**
|
|
262
|
+
* Validate and write one known rule file. The document must parse and
|
|
263
|
+
* compile (same checks as a load) BEFORE anything is written — an
|
|
264
|
+
* invalid edit is rejected with its error and the file stays untouched.
|
|
265
|
+
* After a successful write every cached workspace reloads so the edit
|
|
266
|
+
* is in effect immediately.
|
|
267
|
+
*/
|
|
268
|
+
saveRuleFile(path: string, text: string): {
|
|
269
|
+
ok: boolean;
|
|
270
|
+
error?: string;
|
|
271
|
+
reloaded?: number;
|
|
272
|
+
};
|
|
146
273
|
/** The installed `@deepseek-ai/dsh-session` version, or `null` when unresolvable (falls back to the append probe). */
|
|
147
274
|
private peerVersion;
|
|
148
275
|
/** One-time warning that session-log audit was disabled to keep session logs loadable. */
|
|
@@ -179,6 +306,8 @@ export declare class PermissionRulesRuntime {
|
|
|
179
306
|
private displaySource;
|
|
180
307
|
/** Render the session's `permissionRules/decision` audit trail, newest last. */
|
|
181
308
|
private decisionsCommand;
|
|
309
|
+
/** Render the network policy state: mode mapping, proxy liveness, counters, recent blocks. */
|
|
310
|
+
private networkCommand;
|
|
182
311
|
/**
|
|
183
312
|
* Validate deployment-level file references at mount — the earliest
|
|
184
313
|
* resolvable point. An absolute `rulesFile` or a configured
|
|
@@ -249,16 +378,19 @@ export declare class PermissionRulesRuntime {
|
|
|
249
378
|
* @param ctx - the host context.
|
|
250
379
|
* @param config - raw plugin config.
|
|
251
380
|
*/
|
|
252
|
-
export declare function apply(ctx: Context, config: Config): void
|
|
381
|
+
export declare function apply(ctx: Context, config: Config): Promise<void>;
|
|
253
382
|
/**
|
|
254
383
|
* Whether a `@deepseek-ai/dsh-session` version line predates the
|
|
255
|
-
* `ignorable` envelope-marker surface:
|
|
256
|
-
* silently
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
*
|
|
384
|
+
* `ignorable` envelope-marker surface: every released rc line through
|
|
385
|
+
* `0.1.0-rc.7` silently drops the marker from `Session.append` options
|
|
386
|
+
* (the stamping fix exists on harness master only — no release carries it
|
|
387
|
+
* yet), so audit events written by those builds land unmarked and break
|
|
388
|
+
* resume on stricter hosts. Extend the bound when a new rc line ships that
|
|
389
|
+
* still drops the marker. Non-matching (later rc, stable, or unresolvable)
|
|
390
|
+
* versions are treated as possibly-marker-aware and verified by the
|
|
391
|
+
* append probe.
|
|
260
392
|
* @param version - the installed peer version string.
|
|
261
|
-
* @returns true for the known-unmarked rc.1–rc.
|
|
393
|
+
* @returns true for the known-unmarked rc.1–rc.7 lines.
|
|
262
394
|
*/
|
|
263
395
|
export declare function isUnmarkedHostVersion(version: string): boolean;
|
|
264
396
|
export {};
|