@dollhousemcp/mcp-server 2.0.15 → 2.0.17

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md.backup +18 -0
  3. package/dist/elements/base/BaseElementManager.d.ts.map +1 -1
  4. package/dist/elements/base/BaseElementManager.js +17 -1
  5. package/dist/elements/memories/MemoryManager.d.ts.map +1 -1
  6. package/dist/elements/memories/MemoryManager.js +13 -2
  7. package/dist/generated/version.d.ts +2 -2
  8. package/dist/generated/version.js +3 -3
  9. package/dist/handlers/ElementCRUDHandler.d.ts.map +1 -1
  10. package/dist/handlers/ElementCRUDHandler.js +7 -3
  11. package/dist/handlers/element-crud/createElement.d.ts.map +1 -1
  12. package/dist/handlers/element-crud/createElement.js +6 -2
  13. package/dist/handlers/element-crud/editElement.d.ts.map +1 -1
  14. package/dist/handlers/element-crud/editElement.js +6 -2
  15. package/dist/handlers/element-crud/helpers.d.ts +2 -0
  16. package/dist/handlers/element-crud/helpers.d.ts.map +1 -1
  17. package/dist/handlers/element-crud/helpers.js +21 -2
  18. package/dist/handlers/mcp-aql/IntrospectionResolver.d.ts.map +1 -1
  19. package/dist/handlers/mcp-aql/IntrospectionResolver.js +34 -7
  20. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
  21. package/dist/handlers/mcp-aql/MCPAQLHandler.js +51 -20
  22. package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
  23. package/dist/handlers/mcp-aql/OperationSchema.js +6 -4
  24. package/dist/handlers/mcp-aql/evaluatePermission.d.ts +2 -1
  25. package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -1
  26. package/dist/handlers/mcp-aql/evaluatePermission.js +23 -11
  27. package/dist/handlers/mcp-aql/policies/ElementPolicies.d.ts +8 -0
  28. package/dist/handlers/mcp-aql/policies/ElementPolicies.d.ts.map +1 -1
  29. package/dist/handlers/mcp-aql/policies/ElementPolicies.js +26 -1
  30. package/dist/handlers/strategies/BaseActivationStrategy.d.ts.map +1 -1
  31. package/dist/handlers/strategies/BaseActivationStrategy.js +12 -3
  32. package/dist/handlers/strategies/PersonaActivationStrategy.js +2 -2
  33. package/dist/utils/permissionHooks.d.ts +74 -0
  34. package/dist/utils/permissionHooks.d.ts.map +1 -0
  35. package/dist/utils/permissionHooks.js +771 -0
  36. package/dist/web/public/index.html +12 -6
  37. package/dist/web/public/permissions.css +11 -0
  38. package/dist/web/public/permissions.js +78 -35
  39. package/dist/web/public/setup.css +172 -1
  40. package/dist/web/public/setup.js +644 -38
  41. package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
  42. package/dist/web/routes/permissionRoutes.js +95 -27
  43. package/dist/web/routes/setupRoutes.d.ts +4 -0
  44. package/dist/web/routes/setupRoutes.d.ts.map +1 -1
  45. package/dist/web/routes/setupRoutes.js +122 -39
  46. package/package.json +8 -1
  47. package/scripts/pretooluse-codex.sh +6 -0
  48. package/scripts/pretooluse-cursor.sh +6 -0
  49. package/scripts/pretooluse-dollhouse.sh +110 -0
  50. package/scripts/pretooluse-gemini.sh +6 -0
  51. package/scripts/pretooluse-vscode.sh +163 -0
  52. package/scripts/pretooluse-windsurf.sh +168 -0
  53. package/server.json +2 -2
@@ -77,6 +77,10 @@
77
77
  <strong>Pinned version</strong>
78
78
  <span>Lock to a specific version, update when you choose</span>
79
79
  </button>
