@pennyfarthing/cyclist 9.3.0 → 10.0.0
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/dist/api/hook-request.d.ts +11 -0
- package/dist/api/hook-request.d.ts.map +1 -1
- package/dist/api/hook-request.js +126 -28
- package/dist/api/hook-request.js.map +1 -1
- package/dist/api/hotspots.d.ts +3 -0
- package/dist/api/hotspots.d.ts.map +1 -0
- package/dist/api/hotspots.js +54 -0
- package/dist/api/hotspots.js.map +1 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/permissions.d.ts +16 -0
- package/dist/api/permissions.d.ts.map +1 -0
- package/dist/api/permissions.js +67 -0
- package/dist/api/permissions.js.map +1 -0
- package/dist/api/settings.d.ts +1 -1
- package/dist/api/settings.d.ts.map +1 -1
- package/dist/api/settings.js +44 -17
- package/dist/api/settings.js.map +1 -1
- package/dist/api/theme-agents.d.ts +4 -0
- package/dist/api/theme-agents.d.ts.map +1 -1
- package/dist/api/theme-agents.js +3 -0
- package/dist/api/theme-agents.js.map +1 -1
- package/dist/approval-gate.d.ts +3 -75
- package/dist/approval-gate.d.ts.map +1 -1
- package/dist/approval-gate.js +4 -121
- package/dist/approval-gate.js.map +1 -1
- package/dist/hooks/cyclist-pretooluse-hook.d.ts +60 -0
- package/dist/hooks/cyclist-pretooluse-hook.d.ts.map +1 -0
- package/dist/hooks/cyclist-pretooluse-hook.js +57 -0
- package/dist/hooks/cyclist-pretooluse-hook.js.map +1 -0
- package/dist/hooks/pretooluse-hook.d.ts +89 -0
- package/dist/hooks/pretooluse-hook.d.ts.map +1 -0
- package/dist/hooks/pretooluse-hook.js +235 -0
- package/dist/hooks/pretooluse-hook.js.map +1 -0
- package/dist/main.d.ts +1 -134
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +42 -373
- package/dist/main.js.map +1 -1
- package/dist/menu-builder.d.ts +7 -1
- package/dist/menu-builder.d.ts.map +1 -1
- package/dist/menu-builder.js +36 -1
- package/dist/menu-builder.js.map +1 -1
- package/dist/otlp-receiver.d.ts.map +1 -1
- package/dist/otlp-receiver.js +6 -0
- package/dist/otlp-receiver.js.map +1 -1
- package/dist/public/css/react.css +1 -1
- package/dist/public/js/react/react.js +42 -42
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +16 -3
- package/dist/server.js.map +1 -1
- package/dist/settings-store.d.ts +3 -1
- package/dist/settings-store.d.ts.map +1 -1
- package/dist/settings-store.js +18 -9
- package/dist/settings-store.js.map +1 -1
- package/dist/story-parser.d.ts +17 -0
- package/dist/story-parser.d.ts.map +1 -1
- package/dist/story-parser.js +183 -13
- package/dist/story-parser.js.map +1 -1
- package/dist/websocket.d.ts +1 -0
- package/dist/websocket.d.ts.map +1 -1
- package/dist/websocket.js +48 -5
- package/dist/websocket.js.map +1 -1
- package/dist/workflow-presets.d.ts +72 -0
- package/dist/workflow-presets.d.ts.map +1 -0
- package/dist/workflow-presets.js +93 -0
- package/dist/workflow-presets.js.map +1 -0
- package/package.json +2 -2
- package/src/public/App.tsx +61 -1
- package/src/public/components/ApprovalModal/index.tsx +31 -1
- package/src/public/components/ControlBar.tsx +19 -20
- package/src/public/components/DockviewWorkspace.tsx +39 -5
- package/src/public/components/FontPicker/index.tsx +118 -33
- package/src/public/components/FullFileTree.tsx +223 -0
- package/src/public/components/Message.tsx +89 -11
- package/src/public/components/MessageView.tsx +206 -93
- package/src/public/components/PersonaHeader.tsx +47 -15
- package/src/public/components/SubagentSpan.tsx +15 -8
- package/src/public/components/panels/BackgroundPanel.tsx +1 -1
- package/src/public/components/panels/ChangedPanel.tsx +30 -44
- package/src/public/components/panels/HotspotsPanel.tsx +365 -0
- package/src/public/components/panels/MessagePanel.tsx +79 -5
- package/src/public/components/panels/SettingsPanel.tsx +3 -28
- package/src/public/components/panels/WorkflowPanel.tsx +108 -13
- package/src/public/components/panels/index.ts +1 -0
- package/src/public/contexts/ClaudeContext.tsx +16 -1
- package/src/public/css/theme-system.css +46 -38
- package/src/public/hooks/useColorScheme.ts +27 -0
- package/src/public/hooks/useFileBrowser.ts +71 -0
- package/src/public/hooks/useHotspots.ts +113 -0
- package/src/public/hooks/usePlanModeExit.ts +105 -0
- package/src/public/hooks/useStory.ts +12 -3
- package/src/public/images/cyclist-dark.png +0 -0
- package/src/public/images/cyclist-light.png +0 -0
- package/src/public/styles/dockview-theme.css +31 -33
- package/src/public/styles/tailwind.css +417 -58
- package/src/public/types/message.ts +6 -1
- package/src/public/utils/markdown.ts +2 -2
- package/src/public/utils/slash-commands.ts +1 -1
- package/src/public/utils/toolStackGrouper.ts +5 -6
|
@@ -16,6 +16,16 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { Router } from 'express';
|
|
18
18
|
import { WebSocket } from 'ws';
|
|
19
|
+
export type HookSeverity = 'safe' | 'normal' | 'destructive';
|
|
20
|
+
interface SeverityResult {
|
|
21
|
+
severity: HookSeverity;
|
|
22
|
+
warning?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Classify the severity of a hook request server-side.
|
|
26
|
+
* Combines tool-name classification with dangerous-path detection.
|
|
27
|
+
*/
|
|
28
|
+
export declare function classifyHookSeverity(toolName: string, input: Record<string, unknown>): SeverityResult;
|
|
19
29
|
export declare function getHookClients(): Set<WebSocket>;
|
|
20
30
|
export declare function addHookClient(ws: WebSocket): void;
|
|
21
31
|
/**
|
|
@@ -27,4 +37,5 @@ export declare function resolveApproval(toolId: string, approved: boolean, data?
|
|
|
27
37
|
*/
|
|
28
38
|
export declare function handleHookWebSocketMessage(ws: WebSocket, message: string): void;
|
|
29
39
|
export declare function createHookRequestRouter(): Router;
|
|
40
|
+
export {};
|
|
30
41
|
//# sourceMappingURL=hook-request.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-request.d.ts","sourceRoot":"","sources":["../../src/api/hook-request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"hook-request.d.ts","sourceRoot":"","sources":["../../src/api/hook-request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AA2E/B,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,aAAa,CAAC;AAE7D,UAAU,cAAc;IACtB,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,cAAc,CAkDhB;AAMD,wBAAgB,cAAc,IAAI,GAAG,CAAC,SAAS,CAAC,CAE/C;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,GAAG,IAAI,CAGjD;AA+BD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,EACjB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAcT;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CA6B/E;AAwFD,wBAAgB,uBAAuB,IAAI,MAAM,CAkBhD"}
|
package/dist/api/hook-request.js
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
import { Router } from 'express';
|
|
18
18
|
import { WebSocket } from 'ws';
|
|
19
|
+
import { checkGrant, isAllowlisted, addGrant } from '../settings-store.js';
|
|
20
|
+
import { isDangerousPath, getPathCategory, extractBashTargetPaths } from '../dangerous-path.js';
|
|
19
21
|
// =============================================================================
|
|
20
22
|
// State
|
|
21
23
|
// =============================================================================
|
|
@@ -26,24 +28,90 @@ const hookClients = new Set();
|
|
|
26
28
|
// Approval timeout (2 minutes)
|
|
27
29
|
const APPROVAL_TIMEOUT_MS = 120000;
|
|
28
30
|
// =============================================================================
|
|
29
|
-
//
|
|
31
|
+
// Scope Extraction (MSSCI-14321)
|
|
30
32
|
// =============================================================================
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Extract the scope identifier from tool input for grant matching.
|
|
35
|
+
* Modeled after getToolScope() in approval-gate.ts.
|
|
36
|
+
*/
|
|
37
|
+
function extractToolScope(toolName, input) {
|
|
38
|
+
switch (toolName) {
|
|
39
|
+
case 'Bash':
|
|
40
|
+
return input.command || '';
|
|
41
|
+
case 'WebFetch':
|
|
42
|
+
return input.url || '';
|
|
43
|
+
case 'Edit':
|
|
44
|
+
case 'Write':
|
|
45
|
+
case 'Read':
|
|
46
|
+
return input.file_path || '';
|
|
47
|
+
default:
|
|
48
|
+
return JSON.stringify(input);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const SAFE_TOOLS = new Set(['Read', 'Grep', 'Glob', 'WebSearch']);
|
|
52
|
+
const DESTRUCTIVE_BASH_PATTERNS = [
|
|
53
|
+
/rm\s+(-[rf]+\s+)*/,
|
|
54
|
+
/git\s+(reset\s+--hard|push\s+--force|clean\s+-[fd])/,
|
|
55
|
+
/drop\s+database/i,
|
|
56
|
+
/truncate\s+table/i,
|
|
44
57
|
];
|
|
45
|
-
|
|
46
|
-
|
|
58
|
+
const SAFE_BASH_PATTERNS = [
|
|
59
|
+
/^(ls|cat|head|tail|grep|find|pwd|echo|which|type|file|stat|wc|diff)\b/,
|
|
60
|
+
/^git\s+(status|log|diff|show|branch|remote)\b/,
|
|
61
|
+
];
|
|
62
|
+
const CATEGORY_WARNINGS = {
|
|
63
|
+
secrets: 'Modifying sensitive secrets/credentials file',
|
|
64
|
+
git: 'Modifying git internals',
|
|
65
|
+
dependencies: 'Modifying dependency files',
|
|
66
|
+
system: 'Modifying system files',
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Classify the severity of a hook request server-side.
|
|
70
|
+
* Combines tool-name classification with dangerous-path detection.
|
|
71
|
+
*/
|
|
72
|
+
export function classifyHookSeverity(toolName, input) {
|
|
73
|
+
// Safe tools are always safe
|
|
74
|
+
if (SAFE_TOOLS.has(toolName)) {
|
|
75
|
+
return { severity: 'safe' };
|
|
76
|
+
}
|
|
77
|
+
// Check dangerous paths for Write/Edit
|
|
78
|
+
if (toolName === 'Write' || toolName === 'Edit') {
|
|
79
|
+
const filePath = input.file_path || '';
|
|
80
|
+
if (filePath && isDangerousPath(filePath)) {
|
|
81
|
+
const category = getPathCategory(filePath);
|
|
82
|
+
return {
|
|
83
|
+
severity: 'destructive',
|
|
84
|
+
warning: category ? CATEGORY_WARNINGS[category] : 'Modifying sensitive path',
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
return { severity: 'normal' };
|
|
88
|
+
}
|
|
89
|
+
// Bash command classification
|
|
90
|
+
if (toolName === 'Bash') {
|
|
91
|
+
const command = input.command || '';
|
|
92
|
+
// Check for destructive bash patterns
|
|
93
|
+
if (DESTRUCTIVE_BASH_PATTERNS.some(p => p.test(command))) {
|
|
94
|
+
return { severity: 'destructive', warning: 'Destructive command detected' };
|
|
95
|
+
}
|
|
96
|
+
// Check for bash redirecting to dangerous paths
|
|
97
|
+
const targetPaths = extractBashTargetPaths(command);
|
|
98
|
+
for (const targetPath of targetPaths) {
|
|
99
|
+
if (isDangerousPath(targetPath)) {
|
|
100
|
+
const category = getPathCategory(targetPath);
|
|
101
|
+
return {
|
|
102
|
+
severity: 'destructive',
|
|
103
|
+
warning: category ? CATEGORY_WARNINGS[category] : 'Redirecting to sensitive path',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// Check for safe bash patterns
|
|
108
|
+
if (SAFE_BASH_PATTERNS.some(p => p.test(command))) {
|
|
109
|
+
return { severity: 'safe' };
|
|
110
|
+
}
|
|
111
|
+
return { severity: 'normal' };
|
|
112
|
+
}
|
|
113
|
+
// Default: normal
|
|
114
|
+
return { severity: 'normal' };
|
|
47
115
|
}
|
|
48
116
|
// =============================================================================
|
|
49
117
|
// WebSocket Client Management
|
|
@@ -92,6 +160,24 @@ export function handleHookWebSocketMessage(ws, message) {
|
|
|
92
160
|
try {
|
|
93
161
|
const data = JSON.parse(message);
|
|
94
162
|
if (data.type === 'hook-response') {
|
|
163
|
+
// Store grant if user approved with a grantScope (MSSCI-14321 AC8)
|
|
164
|
+
if (data.approved && data.data?.grantScope) {
|
|
165
|
+
const pending = pendingApprovals.get(data.toolId);
|
|
166
|
+
const scope = pending
|
|
167
|
+
? extractToolScope(pending.toolName, pending.input)
|
|
168
|
+
: '';
|
|
169
|
+
const grant = {
|
|
170
|
+
tool: pending?.toolName || '',
|
|
171
|
+
scope,
|
|
172
|
+
grant_type: data.data.grantScope,
|
|
173
|
+
granted_at: new Date().toISOString(),
|
|
174
|
+
};
|
|
175
|
+
// Include agent from the original request if present
|
|
176
|
+
if (pending?.agent) {
|
|
177
|
+
grant.agent = pending.agent;
|
|
178
|
+
}
|
|
179
|
+
addGrant(grant);
|
|
180
|
+
}
|
|
95
181
|
resolveApproval(data.toolId, data.approved, data.data);
|
|
96
182
|
}
|
|
97
183
|
}
|
|
@@ -103,21 +189,27 @@ export function handleHookWebSocketMessage(ws, message) {
|
|
|
103
189
|
// Request Handler
|
|
104
190
|
// =============================================================================
|
|
105
191
|
async function handleHookRequest(req, res) {
|
|
106
|
-
const { toolName, toolId, input, sessionId: _sessionId, context } = req.body;
|
|
192
|
+
const { toolName, toolId, input, sessionId: _sessionId, agent, context } = req.body;
|
|
107
193
|
if (!toolName || !toolId) {
|
|
108
194
|
res.status(400).json({ error: 'Missing required fields: toolName, toolId' });
|
|
109
195
|
return;
|
|
110
196
|
}
|
|
111
|
-
// Check for auto-approval
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
197
|
+
// Check for auto-approval via grants (all tool types)
|
|
198
|
+
const scope = extractToolScope(toolName, input || {});
|
|
199
|
+
if (checkGrant(toolName, scope, agent)) {
|
|
200
|
+
res.json({
|
|
201
|
+
decision: 'allow',
|
|
202
|
+
reason: 'Granted by permission grant',
|
|
203
|
+
});
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
// Check Bash allowlist for backward compatibility
|
|
207
|
+
if (toolName === 'Bash' && isAllowlisted(scope)) {
|
|
208
|
+
res.json({
|
|
209
|
+
decision: 'allow',
|
|
210
|
+
reason: 'Command matches allowlist pattern',
|
|
211
|
+
});
|
|
212
|
+
return;
|
|
121
213
|
}
|
|
122
214
|
// No clients connected - fall through to Claude Code's built-in approval
|
|
123
215
|
if (hookClients.size === 0) {
|
|
@@ -133,6 +225,7 @@ async function handleHookRequest(req, res) {
|
|
|
133
225
|
resolve,
|
|
134
226
|
toolName,
|
|
135
227
|
input: input || {},
|
|
228
|
+
agent,
|
|
136
229
|
timestamp: Date.now(),
|
|
137
230
|
});
|
|
138
231
|
// Set timeout
|
|
@@ -146,12 +239,17 @@ async function handleHookRequest(req, res) {
|
|
|
146
239
|
}
|
|
147
240
|
}, APPROVAL_TIMEOUT_MS);
|
|
148
241
|
});
|
|
149
|
-
//
|
|
242
|
+
// Classify severity before broadcast (MSSCI-14323)
|
|
243
|
+
const { severity, warning } = classifyHookSeverity(toolName, input || {});
|
|
244
|
+
// Broadcast to clients (include context, severity, and agent for UI display)
|
|
150
245
|
broadcastHookRequest({
|
|
151
246
|
type: 'hook-request',
|
|
152
247
|
toolId,
|
|
153
248
|
toolName,
|
|
154
249
|
input: input || {},
|
|
250
|
+
severity,
|
|
251
|
+
warning,
|
|
252
|
+
agent,
|
|
155
253
|
context,
|
|
156
254
|
});
|
|
157
255
|
// Wait for response
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-request.js","sourceRoot":"","sources":["../../src/api/hook-request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"hook-request.js","sourceRoot":"","sources":["../../src/api/hook-request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotspots.d.ts","sourceRoot":"","sources":["../../src/api/hotspots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAKjC,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,MAAM,GAAG,MAAM,CAqDxE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { execFile } from 'child_process';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
// Create hotspots API router
|
|
5
|
+
export function createHotspotsRouter(getProjectDir) {
|
|
6
|
+
const router = Router();
|
|
7
|
+
// GET /api/hotspots?days=90&repo=pennyfarthing
|
|
8
|
+
router.get('/', (req, res) => {
|
|
9
|
+
const projectDir = getProjectDir();
|
|
10
|
+
const days = String(req.query.days || '90');
|
|
11
|
+
const repo = req.query.repo;
|
|
12
|
+
const args = [
|
|
13
|
+
'-m', 'pennyfarthing_scripts.hotspots',
|
|
14
|
+
'analyze',
|
|
15
|
+
'--format', 'json',
|
|
16
|
+
'--days', days,
|
|
17
|
+
];
|
|
18
|
+
if (repo) {
|
|
19
|
+
args.push('--repo', repo);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
args.push('--path', projectDir);
|
|
23
|
+
}
|
|
24
|
+
// Find python in the project's pennyfarthing dir
|
|
25
|
+
const pythonPath = join(projectDir, 'pennyfarthing');
|
|
26
|
+
execFile('python3', args, {
|
|
27
|
+
cwd: pythonPath,
|
|
28
|
+
env: { ...process.env, PYTHONPATH: pythonPath },
|
|
29
|
+
timeout: 30000,
|
|
30
|
+
}, (err, stdout, stderr) => {
|
|
31
|
+
if (err) {
|
|
32
|
+
console.error('[Hotspots] Analysis failed:', stderr || err.message);
|
|
33
|
+
res.status(500).json({
|
|
34
|
+
success: false,
|
|
35
|
+
error: stderr || err.message,
|
|
36
|
+
});
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const data = JSON.parse(stdout);
|
|
41
|
+
res.json(data);
|
|
42
|
+
}
|
|
43
|
+
catch (parseErr) {
|
|
44
|
+
console.error('[Hotspots] JSON parse failed:', parseErr);
|
|
45
|
+
res.status(500).json({
|
|
46
|
+
success: false,
|
|
47
|
+
error: 'Failed to parse hotspot analysis output',
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return router;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=hotspots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotspots.js","sourceRoot":"","sources":["../../src/api/hotspots.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,6BAA6B;AAC7B,MAAM,UAAU,oBAAoB,CAAC,aAA2B;IAC9D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,+CAA+C;IAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC3B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAA0B,CAAC;QAElD,MAAM,IAAI,GAAG;YACX,IAAI,EAAE,gCAAgC;YACtC,SAAS;YACT,UAAU,EAAE,MAAM;YAClB,QAAQ,EAAE,IAAI;SACf,CAAC;QAEF,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QAClC,CAAC;QAED,iDAAiD;QACjD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;QAErD,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE;YACxB,GAAG,EAAE,UAAU;YACf,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,UAAU,EAAE,UAAU,EAAE;YAC/C,OAAO,EAAE,KAAK;SACf,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACzB,IAAI,GAAG,EAAE,CAAC;gBACR,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,MAAM,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;gBACpE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC,OAAO;iBAC7B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;gBAChC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;YAAC,OAAO,QAAQ,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,QAAQ,CAAC,CAAC;gBACzD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;oBACnB,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,yCAAyC;iBACjD,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/api/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { createGitRouter, getGitInfo, getAllReposGitInfo, getGitInfoAsync, getAl
|
|
|
5
5
|
export type { GitInfo } from './git.js';
|
|
6
6
|
export { createOTLPRouter } from './otlp.js';
|
|
7
7
|
export { createStoryRouter } from './story.js';
|
|
8
|
+
export { createHotspotsRouter } from './hotspots.js';
|
|
8
9
|
export { createFileBrowserRouter } from './file-browser.js';
|
|
9
10
|
export { createTokenStatsRouter, broadcastTokenStats, getTokenStatsClients, initTokenStatsBroadcast } from './token-stats.js';
|
|
10
11
|
export { createContextRouter, getContextUsage } from './context.js';
|
|
@@ -24,4 +25,5 @@ export { createIdentityRouter } from './identity.js';
|
|
|
24
25
|
export type { IdentityInfo } from './identity.js';
|
|
25
26
|
export { createTodosRouter, setWebModeTodos, getWebModeTodos } from './todos.js';
|
|
26
27
|
export { createAuditLogRouter } from './audit-log.js';
|
|
28
|
+
export { createPermissionsRouter } from './permissions.js';
|
|
27
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACrH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC9H,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1D,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAEzJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAExI,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AACrH,YAAY,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC9H,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC1D,YAAY,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AAEzJ,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAExI,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/api/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { createPersonaRouter, broadcastPersona, getPersonaClients } from './pers
|
|
|
5
5
|
export { createGitRouter, getGitInfo, getAllReposGitInfo, getGitInfoAsync, getAllReposGitInfoAsync } from './git.js';
|
|
6
6
|
export { createOTLPRouter } from './otlp.js';
|
|
7
7
|
export { createStoryRouter } from './story.js';
|
|
8
|
+
export { createHotspotsRouter } from './hotspots.js';
|
|
8
9
|
export { createFileBrowserRouter } from './file-browser.js';
|
|
9
10
|
export { createTokenStatsRouter, broadcastTokenStats, getTokenStatsClients, initTokenStatsBroadcast } from './token-stats.js';
|
|
10
11
|
export { createContextRouter, getContextUsage } from './context.js';
|
|
@@ -29,4 +30,6 @@ export { createIdentityRouter } from './identity.js';
|
|
|
29
30
|
export { createTodosRouter, setWebModeTodos, getWebModeTodos } from './todos.js';
|
|
30
31
|
// Audit log API
|
|
31
32
|
export { createAuditLogRouter } from './audit-log.js';
|
|
33
|
+
// MSSCI-14325: Permissions API (grant management)
|
|
34
|
+
export { createPermissionsRouter } from './permissions.js';
|
|
32
35
|
//# sourceMappingURL=index.js.map
|
package/dist/api/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAErH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC9H,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,2FAA2F;AAC3F,6CAA6C;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,8BAA8B;AAC9B,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACzJ,kCAAkC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,gCAAgC;AAChC,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClE,yDAAyD;AACzD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AACxI,4CAA4C;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,kCAAkC;AAClC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACjF,gBAAgB;AAChB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AACrB,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5G,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,kBAAkB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAErH,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAC9H,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,2FAA2F;AAC3F,6CAA6C;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,8BAA8B;AAC9B,OAAO,EAAE,2BAA2B,EAAE,wBAAwB,EAAE,4BAA4B,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACzJ,kCAAkC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/C,gCAAgC;AAChC,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAClE,yDAAyD;AACzD,OAAO,EAAE,uBAAuB,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AACxI,4CAA4C;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,kCAAkC;AAClC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACjF,gBAAgB;AAChB,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AACtD,kDAAkD;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permissions API Router
|
|
3
|
+
*
|
|
4
|
+
* Bridges the /permissions skill to settings-store.ts grant management.
|
|
5
|
+
*
|
|
6
|
+
* Story: MSSCI-14325 - Connect /permissions skill to grant store
|
|
7
|
+
*
|
|
8
|
+
* Routes:
|
|
9
|
+
* - GET / List all active grants
|
|
10
|
+
* - POST /grant Add a permission grant
|
|
11
|
+
* - DELETE /revoke/:tool Revoke grants for a tool
|
|
12
|
+
* - GET /show/:tool Show grants for a specific tool
|
|
13
|
+
*/
|
|
14
|
+
import { Router } from 'express';
|
|
15
|
+
export declare function createPermissionsRouter(): Router;
|
|
16
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/api/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AAKpD,wBAAgB,uBAAuB,IAAI,MAAM,CAiEhD"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permissions API Router
|
|
3
|
+
*
|
|
4
|
+
* Bridges the /permissions skill to settings-store.ts grant management.
|
|
5
|
+
*
|
|
6
|
+
* Story: MSSCI-14325 - Connect /permissions skill to grant store
|
|
7
|
+
*
|
|
8
|
+
* Routes:
|
|
9
|
+
* - GET / List all active grants
|
|
10
|
+
* - POST /grant Add a permission grant
|
|
11
|
+
* - DELETE /revoke/:tool Revoke grants for a tool
|
|
12
|
+
* - GET /show/:tool Show grants for a specific tool
|
|
13
|
+
*/
|
|
14
|
+
import { Router } from 'express';
|
|
15
|
+
import { getGrants, addGrant, removeGrant } from '../settings-store.js';
|
|
16
|
+
const VALID_GRANT_TYPES = ['once', 'session', 'always'];
|
|
17
|
+
export function createPermissionsRouter() {
|
|
18
|
+
const router = Router();
|
|
19
|
+
// GET / - List all active grants
|
|
20
|
+
router.get('/', (_req, res) => {
|
|
21
|
+
res.json({ grants: getGrants() });
|
|
22
|
+
});
|
|
23
|
+
// POST /grant - Add a permission grant
|
|
24
|
+
router.post('/grant', (req, res) => {
|
|
25
|
+
const { tool, scope, grant_type } = req.body;
|
|
26
|
+
if (!tool || typeof tool !== 'string') {
|
|
27
|
+
res.status(400).json({ error: 'Missing required field: tool' });
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (!scope || typeof scope !== 'string') {
|
|
31
|
+
res.status(400).json({ error: 'Missing required field: scope' });
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const grantType = grant_type || 'session';
|
|
35
|
+
if (!VALID_GRANT_TYPES.includes(grantType)) {
|
|
36
|
+
res.status(400).json({ error: `Invalid grant_type: ${grantType}. Must be one of: ${VALID_GRANT_TYPES.join(', ')}` });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const grant = {
|
|
40
|
+
tool,
|
|
41
|
+
scope,
|
|
42
|
+
grant_type: grantType,
|
|
43
|
+
granted_at: new Date().toISOString(),
|
|
44
|
+
};
|
|
45
|
+
addGrant(grant);
|
|
46
|
+
res.status(201).json({ grant });
|
|
47
|
+
});
|
|
48
|
+
// DELETE /revoke/:tool - Revoke grants for a tool
|
|
49
|
+
router.delete('/revoke/:tool', (req, res) => {
|
|
50
|
+
const { tool } = req.params;
|
|
51
|
+
const scopeFilter = req.query.scope;
|
|
52
|
+
const allGrants = getGrants();
|
|
53
|
+
const toRemove = allGrants.filter((g) => g.tool === tool && (!scopeFilter || g.scope === scopeFilter));
|
|
54
|
+
for (const grant of toRemove) {
|
|
55
|
+
removeGrant(grant);
|
|
56
|
+
}
|
|
57
|
+
res.json({ removed: toRemove.length });
|
|
58
|
+
});
|
|
59
|
+
// GET /show/:tool - Show grants for a specific tool
|
|
60
|
+
router.get('/show/:tool', (req, res) => {
|
|
61
|
+
const { tool } = req.params;
|
|
62
|
+
const grants = getGrants().filter((g) => g.tool === tool);
|
|
63
|
+
res.json({ grants });
|
|
64
|
+
});
|
|
65
|
+
return router;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/api/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAA6C,MAAM,sBAAsB,CAAC;AAEnH,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAExD,MAAM,UAAU,uBAAuB;IACrC,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,iCAAiC;IACjC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;QAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,uCAAuC;IACvC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACpD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;QAE7C,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,8BAA8B,EAAE,CAAC,CAAC;YAChE,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACxC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC;YACjE,OAAO;QACT,CAAC;QAED,MAAM,SAAS,GAAmB,UAAU,IAAI,SAAS,CAAC;QAE1D,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,SAAS,qBAAqB,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACrH,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAoB;YAC7B,IAAI;YACJ,KAAK;YACL,UAAU,EAAE,SAAS;YACrB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACrC,CAAC;QAEF,QAAQ,CAAC,KAAK,CAAC,CAAC;QAChB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,kDAAkD;IAClD,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QAC7D,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAC5B,MAAM,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,KAA2B,CAAC;QAE1D,MAAM,SAAS,GAAG,SAAS,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,KAAK,KAAK,WAAW,CAAC,CACpE,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC7B,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,oDAAoD;IACpD,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;QACxD,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC;QAC5B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/api/settings.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export declare function createErrorResponse(code: ErrorCode, message: string): E
|
|
|
46
46
|
* Get settings for WebSocket broadcast
|
|
47
47
|
* Used by websocket.ts for /ws/settings endpoint
|
|
48
48
|
*/
|
|
49
|
-
export declare function getSettingsForWebSocket(projectDir: string | null): Promise<
|
|
49
|
+
export declare function getSettingsForWebSocket(projectDir: string | null): Promise<Record<string, unknown>>;
|
|
50
50
|
/**
|
|
51
51
|
* Create the settings router
|
|
52
52
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/api/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EAAwC,KAAK,eAAe,EAAsB,MAAM,gBAAgB,CAAC;AAShH;;;;;GAKG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC;IACzE,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG;QACtC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,aAAa,CAAC,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAMD;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,kBAAkB,GAAG,YAAY,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAEjG;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAMnF;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/api/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EAAwC,KAAK,eAAe,EAAsB,MAAM,gBAAgB,CAAC;AAShH;;;;;GAKG;AACH,MAAM,WAAW,gBAAiB,SAAQ,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC;IACzE,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG;QACtC,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,SAAS,CAAC,EAAE,OAAO,CAAC;QACpB,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,aAAa,CAAC,EAAE;QACd,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAMD;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,kBAAkB,GAAG,YAAY,GAAG,kBAAkB,GAAG,eAAe,CAAC;AAEjG;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAMnF;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAmDzG;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAob7C"}
|
package/dist/api/settings.js
CHANGED
|
@@ -31,24 +31,33 @@ export function createErrorResponse(code, message) {
|
|
|
31
31
|
*/
|
|
32
32
|
export async function getSettingsForWebSocket(projectDir) {
|
|
33
33
|
const settings = getCurrentSettings();
|
|
34
|
-
// Read
|
|
34
|
+
// Read config.local.yaml as single source of truth
|
|
35
35
|
let theme = 'alice-in-wonderland';
|
|
36
36
|
let handoffMode = 'manual';
|
|
37
37
|
let bellMode = false;
|
|
38
|
+
let display;
|
|
39
|
+
let notifications;
|
|
38
40
|
if (projectDir) {
|
|
39
41
|
try {
|
|
40
42
|
const configPath = path.join(projectDir, '.pennyfarthing', 'config.local.yaml');
|
|
41
43
|
if (fs.existsSync(configPath)) {
|
|
42
44
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
43
45
|
const parsed = parse(content);
|
|
44
|
-
if (parsed?.theme) {
|
|
46
|
+
if (parsed?.theme && typeof parsed.theme === 'string') {
|
|
45
47
|
theme = parsed.theme;
|
|
46
48
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
const workflow = parsed?.workflow;
|
|
50
|
+
if (workflow?.handoff_mode) {
|
|
51
|
+
handoffMode = workflow.handoff_mode;
|
|
49
52
|
}
|
|
50
|
-
if (
|
|
51
|
-
bellMode =
|
|
53
|
+
if (workflow?.bell_mode !== undefined) {
|
|
54
|
+
bellMode = workflow.bell_mode;
|
|
55
|
+
}
|
|
56
|
+
if (parsed?.display && typeof parsed.display === 'object') {
|
|
57
|
+
display = parsed.display;
|
|
58
|
+
}
|
|
59
|
+
if (parsed?.notifications && typeof parsed.notifications === 'object') {
|
|
60
|
+
notifications = parsed.notifications;
|
|
52
61
|
}
|
|
53
62
|
}
|
|
54
63
|
}
|
|
@@ -56,7 +65,7 @@ export async function getSettingsForWebSocket(projectDir) {
|
|
|
56
65
|
// Ignore project config errors - use defaults
|
|
57
66
|
}
|
|
58
67
|
}
|
|
59
|
-
|
|
68
|
+
const response = {
|
|
60
69
|
...settings,
|
|
61
70
|
workflow: {
|
|
62
71
|
...settings.workflow,
|
|
@@ -65,6 +74,11 @@ export async function getSettingsForWebSocket(projectDir) {
|
|
|
65
74
|
},
|
|
66
75
|
pennyfarthing: { theme },
|
|
67
76
|
};
|
|
77
|
+
if (display)
|
|
78
|
+
response.display = display;
|
|
79
|
+
if (notifications)
|
|
80
|
+
response.notifications = notifications;
|
|
81
|
+
return response;
|
|
68
82
|
}
|
|
69
83
|
/**
|
|
70
84
|
* Create the settings router
|
|
@@ -79,10 +93,12 @@ export function createSettingsRouter() {
|
|
|
79
93
|
router.get('/', async (_req, res) => {
|
|
80
94
|
try {
|
|
81
95
|
const settings = getCurrentSettings();
|
|
82
|
-
// Read
|
|
83
|
-
let theme = 'alice-in-wonderland';
|
|
84
|
-
let handoffMode = 'manual';
|
|
85
|
-
let bellMode = false;
|
|
96
|
+
// Read config.local.yaml as single source of truth for all project settings
|
|
97
|
+
let theme = 'alice-in-wonderland';
|
|
98
|
+
let handoffMode = 'manual';
|
|
99
|
+
let bellMode = false;
|
|
100
|
+
let display;
|
|
101
|
+
let notifications;
|
|
86
102
|
const projectDir = getProjectDirectory();
|
|
87
103
|
if (projectDir) {
|
|
88
104
|
try {
|
|
@@ -90,14 +106,21 @@ export function createSettingsRouter() {
|
|
|
90
106
|
if (fs.existsSync(configPath)) {
|
|
91
107
|
const content = fs.readFileSync(configPath, 'utf-8');
|
|
92
108
|
const parsed = parse(content);
|
|
93
|
-
if (parsed?.theme) {
|
|
109
|
+
if (parsed?.theme && typeof parsed.theme === 'string') {
|
|
94
110
|
theme = parsed.theme;
|
|
95
111
|
}
|
|
96
|
-
|
|
97
|
-
|
|
112
|
+
const workflow = parsed?.workflow;
|
|
113
|
+
if (workflow?.handoff_mode) {
|
|
114
|
+
handoffMode = workflow.handoff_mode;
|
|
115
|
+
}
|
|
116
|
+
if (workflow?.bell_mode !== undefined) {
|
|
117
|
+
bellMode = workflow.bell_mode;
|
|
118
|
+
}
|
|
119
|
+
if (parsed?.display && typeof parsed.display === 'object') {
|
|
120
|
+
display = parsed.display;
|
|
98
121
|
}
|
|
99
|
-
if (parsed?.
|
|
100
|
-
|
|
122
|
+
if (parsed?.notifications && typeof parsed.notifications === 'object') {
|
|
123
|
+
notifications = parsed.notifications;
|
|
101
124
|
}
|
|
102
125
|
}
|
|
103
126
|
}
|
|
@@ -105,7 +128,7 @@ export function createSettingsRouter() {
|
|
|
105
128
|
// Ignore project config errors - use defaults
|
|
106
129
|
}
|
|
107
130
|
}
|
|
108
|
-
// Construct response with
|
|
131
|
+
// Construct response with all persisted settings
|
|
109
132
|
const response = {
|
|
110
133
|
...settings,
|
|
111
134
|
workflow: {
|
|
@@ -115,6 +138,10 @@ export function createSettingsRouter() {
|
|
|
115
138
|
},
|
|
116
139
|
pennyfarthing: { theme },
|
|
117
140
|
};
|
|
141
|
+
if (display)
|
|
142
|
+
response.display = display;
|
|
143
|
+
if (notifications)
|
|
144
|
+
response.notifications = notifications;
|
|
118
145
|
res.json(response);
|
|
119
146
|
}
|
|
120
147
|
catch (error) {
|