@decibelsystems/tools 2.0.2 → 2.1.1

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 (96) hide show
  1. package/README.md +115 -233
  2. package/dist/config/queueableActions.d.ts +11 -0
  3. package/dist/config/queueableActions.d.ts.map +1 -0
  4. package/dist/config/queueableActions.js +22 -0
  5. package/dist/config/queueableActions.js.map +1 -0
  6. package/dist/daemon.d.ts +29 -0
  7. package/dist/daemon.d.ts.map +1 -1
  8. package/dist/daemon.js +64 -0
  9. package/dist/daemon.js.map +1 -1
  10. package/dist/daemonConfig.d.ts +7 -0
  11. package/dist/daemonConfig.d.ts.map +1 -1
  12. package/dist/daemonConfig.js +9 -0
  13. package/dist/daemonConfig.js.map +1 -1
  14. package/dist/facades/definitions.d.ts.map +1 -1
  15. package/dist/facades/definitions.js +130 -33
  16. package/dist/facades/definitions.js.map +1 -1
  17. package/dist/httpQueueDetection.d.ts +16 -0
  18. package/dist/httpQueueDetection.d.ts.map +1 -0
  19. package/dist/httpQueueDetection.js +36 -0
  20. package/dist/httpQueueDetection.js.map +1 -0
  21. package/dist/httpServer.d.ts +4 -0
  22. package/dist/httpServer.d.ts.map +1 -1
  23. package/dist/httpServer.js +224 -97
  24. package/dist/httpServer.js.map +1 -1
  25. package/dist/kernel.d.ts +2 -0
  26. package/dist/kernel.d.ts.map +1 -1
  27. package/dist/kernel.js +1 -0
  28. package/dist/kernel.js.map +1 -1
  29. package/dist/server.js +30 -1
  30. package/dist/server.js.map +1 -1
  31. package/dist/tools/agentic/agentQueue.d.ts +50 -0
  32. package/dist/tools/agentic/agentQueue.d.ts.map +1 -0
  33. package/dist/tools/agentic/agentQueue.js +226 -0
  34. package/dist/tools/agentic/agentQueue.js.map +1 -0
  35. package/dist/tools/agentic/index.d.ts +2 -0
  36. package/dist/tools/agentic/index.d.ts.map +1 -1
  37. package/dist/tools/agentic/index.js +84 -0
  38. package/dist/tools/agentic/index.js.map +1 -1
  39. package/dist/tools/coordinator/coordinator.d.ts +14 -0
  40. package/dist/tools/coordinator/coordinator.d.ts.map +1 -1
  41. package/dist/tools/coordinator/coordinator.js +101 -0
  42. package/dist/tools/coordinator/coordinator.js.map +1 -1
  43. package/dist/tools/coordinator/index.d.ts +2 -0
  44. package/dist/tools/coordinator/index.d.ts.map +1 -1
  45. package/dist/tools/coordinator/index.js +2 -0
  46. package/dist/tools/coordinator/index.js.map +1 -1
  47. package/dist/tools/decibel/index.d.ts +3 -0
  48. package/dist/tools/decibel/index.d.ts.map +1 -0
  49. package/dist/tools/decibel/index.js +150 -0
  50. package/dist/tools/decibel/index.js.map +1 -0
  51. package/dist/tools/decibel.d.ts +13 -0
  52. package/dist/tools/decibel.d.ts.map +1 -0
  53. package/dist/tools/decibel.js +156 -0
  54. package/dist/tools/decibel.js.map +1 -0
  55. package/dist/tools/deck.d.ts +4 -4
  56. package/dist/tools/deck.d.ts.map +1 -1
  57. package/dist/tools/deck.js +1546 -78
  58. package/dist/tools/deck.js.map +1 -1
  59. package/dist/tools/designer/index.d.ts +6 -0
  60. package/dist/tools/designer/index.d.ts.map +1 -1
  61. package/dist/tools/designer/index.js +344 -1
  62. package/dist/tools/designer/index.js.map +1 -1
  63. package/dist/tools/designer.d.ts +143 -0
  64. package/dist/tools/designer.d.ts.map +1 -1
  65. package/dist/tools/designer.js +457 -0
  66. package/dist/tools/designer.js.map +1 -1
  67. package/dist/tools/guardian/index.d.ts +1 -0
  68. package/dist/tools/guardian/index.d.ts.map +1 -1
  69. package/dist/tools/guardian/index.js +40 -1
  70. package/dist/tools/guardian/index.js.map +1 -1
  71. package/dist/tools/guardian.d.ts +30 -0
  72. package/dist/tools/guardian.d.ts.map +1 -1
  73. package/dist/tools/guardian.js +96 -0
  74. package/dist/tools/guardian.js.map +1 -1
  75. package/dist/tools/index.d.ts.map +1 -1
  76. package/dist/tools/index.js +7 -1
  77. package/dist/tools/index.js.map +1 -1
  78. package/dist/tools/mother.d.ts +11 -0
  79. package/dist/tools/mother.d.ts.map +1 -0
  80. package/dist/tools/mother.js +503 -0
  81. package/dist/tools/mother.js.map +1 -0
  82. package/dist/tools/swarm.d.ts +11 -0
  83. package/dist/tools/swarm.d.ts.map +1 -0
  84. package/dist/tools/swarm.js +701 -0
  85. package/dist/tools/swarm.js.map +1 -0
  86. package/dist/tools/terminal.d.ts +17 -0
  87. package/dist/tools/terminal.d.ts.map +1 -0
  88. package/dist/tools/terminal.js +968 -0
  89. package/dist/tools/terminal.js.map +1 -0
  90. package/dist/transports/http.d.ts.map +1 -1
  91. package/dist/transports/http.js +2 -0
  92. package/dist/transports/http.js.map +1 -1
  93. package/dist/transports/types.d.ts +4 -0
  94. package/dist/transports/types.d.ts.map +1 -1
  95. package/package.json +1 -1
  96. package/templates/docs.html +1084 -0
