agy-worker-mcp 0.3.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.
- package/CHANGELOG.md +141 -0
- package/LICENSE +21 -0
- package/README.md +309 -0
- package/commands/agy-ceiling.md +31 -0
- package/dist/broker/blockers.d.ts +86 -0
- package/dist/broker/blockers.d.ts.map +1 -0
- package/dist/broker/blockers.js +390 -0
- package/dist/broker/blockers.js.map +1 -0
- package/dist/broker/outcome.d.ts +85 -0
- package/dist/broker/outcome.d.ts.map +1 -0
- package/dist/broker/outcome.js +147 -0
- package/dist/broker/outcome.js.map +1 -0
- package/dist/broker/reconcile.d.ts +74 -0
- package/dist/broker/reconcile.d.ts.map +1 -0
- package/dist/broker/reconcile.js +415 -0
- package/dist/broker/reconcile.js.map +1 -0
- package/dist/broker/result.d.ts +88 -0
- package/dist/broker/result.d.ts.map +1 -0
- package/dist/broker/result.js +234 -0
- package/dist/broker/result.js.map +1 -0
- package/dist/broker/verify.d.ts +52 -0
- package/dist/broker/verify.d.ts.map +1 -0
- package/dist/broker/verify.js +174 -0
- package/dist/broker/verify.js.map +1 -0
- package/dist/contract/errors.d.ts +119 -0
- package/dist/contract/errors.d.ts.map +1 -0
- package/dist/contract/errors.js +99 -0
- package/dist/contract/errors.js.map +1 -0
- package/dist/contract/index.d.ts +10 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +10 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/paths.d.ts +139 -0
- package/dist/contract/paths.d.ts.map +1 -0
- package/dist/contract/paths.js +359 -0
- package/dist/contract/paths.js.map +1 -0
- package/dist/contract/schema.sql +64 -0
- package/dist/contract/types.d.ts +1113 -0
- package/dist/contract/types.d.ts.map +1 -0
- package/dist/contract/types.js +114 -0
- package/dist/contract/types.js.map +1 -0
- package/dist/events/cursor.d.ts +65 -0
- package/dist/events/cursor.d.ts.map +1 -0
- package/dist/events/cursor.js +286 -0
- package/dist/events/cursor.js.map +1 -0
- package/dist/events/detect.d.ts +58 -0
- package/dist/events/detect.d.ts.map +1 -0
- package/dist/events/detect.js +183 -0
- package/dist/events/detect.js.map +1 -0
- package/dist/events/normalize.d.ts +30 -0
- package/dist/events/normalize.d.ts.map +1 -0
- package/dist/events/normalize.js +158 -0
- package/dist/events/normalize.js.map +1 -0
- package/dist/events/parse.d.ts +41 -0
- package/dist/events/parse.d.ts.map +1 -0
- package/dist/events/parse.js +89 -0
- package/dist/events/parse.js.map +1 -0
- package/dist/gate/bind.d.ts +28 -0
- package/dist/gate/bind.d.ts.map +1 -0
- package/dist/gate/bind.js +154 -0
- package/dist/gate/bind.js.map +1 -0
- package/dist/gate/gate.d.ts +139 -0
- package/dist/gate/gate.d.ts.map +1 -0
- package/dist/gate/gate.js +488 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/hooks-file.d.ts +55 -0
- package/dist/gate/hooks-file.d.ts.map +1 -0
- package/dist/gate/hooks-file.js +104 -0
- package/dist/gate/hooks-file.js.map +1 -0
- package/dist/gate.d.ts +3 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +20 -0
- package/dist/gate.js.map +1 -0
- package/dist/policy/ceiling-review.d.ts +22 -0
- package/dist/policy/ceiling-review.d.ts.map +1 -0
- package/dist/policy/ceiling-review.js +170 -0
- package/dist/policy/ceiling-review.js.map +1 -0
- package/dist/policy/ceiling.d.ts +128 -0
- package/dist/policy/ceiling.d.ts.map +1 -0
- package/dist/policy/ceiling.js +273 -0
- package/dist/policy/ceiling.js.map +1 -0
- package/dist/policy/containment.d.ts +100 -0
- package/dist/policy/containment.d.ts.map +1 -0
- package/dist/policy/containment.js +1071 -0
- package/dist/policy/containment.js.map +1 -0
- package/dist/policy/hard-deny.d.ts +28 -0
- package/dist/policy/hard-deny.d.ts.map +1 -0
- package/dist/policy/hard-deny.js +78 -0
- package/dist/policy/hard-deny.js.map +1 -0
- package/dist/policy/profiles.d.ts +82 -0
- package/dist/policy/profiles.d.ts.map +1 -0
- package/dist/policy/profiles.js +317 -0
- package/dist/policy/profiles.js.map +1 -0
- package/dist/policy/rules.d.ts +138 -0
- package/dist/policy/rules.d.ts.map +1 -0
- package/dist/policy/rules.js +1180 -0
- package/dist/policy/rules.js.map +1 -0
- package/dist/policy/seatbelt.d.ts +32 -0
- package/dist/policy/seatbelt.d.ts.map +1 -0
- package/dist/policy/seatbelt.js +59 -0
- package/dist/policy/seatbelt.js.map +1 -0
- package/dist/policy/tools.d.ts +36 -0
- package/dist/policy/tools.d.ts.map +1 -0
- package/dist/policy/tools.js +94 -0
- package/dist/policy/tools.js.map +1 -0
- package/dist/runner/gate-watchdog.d.ts +93 -0
- package/dist/runner/gate-watchdog.d.ts.map +1 -0
- package/dist/runner/gate-watchdog.js +153 -0
- package/dist/runner/gate-watchdog.js.map +1 -0
- package/dist/runner/idle.d.ts +51 -0
- package/dist/runner/idle.d.ts.map +1 -0
- package/dist/runner/idle.js +81 -0
- package/dist/runner/idle.js.map +1 -0
- package/dist/runner/inbox.d.ts +56 -0
- package/dist/runner/inbox.d.ts.map +1 -0
- package/dist/runner/inbox.js +134 -0
- package/dist/runner/inbox.js.map +1 -0
- package/dist/runner/reap.d.ts +65 -0
- package/dist/runner/reap.d.ts.map +1 -0
- package/dist/runner/reap.js +168 -0
- package/dist/runner/reap.js.map +1 -0
- package/dist/runner/runner.d.ts +51 -0
- package/dist/runner/runner.d.ts.map +1 -0
- package/dist/runner/runner.js +289 -0
- package/dist/runner/runner.js.map +1 -0
- package/dist/runner/spawn.d.ts +98 -0
- package/dist/runner/spawn.d.ts.map +1 -0
- package/dist/runner/spawn.js +230 -0
- package/dist/runner/spawn.js.map +1 -0
- package/dist/runner/verify.d.ts +24 -0
- package/dist/runner/verify.d.ts.map +1 -0
- package/dist/runner/verify.js +108 -0
- package/dist/runner/verify.js.map +1 -0
- package/dist/runner.d.ts +3 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +15 -0
- package/dist/runner.js.map +1 -0
- package/dist/server/context.d.ts +41 -0
- package/dist/server/context.d.ts.map +1 -0
- package/dist/server/context.js +59 -0
- package/dist/server/context.js.map +1 -0
- package/dist/server/instructions.d.ts +13 -0
- package/dist/server/instructions.d.ts.map +1 -0
- package/dist/server/instructions.js +121 -0
- package/dist/server/instructions.js.map +1 -0
- package/dist/server/server.d.ts +20 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +55 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/tools/cancel.d.ts +24 -0
- package/dist/server/tools/cancel.d.ts.map +1 -0
- package/dist/server/tools/cancel.js +59 -0
- package/dist/server/tools/cancel.js.map +1 -0
- package/dist/server/tools/capabilities.d.ts +36 -0
- package/dist/server/tools/capabilities.d.ts.map +1 -0
- package/dist/server/tools/capabilities.js +116 -0
- package/dist/server/tools/capabilities.js.map +1 -0
- package/dist/server/tools/ceiling.d.ts +31 -0
- package/dist/server/tools/ceiling.d.ts.map +1 -0
- package/dist/server/tools/ceiling.js +121 -0
- package/dist/server/tools/ceiling.js.map +1 -0
- package/dist/server/tools/index.d.ts +38 -0
- package/dist/server/tools/index.d.ts.map +1 -0
- package/dist/server/tools/index.js +115 -0
- package/dist/server/tools/index.js.map +1 -0
- package/dist/server/tools/listJobs.d.ts +30 -0
- package/dist/server/tools/listJobs.d.ts.map +1 -0
- package/dist/server/tools/listJobs.js +37 -0
- package/dist/server/tools/listJobs.js.map +1 -0
- package/dist/server/tools/logs.d.ts +31 -0
- package/dist/server/tools/logs.d.ts.map +1 -0
- package/dist/server/tools/logs.js +96 -0
- package/dist/server/tools/logs.js.map +1 -0
- package/dist/server/tools/result.d.ts +32 -0
- package/dist/server/tools/result.d.ts.map +1 -0
- package/dist/server/tools/result.js +95 -0
- package/dist/server/tools/result.js.map +1 -0
- package/dist/server/tools/send.d.ts +37 -0
- package/dist/server/tools/send.d.ts.map +1 -0
- package/dist/server/tools/send.js +71 -0
- package/dist/server/tools/send.js.map +1 -0
- package/dist/server/tools/sessions.d.ts +28 -0
- package/dist/server/tools/sessions.d.ts.map +1 -0
- package/dist/server/tools/sessions.js +54 -0
- package/dist/server/tools/sessions.js.map +1 -0
- package/dist/server/tools/start.d.ts +107 -0
- package/dist/server/tools/start.d.ts.map +1 -0
- package/dist/server/tools/start.js +482 -0
- package/dist/server/tools/start.js.map +1 -0
- package/dist/server/tools/wait.d.ts +29 -0
- package/dist/server/tools/wait.d.ts.map +1 -0
- package/dist/server/tools/wait.js +120 -0
- package/dist/server/tools/wait.js.map +1 -0
- package/dist/server.d.ts +3 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +17 -0
- package/dist/server.js.map +1 -0
- package/dist/setup/install.d.ts +52 -0
- package/dist/setup/install.d.ts.map +1 -0
- package/dist/setup/install.js +108 -0
- package/dist/setup/install.js.map +1 -0
- package/dist/setup.d.ts +3 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +24 -0
- package/dist/setup.js.map +1 -0
- package/dist/store/db.d.ts +49 -0
- package/dist/store/db.d.ts.map +1 -0
- package/dist/store/db.js +101 -0
- package/dist/store/db.js.map +1 -0
- package/dist/store/jobs.d.ts +45 -0
- package/dist/store/jobs.d.ts.map +1 -0
- package/dist/store/jobs.js +150 -0
- package/dist/store/jobs.js.map +1 -0
- package/dist/store/locks.d.ts +60 -0
- package/dist/store/locks.d.ts.map +1 -0
- package/dist/store/locks.js +172 -0
- package/dist/store/locks.js.map +1 -0
- package/dist/store/sessions.d.ts +37 -0
- package/dist/store/sessions.d.ts.map +1 -0
- package/dist/store/sessions.js +117 -0
- package/dist/store/sessions.js.map +1 -0
- package/dist/trace/digest.d.ts +77 -0
- package/dist/trace/digest.d.ts.map +1 -0
- package/dist/trace/digest.js +481 -0
- package/dist/trace/digest.js.map +1 -0
- package/package.json +68 -0
- package/skills/agy-ceiling/SKILL.md +72 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import { canonicalize } from '../contract/paths.js';
|
|
6
|
+
import { ValidationError } from '../contract/errors.js';
|
|
7
|
+
import { HARD_DENY } from './hard-deny.js';
|
|
8
|
+
import { matchesPathGlob, parseRule } from './rules.js';
|
|
9
|
+
export const EMPTY_CEILING = Object.freeze({
|
|
10
|
+
present: false,
|
|
11
|
+
path: null,
|
|
12
|
+
allow: [],
|
|
13
|
+
deny: [],
|
|
14
|
+
exceptions: [],
|
|
15
|
+
sandbox: 'none',
|
|
16
|
+
read_roots: [],
|
|
17
|
+
write_roots: [],
|
|
18
|
+
command_policy: 'allowlist',
|
|
19
|
+
version: null,
|
|
20
|
+
warnings: [],
|
|
21
|
+
});
|
|
22
|
+
const ceilingSchemaV1 = z.object({
|
|
23
|
+
version: z.literal(1),
|
|
24
|
+
extra_allow: z.array(z.string()).optional(),
|
|
25
|
+
extra_deny: z.array(z.string()).optional(),
|
|
26
|
+
sandboxed: z.boolean().optional(),
|
|
27
|
+
additional_dirs: z.array(z.string()).optional(),
|
|
28
|
+
command_policy: z.enum(['allowlist', 'denylist']).optional(),
|
|
29
|
+
}).strict();
|
|
30
|
+
const ceilingSchemaV2 = z.object({
|
|
31
|
+
version: z.literal(2),
|
|
32
|
+
allow: z.array(z.string()).optional(),
|
|
33
|
+
deny: z.array(z.string()).optional(),
|
|
34
|
+
exceptions: z.array(z.string()).optional(),
|
|
35
|
+
sandbox: z.enum(['none', 'seatbelt', 'agy']).optional(),
|
|
36
|
+
/** Legacy spelling of `sandbox: 'agy'`; kept so a 0.2.x v2-shaped file still loads. */
|
|
37
|
+
sandboxed: z.boolean().optional(),
|
|
38
|
+
read_roots: z.array(z.string()).optional(),
|
|
39
|
+
write_roots: z.array(z.string()).optional(),
|
|
40
|
+
command_policy: z.enum(['allowlist', 'denylist']).optional(),
|
|
41
|
+
}).strict();
|
|
42
|
+
const ceilingSchema = z.discriminatedUnion('version', [ceilingSchemaV1, ceilingSchemaV2]);
|
|
43
|
+
/** v1 → v2 key names, for the conversion warning and the error text. */
|
|
44
|
+
const V1_RENAMES = [
|
|
45
|
+
['extra_allow', 'allow'],
|
|
46
|
+
['extra_deny', 'deny'],
|
|
47
|
+
['additional_dirs', 'read_roots'],
|
|
48
|
+
];
|
|
49
|
+
/** `<project state dir>/policy.json`. Exported so callers (capabilities, tests) don't hardcode the filename. */
|
|
50
|
+
export function ceilingPath(paths) {
|
|
51
|
+
return join(paths.dir, 'policy.json');
|
|
52
|
+
}
|
|
53
|
+
function expandHome(p) {
|
|
54
|
+
const home = process.env.HOME ?? homedir();
|
|
55
|
+
if (p === '~')
|
|
56
|
+
return home;
|
|
57
|
+
if (p.startsWith('~/'))
|
|
58
|
+
return join(home, p.slice(2));
|
|
59
|
+
return p;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Best-effort absolute form of a `read_roots` entry. `canonicalize()`
|
|
63
|
+
* (`contract/paths.ts`) never treats `*`/`**` specially — it only resolves real
|
|
64
|
+
* ancestors via `realpathSync` and appends whatever tail does not exist yet —
|
|
65
|
+
* so a glob segment simply survives as literal path content, which is exactly
|
|
66
|
+
* what `matchesPathGlob` expects to match against later.
|
|
67
|
+
*/
|
|
68
|
+
function resolveDirPattern(pattern) {
|
|
69
|
+
return canonicalize(expandHome(pattern));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Convert a ceiling `read_roots` pattern (potentially a glob like `~/.jdks/**`)
|
|
73
|
+
* into a concrete directory root for `--add-dir`.
|
|
74
|
+
*
|
|
75
|
+
* Takes the fixed prefix before the first wildcard (`*`), strips trailing `/`,
|
|
76
|
+
* resolves home expansion and canonicalization via `resolveDirPattern`, and returns
|
|
77
|
+
* the canonical directory path if it exists and is a directory; otherwise null.
|
|
78
|
+
*/
|
|
79
|
+
export function additionalDirRoot(pattern) {
|
|
80
|
+
const starIdx = pattern.indexOf('*');
|
|
81
|
+
let prefix = starIdx === -1 ? pattern : pattern.slice(0, starIdx);
|
|
82
|
+
while (prefix.length > 1 && prefix.endsWith('/')) {
|
|
83
|
+
prefix = prefix.slice(0, -1);
|
|
84
|
+
}
|
|
85
|
+
if (prefix === '')
|
|
86
|
+
return null;
|
|
87
|
+
const resolved = resolveDirPattern(prefix);
|
|
88
|
+
try {
|
|
89
|
+
if (existsSync(resolved) && statSync(resolved).isDirectory()) {
|
|
90
|
+
return canonicalize(resolved);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
/** Every throw from `loadCeiling` goes through here so the shape stays uniform. */
|
|
99
|
+
function fail(path, expected, value) {
|
|
100
|
+
throw new ValidationError({
|
|
101
|
+
field: 'ceiling',
|
|
102
|
+
value: value ?? path,
|
|
103
|
+
expected: `${expected} — fix ${path}`,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Load and validate the project ceiling.
|
|
108
|
+
*
|
|
109
|
+
* Missing file → {@link EMPTY_CEILING} (a project with no ceiling file grants
|
|
110
|
+
* nothing beyond the profiles' own defaults — narrower, not wider, than
|
|
111
|
+
* having one). Present but invalid — bad JSON, `version` other than `1`/`2`, a
|
|
112
|
+
* non-string entry, an entry that does not parse as `verb(pattern)`
|
|
113
|
+
* (`parseRule`), or a legacy `unsandboxed` entry — throws
|
|
114
|
+
* {@link ValidationError} with `field: 'ceiling'` and the file path, so
|
|
115
|
+
* `agy_start` fails closed and tells the human what to fix instead of quietly
|
|
116
|
+
* falling back to an empty ceiling (which would look like "nothing is
|
|
117
|
+
* misconfigured" when something very much is).
|
|
118
|
+
*
|
|
119
|
+
* `{workspace}` substitution on `allow`/`deny`/`exceptions` is
|
|
120
|
+
* deferred to `resolvePolicy` — this file has no workspace of its own; one
|
|
121
|
+
* project can run jobs against several `cwd` values under the same ceiling.
|
|
122
|
+
* `read_roots` entries are not job-specific, so they are `~`-expanded and
|
|
123
|
+
* canonicalized once, here.
|
|
124
|
+
*/
|
|
125
|
+
export function loadCeiling(paths) {
|
|
126
|
+
const path = ceilingPath(paths);
|
|
127
|
+
if (!existsSync(path))
|
|
128
|
+
return { ...EMPTY_CEILING, path };
|
|
129
|
+
let raw;
|
|
130
|
+
try {
|
|
131
|
+
raw = readFileSync(path, 'utf8');
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
return fail(path, `policy.json exists but could not be read (${String(e)})`);
|
|
135
|
+
}
|
|
136
|
+
let json;
|
|
137
|
+
try {
|
|
138
|
+
json = JSON.parse(raw);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return fail(path, 'policy.json is not valid JSON');
|
|
142
|
+
}
|
|
143
|
+
return parseCeilingJson(json, path);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The validation half of {@link loadCeiling}, separated so `agy_ceiling` can
|
|
147
|
+
* check a draft that exists only in the caller's hands — same rules, same
|
|
148
|
+
* error texts, no file. `path` only labels the error.
|
|
149
|
+
*/
|
|
150
|
+
export function parseCeilingJson(json, path) {
|
|
151
|
+
if (typeof json === 'object' && json !== null && 'unsandboxed' in json) {
|
|
152
|
+
return fail(path, 'the "unsandboxed" key was removed in 0.2.1; allowed commands now run without agy\'s OS sandbox by default. Delete "unsandboxed" from policy.json (and set "sandboxed": true if you want the old behaviour of forcing the sandbox on)');
|
|
153
|
+
}
|
|
154
|
+
const parsed = ceilingSchema.safeParse(json);
|
|
155
|
+
if (!parsed.success) {
|
|
156
|
+
return fail(path, `policy.json must be { version: 2, allow?, deny?, exceptions?, sandbox?, read_roots?, write_roots?, command_policy? } (${parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')})`, json);
|
|
157
|
+
}
|
|
158
|
+
const warnings = [];
|
|
159
|
+
let allow;
|
|
160
|
+
let deny;
|
|
161
|
+
let exceptions;
|
|
162
|
+
let readRoots;
|
|
163
|
+
let writeRoots = [];
|
|
164
|
+
let sandbox;
|
|
165
|
+
const d = parsed.data;
|
|
166
|
+
if (d.version === 1) {
|
|
167
|
+
sandbox = d.sandboxed ? 'agy' : 'none';
|
|
168
|
+
allow = d.extra_allow ?? [];
|
|
169
|
+
deny = d.extra_deny ?? [];
|
|
170
|
+
exceptions = [];
|
|
171
|
+
readRoots = d.additional_dirs ?? [];
|
|
172
|
+
const present = V1_RENAMES.filter(([from]) => from in json);
|
|
173
|
+
warnings.push(`policy.json is version 1; rename ${present.length > 0 ? present.map(([a, b]) => `${a} → ${b}`).join(', ') : 'its keys'} and set "version": 2 (v1 is read and converted in 0.3.x, removed in 0.4)`);
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
allow = d.allow ?? [];
|
|
177
|
+
deny = d.deny ?? [];
|
|
178
|
+
exceptions = d.exceptions ?? [];
|
|
179
|
+
readRoots = d.read_roots ?? [];
|
|
180
|
+
writeRoots = d.write_roots ?? [];
|
|
181
|
+
if (d.sandbox !== undefined && d.sandboxed !== undefined) {
|
|
182
|
+
return fail(path, 'policy.json sets both "sandbox" and the legacy "sandboxed"; keep "sandbox" only');
|
|
183
|
+
}
|
|
184
|
+
sandbox = d.sandbox ?? (d.sandboxed ? 'agy' : 'none');
|
|
185
|
+
if (d.sandboxed !== undefined) {
|
|
186
|
+
warnings.push('policy.json uses the legacy "sandboxed" key; write "sandbox": "agy" (or "none") instead');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const commandPolicy = d.command_policy ?? 'allowlist';
|
|
190
|
+
for (const root of writeRoots) {
|
|
191
|
+
if (root.includes('*')) {
|
|
192
|
+
return fail(path, `write_roots entry is a glob (${root}); write roots are plain directories`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
for (const rule of [...allow, ...deny, ...exceptions]) {
|
|
196
|
+
try {
|
|
197
|
+
parseRule(rule);
|
|
198
|
+
}
|
|
199
|
+
catch {
|
|
200
|
+
return fail(path, `allow/deny/exceptions entry is not a valid "verb(pattern)" rule: ${rule}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
for (const rule of exceptions) {
|
|
204
|
+
if (HARD_DENY.includes(rule)) {
|
|
205
|
+
return fail(path, `exceptions may not lift a HARD_DENY rule (${rule}); those protect the gate itself (.agents, credentials, subagents) and cannot be opened by any file`);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
present: true,
|
|
210
|
+
path,
|
|
211
|
+
allow,
|
|
212
|
+
deny,
|
|
213
|
+
exceptions,
|
|
214
|
+
sandbox,
|
|
215
|
+
read_roots: readRoots.map(resolveDirPattern),
|
|
216
|
+
write_roots: Array.from(new Set(writeRoots.map(resolveDirPattern))),
|
|
217
|
+
command_policy: commandPolicy,
|
|
218
|
+
version: d.version,
|
|
219
|
+
warnings,
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Is `canonicalDir` (already `~`-expanded/canonicalized, e.g. via
|
|
224
|
+
* {@link resolveDirPattern}) covered by some glob in the ceiling's
|
|
225
|
+
* `read_roots`? The one place `read_roots` matching happens, so
|
|
226
|
+
* `resolvePolicy` and any test never re-implement the glob semantics.
|
|
227
|
+
*/
|
|
228
|
+
export function additionalDirCovered(ceiling, canonicalDir) {
|
|
229
|
+
return ceiling.read_roots.some((pattern) => matchesPathGlob(pattern, canonicalDir));
|
|
230
|
+
}
|
|
231
|
+
/** `~`-expand and canonicalize a requested `read_roots` entry the same way ceiling entries are resolved. */
|
|
232
|
+
export function resolveRequestedDir(pattern) {
|
|
233
|
+
return resolveDirPattern(pattern);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Render a loaded ceiling for `agy_capabilities`.
|
|
237
|
+
*
|
|
238
|
+
* No `{workspace}` substitution: capabilities has no per-job workspace (a
|
|
239
|
+
* project can run jobs against several `cwd` values), so a rule string
|
|
240
|
+
* carrying the literal `{workspace}` placeholder is returned exactly as
|
|
241
|
+
* written in `policy.json`. A caller sees the substituted, job-real form in
|
|
242
|
+
* `agy_start`'s own `policy_summary` instead.
|
|
243
|
+
*/
|
|
244
|
+
/**
|
|
245
|
+
* The one sentence every surface says when there is no ceiling file. Not an
|
|
246
|
+
* error — the profile as shipped is the safe default — but the agent and the
|
|
247
|
+
* user should both know that the door exists and who holds the key: the user
|
|
248
|
+
* approves, the agent (via `agy_ceiling` / the `agy-ceiling` skill) or the
|
|
249
|
+
* user (via `/agy-ceiling`) drafts.
|
|
250
|
+
*/
|
|
251
|
+
export function ceilingAbsenceHint(path) {
|
|
252
|
+
const where = path ? ` at ${path}` : '';
|
|
253
|
+
return (`no project ceiling${where}: jobs run with the profile as shipped (general_worker allows build/test tools and local git; ` +
|
|
254
|
+
`git push, curl, wget, ssh, sudo, docker, npm/pip install and rm -rf are denied, and any other command is denied unless the ceiling allows it). ` +
|
|
255
|
+
`If this project needs more, propose a ceiling: call agy_ceiling (or the user runs /agy-ceiling, or use the agy-ceiling skill), ` +
|
|
256
|
+
`show the draft, and write the file only after the user approves it in this conversation.`);
|
|
257
|
+
}
|
|
258
|
+
export function describeCeiling(ceiling, path, present) {
|
|
259
|
+
return {
|
|
260
|
+
path,
|
|
261
|
+
present,
|
|
262
|
+
version: ceiling.version,
|
|
263
|
+
allow: ceiling.allow,
|
|
264
|
+
deny: ceiling.deny,
|
|
265
|
+
exceptions: ceiling.exceptions,
|
|
266
|
+
sandbox: ceiling.sandbox,
|
|
267
|
+
read_roots: ceiling.read_roots,
|
|
268
|
+
write_roots: ceiling.write_roots,
|
|
269
|
+
command_policy: ceiling.command_policy,
|
|
270
|
+
warnings: present ? ceiling.warnings : [...ceiling.warnings, ceilingAbsenceHint(path)],
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
//# sourceMappingURL=ceiling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ceiling.js","sourceRoot":"","sources":["../../src/policy/ceiling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read/write root enforcement.
|
|
3
|
+
*
|
|
4
|
+
* The primitives live in `contract/paths.ts` (`canonicalize`, `isWithin`,
|
|
5
|
+
* `assertContained`); this module is the policy layer that decides which roots a
|
|
6
|
+
* job gets and pulls the paths out of a tool call.
|
|
7
|
+
*/
|
|
8
|
+
export interface ContainmentRoots {
|
|
9
|
+
read: string[];
|
|
10
|
+
write: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Roots for a job. Write is the workspace alone. Read may include a small set of
|
|
14
|
+
* additional canonical directories, but never credential paths.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildRoots(workspace: string, extraRead?: string[]): ContainmentRoots;
|
|
17
|
+
/** @throws {import('../contract/errors.js').PathEscapeError} */
|
|
18
|
+
export declare function checkRead(path: string, roots: ContainmentRoots): string;
|
|
19
|
+
/** @throws {import('../contract/errors.js').PathEscapeError} */
|
|
20
|
+
export declare function checkWrite(path: string, roots: ContainmentRoots): string;
|
|
21
|
+
/** A bare, unquoted, absolute-looking token or NAME=/abs/path assignment inside a shell command line. */
|
|
22
|
+
export declare const ABS_PATH_TOKEN: RegExp;
|
|
23
|
+
/**
|
|
24
|
+
* Allowed non-workspace read targets (special pseudo-devices).
|
|
25
|
+
* Kept strictly to the standard dev sinks/sources documented in gate policy:
|
|
26
|
+
* /dev/null, /dev/stdin, /dev/stdout, /dev/stderr.
|
|
27
|
+
* All other paths outside workspace/read_roots are denied.
|
|
28
|
+
*/
|
|
29
|
+
export declare const ALLOWED_DEV_READS: Set<string>;
|
|
30
|
+
export declare function getCanonicalHome(): string;
|
|
31
|
+
/**
|
|
32
|
+
* Normalises a path token before containment:
|
|
33
|
+
* - a leading `~/` or bare `~` is expanded to the real home directory;
|
|
34
|
+
* - a glob (`*`, `?`, `[`) is cut back to its literal directory prefix
|
|
35
|
+
* (`src/*.ts` → `src`, `*.ts` → `.`, `dist/**/x` → `dist`), because a shell
|
|
36
|
+
* glob can only ever expand inside the directory named before the first
|
|
37
|
+
* glob character — containing that directory contains every match.
|
|
38
|
+
* Anything else (`$VAR`, backticks, a non-leading `~`) is left as is for
|
|
39
|
+
* {@link hasUnexpandedChars} to reject.
|
|
40
|
+
*/
|
|
41
|
+
export declare function expandLeadingTilde(token: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* True when a token still carries a shell expansion the gate cannot resolve:
|
|
44
|
+
* `$VAR`/`$HOME`/`$(…)`, backticks, or a `~` that is not the leading one
|
|
45
|
+
* (checked after {@link expandLeadingTilde}). Globs are not listed — they are
|
|
46
|
+
* cut back to their literal directory by `expandLeadingTilde` instead.
|
|
47
|
+
*/
|
|
48
|
+
export declare function hasUnexpandedChars(token: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Tests whether a token looks like a path argument:
|
|
51
|
+
* - absolute (starts with / or isAbsolute)
|
|
52
|
+
* - starts with ~/ or is ~
|
|
53
|
+
* - starts with ./ or ../
|
|
54
|
+
* - contains /
|
|
55
|
+
* - matches an existing file relative to the workspace
|
|
56
|
+
*/
|
|
57
|
+
export declare function isPathLike(token: string, workspace?: string): boolean;
|
|
58
|
+
export declare const MUTATION_COMMANDS: Set<string>;
|
|
59
|
+
export declare const READ_UTILITIES: Set<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Extract target write paths for mutating commands.
|
|
62
|
+
* Includes rm, mv, cp, touch, mkdir, sed -i, sort -o, tee, git archive/clone/init/worktree,
|
|
63
|
+
* install, ln, truncate, dd of=, tar -C/-f, unzip -d, rsync, javac -d.
|
|
64
|
+
* Recurses into bash -c / sh -c.
|
|
65
|
+
*/
|
|
66
|
+
export declare function commandMutationWritePaths(commandLine: string, cwd?: string | null): string[];
|
|
67
|
+
export interface CommandContainmentAnalysis {
|
|
68
|
+
writePaths: string[];
|
|
69
|
+
readPaths: string[];
|
|
70
|
+
unexpandedPath: string | null;
|
|
71
|
+
candidatePaths: string[];
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Full structural extraction of paths from a command line.
|
|
75
|
+
* Extracts mutation targets, redirection targets, and read targets.
|
|
76
|
+
* Detects unexpanded shell expansions and collects candidate paths for credential checks.
|
|
77
|
+
*/
|
|
78
|
+
export declare function extractCommandContainment(commandLine: string, workspace: string): CommandContainmentAnalysis;
|
|
79
|
+
export declare function pathsFromToolCall(toolName: string, args: Record<string, unknown>): {
|
|
80
|
+
read: string[];
|
|
81
|
+
write: string[];
|
|
82
|
+
};
|
|
83
|
+
export declare function assignmentReadPaths(commandLine: string): string[];
|
|
84
|
+
/** Non-throwing containment probe over both root sets. */
|
|
85
|
+
export declare function isContainedForKind(path: string, roots: ContainmentRoots, kind: 'read' | 'write'): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* I6: `{workspace}/.agents/**` holds the
|
|
88
|
+
* gate's own `hooks.json`, so it is write-protected even though it sits
|
|
89
|
+
* *inside* the workspace and would otherwise pass ordinary containment.
|
|
90
|
+
*/
|
|
91
|
+
export declare function isAgentsPath(path: string, workspace: string): boolean;
|
|
92
|
+
export declare function redirectionTargets(commandLine: string, workspace: string): string[];
|
|
93
|
+
export declare function escapingRedirectTarget(commandLine: string, workspace: string): string | null;
|
|
94
|
+
/**
|
|
95
|
+
* Ceiling write_roots sanity.
|
|
96
|
+
* If an effective write root is /, the home directory, contains ~/.agy-worker,
|
|
97
|
+
* or contains the gate binary, refuse with ValidationError.
|
|
98
|
+
*/
|
|
99
|
+
export declare function validateWriteRoots(writeRoots: string[], gatePath?: string): void;
|
|
100
|
+
//# sourceMappingURL=containment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"containment.d.ts","sourceRoot":"","sources":["../../src/policy/containment.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,KAAK,EAAE,MAAM,EAAE,CAAA;CAChB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAIpF;AAED,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAEvE;AAED,gEAAgE;AAChE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAExE;AAED,yGAAyG;AACzG,eAAO,MAAM,cAAc,QAAyD,CAAA;AAEpF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,aAK5B,CAAA;AAEF,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAYxD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAerE;AAED,eAAO,MAAM,iBAAiB,aAW5B,CAAA;AAEF,eAAO,MAAM,cAAc,aAuBzB,CAAA;AA4QF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAsF5F;AA4PD,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,0BAA0B,CA2H5G;AAED,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAoCrC;AAKD,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAqBjE;AAED,0DAA0D;AAC1D,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,MAAM,GAAG,OAAO,GACrB,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAGrE;AASD,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CA0BnF;AAED,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ5F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAqChF"}
|