80
+ <button class="setup-method-btn" data-method="permissions" aria-pressed="false">
81
+ <strong>Permissions &amp; Security</strong>
82
+ <span>Manual hook assets and enforcement guidance</span>
83
+ </button>
80
84
  </fieldset>
81
85
 
82
86
  <fieldset class="setup-channel-toggle" id="setup-channel-toggle">
@@ -119,6 +123,8 @@ npm install @dollhousemcp/mcp-server</code></pre>
119
123
  </div>
120
124
  </div>
121
125
 
126
+ <div class="setup-permissions-intro" id="setup-permissions-intro" hidden></div>
127
+
122
128
  <div class="setup-platforms" id="setup-platforms" role="tablist" aria-label="Platform install instructions">
123
129
  <button class="setup-platform-tab is-active" role="tab" aria-selected="true" aria-controls="setup-panel-claude-desktop" id="setup-tab-claude-desktop">Claude Desktop</button>
124
130
  <button class="setup-platform-tab" role="tab" aria-selected="false" aria-controls="setup-panel-claude-code" id="setup-tab-claude-code">Claude Code</button>
@@ -133,7 +139,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
133
139
 
134
140
  <!-- Claude Desktop -->
135
141
  <section class="setup-panel is-active" role="tabpanel" id="setup-panel-claude-desktop" aria-labelledby="setup-tab-claude-desktop">
136
- <div class="setup-method setup-method-primary">
142
+ <div class="setup-method setup-method-primary" data-setup-modes="npx global">
137
143
  <h3>Auto-configure <span class="setup-method-badge setup-badge">auto-updating</span></h3>
138
144
  <p class="setup-method-desc">Pulls the latest version of DollhouseMCP on every startup. Uses <code>npx @latest</code> under the hood. Restart Claude Desktop after.</p>
139
145
  <div class="setup-install-row">
@@ -141,12 +147,12 @@ npm install @dollhousemcp/mcp-server</code></pre>
141
147
  <span class="setup-install-status" data-install-status="claude"></span>
142
148
  </div>
143
149
  </div>
144
- <div class="setup-method setup-mcpb-option" id="setup-mcpb-section" hidden>
150
+ <div class="setup-method setup-mcpb-option" id="setup-mcpb-section" data-setup-modes="global" hidden>
145
151
  <h3>Or install via Desktop Extension <span class="setup-badge">pinned version</span></h3>
146
152
  <p>Download the <code>.mcpb</code> bundle and double-click it to install. Claude Desktop handles everything automatically &mdash; no terminal, no config editing. This installs a pinned copy that won't auto-update.</p>
147
153
  <a class="setup-btn setup-btn-secondary" href="/api/setup/mcpb" id="pinned-mcpb-btn">Download .mcpb <span id="pinned-mcpb-version"></span></a>
148
154
  </div>
149
- <div class="setup-method">
155
+ <div class="setup-method" data-setup-modes="npx global">
150
156
  <h3>Or add manually
151
157
  <button class="setup-open-btn" type="button" data-open-client="claude">Open config file</button>
152
158
  </h3>
@@ -173,7 +179,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
173
179
 
174
180
  <!-- Claude Code -->
175
181
  <section class="setup-panel" role="tabpanel" id="setup-panel-claude-code" aria-labelledby="setup-tab-claude-code" hidden>
176
- <div class="setup-method setup-method-primary">
182
+ <div class="setup-method setup-method-primary" data-setup-modes="npx global">
177
183
  <h3>Auto-configure <span class="setup-method-badge setup-badge">auto-updating</span></h3>
178
184
  <p class="setup-method-desc">Adds DollhouseMCP to Claude Code, pulling the latest version on every startup.</p>
179
185
  <div class="setup-install-row">
@@ -181,7 +187,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
181
187
  <span class="setup-install-status" data-install-status="claude-code"></span>
182
188
  </div>
183
189
  </div>
184
- <div class="setup-method">
190
+ <div class="setup-method" data-setup-modes="npx global">
185
191
  <h3>Or run in your terminal</h3>
