@cyanmycelium/mcp-broker 0.4.0 → 1.2.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.
Files changed (151) hide show
  1. package/.mcp-broker.example/CONFIGURATION-EN.md +861 -0
  2. package/.mcp-broker.example/CONFIGURATION-FR.md +871 -0
  3. package/.mcp-broker.example/README.md +8 -3
  4. package/.mcp-broker.example/config.json +86 -0
  5. package/README.md +122 -3
  6. package/dist/bin.d.ts +0 -1
  7. package/dist/bin.js +180 -208
  8. package/dist/bin.js.map +1 -1
  9. package/dist/chunk-FTDKH2C4.js +3670 -0
  10. package/dist/chunk-FTDKH2C4.js.map +1 -0
  11. package/dist/{broker/grammars → grammars}/claude/en.json +1 -1
  12. package/dist/{broker/grammars → grammars}/claude/fr.json +1 -1
  13. package/dist/index.d.ts +1790 -18
  14. package/dist/index.js +2 -14
  15. package/dist/index.js.map +1 -1
  16. package/package.json +14 -8
  17. package/scripts/copy-assets.mjs +16 -10
  18. package/scripts/gen-cert.mjs +5 -5
  19. package/scripts/pack-mcpb.mjs +5 -5
  20. package/scripts/sign-bundle.mjs +6 -6
  21. package/src/auth/auth.config.ts +98 -0
  22. package/src/auth/auth.types.ts +120 -0
  23. package/src/auth/http.auth.ts +128 -0
  24. package/src/auth/index.ts +34 -0
  25. package/src/auth/jwt.validator.ts +63 -0
  26. package/src/auth/provider.auth.ts +114 -0
  27. package/src/auth/resource.metadata.ts +34 -0
  28. package/src/authorization/audit.ts +35 -0
  29. package/src/authorization/capability.classifier.ts +114 -0
  30. package/src/authorization/index.ts +37 -0
  31. package/src/authorization/policy.engine.ts +212 -0
  32. package/src/authorization/policy.types.ts +105 -0
  33. package/src/authorization/resource.path.ts +126 -0
  34. package/src/authorization/runtime.ts +56 -0
  35. package/src/authorization/slot.resource.ts +50 -0
  36. package/src/authorization/subject.mapper.ts +81 -0
  37. package/src/bin.ts +90 -7
  38. package/src/broker/adapters/broker.adapter.info.ts +3 -3
  39. package/src/broker/adapters/broker.adapter.providers.ts +3 -3
  40. package/src/broker/aggregate/aggregate.catalog.ts +49 -21
  41. package/src/broker/aggregate/aggregate.server.ts +149 -19
  42. package/src/broker/aggregate/provider.client.session.ts +22 -22
  43. package/src/broker/behaviors/broker.behavior.info.ts +4 -4
  44. package/src/broker/behaviors/broker.behavior.providers.ts +6 -6
  45. package/src/broker/broker.context.ts +10 -4
  46. package/src/broker/broker.grammars.ts +16 -13
  47. package/src/broker/broker.server.ts +12 -9
  48. package/src/broker/grammars/claude/en.json +1 -1
  49. package/src/broker/grammars/claude/fr.json +1 -1
  50. package/src/broker/index.ts +9 -9
  51. package/src/config.ts +81 -8
  52. package/src/index.ts +121 -20
  53. package/src/{mcpb.loader.ts → mcpb/mcpb.loader.ts} +24 -21
  54. package/src/{mcpb.unzip.ts → mcpb/mcpb.unzip.ts} +2 -2
  55. package/src/remote.transports.ts +11 -8
  56. package/src/remote.upstream.ts +11 -8
  57. package/src/stdio.upstream.ts +9 -6
  58. package/src/upstream.ts +6 -3
  59. package/src/ws/ws.interfaces.ts +357 -0
  60. package/src/{ws.tunnel.builder.ts → ws/ws.tunnel.builder.ts} +112 -9
  61. package/src/{ws.tunnel.ts → ws/ws.tunnel.ts} +646 -457
  62. package/web/README.md +94 -0
  63. package/web/assets/logo.png +0 -0
  64. package/web/broker-self-mcp.html +338 -0
  65. package/web/css/styles.css +580 -0
  66. package/web/demos/DemoPlaceholder.html +258 -0
  67. package/web/demos/broker-explorer/css/app.css +393 -0
  68. package/web/demos/broker-explorer/index.html +94 -0
  69. package/web/demos/broker-explorer/js/app.js +271 -0
  70. package/web/demos/broker-explorer/js/mcp-ws-client.js +132 -0
  71. package/web/demos/oauth-lab/README.md +94 -0
  72. package/web/demos/oauth-lab/config.json +117 -0
  73. package/web/demos/oauth-lab/css/app.css +1097 -0
  74. package/web/demos/oauth-lab/index.html +323 -0
  75. package/web/demos/oauth-lab/js/app.js +654 -0
  76. package/web/demos/oauth-lab/server/auth-server.mjs +426 -0
  77. package/web/demos/oauth-lab/server/factory-provider.mjs +269 -0
  78. package/web/demos/oauth-lab/server/smoke-test.mjs +308 -0
  79. package/web/demos/oauth-lab/server/start.mjs +106 -0
  80. package/web/demos/provider-tunnel/css/app.css +384 -0
  81. package/web/demos/provider-tunnel/index.html +99 -0
  82. package/web/demos/provider-tunnel/js/app.js +226 -0
  83. package/web/demos/provider-tunnel/js/toolbox-server.js +186 -0
  84. package/web/index.html +558 -0
  85. package/web/js/lib/broker-tunnel.js +173 -0
  86. package/dist/broker/adapters/broker.adapter.info.d.ts +0 -16
  87. package/dist/broker/adapters/broker.adapter.info.js +0 -43
  88. package/dist/broker/adapters/broker.adapter.info.js.map +0 -1
  89. package/dist/broker/adapters/broker.adapter.providers.d.ts +0 -18
  90. package/dist/broker/adapters/broker.adapter.providers.js +0 -61
  91. package/dist/broker/adapters/broker.adapter.providers.js.map +0 -1
  92. package/dist/broker/aggregate/aggregate.catalog.d.ts +0 -54
  93. package/dist/broker/aggregate/aggregate.catalog.js +0 -105
  94. package/dist/broker/aggregate/aggregate.catalog.js.map +0 -1
  95. package/dist/broker/aggregate/aggregate.server.d.ts +0 -47
  96. package/dist/broker/aggregate/aggregate.server.js +0 -151
  97. package/dist/broker/aggregate/aggregate.server.js.map +0 -1
  98. package/dist/broker/aggregate/provider.client.session.d.ts +0 -52
  99. package/dist/broker/aggregate/provider.client.session.js +0 -140
  100. package/dist/broker/aggregate/provider.client.session.js.map +0 -1
  101. package/dist/broker/behaviors/broker.behavior.info.d.ts +0 -15
  102. package/dist/broker/behaviors/broker.behavior.info.js +0 -41
  103. package/dist/broker/behaviors/broker.behavior.info.js.map +0 -1
  104. package/dist/broker/behaviors/broker.behavior.providers.d.ts +0 -19
  105. package/dist/broker/behaviors/broker.behavior.providers.js +0 -69
  106. package/dist/broker/behaviors/broker.behavior.providers.js.map +0 -1
  107. package/dist/broker/broker.context.d.ts +0 -59
  108. package/dist/broker/broker.context.js +0 -2
  109. package/dist/broker/broker.context.js.map +0 -1
  110. package/dist/broker/broker.grammars.d.ts +0 -130
  111. package/dist/broker/broker.grammars.js +0 -229
  112. package/dist/broker/broker.grammars.js.map +0 -1
  113. package/dist/broker/broker.server.d.ts +0 -66
  114. package/dist/broker/broker.server.js +0 -73
  115. package/dist/broker/broker.server.js.map +0 -1
  116. package/dist/broker/index.d.ts +0 -9
  117. package/dist/broker/index.js +0 -7
  118. package/dist/broker/index.js.map +0 -1
  119. package/dist/config.d.ts +0 -136
  120. package/dist/config.js +0 -61
  121. package/dist/config.js.map +0 -1
  122. package/dist/mcpb.loader.d.ts +0 -24
  123. package/dist/mcpb.loader.js +0 -161
  124. package/dist/mcpb.loader.js.map +0 -1
  125. package/dist/mcpb.unzip.d.ts +0 -6
  126. package/dist/mcpb.unzip.js +0 -95
  127. package/dist/mcpb.unzip.js.map +0 -1
  128. package/dist/remote.transports.d.ts +0 -16
  129. package/dist/remote.transports.js +0 -297
  130. package/dist/remote.transports.js.map +0 -1
  131. package/dist/remote.upstream.d.ts +0 -36
  132. package/dist/remote.upstream.js +0 -52
  133. package/dist/remote.upstream.js.map +0 -1
  134. package/dist/stdio.upstream.d.ts +0 -45
  135. package/dist/stdio.upstream.js +0 -85
  136. package/dist/stdio.upstream.js.map +0 -1
  137. package/dist/upstream.d.ts +0 -33
  138. package/dist/upstream.js +0 -2
  139. package/dist/upstream.js.map +0 -1
  140. package/dist/version.d.ts +0 -2
  141. package/dist/version.js +0 -9
  142. package/dist/version.js.map +0 -1
  143. package/dist/ws.tunnel.builder.d.ts +0 -139
  144. package/dist/ws.tunnel.builder.js +0 -205
  145. package/dist/ws.tunnel.builder.js.map +0 -1
  146. package/dist/ws.tunnel.d.ts +0 -373
  147. package/dist/ws.tunnel.js +0 -1090
  148. package/dist/ws.tunnel.js.map +0 -1
  149. /package/dist/{broker/grammars → grammars}/default/en.json +0 -0
  150. /package/dist/{broker/grammars → grammars}/default/fr.json +0 -0
  151. /package/dist/{broker/grammars → grammars}/default/zh.json +0 -0
