capgate 0.0.1

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.
@@ -0,0 +1,235 @@
1
+ // Compiler: ServerManifest → NormalizedPolicy.
2
+ //
3
+ // Responsibilities:
4
+ // 1. Parse capability strings in raw manifests into typed Capability values.
5
+ // 2. Union server-level + per-tool capabilities into a single flat list.
6
+ // 3. Normalize (write implies read; longer fs paths absorb shorter overlaps).
7
+ // 4. Dedupe by (kind, scope key).
8
+ // 5. Partition by kind into the NormalizedPolicy shape.
9
+ //
10
+ // The compiler is a pure function. No I/O. No adapter knowledge.
11
+ import { GRAMMAR_VERSION, parseCapability } from './grammar.js';
12
+ import { CompilationError, } from './ir.js';
13
+ // ---------------------------------------------------------------------------
14
+ // Public API
15
+ // ---------------------------------------------------------------------------
16
+ export function compile(raw) {
17
+ assertManifestShape(raw);
18
+ const parsed = parseManifest(raw);
19
+ const all = [
20
+ ...(parsed.serverCapabilities ?? []),
21
+ ...parsed.tools.flatMap((t) => t.capabilities),
22
+ ];
23
+ return normalize({ name: raw.name, version: raw.version }, all);
24
+ }
25
+ /** Parse a RawServerManifest into a ServerManifest with typed Capability[]. */
26
+ export function parseManifest(raw) {
27
+ const serverCapabilities = raw.serverCapabilities?.map((s) => parseCapability(s).capability) ?? [];
28
+ const tools = raw.tools.map((t) => ({
29
+ name: t.name,
30
+ description: t.description,
31
+ inputSchema: t.inputSchema,
32
+ capabilities: t.capabilities.map((s) => parseCapability(s).capability),
33
+ }));
34
+ return { name: raw.name, version: raw.version, serverCapabilities, tools };
35
+ }
36
+ // ---------------------------------------------------------------------------
37
+ // Normalization pipeline
38
+ // ---------------------------------------------------------------------------
39
+ export function normalize(server, caps) {
40
+ const policy = {
41
+ server,
42
+ fs: [],
43
+ net: [],
44
+ exec: [],
45
+ env: [],
46
+ ipc: [],
47
+ clock: 'none',
48
+ assertions: [],
49
+ nestedSandbox: false,
50
+ };
51
+ // Per-kind accumulators keyed by a canonical scope key.
52
+ const fsAcc = new Map();
53
+ const netAcc = new Map();
54
+ const execAcc = new Map();
55
+ const envAcc = new Map();
56
+ const ipcAcc = new Map();
57
+ const assertAcc = new Map();
58
+ for (const cap of caps) {
59
+ if (cap.refinements?.nestedSandbox)
60
+ policy.nestedSandbox = true;
61
+ switch (cap.kind) {
62
+ case 'fs': {
63
+ const key = cap.scope.path;
64
+ const entry = fsAcc.get(key) ?? {
65
+ path: cap.scope.path,
66
+ actions: new Set(),
67
+ isGlob: cap.scope.isGlob,
68
+ };
69
+ for (const a of cap.actions)
70
+ entry.actions.add(a);
71
+ fsAcc.set(key, entry);
72
+ break;
73
+ }
74
+ case 'net': {
75
+ const key = `${cap.scope.host}:${cap.scope.port ?? '*'}`;
76
+ const entry = netAcc.get(key) ?? { ...cap.scope };
77
+ // blockPrivate is OR-ed: if any declaration wants it blocked, block it.
78
+ entry.blockPrivate = entry.blockPrivate || cap.scope.blockPrivate;
79
+ netAcc.set(key, entry);
80
+ break;
81
+ }
82
+ case 'exec': {
83
+ execAcc.set(cap.scope.binary, { binary: cap.scope.binary });
84
+ break;
85
+ }
86
+ case 'env': {
87
+ // Inject dominates read (inject requires read); collapse to inject if present.
88
+ const existing = envAcc.get(cap.scope.name);
89
+ const action = existing?.action === 'inject' || cap.actions.includes('inject') ? 'inject' : 'read';
90
+ envAcc.set(cap.scope.name, { name: cap.scope.name, action });
91
+ break;
92
+ }
93
+ case 'ipc': {
94
+ ipcAcc.set(cap.scope.endpoint, { endpoint: cap.scope.endpoint });
95
+ break;
96
+ }
97
+ case 'clock': {
98
+ // tzdata dominates system.
99
+ if (cap.scope.source === 'tzdata')
100
+ policy.clock = 'tzdata';
101
+ else if (policy.clock === 'none')
102
+ policy.clock = 'system';
103
+ break;
104
+ }
105
+ case 'assert': {
106
+ assertAcc.set(cap.scope.id, cap.scope);
107
+ break;
108
+ }
109
+ }
110
+ }
111
+ policy.fs = mergeFsRoots([...fsAcc.values()].map((e) => ({
112
+ path: e.path,
113
+ actions: normalizeFsActions([...e.actions]),
114
+ isGlob: e.isGlob,
115
+ })));
116
+ policy.net = [...netAcc.values()];
117
+ policy.exec = [...execAcc.values()];
118
+ policy.env = [...envAcc.values()];
119
+ policy.ipc = [...ipcAcc.values()];
120
+ policy.assertions = [...assertAcc.values()];
121
+ stableSort(policy);
122
+ return policy;
123
+ }
124
+ // ---------------------------------------------------------------------------
125
+ // FS normalization helpers
126
+ // ---------------------------------------------------------------------------
127
+ /** write/create/delete imply read; delete implies write. Canonical order. */
128
+ function normalizeFsActions(actions) {
129
+ const set = new Set(actions);
130
+ if (set.has('delete'))
131
+ set.add('write');
132
+ if (set.has('write') || set.has('create') || set.has('delete'))
133
+ set.add('read');
134
+ const order = ['read', 'create', 'write', 'delete'];
135
+ return order.filter((a) => set.has(a));
136
+ }
137
+ /**
138
+ * Merge fs roots where one path is a prefix-superset of another. bwrap and
139
+ * friends bind directories — once /workspace/** is bound, /workspace/src is
140
+ * redundant. We pick the shortest covering path and union the actions.
141
+ *
142
+ * This is a deliberately conservative merge: exact equality and simple prefix
143
+ * only. No glob-intersection solver.
144
+ */
145
+ function mergeFsRoots(roots) {
146
+ // Stable sort by path length ascending → shortest first.
147
+ const sorted = [...roots].sort((a, b) => prefixKey(a.path).localeCompare(prefixKey(b.path)));
148
+ const out = [];
149
+ for (const r of sorted) {
150
+ const covering = out.find((existing) => covers(existing.path, r.path));
151
+ if (covering) {
152
+ covering.actions = normalizeFsActions([...covering.actions, ...r.actions]);
153
+ continue;
154
+ }
155
+ out.push({ ...r });
156
+ }
157
+ return out;
158
+ }
159
+ /** Strip glob suffixes for prefix comparison. "/a/**" → "/a/". */
160
+ function prefixKey(path) {
161
+ return path.replace(/\/\*\*$/, '/').replace(/\/\*$/, '/');
162
+ }
163
+ /** True if `a` covers `b` (a is a directory prefix of b, treating globs as open-ended). */
164
+ function covers(a, b) {
165
+ if (a === b)
166
+ return true;
167
+ const aKey = prefixKey(a);
168
+ const bKey = prefixKey(b);
169
+ if (aKey === bKey)
170
+ return true;
171
+ // a must end in "/" after normalization to be a directory prefix.
172
+ if (!aKey.endsWith('/'))
173
+ return false;
174
+ return bKey.startsWith(aKey);
175
+ }
176
+ // ---------------------------------------------------------------------------
177
+ // Deterministic output — golden files demand stable ordering.
178
+ // ---------------------------------------------------------------------------
179
+ function stableSort(p) {
180
+ p.fs.sort((a, b) => a.path.localeCompare(b.path));
181
+ p.net.sort((a, b) => a.host.localeCompare(b.host) || portCmp(a.port, b.port));
182
+ p.exec.sort((a, b) => a.binary.localeCompare(b.binary));
183
+ p.env.sort((a, b) => a.name.localeCompare(b.name));
184
+ p.ipc.sort((a, b) => a.endpoint.localeCompare(b.endpoint));
185
+ p.assertions.sort((a, b) => a.id.localeCompare(b.id));
186
+ }
187
+ function portCmp(a, b) {
188
+ if (a === b)
189
+ return 0;
190
+ if (a === null)
191
+ return -1;
192
+ if (b === null)
193
+ return 1;
194
+ return a - b;
195
+ }
196
+ // ---------------------------------------------------------------------------
197
+ // Input validation — shape-only. Grammar errors surface from parseCapability.
198
+ // ---------------------------------------------------------------------------
199
+ function assertManifestShape(raw) {
200
+ if (!raw || typeof raw !== 'object') {
201
+ throw new CompilationError('MANIFEST_SHAPE', 'manifest must be an object');
202
+ }
203
+ if (raw.grammar !== undefined) {
204
+ if (typeof raw.grammar !== 'string') {
205
+ throw new CompilationError('MANIFEST_SHAPE', 'manifest.grammar must be a string');
206
+ }
207
+ if (raw.grammar !== GRAMMAR_VERSION) {
208
+ throw new CompilationError('GRAMMAR_VERSION_MISMATCH', `manifest declares grammar "${raw.grammar}" but compiler is at "${GRAMMAR_VERSION}"`, { declared: raw.grammar, supported: GRAMMAR_VERSION });
209
+ }
210
+ }
211
+ if (typeof raw.name !== 'string' || !raw.name) {
212
+ throw new CompilationError('MANIFEST_SHAPE', 'manifest.name must be a non-empty string');
213
+ }
214
+ if (typeof raw.version !== 'string' || !raw.version) {
215
+ throw new CompilationError('MANIFEST_SHAPE', 'manifest.version must be a non-empty string');
216
+ }
217
+ if (!Array.isArray(raw.tools)) {
218
+ throw new CompilationError('MANIFEST_SHAPE', 'manifest.tools must be an array');
219
+ }
220
+ if (raw.serverCapabilities && !Array.isArray(raw.serverCapabilities)) {
221
+ throw new CompilationError('MANIFEST_SHAPE', 'manifest.serverCapabilities must be an array');
222
+ }
223
+ for (const [i, t] of raw.tools.entries()) {
224
+ if (!t || typeof t !== 'object') {
225
+ throw new CompilationError('MANIFEST_SHAPE', `tools[${i}] must be an object`);
226
+ }
227
+ if (typeof t.name !== 'string' || !t.name) {
228
+ throw new CompilationError('MANIFEST_SHAPE', `tools[${i}].name must be a non-empty string`);
229
+ }
230
+ if (!Array.isArray(t.capabilities)) {
231
+ throw new CompilationError('MANIFEST_SHAPE', `tools[${i}].capabilities must be an array`);
232
+ }
233
+ }
234
+ }
235
+ //# sourceMappingURL=compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.js","sourceRoot":"","sources":["../../src/policy/compiler.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,EAAE;AACF,oBAAoB;AACpB,+EAA+E;AAC/E,2EAA2E;AAC3E,gFAAgF;AAChF,oCAAoC;AACpC,0DAA0D;AAC1D,EAAE;AACF,iEAAiE;AAEjE,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAGL,gBAAgB,GAMjB,MAAM,SAAS,CAAC;AAuBjB,8EAA8E;AAC9E,aAAa;AACb,8EAA8E;AAE9E,MAAM,UAAU,OAAO,CAAC,GAAsB;IAC5C,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAEzB,MAAM,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,GAAG,GAAiB;QACxB,GAAG,CAAC,MAAM,CAAC,kBAAkB,IAAI,EAAE,CAAC;QACpC,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;KAC/C,CAAC;IAEF,OAAO,SAAS,CACd,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,EACxC,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,GAAsB;IAClD,MAAM,kBAAkB,GACtB,GAAG,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAC1E,MAAM,KAAK,GAAmB,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClD,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,YAAY,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;KACvE,CAAC,CAAC,CAAC;IACJ,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAC7E,CAAC;AAED,8EAA8E;AAC9E,yBAAyB;AACzB,8EAA8E;AAE9E,MAAM,UAAU,SAAS,CACvB,MAAyC,EACzC,IAAkB;IAElB,MAAM,MAAM,GAAqB;QAC/B,MAAM;QACN,EAAE,EAAE,EAAE;QACN,GAAG,EAAE,EAAE;QACP,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,EAAE;QACP,GAAG,EAAE,EAAE;QACP,KAAK,EAAE,MAAM;QACb,UAAU,EAAE,EAAE;QACd,aAAa,EAAE,KAAK;KACrB,CAAC;IAEF,wDAAwD;IACxD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAqE,CAAC;IAC3F,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwE,CAAC;IAC/F,MAAM,OAAO,GAAG,IAAI,GAAG,EAA8B,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,GAAG,EAA+C,CAAC;IACtE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAgC,CAAC;IACvD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEjD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,WAAW,EAAE,aAAa;YAAE,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC;QAEhE,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;YACjB,KAAK,IAAI,CAAC,CAAC,CAAC;gBACV,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;oBAC9B,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI;oBACpB,OAAO,EAAE,IAAI,GAAG,EAAY;oBAC5B,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM;iBACzB,CAAC;gBACF,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO;oBAAE,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAClD,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBACtB,MAAM;YACR,CAAC;YACD,KAAK,KAAK,CAAC,CAAC,CAAC;gBACX,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC;gBACzD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC;gBAClD,wEAAwE;gBACxE,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,YAAY,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC;gBAClE,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBACvB,MAAM;YACR,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC5D,MAAM;YACR,CAAC;YACD,KAAK,KAAK,CAAC,CAAC,CAAC;gBACX,+EAA+E;gBAC/E,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,MAAM,GACV,QAAQ,EAAE,MAAM,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;gBACtF,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC7D,MAAM;YACR,CAAC;YACD,KAAK,KAAK,CAAC,CAAC,CAAC;gBACX,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;gBACjE,MAAM;YACR,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,2BAA2B;gBAC3B,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ;oBAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;qBACtD,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM;oBAAE,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;gBAC1D,MAAM;YACR,CAAC;YACD,KAAK,QAAQ,CAAC,CAAC,CAAC;gBACd,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC;gBACvC,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,CAAC,EAAE,GAAG,YAAY,CACtB,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,OAAO,EAAE,kBAAkB,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,EAAE,CAAC,CAAC,MAAM;KACjB,CAAC,CAAC,CACJ,CAAC;IACF,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACpC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,UAAU,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAE5C,UAAU,CAAC,MAAM,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,6EAA6E;AAC7E,SAAS,kBAAkB,CAAC,OAAmB;IAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAChF,MAAM,KAAK,GAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAChE,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,YAAY,CACnB,KAA+D;IAE/D,yDAAyD;IACzD,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7F,MAAM,GAAG,GAAkB,EAAE,CAAC;IAE9B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACvE,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,OAAO,GAAG,kBAAkB,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YAC3E,SAAS;QACX,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kEAAkE;AAClE,SAAS,SAAS,CAAC,IAAY;IAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED,2FAA2F;AAC3F,SAAS,MAAM,CAAC,CAAS,EAAE,CAAS;IAClC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;IAC1B,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,kEAAkE;IAClE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,8EAA8E;AAC9E,8DAA8D;AAC9D,8EAA8E;AAE9E,SAAS,UAAU,CAAC,CAAmB;IACrC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,OAAO,CAAC,CAAgB,EAAE,CAAgB;IACjD,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC,CAAC;IAC1B,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,8EAA8E;AAC9E,8EAA8E;AAE9E,SAAS,mBAAmB,CAAC,GAAsB;IACjD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,4BAA4B,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,mCAAmC,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,GAAG,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;YACpC,MAAM,IAAI,gBAAgB,CACxB,0BAA0B,EAC1B,8BAA8B,GAAG,CAAC,OAAO,yBAAyB,eAAe,GAAG,EACpF,EAAE,QAAQ,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CACtD,CAAC;QACJ,CAAC;IACH,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,0CAA0C,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACpD,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,6CAA6C,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,iCAAiC,CAAC,CAAC;IAClF,CAAC;IACD,IAAI,GAAG,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,8CAA8C,CAAC,CAAC;IAC/F,CAAC;IACD,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAChC,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,SAAS,CAAC,qBAAqB,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1C,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,SAAS,CAAC,mCAAmC,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,SAAS,CAAC,iCAAiC,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { Capability } from './ir.js';
2
+ /**
3
+ * Grammar version. Bumped whenever the capability string syntax, refinement
4
+ * keys, or IR shape changes in a non-backwards-compatible way. Manifests MAY
5
+ * declare `"grammar": "0.0"` to pin; the compiler rejects mismatches.
6
+ *
7
+ * Semver: MAJOR.MINOR, no patch. MINOR bumps are additive (new kind, new
8
+ * refinement). MAJOR bumps remove or redefine existing syntax.
9
+ */
10
+ export declare const GRAMMAR_VERSION = "0.0";
11
+ export interface ParseResult {
12
+ capability: Capability;
13
+ }
14
+ export declare function parseCapability(raw: string): ParseResult;
15
+ //# sourceMappingURL=grammar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grammar.d.ts","sourceRoot":"","sources":["../../src/policy/grammar.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,UAAU,EAQX,MAAM,SAAS,CAAC;AAEjB;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,QAAQ,CAAC;AAYrC,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,UAAU,CAAC;CACxB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAqBxD"}
@@ -0,0 +1,201 @@
1
+ // Capability string grammar — the shorthand humans write in manifests.
2
+ //
3
+ // Format: <kind>:<actions>:<scope>[?refinement=value&...]
4
+ // Examples:
5
+ // fs:read,write:/workspace/**
6
+ // fs:read:/usr/share/zoneinfo
7
+ // net:connect:api.github.com:443
8
+ // net:connect:* (any host, any port; implicit blockPrivate=true)
9
+ // exec:spawn:git
10
+ // env:inject:GITHUB_PAT
11
+ // ipc:connect:x11
12
+ // clock:tzdata
13
+ // assert:postgres.read_only_txn:"all queries run in READ ONLY TRANSACTION"
14
+ //
15
+ // The grammar is deliberately small. Anything that cannot be expressed here
16
+ // (e.g. seccomp syscall filters) is an adapter concern, not a capability.
17
+ import { CompilationError, } from './ir.js';
18
+ /**
19
+ * Grammar version. Bumped whenever the capability string syntax, refinement
20
+ * keys, or IR shape changes in a non-backwards-compatible way. Manifests MAY
21
+ * declare `"grammar": "0.0"` to pin; the compiler rejects mismatches.
22
+ *
23
+ * Semver: MAJOR.MINOR, no patch. MINOR bumps are additive (new kind, new
24
+ * refinement). MAJOR bumps remove or redefine existing syntax.
25
+ */
26
+ export const GRAMMAR_VERSION = '0.0';
27
+ const FS_ACTIONS = new Set(['read', 'write', 'create', 'delete']);
28
+ const NET_ACTIONS = new Set(['connect']);
29
+ const EXEC_ACTIONS = new Set(['spawn']);
30
+ const ENV_ACTIONS = new Set(['read', 'inject']);
31
+ const IPC_ACTIONS = new Set(['connect']);
32
+ const GLOB_CHARS = /[*?[\]]/;
33
+ const RFC1918_OR_LOOPBACK = /^(10\.|172\.(1[6-9]|2\d|3[01])\.|192\.168\.|127\.|::1$|localhost$)/i;
34
+ export function parseCapability(raw) {
35
+ const [body, refinementStr] = splitRefinements(raw);
36
+ const parts = splitTop(body, ':');
37
+ if (parts.length < 2) {
38
+ throw new CompilationError('CAP_MALFORMED', `expected at least <kind>:<scope>, got "${raw}"`);
39
+ }
40
+ const kind = parts[0];
41
+ const refinements = parseRefinements(refinementStr);
42
+ switch (kind) {
43
+ case 'fs': return { capability: parseFs(parts, refinements, raw) };
44
+ case 'net': return { capability: parseNet(parts, refinements, raw) };
45
+ case 'exec': return { capability: parseExec(parts, refinements, raw) };
46
+ case 'env': return { capability: parseEnv(parts, refinements, raw) };
47
+ case 'ipc': return { capability: parseIpc(parts, refinements, raw) };
48
+ case 'clock': return { capability: parseClock(parts, refinements, raw) };
49
+ case 'assert': return { capability: parseAssert(parts, refinements, raw) };
50
+ default:
51
+ throw new CompilationError('CAP_UNKNOWN_KIND', `unknown capability kind "${kind}"`, { raw });
52
+ }
53
+ }
54
+ // ---------------------------------------------------------------------------
55
+ // Per-kind parsers
56
+ // ---------------------------------------------------------------------------
57
+ function parseFs(parts, refinements, raw) {
58
+ if (parts.length !== 3) {
59
+ throw new CompilationError('CAP_FS_SHAPE', `fs needs <actions>:<path>, got "${raw}"`);
60
+ }
61
+ const actions = parseActions(parts[1], FS_ACTIONS, 'fs', raw);
62
+ const path = parts[2];
63
+ if (!path.startsWith('/')) {
64
+ throw new CompilationError('CAP_FS_RELATIVE', `fs path must be absolute: "${path}"`);
65
+ }
66
+ return {
67
+ kind: 'fs',
68
+ actions,
69
+ scope: { path, isGlob: GLOB_CHARS.test(path) },
70
+ refinements,
71
+ };
72
+ }
73
+ function parseNet(parts, refinements, raw) {
74
+ // net:connect:host OR net:connect:host:port
75
+ if (parts.length < 3 || parts.length > 4) {
76
+ throw new CompilationError('CAP_NET_SHAPE', `net needs <actions>:<host>[:<port>], got "${raw}"`);
77
+ }
78
+ const actions = parseActions(parts[1], NET_ACTIONS, 'net', raw);
79
+ const host = parts[2];
80
+ const port = parts.length === 4 ? parseInt(parts[3], 10) : null;
81
+ if (port !== null && (Number.isNaN(port) || port < 1 || port > 65535)) {
82
+ throw new CompilationError('CAP_NET_PORT', `net port out of range: "${parts[3]}"`);
83
+ }
84
+ const blockPrivate = host === '*' ? true : !RFC1918_OR_LOOPBACK.test(host);
85
+ return {
86
+ kind: 'net',
87
+ actions,
88
+ scope: { host, port, blockPrivate },
89
+ refinements,
90
+ };
91
+ }
92
+ function parseExec(parts, refinements, raw) {
93
+ if (parts.length !== 3) {
94
+ throw new CompilationError('CAP_EXEC_SHAPE', `exec needs <actions>:<binary>, got "${raw}"`);
95
+ }
96
+ const actions = parseActions(parts[1], EXEC_ACTIONS, 'exec', raw);
97
+ const binary = parts[2];
98
+ if (binary.includes('/')) {
99
+ throw new CompilationError('CAP_EXEC_PATH', `exec binary is a basename only: "${binary}"`);
100
+ }
101
+ return { kind: 'exec', actions, scope: { binary }, refinements };
102
+ }
103
+ function parseEnv(parts, refinements, raw) {
104
+ if (parts.length !== 3) {
105
+ throw new CompilationError('CAP_ENV_SHAPE', `env needs <actions>:<name>, got "${raw}"`);
106
+ }
107
+ const actions = parseActions(parts[1], ENV_ACTIONS, 'env', raw);
108
+ const name = parts[2];
109
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(name)) {
110
+ throw new CompilationError('CAP_ENV_NAME', `env var name must be UPPER_SNAKE: "${name}"`);
111
+ }
112
+ return { kind: 'env', actions, scope: { name }, refinements };
113
+ }
114
+ function parseIpc(parts, refinements, raw) {
115
+ if (parts.length !== 3) {
116
+ throw new CompilationError('CAP_IPC_SHAPE', `ipc needs <actions>:<endpoint>, got "${raw}"`);
117
+ }
118
+ const actions = parseActions(parts[1], IPC_ACTIONS, 'ipc', raw);
119
+ return { kind: 'ipc', actions, scope: { endpoint: parts[2] }, refinements };
120
+ }
121
+ function parseClock(parts, refinements, raw) {
122
+ if (parts.length !== 2) {
123
+ throw new CompilationError('CAP_CLOCK_SHAPE', `clock needs <source>, got "${raw}"`);
124
+ }
125
+ const source = parts[1];
126
+ if (source !== 'system' && source !== 'tzdata') {
127
+ throw new CompilationError('CAP_CLOCK_SOURCE', `clock source must be system|tzdata: "${source}"`);
128
+ }
129
+ return { kind: 'clock', actions: [], scope: { source }, refinements };
130
+ }
131
+ function parseAssert(parts, refinements, raw) {
132
+ if (parts.length < 2) {
133
+ throw new CompilationError('CAP_ASSERT_SHAPE', `assert needs <id>[:<description>], got "${raw}"`);
134
+ }
135
+ const id = parts[1];
136
+ const description = parts.slice(2).join(':') || id;
137
+ return { kind: 'assert', actions: [], scope: { id, description }, refinements };
138
+ }
139
+ // ---------------------------------------------------------------------------
140
+ // Helpers
141
+ // ---------------------------------------------------------------------------
142
+ function parseActions(raw, allowed, kind, full) {
143
+ if (!raw)
144
+ throw new CompilationError('CAP_ACTIONS_EMPTY', `${kind} requires actions in "${full}"`);
145
+ const parts = raw.split(',').map((a) => a.trim());
146
+ const out = [];
147
+ for (const a of parts) {
148
+ if (!allowed.has(a)) {
149
+ throw new CompilationError('CAP_ACTION_UNKNOWN', `${kind} action "${a}" not allowed`, {
150
+ allowed: [...allowed],
151
+ });
152
+ }
153
+ if (!out.includes(a))
154
+ out.push(a);
155
+ }
156
+ return out;
157
+ }
158
+ function splitRefinements(raw) {
159
+ const q = raw.indexOf('?');
160
+ if (q === -1)
161
+ return [raw, undefined];
162
+ return [raw.slice(0, q), raw.slice(q + 1)];
163
+ }
164
+ function parseRefinements(raw) {
165
+ if (!raw)
166
+ return undefined;
167
+ const out = {};
168
+ for (const pair of raw.split('&')) {
169
+ const [k, v] = pair.split('=');
170
+ if (k === 'nestedSandbox') {
171
+ out.nestedSandbox = v === 'true' || v === '1';
172
+ }
173
+ else {
174
+ (out.adapter ??= {})[k] = v ?? true;
175
+ }
176
+ }
177
+ return out;
178
+ }
179
+ // splitTop is a colon-splitter that respects quoted segments so that
180
+ // assert:id:"text with : inside" parses correctly.
181
+ function splitTop(raw, sep) {
182
+ const out = [];
183
+ let cur = '';
184
+ let inQuote = false;
185
+ for (let i = 0; i < raw.length; i++) {
186
+ const ch = raw[i];
187
+ if (ch === '"') {
188
+ inQuote = !inQuote;
189
+ continue;
190
+ }
191
+ if (ch === sep && !inQuote) {
192
+ out.push(cur);
193
+ cur = '';
194
+ continue;
195
+ }
196
+ cur += ch;
197
+ }
198
+ out.push(cur);
199
+ return out;
200
+ }
201
+ //# sourceMappingURL=grammar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grammar.js","sourceRoot":"","sources":["../../src/policy/grammar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export type { Capability, CapabilityKind, FsAction, NetAction, ExecAction, EnvAction, IpcAction, FsScope, NetScope, ExecScope, EnvScope, IpcScope, ClockScope, AssertScope, Refinements, ToolManifest, ServerManifest, NormalizedPolicy, } from './ir.js';
2
+ export { CompilationError, isEnforceable } from './ir.js';
3
+ export { parseCapability, GRAMMAR_VERSION } from './grammar.js';
4
+ export type { ParseResult } from './grammar.js';
5
+ export { compile, parseManifest, normalize } from './compiler.js';
6
+ export type { RawServerManifest, RawToolManifest } from './compiler.js';
7
+ export { lowerToBwrap } from './adapters/bwrap.js';
8
+ export type { BwrapArtifact, BwrapOptions, EgressRule } from './adapters/bwrap.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,UAAU,EACV,cAAc,EACd,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EACd,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ // Public surface of the policy compiler. Re-exported from the root "capgate"
2
+ // entry point in src/index.ts.
3
+ export { CompilationError, isEnforceable } from './ir.js';
4
+ export { parseCapability, GRAMMAR_VERSION } from './grammar.js';
5
+ export { compile, parseManifest, normalize } from './compiler.js';
6
+ export { lowerToBwrap } from './adapters/bwrap.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+BAA+B;AAsB/B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,147 @@
1
+ export type CapabilityKind = 'fs' | 'net' | 'exec' | 'env' | 'ipc' | 'clock' | 'assert';
2
+ export type FsAction = 'read' | 'write' | 'create' | 'delete';
3
+ export type NetAction = 'connect';
4
+ export type ExecAction = 'spawn';
5
+ export type EnvAction = 'read' | 'inject';
6
+ export type IpcAction = 'connect';
7
+ export interface FsScope {
8
+ /** Absolute path or glob. Relative paths are rejected at parse time. */
9
+ path: string;
10
+ /** True if `path` is a glob (contains *, **, ?, [). Derived, not input. */
11
+ isGlob: boolean;
12
+ }
13
+ export interface NetScope {
14
+ /** Hostname, IP, or wildcard ("*"). RFC1918 blocks are a separate flag. */
15
+ host: string;
16
+ /** TCP/UDP port. null = any port. */
17
+ port: number | null;
18
+ /** If true, RFC1918 + loopback destinations must be rejected by the proxy. */
19
+ blockPrivate: boolean;
20
+ }
21
+ export interface ExecScope {
22
+ /** Binary name resolved against PATH at compile time (e.g. "git", "chromium"). */
23
+ binary: string;
24
+ }
25
+ export interface EnvScope {
26
+ /** Variable name. Values are never embedded in the IR — handled by secret layer. */
27
+ name: string;
28
+ }
29
+ export interface IpcScope {
30
+ /** "unix:/path", "x11", "dbus:session", "dbus:system". */
31
+ endpoint: string;
32
+ }
33
+ export interface ClockScope {
34
+ /** "system" = wall clock only; "tzdata" = also needs /usr/share/zoneinfo. */
35
+ source: 'system' | 'tzdata';
36
+ }
37
+ export interface AssertScope {
38
+ /** Machine-readable assertion id, e.g. "postgres.read_only_txn". */
39
+ id: string;
40
+ /** Human explanation for audit logs and policy reviewers. */
41
+ description: string;
42
+ }
43
+ export type Capability = {
44
+ kind: 'fs';
45
+ actions: FsAction[];
46
+ scope: FsScope;
47
+ refinements?: Refinements;
48
+ } | {
49
+ kind: 'net';
50
+ actions: NetAction[];
51
+ scope: NetScope;
52
+ refinements?: Refinements;
53
+ } | {
54
+ kind: 'exec';
55
+ actions: ExecAction[];
56
+ scope: ExecScope;
57
+ refinements?: Refinements;
58
+ } | {
59
+ kind: 'env';
60
+ actions: EnvAction[];
61
+ scope: EnvScope;
62
+ refinements?: Refinements;
63
+ } | {
64
+ kind: 'ipc';
65
+ actions: IpcAction[];
66
+ scope: IpcScope;
67
+ refinements?: Refinements;
68
+ } | {
69
+ kind: 'clock';
70
+ actions: [];
71
+ scope: ClockScope;
72
+ refinements?: Refinements;
73
+ } | {
74
+ kind: 'assert';
75
+ actions: [];
76
+ scope: AssertScope;
77
+ refinements?: Refinements;
78
+ };
79
+ export interface Refinements {
80
+ /** Tool carries its own sandbox that conflicts with namespace isolation (e.g. Chromium). */
81
+ nestedSandbox?: boolean;
82
+ /** Adapter-specific free-form. Compiler passes through; adapters may read. */
83
+ adapter?: Record<string, unknown>;
84
+ }
85
+ export declare function isEnforceable(cap: Capability): boolean;
86
+ export interface ToolManifest {
87
+ /** MCP tool name. Unique within a server. */
88
+ name: string;
89
+ /** MCP-declared description. Informational only; not used for enforcement. */
90
+ description?: string;
91
+ /** JSON Schema for tool input. Used for input validation, not policy. */
92
+ inputSchema?: Record<string, unknown>;
93
+ /** Declared capabilities. Empty array = pure function, no side effects. */
94
+ capabilities: Capability[];
95
+ }
96
+ export interface ServerManifest {
97
+ /** Server identifier, e.g. "@modelcontextprotocol/server-filesystem". */
98
+ name: string;
99
+ version: string;
100
+ /** Capabilities that apply to every tool (e.g. "read tzdata" for time server). */
101
+ serverCapabilities?: Capability[];
102
+ tools: ToolManifest[];
103
+ }
104
+ export interface NormalizedPolicy {
105
+ /** Server identity — carried through for logging and provenance. */
106
+ server: {
107
+ name: string;
108
+ version: string;
109
+ };
110
+ /** Deduped, merged fs roots. Write implies read. */
111
+ fs: {
112
+ path: string;
113
+ actions: FsAction[];
114
+ isGlob: boolean;
115
+ }[];
116
+ /** Deduped net endpoints. blockPrivate is OR-ed across merges. */
117
+ net: {
118
+ host: string;
119
+ port: number | null;
120
+ blockPrivate: boolean;
121
+ }[];
122
+ /** Binaries the sandbox must keep executable. */
123
+ exec: {
124
+ binary: string;
125
+ }[];
126
+ /** Env vars to inject (values resolved out-of-band from a secret store). */
127
+ env: {
128
+ name: string;
129
+ action: EnvAction;
130
+ }[];
131
+ /** IPC endpoints to expose. */
132
+ ipc: {
133
+ endpoint: string;
134
+ }[];
135
+ /** Clock access profile. "none" if no clock capability declared. */
136
+ clock: 'none' | 'system' | 'tzdata';
137
+ /** Declared assertions. Adapter emits them as metadata, not as enforcement. */
138
+ assertions: AssertScope[];
139
+ /** True if any capability requested a nested sandbox. Adapters MUST react. */
140
+ nestedSandbox: boolean;
141
+ }
142
+ export declare class CompilationError extends Error {
143
+ code: string;
144
+ context?: Record<string, unknown> | undefined;
145
+ constructor(code: string, message: string, context?: Record<string, unknown> | undefined);
146
+ }
147
+ //# sourceMappingURL=ir.d.ts.map