hoolix 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/commands/approvals.d.ts +2 -0
- package/dist/commands/approvals.d.ts.map +1 -0
- package/dist/commands/approvals.js +65 -0
- package/dist/commands/approvals.js.map +1 -0
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +78 -3
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +22 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/gateway.d.ts.map +1 -1
- package/dist/commands/gateway.js +12 -5
- package/dist/commands/gateway.js.map +1 -1
- package/dist/commands/profile.d.ts +2 -0
- package/dist/commands/profile.d.ts.map +1 -0
- package/dist/commands/profile.js +169 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/core/approvals.d.ts +67 -0
- package/dist/core/approvals.d.ts.map +1 -0
- package/dist/core/approvals.js +104 -0
- package/dist/core/approvals.js.map +1 -0
- package/dist/core/paths.d.ts +4 -0
- package/dist/core/paths.d.ts.map +1 -1
- package/dist/core/paths.js +12 -0
- package/dist/core/paths.js.map +1 -1
- package/dist/core/policy.d.ts +20 -0
- package/dist/core/policy.d.ts.map +1 -0
- package/dist/core/policy.js +95 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/profiles.d.ts +141 -0
- package/dist/core/profiles.d.ts.map +1 -0
- package/dist/core/profiles.js +159 -0
- package/dist/core/profiles.js.map +1 -0
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/gateway-host.d.ts.map +1 -1
- package/dist/mcp/gateway-host.js +75 -8
- package/dist/mcp/gateway-host.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +38 -5
- package/dist/tui/index.js.map +1 -1
- package/dist/ui/help.d.ts.map +1 -1
- package/dist/ui/help.js +6 -1
- package/dist/ui/help.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { createProfile, deleteProfile, getProfile, listProfiles, maskProfile, saveProfile, expandIncludes } from '../core/profiles.js';
|
|
2
|
+
import { logger } from '../core/logger.js';
|
|
3
|
+
import { printTitle, printSection, printDetails, printCommand, printJson, printTable } from '../ui/format.js';
|
|
4
|
+
function valuesFor(args, flag) {
|
|
5
|
+
const values = [];
|
|
6
|
+
for (let i = 0; i < args.length; i++) {
|
|
7
|
+
if (args[i] === flag && args[i + 1])
|
|
8
|
+
values.push(args[i + 1]);
|
|
9
|
+
}
|
|
10
|
+
return values;
|
|
11
|
+
}
|
|
12
|
+
function valueFor(args, flag) {
|
|
13
|
+
const idx = args.indexOf(flag);
|
|
14
|
+
return idx !== -1 ? args[idx + 1] : undefined;
|
|
15
|
+
}
|
|
16
|
+
function parseApproval(value) {
|
|
17
|
+
if (value === 'read-only')
|
|
18
|
+
return value;
|
|
19
|
+
if (value === 'always' || value === 'always-approve')
|
|
20
|
+
return 'always';
|
|
21
|
+
return 'writes';
|
|
22
|
+
}
|
|
23
|
+
function splitCsv(values) {
|
|
24
|
+
return values.flatMap((value) => value.split(',').map((part) => part.trim()).filter(Boolean));
|
|
25
|
+
}
|
|
26
|
+
function parseRules(values) {
|
|
27
|
+
return splitCsv(values).map((value) => {
|
|
28
|
+
const [match, effectRaw] = value.includes('=')
|
|
29
|
+
? value.split('=', 2)
|
|
30
|
+
: value.split(':', 2);
|
|
31
|
+
const effect = effectRaw === 'deny' || effectRaw === 'approve' ? effectRaw : 'allow';
|
|
32
|
+
return { match: match.trim(), effect };
|
|
33
|
+
}).filter((rule) => rule.match);
|
|
34
|
+
}
|
|
35
|
+
function parseSandbox(args) {
|
|
36
|
+
return {
|
|
37
|
+
filesystemRoots: splitCsv(valuesFor(args, '--fs-root')),
|
|
38
|
+
blockedPaths: splitCsv(valuesFor(args, '--block-path')),
|
|
39
|
+
allowedDomains: splitCsv(valuesFor(args, '--allow-domain')),
|
|
40
|
+
blockedDomains: splitCsv(valuesFor(args, '--block-domain')),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export async function cmdProfile(args, json) {
|
|
44
|
+
const sub = args[1] || 'list';
|
|
45
|
+
if (sub === 'create') {
|
|
46
|
+
const name = args[2];
|
|
47
|
+
if (!name) {
|
|
48
|
+
if (json)
|
|
49
|
+
printJson({ ok: false, error: 'Missing profile name. Next: hoolix profile create codex --include github,filesystem --approval writes.' });
|
|
50
|
+
else
|
|
51
|
+
logger.error('Usage: hoolix profile create <name> --include github,filesystem --approval writes');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const profile = await createProfile({
|
|
56
|
+
name,
|
|
57
|
+
includes: splitCsv(valuesFor(args, '--include')),
|
|
58
|
+
gateways: splitCsv(valuesFor(args, '--gateway')),
|
|
59
|
+
approvalMode: parseApproval(valueFor(args, '--approval')),
|
|
60
|
+
sandbox: parseSandbox(args),
|
|
61
|
+
});
|
|
62
|
+
const rules = parseRules(valuesFor(args, '--rule'));
|
|
63
|
+
const saved = rules.length > 0 ? await saveProfile({ ...profile, policy: { ...profile.policy, rules: [...profile.policy.rules, ...rules] } }) : profile;
|
|
64
|
+
if (json) {
|
|
65
|
+
printJson({ ok: true, profile: maskProfile(saved), next: [`hoolix gateway connect <gateway> --client codex --profile ${saved.slug}`] });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
printTitle('Profile created', `"${saved.name}" will identify one MCP client or agent.`);
|
|
69
|
+
printDetails([
|
|
70
|
+
['Slug', saved.slug],
|
|
71
|
+
['Allowed tools', saved.allowedTools.join(', ')],
|
|
72
|
+
['Gateways', saved.allowedGateways.length ? saved.allowedGateways.join(', ') : 'any'],
|
|
73
|
+
['Approval', saved.approvalMode],
|
|
74
|
+
['Rules', String(saved.policy.rules.length)],
|
|
75
|
+
]);
|
|
76
|
+
console.log('');
|
|
77
|
+
printSection('Next steps');
|
|
78
|
+
printCommand(`hoolix gateway connect my-tools --client codex --profile ${saved.slug}`);
|
|
79
|
+
printCommand('hoolix approvals list');
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
83
|
+
if (json)
|
|
84
|
+
printJson({ ok: false, error: message });
|
|
85
|
+
else
|
|
86
|
+
logger.error(message);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (sub === 'list') {
|
|
92
|
+
const profiles = await listProfiles();
|
|
93
|
+
if (json) {
|
|
94
|
+
printJson(profiles.map(maskProfile));
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (profiles.length === 0) {
|
|
98
|
+
printTitle('Profiles', 'No client profiles yet.');
|
|
99
|
+
printCommand('hoolix profile create codex --include github,filesystem --approval writes');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
printTitle('Profiles', `${profiles.length} profile${profiles.length === 1 ? '' : 's'}`);
|
|
103
|
+
printTable(profiles.map((profile) => ({
|
|
104
|
+
Name: profile.name,
|
|
105
|
+
Slug: profile.slug,
|
|
106
|
+
Approval: profile.approvalMode,
|
|
107
|
+
Tools: profile.allowedTools.join(', '),
|
|
108
|
+
Gateways: profile.allowedGateways.length ? profile.allowedGateways.join(', ') : 'any',
|
|
109
|
+
Rules: String(profile.policy.rules.length),
|
|
110
|
+
})));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (sub === 'edit') {
|
|
114
|
+
const slug = args[2];
|
|
115
|
+
if (!slug) {
|
|
116
|
+
if (json)
|
|
117
|
+
printJson({ ok: false, error: 'Missing profile name. Next: hoolix profile edit codex --approval always.' });
|
|
118
|
+
else
|
|
119
|
+
logger.error('Usage: hoolix profile edit <name> [--include ...] [--approval ...] [--rule pattern=effect]');
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
const current = await getProfile(slug);
|
|
123
|
+
const includes = splitCsv(valuesFor(args, '--include'));
|
|
124
|
+
const gateways = splitCsv(valuesFor(args, '--gateway'));
|
|
125
|
+
const rules = parseRules(valuesFor(args, '--rule'));
|
|
126
|
+
const approval = valueFor(args, '--approval');
|
|
127
|
+
const sandbox = parseSandbox(args);
|
|
128
|
+
const updated = await saveProfile({
|
|
129
|
+
...current,
|
|
130
|
+
allowedTools: includes.length ? expandIncludes(includes) : current.allowedTools,
|
|
131
|
+
allowedGateways: gateways.length ? gateways : current.allowedGateways,
|
|
132
|
+
approvalMode: approval ? parseApproval(approval) : current.approvalMode,
|
|
133
|
+
policy: rules.length ? { ...current.policy, rules: [...current.policy.rules, ...rules] } : current.policy,
|
|
134
|
+
sandbox: {
|
|
135
|
+
filesystemRoots: sandbox.filesystemRoots?.length ? sandbox.filesystemRoots : current.sandbox.filesystemRoots,
|
|
136
|
+
blockedPaths: sandbox.blockedPaths?.length ? sandbox.blockedPaths : current.sandbox.blockedPaths,
|
|
137
|
+
allowedDomains: sandbox.allowedDomains?.length ? sandbox.allowedDomains : current.sandbox.allowedDomains,
|
|
138
|
+
blockedDomains: sandbox.blockedDomains?.length ? sandbox.blockedDomains : current.sandbox.blockedDomains,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
if (json)
|
|
142
|
+
printJson({ ok: true, profile: maskProfile(updated) });
|
|
143
|
+
else
|
|
144
|
+
logger.success(`Updated profile ${updated.slug}`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (sub === 'delete') {
|
|
148
|
+
const slug = args[2];
|
|
149
|
+
if (!slug) {
|
|
150
|
+
if (json)
|
|
151
|
+
printJson({ ok: false, error: 'Missing profile name. Next: hoolix profile delete codex.' });
|
|
152
|
+
else
|
|
153
|
+
logger.error('Usage: hoolix profile delete <name>');
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
await deleteProfile(slug);
|
|
157
|
+
if (json)
|
|
158
|
+
printJson({ ok: true, profile: slug, deleted: true });
|
|
159
|
+
else
|
|
160
|
+
logger.success(`Deleted profile ${slug}`);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (json)
|
|
164
|
+
printJson({ ok: false, error: `Unknown profile command "${sub}". Next: use create, list, edit, or delete.` });
|
|
165
|
+
else
|
|
166
|
+
logger.error(`Unknown profile command "${sub}". Next: run hoolix profile list.`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/commands/profile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ApprovalStatusSchema: z.ZodEnum<["pending", "approved", "denied", "consumed"]>;
|
|
3
|
+
export declare const ApprovalRecordSchema: z.ZodObject<{
|
|
4
|
+
id: z.ZodString;
|
|
5
|
+
status: z.ZodEnum<["pending", "approved", "denied", "consumed"]>;
|
|
6
|
+
gateway: z.ZodString;
|
|
7
|
+
profile: z.ZodString;
|
|
8
|
+
toolName: z.ZodString;
|
|
9
|
+
backend: z.ZodOptional<z.ZodString>;
|
|
10
|
+
argumentsPreview: z.ZodString;
|
|
11
|
+
argumentsHash: z.ZodString;
|
|
12
|
+
createdAt: z.ZodString;
|
|
13
|
+
decidedAt: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, "strip", z.ZodTypeAny, {
|
|
15
|
+
status: "pending" | "approved" | "denied" | "consumed";
|
|
16
|
+
id: string;
|
|
17
|
+
createdAt: string;
|
|
18
|
+
toolName: string;
|
|
19
|
+
profile: string;
|
|
20
|
+
gateway: string;
|
|
21
|
+
argumentsPreview: string;
|
|
22
|
+
argumentsHash: string;
|
|
23
|
+
backend?: string | undefined;
|
|
24
|
+
decidedAt?: string | undefined;
|
|
25
|
+
}, {
|
|
26
|
+
status: "pending" | "approved" | "denied" | "consumed";
|
|
27
|
+
id: string;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
toolName: string;
|
|
30
|
+
profile: string;
|
|
31
|
+
gateway: string;
|
|
32
|
+
argumentsPreview: string;
|
|
33
|
+
argumentsHash: string;
|
|
34
|
+
backend?: string | undefined;
|
|
35
|
+
decidedAt?: string | undefined;
|
|
36
|
+
}>;
|
|
37
|
+
export type ApprovalRecord = z.infer<typeof ApprovalRecordSchema>;
|
|
38
|
+
export interface ApprovalStore {
|
|
39
|
+
version: string;
|
|
40
|
+
approvals: ApprovalRecord[];
|
|
41
|
+
}
|
|
42
|
+
export declare function listApprovals(status?: ApprovalRecord['status']): Promise<ApprovalRecord[]>;
|
|
43
|
+
export declare function listPendingApprovals(): Promise<ApprovalRecord[]>;
|
|
44
|
+
export declare function queueApproval(input: {
|
|
45
|
+
gateway: string;
|
|
46
|
+
profile: string;
|
|
47
|
+
toolName: string;
|
|
48
|
+
backend?: string;
|
|
49
|
+
argumentsPreview: string;
|
|
50
|
+
argumentsHash: string;
|
|
51
|
+
}): Promise<ApprovalRecord>;
|
|
52
|
+
export declare function decideApproval(id: string, status: 'approved' | 'denied'): Promise<ApprovalRecord>;
|
|
53
|
+
export declare function consumeMatchingApproval(input: {
|
|
54
|
+
gateway: string;
|
|
55
|
+
profile: string;
|
|
56
|
+
toolName: string;
|
|
57
|
+
argumentsHash: string;
|
|
58
|
+
}): Promise<ApprovalRecord | null>;
|
|
59
|
+
export declare function findDeniedMatchingApproval(input: {
|
|
60
|
+
gateway: string;
|
|
61
|
+
profile: string;
|
|
62
|
+
toolName: string;
|
|
63
|
+
argumentsHash: string;
|
|
64
|
+
}): Promise<ApprovalRecord | null>;
|
|
65
|
+
export declare function previewArgs(value: unknown): string;
|
|
66
|
+
export declare function hashArgs(value: unknown): Promise<string>;
|
|
67
|
+
//# sourceMappingURL=approvals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../../src/core/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,oBAAoB,0DAAwD,CAAC;AAE1F,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAW/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,cAAc,EAAE,CAAC;CAC7B;AAmBD,wBAAsB,aAAa,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAIhG;AAED,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC,CAEtE;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,cAAc,CAAC,CAyB1B;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,CAAC,cAAc,CAAC,CAQvG;AAED,wBAAsB,uBAAuB,CAAC,KAAK,EAAE;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAcjC;AAED,wBAAsB,0BAA0B,CAAC,KAAK,EAAE;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CASjC;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGlD;AAED,wBAAsB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import { getApprovalsPath, ensureDirectories } from './paths.js';
|
|
4
|
+
export const ApprovalStatusSchema = z.enum(['pending', 'approved', 'denied', 'consumed']);
|
|
5
|
+
export const ApprovalRecordSchema = z.object({
|
|
6
|
+
id: z.string(),
|
|
7
|
+
status: ApprovalStatusSchema,
|
|
8
|
+
gateway: z.string(),
|
|
9
|
+
profile: z.string(),
|
|
10
|
+
toolName: z.string(),
|
|
11
|
+
backend: z.string().optional(),
|
|
12
|
+
argumentsPreview: z.string(),
|
|
13
|
+
argumentsHash: z.string(),
|
|
14
|
+
createdAt: z.string().datetime(),
|
|
15
|
+
decidedAt: z.string().datetime().optional(),
|
|
16
|
+
});
|
|
17
|
+
async function loadStore() {
|
|
18
|
+
await ensureDirectories();
|
|
19
|
+
const path = getApprovalsPath();
|
|
20
|
+
if (!(await fs.pathExists(path))) {
|
|
21
|
+
const fresh = { version: '1.0.0', approvals: [] };
|
|
22
|
+
await fs.writeJson(path, fresh, { spaces: 2 });
|
|
23
|
+
return fresh;
|
|
24
|
+
}
|
|
25
|
+
const raw = await fs.readJson(path);
|
|
26
|
+
const approvals = z.array(ApprovalRecordSchema).parse(raw.approvals ?? []);
|
|
27
|
+
return { version: String(raw.version ?? '1.0.0'), approvals };
|
|
28
|
+
}
|
|
29
|
+
async function saveStore(store) {
|
|
30
|
+
await fs.writeJson(getApprovalsPath(), store, { spaces: 2 });
|
|
31
|
+
}
|
|
32
|
+
export async function listApprovals(status) {
|
|
33
|
+
const store = await loadStore();
|
|
34
|
+
const approvals = status ? store.approvals.filter((approval) => approval.status === status) : store.approvals;
|
|
35
|
+
return approvals.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
|
|
36
|
+
}
|
|
37
|
+
export async function listPendingApprovals() {
|
|
38
|
+
return listApprovals('pending');
|
|
39
|
+
}
|
|
40
|
+
export async function queueApproval(input) {
|
|
41
|
+
const store = await loadStore();
|
|
42
|
+
const existing = store.approvals.find((approval) => approval.status === 'pending' &&
|
|
43
|
+
approval.gateway === input.gateway &&
|
|
44
|
+
approval.profile === input.profile &&
|
|
45
|
+
approval.toolName === input.toolName &&
|
|
46
|
+
approval.argumentsHash === input.argumentsHash);
|
|
47
|
+
if (existing)
|
|
48
|
+
return existing;
|
|
49
|
+
const record = {
|
|
50
|
+
id: `appr_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`,
|
|
51
|
+
status: 'pending',
|
|
52
|
+
gateway: input.gateway,
|
|
53
|
+
profile: input.profile,
|
|
54
|
+
toolName: input.toolName,
|
|
55
|
+
backend: input.backend,
|
|
56
|
+
argumentsPreview: input.argumentsPreview,
|
|
57
|
+
argumentsHash: input.argumentsHash,
|
|
58
|
+
createdAt: new Date().toISOString(),
|
|
59
|
+
};
|
|
60
|
+
store.approvals.push(record);
|
|
61
|
+
await saveStore(store);
|
|
62
|
+
return record;
|
|
63
|
+
}
|
|
64
|
+
export async function decideApproval(id, status) {
|
|
65
|
+
const store = await loadStore();
|
|
66
|
+
const record = store.approvals.find((approval) => approval.id === id);
|
|
67
|
+
if (!record)
|
|
68
|
+
throw new Error(`Approval "${id}" not found. Next: run hoolix approvals list.`);
|
|
69
|
+
record.status = status;
|
|
70
|
+
record.decidedAt = new Date().toISOString();
|
|
71
|
+
await saveStore(store);
|
|
72
|
+
return record;
|
|
73
|
+
}
|
|
74
|
+
export async function consumeMatchingApproval(input) {
|
|
75
|
+
const store = await loadStore();
|
|
76
|
+
const record = store.approvals.find((approval) => approval.status === 'approved' &&
|
|
77
|
+
approval.gateway === input.gateway &&
|
|
78
|
+
approval.profile === input.profile &&
|
|
79
|
+
approval.toolName === input.toolName &&
|
|
80
|
+
approval.argumentsHash === input.argumentsHash);
|
|
81
|
+
if (!record)
|
|
82
|
+
return null;
|
|
83
|
+
record.status = 'consumed';
|
|
84
|
+
record.decidedAt = new Date().toISOString();
|
|
85
|
+
await saveStore(store);
|
|
86
|
+
return record;
|
|
87
|
+
}
|
|
88
|
+
export async function findDeniedMatchingApproval(input) {
|
|
89
|
+
const store = await loadStore();
|
|
90
|
+
return store.approvals.find((approval) => approval.status === 'denied' &&
|
|
91
|
+
approval.gateway === input.gateway &&
|
|
92
|
+
approval.profile === input.profile &&
|
|
93
|
+
approval.toolName === input.toolName &&
|
|
94
|
+
approval.argumentsHash === input.argumentsHash) ?? null;
|
|
95
|
+
}
|
|
96
|
+
export function previewArgs(value) {
|
|
97
|
+
const json = JSON.stringify(value ?? {});
|
|
98
|
+
return json.length > 500 ? `${json.slice(0, 500)}...` : json;
|
|
99
|
+
}
|
|
100
|
+
export async function hashArgs(value) {
|
|
101
|
+
const crypto = await import('node:crypto');
|
|
102
|
+
return crypto.createHash('sha256').update(JSON.stringify(value ?? {})).digest('hex');
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/core/approvals.ts"],"names":[],"mappings":"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"}
|
package/dist/core/paths.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export interface AppPaths {
|
|
|
3
3
|
config: string;
|
|
4
4
|
servers: string;
|
|
5
5
|
gateways: string;
|
|
6
|
+
profiles: string;
|
|
6
7
|
cache: string;
|
|
7
8
|
}
|
|
8
9
|
export declare function getPaths(): AppPaths;
|
|
@@ -17,4 +18,7 @@ export declare function getGatewayDir(name: string): string;
|
|
|
17
18
|
export declare function getGatewayConfigPath(name: string): string;
|
|
18
19
|
export declare function getGatewayRuntimePath(name: string): string;
|
|
19
20
|
export declare function getGatewayDataDir(name: string): string;
|
|
21
|
+
export declare function getProfileDir(name: string): string;
|
|
22
|
+
export declare function getProfileConfigPath(name: string): string;
|
|
23
|
+
export declare function getApprovalsPath(): string;
|
|
20
24
|
//# sourceMappingURL=paths.d.ts.map
|
package/dist/core/paths.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,QAAQ,IAAI,QAAQ,
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAID,wBAAgB,QAAQ,IAAI,QAAQ,CAyBnC;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,QAAQ,CAAC,CAQ3D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
|
package/dist/core/paths.js
CHANGED
|
@@ -14,6 +14,7 @@ export function getPaths() {
|
|
|
14
14
|
const data = process.env[DATA_DIR_ENV] || paths.data;
|
|
15
15
|
const servers = path.join(data, 'servers');
|
|
16
16
|
const gateways = path.join(data, 'gateways');
|
|
17
|
+
const profiles = path.join(data, 'profiles');
|
|
17
18
|
const config = path.join(data, 'config.json');
|
|
18
19
|
const cache = path.join(data, 'cache');
|
|
19
20
|
cachedPaths = {
|
|
@@ -21,6 +22,7 @@ export function getPaths() {
|
|
|
21
22
|
config,
|
|
22
23
|
servers,
|
|
23
24
|
gateways,
|
|
25
|
+
profiles,
|
|
24
26
|
cache,
|
|
25
27
|
};
|
|
26
28
|
return cachedPaths;
|
|
@@ -33,6 +35,7 @@ export async function ensureDirectories() {
|
|
|
33
35
|
await fs.ensureDir(p.data);
|
|
34
36
|
await fs.ensureDir(p.servers);
|
|
35
37
|
await fs.ensureDir(p.gateways);
|
|
38
|
+
await fs.ensureDir(p.profiles);
|
|
36
39
|
await fs.ensureDir(p.cache);
|
|
37
40
|
return p;
|
|
38
41
|
}
|
|
@@ -63,4 +66,13 @@ export function getGatewayRuntimePath(name) {
|
|
|
63
66
|
export function getGatewayDataDir(name) {
|
|
64
67
|
return path.join(getGatewayDir(name), 'data');
|
|
65
68
|
}
|
|
69
|
+
export function getProfileDir(name) {
|
|
70
|
+
return path.join(getPaths().profiles, name);
|
|
71
|
+
}
|
|
72
|
+
export function getProfileConfigPath(name) {
|
|
73
|
+
return path.join(getProfileDir(name), 'profile.json');
|
|
74
|
+
}
|
|
75
|
+
export function getApprovalsPath() {
|
|
76
|
+
return path.join(getPaths().data, 'approvals.json');
|
|
77
|
+
}
|
|
66
78
|
//# sourceMappingURL=paths.js.map
|
package/dist/core/paths.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAE1B,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAC1B,MAAM,YAAY,GAAG,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Profile } from './profiles.js';
|
|
2
|
+
export type PolicyDecision = {
|
|
3
|
+
effect: 'allow';
|
|
4
|
+
reason?: string;
|
|
5
|
+
} | {
|
|
6
|
+
effect: 'deny';
|
|
7
|
+
reason: string;
|
|
8
|
+
} | {
|
|
9
|
+
effect: 'approve';
|
|
10
|
+
reason: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function matchesPattern(pattern: string, value: string): boolean;
|
|
13
|
+
export declare function isWriteTool(toolName: string): boolean;
|
|
14
|
+
export declare function evaluatePolicy(input: {
|
|
15
|
+
profile: Profile | null;
|
|
16
|
+
gateway: string;
|
|
17
|
+
toolName: string;
|
|
18
|
+
args: unknown;
|
|
19
|
+
}): PolicyDecision;
|
|
20
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,MAAM,cAAc,GACtB;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAO1C,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtE;AAMD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErD;AAsDD,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACf,GAAG,cAAc,CA0BjB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
function wildcardToRegex(pattern) {
|
|
3
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
|
|
4
|
+
return new RegExp(`^${escaped}$`, 'i');
|
|
5
|
+
}
|
|
6
|
+
export function matchesPattern(pattern, value) {
|
|
7
|
+
return wildcardToRegex(pattern).test(value);
|
|
8
|
+
}
|
|
9
|
+
function anyPatternMatches(patterns, value) {
|
|
10
|
+
return patterns.some((pattern) => matchesPattern(pattern, value));
|
|
11
|
+
}
|
|
12
|
+
export function isWriteTool(toolName) {
|
|
13
|
+
return /(^|[._-])(create|update|write|delete|remove|send|post|push|merge|mutate|insert|edit|apply)([._-]|$)/i.test(toolName);
|
|
14
|
+
}
|
|
15
|
+
function collectStrings(value, out = []) {
|
|
16
|
+
if (typeof value === 'string')
|
|
17
|
+
out.push(value);
|
|
18
|
+
else if (Array.isArray(value))
|
|
19
|
+
value.forEach((item) => collectStrings(item, out));
|
|
20
|
+
else if (value && typeof value === 'object')
|
|
21
|
+
Object.values(value).forEach((item) => collectStrings(item, out));
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
function normalizeFsPath(value) {
|
|
25
|
+
return path.resolve(value);
|
|
26
|
+
}
|
|
27
|
+
function isSubPath(candidate, root) {
|
|
28
|
+
const rel = path.relative(normalizeFsPath(root), normalizeFsPath(candidate));
|
|
29
|
+
return rel === '' || (!!rel && !rel.startsWith('..') && !path.isAbsolute(rel));
|
|
30
|
+
}
|
|
31
|
+
function sandboxDecision(profile, toolName, args) {
|
|
32
|
+
const strings = collectStrings(args);
|
|
33
|
+
const sandbox = profile.sandbox;
|
|
34
|
+
if (/filesystem|file|path/i.test(toolName)) {
|
|
35
|
+
for (const blocked of sandbox.blockedPaths) {
|
|
36
|
+
if (strings.some((candidate) => candidate.includes(blocked) || isSubPath(candidate, blocked))) {
|
|
37
|
+
return { effect: 'deny', reason: `blocked path matched "${blocked}"` };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (sandbox.filesystemRoots.length > 0) {
|
|
41
|
+
const pathLike = strings.filter((candidate) => /[\\/]/.test(candidate) || /^[a-zA-Z]:/.test(candidate));
|
|
42
|
+
for (const candidate of pathLike) {
|
|
43
|
+
if (!sandbox.filesystemRoots.some((root) => isSubPath(candidate, root))) {
|
|
44
|
+
return { effect: 'deny', reason: `path outside allowed filesystem roots: ${candidate}` };
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const urls = strings
|
|
50
|
+
.map((candidate) => {
|
|
51
|
+
try {
|
|
52
|
+
return new URL(candidate);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
.filter((url) => !!url);
|
|
59
|
+
for (const url of urls) {
|
|
60
|
+
if (sandbox.blockedDomains.some((domain) => url.hostname === domain || url.hostname.endsWith(`.${domain}`))) {
|
|
61
|
+
return { effect: 'deny', reason: `blocked domain matched "${url.hostname}"` };
|
|
62
|
+
}
|
|
63
|
+
if (sandbox.allowedDomains.length > 0 && !sandbox.allowedDomains.some((domain) => url.hostname === domain || url.hostname.endsWith(`.${domain}`))) {
|
|
64
|
+
return { effect: 'deny', reason: `domain outside allowed list: ${url.hostname}` };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
export function evaluatePolicy(input) {
|
|
70
|
+
const { profile, gateway, toolName, args } = input;
|
|
71
|
+
if (!profile)
|
|
72
|
+
return { effect: 'allow', reason: 'no profile' };
|
|
73
|
+
if (profile.allowedGateways.length > 0 && !profile.allowedGateways.includes(gateway)) {
|
|
74
|
+
return { effect: 'deny', reason: `profile "${profile.slug}" cannot access gateway "${gateway}"` };
|
|
75
|
+
}
|
|
76
|
+
if (profile.allowedTools.length > 0 && !anyPatternMatches(profile.allowedTools, toolName)) {
|
|
77
|
+
return { effect: 'deny', reason: `profile "${profile.slug}" cannot access tool "${toolName}"` };
|
|
78
|
+
}
|
|
79
|
+
const sandbox = sandboxDecision(profile, toolName, args);
|
|
80
|
+
if (sandbox)
|
|
81
|
+
return sandbox;
|
|
82
|
+
for (const rule of profile.policy.rules) {
|
|
83
|
+
if (matchesPattern(rule.match, toolName)) {
|
|
84
|
+
return { effect: rule.effect, reason: `matched rule ${rule.match}` };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (profile.approvalMode === 'always')
|
|
88
|
+
return { effect: 'approve', reason: 'profile requires approval for every tool' };
|
|
89
|
+
if (profile.approvalMode === 'read-only' && isWriteTool(toolName))
|
|
90
|
+
return { effect: 'deny', reason: 'profile is read-only' };
|
|
91
|
+
if (profile.approvalMode === 'writes' && isWriteTool(toolName))
|
|
92
|
+
return { effect: 'approve', reason: 'profile requires approval for writes' };
|
|
93
|
+
return { effect: profile.policy.defaultEffect, reason: 'default policy' };
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/core/policy.ts"],"names":[],"mappings":"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"}
|