@dollhousemcp/mcp-server 2.0.13 → 2.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/di/Container.d.ts.map +1 -1
- package/dist/di/Container.js +19 -9
- package/dist/elements/BaseElement.js +2 -2
- package/dist/elements/memories/Memory.d.ts.map +1 -1
- package/dist/elements/memories/Memory.js +3 -3
- package/dist/elements/skills/Skill.d.ts.map +1 -1
- package/dist/elements/skills/Skill.js +4 -4
- package/dist/elements/templates/Template.d.ts.map +1 -1
- package/dist/elements/templates/Template.js +4 -4
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/handlers/ElementCRUDHandler.d.ts +10 -0
- package/dist/handlers/ElementCRUDHandler.d.ts.map +1 -1
- package/dist/handlers/ElementCRUDHandler.js +123 -1
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts +1 -0
- package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/MCPAQLHandler.js +31 -2
- package/dist/services/ActivationStore.d.ts +20 -0
- package/dist/services/ActivationStore.d.ts.map +1 -1
- package/dist/services/ActivationStore.js +104 -1
- package/dist/web/console/IngestRoutes.d.ts +1 -0
- package/dist/web/console/IngestRoutes.d.ts.map +1 -1
- package/dist/web/console/IngestRoutes.js +4 -1
- package/dist/web/console/UnifiedConsole.js +2 -1
- package/dist/web/public/permissions.css +224 -16
- package/dist/web/public/permissions.js +326 -63
- package/dist/web/public/sessions.js +218 -98
- package/dist/web/public/styles.css +15 -10
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
- package/dist/web/routes/permissionRoutes.js +57 -19
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +2 -1
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -15,6 +15,16 @@
|
|
|
15
15
|
const POLL_INTERVAL_MS = 3000;
|
|
16
16
|
let initialized = false;
|
|
17
17
|
let lastDecisionId = null;
|
|
18
|
+
let latestAggregateData = null;
|
|
19
|
+
let latestSelectedData = null;
|
|
20
|
+
let latestPollRequestId = 0;
|
|
21
|
+
|
|
22
|
+
async function fetchPermissionStatus(sessionId) {
|
|
23
|
+
const query = sessionId ? `?sessionId=${encodeURIComponent(sessionId)}` : '';
|
|
24
|
+
const res = await DollhouseAuth.apiFetch(`/api/permissions/status${query}`);
|
|
25
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
26
|
+
return res.json();
|
|
27
|
+
}
|
|
18
28
|
|
|
19
29
|
// ── Public API ─────────────────────────────────────────────
|
|
20
30
|
|
|
@@ -23,6 +33,7 @@
|
|
|
23
33
|
init: initPermissions,
|
|
24
34
|
destroy: destroyPermissions,
|
|
25
35
|
refresh: function () { poll(); },
|
|
36
|
+
onSessionChange: function () { renderFromCache(); },
|
|
26
37
|
};
|
|
27
38
|
|
|
28
39
|
// Hook into tab switching — Todd's app.js lazyInitTab only knows logs/metrics,
|
|
@@ -69,22 +80,44 @@
|
|
|
69
80
|
// ── Polling ────────────────────────────────────────────────
|
|
70
81
|
|
|
71
82
|
async function poll() {
|
|
83
|
+
const requestId = ++latestPollRequestId;
|
|
72
84
|
try {
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
const aggregateData = await fetchPermissionStatus('');
|
|
86
|
+
if (requestId !== latestPollRequestId) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const currentSessionId = window.DollhouseSessions?.getFilterSessionId?.() || '';
|
|
91
|
+
const selectedData = deriveSelectedSessionData(aggregateData, currentSessionId);
|
|
92
|
+
|
|
93
|
+
latestAggregateData = aggregateData;
|
|
94
|
+
latestSelectedData = selectedData;
|
|
95
|
+
window.DollhouseSessions?.setPolicySessions?.(aggregateData.knownSessions || []);
|
|
96
|
+
render(aggregateData, selectedData);
|
|
77
97
|
} catch (err) {
|
|
78
98
|
renderError(err.message);
|
|
79
99
|
}
|
|
80
100
|
}
|
|
81
101
|
|
|
102
|
+
function renderFromCache() {
|
|
103
|
+
if (!latestAggregateData) {
|
|
104
|
+
poll();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const sessionId = window.DollhouseSessions?.getFilterSessionId?.() || '';
|
|
109
|
+
latestSelectedData = deriveSelectedSessionData(latestAggregateData, sessionId);
|
|
110
|
+
renderPolicySources(latestAggregateData, latestSelectedData);
|
|
111
|
+
renderSelectedSessionDetail(latestSelectedData);
|
|
112
|
+
}
|
|
113
|
+
|
|
82
114
|
// ── Rendering ──────────────────────────────────────────────
|
|
83
115
|
|
|
84
|
-
function render(data) {
|
|
116
|
+
function render(data, selectedData) {
|
|
85
117
|
renderStatusBar(data);
|
|
86
118
|
renderSummaryStats(data);
|
|
87
|
-
renderPolicySources(data);
|
|
119
|
+
renderPolicySources(data, selectedData);
|
|
120
|
+
renderSelectedSessionDetail(selectedData);
|
|
88
121
|
renderDenyPatterns(data);
|
|
89
122
|
renderAllowPatterns(data);
|
|
90
123
|
renderConfirmPatterns(data);
|
|
@@ -128,9 +161,9 @@
|
|
|
128
161
|
}
|
|
129
162
|
|
|
130
163
|
function renderSummaryStats(data) {
|
|
131
|
-
setText('perm-stat-deny-count', data.
|
|
132
|
-
setText('perm-stat-allow-count', data.
|
|
133
|
-
setText('perm-stat-confirm-count', data.
|
|
164
|
+
setText('perm-stat-deny-count', getAggregatePatterns(data, 'denyPatterns').length);
|
|
165
|
+
setText('perm-stat-allow-count', getAggregatePatterns(data, 'allowPatterns').length);
|
|
166
|
+
setText('perm-stat-confirm-count', getAggregatePatterns(data, 'confirmPatterns').length);
|
|
134
167
|
setText('perm-stat-decisions', data.recentDecisions?.length || 0);
|
|
135
168
|
|
|
136
169
|
// Decision breakdown
|
|
@@ -143,18 +176,19 @@
|
|
|
143
176
|
setText('perm-stat-asked', asked);
|
|
144
177
|
}
|
|
145
178
|
|
|
146
|
-
function renderPolicySources(data) {
|
|
179
|
+
function renderPolicySources(data, selectedData) {
|
|
147
180
|
const list = document.getElementById('perm-source-list');
|
|
148
181
|
if (!list) return;
|
|
149
182
|
|
|
150
183
|
const elements = data.elements || [];
|
|
184
|
+
const selectedSessionId = selectedData?.sessionId;
|
|
151
185
|
if (elements.length === 0) {
|
|
152
186
|
list.innerHTML = '<li class="perm-pattern-empty">No active elements with policies</li>';
|
|
153
187
|
return;
|
|
154
188
|
}
|
|
155
189
|
|
|
156
190
|
list.innerHTML = elements.map(el => `
|
|
157
|
-
<li class="perm-source-item">
|
|
191
|
+
<li class="perm-source-item${elementMatchesSelected(el, selectedSessionId) ? ' perm-source-item--selected' : ''}">
|
|
158
192
|
<span class="perm-source-type">${esc(el.type)}</span>
|
|
159
193
|
<span class="perm-source-name">${esc(el.element_name)}</span>
|
|
160
194
|
${el.description ? `<span style="color:var(--ink-400);font-size:0.75rem;margin-left:auto">${esc(el.description)}</span>` : ''}
|
|
@@ -162,16 +196,69 @@
|
|
|
162
196
|
`).join('');
|
|
163
197
|
}
|
|
164
198
|
|
|
199
|
+
function renderSelectedSessionDetail(selectedData) {
|
|
200
|
+
const card = document.getElementById('perm-selected-card');
|
|
201
|
+
const title = document.getElementById('perm-selected-title');
|
|
202
|
+
const subtitle = document.getElementById('perm-selected-subtitle');
|
|
203
|
+
const badge = document.getElementById('perm-selected-badge');
|
|
204
|
+
const sourceList = document.getElementById('perm-selected-source-list');
|
|
205
|
+
const denyList = document.getElementById('perm-selected-deny-list');
|
|
206
|
+
const allowList = document.getElementById('perm-selected-allow-list');
|
|
207
|
+
const confirmList = document.getElementById('perm-selected-confirm-list');
|
|
208
|
+
|
|
209
|
+
if (!card || !title || !subtitle || !badge || !sourceList || !denyList || !allowList || !confirmList) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!selectedData?.sessionId) {
|
|
214
|
+
card.hidden = true;
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
card.hidden = false;
|
|
219
|
+
|
|
220
|
+
const sessionInfo = window.DollhouseSessions?.getSelectableSessions?.()
|
|
221
|
+
?.find(session => session.sessionId === selectedData.sessionId);
|
|
222
|
+
const sessionLabel = window.DollhouseSessions?.displayName?.(sessionInfo || selectedData.sessionId)
|
|
223
|
+
|| selectedData.sessionId;
|
|
224
|
+
const policyOnly = !!sessionInfo?.isPolicyOnly;
|
|
225
|
+
|
|
226
|
+
title.textContent = `Selected Session: ${sessionLabel}`;
|
|
227
|
+
subtitle.textContent = policyOnly
|
|
228
|
+
? `${selectedData.sessionId} is showing saved policy state from disk. This is not a live attached client.`
|
|
229
|
+
: `${selectedData.sessionId} is the current live policy view for this session. Decision activity is still shown in the All Sessions section below.`;
|
|
230
|
+
|
|
231
|
+
badge.hidden = !policyOnly;
|
|
232
|
+
if (policyOnly) {
|
|
233
|
+
badge.textContent = 'Persisted Policy State (Debug Info)';
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const elements = selectedData.elements || [];
|
|
237
|
+
sourceList.innerHTML = elements.length === 0
|
|
238
|
+
? '<li class="perm-pattern-empty">No policy-bearing elements found for this session</li>'
|
|
239
|
+
: elements.map(el => `
|
|
240
|
+
<li class="perm-source-item perm-source-item--detail">
|
|
241
|
+
<span class="perm-source-type">${esc(el.type)}</span>
|
|
242
|
+
<span class="perm-source-name">${esc(el.element_name)}</span>
|
|
243
|
+
${el.description ? `<span style="color:var(--ink-400);font-size:0.75rem;margin-left:auto">${esc(el.description)}</span>` : ''}
|
|
244
|
+
</li>
|
|
245
|
+
`).join('');
|
|
246
|
+
|
|
247
|
+
renderPatternList('perm-selected-deny-list', selectedData.denyPatterns || [], 'deny');
|
|
248
|
+
renderPatternList('perm-selected-allow-list', selectedData.allowPatterns || [], 'allow');
|
|
249
|
+
renderPatternList('perm-selected-confirm-list', selectedData.confirmPatterns || [], 'confirm');
|
|
250
|
+
}
|
|
251
|
+
|
|
165
252
|
function renderDenyPatterns(data) {
|
|
166
|
-
renderPatternList('perm-deny-list', data
|
|
253
|
+
renderPatternList('perm-deny-list', getAggregatePatterns(data, 'denyPatterns'), 'deny');
|
|
167
254
|
}
|
|
168
255
|
|
|
169
256
|
function renderAllowPatterns(data) {
|
|
170
|
-
renderPatternList('perm-allow-list', data
|
|
257
|
+
renderPatternList('perm-allow-list', getAggregatePatterns(data, 'allowPatterns'), 'allow');
|
|
171
258
|
}
|
|
172
259
|
|
|
173
260
|
function renderConfirmPatterns(data) {
|
|
174
|
-
renderPatternList('perm-confirm-list', data
|
|
261
|
+
renderPatternList('perm-confirm-list', getAggregatePatterns(data, 'confirmPatterns'), 'confirm');
|
|
175
262
|
}
|
|
176
263
|
|
|
177
264
|
function renderPatternList(elementId, patterns, type) {
|
|
@@ -193,11 +280,16 @@
|
|
|
193
280
|
|
|
194
281
|
function renderLiveFeed(data) {
|
|
195
282
|
const feed = document.getElementById('perm-feed');
|
|
283
|
+
const modalFeed = document.getElementById('perm-audit-modal-feed');
|
|
284
|
+
const modalCount = document.getElementById('perm-audit-modal-count');
|
|
196
285
|
if (!feed) return;
|
|
197
286
|
|
|
198
287
|
const decisions = data.recentDecisions || [];
|
|
199
288
|
if (decisions.length === 0) {
|
|
200
|
-
|
|
289
|
+
const empty = '<div class="perm-feed-empty">No permission decisions yet. Waiting for tool calls...</div>';
|
|
290
|
+
feed.innerHTML = empty;
|
|
291
|
+
if (modalFeed) modalFeed.innerHTML = empty;
|
|
292
|
+
if (modalCount) modalCount.textContent = '0 captured entries';
|
|
201
293
|
return;
|
|
202
294
|
}
|
|
203
295
|
|
|
@@ -206,7 +298,7 @@
|
|
|
206
298
|
if (latestId === lastDecisionId) return; // no change
|
|
207
299
|
lastDecisionId = latestId;
|
|
208
300
|
|
|
209
|
-
|
|
301
|
+
const html = decisions.map(d => {
|
|
210
302
|
const time = new Date(d.timestamp).toLocaleTimeString();
|
|
211
303
|
const toolDisplay = d.tool_name === 'Bash'
|
|
212
304
|
? `Bash: ${esc(truncate(d.command || '', 60))}`
|
|
@@ -221,6 +313,52 @@
|
|
|
221
313
|
</div>
|
|
222
314
|
`;
|
|
223
315
|
}).join('');
|
|
316
|
+
|
|
317
|
+
feed.innerHTML = html;
|
|
318
|
+
if (modalFeed) modalFeed.innerHTML = html;
|
|
319
|
+
if (modalCount) {
|
|
320
|
+
modalCount.textContent = `${decisions.length} captured ${decisions.length === 1 ? 'entry' : 'entries'}`;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function deriveSelectedSessionData(aggregateData, sessionId) {
|
|
325
|
+
if (!sessionId) return null;
|
|
326
|
+
|
|
327
|
+
const elements = (aggregateData?.elements || []).filter(function (element) {
|
|
328
|
+
return Array.isArray(element.sessionIds) && element.sessionIds.indexOf(sessionId) !== -1;
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
sessionId: sessionId,
|
|
333
|
+
activeElementCount: elements.length,
|
|
334
|
+
hasAllowlist: elements.some(function (element) {
|
|
335
|
+
return Array.isArray(element.allowPatterns) && element.allowPatterns.length > 0;
|
|
336
|
+
}),
|
|
337
|
+
denyPatterns: flattenElementPatterns(elements, 'denyPatterns'),
|
|
338
|
+
allowPatterns: flattenElementPatterns(elements, 'allowPatterns'),
|
|
339
|
+
confirmPatterns: flattenElementPatterns(elements, 'confirmPatterns'),
|
|
340
|
+
elements: elements.map(function (element) {
|
|
341
|
+
return {
|
|
342
|
+
type: element.type,
|
|
343
|
+
element_name: element.element_name,
|
|
344
|
+
description: element.description,
|
|
345
|
+
};
|
|
346
|
+
}),
|
|
347
|
+
permissionPromptActive: !!aggregateData?.permissionPromptActive,
|
|
348
|
+
recentDecisions: aggregateData?.recentDecisions || [],
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function flattenElementPatterns(elements, key) {
|
|
353
|
+
return elements.flatMap(function (element) {
|
|
354
|
+
return Array.isArray(element[key]) ? element[key] : [];
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function getAggregatePatterns(data, key) {
|
|
359
|
+
const combined = Array.isArray(data && data[key]) ? data[key] : [];
|
|
360
|
+
const perElement = flattenElementPatterns((data && data.elements) || [], key);
|
|
361
|
+
return Array.from(new Set(combined.concat(perElement)));
|
|
224
362
|
}
|
|
225
363
|
|
|
226
364
|
// ── Dashboard HTML ─────────────────────────────────────────
|
|
@@ -246,8 +384,35 @@
|
|
|
246
384
|
|
|
247
385
|
<div class="perm-dashboard">
|
|
248
386
|
|
|
387
|
+
<!-- All Sessions Live Decision Feed -->
|
|
388
|
+
<div class="perm-card perm-card--full" data-collapsed="false" id="perm-all-feed-card">
|
|
389
|
+
<div class="perm-card-header" role="button" tabindex="0" aria-expanded="true">
|
|
390
|
+
<h3 class="perm-card-title">All Sessions Live Decision Feed</h3>
|
|
391
|
+
<span class="perm-card-toggle" aria-hidden="true">▾</span>
|
|
392
|
+
</div>
|
|
393
|
+
<div class="perm-card-body">
|
|
394
|
+
<div class="perm-selected-header perm-selected-header--compact">
|
|
395
|
+
<div>
|
|
396
|
+
<div class="perm-selected-subtitle">Aggregate audit stream across all sessions. Newest decisions appear first.</div>
|
|
397
|
+
</div>
|
|
398
|
+
<button
|
|
399
|
+
type="button"
|
|
400
|
+
class="perm-panel-action"
|
|
401
|
+
id="perm-feed-expand-btn"
|
|
402
|
+
aria-haspopup="dialog"
|
|
403
|
+
aria-controls="perm-audit-modal"
|
|
404
|
+
>
|
|
405
|
+
Open Audit View
|
|
406
|
+
</button>
|
|
407
|
+
</div>
|
|
408
|
+
<div class="perm-feed" id="perm-feed" role="log" aria-live="polite" aria-label="Permission decisions across all sessions">
|
|
409
|
+
<div class="perm-feed-empty">No permission decisions yet. Waiting for tool calls...</div>
|
|
410
|
+
</div>
|
|
411
|
+
</div>
|
|
412
|
+
</div>
|
|
413
|
+
|
|
249
414
|
<!-- Summary Stats -->
|
|
250
|
-
<div class="perm-card perm-card--full" data-collapsed="false">
|
|
415
|
+
<div class="perm-card perm-card--full" data-collapsed="false" id="perm-autonomy-card">
|
|
251
416
|
<div class="perm-card-header" role="button" tabindex="0" aria-expanded="true">
|
|
252
417
|
<h3 class="perm-card-title">Autonomy Overview</h3>
|
|
253
418
|
<span class="perm-card-toggle" aria-hidden="true">▾</span>
|
|
@@ -286,72 +451,115 @@
|
|
|
286
451
|
</div>
|
|
287
452
|
</div>
|
|
288
453
|
|
|
289
|
-
<!--
|
|
290
|
-
<div class="perm-card" data-collapsed="false">
|
|
454
|
+
<!-- Selected Session Detail -->
|
|
455
|
+
<div class="perm-card perm-card--full" data-collapsed="false" id="perm-selected-card" hidden>
|
|
291
456
|
<div class="perm-card-header" role="button" tabindex="0" aria-expanded="true">
|
|
292
|
-
<h3 class="perm-card-title">
|
|
457
|
+
<h3 class="perm-card-title">Selected Session Detail</h3>
|
|
293
458
|
<span class="perm-card-toggle" aria-hidden="true">▾</span>
|
|
294
459
|
</div>
|
|
295
460
|
<div class="perm-card-body">
|
|
296
|
-
<
|
|
297
|
-
<
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
461
|
+
<div class="perm-selected-header">
|
|
462
|
+
<div>
|
|
463
|
+
<div class="perm-selected-title" id="perm-selected-title">Selected Session</div>
|
|
464
|
+
<div class="perm-selected-subtitle" id="perm-selected-subtitle"></div>
|
|
465
|
+
</div>
|
|
466
|
+
<span class="perm-selected-badge" id="perm-selected-badge" hidden>Persisted Policy State (Debug Info)</span>
|
|
467
|
+
</div>
|
|
301
468
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
469
|
+
<div class="perm-selected-grid">
|
|
470
|
+
<div class="perm-selected-panel">
|
|
471
|
+
<h4 class="perm-selected-panel-title">Policy Sources</h4>
|
|
472
|
+
<ul class="perm-source-list" id="perm-selected-source-list">
|
|
473
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
474
|
+
</ul>
|
|
475
|
+
</div>
|
|
476
|
+
<div class="perm-selected-panel">
|
|
477
|
+
<h4 class="perm-selected-panel-title">Deny Patterns</h4>
|
|
478
|
+
<ul class="perm-pattern-list" id="perm-selected-deny-list">
|
|
479
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
480
|
+
</ul>
|
|
481
|
+
</div>
|
|
482
|
+
<div class="perm-selected-panel">
|
|
483
|
+
<h4 class="perm-selected-panel-title">Allow Patterns</h4>
|
|
484
|
+
<ul class="perm-pattern-list" id="perm-selected-allow-list">
|
|
485
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
486
|
+
</ul>
|
|
487
|
+
</div>
|
|
488
|
+
<div class="perm-selected-panel">
|
|
489
|
+
<h4 class="perm-selected-panel-title">Confirm Patterns</h4>
|
|
490
|
+
<ul class="perm-pattern-list" id="perm-selected-confirm-list">
|
|
491
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
492
|
+
</ul>
|
|
493
|
+
</div>
|
|
494
|
+
</div>
|
|
312
495
|
</div>
|
|
313
496
|
</div>
|
|
314
497
|
|
|
315
|
-
|
|
316
|
-
<div class="perm-card" data-collapsed="true">
|
|
498
|
+
<div class="perm-card perm-card--full" data-collapsed="false" id="perm-all-detail-card">
|
|
317
499
|
<div class="perm-card-header" role="button" tabindex="0" aria-expanded="true">
|
|
318
|
-
<h3 class="perm-card-title">
|
|
500
|
+
<h3 class="perm-card-title">All Sessions Detail</h3>
|
|
319
501
|
<span class="perm-card-toggle" aria-hidden="true">▾</span>
|
|
320
502
|
</div>
|
|
321
503
|
<div class="perm-card-body">
|
|
322
|
-
<
|
|
323
|
-
<
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
504
|
+
<div class="perm-selected-header perm-selected-header--compact">
|
|
505
|
+
<div>
|
|
506
|
+
<div class="perm-selected-title">All Sessions</div>
|
|
507
|
+
<div class="perm-selected-subtitle">Aggregate policy state across all live and persisted sessions. The decision feed below is currently aggregate, not selection-scoped.</div>
|
|
508
|
+
</div>
|
|
509
|
+
</div>
|
|
327
510
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
511
|
+
<div class="perm-selected-grid">
|
|
512
|
+
<div class="perm-selected-panel">
|
|
513
|
+
<h4 class="perm-selected-panel-title">Policy Sources</h4>
|
|
514
|
+
<ul class="perm-source-list" id="perm-source-list">
|
|
515
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
516
|
+
</ul>
|
|
517
|
+
</div>
|
|
518
|
+
<div class="perm-selected-panel">
|
|
519
|
+
<h4 class="perm-selected-panel-title">Deny Patterns</h4>
|
|
520
|
+
<ul class="perm-pattern-list" id="perm-deny-list">
|
|
521
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
522
|
+
</ul>
|
|
523
|
+
</div>
|
|
524
|
+
<div class="perm-selected-panel">
|
|
525
|
+
<h4 class="perm-selected-panel-title">Allow Patterns</h4>
|
|
526
|
+
<ul class="perm-pattern-list" id="perm-allow-list">
|
|
527
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
528
|
+
</ul>
|
|
529
|
+
</div>
|
|
530
|
+
<div class="perm-selected-panel">
|
|
531
|
+
<h4 class="perm-selected-panel-title">Confirm Patterns</h4>
|
|
532
|
+
<ul class="perm-pattern-list" id="perm-confirm-list">
|
|
533
|
+
<li class="perm-pattern-empty">Loading...</li>
|
|
534
|
+
</ul>
|
|
535
|
+
</div>
|
|
536
|
+
</div>
|
|
338
537
|
</div>
|
|
339
538
|
</div>
|
|
340
539
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
540
|
+
</div>
|
|
541
|
+
|
|
542
|
+
<dialog class="modal perm-audit-modal" id="perm-audit-modal" aria-labelledby="perm-audit-modal-title">
|
|
543
|
+
<div class="modal-overlay" data-close-audit-modal></div>
|
|
544
|
+
<div class="modal-dialog perm-audit-modal-dialog" role="document">
|
|
545
|
+
<header class="modal-header">
|
|
546
|
+
<div class="modal-heading">
|
|
547
|
+
<h2 class="modal-title" id="perm-audit-modal-title">All Sessions Audit View</h2>
|
|
548
|
+
<span class="modal-type">Permissions</span>
|
|
549
|
+
</div>
|
|
550
|
+
<div class="modal-meta">
|
|
551
|
+
<span>Aggregate decision log across all sessions</span>
|
|
552
|
+
<span id="perm-audit-modal-count">0 captured entries</span>
|
|
553
|
+
</div>
|
|
554
|
+
<button type="button" class="modal-close" id="perm-audit-modal-close" aria-label="Close audit view">✕</button>
|
|
555
|
+
</header>
|
|
556
|
+
<div class="modal-body">
|
|
557
|
+
<div class="perm-feed perm-feed--modal" id="perm-audit-modal-feed" role="log" aria-live="polite" aria-label="Full permission decision audit feed">
|
|
349
558
|
<div class="perm-feed-empty">No permission decisions yet. Waiting for tool calls...</div>
|
|
350
559
|
</div>
|
|
351
560
|
</div>
|
|
352
561
|
</div>
|
|
353
|
-
|
|
354
|
-
</div>
|
|
562
|
+
</dialog>
|
|
355
563
|
`;
|
|
356
564
|
}
|
|
357
565
|
|
|
@@ -370,6 +578,56 @@
|
|
|
370
578
|
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); }
|
|
371
579
|
});
|
|
372
580
|
});
|
|
581
|
+
|
|
582
|
+
const expandBtn = document.getElementById('perm-feed-expand-btn');
|
|
583
|
+
const auditModal = document.getElementById('perm-audit-modal');
|
|
584
|
+
const closeBtn = document.getElementById('perm-audit-modal-close');
|
|
585
|
+
if (expandBtn && auditModal) {
|
|
586
|
+
expandBtn.addEventListener('click', function (e) {
|
|
587
|
+
e.stopPropagation();
|
|
588
|
+
openAuditModal();
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (closeBtn) {
|
|
593
|
+
closeBtn.addEventListener('click', closeAuditModal);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
if (auditModal) {
|
|
597
|
+
auditModal.addEventListener('click', function (e) {
|
|
598
|
+
if (e.target === auditModal || e.target.hasAttribute('data-close-audit-modal')) {
|
|
599
|
+
closeAuditModal();
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
auditModal.addEventListener('close', function () {
|
|
603
|
+
document.body.classList.remove('modal-open');
|
|
604
|
+
});
|
|
605
|
+
auditModal.addEventListener('cancel', function () {
|
|
606
|
+
document.body.classList.remove('modal-open');
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
function openAuditModal() {
|
|
612
|
+
const auditModal = document.getElementById('perm-audit-modal');
|
|
613
|
+
if (!auditModal) return;
|
|
614
|
+
if (typeof auditModal.showModal === 'function') {
|
|
615
|
+
auditModal.showModal();
|
|
616
|
+
} else {
|
|
617
|
+
auditModal.setAttribute('open', '');
|
|
618
|
+
}
|
|
619
|
+
document.body.classList.add('modal-open');
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function closeAuditModal() {
|
|
623
|
+
const auditModal = document.getElementById('perm-audit-modal');
|
|
624
|
+
if (!auditModal) return;
|
|
625
|
+
if (typeof auditModal.close === 'function') {
|
|
626
|
+
auditModal.close();
|
|
627
|
+
} else {
|
|
628
|
+
auditModal.removeAttribute('open');
|
|
629
|
+
}
|
|
630
|
+
document.body.classList.remove('modal-open');
|
|
373
631
|
}
|
|
374
632
|
|
|
375
633
|
function setText(id, value) {
|
|
@@ -377,6 +635,11 @@
|
|
|
377
635
|
if (el) el.textContent = String(value);
|
|
378
636
|
}
|
|
379
637
|
|
|
638
|
+
function elementMatchesSelected(element, sessionId) {
|
|
639
|
+
if (!sessionId || !Array.isArray(element?.sessionIds)) return false;
|
|
640
|
+
return element.sessionIds.includes(sessionId);
|
|
641
|
+
}
|
|
642
|
+
|
|
380
643
|
// dmcp-sec[DMCP-SEC-004] — Client-side JS: UnicodeValidator unavailable in browser.
|
|
381
644
|
// Using native String.normalize('NFC') which performs the same NFC normalization.
|
|
382
645
|
// All data comes from our own server API, not direct user input.
|