@dollhousemcp/mcp-server 2.0.0-rc.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/CHANGELOG.md +52 -61
  2. package/README.github.md +2 -2
  3. package/README.md +2 -2
  4. package/README.md.backup +284 -224
  5. package/README.npm.md +2 -2
  6. package/dist/cache/LRUCache.d.ts +3 -0
  7. package/dist/cache/LRUCache.d.ts.map +1 -1
  8. package/dist/cache/LRUCache.js +36 -26
  9. package/dist/config/env.d.ts +14 -4
  10. package/dist/config/env.d.ts.map +1 -1
  11. package/dist/config/env.js +20 -6
  12. package/dist/di/Container.d.ts +21 -0
  13. package/dist/di/Container.d.ts.map +1 -1
  14. package/dist/di/Container.js +250 -53
  15. package/dist/elements/BaseElement.d.ts.map +1 -1
  16. package/dist/elements/BaseElement.js +5 -10
  17. package/dist/elements/base/BaseElementManager.d.ts +22 -0
  18. package/dist/elements/base/BaseElementManager.d.ts.map +1 -1
  19. package/dist/elements/base/BaseElementManager.js +47 -7
  20. package/dist/elements/memories/Memory.d.ts +1 -0
  21. package/dist/elements/memories/Memory.d.ts.map +1 -1
  22. package/dist/elements/memories/Memory.js +12 -8
  23. package/dist/elements/memories/MemoryManager.d.ts.map +1 -1
  24. package/dist/elements/memories/MemoryManager.js +23 -42
  25. package/dist/elements/memories/MemorySearchIndex.js +2 -2
  26. package/dist/generated/version.d.ts +2 -2
  27. package/dist/generated/version.d.ts.map +1 -1
  28. package/dist/generated/version.js +3 -3
  29. package/dist/handlers/EnhancedIndexHandler.js +6 -6
  30. package/dist/handlers/element-crud/listElements.d.ts +2 -0
  31. package/dist/handlers/element-crud/listElements.d.ts.map +1 -1
  32. package/dist/handlers/element-crud/listElements.js +3 -1
  33. package/dist/handlers/mcp-aql/Gatekeeper.d.ts.map +1 -1
  34. package/dist/handlers/mcp-aql/Gatekeeper.js +23 -17
  35. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts +14 -0
  36. package/dist/handlers/mcp-aql/MCPAQLHandler.d.ts.map +1 -1
  37. package/dist/handlers/mcp-aql/MCPAQLHandler.js +110 -14
  38. package/dist/handlers/mcp-aql/OperationRouter.d.ts.map +1 -1
  39. package/dist/handlers/mcp-aql/OperationRouter.js +13 -1
  40. package/dist/handlers/mcp-aql/OperationSchema.d.ts +7 -0
  41. package/dist/handlers/mcp-aql/OperationSchema.d.ts.map +1 -1
  42. package/dist/handlers/mcp-aql/OperationSchema.js +52 -1
  43. package/dist/handlers/mcp-aql/evaluatePermission.d.ts +53 -0
  44. package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -0
  45. package/dist/handlers/mcp-aql/evaluatePermission.js +132 -0
  46. package/dist/handlers/mcp-aql/policies/ToolClassification.d.ts.map +1 -1
  47. package/dist/handlers/mcp-aql/policies/ToolClassification.js +2 -1
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +3 -3
  50. package/dist/logging/LogHooks.js +11 -11
  51. package/dist/logging/LogManager.d.ts +0 -2
  52. package/dist/logging/LogManager.d.ts.map +1 -1
  53. package/dist/logging/LogManager.js +1 -3
  54. package/dist/logging/sinks/MemoryLogSink.d.ts +2 -0
  55. package/dist/logging/sinks/MemoryLogSink.d.ts.map +1 -1
  56. package/dist/logging/sinks/MemoryLogSink.js +12 -3
  57. package/dist/logging/types.d.ts +0 -2
  58. package/dist/logging/types.d.ts.map +1 -1
  59. package/dist/logging/types.js +1 -1
  60. package/dist/metrics/GatekeeperMetricsTracker.d.ts +32 -0
  61. package/dist/metrics/GatekeeperMetricsTracker.d.ts.map +1 -0
  62. package/dist/metrics/GatekeeperMetricsTracker.js +42 -0
  63. package/dist/metrics/MetricsManager.d.ts +47 -0
  64. package/dist/metrics/MetricsManager.d.ts.map +1 -0
  65. package/dist/metrics/MetricsManager.js +232 -0
  66. package/dist/metrics/OperationMetricsTracker.d.ts +32 -0
  67. package/dist/metrics/OperationMetricsTracker.d.ts.map +1 -0
  68. package/dist/metrics/OperationMetricsTracker.js +53 -0
  69. package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts +27 -0
  70. package/dist/metrics/collectors/DefaultElementProviderCollector.d.ts.map +1 -0
  71. package/dist/metrics/collectors/DefaultElementProviderCollector.js +69 -0
  72. package/dist/metrics/collectors/FileLockManagerCollector.d.ts +16 -0
  73. package/dist/metrics/collectors/FileLockManagerCollector.d.ts.map +1 -0
  74. package/dist/metrics/collectors/FileLockManagerCollector.js +51 -0
  75. package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts +16 -0
  76. package/dist/metrics/collectors/GatekeeperMetricsCollector.d.ts.map +1 -0
  77. package/dist/metrics/collectors/GatekeeperMetricsCollector.js +76 -0
  78. package/dist/metrics/collectors/LRUCacheCollector.d.ts +18 -0
  79. package/dist/metrics/collectors/LRUCacheCollector.d.ts.map +1 -0
  80. package/dist/metrics/collectors/LRUCacheCollector.js +95 -0
  81. package/dist/metrics/collectors/OperationMetricsCollector.d.ts +16 -0
  82. package/dist/metrics/collectors/OperationMetricsCollector.d.ts.map +1 -0
  83. package/dist/metrics/collectors/OperationMetricsCollector.js +80 -0
  84. package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts +17 -0
  85. package/dist/metrics/collectors/OperationalTelemetryCollector.d.ts.map +1 -0
  86. package/dist/metrics/collectors/OperationalTelemetryCollector.js +26 -0
  87. package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts +14 -0
  88. package/dist/metrics/collectors/PerformanceMonitorCollector.d.ts.map +1 -0
  89. package/dist/metrics/collectors/PerformanceMonitorCollector.js +141 -0
  90. package/dist/metrics/collectors/SecurityMonitorCollector.d.ts +21 -0
  91. package/dist/metrics/collectors/SecurityMonitorCollector.d.ts.map +1 -0
  92. package/dist/metrics/collectors/SecurityMonitorCollector.js +56 -0
  93. package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts +15 -0
  94. package/dist/metrics/collectors/SecurityTelemetryCollector.d.ts.map +1 -0
  95. package/dist/metrics/collectors/SecurityTelemetryCollector.js +112 -0
  96. package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts +16 -0
  97. package/dist/metrics/collectors/TriggerMetricsTrackerCollector.d.ts.map +1 -0
  98. package/dist/metrics/collectors/TriggerMetricsTrackerCollector.js +26 -0
  99. package/dist/metrics/collectors/index.d.ts +11 -0
  100. package/dist/metrics/collectors/index.d.ts.map +1 -0
  101. package/dist/metrics/collectors/index.js +11 -0
  102. package/dist/metrics/sinks/MemoryMetricsSink.d.ts +22 -0
  103. package/dist/metrics/sinks/MemoryMetricsSink.d.ts.map +1 -0
  104. package/dist/metrics/sinks/MemoryMetricsSink.js +121 -0
  105. package/dist/metrics/types.d.ts +98 -0
  106. package/dist/metrics/types.d.ts.map +1 -0
  107. package/dist/metrics/types.js +24 -0
  108. package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
  109. package/dist/portfolio/DefaultElementProvider.js +1 -7
  110. package/dist/portfolio/EnhancedIndexManager.d.ts.map +1 -1
  111. package/dist/portfolio/EnhancedIndexManager.js +18 -18
  112. package/dist/portfolio/NLPScoringManager.d.ts.map +1 -1
  113. package/dist/portfolio/NLPScoringManager.js +5 -9
  114. package/dist/portfolio/PortfolioIndexManager.js +2 -2
  115. package/dist/portfolio/RelationshipManager.js +2 -2
  116. package/dist/portfolio/VerbTriggerManager.d.ts.map +1 -1
  117. package/dist/portfolio/VerbTriggerManager.js +5 -19
  118. package/dist/portfolio/config/IndexConfig.d.ts.map +1 -1
  119. package/dist/portfolio/config/IndexConfig.js +1 -12
  120. package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.d.ts.map +1 -1
  121. package/dist/portfolio/enhanced-index/ElementDefinitionBuilder.js +3 -15
  122. package/dist/portfolio/enhanced-index/SemanticRelationshipService.d.ts.map +1 -1
  123. package/dist/portfolio/enhanced-index/SemanticRelationshipService.js +2 -16
  124. package/dist/portfolio/types/RelationshipTypes.d.ts.map +1 -1
  125. package/dist/portfolio/types/RelationshipTypes.js +3 -17
  126. package/dist/security/audit/config/suppressions.d.ts.map +1 -1
  127. package/dist/security/audit/config/suppressions.js +36 -8
  128. package/dist/security/constants.d.ts.map +1 -1
  129. package/dist/security/constants.js +10 -6
  130. package/dist/security/fileLockManager.d.ts.map +1 -1
  131. package/dist/security/fileLockManager.js +8 -6
  132. package/dist/security/secureYamlParser.d.ts.map +1 -1
  133. package/dist/security/secureYamlParser.js +1 -13
  134. package/dist/security/securityMonitor.d.ts +2 -1
  135. package/dist/security/securityMonitor.d.ts.map +1 -1
  136. package/dist/security/securityMonitor.js +14 -3
  137. package/dist/security/telemetry/SecurityTelemetry.d.ts +16 -0
  138. package/dist/security/telemetry/SecurityTelemetry.d.ts.map +1 -1
  139. package/dist/security/telemetry/SecurityTelemetry.js +30 -2
  140. package/dist/security/tokenManager.d.ts +3 -0
  141. package/dist/security/tokenManager.d.ts.map +1 -1
  142. package/dist/security/tokenManager.js +13 -5
  143. package/dist/security/validation/BackgroundValidator.d.ts.map +1 -1
  144. package/dist/security/validation/BackgroundValidator.js +7 -7
  145. package/dist/server/startup.d.ts.map +1 -1
  146. package/dist/server/startup.js +8 -24
  147. package/dist/server/tools/MCPAQLTools.js +4 -1
  148. package/dist/services/ActivationStore.d.ts.map +1 -1
  149. package/dist/services/ActivationStore.js +9 -3
  150. package/dist/services/FileWatchService.d.ts +1 -0
  151. package/dist/services/FileWatchService.d.ts.map +1 -1
  152. package/dist/services/FileWatchService.js +83 -48
  153. package/dist/services/MetadataService.d.ts.map +1 -1
  154. package/dist/services/MetadataService.js +7 -2
  155. package/dist/services/query/ElementQueryService.d.ts.map +1 -1
  156. package/dist/services/query/ElementQueryService.js +1 -41
  157. package/dist/services/query/PaginationService.d.ts.map +1 -1
  158. package/dist/services/query/PaginationService.js +1 -14
  159. package/dist/services/query/SortService.d.ts.map +1 -1
  160. package/dist/services/query/SortService.js +1 -6
  161. package/dist/services/validation/ValidationService.d.ts.map +1 -1
  162. package/dist/services/validation/ValidationService.js +3 -8
  163. package/dist/storage/ElementStorageLayer.d.ts.map +1 -1
  164. package/dist/storage/ElementStorageLayer.js +5 -2
  165. package/dist/storage/MemoryStorageLayer.d.ts.map +1 -1
  166. package/dist/storage/MemoryStorageLayer.js +5 -2
  167. package/dist/telemetry/OperationalTelemetry.js +2 -2
  168. package/dist/utils/EventDeduplicator.d.ts +44 -0
  169. package/dist/utils/EventDeduplicator.d.ts.map +1 -0
  170. package/dist/utils/EventDeduplicator.js +93 -0
  171. package/dist/utils/FileLock.d.ts.map +1 -1
  172. package/dist/utils/FileLock.js +1 -9
  173. package/dist/utils/PerformanceMonitor.d.ts.map +1 -1
  174. package/dist/utils/PerformanceMonitor.js +5 -5
  175. package/dist/utils/SlidingWindowRateLimiter.d.ts +13 -0
  176. package/dist/utils/SlidingWindowRateLimiter.d.ts.map +1 -0
  177. package/dist/utils/SlidingWindowRateLimiter.js +23 -0
  178. package/dist/web/console/IngestRoutes.d.ts +84 -0
  179. package/dist/web/console/IngestRoutes.d.ts.map +1 -0
  180. package/dist/web/console/IngestRoutes.js +252 -0
  181. package/dist/web/console/LeaderElection.d.ts +89 -0
  182. package/dist/web/console/LeaderElection.d.ts.map +1 -0
  183. package/dist/web/console/LeaderElection.js +205 -0
  184. package/dist/web/console/LeaderForwardingSink.d.ts +61 -0
  185. package/dist/web/console/LeaderForwardingSink.d.ts.map +1 -0
  186. package/dist/web/console/LeaderForwardingSink.js +197 -0
  187. package/dist/web/console/SessionNames.d.ts +46 -0
  188. package/dist/web/console/SessionNames.d.ts.map +1 -0
  189. package/dist/web/console/SessionNames.js +257 -0
  190. package/dist/web/console/UnifiedConsole.d.ts +64 -0
  191. package/dist/web/console/UnifiedConsole.d.ts.map +1 -0
  192. package/dist/web/console/UnifiedConsole.js +119 -0
  193. package/dist/web/contentPipeline.d.ts +58 -0
  194. package/dist/web/contentPipeline.d.ts.map +1 -0
  195. package/dist/web/contentPipeline.js +112 -0
  196. package/dist/web/portDiscovery.d.ts +58 -0
  197. package/dist/web/portDiscovery.d.ts.map +1 -0
  198. package/dist/web/portDiscovery.js +143 -0
  199. package/dist/web/public/app.js +148 -60
  200. package/dist/web/public/logs.js +638 -0
  201. package/dist/web/public/metrics.js +682 -0
  202. package/dist/web/public/permissions.js +394 -0
  203. package/dist/web/public/sessions.js +369 -0
  204. package/dist/web/routes/healthRoutes.d.ts +16 -0
  205. package/dist/web/routes/healthRoutes.d.ts.map +1 -0
  206. package/dist/web/routes/healthRoutes.js +29 -0
  207. package/dist/web/routes/logRoutes.d.ts +18 -0
  208. package/dist/web/routes/logRoutes.d.ts.map +1 -0
  209. package/dist/web/routes/logRoutes.js +126 -0
  210. package/dist/web/routes/metricsRoutes.d.ts +17 -0
  211. package/dist/web/routes/metricsRoutes.d.ts.map +1 -0
  212. package/dist/web/routes/metricsRoutes.js +90 -0
  213. package/dist/web/routes/permissionRoutes.d.ts +16 -0
  214. package/dist/web/routes/permissionRoutes.d.ts.map +1 -0
  215. package/dist/web/routes/permissionRoutes.js +133 -0
  216. package/dist/web/routes.d.ts.map +1 -1
  217. package/dist/web/routes.js +309 -339
  218. package/dist/web/server.d.ts +21 -1
  219. package/dist/web/server.d.ts.map +1 -1
  220. package/dist/web/server.js +42 -4
  221. package/dist/web/sinks/WebSSELogSink.d.ts +15 -0
  222. package/dist/web/sinks/WebSSELogSink.d.ts.map +1 -0
  223. package/dist/web/sinks/WebSSELogSink.js +22 -0
  224. package/dist/web/sinks/WebSSEMetricsSink.d.ts +16 -0
  225. package/dist/web/sinks/WebSSEMetricsSink.d.ts.map +1 -0
  226. package/dist/web/sinks/WebSSEMetricsSink.js +23 -0
  227. package/package.json +2 -2
  228. package/server.json +2 -2
  229. package/dist/constants/version.d.ts +0 -3
  230. package/dist/constants/version.d.ts.map +0 -1
  231. package/dist/constants/version.js +0 -4
  232. package/dist/logging/sinks/SSELogSink.d.ts +0 -35
  233. package/dist/logging/sinks/SSELogSink.d.ts.map +0 -1
  234. package/dist/logging/sinks/SSELogSink.js +0 -181
  235. package/dist/logging/viewer/viewerHtml.d.ts +0 -8
  236. package/dist/logging/viewer/viewerHtml.d.ts.map +0 -1
  237. package/dist/logging/viewer/viewerHtml.js +0 -204
  238. package/dist/web/public/public/app.js +0 -1878
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Metrics API routes for the unified dev console.
3
+ *
4
+ * Mounts on the existing Express app to provide:
5
+ * - GET /api/metrics — JSON query (delegates to MemoryMetricsSink)
6
+ * - GET /api/metrics/stream — SSE endpoint, pushes each new snapshot
7
+ */
8
+ import { Router } from 'express';
9
+ import { UnicodeValidator } from '../../security/validators/unicodeValidator.js';
10
+ function normalizedStringParam(query, key) {
11
+ const val = query[key];
12
+ if (typeof val === 'string' && val) {
13
+ return UnicodeValidator.normalize(val).normalizedContent;
14
+ }
15
+ return undefined;
16
+ }
17
+ function parseMetricsQueryOptions(query) {
18
+ const options = {};
19
+ const names = normalizedStringParam(query, 'names');
20
+ if (names)
21
+ options['names'] = names.split(',').map(s => s.trim());
22
+ const source = normalizedStringParam(query, 'source');
23
+ if (source)
24
+ options['source'] = source;
25
+ const type = normalizedStringParam(query, 'type');
26
+ if (type)
27
+ options['type'] = type;
28
+ for (const field of ['since', 'until']) {
29
+ if (typeof query[field] === 'string' && query[field])
30
+ options[field] = query[field];
31
+ }
32
+ if (typeof query['latest'] === 'string') {
33
+ options['latest'] = query['latest'] !== 'false';
34
+ }
35
+ for (const field of ['limit', 'offset']) {
36
+ if (typeof query[field] === 'string') {
37
+ const parsed = Number.parseInt(query[field], 10);
38
+ if (!Number.isNaN(parsed))
39
+ options[field] = parsed;
40
+ }
41
+ }
42
+ return options;
43
+ }
44
+ export function createMetricsRoutes(metricsSink) {
45
+ const router = Router();
46
+ const clients = new Set();
47
+ // GET /api/metrics — JSON query
48
+ router.get('/metrics', (req, res) => {
49
+ const result = metricsSink.query(parseMetricsQueryOptions(req.query));
50
+ res.json(result);
51
+ });
52
+ // GET /api/metrics/stream — SSE endpoint for real-time metric snapshots.
53
+ // Currently unused by the built-in web console (which polls /api/metrics).
54
+ // Retained for third-party consumers (Prometheus, Grafana agent, custom dashboards)
55
+ // that benefit from push-based metric delivery.
56
+ router.get('/metrics/stream', (req, res) => {
57
+ res.writeHead(200, {
58
+ 'Content-Type': 'text/event-stream',
59
+ 'Cache-Control': 'no-cache',
60
+ 'Connection': 'keep-alive',
61
+ });
62
+ res.write(':connected\n\n');
63
+ const client = { res };
64
+ clients.add(client);
65
+ // Keep-alive heartbeat — prevents proxies from closing idle connections
66
+ const heartbeat = setInterval(() => {
67
+ res.write(': heartbeat\n\n');
68
+ }, 30_000);
69
+ req.on('close', () => {
70
+ clearInterval(heartbeat);
71
+ clients.delete(client);
72
+ });
73
+ });
74
+ function onSnapshot(snapshot) {
75
+ const data = JSON.stringify(snapshot);
76
+ for (const client of clients) {
77
+ if (client.res.destroyed) {
78
+ clients.delete(client);
79
+ continue;
80
+ }
81
+ client.res.write(`data: ${data}\n\n`);
82
+ }
83
+ }
84
+ return {
85
+ router,
86
+ onSnapshot,
87
+ clientCount: () => clients.size,
88
+ };
89
+ }
90
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljc1JvdXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93ZWIvcm91dGVzL21ldHJpY3NSb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUlqQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQztBQVlqRixTQUFTLHFCQUFxQixDQUFDLEtBQXVCLEVBQUUsR0FBVztJQUNqRSxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkIsSUFBSSxPQUFPLEdBQUcsS0FBSyxRQUFRLElBQUksR0FBRyxFQUFFLENBQUM7UUFDbkMsT0FBTyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsaUJBQWlCLENBQUM7SUFDM0QsQ0FBQztJQUNELE9BQU8sU0FBUyxDQUFDO0FBQ25CLENBQUM7QUFFRCxTQUFTLHdCQUF3QixDQUFDLEtBQXVCO0lBQ3ZELE1BQU0sT0FBTyxHQUE0QixFQUFFLENBQUM7SUFFNUMsTUFBTSxLQUFLLEdBQUcscUJBQXFCLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3BELElBQUksS0FBSztRQUFFLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRWxFLE1BQU0sTUFBTSxHQUFHLHFCQUFxQixDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN0RCxJQUFJLE1BQU07UUFBRSxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUcsTUFBTSxDQUFDO0lBRXZDLE1BQU0sSUFBSSxHQUFHLHFCQUFxQixDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FB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QU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzdCLElBQUksTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUFDLFNBQVM7WUFBQyxDQUFDO1lBQy9ELE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsSUFBSSxNQUFNLENBQUMsQ0FBQztRQUN4QyxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxNQUFNO1FBQ04sVUFBVTtRQUNWLFdBQVcsRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSTtLQUNoQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTWV0cmljcyBBUEkgcm91dGVzIGZvciB0aGUgdW5pZmllZCBkZXYgY29uc29sZS5cbiAqXG4gKiBNb3VudHMgb24gdGhlIGV4aXN0aW5nIEV4cHJlc3MgYXBwIHRvIHByb3ZpZGU6XG4gKiAtIEdFVCAvYXBpL21ldHJpY3MgICAgICAgIOKAlCBKU09OIHF1ZXJ5IChkZWxlZ2F0ZXMgdG8gTWVtb3J5TWV0cmljc1NpbmspXG4gKiAtIEdFVCAvYXBpL21ldHJpY3Mvc3RyZWFtIOKAlCBTU0UgZW5kcG9pbnQsIHB1c2hlcyBlYWNoIG5ldyBzbmFwc2hvdFxuICovXG5cbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHR5cGUgeyBNZW1vcnlNZXRyaWNzU2luayB9IGZyb20gJy4uLy4uL21ldHJpY3Mvc2lua3MvTWVtb3J5TWV0cmljc1NpbmsuanMnO1xuaW1wb3J0IHR5cGUgeyBNZXRyaWNTbmFwc2hvdCwgTWV0cmljVHlwZSB9IGZyb20gJy4uLy4uL21ldHJpY3MvdHlwZXMuanMnO1xuaW1wb3J0IHsgVW5pY29kZVZhbGlkYXRvciB9IGZyb20gJy4uLy4uL3NlY3VyaXR5L3ZhbGlkYXRvcnMvdW5pY29kZVZhbGlkYXRvci5qcyc7XG5cbmludGVyZmFjZSBTU0VDbGllbnQge1xuICByZXM6IFJlc3BvbnNlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1ldHJpY3NSb3V0ZXNSZXN1bHQge1xuICByb3V0ZXI6IFJvdXRlcjtcbiAgb25TbmFwc2hvdDogKHNuYXBzaG90OiBNZXRyaWNTbmFwc2hvdCkgPT4gdm9pZDtcbiAgY2xpZW50Q291bnQ6ICgpID0+IG51bWJlcjtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplZFN0cmluZ1BhcmFtKHF1ZXJ5OiBSZXF1ZXN0WydxdWVyeSddLCBrZXk6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHZhbCA9IHF1ZXJ5W2tleV07XG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJyAmJiB2YWwpIHtcbiAgICByZXR1cm4gVW5pY29kZVZhbGlkYXRvci5ub3JtYWxpemUodmFsKS5ub3JtYWxpemVkQ29udGVudDtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBwYXJzZU1ldHJpY3NRdWVyeU9wdGlvbnMocXVlcnk6IFJlcXVlc3RbJ3F1ZXJ5J10pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGNvbnN0IG9wdGlvbnM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG5cbiAgY29uc3QgbmFtZXMgPSBub3JtYWxpemVkU3RyaW5nUGFyYW0ocXVlcnksICduYW1lcycpO1xuICBpZiAobmFtZXMpIG9wdGlvbnNbJ25hbWVzJ10gPSBuYW1lcy5zcGxpdCgnLCcpLm1hcChzID0+IHMudHJpbSgpKTtcblxuICBjb25zdCBzb3VyY2UgPSBub3JtYWxpemVkU3RyaW5nUGFyYW0ocXVlcnksICdzb3VyY2UnKTtcbiAgaWYgKHNvdXJjZSkgb3B0aW9uc1snc291cmNlJ10gPSBzb3VyY2U7XG5cbiAgY29uc3QgdHlwZSA9IG5vcm1hbGl6ZWRTdHJpbmdQYXJhbShxdWVyeSwgJ3R5cGUnKTtcbiAgaWYgKHR5cGUpIG9wdGlvbnNbJ3R5cGUnXSA9IHR5cGUgYXMgTWV0cmljVHlwZTtcblxuICBmb3IgKGNvbnN0IGZpZWxkIG9mIFsnc2luY2UnLCAndW50aWwnXSBhcyBjb25zdCkge1xuICAgIGlmICh0eXBlb2YgcXVlcnlbZmllbGRdID09PSAnc3RyaW5nJyAmJiBxdWVyeVtmaWVsZF0pIG9wdGlvbnNbZmllbGRdID0gcXVlcnlbZmllbGRdO1xuICB9XG4gIGlmICh0eXBlb2YgcXVlcnlbJ2xhdGVzdCddID09PSAnc3RyaW5nJykge1xuICAgIG9wdGlvbnNbJ2xhdGVzdCddID0gcXVlcnlbJ2xhdGVzdCddICE9PSAnZmFsc2UnO1xuICB9XG4gIGZvciAoY29uc3QgZmllbGQgb2YgWydsaW1pdCcsICdvZmZzZXQnXSBhcyBjb25zdCkge1xuICAgIGlmICh0eXBlb2YgcXVlcnlbZmllbGRdID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc3QgcGFyc2VkID0gTnVtYmVyLnBhcnNlSW50KHF1ZXJ5W2ZpZWxkXSwgMTApO1xuICAgICAgaWYgKCFOdW1iZXIuaXNOYU4ocGFyc2VkKSkgb3B0aW9uc1tmaWVsZF0gPSBwYXJzZWQ7XG4gICAgfVxuICB9XG4gIHJldHVybiBvcHRpb25zO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWV0cmljc1JvdXRlcyhtZXRyaWNzU2luazogTWVtb3J5TWV0cmljc1NpbmspOiBNZXRyaWNzUm91dGVzUmVzdWx0IHtcbiAgY29uc3Qgcm91dGVyID0gUm91dGVyKCk7XG4gIGNvbnN0IGNsaWVudHMgPSBuZXcgU2V0PFNTRUNsaWVudD4oKTtcblxuICAvLyBHRVQgL2FwaS9tZXRyaWNzIOKAlCBKU09OIHF1ZXJ5XG4gIHJvdXRlci5nZXQoJy9tZXRyaWNzJywgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IG1ldHJpY3NTaW5rLnF1ZXJ5KHBhcnNlTWV0cmljc1F1ZXJ5T3B0aW9ucyhyZXEucXVlcnkpKTtcbiAgICByZXMuanNvbihyZXN1bHQpO1xuICB9KTtcblxuICAvLyBHRVQgL2FwaS9tZXRyaWNzL3N0cmVhbSDigJQgU1NFIGVuZHBvaW50IGZvciByZWFsLXRpbWUgbWV0cmljIHNuYXBzaG90cy5cbiAgLy8gQ3VycmVudGx5IHVudXNlZCBieSB0aGUgYnVpbHQtaW4gd2ViIGNvbnNvbGUgKHdoaWNoIHBvbGxzIC9hcGkvbWV0cmljcykuXG4gIC8vIFJldGFpbmVkIGZvciB0aGlyZC1wYXJ0eSBjb25zdW1lcnMgKFByb21ldGhldXMsIEdyYWZhbmEgYWdlbnQsIGN1c3RvbSBkYXNoYm9hcmRzKVxuICAvLyB0aGF0IGJlbmVmaXQgZnJvbSBwdXNoLWJhc2VkIG1ldHJpYyBkZWxpdmVyeS5cbiAgcm91dGVyLmdldCgnL21ldHJpY3Mvc3RyZWFtJywgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7XG4gICAgICAnQ29udGVudC1UeXBlJzogJ3RleHQvZXZlbnQtc3RyZWFtJyxcbiAgICAgICdDYWNoZS1Db250cm9sJzogJ25vLWNhY2hlJyxcbiAgICAgICdDb25uZWN0aW9uJzogJ2tlZXAtYWxpdmUnLFxuICAgIH0pO1xuICAgIHJlcy53cml0ZSgnOmNvbm5lY3RlZFxcblxcbicpO1xuXG4gICAgY29uc3QgY2xpZW50OiBTU0VDbGllbnQgPSB7IHJlcyB9O1xuICAgIGNsaWVudHMuYWRkKGNsaWVudCk7XG5cbiAgICAvLyBLZWVwLWFsaXZlIGhlYXJ0YmVhdCDigJQgcHJldmVudHMgcHJveGllcyBmcm9tIGNsb3NpbmcgaWRsZSBjb25uZWN0aW9uc1xuICAgIGNvbnN0IGhlYXJ0YmVhdCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgIHJlcy53cml0ZSgnOiBoZWFydGJlYXRcXG5cXG4nKTtcbiAgICB9LCAzMF8wMDApO1xuXG4gICAgcmVxLm9uKCdjbG9zZScsICgpID0+IHtcbiAgICAgIGNsZWFySW50ZXJ2YWwoaGVhcnRiZWF0KTtcbiAgICAgIGNsaWVudHMuZGVsZXRlKGNsaWVudCk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIG9uU25hcHNob3Qoc25hcHNob3Q6IE1ldHJpY1NuYXBzaG90KTogdm9pZCB7XG4gICAgY29uc3QgZGF0YSA9IEpTT04uc3RyaW5naWZ5KHNuYXBzaG90KTtcbiAgICBmb3IgKGNvbnN0IGNsaWVudCBvZiBjbGllbnRzKSB7XG4gICAgICBpZiAoY2xpZW50LnJlcy5kZXN0cm95ZWQpIHsgY2xpZW50cy5kZWxldGUoY2xpZW50KTsgY29udGludWU7IH1cbiAgICAgIGNsaWVudC5yZXMud3JpdGUoYGRhdGE6ICR7ZGF0YX1cXG5cXG5gKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHJvdXRlcixcbiAgICBvblNuYXBzaG90LFxuICAgIGNsaWVudENvdW50OiAoKSA9PiBjbGllbnRzLnNpemUsXG4gIH07XG59XG4iXX0=
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Permission evaluation HTTP routes and decision tracking.
3
+ *
4
+ * Provides:
5
+ * - POST /evaluate_permission — evaluates tool permissions via MCP-AQL
6
+ * - GET /permissions/status — returns current policies and recent decisions
7
+ * - Decision tracking ring buffer for the live dashboard feed
8
+ */
9
+ import { Router } from 'express';
10
+ import type { MCPAQLHandler } from '../../handlers/mcp-aql/MCPAQLHandler.js';
11
+ /**
12
+ * Register permission-related routes on a gateway router.
13
+ * Must be called with the MCP-AQL handler for policy evaluation.
14
+ */
15
+ export declare function registerPermissionRoutes(router: Router, handler: MCPAQLHandler): void;
16
+ //# sourceMappingURL=permissionRoutes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissionRoutes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/permissionRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAkD7E;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,IAAI,CAiGrF"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Permission evaluation HTTP routes and decision tracking.
3
+ *
4
+ * Provides:
5
+ * - POST /evaluate_permission — evaluates tool permissions via MCP-AQL
6
+ * - GET /permissions/status — returns current policies and recent decisions
7
+ * - Decision tracking ring buffer for the live dashboard feed
8
+ */
9
+ import express from 'express';
10
+ import { logger } from '../../utils/logger.js';
11
+ import { SlidingWindowRateLimiter } from '../../utils/SlidingWindowRateLimiter.js';
12
+ const DECISION_BUFFER_SIZE = 200;
13
+ const recentDecisions = [];
14
+ let decisionCounter = 0;
15
+ /** Extract a string field from a record, trying multiple keys in order */
16
+ function extractString(obj, keys, fallback) {
17
+ for (const key of keys) {
18
+ const val = obj?.[key];
19
+ if (typeof val === 'string')
20
+ return val;
21
+ }
22
+ return fallback;
23
+ }
24
+ function trackDecision(toolName, input, result) {
25
+ const entry = {
26
+ id: `d-${++decisionCounter}`,
27
+ timestamp: new Date().toISOString(),
28
+ tool_name: toolName,
29
+ command: toolName === 'Bash' && typeof input?.command === 'string' ? input.command : undefined,
30
+ decision: extractString(result, ['decision', 'behavior'], 'unknown'),
31
+ reason: extractString(result, ['reason', 'message'], ''),
32
+ };
33
+ recentDecisions.unshift(entry);
34
+ if (recentDecisions.length > DECISION_BUFFER_SIZE) {
35
+ recentDecisions.length = DECISION_BUFFER_SIZE;
36
+ }
37
+ }
38
+ /** Helper to extract single result from MCP-AQL batch response */
39
+ function asSingleResult(results) {
40
+ if (Array.isArray(results))
41
+ return results[0] || { success: false, error: 'Empty result' };
42
+ return results;
43
+ }
44
+ /**
45
+ * Register permission-related routes on a gateway router.
46
+ * Must be called with the MCP-AQL handler for policy evaluation.
47
+ */
48
+ export function registerPermissionRoutes(router, handler) {
49
+ /**
50
+ * POST /api/evaluate_permission
51
+ * Permission evaluation endpoint for PreToolUse hooks.
52
+ * Routes through evaluate_permission MCP-AQL READ operation.
53
+ * Fail-open: returns allow on any error to avoid blocking the user.
54
+ */
55
+ const permissionLimiter = new SlidingWindowRateLimiter(120, 60_000);
56
+ router.post('/evaluate_permission', express.json(), async (req, res) => {
57
+ if (!permissionLimiter.tryAcquire()) {
58
+ res.json({ decision: 'allow' }); // fail open on rate limit
59
+ return;
60
+ }
61
+ const body = req.body;
62
+ // Unicode normalization (NFC) on string inputs to prevent homograph attacks
63
+ const tool_name = typeof body.tool_name === 'string' ? body.tool_name.normalize('NFC') : undefined;
64
+ const platform = typeof body.platform === 'string' ? body.platform.normalize('NFC') : undefined;
65
+ const input = body.input;
66
+ if (!tool_name) {
67
+ res.json({ decision: 'allow' }); // fail open on bad input
68
+ return;
69
+ }
70
+ try {
71
+ const opResult = asSingleResult(await handler.handleRead({
72
+ operation: 'evaluate_permission',
73
+ params: {
74
+ tool_name,
75
+ input: input || {},
76
+ platform: platform || 'claude_code',
77
+ },
78
+ }));
79
+ if (!opResult.success) {
80
+ logger.warn(`[WebUI/Gateway] evaluate_permission failed: ${opResult.error}`);
81
+ res.json({ decision: 'allow' }); // fail open
82
+ return;
83
+ }
84
+ // Track decision for live dashboard feed
85
+ trackDecision(tool_name, input || {}, opResult.data);
86
+ res.json(opResult.data);
87
+ }
88
+ catch (err) {
89
+ logger.error('[WebUI/Gateway] evaluate_permission error:', err);
90
+ res.json({ decision: 'allow' }); // fail open
91
+ }
92
+ });
93
+ /**
94
+ * GET /api/permissions/status
95
+ * Returns current permission policies and recent decisions
96
+ * for the live permissions dashboard.
97
+ */
98
+ router.get('/permissions/status', async (_req, res) => {
99
+ try {
100
+ const opResult = asSingleResult(await handler.handleRead({
101
+ operation: 'get_effective_cli_policies',
102
+ }));
103
+ if (!opResult.success) {
104
+ res.status(500).json({ error: opResult.error || 'Failed to get policies' });
105
+ return;
106
+ }
107
+ const data = opResult.data;
108
+ // Extract confirm patterns from elements
109
+ const elements = (data.elements || []);
110
+ const confirmPatterns = [];
111
+ for (const el of elements) {
112
+ const confirm = el.confirmPatterns;
113
+ if (confirm?.length)
114
+ confirmPatterns.push(...confirm);
115
+ }
116
+ res.json({
117
+ activeElementCount: data.activeElementCount,
118
+ hasAllowlist: data.hasAllowlist,
119
+ denyPatterns: data.combinedDenyPatterns,
120
+ allowPatterns: data.combinedAllowPatterns,
121
+ confirmPatterns,
122
+ elements,
123
+ permissionPromptActive: data.permissionPromptActive,
124
+ recentDecisions,
125
+ });
126
+ }
127
+ catch (err) {
128
+ logger.error('[WebUI/Gateway] permissions/status error:', err);
129
+ res.status(500).json({ error: 'Failed to get permission status' });
130
+ }
131
+ });
132
+ }
133
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvblJvdXRlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93ZWIvcm91dGVzL3Blcm1pc3Npb25Sb3V0ZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sT0FBbUIsTUFBTSxTQUFTLENBQUM7QUFDMUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRy9DLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLHlDQUF5QyxDQUFDO0FBY25GLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDO0FBQ2pDLE1BQU0sZUFBZSxHQUF5QixFQUFFLENBQUM7QUFDakQsSUFBSSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBRXhCLDBFQUEwRTtBQUMxRSxTQUFTLGFBQWEsQ0FBQyxHQUE0QixFQUFFLElBQWMsRUFBRSxRQUFnQjtJQUNuRixLQUFLLE1BQU0sR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3ZCLE1BQU0sR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZCLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUTtZQUFFLE9BQU8sR0FBRyxDQUFDO0lBQzFDLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsUUFBZ0IsRUFBRSxLQUE4QixFQUFFLE1BQStCO0lBQ3RHLE1BQU0sS0FBSyxHQUF1QjtRQUNoQyxFQUFFLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRTtRQUM1QixTQUFTLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7UUFDbkMsU0FBUyxFQUFFLFFBQVE7UUFDbkIsT0FBTyxFQUFFLFFBQVEsS0FBSyxNQUFNLElBQUksT0FBTyxLQUFLLEVBQUUsT0FBTyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMs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Q0FBQztnQkFDM0QsSUFBSSxPQUFPLEVBQUUsTUFBTTtvQkFBRSxlQUFlLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUM7WUFDeEQsQ0FBQztZQUVELEdBQUcsQ0FBQyxJQUFJLENBQUM7Z0JBQ1Asa0JBQWtCLEVBQUUsSUFBSSxDQUFDLGtCQUFrQjtnQkFDM0MsWUFBWSxFQUFFLElBQUksQ0FBQyxZQUFZO2dCQUMvQixZQUFZLEVBQUUsSUFBSSxDQUFDLG9CQUFvQjtnQkFDdkMsYUFBYSxFQUFFLElBQUksQ0FBQyxxQkFBcUI7Z0JBQ3pDLGVBQWU7Z0JBQ2YsUUFBUTtnQkFDUixzQkFBc0IsRUFBRSxJQUFJLENBQUMsc0JBQXNCO2dCQUNuRCxlQUFlO2FBQ2hCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQywyQ0FBMkMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUMvRCxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxpQ0FBaUMsRUFBRSxDQUFDLENBQUM7UUFDckUsQ0FBQztJQUNILENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUGVybWlzc2lvbiBldmFsdWF0aW9uIEhUVFAgcm91dGVzIGFuZCBkZWNpc2lvbiB0cmFja2luZy5cbiAqXG4gKiBQcm92aWRlczpcbiAqIC0gUE9TVCAvZXZhbHVhdGVfcGVybWlzc2lvbiDigJQgZXZhbHVhdGVzIHRvb2wgcGVybWlzc2lvbnMgdmlhIE1DUC1BUUxcbiAqIC0gR0VUIC9wZXJtaXNzaW9ucy9zdGF0dXMg4oCUIHJldHVybnMgY3VycmVudCBwb2xpY2llcyBhbmQgcmVjZW50IGRlY2lzaW9uc1xuICogLSBEZWNpc2lvbiB0cmFja2luZyByaW5nIGJ1ZmZlciBmb3IgdGhlIGxpdmUgZGFzaGJvYXJkIGZlZWRcbiAqL1xuXG5pbXBvcnQgZXhwcmVzcywgeyBSb3V0ZXIgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgdHlwZSB7IE1DUEFRTEhhbmRsZXIgfSBmcm9tICcuLi8uLi9oYW5kbGVycy9tY3AtYXFsL01DUEFRTEhhbmRsZXIuanMnO1xuXG5pbXBvcnQgeyBTbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIgfSBmcm9tICcuLi8uLi91dGlscy9TbGlkaW5nV2luZG93UmF0ZUxpbWl0ZXIuanMnO1xuXG4vLyDilIDilIAgUGVybWlzc2lvbiBEZWNpc2lvbiBUcmFja2luZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIFJpbmcgYnVmZmVyIG9mIHJlY2VudCBwZXJtaXNzaW9uIGRlY2lzaW9ucyBmb3IgdGhlIGxpdmUgZGFzaGJvYXJkIGZlZWQuXG5cbmludGVyZmFjZSBQZXJtaXNzaW9uRGVjaXNpb24ge1xuICBpZDogc3RyaW5nO1xuICB0aW1lc3RhbXA6IHN0cmluZztcbiAgdG9vbF9uYW1lOiBzdHJpbmc7XG4gIGNvbW1hbmQ/OiBzdHJpbmc7XG4gIGRlY2lzaW9uOiBzdHJpbmc7XG4gIHJlYXNvbj86IHN0cmluZztcbn1cblxuY29uc3QgREVDSVNJT05fQlVGRkVSX1NJWkUgPSAyMDA7XG5jb25zdCByZWNlbnREZWNpc2lvbnM6IFBlcm1pc3Npb25EZWNpc2lvbltdID0gW107XG5sZXQgZGVjaXNpb25Db3VudGVyID0gMDtcblxuLyoqIEV4dHJhY3QgYSBzdHJpbmcgZmllbGQgZnJvbSBhIHJlY29yZCwgdHJ5aW5nIG11bHRpcGxlIGtleXMgaW4gb3JkZXIgKi9cbmZ1bmN0aW9uIGV4dHJhY3RTdHJpbmcob2JqOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwga2V5czogc3RyaW5nW10sIGZhbGxiYWNrOiBzdHJpbmcpOiBzdHJpbmcge1xuICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgY29uc3QgdmFsID0gb2JqPy5ba2V5XTtcbiAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHJldHVybiB2YWw7XG4gIH1cbiAgcmV0dXJuIGZhbGxiYWNrO1xufVxuXG5mdW5jdGlvbiB0cmFja0RlY2lzaW9uKHRvb2xOYW1lOiBzdHJpbmcsIGlucHV0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgcmVzdWx0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IHZvaWQge1xuICBjb25zdCBlbnRyeTogUGVybWlzc2lvbkRlY2lzaW9uID0ge1xuICAgIGlkOiBgZC0keysrZGVjaXNpb25Db3VudGVyfWAsXG4gICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgdG9vbF9uYW1lOiB0b29sTmFtZSxcbiAgICBjb21tYW5kOiB0b29sTmFtZSA9PT0gJ0Jhc2gnICYmIHR5cGVvZiBpbnB1dD8uY29tbWFuZCA9PT0gJ3N0cmluZycgPyBpbnB1dC5jb21tYW5kIDogdW5kZWZpbmVkLFxuICAgIGRlY2lzaW9uOiBleHRyYWN0U3RyaW5nKHJlc3VsdCwgWydkZWNpc2lvbicsICdiZWhhdmlvciddLCAndW5rbm93bicpLFxuICAgIHJlYXNvbjogZXh0cmFjdFN0cmluZyhyZXN1bHQsIFsncmVhc29uJywgJ21lc3NhZ2UnXSwgJycpLFxuICB9O1xuICByZWNlbnREZWNpc2lvbnMudW5zaGlmdChlbnRyeSk7XG4gIGlmIChyZWNlbnREZWNpc2lvbnMubGVuZ3RoID4gREVDSVNJT05fQlVGRkVSX1NJWkUpIHtcbiAgICByZWNlbnREZWNpc2lvbnMubGVuZ3RoID0gREVDSVNJT05fQlVGRkVSX1NJWkU7XG4gIH1cbn1cblxuLyoqIEhlbHBlciB0byBleHRyYWN0IHNpbmdsZSByZXN1bHQgZnJvbSBNQ1AtQVFMIGJhdGNoIHJlc3BvbnNlICovXG5mdW5jdGlvbiBhc1NpbmdsZVJlc3VsdChyZXN1bHRzOiB1bmtub3duKTogeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHJlc3VsdHMpKSByZXR1cm4gcmVzdWx0c1swXSB8fCB7IHN1Y2Nlc3M6IGZhbHNlLCBlcnJvcjogJ0VtcHR5IHJlc3VsdCcgfTtcbiAgcmV0dXJuIHJlc3VsdHMgYXMgeyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogdW5rbm93bjsgZXJyb3I/OiBzdHJpbmcgfTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlciBwZXJtaXNzaW9uLXJlbGF0ZWQgcm91dGVzIG9uIGEgZ2F0ZXdheSByb3V0ZXIuXG4gKiBNdXN0IGJlIGNhbGxlZCB3aXRoIHRoZSBNQ1AtQVFMIGhhbmRsZXIgZm9yIHBvbGljeSBldmFsdWF0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJQZXJtaXNzaW9uUm91dGVzKHJvdXRlcjogUm91dGVyLCBoYW5kbGVyOiBNQ1BBUUxIYW5kbGVyKTogdm9pZCB7XG4gIC8qKlxuICAgKiBQT1NUIC9hcGkvZXZhbHVhdGVfcGVybWlzc2lvblxuICAgKiBQZXJtaXNzaW9uIGV2YWx1YXRpb24gZW5kcG9pbnQgZm9yIFByZVRvb2xVc2UgaG9va3MuXG4gICAqIFJvdXRlcyB0aHJvdWdoIGV2YWx1YXRlX3Blcm1pc3Npb24gTUNQLUFRTCBSRUFEIG9wZXJhdGlvbi5cbiAgICogRmFpbC1vcGVuOiByZXR1cm5zIGFsbG93IG9uIGFueSBlcnJvciB0byBhdm9pZCBibG9ja2luZyB0aGUgdXNlci5cbiAgICovXG4gIGNvbnN0IHBlcm1pc3Npb25MaW1pdGVyID0gbmV3IFNsaWRpbmdXaW5kb3dSYXRlTGltaXRlcigxMjAsIDYwXzAwMCk7XG4gIHJvdXRlci5wb3N0KCcvZXZhbHVhdGVfcGVybWlzc2lvbicsIGV4cHJlc3MuanNvbigpLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAgICBpZiAoIXBlcm1pc3Npb25MaW1pdGVyLnRyeUFjcXVpcmUoKSkge1xuICAgICAgcmVzLmpzb24oeyBkZWNpc2lvbjogJ2FsbG93JyB9KTsgLy8gZmFpbCBvcGVuIG9uIHJhdGUgbGltaXRcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBib2R5ID0gcmVxLmJvZHkgYXMge1xuICAgICAgdG9vbF9uYW1lPzogc3RyaW5nO1xuICAgICAgaW5wdXQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgIHBsYXRmb3JtPzogc3RyaW5nO1xuICAgIH07XG5cbiAgICAvLyBVbmljb2RlIG5vcm1hbGl6YXRpb24gKE5GQykgb24gc3RyaW5nIGlucHV0cyB0byBwcmV2ZW50IGhvbW9ncmFwaCBhdHRhY2tzXG4gICAgY29uc3QgdG9vbF9uYW1lID0gdHlwZW9mIGJvZHkudG9vbF9uYW1lID09PSAnc3RyaW5nJyA/IGJvZHkudG9vbF9uYW1lLm5vcm1hbGl6ZSgnTkZDJykgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcGxhdGZvcm0gPSB0eXBlb2YgYm9keS5wbGF0Zm9ybSA9PT0gJ3N0cmluZycgPyBib2R5LnBsYXRmb3JtLm5vcm1hbGl6ZSgnTkZDJykgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgaW5wdXQgPSBib2R5LmlucHV0O1xuXG4gICAgaWYgKCF0b29sX25hbWUpIHtcbiAgICAgIHJlcy5qc29uKHsgZGVjaXNpb246ICdhbGxvdycgfSk7IC8vIGZhaWwgb3BlbiBvbiBiYWQgaW5wdXRcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3BSZXN1bHQgPSBhc1NpbmdsZVJlc3VsdChhd2FpdCBoYW5kbGVyLmhhbmRsZVJlYWQoe1xuICAgICAgICBvcGVyYXRpb246ICdldmFsdWF0ZV9wZXJtaXNzaW9uJyxcbiAgICAgICAgcGFyYW1zOiB7XG4gICAgICAgICAgdG9vbF9uYW1lLFxuICAgICAgICAgIGlucHV0OiBpbnB1dCB8fCB7fSxcbiAgICAgICAgICBwbGF0Zm9ybTogcGxhdGZvcm0gfHwgJ2NsYXVkZV9jb2RlJyxcbiAgICAgICAgfSxcbiAgICAgIH0pKTtcblxuICAgICAgaWYgKCFvcFJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBbV2ViVUkvR2F0ZXdheV0gZXZhbHVhdGVfcGVybWlzc2lvbiBmYWlsZWQ6ICR7b3BSZXN1bHQuZXJyb3J9YCk7XG4gICAgICAgIHJlcy5qc29uKHsgZGVjaXNpb246ICdhbGxvdycgfSk7IC8vIGZhaWwgb3BlblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFRyYWNrIGRlY2lzaW9uIGZvciBsaXZlIGRhc2hib2FyZCBmZWVkXG4gICAgICB0cmFja0RlY2lzaW9uKHRvb2xfbmFtZSwgaW5wdXQgfHwge30sIG9wUmVzdWx0LmRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xuXG4gICAgICByZXMuanNvbihvcFJlc3VsdC5kYXRhKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignW1dlYlVJL0dhdGV3YXldIGV2YWx1YXRlX3Blcm1pc3Npb24gZXJyb3I6JywgZXJyKTtcbiAgICAgIHJlcy5qc29uKHsgZGVjaXNpb246ICdhbGxvdycgfSk7IC8vIGZhaWwgb3BlblxuICAgIH1cbiAgfSk7XG5cbiAgLyoqXG4gICAqIEdFVCAvYXBpL3Blcm1pc3Npb25zL3N0YXR1c1xuICAgKiBSZXR1cm5zIGN1cnJlbnQgcGVybWlzc2lvbiBwb2xpY2llcyBhbmQgcmVjZW50IGRlY2lzaW9uc1xuICAgKiBmb3IgdGhlIGxpdmUgcGVybWlzc2lvbnMgZGFzaGJvYXJkLlxuICAgKi9cbiAgcm91dGVyLmdldCgnL3Blcm1pc3Npb25zL3N0YXR1cycsIGFzeW5jIChfcmVxLCByZXMpID0+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3Qgb3BSZXN1bHQgPSBhc1NpbmdsZVJlc3VsdChhd2FpdCBoYW5kbGVyLmhhbmRsZVJlYWQoe1xuICAgICAgICBvcGVyYXRpb246ICdnZXRfZWZmZWN0aXZlX2NsaV9wb2xpY2llcycsXG4gICAgICB9KSk7XG5cbiAgICAgIGlmICghb3BSZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICByZXMuc3RhdHVzKDUwMCkuanNvbih7IGVycm9yOiBvcFJlc3VsdC5lcnJvciB8fCAnRmFpbGVkIHRvIGdldCBwb2xpY2llcycgfSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IG9wUmVzdWx0LmRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbiAgICAgIC8vIEV4dHJhY3QgY29uZmlybSBwYXR0ZXJucyBmcm9tIGVsZW1lbnRzXG4gICAgICBjb25zdCBlbGVtZW50cyA9IChkYXRhLmVsZW1lbnRzIHx8IFtdKSBhcyBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj47XG4gICAgICBjb25zdCBjb25maXJtUGF0dGVybnM6IHN0cmluZ1tdID0gW107XG4gICAgICBmb3IgKGNvbnN0IGVsIG9mIGVsZW1lbnRzKSB7XG4gICAgICAgIGNvbnN0IGNvbmZpcm0gPSBlbC5jb25maXJtUGF0dGVybnMgYXMgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmIChjb25maXJtPy5sZW5ndGgpIGNvbmZpcm1QYXR0ZXJucy5wdXNoKC4uLmNvbmZpcm0pO1xuICAgICAgfVxuXG4gICAgICByZXMuanNvbih7XG4gICAgICAgIGFjdGl2ZUVsZW1lbnRDb3VudDogZGF0YS5hY3RpdmVFbGVtZW50Q291bnQsXG4gICAgICAgIGhhc0FsbG93bGlzdDogZGF0YS5oYXNBbGxvd2xpc3QsXG4gICAgICAgIGRlbnlQYXR0ZXJuczogZGF0YS5jb21iaW5lZERlbnlQYXR0ZXJucyxcbiAgICAgICAgYWxsb3dQYXR0ZXJuczogZGF0YS5jb21iaW5lZEFsbG93UGF0dGVybnMsXG4gICAgICAgIGNvbmZpcm1QYXR0ZXJucyxcbiAgICAgICAgZWxlbWVudHMsXG4gICAgICAgIHBlcm1pc3Npb25Qcm9tcHRBY3RpdmU6IGRhdGEucGVybWlzc2lvblByb21wdEFjdGl2ZSxcbiAgICAgICAgcmVjZW50RGVjaXNpb25zLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ1tXZWJVSS9HYXRld2F5XSBwZXJtaXNzaW9ucy9zdGF0dXMgZXJyb3I6JywgZXJyKTtcbiAgICAgIHJlcy5zdGF0dXMoNTAwKS5qc29uKHsgZXJyb3I6ICdGYWlsZWQgdG8gZ2V0IHBlcm1pc3Npb24gc3RhdHVzJyB9KTtcbiAgICB9XG4gIH0pO1xufVxuIl19
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/web/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAK1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AA6E1E,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAsa5D;AA0BD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CA2P3F"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/web/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAM1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AAgd1E,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAiJ5D;AAqBD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CA0H3F"}