186
192
  <p>Start a new conversation and you're ready.</p>
187
193
  <div class="setup-code-block">
@@ -189,7 +195,7 @@ npm install @dollhousemcp/mcp-server</code></pre>
189
195
  <pre><code>claude mcp add dollhousemcp -- npx -y @dollhousemcp/mcp-server@latest</code></pre>
190
196
  </div>
191
197
  </div>
192
- <div class="setup-method">
198
+ <div class="setup-method" data-setup-modes="npx global">
193
199
  <h3>Or add manually
194
200
  <button class="setup-open-btn" type="button" data-open-client="claude-code">Open config file</button>
195
201
  </h3>
@@ -46,6 +46,11 @@
46
46
  box-shadow: 0 0 6px rgba(239, 68, 68, 0.5);
47
47
  }
48
48
 
49
+ .perm-status-dot[data-status="warning"] {
50
+ background: #f59e0b;
51
+ box-shadow: 0 0 6px rgba(245, 158, 11, 0.45);
52
+ }
53
+
49
54
  .perm-status-spacer {
50
55
  flex: 1;
51
56
  }
@@ -54,6 +59,12 @@
54
59
  color: var(--ink-400, #64748b);
55
60
  }
56
61
 
62
+ .perm-inline-advisory {
63
+ display: inline-block;
64
+ color: var(--signal-4-ink, #b45309);
65
+ margin-top: 0.35rem;
66
+ }
67
+
57
68
  /* ── Dashboard Grid ────────────────────────────────────────── */
58
69
 
59
70
  .perm-dashboard {
@@ -116,6 +116,7 @@
116
116
  function render(data, selectedData) {
117
117
  renderStatusBar(data);
118
118
  renderSummaryStats(data);
119
+ renderAdvisory(data);
119
120
  renderPolicySources(data, selectedData);
120
121
  renderSelectedSessionDetail(selectedData);
121
122
  renderDenyPatterns(data);
@@ -137,6 +138,7 @@
137
138
  const serverDot = document.getElementById('perm-dot-server');
138
139
  const ensembleDot = document.getElementById('perm-dot-ensemble');
139
140
  const hookDot = document.getElementById('perm-dot-hook');
141
+ const hookLabel = hookDot ? hookDot.parentElement.querySelector('.perm-status-label') : null;
140
142
  const updated = document.getElementById('perm-last-updated');
141
143
 
142
144
  if (serverDot) {
@@ -149,11 +151,29 @@
149
151
  ensembleDot.parentElement.querySelector('.perm-status-label').textContent =
150
152
  hasElements ? `${data.activeElementCount} elements` : 'No ensemble';
151
153
  }
152
- if (hookDot) {
153
- const hasPatterns = (data.denyPatterns?.length || 0) + (data.allowPatterns?.length || 0) > 0;
154
- hookDot.dataset.status = hasPatterns ? 'active' : 'inactive';
155
- hookDot.parentElement.querySelector('.perm-status-label').textContent =
156
- hasPatterns ? 'Policies active' : 'No policies';
154
+ if (hookDot && hookLabel) {
155
+ const hasExternalRules = (data.denyPatterns?.length || 0)
156
+ + (data.allowPatterns?.length || 0)
157
+ + (data.confirmPatterns?.length || 0) > 0;
158
+ const hasAnyRules = (data.denyRules?.length || 0)
159
+ + (data.allowRules?.length || 0)
160
+ + (data.confirmRules?.length || 0) > 0;
161
+ if (!hasAnyRules) {
162
+ hookDot.dataset.status = 'inactive';
163
+ hookLabel.textContent = 'No policies';
164
+ } else if (!hasExternalRules) {
165
+ hookDot.dataset.status = 'active';
166
+ hookLabel.textContent = 'MCP-AQL policies active';
167
+ } else if (data.permissionPromptActive) {
168
+ hookDot.dataset.status = 'active';
169
+ hookLabel.textContent = 'Prompt tool active';
170
+ } else if (data.hookInstalled) {
171
+ hookDot.dataset.status = 'active';
172
+ hookLabel.textContent = data.hookHost ? `Hook installed (${data.hookHost})` : 'Hook installed';
173
+ } else {
174
+ hookDot.dataset.status = 'warning';
175
+ hookLabel.textContent = 'Policies loaded, not enforced';
176
+ }
157
177
  }
158
178
  if (updated) {
159
179
  updated.textContent = new Date().toLocaleTimeString();
@@ -161,9 +181,9 @@
161
181
  }
162
182
 
163
183
  function renderSummaryStats(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);
184
+ setText('perm-stat-deny-count', getAggregateRules(data, 'denyRules').length);
185
+ setText('perm-stat-allow-count', getAggregateRules(data, 'allowRules').length);
186
+ setText('perm-stat-confirm-count', getAggregateRules(data, 'confirmRules').length);
167
187
  setText('perm-stat-decisions', data.recentDecisions?.length || 0);
168
188
 
169
189
  // Decision breakdown
@@ -176,6 +196,19 @@
176
196
  setText('perm-stat-asked', asked);
177
197
  }
178
198
 
199
+ function renderAdvisory(data) {
200
+ const advisory = document.getElementById('perm-all-sessions-advisory');
201
+ if (!advisory) return;
202
+
203
+ if (data && data.advisory) {
204
+ advisory.hidden = false;
205
+ advisory.textContent = ` ${data.advisory}`;
206
+ } else {
207
+ advisory.hidden = true;
208
+ advisory.textContent = '';
209
+ }
210
+ }
211
+
179
212
  function renderPolicySources(data, selectedData) {
180
213
  const list = document.getElementById('perm-source-list');
181
214
  if (!list) return;
@@ -190,7 +223,7 @@
190
223
  list.innerHTML = elements.map(el => `
191
224
  <li class="perm-source-item${elementMatchesSelected(el, selectedSessionId) ? ' perm-source-item--selected' : ''}">
192
225
  <span class="perm-source-type">${esc(el.type)}</span>
193
- <span class="perm-source-name">${esc(el.element_name)}</span>
226
+ <span class="perm-source-name">${esc(el.element_name || el.name || '')}</span>
194
227
  ${el.description ? `<span style="color:var(--ink-400);font-size:0.75rem;margin-left:auto">${esc(el.description)}</span>` : ''}
195
228
  </li>
196
229
  `).join('');
@@ -239,26 +272,26 @@
239
272
  : elements.map(el => `
240
273
  <li class="perm-source-item perm-source-item--detail">
241
274
  <span class="perm-source-type">${esc(el.type)}</span>
242
- <span class="perm-source-name">${esc(el.element_name)}</span>
275
+ <span class="perm-source-name">${esc(el.element_name || el.name || '')}</span>
243
276
  ${el.description ? `<span style="color:var(--ink-400);font-size:0.75rem;margin-left:auto">${esc(el.description)}</span>` : ''}
244
277
  </li>
245
278
  `).join('');
246
279
 
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');
280
+ renderPatternList('perm-selected-deny-list', selectedData.denyRules || [], 'deny');
281
+ renderPatternList('perm-selected-allow-list', selectedData.allowRules || [], 'allow');
282
+ renderPatternList('perm-selected-confirm-list', selectedData.confirmRules || [], 'confirm');
250
283
  }
251
284
 
252
285
  function renderDenyPatterns(data) {
253
- renderPatternList('perm-deny-list', getAggregatePatterns(data, 'denyPatterns'), 'deny');
286
+ renderPatternList('perm-deny-list', getAggregateRules(data, 'denyRules'), 'deny');
254
287
  }
255
288
 
256
289
  function renderAllowPatterns(data) {
257
- renderPatternList('perm-allow-list', getAggregatePatterns(data, 'allowPatterns'), 'allow');
290
+ renderPatternList('perm-allow-list', getAggregateRules(data, 'allowRules'), 'allow');
258
291
  }
259
292
 
260
293
  function renderConfirmPatterns(data) {
261
- renderPatternList('perm-confirm-list', getAggregatePatterns(data, 'confirmPatterns'), 'confirm');
294
+ renderPatternList('perm-confirm-list', getAggregateRules(data, 'confirmRules'), 'confirm');
262
295
  }
263
296
 
264
297
  function renderPatternList(elementId, patterns, type) {
@@ -266,7 +299,7 @@
266
299
  if (!list) return;
267
300
 
268
301
  if (patterns.length === 0) {
269
- list.innerHTML = `<li class="perm-pattern-empty">No ${type} patterns active</li>`;
302
+ list.innerHTML = `<li class="perm-pattern-empty">No ${type} rules active</li>`;
270
303
  return;
271
304
  }
272
305
 
@@ -332,11 +365,11 @@
332
365
  sessionId: sessionId,
333
366
  activeElementCount: elements.length,
334
367
  hasAllowlist: elements.some(function (element) {
335
- return Array.isArray(element.allowPatterns) && element.allowPatterns.length > 0;
368
+ return Array.isArray(element.allowRules) && element.allowRules.length > 0;
336
369
  }),
337
- denyPatterns: flattenElementPatterns(elements, 'denyPatterns'),
338
- allowPatterns: flattenElementPatterns(elements, 'allowPatterns'),
339
- confirmPatterns: flattenElementPatterns(elements, 'confirmPatterns'),
370
+ denyRules: flattenElementPatterns(elements, 'denyRules'),
371
+ allowRules: flattenElementPatterns(elements, 'allowRules'),
372
+ confirmRules: flattenElementPatterns(elements, 'confirmRules'),
340
373
  elements: elements.map(function (element) {
341
374
  return {
342
375
  type: element.type,
@@ -361,6 +394,12 @@
361
394
  return Array.from(new Set(combined.concat(perElement)));
362
395
  }
363
396
 
397
+ function getAggregateRules(data, key) {
398
+ const combined = Array.isArray(data && data[key]) ? data[key] : [];
399
+ const perElement = flattenElementPatterns((data && data.elements) || [], key);
400
+ return Array.from(new Set(combined.concat(perElement)));
401
+ }
402
+
364
403
  // ── Dashboard HTML ─────────────────────────────────────────
365
404
 
366
405
  function buildDashboardHTML() {
@@ -374,10 +413,10 @@
374
413
  <span class="perm-status-dot" id="perm-dot-ensemble" data-status="inactive"></span>
375
414
  <span class="perm-status-label">Ensemble</span>
376
415
  </div>
377
- <div class="perm-status-indicator">
378
- <span class="perm-status-dot" id="perm-dot-hook" data-status="inactive"></span>
379
- <span class="perm-status-label">Policies</span>
380
- </div>
416
+ <div class="perm-status-indicator">
417
+ <span class="perm-status-dot" id="perm-dot-hook" data-status="inactive"></span>
418
+ <span class="perm-status-label">Policies</span>
419
+ </div>
381
420
  <span class="perm-status-spacer"></span>
382
421
  <span class="perm-status-updated">Updated: <span id="perm-last-updated">--:--:--</span></span>
383
422
  </div>
@@ -421,15 +460,15 @@
421
460
  <div class="perm-stat-grid">
422
461
  <div class="perm-stat">
423
462
  <div class="perm-stat-value perm-stat-value--deny" id="perm-stat-deny-count">0</div>
424
- <div class="perm-stat-label">Deny Patterns</div>
463
+ <div class="perm-stat-label">Deny Rules</div>
425
464
  </div>
426
465
  <div class="perm-stat">
427
466
  <div class="perm-stat-value perm-stat-value--allow" id="perm-stat-allow-count">0</div>
428
- <div class="perm-stat-label">Allow Patterns</div>
467
+ <div class="perm-stat-label">Allow Rules</div>
429
468
  </div>
430
469
  <div class="perm-stat">
431
470
  <div class="perm-stat-value perm-stat-value--ask" id="perm-stat-confirm-count">0</div>
432
- <div class="perm-stat-label">Confirm Patterns</div>
471
+ <div class="perm-stat-label">Confirm Rules</div>
433
472
  </div>
434
473
  <div class="perm-stat">
435
474
  <div class="perm-stat-value" id="perm-stat-decisions">0</div>
@@ -474,19 +513,19 @@
474
513
  </ul>
475
514
  </div>
476
515
  <div class="perm-selected-panel">
477
- <h4 class="perm-selected-panel-title">Deny Patterns</h4>
516
+ <h4 class="perm-selected-panel-title">Deny Rules</h4>
478
517
  <ul class="perm-pattern-list" id="perm-selected-deny-list">
479
518
  <li class="perm-pattern-empty">Loading...</li>
480
519
  </ul>
481
520
  </div>
482
521
  <div class="perm-selected-panel">
483
- <h4 class="perm-selected-panel-title">Allow Patterns</h4>
522
+ <h4 class="perm-selected-panel-title">Allow Rules</h4>
484
523
  <ul class="perm-pattern-list" id="perm-selected-allow-list">
485
524
  <li class="perm-pattern-empty">Loading...</li>
486
525
  </ul>
487
526
  </div>
488
527
  <div class="perm-selected-panel">
489
- <h4 class="perm-selected-panel-title">Confirm Patterns</h4>
528
+ <h4 class="perm-selected-panel-title">Confirm Rules</h4>
490
529
  <ul class="perm-pattern-list" id="perm-selected-confirm-list">
491
530
  <li class="perm-pattern-empty">Loading...</li>
492
531
  </ul>
@@ -504,7 +543,7 @@
504
543
  <div class="perm-selected-header perm-selected-header--compact">
505
544
  <div>
506
545
  <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>
546
+ <div class="perm-selected-subtitle">${esc('Aggregate policy state across all live and persisted sessions. Rules shown here include both Dollhouse operation policies and external tool restrictions.')}${dataAdvisoryPlaceholder()}</div>
508
547
  </div>
509
548
  </div>
510
549
 
@@ -516,19 +555,19 @@
516
555
  </ul>
517
556
  </div>
518
557
  <div class="perm-selected-panel">
519
- <h4 class="perm-selected-panel-title">Deny Patterns</h4>
558
+ <h4 class="perm-selected-panel-title">Deny Rules</h4>
520
559
  <ul class="perm-pattern-list" id="perm-deny-list">
521
560
  <li class="perm-pattern-empty">Loading...</li>
522
561
  </ul>
523
562
  </div>
524
563
  <div class="perm-selected-panel">
525
- <h4 class="perm-selected-panel-title">Allow Patterns</h4>
564
+ <h4 class="perm-selected-panel-title">Allow Rules</h4>
526
565
  <ul class="perm-pattern-list" id="perm-allow-list">
527
566
  <li class="perm-pattern-empty">Loading...</li>
528
567
  </ul>
529
568
  </div>
530
569
  <div class="perm-selected-panel">
531
- <h4 class="perm-selected-panel-title">Confirm Patterns</h4>
570
+ <h4 class="perm-selected-panel-title">Confirm Rules</h4>
532
571
  <ul class="perm-pattern-list" id="perm-confirm-list">
533
572
  <li class="perm-pattern-empty">Loading...</li>
534
573
  </ul>
@@ -654,4 +693,8 @@
654
693
  return str.length > len ? str.slice(0, len) + '...' : str;
655
694
  }
656
695
 
696
+ function dataAdvisoryPlaceholder() {
697
+ return '<span id="perm-all-sessions-advisory" class="perm-inline-advisory" hidden></span>';
698
+ }
699
+
657
700
  })();
@@ -70,7 +70,7 @@
70
70
 
71
71
  .setup-method-toggle {
72
72
  display: grid;
73
- grid-template-columns: 1fr 1fr;
73
+ grid-template-columns: repeat(3, minmax(0, 1fr));
74
74
  gap: 0.5rem;
75
75
  border: none;
76
76
  padding: 0;
@@ -162,6 +162,41 @@
162
162
  margin-bottom: 1.2rem;
163
163
  }
164
164
 
165
+ .setup-permissions-intro {
166
+ display: grid;
167
+ gap: 1.2rem;
168
+ margin-bottom: 1.2rem;
169
+ }
170
+
171
+ .setup-permissions-intro[hidden] {
172
+ display: none !important;
173
+ }
174
+
175
+ .setup-permissions-note {
176
+ padding: 1rem 1.2rem;
177
+ border: 1px solid var(--line);
178
+ border-radius: var(--radius-md);
179
+ background: var(--surface-2);
180
+ min-width: 0;
181
+ overflow: hidden;
182
+ }
183
+
184
+ .setup-permissions-note strong {
185
+ display: block;
186
+ font-family: var(--font-heading);
187
+ font-size: var(--step-0);
188
+ font-weight: 700;
189
+ color: var(--ink-950);
190
+ margin-bottom: 0.35rem;
191
+ }
192
+
193
+ .setup-permissions-note p {
194
+ margin: 0;
195
+ color: var(--ink-700);
196
+ font-size: var(--step--1);
197
+ line-height: 1.55;
198
+ }
199
+
165
200
  .setup-method h4 {
166
201
  font-family: var(--font-heading);
167
202
  font-size: var(--step-0);
@@ -217,6 +252,7 @@
217
252
  .setup-panel {
218
253
  display: grid;
219
254
  gap: 1.2rem;
255
+ min-width: 0;
220
256
  }
221
257
 
222
258
  .setup-panel[hidden] {
@@ -230,6 +266,7 @@
230
266
  border: 1px solid var(--line);
231
267
  border-radius: var(--radius-md);
232
268
  padding: 1.2rem 1.4rem;
269
+ min-width: 0;
233
270
  }
234
271
 
235
272
  .setup-method-primary {
@@ -259,6 +296,131 @@
259
296
  margin-bottom: 0;
260
297
  }
261
298
 
299
+ .setup-security-mode code {
300
+ word-break: break-word;
301
+ }
302
+
303
+ .setup-security-mode {
304
+ min-width: 0;
305
+ overflow: hidden;
306
+ }
307
+
308
+ .setup-manual-fallback {
309
+ border: 1px solid var(--line);
310
+ border-radius: var(--radius-sm);
311
+ background: var(--surface-1);
312
+ overflow: hidden;
313
+ }
314
+
315
+ .setup-manual-fallback summary {
316
+ cursor: pointer;
317
+ list-style: none;
318
+ padding: 0.9rem 1rem;
319
+ font-family: var(--font-heading);
320
+ font-size: var(--step-0);
321
+ font-weight: 600;
322
+ color: var(--ink-900);
323
+ }
324
+
325
+ .setup-manual-fallback summary::-webkit-details-marker {
326
+ display: none;
327
+ }
328
+
329
+ .setup-manual-fallback summary::after {
330
+ content: '+';
331
+ float: right;
332
+ color: var(--ink-500);
333
+ }
334
+
335
+ .setup-manual-fallback[open] summary::after {
336
+ content: '-';
337
+ }
338
+
339
+ .setup-manual-fallback-body {
340
+ padding: 0 1rem 1rem;
341
+ border-top: 1px solid var(--line);
342
+ }
343
+
344
+ .setup-permission-status {
345
+ margin: 0 0 0.8rem;
346
+ padding: 0.85rem 1rem;
347
+ border-radius: var(--radius-sm);
348
+ border: 1px solid var(--line);
349
+ background: color-mix(in srgb, var(--surface-1) 85%, white);
350
+ }
351
+
352
+ .setup-permission-status-title {
353
+ display: block;
354
+ margin-bottom: 0.3rem;
355
+ color: var(--ink-900);
356
+ }
357
+
358
+ .setup-permission-status-msg {
359
+ margin: 0;
360
+ color: var(--ink-700);
361
+ }
362
+
363
+ .setup-permission-status[data-state="warning"] {
364
+ border-color: color-mix(in srgb, #f59e0b 40%, var(--line));
365
+ background: color-mix(in srgb, #f59e0b 10%, var(--surface-2));
366
+ }
367
+
368
+ .setup-permission-status[data-state="warning"] .setup-permission-status-title {
369
+ color: #b45309;
370
+ }
371
+
372
+ .setup-permission-status[data-state="info"] {
373
+ border-color: color-mix(in srgb, var(--signal) 30%, var(--line));
374
+ background: color-mix(in srgb, var(--signal-2) 10%, var(--surface-2));
375
+ }
376
+
377
+ .setup-permission-status[data-state="info"] .setup-permission-status-title {
378
+ color: var(--signal);
379
+ }
380
+
381
+ [data-theme="dark"] .setup-permission-status[data-state="warning"] .setup-permission-status-title {
382
+ color: #fbbf24;
383
+ }
384
+
385
+ .setup-support-badge {
386
+ display: inline-flex;
387
+ align-items: center;
388
+ margin-left: 0.45rem;
389
+ padding: 0.18rem 0.5rem;
390
+ border-radius: 999px;
391
+ font-family: var(--font-mono);
392
+ font-size: 0.7rem;
393
+ font-weight: 700;
394
+ text-transform: uppercase;
395
+ letter-spacing: 0.02em;
396
+ }
397
+
398
+ .setup-support-badge--verified {
399
+ background: color-mix(in srgb, #22c55e 18%, var(--surface-2));
400
+ color: #15803d;
401
+ border: 1px solid color-mix(in srgb, #22c55e 45%, var(--line));
402
+ }
403
+
404
+ .setup-support-badge--manual {
405
+ background: color-mix(in srgb, #f59e0b 14%, var(--surface-2));
406
+ color: #b45309;
407
+ border: 1px solid color-mix(in srgb, #f59e0b 40%, var(--line));
408
+ }
409
+
410
+ .setup-support-badge--unsupported {
411
+ background: color-mix(in srgb, #64748b 14%, var(--surface-2));
412
+ color: var(--ink-600);
413
+ border: 1px solid color-mix(in srgb, #64748b 35%, var(--line));
414
+ }
415
+
416
+ [data-theme="dark"] .setup-support-badge--verified {
417
+ color: #4ade80;
418
+ }
419
+
420
+ [data-theme="dark"] .setup-support-badge--manual {
421
+ color: #fbbf24;
422
+ }
423
+
262
424
  .setup-paths {
263
425
  list-style: none;
264
426
  margin: 0 0 0.8rem;
@@ -292,6 +454,8 @@
292
454
  .setup-code-block {
293
455
  position: relative;
294
456
  margin: 0.5rem 0;
457
+ min-width: 0;
458
+ max-width: 100%;
295
459
  }
296
460
 
297
461
  .setup-code-block pre {
@@ -307,6 +471,9 @@
307
471
  overflow-x: auto;
308
472
  white-space: pre;
309
473
  tab-size: 2;
474
+ max-width: 100%;
475
+ min-width: 0;
476
+ box-sizing: border-box;
310
477
  }
311
478
 
312
479
  [data-theme="dark"] .setup-code-block pre {
@@ -667,6 +834,10 @@
667
834
  padding: 1rem;
668
835
  }
669
836
 
837
+ .setup-method-toggle {
838
+ grid-template-columns: 1fr;
839
+ }
840
+
670
841
  .setup-platforms {
671
842
  gap: 0.25rem;
672
843
  }