@@ -0,0 +1,1097 @@
1
+ :root {
2
+ --amber: #ffbd72;
3
+ --red: #ff7f72;
4
+ --green: #72d69c;
5
+ --violet: #b8a1ff;
6
+ --panel: #0f151e;
7
+ --panel-high: #141c28;
8
+ --code: #090d13;
9
+ --col: 1480px;
10
+ }
11
+
12
+ html {
13
+ scroll-behavior: smooth;
14
+ }
15
+
16
+ body {
17
+ min-height: 100vh;
18
+ font-size: 14px;
19
+ background:
20
+ radial-gradient(circle at 13% -10%, rgba(59, 130, 246, 0.12), transparent 32rem), radial-gradient(circle at 93% 20%, rgba(184, 161, 255, 0.06), transparent 30rem),
21
+ var(--bg);
22
+ }
23
+
24
+ button,
25
+ input {
26
+ font: inherit;
27
+ }
28
+
29
+ button {
30
+ color: inherit;
31
+ }
32
+
33
+ .hidden {
34
+ display: none !important;
35
+ }
36
+
37
+ .sr-only {
38
+ position: absolute;
39
+ width: 1px;
40
+ height: 1px;
41
+ padding: 0;
42
+ margin: -1px;
43
+ overflow: hidden;
44
+ clip: rect(0, 0, 0, 0);
45
+ white-space: nowrap;
46
+ border: 0;
47
+ }
48
+
49
+ .lab-topbar {
50
+ height: 58px;
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 16px;
54
+ padding: 0 24px;
55
+ }
56
+
57
+ .lab-topbar .brand:hover,
58
+ .lab-topbar .topbar-link:hover {
59
+ text-decoration: none;
60
+ }
61
+
62
+ .topbar-tag {
63
+ padding: 3px 8px;
64
+ border: 1px solid var(--rule-strong);
65
+ border-radius: 4px;
66
+ color: var(--blue-bright);
67
+ font: 600 10px var(--font-mono);
68
+ letter-spacing: 0.12em;
69
+ text-transform: uppercase;
70
+ }
71
+
72
+ .topbar-spacer {
73
+ flex: 1;
74
+ }
75
+
76
+ .topbar-link {
77
+ color: var(--fg-muted);
78
+ font-size: 12px;
79
+ }
80
+
81
+ .service-status {
82
+ display: flex;
83
+ gap: 7px;
84
+ }
85
+
86
+ .service-pill {
87
+ display: inline-flex;
88
+ align-items: center;
89
+ gap: 6px;
90
+ padding: 4px 8px;
91
+ border: 1px solid var(--rule);
92
+ border-radius: 99px;
93
+ color: var(--fg-dim);
94
+ font: 10px var(--font-mono);
95
+ letter-spacing: 0.06em;
96
+ text-transform: uppercase;
97
+ }
98
+
99
+ .service-pill i {
100
+ width: 6px;
101
+ height: 6px;
102
+ border-radius: 50%;
103
+ background: currentColor;
104
+ }
105
+
106
+ .service-pill.online {
107
+ color: var(--green);
108
+ border-color: rgba(114, 214, 156, 0.28);
109
+ background: rgba(114, 214, 156, 0.05);
110
+ }
111
+
112
+ .service-pill.offline {
113
+ color: var(--red);
114
+ border-color: rgba(255, 127, 114, 0.28);
115
+ }
116
+
117
+ .service-pill.checking i {
118
+ animation: blink 1s infinite alternate;
119
+ }
120
+
121
+ @keyframes blink {
122
+ to {
123
+ opacity: 0.25;
124
+ }
125
+ }
126
+
127
+ .lab-shell {
128
+ width: min(1480px, calc(100% - 40px));
129
+ margin: 0 auto;
130
+ padding: 54px 0 80px;
131
+ }
132
+
133
+ .lab-hero {
134
+ display: grid;
135
+ grid-template-columns: minmax(0, 1fr) auto;
136
+ gap: 48px;
137
+ align-items: end;
138
+ padding: 0 4px 38px;
139
+ }
140
+
141
+ .lab-hero h1 {
142
+ max-width: 820px;
143
+ margin: 5px 0 14px;
144
+ color: var(--fg);
145
+ font: 500 clamp(34px, 5vw, 64px) / 1.04 var(--font-mono);
146
+ letter-spacing: -0.055em;
147
+ }
148
+
149
+ .lab-hero p {
150
+ max-width: 800px;
151
+ margin: 0;
152
+ color: var(--fg-muted);
153
+ font-size: 16px;
154
+ line-height: 1.7;
155
+ }
156
+
157
+ .hero-proof {
158
+ width: 180px;
159
+ display: flex;
160
+ flex-wrap: wrap;
161
+ justify-content: flex-end;
162
+ gap: 7px;
163
+ }
164
+
165
+ .hero-proof span {
166
+ padding: 5px 8px;
167
+ border: 1px solid var(--rule-strong);
168
+ border-radius: 4px;
169
+ background: rgba(17, 22, 29, 0.75);
170
+ color: var(--fg-muted);
171
+ font: 10px var(--font-mono);
172
+ }
173
+
174
+ .hero-proof code {
175
+ width: 100%;
176
+ padding: 8px 10px;
177
+ border: 1px solid rgba(59, 130, 246, 0.38);
178
+ border-radius: 5px;
179
+ background: rgba(59, 130, 246, 0.09);
180
+ color: var(--blue-bright);
181
+ font: 10px var(--font-mono);
182
+ text-align: center;
183
+ }
184
+
185
+ .flow {
186
+ display: grid;
187
+ grid-template-columns: repeat(4, 1fr);
188
+ margin: 0 0 16px;
189
+ padding: 0;
190
+ list-style: none;
191
+ border: 1px solid var(--rule-strong);
192
+ border-radius: 10px;
193
+ background: rgba(15, 21, 30, 0.88);
194
+ overflow: hidden;
195
+ }
196
+
197
+ .flow li {
198
+ min-height: 76px;
199
+ display: flex;
200
+ align-items: center;
201
+ gap: 13px;
202
+ padding: 14px 18px;
203
+ border-right: 1px solid var(--rule);
204
+ transition: background 0.2s;
205
+ }
206
+
207
+ .flow li:last-child {
208
+ border-right: 0;
209
+ }
210
+
211
+ .flow li.complete {
212
+ background: rgba(59, 130, 246, 0.06);
213
+ }
214
+
215
+ .flow li.complete .flow-number {
216
+ color: var(--green);
217
+ border-color: rgba(114, 214, 156, 0.35);
218
+ }
219
+
220
+ .flow-number {
221
+ width: 31px;
222
+ height: 31px;
223
+ display: grid;
224
+ flex: 0 0 auto;
225
+ place-items: center;
226
+ border: 1px solid var(--rule-strong);
227
+ border-radius: 50%;
228
+ color: var(--blue-bright);
229
+ font: 10px var(--font-mono);
230
+ }
231
+
232
+ .flow li > span:last-child {
233
+ display: grid;
234
+ gap: 3px;
235
+ }
236
+
237
+ .flow b {
238
+ font-size: 13px;
239
+ font-weight: 600;
240
+ }
241
+
242
+ .flow small {
243
+ color: var(--fg-dim);
244
+ font: 10px var(--font-mono);
245
+ }
246
+
247
+ .workspace {
248
+ display: grid;
249
+ grid-template-columns: minmax(360px, 0.8fr) minmax(620px, 1.45fr);
250
+ gap: 16px;
251
+ align-items: start;
252
+ }
253
+
254
+ .panel {
255
+ border: 1px solid var(--rule-strong);
256
+ border-radius: 10px;
257
+ background: rgba(15, 21, 30, 0.94);
258
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
259
+ }
260
+
261
+ .setup-panel,
262
+ .actions-panel {
263
+ padding: 22px;
264
+ }
265
+
266
+ .panel-heading,
267
+ .section-heading-row {
268
+ display: flex;
269
+ align-items: flex-start;
270
+ justify-content: space-between;
271
+ gap: 20px;
272
+ }
273
+
274
+ .panel-heading.compact {
275
+ align-items: center;
276
+ }
277
+
278
+ .section-kicker {
279
+ display: block;
280
+ margin-bottom: 5px;
281
+ color: var(--blue-bright);
282
+ font: 10px var(--font-mono);
283
+ letter-spacing: 0.13em;
284
+ text-transform: uppercase;
285
+ }
286
+
287
+ .panel h2,
288
+ .policy-section h2,
289
+ .audit-section h2 {
290
+ margin: 0;
291
+ color: var(--fg);
292
+ font: 500 18px var(--font-mono);
293
+ letter-spacing: -0.025em;
294
+ }
295
+
296
+ .quiet-button,
297
+ .primary-button {
298
+ appearance: none;
299
+ border-radius: 6px;
300
+ cursor: pointer;
301
+ transition:
302
+ border-color 0.15s,
303
+ background 0.15s,
304
+ transform 0.15s;
305
+ }
306
+
307
+ .quiet-button {
308
+ padding: 7px 10px;
309
+ border: 1px solid var(--rule-strong);
310
+ background: var(--bg-elev-1);
311
+ color: var(--fg-muted);
312
+ font: 10px var(--font-mono);
313
+ letter-spacing: 0.07em;
314
+ text-transform: uppercase;
315
+ }
316
+
317
+ .quiet-button:hover,
318
+ .quiet-button:focus-visible {
319
+ border-color: var(--blue-dim);
320
+ color: var(--fg);
321
+ outline: none;
322
+ }
323
+
324
+ .quiet-button.danger:hover {
325
+ border-color: rgba(255, 127, 114, 0.5);
326
+ color: var(--red);
327
+ }
328
+
329
+ .resource-list {
330
+ display: grid;
331
+ gap: 8px;
332
+ margin: 20px 0 0;
333
+ padding: 0;
334
+ border: 0;
335
+ }
336
+
337
+ .resource-option {
338
+ position: relative;
339
+ display: grid;
340
+ grid-template-columns: 38px 1fr 12px;
341
+ gap: 11px;
342
+ align-items: center;
343
+ padding: 11px 12px;
344
+ border: 1px solid var(--rule);
345
+ border-radius: 7px;
346
+ background: var(--bg-elev-1);
347
+ cursor: pointer;
348
+ transition:
349
+ border-color 0.15s,
350
+ background 0.15s;
351
+ }
352
+
353
+ .resource-option:has(input:checked) {
354
+ border-color: rgba(59, 130, 246, 0.68);
355
+ background: rgba(59, 130, 246, 0.07);
356
+ }
357
+
358
+ .resource-option input {
359
+ position: absolute;
360
+ opacity: 0;
361
+ }
362
+
363
+ .resource-option > span:nth-child(3) {
364
+ min-width: 0;
365
+ display: grid;
366
+ }
367
+
368
+ .resource-option b {
369
+ font-size: 13px;
370
+ font-weight: 600;
371
+ }
372
+
373
+ .resource-option small {
374
+ overflow: hidden;
375
+ color: var(--fg-dim);
376
+ font: 9px var(--font-mono);
377
+ text-overflow: ellipsis;
378
+ white-space: nowrap;
379
+ }
380
+
381
+ .resource-option > i {
382
+ width: 8px;
383
+ height: 8px;
384
+ border: 1px solid var(--rule-strong);
385
+ border-radius: 50%;
386
+ }
387
+
388
+ .resource-option:has(input:checked) > i {
389
+ border-color: var(--blue);
390
+ background: var(--blue);
391
+ box-shadow: 0 0 9px var(--blue);
392
+ }
393
+
394
+ .resource-icon {
395
+ width: 38px;
396
+ height: 34px;
397
+ display: grid;
398
+ place-items: center;
399
+ border: 1px solid rgba(59, 130, 246, 0.3);
400
+ border-radius: 5px;
401
+ background: rgba(59, 130, 246, 0.08);
402
+ color: var(--blue-bright);
403
+ font: 600 10px var(--font-mono);
404
+ }
405
+
406
+ .resource-icon.critical {
407
+ border-color: rgba(255, 127, 114, 0.3);
408
+ background: rgba(255, 127, 114, 0.07);
409
+ color: var(--red);
410
+ }
411
+
412
+ .resource-icon.energy {
413
+ border-color: rgba(184, 224, 96, 0.3);
414
+ background: rgba(184, 224, 96, 0.07);
415
+ color: var(--lime);
416
+ }
417
+
418
+ .resource-icon.system {
419
+ border-color: rgba(184, 161, 255, 0.3);
420
+ background: rgba(184, 161, 255, 0.07);
421
+ color: var(--violet);
422
+ }
423
+
424
+ .metadata-card {
425
+ min-height: 86px;
426
+ margin-top: 14px;
427
+ padding: 13px;
428
+ border: 1px dashed var(--rule-strong);
429
+ border-radius: 7px;
430
+ background: var(--code);
431
+ }
432
+
433
+ .metadata-empty {
434
+ display: flex;
435
+ align-items: center;
436
+ gap: 11px;
437
+ color: var(--fg-dim);
438
+ }
439
+
440
+ .metadata-empty p {
441
+ margin: 0;
442
+ line-height: 1.5;
443
+ }
444
+
445
+ .metadata-mark {
446
+ width: 28px;
447
+ height: 28px;
448
+ display: grid;
449
+ flex: 0 0 auto;
450
+ place-items: center;
451
+ border: 1px solid var(--rule-strong);
452
+ border-radius: 50%;
453
+ color: var(--blue-bright);
454
+ font: 12px var(--font-mono);
455
+ }
456
+
457
+ .metadata-values {
458
+ display: grid;
459
+ gap: 7px;
460
+ margin: 0;
461
+ }
462
+
463
+ .metadata-values div {
464
+ display: grid;
465
+ grid-template-columns: 92px 1fr;
466
+ gap: 8px;
467
+ }
468
+
469
+ .metadata-values dt {
470
+ color: var(--fg-dim);
471
+ font: 9px var(--font-mono);
472
+ letter-spacing: 0.08em;
473
+ text-transform: uppercase;
474
+ }
475
+
476
+ .metadata-values dd {
477
+ min-width: 0;
478
+ margin: 0;
479
+ overflow-wrap: anywhere;
480
+ color: var(--fg-muted);
481
+ font: 10px / 1.45 var(--font-mono);
482
+ }
483
+
484
+ .session-card {
485
+ margin-top: 22px;
486
+ padding-top: 20px;
487
+ border-top: 1px solid var(--rule);
488
+ }
489
+
490
+ .muted,
491
+ .panel-intro {
492
+ color: var(--fg-muted);
493
+ line-height: 1.6;
494
+ }
495
+
496
+ .primary-button {
497
+ width: 100%;
498
+ display: flex;
499
+ align-items: center;
500
+ justify-content: space-between;
501
+ margin-top: 14px;
502
+ padding: 12px 14px;
503
+ border: 1px solid var(--blue-dim);
504
+ background: rgba(59, 130, 246, 0.13);
505
+ color: var(--fg);
506
+ font: 600 11px var(--font-mono);
507
+ }
508
+
509
+ .primary-button:hover,
510
+ .primary-button:focus-visible {
511
+ background: rgba(59, 130, 246, 0.2);
512
+ transform: translateY(-1px);
513
+ outline: none;
514
+ }
515
+
516
+ .primary-button:disabled {
517
+ cursor: wait;
518
+ opacity: 0.55;
519
+ transform: none;
520
+ }
521
+
522
+ .primary-button b {
523
+ color: var(--blue-bright);
524
+ }
525
+
526
+ .identity-row {
527
+ display: grid;
528
+ grid-template-columns: 40px 1fr auto;
529
+ gap: 11px;
530
+ align-items: center;
531
+ margin: 16px 0 14px;
532
+ }
533
+
534
+ .identity-avatar {
535
+ width: 40px;
536
+ height: 40px;
537
+ display: grid;
538
+ place-items: center;
539
+ border: 1px solid rgba(59, 130, 246, 0.35);
540
+ border-radius: 7px;
541
+ background: rgba(59, 130, 246, 0.09);
542
+ color: var(--blue-bright);
543
+ font: 600 11px var(--font-mono);
544
+ }
545
+
546
+ .identity-row > span:nth-child(2) {
547
+ display: grid;
548
+ }
549
+
550
+ .identity-row b {
551
+ font-size: 13px;
552
+ }
553
+
554
+ .identity-row small {
555
+ color: var(--fg-dim);
556
+ font: 10px var(--font-mono);
557
+ }
558
+
559
+ .token-valid {
560
+ padding: 4px 7px;
561
+ border: 1px solid rgba(114, 214, 156, 0.3);
562
+ border-radius: 99px;
563
+ background: rgba(114, 214, 156, 0.06);
564
+ color: var(--green);
565
+ font: 9px var(--font-mono);
566
+ text-transform: uppercase;
567
+ }
568
+
569
+ .token-valid.mismatch {
570
+ border-color: rgba(255, 127, 114, 0.3);
571
+ background: rgba(255, 127, 114, 0.06);
572
+ color: var(--red);
573
+ }
574
+
575
+ .audience-notice {
576
+ margin: 0 0 14px;
577
+ padding: 10px;
578
+ border: 1px solid rgba(255, 188, 92, 0.32);
579
+ border-radius: 6px;
580
+ background: rgba(255, 188, 92, 0.06);
581
+ }
582
+
583
+ .audience-notice p {
584
+ margin: 0;
585
+ color: var(--fg-muted);
586
+ font: 10px/1.55 var(--font-mono);
587
+ }
588
+
589
+ .audience-notice .primary-button {
590
+ width: 100%;
591
+ margin-top: 9px;
592
+ }
593
+
594
+ .claims-grid {
595
+ display: grid;
596
+ gap: 1px;
597
+ margin: 0;
598
+ border: 1px solid var(--rule);
599
+ border-radius: 6px;
600
+ background: var(--rule);
601
+ overflow: hidden;
602
+ }
603
+
604
+ .claims-grid div {
605
+ min-width: 0;
606
+ display: grid;
607
+ grid-template-columns: 62px 1fr;
608
+ gap: 8px;
609
+ padding: 7px 9px;
610
+ background: var(--bg-elev-1);
611
+ }
612
+
613
+ .claims-grid dt {
614
+ color: var(--blue-bright);
615
+ font: 9px var(--font-mono);
616
+ }
617
+
618
+ .claims-grid dd {
619
+ min-width: 0;
620
+ margin: 0;
621
+ overflow: hidden;
622
+ color: var(--fg-muted);
623
+ font: 9px var(--font-mono);
624
+ text-overflow: ellipsis;
625
+ white-space: nowrap;
626
+ }
627
+
628
+ .token-details {
629
+ margin-top: 9px;
630
+ }
631
+
632
+ .token-details summary {
633
+ color: var(--fg-dim);
634
+ font: 9px var(--font-mono);
635
+ cursor: pointer;
636
+ }
637
+
638
+ .token-details pre {
639
+ max-height: 190px;
640
+ margin: 8px 0 0;
641
+ padding: 10px;
642
+ overflow: auto;
643
+ border: 1px solid var(--rule);
644
+ border-radius: 5px;
645
+ background: var(--code);
646
+ color: var(--fg-muted);
647
+ font: 9px / 1.5 var(--font-mono);
648
+ }
649
+
650
+ .target-slot {
651
+ padding: 5px 8px;
652
+ border: 1px solid var(--rule-strong);
653
+ border-radius: 4px;
654
+ color: var(--blue-bright);
655
+ font: 10px var(--font-mono);
656
+ }
657
+
658
+ .panel-intro {
659
+ max-width: 760px;
660
+ margin: 15px 0 18px;
661
+ }
662
+
663
+ .action-grid {
664
+ display: grid;
665
+ grid-template-columns: repeat(2, minmax(0, 1fr));
666
+ gap: 8px;
667
+ }
668
+
669
+ .action-card {
670
+ position: relative;
671
+ min-height: 104px;
672
+ display: grid;
673
+ align-content: start;
674
+ gap: 4px;
675
+ padding: 13px 118px 13px 13px;
676
+ appearance: none;
677
+ border: 1px solid var(--rule);
678
+ border-radius: 7px;
679
+ background: var(--bg-elev-1);
680
+ text-align: left;
681
+ cursor: pointer;
682
+ transition:
683
+ border-color 0.15s,
684
+ background 0.15s,
685
+ transform 0.15s;
686
+ }
687
+
688
+ .action-card:hover,
689
+ .action-card:focus-visible {
690
+ border-color: var(--blue-dim);
691
+ background: var(--panel-high);
692
+ transform: translateY(-1px);
693
+ outline: none;
694
+ }
695
+
696
+ .action-card:disabled {
697
+ cursor: wait;
698
+ opacity: 0.6;
699
+ transform: none;
700
+ }
701
+
702
+ .action-method {
703
+ color: var(--blue-bright);
704
+ font: 9px var(--font-mono);
705
+ }
706
+
707
+ .action-card b {
708
+ font-size: 13px;
709
+ }
710
+
711
+ .action-card small {
712
+ color: var(--fg-dim);
713
+ font-size: 11px;
714
+ line-height: 1.45;
715
+ }
716
+
717
+ .expect {
718
+ position: absolute;
719
+ top: 12px;
720
+ right: 11px;
721
+ max-width: 98px;
722
+ padding: 4px 6px;
723
+ border: 1px solid var(--rule-strong);
724
+ border-radius: 4px;
725
+ color: var(--fg-dim);
726
+ font: 8px var(--font-mono);
727
+ text-align: center;
728
+ text-transform: uppercase;
729
+ }
730
+
731
+ .expect.allow {
732
+ border-color: rgba(114, 214, 156, 0.3);
733
+ color: var(--green);
734
+ }
735
+
736
+ .expect.deny {
737
+ border-color: rgba(255, 127, 114, 0.3);
738
+ color: var(--red);
739
+ }
740
+
741
+ .console-card {
742
+ margin-top: 14px;
743
+ border: 1px solid var(--rule-strong);
744
+ border-radius: 8px;
745
+ background: var(--code);
746
+ overflow: hidden;
747
+ }
748
+
749
+ .console-head {
750
+ min-height: 40px;
751
+ display: flex;
752
+ align-items: center;
753
+ justify-content: space-between;
754
+ padding: 0 13px;
755
+ border-bottom: 1px solid var(--rule);
756
+ color: var(--fg-dim);
757
+ font: 9px var(--font-mono);
758
+ }
759
+
760
+ .console-head > span:first-child {
761
+ display: flex;
762
+ align-items: center;
763
+ gap: 7px;
764
+ }
765
+
766
+ .console-head i {
767
+ width: 7px;
768
+ height: 7px;
769
+ border-radius: 50%;
770
+ background: var(--fg-dim);
771
+ }
772
+
773
+ .console-head i.success {
774
+ background: var(--green);
775
+ box-shadow: 0 0 8px rgba(114, 214, 156, 0.7);
776
+ }
777
+
778
+ .console-head i.failure {
779
+ background: var(--red);
780
+ box-shadow: 0 0 8px rgba(255, 127, 114, 0.6);
781
+ }
782
+
783
+ .console-columns {
784
+ display: grid;
785
+ grid-template-columns: 0.85fr 1.15fr;
786
+ }
787
+
788
+ .console-columns > div {
789
+ min-width: 0;
790
+ padding: 12px;
791
+ }
792
+
793
+ .console-columns > div + div {
794
+ border-left: 1px solid var(--rule);
795
+ }
796
+
797
+ .console-label {
798
+ color: var(--fg-dim);
799
+ font: 8px var(--font-mono);
800
+ letter-spacing: 0.12em;
801
+ text-transform: uppercase;
802
+ }
803
+
804
+ .console-card pre {
805
+ height: 184px;
806
+ margin: 8px 0 0;
807
+ overflow: auto;
808
+ color: #b8c5d5;
809
+ font: 9px / 1.55 var(--font-mono);
810
+ white-space: pre-wrap;
811
+ overflow-wrap: anywhere;
812
+ }
813
+
814
+ .policy-section,
815
+ .audit-section {
816
+ margin-top: 16px;
817
+ padding: 24px;
818
+ border: 1px solid var(--rule-strong);
819
+ border-radius: 10px;
820
+ background: rgba(15, 21, 30, 0.88);
821
+ }
822
+
823
+ .section-heading-row {
824
+ align-items: end;
825
+ }
826
+
827
+ .section-heading-row > p {
828
+ max-width: 580px;
829
+ margin: 0;
830
+ color: var(--fg-muted);
831
+ font-size: 12px;
832
+ }
833
+
834
+ .persona-grid {
835
+ display: grid;
836
+ grid-template-columns: repeat(4, 1fr);
837
+ gap: 9px;
838
+ margin-top: 20px;
839
+ }
840
+
841
+ .persona-grid article {
842
+ position: relative;
843
+ min-width: 0;
844
+ padding: 16px;
845
+ border: 1px solid var(--rule);
846
+ border-radius: 7px;
847
+ background: var(--bg-elev-1);
848
+ }
849
+
850
+ .persona-code {
851
+ width: 32px;
852
+ height: 28px;
853
+ display: grid;
854
+ place-items: center;
855
+ margin-bottom: 13px;
856
+ border: 1px solid rgba(59, 130, 246, 0.3);
857
+ border-radius: 4px;
858
+ background: rgba(59, 130, 246, 0.08);
859
+ color: var(--blue-bright);
860
+ font: 600 9px var(--font-mono);
861
+ }
862
+
863
+ .persona-code.admin {
864
+ border-color: rgba(184, 161, 255, 0.35);
865
+ background: rgba(184, 161, 255, 0.08);
866
+ color: var(--violet);
867
+ }
868
+
869
+ .persona-grid h3 {
870
+ margin: 0 0 6px;
871
+ font-size: 13px;
872
+ }
873
+
874
+ .persona-grid p {
875
+ min-height: 54px;
876
+ margin: 0 0 12px;
877
+ color: var(--fg-dim);
878
+ font-size: 11px;
879
+ line-height: 1.55;
880
+ }
881
+
882
+ .persona-grid article > div {
883
+ display: flex;
884
+ justify-content: space-between;
885
+ gap: 10px;
886
+ padding: 6px 0;
887
+ border-top: 1px solid var(--rule);
888
+ color: var(--fg-dim);
889
+ font: 9px var(--font-mono);
890
+ }
891
+
892
+ .persona-grid article > div b {
893
+ color: var(--green);
894
+ font-weight: 500;
895
+ text-align: right;
896
+ }
897
+
898
+ .persona-grid article > div b.denied {
899
+ color: var(--red);
900
+ }
901
+
902
+ .audit-actions {
903
+ display: flex;
904
+ align-items: center;
905
+ gap: 10px;
906
+ color: var(--fg-dim);
907
+ font: 9px var(--font-mono);
908
+ }
909
+
910
+ .audit-list {
911
+ display: grid;
912
+ gap: 1px;
913
+ margin-top: 18px;
914
+ border: 1px solid var(--rule);
915
+ border-radius: 7px;
916
+ background: var(--rule);
917
+ overflow: hidden;
918
+ }
919
+
920
+ .audit-empty {
921
+ padding: 24px;
922
+ background: var(--code);
923
+ color: var(--fg-dim);
924
+ text-align: center;
925
+ font: 10px var(--font-mono);
926
+ }
927
+
928
+ .audit-event {
929
+ display: grid;
930
+ grid-template-columns: 64px 82px minmax(150px, 0.8fr) minmax(240px, 1.3fr) minmax(120px, 0.7fr);
931
+ gap: 10px;
932
+ align-items: center;
933
+ padding: 9px 11px;
934
+ background: var(--bg-elev-1);
935
+ font: 9px var(--font-mono);
936
+ }
937
+
938
+ .audit-event .decision {
939
+ width: max-content;
940
+ padding: 3px 6px;
941
+ border: 1px solid rgba(114, 214, 156, 0.3);
942
+ border-radius: 3px;
943
+ color: var(--green);
944
+ text-transform: uppercase;
945
+ }
946
+
947
+ .audit-event.denied .decision {
948
+ border-color: rgba(255, 127, 114, 0.3);
949
+ color: var(--red);
950
+ }
951
+
952
+ .audit-time,
953
+ .audit-reason {
954
+ color: var(--fg-dim);
955
+ }
956
+
957
+ .audit-capability {
958
+ color: var(--blue-bright);
959
+ overflow-wrap: anywhere;
960
+ }
961
+
962
+ .audit-resource {
963
+ min-width: 0;
964
+ overflow: hidden;
965
+ color: var(--fg-muted);
966
+ text-overflow: ellipsis;
967
+ white-space: nowrap;
968
+ }
969
+
970
+ .toast {
971
+ position: fixed;
972
+ right: 22px;
973
+ bottom: 22px;
974
+ z-index: 20;
975
+ padding: 10px 13px;
976
+ border: 1px solid var(--rule-strong);
977
+ border-radius: 6px;
978
+ background: var(--panel-high);
979
+ color: var(--fg);
980
+ font: 10px var(--font-mono);
981
+ opacity: 0;
982
+ transform: translateY(8px);
983
+ pointer-events: none;
984
+ transition:
985
+ opacity 0.16s,
986
+ transform 0.16s;
987
+ }
988
+
989
+ .toast.show {
990
+ opacity: 1;
991
+ transform: translateY(0);
992
+ }
993
+
994
+ @media (max-width: 1100px) {
995
+ .workspace {
996
+ grid-template-columns: 1fr;
997
+ }
998
+
999
+ .setup-panel {
1000
+ display: grid;
1001
+ grid-template-columns: 1fr 1fr;
1002
+ column-gap: 20px;
1003
+ }
1004
+
1005
+ .setup-panel > .panel-heading,
1006
+ .setup-panel > .resource-list,
1007
+ .setup-panel > .metadata-card {
1008
+ grid-column: 1;
1009
+ }
1010
+
1011
+ .setup-panel > .session-card {
1012
+ grid-column: 2;
1013
+ grid-row: 1 / span 3;
1014
+ margin-top: 0;
1015
+ padding: 0 0 0 20px;
1016
+ border-top: 0;
1017
+ border-left: 1px solid var(--rule);
1018
+ }
1019
+
1020
+ .persona-grid {
1021
+ grid-template-columns: repeat(2, 1fr);
1022
+ }
1023
+ }
1024
+
1025
+ @media (max-width: 760px) {
1026
+ .lab-topbar {
1027
+ padding: 0 14px;
1028
+ }
1029
+
1030
+ .topbar-tag,
1031
+ .topbar-link,
1032
+ .service-pill:first-child {
1033
+ display: none;
1034
+ }
1035
+
1036
+ .lab-shell {
1037
+ width: min(100% - 24px, 1480px);
1038
+ padding-top: 32px;
1039
+ }
1040
+
1041
+ .lab-hero {
1042
+ grid-template-columns: 1fr;
1043
+ gap: 20px;
1044
+ }
1045
+
1046
+ .hero-proof {
1047
+ width: auto;
1048
+ justify-content: flex-start;
1049
+ }
1050
+
1051
+ .flow {
1052
+ grid-template-columns: repeat(2, 1fr);
1053
+ }
1054
+
1055
+ .flow li:nth-child(2) {
1056
+ border-right: 0;
1057
+ }
1058
+
1059
+ .flow li:nth-child(-n + 2) {
1060
+ border-bottom: 1px solid var(--rule);
1061
+ }
1062
+
1063
+ .setup-panel {
1064
+ display: block;
1065
+ }
1066
+
1067
+ .setup-panel > .session-card {
1068
+ margin-top: 22px;
1069
+ padding: 20px 0 0;
1070
+ border-top: 1px solid var(--rule);
1071
+ border-left: 0;
1072
+ }
1073
+
1074
+ .action-grid,
1075
+ .console-columns,
1076
+ .persona-grid {
1077
+ grid-template-columns: 1fr;
1078
+ }
1079
+
1080
+ .console-columns > div + div {
1081
+ border-top: 1px solid var(--rule);
1082
+ border-left: 0;
1083
+ }
1084
+
1085
+ .section-heading-row {
1086
+ display: grid;
1087
+ }
1088
+
1089
+ .audit-event {
1090
+ grid-template-columns: 58px 74px 1fr;
1091
+ }
1092
+
1093
+ .audit-resource,
1094
+ .audit-reason {
1095
+ display: none;
1096
+ }
1097
+ }