@@ -0,0 +1,1084 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Decibel Tools API</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
10
+ <style>
11
+ :root {
12
+ --bg: #09090b;
13
+ --surface: #111113;
14
+ --surface-2: #18181b;
15
+ --border: #27272a;
16
+ --text: #f4f4f5;
17
+ --text-muted: #71717a;
18
+ --accent: #7c3aed;
19
+ --accent-dim: #6d28d9;
20
+ --primary: #2563eb;
21
+ --green: #4ade80;
22
+ --yellow: #fbbf24;
23
+ --red: #f87171;
24
+ --blue: #2563eb;
25
+ --orange: #fb923c;
26
+ --cyan: #22d3ee;
27
+ --mono: 'JetBrains Mono', monospace;
28
+ --sans: 'Inter', system-ui, sans-serif;
29
+ }
30
+ * { margin: 0; padding: 0; box-sizing: border-box; }
31
+ body {
32
+ font-family: var(--sans);
33
+ background: var(--bg);
34
+ color: var(--text);
35
+ line-height: 1.6;
36
+ -webkit-font-smoothing: antialiased;
37
+ }
38
+ a { color: var(--primary); text-decoration: none; }
39
+ a:hover { text-decoration: underline; }
40
+ code, pre {
41
+ font-family: var(--mono);
42
+ font-size: 0.875rem;
43
+ }
44
+ pre {
45
+ background: var(--surface);
46
+ border: 1px solid var(--border);
47
+ border-radius: 8px;
48
+ padding: 1rem 1.25rem;
49
+ overflow-x: auto;
50
+ line-height: 1.5;
51
+ }
52
+ code {
53
+ background: var(--surface-2);
54
+ padding: 0.15em 0.4em;
55
+ border-radius: 4px;
56
+ font-size: 0.85em;
57
+ }
58
+ pre code {
59
+ background: none;
60
+ padding: 0;
61
+ border-radius: 0;
62
+ font-size: inherit;
63
+ }
64
+
65
+ /* Layout */
66
+ .wrapper {
67
+ display: flex;
68
+ min-height: 100vh;
69
+ }
70
+
71
+ /* Sidebar */
72
+ .sidebar {
73
+ width: 260px;
74
+ min-width: 260px;
75
+ background: var(--surface);
76
+ border-right: 1px solid var(--border);
77
+ padding: 1.5rem 0;
78
+ position: fixed;
79
+ top: 0;
80
+ left: 0;
81
+ bottom: 0;
82
+ overflow-y: auto;
83
+ z-index: 10;
84
+ }
85
+ .sidebar-logo {
86
+ padding: 0 1.25rem 1.25rem;
87
+ border-bottom: 1px solid var(--border);
88
+ margin-bottom: 1rem;
89
+ }
90
+ .sidebar-logo h1 {
91
+ font-size: 1.1rem;
92
+ font-weight: 700;
93
+ letter-spacing: -0.02em;
94
+ }
95
+ .sidebar-logo h1 span { color: var(--primary); }
96
+ .sidebar-logo p {
97
+ font-size: 0.75rem;
98
+ color: var(--text-muted);
99
+ margin-top: 0.25rem;
100
+ }
101
+ .nav-section {
102
+ padding: 0.75rem 1.25rem 0.25rem;
103
+ font-size: 0.65rem;
104
+ font-weight: 700;
105
+ text-transform: uppercase;
106
+ letter-spacing: 0.1em;
107
+ color: var(--text-muted);
108
+ }
109
+ .nav-link {
110
+ display: block;
111
+ padding: 0.35rem 1.25rem;
112
+ font-size: 0.85rem;
113
+ color: var(--text-muted);
114
+ transition: all 0.15s;
115
+ }
116
+ .nav-link:hover {
117
+ color: var(--text);
118
+ background: var(--surface-2);
119
+ text-decoration: none;
120
+ }
121
+
122
+ /* Main */
123
+ .main {
124
+ flex: 1;
125
+ margin-left: 260px;
126
+ max-width: 900px;
127
+ padding: 3rem 3rem 6rem;
128
+ }
129
+
130
+ /* Hero */
131
+ .hero {
132
+ margin-bottom: 3rem;
133
+ padding-bottom: 2rem;
134
+ border-bottom: 1px solid var(--border);
135
+ }
136
+ .hero h1 {
137
+ font-size: 2rem;
138
+ font-weight: 800;
139
+ letter-spacing: -0.03em;
140
+ margin-bottom: 0.5rem;
141
+ }
142
+ .hero h1 span { color: var(--primary); }
143
+ .hero p {
144
+ font-size: 1.05rem;
145
+ color: var(--text-muted);
146
+ max-width: 600px;
147
+ }
148
+ .hero-meta {
149
+ display: flex;
150
+ gap: 1.5rem;
151
+ margin-top: 1.25rem;
152
+ font-size: 0.8rem;
153
+ }
154
+ .hero-meta span {
155
+ display: inline-flex;
156
+ align-items: center;
157
+ gap: 0.4rem;
158
+ color: var(--text-muted);
159
+ }
160
+ .hero-meta .dot {
161
+ width: 8px;
162
+ height: 8px;
163
+ border-radius: 50%;
164
+ display: inline-block;
165
+ }
166
+ .dot-green { background: var(--green); }
167
+
168
+ /* Base URL box */
169
+ .base-url {
170
+ background: var(--surface);
171
+ border: 1px solid var(--border);
172
+ border-radius: 8px;
173
+ padding: 1rem 1.25rem;
174
+ margin-bottom: 2.5rem;
175
+ }
176
+ .base-url label {
177
+ font-size: 0.7rem;
178
+ font-weight: 700;
179
+ text-transform: uppercase;
180
+ letter-spacing: 0.08em;
181
+ color: var(--text-muted);
182
+ display: block;
183
+ margin-bottom: 0.35rem;
184
+ }
185
+ .base-url code {
186
+ font-size: 1rem;
187
+ color: var(--green);
188
+ background: none;
189
+ padding: 0;
190
+ }
191
+
192
+ /* Sections */
193
+ .section {
194
+ margin-bottom: 3rem;
195
+ }
196
+ .section > h2 {
197
+ font-size: 1.35rem;
198
+ font-weight: 700;
199
+ letter-spacing: -0.02em;
200
+ margin-bottom: 0.5rem;
201
+ padding-top: 1rem;
202
+ }
203
+ .section > p {
204
+ color: var(--text-muted);
205
+ margin-bottom: 1.5rem;
206
+ font-size: 0.95rem;
207
+ }
208
+
209
+ /* Endpoint cards */
210
+ .endpoint {
211
+ background: var(--surface);
212
+ border: 1px solid var(--border);
213
+ border-radius: 10px;
214
+ margin-bottom: 1.25rem;
215
+ overflow: hidden;
216
+ }
217
+ .endpoint-header {
218
+ display: flex;
219
+ align-items: center;
220
+ gap: 0.75rem;
221
+ padding: 0.85rem 1.25rem;
222
+ cursor: pointer;
223
+ user-select: none;
224
+ transition: background 0.15s;
225
+ }
226
+ .endpoint-header:hover {
227
+ background: var(--surface-2);
228
+ }
229
+ .method {
230
+ font-family: var(--mono);
231
+ font-size: 0.7rem;
232
+ font-weight: 700;
233
+ padding: 0.2rem 0.5rem;
234
+ border-radius: 4px;
235
+ min-width: 52px;
236
+ text-align: center;
237
+ letter-spacing: 0.02em;
238
+ }
239
+ .method-get { background: rgba(37, 99, 235, 0.12); color: var(--primary); }
240
+ .method-post { background: rgba(124, 58, 237, 0.12); color: var(--accent); }
241
+ .method-delete { background: rgba(248, 113, 113, 0.12); color: var(--red); }
242
+ .method-sse { background: rgba(37, 99, 235, 0.12); color: var(--primary); }
243
+ .endpoint-path {
244
+ font-family: var(--mono);
245
+ font-size: 0.9rem;
246
+ color: var(--text);
247
+ flex: 1;
248
+ }
249
+ .endpoint-desc {
250
+ font-size: 0.8rem;
251
+ color: var(--text-muted);
252
+ }
253
+ .endpoint-chevron {
254
+ color: var(--text-muted);
255
+ font-size: 0.8rem;
256
+ transition: transform 0.2s;
257
+ }
258
+ .endpoint.open .endpoint-chevron {
259
+ transform: rotate(90deg);
260
+ }
261
+ .endpoint-body {
262
+ display: none;
263
+ padding: 0 1.25rem 1.25rem;
264
+ border-top: 1px solid var(--border);
265
+ }
266
+ .endpoint.open .endpoint-body {
267
+ display: block;
268
+ }
269
+ .endpoint-body h4 {
270
+ font-size: 0.7rem;
271
+ font-weight: 700;
272
+ text-transform: uppercase;
273
+ letter-spacing: 0.08em;
274
+ color: var(--text-muted);
275
+ margin: 1rem 0 0.5rem;
276
+ }
277
+ .endpoint-body h4:first-child {
278
+ margin-top: 1rem;
279
+ }
280
+ .endpoint-body p {
281
+ font-size: 0.9rem;
282
+ color: var(--text-muted);
283
+ margin-bottom: 0.75rem;
284
+ }
285
+
286
+ /* Tables */
287
+ table {
288
+ width: 100%;
289
+ border-collapse: collapse;
290
+ font-size: 0.85rem;
291
+ margin-bottom: 0.75rem;
292
+ }
293
+ th {
294
+ text-align: left;
295
+ font-size: 0.7rem;
296
+ font-weight: 700;
297
+ text-transform: uppercase;
298
+ letter-spacing: 0.06em;
299
+ color: var(--text-muted);
300
+ padding: 0.5rem 0.75rem;
301
+ border-bottom: 1px solid var(--border);
302
+ }
303
+ td {
304
+ padding: 0.5rem 0.75rem;
305
+ border-bottom: 1px solid var(--border);
306
+ vertical-align: top;
307
+ }
308
+ td code {
309
+ font-size: 0.8rem;
310
+ }
311
+ tr:last-child td { border-bottom: none; }
312
+
313
+ /* Auth badge */
314
+ .badge {
315
+ font-size: 0.65rem;
316
+ font-weight: 700;
317
+ text-transform: uppercase;
318
+ letter-spacing: 0.05em;
319
+ padding: 0.15rem 0.45rem;
320
+ border-radius: 3px;
321
+ white-space: nowrap;
322
+ }
323
+ .badge-auth { background: rgba(251, 191, 36, 0.15); color: var(--yellow); }
324
+ .badge-none { background: rgba(74, 222, 128, 0.1); color: var(--green); }
325
+ .badge-tier { background: rgba(37, 99, 235, 0.12); color: var(--primary); }
326
+
327
+ /* Info boxes */
328
+ .info-box {
329
+ background: rgba(37, 99, 235, 0.08);
330
+ border: 1px solid rgba(37, 99, 235, 0.2);
331
+ border-radius: 8px;
332
+ padding: 1rem 1.25rem;
333
+ margin-bottom: 1.5rem;
334
+ font-size: 0.9rem;
335
+ }
336
+ .info-box.warning {
337
+ background: rgba(251, 191, 36, 0.08);
338
+ border-color: rgba(251, 191, 36, 0.2);
339
+ }
340
+
341
+ /* Responsive */
342
+ @media (max-width: 768px) {
343
+ .sidebar { display: none; }
344
+ .main { margin-left: 0; padding: 1.5rem; }
345
+ }
346
+ </style>
347
+ </head>
348
+ <body>
349
+ <div class="wrapper">
350
+ <!-- Sidebar -->
351
+ <nav class="sidebar">
352
+ <div class="sidebar-logo">
353
+ <h1><span>decibel</span> tools</h1>
354
+ <p>MCP Server HTTP API v2.1</p>
355
+ </div>
356
+
357
+ <div class="nav-section">Getting Started</div>
358
+ <a class="nav-link" href="#overview">Overview</a>
359
+ <a class="nav-link" href="#authentication">Authentication</a>
360
+ <a class="nav-link" href="#errors">Error Handling</a>
361
+
362
+ <div class="nav-section">MCP Protocol</div>
363
+ <a class="nav-link" href="#sse">SSE Transport</a>
364
+ <a class="nav-link" href="#mcp">StreamableHTTP</a>
365
+
366
+ <div class="nav-section">REST API</div>
367
+ <a class="nav-link" href="#tools">List Tools</a>
368
+ <a class="nav-link" href="#call">Execute Tool</a>
369
+ <a class="nav-link" href="#batch">Batch Execute</a>
370
+ <a class="nav-link" href="#facades">List Facades</a>
371
+
372
+ <div class="nav-section">Agent Management</div>
373
+ <a class="nav-link" href="#connect">Connect</a>
374
+ <a class="nav-link" href="#disconnect">Disconnect</a>
375
+ <a class="nav-link" href="#agents">List Agents</a>
376
+ <a class="nav-link" href="#events-stream">Event Stream</a>
377
+ <a class="nav-link" href="#events">Query Events</a>
378
+
379
+ <div class="nav-section">Infrastructure</div>
380
+ <a class="nav-link" href="#health">Health Check</a>
381
+ <a class="nav-link" href="#ready">Readiness Probe</a>
382
+ <a class="nav-link" href="#context-headers">Context Headers</a>
383
+ <a class="nav-link" href="#rate-limiting">Rate Limiting</a>
384
+ <a class="nav-link" href="#tiers">Facade Tiers</a>
385
+ </nav>
386
+
387
+ <!-- Main Content -->
388
+ <main class="main">
389
+ <div class="hero" id="overview">
390
+ <h1><span>Decibel Tools</span> API</h1>
391
+ <p>HTTP interface to the Decibel MCP server. Supports the MCP protocol (SSE + StreamableHTTP), a REST convenience layer, and multi-agent coordination.</p>
392
+ <div class="hero-meta">
393
+ <span><span class="dot dot-green"></span> v{{VERSION}}</span>
394
+ <span>{{FACADE_COUNT}} facades</span>
395
+ <span>{{TOOL_COUNT}} actions</span>
396
+ <span>MCP + REST + SSE</span>
397
+ </div>
398
+ </div>
399
+
400
+ <div class="base-url">
401
+ <label>Base URL</label>
402
+ <code>https://senken.pro</code>
403
+ </div>
404
+
405
+ <!-- ============================================================ -->
406
+ <!-- AUTHENTICATION -->
407
+ <!-- ============================================================ -->
408
+ <div class="section" id="authentication">
409
+ <h2>Authentication</h2>
410
+ <p>When the server is started with <code>--auth-token</code>, all mutating endpoints require a Bearer token. Health and discovery endpoints are always public.</p>
411
+ <pre><code>Authorization: Bearer YOUR_TOKEN</code></pre>
412
+ <p>Alternatively, pass a license key for tier-gated access:</p>
413
+ <pre><code>X-License-Key: YOUR_LICENSE_KEY</code></pre>
414
+ </div>
415
+
416
+ <!-- ============================================================ -->
417
+ <!-- ERROR HANDLING -->
418
+ <!-- ============================================================ -->
419
+ <div class="section" id="errors">
420
+ <h2>Error Handling</h2>
421
+ <p>All endpoints return a consistent JSON envelope.</p>
422
+ <pre><code><span style="color:#888">// Success</span>
423
+ { "status": "executed", ... }
424
+
425
+ <span style="color:#888">// Error</span>
426
+ {
427
+ "status": "error",
428
+ "error": "Human-readable message",
429
+ "code": "ERROR_CODE"
430
+ }</code></pre>
431
+
432
+ <table>
433
+ <thead><tr><th>Code</th><th>HTTP</th><th>Meaning</th></tr></thead>
434
+ <tbody>
435
+ <tr><td><code>UNAUTHORIZED</code></td><td>401</td><td>Missing or invalid auth token</td></tr>
436
+ <tr><td><code>RATE_LIMITED</code></td><td>429</td><td>Too many requests</td></tr>
437
+ <tr><td><code>MISSING_TOOL</code></td><td>400</td><td>Tool not found in registry</td></tr>
438
+ <tr><td><code>ACCESS_DENIED</code></td><td>403</td><td>Facade not in agent's allowlist or tier</td></tr>
439
+ <tr><td><code>BODY_TOO_LARGE</code></td><td>413</td><td>Request body exceeds 1MB</td></tr>
440
+ <tr><td><code>PARSE_ERROR</code></td><td>400</td><td>Invalid JSON in request body</td></tr>
441
+ <tr><td><code>NOT_DAEMON</code></td><td>503</td><td>Agent management endpoint requires daemon mode</td></tr>
442
+ <tr><td><code>TOOL_ERROR</code></td><td>500</td><td>Tool execution failed</td></tr>
443
+ </tbody>
444
+ </table>
445
+ </div>
446
+
447
+ <!-- ============================================================ -->
448
+ <!-- SSE TRANSPORT -->
449
+ <!-- ============================================================ -->
450
+ <div class="section" id="sse">
451
+ <h2>SSE Transport</h2>
452
+ <p>Server-Sent Events transport for the MCP protocol. Used by ChatGPT and other MCP clients that prefer streaming.</p>
453
+
454
+ <div class="endpoint open">
455
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
456
+ <span class="method method-sse">SSE</span>
457
+ <span class="endpoint-path">/sse/</span>
458
+ <span class="endpoint-desc">MCP over Server-Sent Events</span>
459
+ <span class="endpoint-chevron">&#9654;</span>
460
+ </div>
461
+ <div class="endpoint-body">
462
+ <p>Opens a persistent SSE connection for bidirectional MCP communication. The server sends keepalive comments every 30 seconds to maintain the connection.</p>
463
+ <h4>Connection</h4>
464
+ <pre><code>curl -N https://senken.pro/sse/</code></pre>
465
+ <h4>Details</h4>
466
+ <table>
467
+ <tr><td><strong>Methods</strong></td><td><code>GET</code> (stream), <code>POST</code> (messages), <code>DELETE</code> (close)</td></tr>
468
+ <tr><td><strong>Content-Type</strong></td><td><code>text/event-stream</code></td></tr>
469
+ <tr><td><strong>Keepalive</strong></td><td>Comment heartbeat every 30s (configurable via <code>--sse-keepalive</code>)</td></tr>
470
+ <tr><td><strong>CORS</strong></td><td>All origins allowed</td></tr>
471
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-auth">Token if set</span></td></tr>
472
+ </table>
473
+ <h4>Notes</h4>
474
+ <p>The trailing slash matters for some clients (e.g., ChatGPT). Both <code>/sse</code> and <code>/sse/</code> are accepted.</p>
475
+ </div>
476
+ </div>
477
+ </div>
478
+
479
+ <!-- ============================================================ -->
480
+ <!-- STREAMABLE HTTP -->
481
+ <!-- ============================================================ -->
482
+ <div class="section" id="mcp">
483
+ <h2>StreamableHTTP (JSON-RPC)</h2>
484
+ <p>The primary MCP protocol endpoint. Supports the full MCP spec via JSON-RPC over HTTP.</p>
485
+
486
+ <div class="endpoint open">
487
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
488
+ <span class="method method-post">POST</span>
489
+ <span class="endpoint-path">/mcp</span>
490
+ <span class="endpoint-desc">MCP JSON-RPC endpoint</span>
491
+ <span class="endpoint-chevron">&#9654;</span>
492
+ </div>
493
+ <div class="endpoint-body">
494
+ <p>Send MCP protocol messages (JSON-RPC 2.0). This is the recommended transport for programmatic access.</p>
495
+ <h4>Example: List Tools</h4>
496
+ <pre><code>curl -X POST https://senken.pro/mcp \
497
+ -H "Content-Type: application/json" \
498
+ -d '{
499
+ "jsonrpc": "2.0",
500
+ "id": 1,
501
+ "method": "tools/list",
502
+ "params": {}
503
+ }'</code></pre>
504
+ <h4>Example: Call a Tool</h4>
505
+ <pre><code>curl -X POST https://senken.pro/mcp \
506
+ -H "Content-Type: application/json" \
507
+ -d '{
508
+ "jsonrpc": "2.0",
509
+ "id": 2,
510
+ "method": "tools/call",
511
+ "params": {
512
+ "name": "sentinel",
513
+ "arguments": {
514
+ "action": "list_issues",
515
+ "project_id": "my-project"
516
+ }
517
+ }
518
+ }'</code></pre>
519
+ <h4>Supported Methods</h4>
520
+ <table>
521
+ <thead><tr><th>Method</th><th>Description</th></tr></thead>
522
+ <tbody>
523
+ <tr><td><code>initialize</code></td><td>Initialize MCP session</td></tr>
524
+ <tr><td><code>tools/list</code></td><td>List available tools (facades)</td></tr>
525
+ <tr><td><code>tools/call</code></td><td>Execute a tool</td></tr>
526
+ <tr><td><code>resources/list</code></td><td>List available resources</td></tr>
527
+ <tr><td><code>resources/read</code></td><td>Read a resource</td></tr>
528
+ <tr><td><code>prompts/list</code></td><td>List available prompts</td></tr>
529
+ <tr><td><code>prompts/get</code></td><td>Get a prompt</td></tr>
530
+ </tbody>
531
+ </table>
532
+ <h4>Details</h4>
533
+ <table>
534
+ <tr><td><strong>Methods</strong></td><td><code>GET</code>, <code>POST</code>, <code>DELETE</code></td></tr>
535
+ <tr><td><strong>Content-Type</strong></td><td><code>application/json</code></td></tr>
536
+ <tr><td><strong>CORS</strong></td><td>All origins allowed</td></tr>
537
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-auth">Token if set</span></td></tr>
538
+ </table>
539
+ </div>
540
+ </div>
541
+ </div>
542
+
543
+ <!-- ============================================================ -->
544
+ <!-- TOOLS -->
545
+ <!-- ============================================================ -->
546
+ <div class="section" id="tools">
547
+ <h2>List Tools</h2>
548
+ <p>Discover available facades and their actions.</p>
549
+
550
+ <div class="endpoint">
551
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
552
+ <span class="method method-get">GET</span>
553
+ <span class="endpoint-path">/tools</span>
554
+ <span class="endpoint-desc">List all available tools</span>
555
+ <span class="endpoint-chevron">&#9654;</span>
556
+ </div>
557
+ <div class="endpoint-body">
558
+ <p>Returns all registered facades and their actions. Responds with JSON or HTML based on the <code>Accept</code> header.</p>
559
+ <h4>Example</h4>
560
+ <pre><code>curl https://senken.pro/tools \
561
+ -H "Accept: application/json"</code></pre>
562
+ <h4>Response</h4>
563
+ <pre><code>{
564
+ "status": "executed",
565
+ "version": "{{VERSION}}",
566
+ "api_version": "v1",
567
+ "tools": [
568
+ {
569
+ "name": "sentinel",
570
+ "description": "Work tracking: epics, issues, incidents",
571
+ "actions": ["create_issue", "list_issues", "log_epic", ...]
572
+ },
573
+ {
574
+ "name": "swarm",
575
+ "description": "Multi-agent sessions and signals",
576
+ "actions": ["start_session", "join_session", "emit_signal", ...]
577
+ }
578
+ ]
579
+ }</code></pre>
580
+ <table>
581
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-none">Public</span></td></tr>
582
+ </table>
583
+ </div>
584
+ </div>
585
+ </div>
586
+
587
+ <!-- ============================================================ -->
588
+ <!-- CALL -->
589
+ <!-- ============================================================ -->
590
+ <div class="section" id="call">
591
+ <h2>Execute Tool</h2>
592
+ <p>Call any tool directly via the REST convenience layer.</p>
593
+
594
+ <div class="endpoint">
595
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
596
+ <span class="method method-post">POST</span>
597
+ <span class="endpoint-path">/call</span>
598
+ <span class="endpoint-desc">Execute any tool by name</span>
599
+ <span class="endpoint-chevron">&#9654;</span>
600
+ </div>
601
+ <div class="endpoint-body">
602
+ <p>Generic dispatch endpoint. Pass the tool name and arguments. The kernel routes to the correct facade and action.</p>
603
+ <h4>Request</h4>
604
+ <pre><code>curl -X POST https://senken.pro/call \
605
+ -H "Content-Type: application/json" \
606
+ -H "Authorization: Bearer TOKEN" \
607
+ -d '{
608
+ "tool": "sentinel",
609
+ "arguments": {
610
+ "action": "list_issues",
611
+ "project_id": "decibel-tools-mcp"
612
+ }
613
+ }'</code></pre>
614
+ <h4>Request Body</h4>
615
+ <table>
616
+ <thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
617
+ <tbody>
618
+ <tr><td><code>tool</code></td><td>string</td><td>Yes</td><td>Facade or tool name</td></tr>
619
+ <tr><td><code>arguments</code></td><td>object</td><td>Yes</td><td>Tool-specific parameters</td></tr>
620
+ </tbody>
621
+ </table>
622
+ <h4>Response</h4>
623
+ <pre><code>{
624
+ "status": "executed",
625
+ "result": { ... }
626
+ }</code></pre>
627
+ <h4>Context Headers</h4>
628
+ <p>Include optional headers to identify the calling agent and trace requests. See <a href="#context-headers">Context Headers</a>.</p>
629
+ <table>
630
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-auth">Token if set</span></td></tr>
631
+ </table>
632
+ </div>
633
+ </div>
634
+ </div>
635
+
636
+ <!-- ============================================================ -->
637
+ <!-- BATCH -->
638
+ <!-- ============================================================ -->
639
+ <div class="section" id="batch">
640
+ <h2>Batch Execute</h2>
641
+ <p>Execute multiple independent tool calls in parallel.</p>
642
+
643
+ <div class="endpoint">
644
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
645
+ <span class="method method-post">POST</span>
646
+ <span class="endpoint-path">/batch</span>
647
+ <span class="endpoint-desc">Parallel multi-tool execution</span>
648
+ <span class="endpoint-chevron">&#9654;</span>
649
+ </div>
650
+ <div class="endpoint-body">
651
+ <p>Send up to 20 calls in a single request. All calls execute concurrently via <code>Promise.allSettled</code>. Ideal for agent bootstrap (fetching context + issues + roadmap in one round-trip).</p>
652
+ <h4>Request</h4>
653
+ <pre><code>curl -X POST https://senken.pro/batch \
654
+ -H "Content-Type: application/json" \
655
+ -H "X-Agent-Id: analyst-01" \
656
+ -d '{
657
+ "calls": [
658
+ { "facade": "sentinel", "action": "list_issues", "params": { "project_id": "my-project" } },
659
+ { "facade": "oracle", "action": "next_actions", "params": { "project_id": "my-project" } },
660
+ { "facade": "context", "action": "refresh", "params": { "task": "status check" } }
661
+ ],
662
+ "context": {
663
+ "agentId": "analyst-01",
664
+ "runId": "run-abc"
665
+ }
666
+ }'</code></pre>
667
+ <h4>Request Body</h4>
668
+ <table>
669
+ <thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
670
+ <tbody>
671
+ <tr><td><code>calls</code></td><td>array</td><td>Yes</td><td>Array of call objects (max 20)</td></tr>
672
+ <tr><td><code>calls[].facade</code></td><td>string</td><td>Yes</td><td>Facade name</td></tr>
673
+ <tr><td><code>calls[].action</code></td><td>string</td><td>Yes</td><td>Action name</td></tr>
674
+ <tr><td><code>calls[].params</code></td><td>object</td><td>No</td><td>Action parameters</td></tr>
675
+ <tr><td><code>context</code></td><td>object</td><td>No</td><td>Shared context for all calls</td></tr>
676
+ </tbody>
677
+ </table>
678
+ <h4>Response</h4>
679
+ <pre><code>{
680
+ "status": "executed",
681
+ "results": [
682
+ { "status": "executed", ... },
683
+ { "status": "executed", ... },
684
+ { "status": "error", "error": "...", "code": "..." }
685
+ ]
686
+ }</code></pre>
687
+ <table>
688
+ <tr><td><strong>Max calls</strong></td><td>20 per batch</td></tr>
689
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-auth">Token if set</span></td></tr>
690
+ </table>
691
+ </div>
692
+ </div>
693
+ </div>
694
+
695
+ <!-- ============================================================ -->
696
+ <!-- FACADES -->
697
+ <!-- ============================================================ -->
698
+ <div class="section" id="facades">
699
+ <h2>List Facades</h2>
700
+ <p>Facade registry for agent bootstrap and capability discovery.</p>
701
+
702
+ <div class="endpoint">
703
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
704
+ <span class="method method-get">GET</span>
705
+ <span class="endpoint-path">/facades</span>
706
+ <span class="endpoint-desc">Facade registry with tiers</span>
707
+ <span class="endpoint-chevron">&#9654;</span>
708
+ </div>
709
+ <div class="endpoint-body">
710
+ <p>Returns all facades with their descriptions, actions, and tier. Use the <code>tier</code> query param to control verbosity.</p>
711
+ <h4>Example</h4>
712
+ <pre><code>curl "https://senken.pro/facades?tier=compact"</code></pre>
713
+ <h4>Query Parameters</h4>
714
+ <table>
715
+ <thead><tr><th>Param</th><th>Values</th><th>Description</th></tr></thead>
716
+ <tbody>
717
+ <tr><td><code>tier</code></td><td><code>full</code>, <code>compact</code>, <code>micro</code></td><td>Description verbosity level (default: <code>full</code>)</td></tr>
718
+ </tbody>
719
+ </table>
720
+ <h4>Response</h4>
721
+ <pre><code>{
722
+ "status": "executed",
723
+ "facades": [
724
+ {
725
+ "name": "sentinel",
726
+ "description": "Work tracking: epics, issues, incidents...",
727
+ "actions": ["create_issue", "list_issues", "log_epic", ...],
728
+ "tier": "core"
729
+ }
730
+ ],
731
+ "facade_count": 30,
732
+ "internal_tool_count": 170
733
+ }</code></pre>
734
+ <table>
735
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-none">Public</span></td></tr>
736
+ </table>
737
+ </div>
738
+ </div>
739
+ </div>
740
+
741
+ <!-- ============================================================ -->
742
+ <!-- CONNECT -->
743
+ <!-- ============================================================ -->
744
+ <div class="section" id="connect">
745
+ <h2>Agent Connect</h2>
746
+ <p>Register an agent with the daemon's agent registry. Required for multi-agent coordination.</p>
747
+
748
+ <div class="endpoint">
749
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
750
+ <span class="method method-post">POST</span>
751
+ <span class="endpoint-path">/connect</span>
752
+ <span class="endpoint-desc">Agent handshake</span>
753
+ <span class="endpoint-chevron">&#9654;</span>
754
+ </div>
755
+ <div class="endpoint-body">
756
+ <p>Registers an agent with the daemon. Returns the agent's capabilities, allowed facades, tier, and rate limit. Only available in daemon mode.</p>
757
+ <h4>Request</h4>
758
+ <pre><code>curl -X POST https://senken.pro/connect \
759
+ -H "Content-Type: application/json" \
760
+ -d '{
761
+ "agent_id": "analyst-01",
762
+ "capabilities": ["sentinel", "oracle", "context"]
763
+ }'</code></pre>
764
+ <h4>Request Body</h4>
765
+ <table>
766
+ <thead><tr><th>Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead>
767
+ <tbody>
768
+ <tr><td><code>agent_id</code></td><td>string</td><td>Yes</td><td>Unique agent identifier</td></tr>
769
+ <tr><td><code>capabilities</code></td><td>string[]</td><td>No</td><td>Facade names the agent needs</td></tr>
770
+ </tbody>
771
+ </table>
772
+ <h4>Response</h4>
773
+ <pre><code>{
774
+ "status": "executed",
775
+ "agent_id": "analyst-01",
776
+ "connected_at": "2026-03-30T19:35:00.000Z",
777
+ "capabilities": ["sentinel", "oracle", "context"],
778
+ "allowed_facades": ["sentinel", "oracle", "context"],
779
+ "tier": "pro",
780
+ "rate_limit_rpm": 100
781
+ }</code></pre>
782
+ <table>
783
+ <tr><td><strong>Requires</strong></td><td>Daemon mode (<code>--daemon</code>)</td></tr>
784
+ <tr><td><strong>Error</strong></td><td><code>503 NOT_DAEMON</code> if not in daemon mode</td></tr>
785
+ </table>
786
+ </div>
787
+ </div>
788
+ </div>
789
+
790
+ <!-- ============================================================ -->
791
+ <!-- DISCONNECT -->
792
+ <!-- ============================================================ -->
793
+ <div class="section" id="disconnect">
794
+ <h2>Agent Disconnect</h2>
795
+ <p>Gracefully unregister an agent from the daemon.</p>
796
+
797
+ <div class="endpoint">
798
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
799
+ <span class="method method-post">POST</span>
800
+ <span class="endpoint-path">/disconnect</span>
801
+ <span class="endpoint-desc">Graceful agent disconnect</span>
802
+ <span class="endpoint-chevron">&#9654;</span>
803
+ </div>
804
+ <div class="endpoint-body">
805
+ <h4>Request</h4>
806
+ <pre><code>curl -X POST https://senken.pro/disconnect \
807
+ -H "Content-Type: application/json" \
808
+ -d '{ "agent_id": "analyst-01" }'</code></pre>
809
+ <h4>Response</h4>
810
+ <pre><code>{
811
+ "status": "executed",
812
+ "agent_id": "analyst-01",
813
+ "disconnected": true
814
+ }</code></pre>
815
+ </div>
816
+ </div>
817
+ </div>
818
+
819
+ <!-- ============================================================ -->
820
+ <!-- AGENTS -->
821
+ <!-- ============================================================ -->
822
+ <div class="section" id="agents">
823
+ <h2>List Agents</h2>
824
+ <p>See all currently connected agents.</p>
825
+
826
+ <div class="endpoint">
827
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
828
+ <span class="method method-get">GET</span>
829
+ <span class="endpoint-path">/agents</span>
830
+ <span class="endpoint-desc">List connected agents</span>
831
+ <span class="endpoint-chevron">&#9654;</span>
832
+ </div>
833
+ <div class="endpoint-body">
834
+ <h4>Example</h4>
835
+ <pre><code>curl https://senken.pro/agents</code></pre>
836
+ <h4>Response</h4>
837
+ <pre><code>{
838
+ "status": "executed",
839
+ "agents": [
840
+ {
841
+ "id": "analyst-01",
842
+ "connected_at": "2026-03-30T19:35:00.000Z",
843
+ "capabilities": ["sentinel", "oracle"],
844
+ "last_seen": "2026-03-30T19:40:00.000Z"
845
+ }
846
+ ],
847
+ "count": 1
848
+ }</code></pre>
849
+ <table>
850
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-none">Public</span></td></tr>
851
+ </table>
852
+ </div>
853
+ </div>
854
+ </div>
855
+
856
+ <!-- ============================================================ -->
857
+ <!-- EVENTS STREAM -->
858
+ <!-- ============================================================ -->
859
+ <div class="section" id="events-stream">
860
+ <h2>Event Stream</h2>
861
+ <p>Real-time SSE stream of dispatch events. Monitor tool calls as they happen.</p>
862
+
863
+ <div class="endpoint">
864
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
865
+ <span class="method method-sse">SSE</span>
866
+ <span class="endpoint-path">/events/stream</span>
867
+ <span class="endpoint-desc">Real-time dispatch events</span>
868
+ <span class="endpoint-chevron">&#9654;</span>
869
+ </div>
870
+ <div class="endpoint-body">
871
+ <p>Opens an SSE stream that emits every tool dispatch as it happens. Useful for dashboards, audit logs, and debugging agent behavior.</p>
872
+ <h4>Example</h4>
873
+ <pre><code>curl -N "https://senken.pro/events/stream?agent_id=analyst-01"</code></pre>
874
+ <h4>Query Parameters</h4>
875
+ <table>
876
+ <thead><tr><th>Param</th><th>Type</th><th>Description</th></tr></thead>
877
+ <tbody>
878
+ <tr><td><code>agent_id</code></td><td>string</td><td>Filter by agent (optional)</td></tr>
879
+ <tr><td><code>facade</code></td><td>string</td><td>Filter by facade (optional)</td></tr>
880
+ </tbody>
881
+ </table>
882
+ <h4>Event Format</h4>
883
+ <pre><code>data: {
884
+ "timestamp": "2026-03-30T19:35:12.345Z",
885
+ "agentId": "analyst-01",
886
+ "facade": "sentinel",
887
+ "action": "list_issues",
888
+ "duration_ms": 42,
889
+ "status": "ok"
890
+ }</code></pre>
891
+ <table>
892
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-none">Public</span></td></tr>
893
+ </table>
894
+ </div>
895
+ </div>
896
+ </div>
897
+
898
+ <!-- ============================================================ -->
899
+ <!-- EVENTS QUERY -->
900
+ <!-- ============================================================ -->
901
+ <div class="section" id="events">
902
+ <h2>Query Events</h2>
903
+ <p>Query the dispatch event log for historical tool calls.</p>
904
+
905
+ <div class="endpoint">
906
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
907
+ <span class="method method-get">GET</span>
908
+ <span class="endpoint-path">/events</span>
909
+ <span class="endpoint-desc">Query dispatch event log</span>
910
+ <span class="endpoint-chevron">&#9654;</span>
911
+ </div>
912
+ <div class="endpoint-body">
913
+ <h4>Query Parameters</h4>
914
+ <table>
915
+ <thead><tr><th>Param</th><th>Type</th><th>Description</th></tr></thead>
916
+ <tbody>
917
+ <tr><td><code>since</code></td><td>ISO 8601</td><td>Events after this timestamp</td></tr>
918
+ <tr><td><code>agent_id</code></td><td>string</td><td>Filter by agent</td></tr>
919
+ <tr><td><code>limit</code></td><td>number</td><td>Max events (default: 100)</td></tr>
920
+ </tbody>
921
+ </table>
922
+ <h4>Response</h4>
923
+ <pre><code>{
924
+ "status": "executed",
925
+ "events": [ ... ],
926
+ "total": 42
927
+ }</code></pre>
928
+ </div>
929
+ </div>
930
+ </div>
931
+
932
+ <!-- ============================================================ -->
933
+ <!-- HEALTH -->
934
+ <!-- ============================================================ -->
935
+ <div class="section" id="health">
936
+ <h2>Health Check</h2>
937
+ <p>System health and runtime info.</p>
938
+
939
+ <div class="endpoint">
940
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
941
+ <span class="method method-get">GET</span>
942
+ <span class="endpoint-path">/health</span>
943
+ <span class="endpoint-desc">Detailed health check</span>
944
+ <span class="endpoint-chevron">&#9654;</span>
945
+ </div>
946
+ <div class="endpoint-body">
947
+ <h4>Response</h4>
948
+ <pre><code>{
949
+ "status": "ok",
950
+ "version": "{{VERSION}}",
951
+ "api_version": "v1",
952
+ "uptime_ms": 3600000,
953
+ "uptime_human": "1h 0m 0s",
954
+ "pid": 12345,
955
+ "facade_count": 30,
956
+ "internal_tool_count": 170,
957
+ "connected_clients": 2,
958
+ "active_requests": 0,
959
+ "connected_agents": 3,
960
+ "pro": true,
961
+ "license_tier": "pro",
962
+ "supabase_configured": true
963
+ }</code></pre>
964
+ <table>
965
+ <tr><td><strong>Auth</strong></td><td><span class="badge badge-none">Public</span></td></tr>
966
+ </table>
967
+ </div>
968
+ </div>
969
+ </div>
970
+
971
+ <!-- ============================================================ -->
972
+ <!-- READY -->
973
+ <!-- ============================================================ -->
974
+ <div class="section" id="ready">
975
+ <h2>Readiness Probe</h2>
976
+
977
+ <div class="endpoint">
978
+ <div class="endpoint-header" onclick="this.parentElement.classList.toggle('open')">
979
+ <span class="method method-get">GET</span>
980
+ <span class="endpoint-path">/ready</span>
981
+ <span class="endpoint-desc">K8s/orchestrator readiness probe</span>
982
+ <span class="endpoint-chevron">&#9654;</span>
983
+ </div>
984
+ <div class="endpoint-body">
985
+ <p>Returns 200 when the server is ready to accept requests, 503 otherwise.</p>
986
+ <pre><code>{ "ready": true, "facade_count": 30 }</code></pre>
987
+ </div>
988
+ </div>
989
+ </div>
990
+
991
+ <!-- ============================================================ -->
992
+ <!-- CONTEXT HEADERS -->
993
+ <!-- ============================================================ -->
994
+ <div class="section" id="context-headers">
995
+ <h2>Context Headers</h2>
996
+ <p>Optional headers for multi-agent tracing and access control. Passed through to the dispatch kernel on every <code>/call</code> and <code>/batch</code> request.</p>
997
+
998
+ <table>
999
+ <thead><tr><th>Header</th><th>Description</th></tr></thead>
1000
+ <tbody>
1001
+ <tr><td><code>X-Agent-Id</code></td><td>Agent identifier (used for rate limiting, event attribution, facade scoping)</td></tr>
1002
+ <tr><td><code>X-Run-Id</code></td><td>Run/session ID for grouping related calls</td></tr>
1003
+ <tr><td><code>X-Parent-Call-Id</code></td><td>Parent call ID for distributed tracing</td></tr>
1004
+ <tr><td><code>X-Scope</code></td><td>Scope hint for the kernel</td></tr>
1005
+ <tr><td><code>X-Engagement-Mode</code></td><td>Engagement mode selector</td></tr>
1006
+ <tr><td><code>X-User-Key</code></td><td>User identifier</td></tr>
1007
+ <tr><td><code>X-Request-Id</code></td><td>Request tracking ID</td></tr>
1008
+ <tr><td><code>X-License-Key</code></td><td>License key (overrides config for tier resolution)</td></tr>
1009
+ <tr><td><code>X-Allowed-Facades</code></td><td>Comma-separated facade whitelist (restricts which facades this call can access)</td></tr>
1010
+ </tbody>
1011
+ </table>
1012
+ </div>
1013
+
1014
+ <!-- ============================================================ -->
1015
+ <!-- RATE LIMITING -->
1016
+ <!-- ============================================================ -->
1017
+ <div class="section" id="rate-limiting">
1018
+ <h2>Rate Limiting</h2>
1019
+ <p>Sliding window rate limiter, scoped per IP or per agent.</p>
1020
+
1021
+ <div class="info-box">
1022
+ <strong>Default:</strong> 100 requests per minute per IP. Agents registered via <code>/connect</code> get their own limit that can be configured in the daemon config.
1023
+ </div>
1024
+
1025
+ <p>When rate limited, the server returns:</p>
1026
+ <pre><code>HTTP 429
1027
+ {
1028
+ "status": "error",
1029
+ "error": "Rate limited",
1030
+ "code": "RATE_LIMITED"
1031
+ }</code></pre>
1032
+ </div>
1033
+
1034
+ <!-- ============================================================ -->
1035
+ <!-- TIERS -->
1036
+ <!-- ============================================================ -->
1037
+ <div class="section" id="tiers">
1038
+ <h2>Facade Tiers</h2>
1039
+ <p>Facades are grouped into three access tiers. In development, all tiers are enabled. In production, pro and apps tiers require environment variables or a valid license key.</p>
1040
+
1041
+ <table>
1042
+ <thead><tr><th>Tier</th><th>Count</th><th>Gate</th><th>Facades</th></tr></thead>
1043
+ <tbody>
1044
+ <tr>
1045
+ <td><span class="badge badge-none">core</span></td>
1046
+ <td>21</td>
1047
+ <td>Always available</td>
1048
+ <td>sentinel, architect, dojo, designer, git, workflow, oracle, roadmap, vector, context, auditor, forecast, velocity, coordinator, swarm, friction, registry, feedback, learnings, provenance, bench, guardian</td>
1049
+ </tr>
1050
+ <tr>
1051
+ <td><span class="badge badge-tier">pro</span></td>
1052
+ <td>4</td>
1053
+ <td><code>DECIBEL_PRO=1</code></td>
1054
+ <td>voice, studio, corpus, agentic</td>
1055
+ </tr>
1056
+ <tr>
1057
+ <td><span class="badge badge-auth">apps</span></td>
1058
+ <td>2+</td>
1059
+ <td><code>DECIBEL_APPS=1</code></td>
1060
+ <td>senken, mother, terminal</td>
1061
+ </tr>
1062
+ </tbody>
1063
+ </table>
1064
+ </div>
1065
+
1066
+ <!-- Footer -->
1067
+ <div style="margin-top: 4rem; padding-top: 2rem; border-top: 1px solid var(--border); color: var(--text-muted); font-size: 0.8rem;">
1068
+ <p>Decibel Tools v{{VERSION}} &middot; <code>@decibelsystems/tools</code> on npm &middot; Built by Decibel Systems</p>
1069
+ </div>
1070
+ </main>
1071
+ </div>
1072
+
1073
+ <script>
1074
+ // Smooth scroll for nav links
1075
+ document.querySelectorAll('.nav-link').forEach(link => {
1076
+ link.addEventListener('click', e => {
1077
+ e.preventDefault();
1078
+ const target = document.querySelector(link.getAttribute('href'));
1079
+ if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
1080
+ });
1081
+ });
1082
+ </script>
1083
+ </body>
1084
+ </html>