@coffeerunhobby/mcp-ha-connect 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/http.d.ts +28 -0
- package/dist/server/http.js +45 -4
- package/dist/server/http.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/CHANGELOG.md +35 -0
- package/openapi.json +1 -1
- package/package.json +1 -1
- package/src/server/http.ts +48 -4
- package/src/version.ts +1 -1
- package/tests/server/http.test.ts +115 -1
- package/CLAUDE.md +0 -403
package/dist/server/http.d.ts
CHANGED
|
@@ -37,6 +37,22 @@ export declare function applySecurityHeaders(res: ServerResponse): void;
|
|
|
37
37
|
* need that detail can query the authenticated MCP tools (e.g. `getVersion`).
|
|
38
38
|
*/
|
|
39
39
|
export declare function handleHealthCheck(res: ServerResponse): void;
|
|
40
|
+
/**
|
|
41
|
+
* Add CORS headers for REST API endpoints (always enabled for Open WebUI compatibility)
|
|
42
|
+
*/
|
|
43
|
+
export declare function addRestApiCors(req: IncomingMessage, res: ServerResponse): void;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a request path is served by the browser-facing REST surface
|
|
46
|
+
* (`/openapi.json`, the `/api/*` bridge, or the SSE events stream) and therefore
|
|
47
|
+
* must always carry CORS headers — INCLUDING on responses produced before the
|
|
48
|
+
* route handler runs (rate-limit 429, auth 401). If those rejections go back
|
|
49
|
+
* without `Access-Control-Allow-Origin`, the browser discards the response and
|
|
50
|
+
* surfaces it as an opaque "NetworkError when attempting to fetch resource",
|
|
51
|
+
* masking the real status (this is why an Open WebUI 401 looked like a network
|
|
52
|
+
* failure). `url` is the raw request URL (query string included); `urlPath` is
|
|
53
|
+
* the path-only form used to match the configurable SSE events path.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isRestApiCorsPath(url: string, urlPath: string, sseEventsPath: string): boolean;
|
|
40
56
|
/**
|
|
41
57
|
* Resolve the permission a REST `/api/*` route requires.
|
|
42
58
|
*
|
|
@@ -52,6 +68,18 @@ export declare function requiredRestPermission(method: string, pathname: string)
|
|
|
52
68
|
* These endpoints translate REST calls to Home Assistant API calls
|
|
53
69
|
*/
|
|
54
70
|
export declare function handleRestApi(req: IncomingMessage, res: ServerResponse, url: string, client: HaClient): Promise<void>;
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the public URL scheme, honoring `X-Forwarded-Proto` (set by Cloudflare /
|
|
73
|
+
* reverse proxies that TLS-terminate upstream). The header is validated against an
|
|
74
|
+
* allowlist so a spoofed value can't inject an arbitrary scheme; anything other than
|
|
75
|
+
* a literal `https` falls back to `http`. Comma-separated values (proxy chains) take
|
|
76
|
+
* the first hop.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resolveForwardedProto(headerValue: string | string[] | undefined): 'http' | 'https';
|
|
79
|
+
/**
|
|
80
|
+
* Generate OpenAPI spec for Open WebUI compatibility
|
|
81
|
+
*/
|
|
82
|
+
export declare function getOpenApiSpec(baseUrl: string): object;
|
|
55
83
|
/**
|
|
56
84
|
* Start HTTP server
|
|
57
85
|
*/
|
package/dist/server/http.js
CHANGED
|
@@ -131,13 +131,27 @@ export function handleHealthCheck(res) {
|
|
|
131
131
|
/**
|
|
132
132
|
* Add CORS headers for REST API endpoints (always enabled for Open WebUI compatibility)
|
|
133
133
|
*/
|
|
134
|
-
function addRestApiCors(req, res) {
|
|
134
|
+
export function addRestApiCors(req, res) {
|
|
135
135
|
const origin = req.headers.origin;
|
|
136
136
|
res.setHeader('Access-Control-Allow-Origin', origin ?? '*');
|
|
137
137
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
138
138
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
139
139
|
res.setHeader('Access-Control-Max-Age', '86400');
|
|
140
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Whether a request path is served by the browser-facing REST surface
|
|
143
|
+
* (`/openapi.json`, the `/api/*` bridge, or the SSE events stream) and therefore
|
|
144
|
+
* must always carry CORS headers — INCLUDING on responses produced before the
|
|
145
|
+
* route handler runs (rate-limit 429, auth 401). If those rejections go back
|
|
146
|
+
* without `Access-Control-Allow-Origin`, the browser discards the response and
|
|
147
|
+
* surfaces it as an opaque "NetworkError when attempting to fetch resource",
|
|
148
|
+
* masking the real status (this is why an Open WebUI 401 looked like a network
|
|
149
|
+
* failure). `url` is the raw request URL (query string included); `urlPath` is
|
|
150
|
+
* the path-only form used to match the configurable SSE events path.
|
|
151
|
+
*/
|
|
152
|
+
export function isRestApiCorsPath(url, urlPath, sseEventsPath) {
|
|
153
|
+
return url === '/openapi.json' || url.startsWith('/api/') || urlPath === sseEventsPath;
|
|
154
|
+
}
|
|
141
155
|
/**
|
|
142
156
|
* Resolve the permission a REST `/api/*` route requires.
|
|
143
157
|
*
|
|
@@ -290,10 +304,25 @@ export async function handleRestApi(req, res, url, client) {
|
|
|
290
304
|
});
|
|
291
305
|
}
|
|
292
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Resolve the public URL scheme, honoring `X-Forwarded-Proto` (set by Cloudflare /
|
|
309
|
+
* reverse proxies that TLS-terminate upstream). The header is validated against an
|
|
310
|
+
* allowlist so a spoofed value can't inject an arbitrary scheme; anything other than
|
|
311
|
+
* a literal `https` falls back to `http`. Comma-separated values (proxy chains) take
|
|
312
|
+
* the first hop.
|
|
313
|
+
*/
|
|
314
|
+
export function resolveForwardedProto(headerValue) {
|
|
315
|
+
const first = Array.isArray(headerValue) ? headerValue[0] : headerValue;
|
|
316
|
+
const proto = String(first ?? '')
|
|
317
|
+
.split(',')[0]
|
|
318
|
+
?.trim()
|
|
319
|
+
.toLowerCase();
|
|
320
|
+
return proto === 'https' ? 'https' : 'http';
|
|
321
|
+
}
|
|
293
322
|
/**
|
|
294
323
|
* Generate OpenAPI spec for Open WebUI compatibility
|
|
295
324
|
*/
|
|
296
|
-
function getOpenApiSpec(baseUrl) {
|
|
325
|
+
export function getOpenApiSpec(baseUrl) {
|
|
297
326
|
return {
|
|
298
327
|
openapi: '3.1.0',
|
|
299
328
|
info: {
|
|
@@ -529,7 +558,7 @@ export async function startHttpServer(options) {
|
|
|
529
558
|
const urlPath = url.split('?')[0];
|
|
530
559
|
// Handle OPTIONS (CORS preflight) - add CORS headers for REST API endpoints
|
|
531
560
|
if (req.method === 'OPTIONS') {
|
|
532
|
-
if (url
|
|
561
|
+
if (isRestApiCorsPath(url, urlPath, sseEventsPath)) {
|
|
533
562
|
addRestApiCors(req, res);
|
|
534
563
|
}
|
|
535
564
|
else {
|
|
@@ -539,6 +568,13 @@ export async function startHttpServer(options) {
|
|
|
539
568
|
res.end();
|
|
540
569
|
return;
|
|
541
570
|
}
|
|
571
|
+
// Apply CORS headers for the browser-facing REST surface BEFORE rate limiting
|
|
572
|
+
// and auth, so a 429 or 401 rejection still carries `Access-Control-Allow-Origin`.
|
|
573
|
+
// Otherwise the browser masks the real status as an opaque "NetworkError when
|
|
574
|
+
// attempting to fetch resource" (Open WebUI auth failures looked like this).
|
|
575
|
+
if (isRestApiCorsPath(url, urlPath, sseEventsPath)) {
|
|
576
|
+
addRestApiCors(req, res);
|
|
577
|
+
}
|
|
542
578
|
// Apply rate limiting (skip health checks and certain paths)
|
|
543
579
|
if (rateLimiter) {
|
|
544
580
|
const allowed = rateLimiter.middleware()(req, res);
|
|
@@ -571,7 +607,12 @@ export async function startHttpServer(options) {
|
|
|
571
607
|
// OpenAPI spec endpoint for Open WebUI compatibility
|
|
572
608
|
if (req.method === 'GET' && url === '/openapi.json') {
|
|
573
609
|
addRestApiCors(req, res);
|
|
574
|
-
|
|
610
|
+
// Honor X-Forwarded-Proto (set by Cloudflare / reverse proxies) so the advertised
|
|
611
|
+
// server URL is https when the public endpoint is TLS-terminated upstream. Without
|
|
612
|
+
// this, an https Open WebUI page is handed an http:// server URL and the browser
|
|
613
|
+
// blocks tool calls as mixed content ("NetworkError when attempting to fetch resource").
|
|
614
|
+
const scheme = resolveForwardedProto(req.headers['x-forwarded-proto']);
|
|
615
|
+
const baseUrl = `${scheme}://${req.headers.host ?? `${bindAddr}:${port}`}`;
|
|
575
616
|
sendJson(res, 200, getOpenApiSpec(baseUrl));
|
|
576
617
|
return;
|
|
577
618
|
}
|
package/dist/server/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAA6C,MAAM,WAAW,CAAC;AAGxG,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAA0D,MAAM,aAAa,CAAC;AAC1G,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAA6B,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AACxF,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAExC,oCAAoC;AACpC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAgC,CAAC;AAEzD;;;GAGG;AACH,SAAS,sBAAsB,CAAC,GAAmB;IACjD,MAAM,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IACpC,MAAM,WAAW,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEtC,uDAAuD;IACvD,GAAG,CAAC,GAAG,GAAG,UACR,KAAe,EACf,kBAAkD,EAClD,QAAqB;QAErB,wDAAwD;QACxD,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;YAC7D,GAAG,CAAC,SAAS,CAAC,eAAe,EAAE,aAAa,UAAU,EAAE,CAAC,CAAC;QAC5D,CAAC;QAED,kDAAkD;QAClD,IAAI,OAAO,kBAAkB,KAAK,UAAU,EAAE,CAAC;YAC7C,OAAO,WAAW,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,kBAAkB,KAAK,SAAS,EAAE,CAAC;YACrC,OAAO,WAAW,CAAC,KAAK,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAmB,CAAC;IAEpB,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAO1C;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,GAAoB,EAAE,WAAmB,cAAc;IAC/E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,IAAI,GAAG,CAAC,CAAC;QACb,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;YACxC,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACnE,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC;YACnB,IAAI,IAAI,GAAG,QAAQ,EAAE,CAAC;gBACpB,OAAO,GAAG,IAAI,CAAC;gBACf,MAAM,GAAG,GAAc,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;gBAC3D,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC;gBACrB,MAAM,CAAC,GAAG,CAAC,CAAC;gBACZ,GAAG,CAAC,OAAO,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACjB,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,SAAS,CAAC,CAAC;gBACnB,OAAO;YACT,CAAC;YACD,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAkB,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qEAAqE;AACrE,SAAS,eAAe,CAAC,KAAc;IACrC,MAAM,IAAI,GAAI,KAA+B,EAAE,UAAU,CAAC;IAC1D,OAAO,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AACrD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAmB;IACtD,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;IACnD,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;IACzC,GAAG,CAAC,SAAS,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,GAAmB,EAAE,UAAkB,EAAE,IAAa;IACtE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,UAAU,GAAG,UAAU,CAAC;IAC5B,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IAClD,GAAG,CAAC,SAAS,CAAC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAmB;IACnD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,GAAoB,EAAE,GAAmB;IAC/D,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;IAClC,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAM,IAAI,GAAG,CAAC,CAAC;IAC5D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,oBAAoB,CAAC,CAAC;IACpE,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,6BAA6B,CAAC,CAAC;IAC7E,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc,EAAE,QAAgB;IACrE,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAE/B,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;QAChB,IACE,QAAQ,KAAK,aAAa;YAC1B,QAAQ,KAAK,cAAc;YAC3B,QAAQ,KAAK,aAAa;YAC1B,QAAQ,KAAK,cAAc;YAC3B,wBAAwB,CAAC,IAAI,CAAC,QAAQ,CAAC;YACvC,0BAA0B,CAAC,IAAI,CAAC,QAAQ,CAAC;YACzC,yBAAyB,CAAC,IAAI,CAAC,QAAQ,CAAC,EACxC,CAAC;YACD,OAAO,UAAU,CAAC,KAAK,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,CAAC,KAAK,MAAM,IAAI,iCAAiC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrE,OAAO,UAAU,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAoB,EACpB,GAAmB,EACnB,GAAW,EACX,MAAgB;IAEhB,+BAA+B;IAC/B,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAEzB,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;IAEpC,kEAAkE;IAClE,MAAM,QAAQ,GAAG,sBAAsB,CAAC,GAAG,CAAC,MAAM,IAAI,KAAK,EAAE,QAAQ,CAAC,CAAC;IACvE,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,8CAA8C;QAC9C,MAAM,eAAe,GAAK,GAA4B,CAAC,IAAI,EAAE,KAAK,EAAE,WAAkC,IAAI,CAAC,CAAC;QAC5G,IAAI,CAAC,aAAa,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE;gBACxC,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,kBAAkB,CAAC,QAAQ,CAAC;gBACtC,GAAG,EAAE,kBAAkB,CAAC,eAAe,CAAC;aACzC,CAAC,CAAC;YACH,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;gBACjB,KAAK,EAAE,WAAW;gBAClB,OAAO,EAAE,sCAAsC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;aACzF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,0CAA0C;QAC1C,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YACvD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,0DAA0D;QAC1D,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9D,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,UAAU,EAAE,CAAC;YACvC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,KAAK,EAAE,CAAC;gBACV,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,QAAQ,YAAY,EAAE,CAAC,CAAC;YAChE,CAAC;YACD,OAAO;QACT,CAAC;QAED,qCAAqC;QACrC,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YACxD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAC3B,CAAC,CAAwB,EAAE,EAAE,CAC3B,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAChF,CAAC;YACF,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,sDAAsD;QACtD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QACjE,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,GAAG,kBAAkB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAwB,EAAE,EAAE,CAC1D,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,MAAM,GAAG,CAAC,CACrC,CAAC;YACF,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,8CAA8C;QAC9C,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,aAAa,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;YACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,EAAE,CAAC;YACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAC5B,CAAC,CAAiE,EAAE,EAAE,CACpE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACzC,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC7D,CAAC;YACF,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;YAC7B,OAAO;QACT,CAAC;QAED,kEAAkE;QAClE,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACjE,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,YAAY,EAAE,CAAC;YACzC,MAAM,QAAQ,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YACxE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACzD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,4CAA4C;QAC5C,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,QAAQ,KAAK,cAAc,EAAE,CAAC;YACxD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3C,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;gBACjB,UAAU,EAAE,QAAQ,CAAC,OAAO;gBAC5B,WAAW,EAAE,OAAO;aACrB,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,yDAAyD;QACzD,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC3E,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,YAAY,EAAE,CAAC;YAC1C,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;YACpD,MAAM,IAAI,GAAG,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAuE,CAAC;YAC1G,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC;gBACtC,MAAM;gBACN,OAAO;gBACP,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS;gBACnE,YAAY,EAAE,IAAI,EAAE,IAAI;aACzB,CAAC,CAAC;YACH,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC3B,OAAO;QACT,CAAC;QAED,YAAY;QACZ,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4EAA4E;QAC5E,IAAI,eAAe,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC,CAAC;YACrG,CAAC;YACD,OAAO;QACT,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/C,qEAAqE;QACrE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;YACjB,KAAK,EAAE,uBAAuB;YAC9B,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,OAAO;QACL,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE;YACJ,KAAK,EAAE,0BAA0B;YACjC,WAAW,EAAE,yEAAyE;YACtF,OAAO,EAAE,OAAO;SACjB;QACD,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;QAC3B,KAAK,EAAE;YACL,aAAa,EAAE;gBACb,GAAG,EAAE;oBACH,WAAW,EAAE,WAAW;oBACxB,OAAO,EAAE,2CAA2C;oBACpD,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,2BAA2B;4BACxC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE,EAAE;yBACpH;qBACF;iBACF;aACF;YACD,yBAAyB,EAAE;gBACzB,GAAG,EAAE;oBACH,WAAW,EAAE,UAAU;oBACvB,OAAO,EAAE,gCAAgC;oBACzC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,qCAAqC,EAAE,CAAC;oBAC/I,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,cAAc;4BAC3B,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE;yBAC1F;qBACF;iBACF;aACF;YACD,kCAAkC,EAAE;gBAClC,IAAI,EAAE;oBACJ,WAAW,EAAE,aAAa;oBAC1B,OAAO,EAAE,+BAA+B;oBACxC,UAAU,EAAE;wBACV,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,sCAAsC,EAAE;wBAC/H,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE;qBACnI;oBACD,WAAW,EAAE;wBACX,OAAO,EAAE;4BACP,kBAAkB,EAAE;gCAClB,MAAM,EAAE;oCACN,IAAI,EAAE,QAAQ;oCACd,UAAU,EAAE;wCACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;wCAC9D,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;qCACtD;iCACF;6BACF;yBACF;qBACF;oBACD,SAAS,EAAE,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,qBAAqB,EAAE,EAAE;iBAC7D;aACF;YACD,cAAc,EAAE;gBACd,GAAG,EAAE;oBACH,WAAW,EAAE,eAAe;oBAC5B,OAAO,EAAE,yCAAyC;oBAClD,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,uBAAuB;4BACpC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE,EAAE;yBACpH;qBACF;iBACF;aACF;YACD,wBAAwB,EAAE;gBACxB,GAAG,EAAE;oBACH,WAAW,EAAE,qBAAqB;oBAClC,OAAO,EAAE,wCAAwC;oBACjD,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;oBAC1I,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,4BAA4B;4BACzC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE,EAAE;yBACpH;qBACF;iBACF;aACF;YACD,aAAa,EAAE;gBACb,GAAG,EAAE;oBACH,WAAW,EAAE,gBAAgB;oBAC7B,OAAO,EAAE,+BAA+B;oBACxC,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;oBACjH,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,mBAAmB;4BAChC,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE,EAAE;yBACpH;qBACF;iBACF;aACF;YACD,0BAA0B,EAAE;gBAC1B,GAAG,EAAE;oBACH,WAAW,EAAE,YAAY;oBACzB,OAAO,EAAE,mCAAmC;oBAC5C,UAAU,EAAE;wBACV,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE;wBACvG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE;qBACzG;oBACD,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,iBAAiB;4BAC9B,OAAO,EAAE,EAAE,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;yBAC/D;qBACF;iBACF;aACF;YACD,cAAc,EAAE;gBACd,GAAG,EAAE;oBACH,WAAW,EAAE,YAAY;oBACzB,OAAO,EAAE,wCAAwC;oBACjD,SAAS,EAAE;wBACT,KAAK,EAAE;4BACL,WAAW,EAAE,qBAAqB;4BAClC,OAAO,EAAE;gCACP,kBAAkB,EAAE;oCAClB,MAAM,EAAE;wCACN,IAAI,EAAE,QAAQ;wCACd,UAAU,EAAE;4CACV,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;4CACrE,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;yCACnE;qCACF;iCACF;6BACF;yBACF;qBACF;iBACF;aACF;SACF;QACD,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAC9B,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBAChC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBACjC;iBACF;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,GAAoB,EAAE,GAAmB,EAAE,MAAyB;IACtF,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;IAClC,MAAM,cAAc,GAAG,MAAM,CAAC,kBAAkB,IAAI,EAAE,CAAC;IAEvD,0DAA0D;IAC1D,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC/E,GAAG,CAAC,SAAS,CAAC,6BAA6B,EAAE,MAAM,IAAI,GAAG,CAAC,CAAC;QAC5D,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,4BAA4B,CAAC,CAAC;QAC5E,GAAG,CAAC,SAAS,CAAC,8BAA8B,EAAE,6CAA6C,CAAC,CAAC;QAC7F,GAAG,CAAC,SAAS,CAAC,wBAAwB,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAYD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAA0B;IAC9D,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IACpE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC;IACrC,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,IAAI,WAAW,CAAC;IACpD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,mBAAmB,IAAI,SAAS,CAAC;IAC3D,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,mBAAmB,CAAC;IAElE,qCAAqC;IACrC,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB;QACzC,CAAC,CAAC,IAAI,WAAW,CAAC;YACd,QAAQ,EAAE,MAAM,CAAC,iBAAiB;YAClC,WAAW,EAAE,MAAM,CAAC,oBAAoB;YACxC,SAAS,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;YACxC,6DAA6D;YAC7D,cAAc,EAAE,MAAM,CAAC,uBAAuB;SAC/C,CAAC;QACJ,CAAC,CAAC,IAAI,CAAC;IAET,6BAA6B;IAC7B,MAAM,cAAc,GAAG,oBAAoB,CAAC;QAC1C,MAAM,EAAE,MAAM,CAAC,UAAU;QACzB,MAAM,EAAE,MAAM,CAAC,UAAU;QACzB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,SAAS,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC;QACxC,UAAU,EAAE,MAAM,CAAC,cAAc;QACjC,MAAM,EAAE,MAAM,CAAC,UAAU;QACzB,QAAQ,EAAE,MAAM,CAAC,YAAY;KAC9B,CAAC,CAAC;IAEH,6EAA6E;IAC7E,IAAI,eAAe,GAA2B,IAAI,CAAC;IACnD,IAAI,MAAM,CAAC,gBAAgB,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9D,eAAe,GAAG,IAAI,eAAe,CAAC;YACpC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,MAAM,CAAC,KAAK;SACpB,CAAC,CAAC;QAEH,sCAAsC;QACtC,IAAI,CAAC;YACH,MAAM,eAAe,CAAC,OAAO,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,oEAAoE,EAAE;gBAChF,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAC9D,CAAC,CAAC;YACH,eAAe,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE;QAClC,IAAI;QACJ,QAAQ;QACR,SAAS,EAAE,QAAQ;QACnB,OAAO;QACP,UAAU;QACV,UAAU,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;QAC/D,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,CAAC,CAAC,QAAQ;QACrB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;QACzC,aAAa,EAAE,MAAM,CAAC,gBAAgB,IAAI,CAAC,CAAC,eAAe;KAC5D,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAoB,EAAE,WAA2B,EAAE,EAAE;QAC1F,4CAA4C;QAC5C,MAAM,EAAE,GAAG,EAAE,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAEpD,mDAAmD;QACnD,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAE1B,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC;QAC3B,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAElC,4EAA4E;QAC5E,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,GAAG,KAAK,eAAe,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;gBACpF,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/B,CAAC;YACD,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,6DAA6D;QAC7D,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,OAAO,GAAG,WAAW,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,wCAAwC;YAClD,CAAC;QACH,CAAC;QAED,6DAA6D;QAC7D,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;YAC9B,OAAO,CAAC,2CAA2C;QACrD,CAAC;QAED,qCAAqC;QACrC,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAE7B,IAAI,CAAC;YACH,wBAAwB;YACxB,IAAI,MAAM,CAAC,qBAAqB,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;gBACvD,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBACvB,OAAO;YACT,CAAC;YAED,kCAAkC;YAClC,IAAI,MAAM,CAAC,gBAAgB,IAAI,eAAe,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;gBAC5E,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;oBACzB,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;oBACzB,MAAM,uBAAuB,CAAC,GAAG,EAAE,GAAG,EAAE,eAAe,CAAC,CAAC;oBACzD,OAAO;gBACT,CAAC;gBACD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mDAAmD,EAAE,CAAC,CAAC;gBACnF,OAAO;YACT,CAAC;YAED,qDAAqD;YACrD,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,GAAG,KAAK,eAAe,EAAE,CAAC;gBACpD,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACzB,MAAM,OAAO,GAAG,UAAU,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,GAAG,QAAQ,IAAI,IAAI,EAAE,EAAE,CAAC;gBACtE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;gBAC5C,OAAO;YACT,CAAC;YAED,uEAAuE;YACvE,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC,CAAC;oBAC/D,OAAO;gBACT,CAAC;gBACD,MAAM,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBAC3C,OAAO;YACT,CAAC;YAED,2CAA2C;YAC3C,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;gBACxB,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,CAAuB,CAAC;gBACtE,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAEtE,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBACrE,MAAM,aAAa,GAA2B,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;gBAClG,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,aAAa,CAAC,CAAC;gBAEtF,IAAI,KAAK,IAAI,MAAM,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC;oBAC1C,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBACjC,CAAC;gBACD,OAAO;YACT,CAAC;YAED,YAAY;YACZ,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,qDAAqD;YACrD,IAAI,eAAe,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;oBACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC,CAAC;gBACrG,CAAC;gBACD,OAAO;YACT,CAAC;YAED,MAAM,CAAC,KAAK,CAAC,oBAAoB,EAAE;gBACjC,KAAK;gBACL,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,GAAG;aACJ,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;gBACrB,sEAAsE;gBACtE,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE;oBACjB,KAAK,EAAE,uBAAuB;oBAC9B,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC;iBAC9B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,+EAA+E;IAC/E,6EAA6E;IAC7E,yEAAyE;IACzE,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,CAAG,kCAAkC;IACpE,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,CAAG,sCAAsC;IACxE,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC,CAAE,qCAAqC;IACvE,MAAM,CAAC,oBAAoB,GAAG,CAAC,CAAC,CAAE,4CAA4C;IAE9E,4BAA4B;IAC5B,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,MAAM,gBAAgB,GAAG,KAAK,EAAE,MAAc,EAAE,EAAE;QAChD,IAAI,cAAc;YAAE,OAAO;QAC3B,cAAc,GAAG,IAAI,CAAC;QAEtB,MAAM,CAAC,IAAI,CAAC,8CAA8C,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAExE,yBAAyB;QACzB,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1C,IAAI,CAAC;gBACH,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;oBACtB,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC7B,CAAC;gBACD,IAAI,WAAW,IAAI,KAAK,IAAI,OAAO,KAAK,CAAC,SAAS,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;oBACxE,MAAM,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;gBAChC,CAAC;gBACD,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,2BAA2B,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,KAAK,EAAE,CAAC;QAEjB,yBAAyB;QACzB,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,UAAU,EAAE,CAAC;QAC/B,CAAC;QAED,oBAAoB;QACpB,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;QAED,oBAAoB;QACpB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;gBAChB,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBAClC,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;IAE5D,kBAAkB;IAClB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE;YACjC,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE;gBACnC,IAAI;gBACJ,QAAQ;gBACR,GAAG,EAAE,UAAU,QAAQ,IAAI,IAAI,GAAG,OAAO,EAAE;gBAC3C,SAAS,EAAE,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,UAAU,QAAQ,IAAI,IAAI,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS;gBAC/F,YAAY,EAAE,MAAM,CAAC,gBAAgB,IAAI,eAAe,CAAC,CAAC,CAAC,UAAU,QAAQ,IAAI,IAAI,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS;aACpH,CAAC,CAAC;YACH,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
### 1.5.2
|
|
2
|
+
**Fix — CORS headers on `/api/*` and `/openapi.json` rejections (401 / 429) so auth
|
|
3
|
+
failures stop masquerading as "NetworkError".**
|
|
4
|
+
The REST-bridge CORS headers were applied only *inside* the route handlers, which run
|
|
5
|
+
**after** the auth and rate-limit middleware. So a `401 Unauthorized` (bad/missing token)
|
|
6
|
+
or a `429` (rate limited) on a browser-facing endpoint went back with **no**
|
|
7
|
+
`Access-Control-Allow-Origin` header. A browser that receives a cross-origin response
|
|
8
|
+
without that header discards it and reports the generic *"NetworkError when attempting to
|
|
9
|
+
fetch resource"* — completely hiding the real `401`. This made an Open WebUI auth
|
|
10
|
+
misconfiguration look identical to a network/tunnel failure.
|
|
11
|
+
|
|
12
|
+
CORS headers for the browser-facing REST surface (`/openapi.json`, `/api/*`, the SSE
|
|
13
|
+
events path) are now applied **before** rate limiting and authentication, so every
|
|
14
|
+
rejection carries `Access-Control-Allow-Origin` and the browser surfaces the true status.
|
|
15
|
+
The path test is extracted into the `isRestApiCorsPath()` helper (shared by the preflight
|
|
16
|
+
and the new early-CORS step); `addRestApiCors()` is unchanged. No behavior change for a
|
|
17
|
+
successful (200) request — it already carried CORS.
|
|
18
|
+
|
|
19
|
+
### 1.5.1
|
|
20
|
+
**Fix — `/openapi.json` now advertises the correct scheme behind a TLS-terminating proxy.**
|
|
21
|
+
The OpenAPI document's `servers[0].url` was built with a hardcoded `http://`. Behind the
|
|
22
|
+
Cloudflare tunnel (which terminates TLS and forwards to the origin over plain HTTP), the
|
|
23
|
+
spec therefore advertised an `http://` server URL even though the public endpoint is
|
|
24
|
+
`https://`. An OpenAPI tool client loaded on an **https** page (e.g. Open WebUI) then
|
|
25
|
+
refused to call any tool, because the browser blocks `http://` subresource fetches from an
|
|
26
|
+
https origin as **mixed content** — surfacing as *"NetworkError when attempting to fetch
|
|
27
|
+
resource."*
|
|
28
|
+
|
|
29
|
+
The handler now honors the `X-Forwarded-Proto` header (set by Cloudflare / reverse
|
|
30
|
+
proxies) when constructing the advertised base URL, so a TLS-terminated deployment
|
|
31
|
+
advertises `https://`. The new `resolveForwardedProto()` helper validates the header
|
|
32
|
+
against an allowlist — anything other than a literal `https` falls back to `http`, and
|
|
33
|
+
comma-separated proxy chains take the first hop — so a spoofed value can't inject an
|
|
34
|
+
arbitrary scheme into the spec. No behavior change for plain-HTTP deployments.
|
|
35
|
+
|
|
1
36
|
### 1.5.0
|
|
2
37
|
**Feature — Omada resource graph: Tier 4 read coverage (VPN · profiles · schedules · backup · audit).**
|
|
3
38
|
Extends graph mode with the *home-relevant* slice of the previously zero-coverage Omada
|
package/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Home Assistant MCP Wrapper",
|
|
5
|
-
"version": "1.5.
|
|
5
|
+
"version": "1.5.2",
|
|
6
6
|
"description": "REST endpoints that wrap MCP tools for Home Assistant integration. Raw JSON-RPC passthrough available at POST / for n8n compatibility."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
package/package.json
CHANGED
package/src/server/http.ts
CHANGED
|
@@ -159,7 +159,7 @@ export function handleHealthCheck(res: ServerResponse): void {
|
|
|
159
159
|
/**
|
|
160
160
|
* Add CORS headers for REST API endpoints (always enabled for Open WebUI compatibility)
|
|
161
161
|
*/
|
|
162
|
-
function addRestApiCors(req: IncomingMessage, res: ServerResponse): void {
|
|
162
|
+
export function addRestApiCors(req: IncomingMessage, res: ServerResponse): void {
|
|
163
163
|
const origin = req.headers.origin;
|
|
164
164
|
res.setHeader('Access-Control-Allow-Origin', origin ?? '*');
|
|
165
165
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
@@ -167,6 +167,21 @@ function addRestApiCors(req: IncomingMessage, res: ServerResponse): void {
|
|
|
167
167
|
res.setHeader('Access-Control-Max-Age', '86400');
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Whether a request path is served by the browser-facing REST surface
|
|
172
|
+
* (`/openapi.json`, the `/api/*` bridge, or the SSE events stream) and therefore
|
|
173
|
+
* must always carry CORS headers — INCLUDING on responses produced before the
|
|
174
|
+
* route handler runs (rate-limit 429, auth 401). If those rejections go back
|
|
175
|
+
* without `Access-Control-Allow-Origin`, the browser discards the response and
|
|
176
|
+
* surfaces it as an opaque "NetworkError when attempting to fetch resource",
|
|
177
|
+
* masking the real status (this is why an Open WebUI 401 looked like a network
|
|
178
|
+
* failure). `url` is the raw request URL (query string included); `urlPath` is
|
|
179
|
+
* the path-only form used to match the configurable SSE events path.
|
|
180
|
+
*/
|
|
181
|
+
export function isRestApiCorsPath(url: string, urlPath: string, sseEventsPath: string): boolean {
|
|
182
|
+
return url === '/openapi.json' || url.startsWith('/api/') || urlPath === sseEventsPath;
|
|
183
|
+
}
|
|
184
|
+
|
|
170
185
|
/**
|
|
171
186
|
* Resolve the permission a REST `/api/*` route requires.
|
|
172
187
|
*
|
|
@@ -348,10 +363,26 @@ export async function handleRestApi(
|
|
|
348
363
|
}
|
|
349
364
|
}
|
|
350
365
|
|
|
366
|
+
/**
|
|
367
|
+
* Resolve the public URL scheme, honoring `X-Forwarded-Proto` (set by Cloudflare /
|
|
368
|
+
* reverse proxies that TLS-terminate upstream). The header is validated against an
|
|
369
|
+
* allowlist so a spoofed value can't inject an arbitrary scheme; anything other than
|
|
370
|
+
* a literal `https` falls back to `http`. Comma-separated values (proxy chains) take
|
|
371
|
+
* the first hop.
|
|
372
|
+
*/
|
|
373
|
+
export function resolveForwardedProto(headerValue: string | string[] | undefined): 'http' | 'https' {
|
|
374
|
+
const first = Array.isArray(headerValue) ? headerValue[0] : headerValue;
|
|
375
|
+
const proto = String(first ?? '')
|
|
376
|
+
.split(',')[0]
|
|
377
|
+
?.trim()
|
|
378
|
+
.toLowerCase();
|
|
379
|
+
return proto === 'https' ? 'https' : 'http';
|
|
380
|
+
}
|
|
381
|
+
|
|
351
382
|
/**
|
|
352
383
|
* Generate OpenAPI spec for Open WebUI compatibility
|
|
353
384
|
*/
|
|
354
|
-
function getOpenApiSpec(baseUrl: string): object {
|
|
385
|
+
export function getOpenApiSpec(baseUrl: string): object {
|
|
355
386
|
return {
|
|
356
387
|
openapi: '3.1.0',
|
|
357
388
|
info: {
|
|
@@ -609,7 +640,7 @@ export async function startHttpServer(options: HttpServerOptions): Promise<void>
|
|
|
609
640
|
|
|
610
641
|
// Handle OPTIONS (CORS preflight) - add CORS headers for REST API endpoints
|
|
611
642
|
if (req.method === 'OPTIONS') {
|
|
612
|
-
if (url
|
|
643
|
+
if (isRestApiCorsPath(url, urlPath, sseEventsPath)) {
|
|
613
644
|
addRestApiCors(req, res);
|
|
614
645
|
} else {
|
|
615
646
|
handleCors(req, res, config);
|
|
@@ -619,6 +650,14 @@ export async function startHttpServer(options: HttpServerOptions): Promise<void>
|
|
|
619
650
|
return;
|
|
620
651
|
}
|
|
621
652
|
|
|
653
|
+
// Apply CORS headers for the browser-facing REST surface BEFORE rate limiting
|
|
654
|
+
// and auth, so a 429 or 401 rejection still carries `Access-Control-Allow-Origin`.
|
|
655
|
+
// Otherwise the browser masks the real status as an opaque "NetworkError when
|
|
656
|
+
// attempting to fetch resource" (Open WebUI auth failures looked like this).
|
|
657
|
+
if (isRestApiCorsPath(url, urlPath, sseEventsPath)) {
|
|
658
|
+
addRestApiCors(req, res);
|
|
659
|
+
}
|
|
660
|
+
|
|
622
661
|
// Apply rate limiting (skip health checks and certain paths)
|
|
623
662
|
if (rateLimiter) {
|
|
624
663
|
const allowed = rateLimiter.middleware()(req, res);
|
|
@@ -656,7 +695,12 @@ export async function startHttpServer(options: HttpServerOptions): Promise<void>
|
|
|
656
695
|
// OpenAPI spec endpoint for Open WebUI compatibility
|
|
657
696
|
if (req.method === 'GET' && url === '/openapi.json') {
|
|
658
697
|
addRestApiCors(req, res);
|
|
659
|
-
|
|
698
|
+
// Honor X-Forwarded-Proto (set by Cloudflare / reverse proxies) so the advertised
|
|
699
|
+
// server URL is https when the public endpoint is TLS-terminated upstream. Without
|
|
700
|
+
// this, an https Open WebUI page is handed an http:// server URL and the browser
|
|
701
|
+
// blocks tool calls as mixed content ("NetworkError when attempting to fetch resource").
|
|
702
|
+
const scheme = resolveForwardedProto(req.headers['x-forwarded-proto']);
|
|
703
|
+
const baseUrl = `${scheme}://${req.headers.host ?? `${bindAddr}:${port}`}`;
|
|
660
704
|
sendJson(res, 200, getOpenApiSpec(baseUrl));
|
|
661
705
|
return;
|
|
662
706
|
}
|
package/src/version.ts
CHANGED
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
6
|
-
import type { ServerResponse } from 'node:http';
|
|
6
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
7
7
|
import type { HaClient } from '../../src/haClient/index.js';
|
|
8
8
|
import type { EnvironmentConfig } from '../../src/config.js';
|
|
9
9
|
import { VERSION } from '../../src/version.js';
|
|
10
|
+
import {
|
|
11
|
+
resolveForwardedProto,
|
|
12
|
+
getOpenApiSpec,
|
|
13
|
+
addRestApiCors,
|
|
14
|
+
isRestApiCorsPath,
|
|
15
|
+
} from '../../src/server/http.js';
|
|
10
16
|
|
|
11
17
|
// Mock dependencies
|
|
12
18
|
vi.mock('node:http');
|
|
@@ -414,4 +420,112 @@ describe('HTTP Server', () => {
|
|
|
414
420
|
expect(duration).toBeLessThan(1000);
|
|
415
421
|
});
|
|
416
422
|
});
|
|
423
|
+
|
|
424
|
+
describe('OpenAPI spec scheme (X-Forwarded-Proto)', () => {
|
|
425
|
+
it('returns https only when the header is exactly https', () => {
|
|
426
|
+
expect(resolveForwardedProto('https')).toBe('https');
|
|
427
|
+
expect(resolveForwardedProto('HTTPS')).toBe('https');
|
|
428
|
+
expect(resolveForwardedProto(' https ')).toBe('https');
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
it('takes the first hop from a comma-separated proxy chain', () => {
|
|
432
|
+
expect(resolveForwardedProto('https,http')).toBe('https');
|
|
433
|
+
expect(resolveForwardedProto('http, https')).toBe('http');
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
it('falls back to http for missing, empty, or unknown values', () => {
|
|
437
|
+
expect(resolveForwardedProto(undefined)).toBe('http');
|
|
438
|
+
expect(resolveForwardedProto('')).toBe('http');
|
|
439
|
+
expect(resolveForwardedProto('http')).toBe('http');
|
|
440
|
+
// A spoofed/garbage scheme can never be injected into the advertised URL.
|
|
441
|
+
expect(resolveForwardedProto('javascript')).toBe('http');
|
|
442
|
+
expect(resolveForwardedProto('ftp')).toBe('http');
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it('handles array-valued headers by using the first entry', () => {
|
|
446
|
+
expect(resolveForwardedProto(['https', 'http'])).toBe('https');
|
|
447
|
+
expect(resolveForwardedProto(['http'])).toBe('http');
|
|
448
|
+
});
|
|
449
|
+
|
|
450
|
+
it('advertises the resolved scheme + host as the OpenAPI server url', () => {
|
|
451
|
+
// The regression: behind Cloudflare the spec must say https, not http, or the
|
|
452
|
+
// browser blocks tool calls from the https Open WebUI page as mixed content.
|
|
453
|
+
const scheme = resolveForwardedProto('https');
|
|
454
|
+
const spec = getOpenApiSpec(`${scheme}://mcp.example.com`) as {
|
|
455
|
+
servers: { url: string }[];
|
|
456
|
+
info: { version: string };
|
|
457
|
+
};
|
|
458
|
+
expect(spec.servers[0].url).toBe('https://mcp.example.com');
|
|
459
|
+
expect(spec.info.version).toBe(VERSION);
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
describe('REST API CORS on pre-handler rejections', () => {
|
|
464
|
+
const SSE_PATH = '/subscribe_events';
|
|
465
|
+
|
|
466
|
+
it('identifies the browser-facing REST surface', () => {
|
|
467
|
+
expect(isRestApiCorsPath('/openapi.json', '/openapi.json', SSE_PATH)).toBe(true);
|
|
468
|
+
expect(isRestApiCorsPath('/api/version', '/api/version', SSE_PATH)).toBe(true);
|
|
469
|
+
expect(isRestApiCorsPath('/api/states/light.x', '/api/states/light.x', SSE_PATH)).toBe(true);
|
|
470
|
+
expect(isRestApiCorsPath('/subscribe_events', '/subscribe_events', SSE_PATH)).toBe(true);
|
|
471
|
+
// Query string must not defeat the SSE path match (urlPath is path-only).
|
|
472
|
+
expect(isRestApiCorsPath('/subscribe_events?token=x', '/subscribe_events', SSE_PATH)).toBe(true);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
it('excludes MCP / health / unknown paths from the REST CORS surface', () => {
|
|
476
|
+
expect(isRestApiCorsPath('/mcp', '/mcp', SSE_PATH)).toBe(false);
|
|
477
|
+
expect(isRestApiCorsPath('/health', '/health', SSE_PATH)).toBe(false);
|
|
478
|
+
expect(isRestApiCorsPath('/', '/', SSE_PATH)).toBe(false);
|
|
479
|
+
// Must not be fooled by a path that merely contains "/api/".
|
|
480
|
+
expect(isRestApiCorsPath('/not/api/x', '/not/api/x', SSE_PATH)).toBe(false);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
it('reflects the request Origin in the CORS headers', () => {
|
|
484
|
+
const set: Record<string, string> = {};
|
|
485
|
+
const res = { setHeader: (k: string, v: string) => { set[k] = v; } } as unknown as ServerResponse;
|
|
486
|
+
const req = { headers: { origin: 'https://owui.example.com' } } as unknown as IncomingMessage;
|
|
487
|
+
addRestApiCors(req, res);
|
|
488
|
+
expect(set['Access-Control-Allow-Origin']).toBe('https://owui.example.com');
|
|
489
|
+
expect(set['Access-Control-Allow-Methods']).toContain('GET');
|
|
490
|
+
expect(set['Access-Control-Allow-Headers']).toContain('Authorization');
|
|
491
|
+
expect(set['Access-Control-Max-Age']).toBe('86400');
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it('falls back to * when the request has no Origin', () => {
|
|
495
|
+
const set: Record<string, string> = {};
|
|
496
|
+
const res = { setHeader: (k: string, v: string) => { set[k] = v; } } as unknown as ServerResponse;
|
|
497
|
+
const req = { headers: {} } as unknown as IncomingMessage;
|
|
498
|
+
addRestApiCors(req, res);
|
|
499
|
+
expect(set['Access-Control-Allow-Origin']).toBe('*');
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it('REGRESSION: a 401 on /api/* still carries Access-Control-Allow-Origin', () => {
|
|
503
|
+
// Reproduces the request pipeline ordering: REST CORS is applied for the path
|
|
504
|
+
// BEFORE the auth middleware rejects, so the browser sees the real 401 instead
|
|
505
|
+
// of an opaque "NetworkError when attempting to fetch resource".
|
|
506
|
+
const set: Record<string, string> = {};
|
|
507
|
+
let status = 0;
|
|
508
|
+
const res = {
|
|
509
|
+
setHeader: (k: string, v: string) => { set[k] = v; },
|
|
510
|
+
writeHead: (code: number) => { status = code; },
|
|
511
|
+
end: () => {},
|
|
512
|
+
} as unknown as ServerResponse;
|
|
513
|
+
const req = { headers: { origin: 'https://owui.example.com' } } as unknown as IncomingMessage;
|
|
514
|
+
|
|
515
|
+
const url = '/api/version';
|
|
516
|
+
// 1) dispatcher applies REST CORS for the path...
|
|
517
|
+
if (isRestApiCorsPath(url, url, SSE_PATH)) {
|
|
518
|
+
addRestApiCors(req, res);
|
|
519
|
+
}
|
|
520
|
+
// 2) ...then auth fails and writes a 401.
|
|
521
|
+
const authOk = false;
|
|
522
|
+
if (!authOk) {
|
|
523
|
+
res.writeHead(401);
|
|
524
|
+
res.end();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
expect(status).toBe(401);
|
|
528
|
+
expect(set['Access-Control-Allow-Origin']).toBe('https://owui.example.com');
|
|
529
|
+
});
|
|
530
|
+
});
|
|
417
531
|
});
|
package/CLAUDE.md
DELETED
|
@@ -1,403 +0,0 @@
|
|
|
1
|
-
# mcp-ha-connect -- Claude Code Agent
|
|
2
|
-
|
|
3
|
-
## Identity & Scope
|
|
4
|
-
|
|
5
|
-
This agent owns the **mcp-ha-connect MCP server** — a Model Context Protocol server for
|
|
6
|
-
Home Assistant, TP-Link Omada, and Local AI integration.
|
|
7
|
-
|
|
8
|
-
**Repo:** `github.com/coffeerunhobby/mcp-ha-connect`
|
|
9
|
-
**npm:** `@coffeerunhobby/mcp-ha-connect`
|
|
10
|
-
**Docker:** `ghcr.io/coffeerunhobby/mcp-ha-connect`
|
|
11
|
-
**Live endpoint:** Cloudflare domain → NAS Docker port 3000 (domain in NAS `.env`)
|
|
12
|
-
|
|
13
|
-
**Working directory:** `C:\workspace\mcp` — this is the canonical copy.
|
|
14
|
-
`W:\mcp-homeassistant` is a stale export at v0.8.0 — ignore it.
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## Stack
|
|
19
|
-
|
|
20
|
-
- **Runtime:** Node.js 20+ (dev machine uses nvm)
|
|
21
|
-
- **Language:** TypeScript, compiled to `dist/` via `tsc`
|
|
22
|
-
- **MCP SDK:** `@modelcontextprotocol/sdk`
|
|
23
|
-
- **Transport:** Streamable HTTP (port 3000, path `/mcp`)
|
|
24
|
-
- **Auth:** JWT bearer tokens with RBAC permission system
|
|
25
|
-
- **Plugins:** Home Assistant · TP-Link Omada SDN · Local AI (Ollama/OpenAI-compat)
|
|
26
|
-
- **Tests:** Vitest (829 unit tests) + integration tests in `tests/integration/`
|
|
27
|
-
- **Container:** Alpine Node image, deployed on Synology NAS via Docker Compose
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## Infrastructure
|
|
32
|
-
|
|
33
|
-
| Resource | Address | Notes |
|
|
34
|
-
|---|---|---|
|
|
35
|
-
| **MCP server** | `mcpserver.10.0.0.18.nip.io:3000` | NAS Docker container |
|
|
36
|
-
| **Home Assistant** | `homeassistant.10.0.0.19.nip.io:8123` | |
|
|
37
|
-
| **Omada controller** | `omada.10.0.0.18.nip.io:8043` | HTTPS, self-signed cert |
|
|
38
|
-
| **Ollama** | `ollama.10.0.0.17.nip.io:11434` | model `phi4:14b` |
|
|
39
|
-
| **n8n** | `n8n.10.0.0.18.nip.io:5678` | also exposed via Cloudflare |
|
|
40
|
-
| **NAS Docker path** | `/volume1/docker/mcp-ha-connect/` | compose.yaml + .env |
|
|
41
|
-
| **Cloudflare** | proxies public domain → NAS port 3000 | domain stored in `.env` |
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Secrets & Credentials
|
|
46
|
-
|
|
47
|
-
All secrets live in the NAS `.env` file and as **Windows User environment variables**.
|
|
48
|
-
Never store token values in source files, commit messages, or this file.
|
|
49
|
-
|
|
50
|
-
| Variable | Purpose |
|
|
51
|
-
|---|---|
|
|
52
|
-
| `NPM_MCP_HA_TOKEN` | npm Granular token for publishing |
|
|
53
|
-
| `GHCR_TOKEN` | GitHub PAT with `write:packages` scope |
|
|
54
|
-
|
|
55
|
-
### Retrieve for use
|
|
56
|
-
|
|
57
|
-
```powershell
|
|
58
|
-
$npmToken = [Environment]::GetEnvironmentVariable('NPM_MCP_HA_TOKEN', 'User')
|
|
59
|
-
$ghcrToken = [Environment]::GetEnvironmentVariable('GHCR_TOKEN', 'User')
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### npm token requirements
|
|
63
|
-
|
|
64
|
-
The npm token must be **Granular type** with:
|
|
65
|
-
- Scope `@coffeerunhobby` → **Read and write** (scope-level, not per-package)
|
|
66
|
-
- **Bypass two-factor authentication** ✅ checked
|
|
67
|
-
|
|
68
|
-
Create at: npmjs.com → Access Tokens → Generate New Token → Granular Access Token
|
|
69
|
-
|
|
70
|
-
**Critical:** Never run `npm logout` — it revokes the token server-side and deletes it
|
|
71
|
-
from npmjs.com. If the token disappears from the web UI, that's why.
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## Release Process
|
|
76
|
-
|
|
77
|
-
### 1. Pre-flight
|
|
78
|
-
|
|
79
|
-
```powershell
|
|
80
|
-
cd C:\workspace\mcp
|
|
81
|
-
npm test # all tests must pass
|
|
82
|
-
npm run build # must compile clean
|
|
83
|
-
npm run lint # ZERO errors AND zero warnings (see Code Quality policy)
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
### 2. Version bump
|
|
87
|
-
|
|
88
|
-
Update **both** files to the new version:
|
|
89
|
-
- `package.json` → `"version": "X.Y.Z"`
|
|
90
|
-
- `src/version.ts` → `export const VERSION = 'X.Y.Z';`
|
|
91
|
-
|
|
92
|
-
Update `docs/CHANGELOG.md` with the new version section.
|
|
93
|
-
|
|
94
|
-
### 3. Commit & tag
|
|
95
|
-
|
|
96
|
-
```powershell
|
|
97
|
-
git add .
|
|
98
|
-
git commit -m "vX.Y.Z - <short description>"
|
|
99
|
-
git tag vX.Y.Z
|
|
100
|
-
git push origin main
|
|
101
|
-
git push origin vX.Y.Z
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
Create the GitHub Release at:
|
|
105
|
-
`https://github.com/coffeerunhobby/mcp-ha-connect/releases/new?tag=vX.Y.Z`
|
|
106
|
-
|
|
107
|
-
### 4. npm publish
|
|
108
|
-
|
|
109
|
-
**Preferred: interactive login (browser).** Granular tokens keep getting revoked, so the
|
|
110
|
-
reliable path is an interactive `npm login`, which opens the browser for auth. The agent
|
|
111
|
-
**cannot** complete this alone — it MUST ask the user to run/confirm the browser login,
|
|
112
|
-
then publish together:
|
|
113
|
-
|
|
114
|
-
```powershell
|
|
115
|
-
cd C:\workspace\mcp
|
|
116
|
-
npm login # opens browser — USER completes this, agent waits
|
|
117
|
-
npm whoami # must print the account name, not 403
|
|
118
|
-
npm publish --access public
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
**Do NOT run `npm logout`** afterward — it revokes any granular token server-side.
|
|
122
|
-
|
|
123
|
-
> Agent rule: when a release reaches this step, STOP and ask the user to help with
|
|
124
|
-
> `npm login` and `npm publish --access public` (browser-based). Do not silently fall
|
|
125
|
-
> back to a stored token — if `npm whoami` returns 403, the token is dead.
|
|
126
|
-
|
|
127
|
-
### 5. Docker build & push
|
|
128
|
-
|
|
129
|
-
Docker Desktop must be running.
|
|
130
|
-
|
|
131
|
-
```powershell
|
|
132
|
-
$ghcrToken = [Environment]::GetEnvironmentVariable('GHCR_TOKEN', 'User')
|
|
133
|
-
$ghcrToken | docker login ghcr.io -u coffeerunhobby --password-stdin
|
|
134
|
-
|
|
135
|
-
cd C:\workspace\mcp
|
|
136
|
-
docker build --no-cache `
|
|
137
|
-
-t ghcr.io/coffeerunhobby/mcp-ha-connect:X.Y.Z `
|
|
138
|
-
-t ghcr.io/coffeerunhobby/mcp-ha-connect:latest .
|
|
139
|
-
|
|
140
|
-
docker push ghcr.io/coffeerunhobby/mcp-ha-connect:X.Y.Z
|
|
141
|
-
docker push ghcr.io/coffeerunhobby/mcp-ha-connect:latest
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
Use `docker build`, not `docker buildx build --platform`. The NAS is amd64 and a plain
|
|
145
|
-
build on a Windows/amd64 host produces the correct image.
|
|
146
|
-
|
|
147
|
-
### 6. Deploy to NAS
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
cd /volume1/docker/mcp-ha-connect
|
|
151
|
-
docker compose pull && docker compose up -d
|
|
152
|
-
docker compose logs --tail=30
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## NAS `.env` — critical settings
|
|
158
|
-
|
|
159
|
-
```env
|
|
160
|
-
MCP_HTTP_BIND_ADDR=0.0.0.0
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
Must be `0.0.0.0`, not `127.0.0.1`. Docker port mapping requires the server to listen on
|
|
164
|
-
all interfaces inside the container — loopback only means Cloudflare gets a 502.
|
|
165
|
-
|
|
166
|
-
```env
|
|
167
|
-
MCP_HTTP_ALLOWED_ORIGINS=...,<cloudflare-domain>,https://<cloudflare-domain>
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Must include both the bare hostname AND the `https://` form of the Cloudflare domain.
|
|
171
|
-
The MCP SDK checks the `host` header (no protocol) for DNS rebinding protection AND
|
|
172
|
-
the `origin` header (with protocol) for CORS.
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
|
|
176
|
-
## Omada SDN — known issues
|
|
177
|
-
|
|
178
|
-
**After upgrading the Omada controller version**, the `OMADA_OMADAC_ID` changes.
|
|
179
|
-
Error code `-44106` is returned for BOTH wrong credentials AND wrong `OMADA_OMADAC_ID` —
|
|
180
|
-
the API does not distinguish between them.
|
|
181
|
-
|
|
182
|
-
**To get the new Omada ID:**
|
|
183
|
-
Omada web UI → Settings → Open API → click the eye icon → copy **Omada ID**.
|
|
184
|
-
|
|
185
|
-
```bash
|
|
186
|
-
sed -i 's/OMADA_OMADAC_ID=.*/OMADA_OMADAC_ID=<new-id>/' /volume1/docker/mcp-ha-connect/.env
|
|
187
|
-
docker compose up -d
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
If Omada is unreachable or credentials are wrong, the server **gracefully degrades** —
|
|
191
|
-
Omada tools are disabled but HA and AI keep working. Set `OMADA_PLUGIN_ENABLED=false`
|
|
192
|
-
to disable Omada entirely while troubleshooting.
|
|
193
|
-
|
|
194
|
-
**`OMADA_SITE_ID` is validated at startup against the live site list** (the controller is
|
|
195
|
-
the source of truth; the env var is only a selector). If `OMADA_SITE_ID` is set but **not**
|
|
196
|
-
present on the controller — a site id can drift after a controller migration, exactly like
|
|
197
|
-
`OMADA_OMADAC_ID` — the **Omada plugin is disabled** at boot with a `logger.error` that
|
|
198
|
-
names the bad value and lists the valid sites (HA + AI stay up). This turns the old failure
|
|
199
|
-
mode (a silent default scoping every read to a dead site → later "user does not have
|
|
200
|
-
permissions to access this site") into a loud, self-diagnosing startup error. Fix by setting
|
|
201
|
-
`OMADA_SITE_ID` to one of the listed ids. Validation lives in `checkConfiguredSite()`
|
|
202
|
-
(`src/omadaClient/site.ts`); a *valid* default still auto-resolves, so site-scoped reads need
|
|
203
|
-
no explicit `siteId`.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Code Quality — fix every error and warning
|
|
208
|
-
|
|
209
|
-
**Always fix errors AND warnings. Never label something "pre-existing debt" and move on.**
|
|
210
|
-
|
|
211
|
-
- `npm run lint`, `npm run build`, and `npm test` must all be **completely clean** —
|
|
212
|
-
zero errors, zero warnings — before a change is considered done.
|
|
213
|
-
- If you touch a file (or a release surfaces lint output) and find existing errors or
|
|
214
|
-
warnings, they are now yours to fix. "It was already broken" is not an acceptable
|
|
215
|
-
reason to leave it.
|
|
216
|
-
- **Exception — release timing:** do not cut a patch release *solely* to clean up lint.
|
|
217
|
-
If quality issues are found right after a release has shipped, fold the fixes into the
|
|
218
|
-
**next feature's** commit rather than churning a `vX.Y.(Z+1)`. Outstanding cleanup of
|
|
219
|
-
this kind is tracked in `.claude/NEXT-SESSION.md` so it isn't forgotten.
|
|
220
|
-
|
|
221
|
-
> Currently outstanding: `Function`-type lint warnings in the test mock helpers
|
|
222
|
-
> (`tests/tools/**/handlers.test.ts`). Fix these as part of the next feature change —
|
|
223
|
-
> NOT as a standalone patch release.
|
|
224
|
-
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
## Development
|
|
228
|
-
|
|
229
|
-
```powershell
|
|
230
|
-
cd C:\workspace\mcp
|
|
231
|
-
npm run dev # tsx watch with .env
|
|
232
|
-
npm test # vitest (excludes integration)
|
|
233
|
-
npm run test:watch # watch mode
|
|
234
|
-
npm run lint # eslint
|
|
235
|
-
npm run build # tsc compile to dist/
|
|
236
|
-
npm run generate:jwt # generate a test JWT token
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Integration tests (requires live .env)
|
|
240
|
-
|
|
241
|
-
```powershell
|
|
242
|
-
npm run test:integration
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
---
|
|
246
|
-
|
|
247
|
-
## Live testing against the running server
|
|
248
|
-
|
|
249
|
-
The dev machine can exercise the deployed MCP server two ways:
|
|
250
|
-
|
|
251
|
-
1. **Connected `homeassistant` MCP in Claude Desktop** — this agent has the live server
|
|
252
|
-
wired in as an MCP connection, so HA/Omada tools can be invoked directly (no curl, no
|
|
253
|
-
manual token; the configured bearer is used). **Caveat:** the MCP client caches the tool
|
|
254
|
-
list at *connection time*. After flipping `MCP_TOOL_REGISTRATION_MODE` (eager ⇄ graph)
|
|
255
|
-
and redeploying, that cached list is **stale** — Claude Desktop must reconnect (restart)
|
|
256
|
-
before the new tool surface (`omada_browse`/`omada_read`, or the typed getters) shows up.
|
|
257
|
-
Until it reconnects, calling a tool the live server no longer registers will fail.
|
|
258
|
-
|
|
259
|
-
2. **Direct `/mcp` curl** — generate a token with
|
|
260
|
-
`npm run generate:jwt -- --sub <user> --exp 1h` (signs with the local `.env`
|
|
261
|
-
`MCP_AUTH_SECRET`, which currently matches the NAS), then POST JSON-RPC to the server's
|
|
262
|
-
`/mcp` with headers `Authorization: Bearer <tok>`, `Content-Type: application/json`,
|
|
263
|
-
`Accept: application/json, text/event-stream`. Responses come back as SSE
|
|
264
|
-
(`data: {...}` lines). `tools/list` and `tools/call` work **without** an initialize
|
|
265
|
-
handshake in stateless mode. The reachable server address lives in
|
|
266
|
-
`.claude/NEXT-SESSION.md` (gitignored — never put the real IP/domain here).
|
|
267
|
-
|
|
268
|
-
Permissions are resolved **server-side** from the token's `sub` via `MCP_PERMISSIONS_CONFIG`
|
|
269
|
-
(they are NOT carried in the token). Pick a `sub` whose mapped role has the bit you need —
|
|
270
|
-
e.g. the ADMIN-gated `/security/threats` node needs a `sub` mapped to an ADMIN role. The NAS
|
|
271
|
-
role map differs from the local `.env`, so don't assume `sub=admin` is actually ADMIN there.
|
|
272
|
-
|
|
273
|
-
---
|
|
274
|
-
|
|
275
|
-
## Never assume. Always verify.
|
|
276
|
-
|
|
277
|
-
- **Cloudflare 502**: check the container is running (`docker compose ps`) and
|
|
278
|
-
`MCP_HTTP_BIND_ADDR=0.0.0.0` is set.
|
|
279
|
-
- **MCP client connects but tools fail**: check `MCP_HTTP_ALLOWED_ORIGINS` includes
|
|
280
|
-
the Cloudflare domain in both bare and `https://` form.
|
|
281
|
-
- **Claude Desktop shows "Server disconnected" but `/health` is 200**: the client's
|
|
282
|
-
mcp-remote auth header is malformed. A `"Authorization: Bearer ${MCP_AUTH_TOKEN}"`
|
|
283
|
-
placeholder does NOT expand on Windows (`cmd /c` uses `%VAR%`, mcp-remote doesn't
|
|
284
|
-
substitute `${VAR}`) → literal text is sent → server 401 → mcp-remote drops into a
|
|
285
|
-
failing OAuth flow. Fix: inline the literal JWT in `claude_desktop_config.json`'s
|
|
286
|
-
`--header` arg, and add `-y` to `npx` so first run doesn't hang. Verify the server
|
|
287
|
-
side first with a direct `curl` POST to `/mcp` carrying the token.
|
|
288
|
-
- **npm publish returns 404 on PUT**: token likely has per-package scope instead of
|
|
289
|
-
scope-level access, or "Bypass 2FA" is not ticked. Delete token and recreate.
|
|
290
|
-
- **Omada auth error -44106**: check `OMADA_OMADAC_ID` first, not just credentials —
|
|
291
|
-
this error code covers both cases.
|
|
292
|
-
- **Before a release**: always run `npm test` and `npm run build` clean.
|
|
293
|
-
- **On release, bump the version everywhere**: `package.json`, `src/version.ts`,
|
|
294
|
-
`docs/CHANGELOG.md`, AND `openapi.json` (`info.version`) — the last one drifts easily.
|
|
295
|
-
|
|
296
|
-
---
|
|
297
|
-
|
|
298
|
-
## Tool registration modes (`MCP_TOOL_REGISTRATION_MODE`)
|
|
299
|
-
|
|
300
|
-
Implemented as a **resource-graph** mode for the Omada plugin (config parses the var;
|
|
301
|
-
`config.toolRegistrationMode` threads through `createServer` → `registerAllTools` →
|
|
302
|
-
`registerOmadaTools`). Values:
|
|
303
|
-
|
|
304
|
-
- **`eager`** (default) — register every typed tool (~26 Omada tools). Today's behavior;
|
|
305
|
-
fully backwards-compatible.
|
|
306
|
-
- **`graph`** — register only `omada_browse` + `omada_read` + the 5 typed write/action
|
|
307
|
-
tools. Reads collapse into a discoverable resource graph (`src/tools/omada/namespace.ts`
|
|
308
|
-
manifest + `src/tools/omada/graph.ts`), shrinking the tool-schema budget for low-context
|
|
309
|
-
models while still exposing every read endpoint.
|
|
310
|
-
|
|
311
|
-
Design invariants (don't regress these):
|
|
312
|
-
- **browse returns TYPES, not instances** — `omada_browse(path)` lists permission-filtered
|
|
313
|
-
child resource types + metadata (kind, permission, pagination, params). It never
|
|
314
|
-
enumerates MACs or calls the controller.
|
|
315
|
-
- **read is per-path RBAC, fail-closed** — `omada_read` declares NO static tool permission;
|
|
316
|
-
each manifest node declares its own bit (most reads = QUERY; the `/security/*` subtree =
|
|
317
|
-
ADMIN). Unknown / container / under-privileged / missing-required-param paths all return a
|
|
318
|
-
clean error and never fetch.
|
|
319
|
-
- **single-page pagination** — paginated nodes forward one page/pageSize to a single GET via
|
|
320
|
-
`OmadaClient.readResource()`; they never walk every page.
|
|
321
|
-
- **graph is a complete superset of eager reads** — every eager read getter has a graph node,
|
|
322
|
-
including the ADMIN-gated IDS/IPS threat-management log at `/security/threats`. Its mandatory
|
|
323
|
-
epoch time-window is enforced via required `params.startTime`/`params.endTime` (epoch seconds),
|
|
324
|
-
validated by `omada_read` before any controller call.
|
|
325
|
-
|
|
326
|
-
HA and AI plugins are unaffected (still eager). Writes stay typed + individually gated in
|
|
327
|
-
both modes — generic write verbs were deliberately rejected (prompt-injection / hallucination
|
|
328
|
-
surface).
|
|
329
|
-
|
|
330
|
-
---
|
|
331
|
-
|
|
332
|
-
## Security
|
|
333
|
-
|
|
334
|
-
This server controls real devices (HA, Omada) and is exposed publicly via Cloudflare, so
|
|
335
|
-
treat it as security-sensitive. A full audit (2026-06-07) with file/line findings is in
|
|
336
|
-
`.claude/NEXT-SESSION.md`; this section is the **durable policy** distilled from it.
|
|
337
|
-
|
|
338
|
-
### Dependencies — update, don't rewrite
|
|
339
|
-
|
|
340
|
-
- Runtime deps are intentionally tiny: `@modelcontextprotocol/sdk`, `ws`, `zod`.
|
|
341
|
-
**Do not hand-roll replacements** for these (or for transitive libs like `hono`,
|
|
342
|
-
`ajv`, `path-to-regexp`). A homegrown version loses community review and adds more
|
|
343
|
-
bugs than it removes. Zod and the MCP SDK earn their keep.
|
|
344
|
-
- The alarming `npm audit` list (`hono`, `@hono/node-server`, `fast-uri`, `ajv`,
|
|
345
|
-
`path-to-regexp`, `qs`) is **entirely transitive under the SDK**:
|
|
346
|
-
`@modelcontextprotocol/sdk → @hono/node-server → hono`. **Bumping the SDK fixes most
|
|
347
|
-
of them.** `ws` is the one direct dep to bump on its own.
|
|
348
|
-
- Triage with `npm audit --omit=dev` — dev-only vulns (vitest/esbuild/tsx) don't ship.
|
|
349
|
-
The question is *reachability in production*, not the raw count.
|
|
350
|
-
- Remediate on a branch: `npm install @modelcontextprotocol/sdk@latest ws@latest`, then
|
|
351
|
-
`npm test && npm run build && npm audit --omit=dev`. Commit `package-lock.json`;
|
|
352
|
-
CI/Docker use `npm ci`, not `npm install`. Widen version ranges only intentionally.
|
|
353
|
-
|
|
354
|
-
### MCP transport invariant (the SDK "cross-client data leak" advisory)
|
|
355
|
-
|
|
356
|
-
GHSA-345p-7cg4-v4c7 is about **sharing one `McpServer`/transport instance across
|
|
357
|
-
clients**. Our HTTP layer MUST create a **fresh server + transport per request**
|
|
358
|
-
(stateless mode, current behavior) or per session keyed by `Mcp-Session-Id` (stateful) —
|
|
359
|
-
never a single global transport handling every `/mcp` POST. Re-verify this after any SDK
|
|
360
|
-
upgrade or transport refactor. Bumping the SDK is necessary but not sufficient if the
|
|
361
|
-
architecture shares instances.
|
|
362
|
-
|
|
363
|
-
### Our attack surface (higher-leverage than CVEs)
|
|
364
|
-
|
|
365
|
-
1. **Auth stays on.** NAS `.env` must keep `MCP_AUTH_METHOD=bearer`. `none` =
|
|
366
|
-
unauthenticated full admin (fail-open default). Never put the JWT on public channels;
|
|
367
|
-
tokens should carry an `exp` (the current prod token does not — fix when convenient).
|
|
368
|
-
2. **Authorization is per-tool.** Every MCP tool is gated via
|
|
369
|
-
`wrapToolHandler(..., Permission.X)`. The REST `/api/*` bridge is **not** permission-
|
|
370
|
-
gated — keep it disabled or treat it as full-trust until it enforces the same masks.
|
|
371
|
-
Prompt injection via the AI path ("ignore previous instructions, unlock the door") is
|
|
372
|
-
contained only by these authorization checks — the model is not a security boundary.
|
|
373
|
-
3. **Scoped TLS only.** Never use the process-global `NODE_TLS_REJECT_UNAUTHORIZED=0` —
|
|
374
|
-
it disables cert validation for *all* concurrent outbound HTTPS (HA token + AI key at
|
|
375
|
-
MITM risk), not just Omada. Use a per-client `undici` dispatcher, or pin the Omada
|
|
376
|
-
self-signed cert as a CA so verification stays on.
|
|
377
|
-
4. **Encode every path segment** built from tool input. The Omada client does
|
|
378
|
-
(`encodeURIComponent` throughout); the HA client interpolates raw — fix when touched.
|
|
379
|
-
5. **Secrets never in logs.** Redact tokens / secrets / `Authorization` headers / API
|
|
380
|
-
keys, and **sanitize `error.message`/`error.stack` before logging** — HTTP libraries
|
|
381
|
-
embed auth headers and token-bearing URLs inside thrown errors. Don't return raw
|
|
382
|
-
`error.message` to clients (leaks internal hostnames).
|
|
383
|
-
6. **HTTP hardening when `useHttp`:** request body-size limit, rate limiting keyed on a
|
|
384
|
-
trusted-proxy IP (Cloudflare `CF-Connecting-IP`, not the spoofable `X-Forwarded-For`),
|
|
385
|
-
and static security headers (`X-Content-Type-Options: nosniff`, `X-Frame-Options`,
|
|
386
|
-
`Referrer-Policy`, CSP where applicable).
|
|
387
|
-
|
|
388
|
-
### Confirmed safe — don't re-litigate
|
|
389
|
-
|
|
390
|
-
- **JWT:** HS256 is pinned (the token's `alg` header is ignored), signature compared with
|
|
391
|
-
`crypto.timingSafeEqual` — not vulnerable to alg-confusion or timing attacks. (Still
|
|
392
|
-
add `exp` enforcement, and `iss`/`aud` if it ever becomes multi-issuer.)
|
|
393
|
-
- **Omada client** encodes every path segment; query params via `URLSearchParams`.
|
|
394
|
-
- **No** `eval` / `new Function` / dynamic `require`; the only child process is
|
|
395
|
-
`spawn('node', [fixedPath])` — no shell, no user-controlled argv.
|
|
396
|
-
- **No arbitrary-URL SSRF via tool args** — HA/Omada/AI base URLs come only from config.
|
|
397
|
-
- **Git hygiene clean** — `.env` is never tracked; no hardcoded real secrets in src/tests.
|
|
398
|
-
|
|
399
|
-
### Insecure defaults to flip when next touched
|
|
400
|
-
|
|
401
|
-
`config.ts` defaults `MCP_AUTH_METHOD=none`; `.env.example` ships `none` +
|
|
402
|
-
`HA_STRICT_SSL=false`; `docker-compose.yml` hardcodes `MCP_HTTP_ALLOWED_ORIGINS=*`.
|
|
403
|
-
None of these reflect the (secure) live deployment — make the secure values the defaults.
|