hoolix 0.0.2 → 0.0.4
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/bin/hoolix.js +13 -3
- 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/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +75 -0
- package/dist/web/assets.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +22 -0
- package/dist/web/server.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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"}
|